From 5e3f545c431ec4bce3e1b52f3f81bc9befe501f2 Mon Sep 17 00:00:00 2001 From: Bart Coddens Date: Fri, 15 Aug 2014 11:20:26 -0700 Subject: [PATCH] 4989 removal of ntfsprogs and parted Reviewed by: Josef Sipek Reviewed by: Garrett D'Amore Approved by: Robert Mustacchi --- usr/src/cmd/Makefile | 2 - usr/src/cmd/ntfsprogs/COPYING | 340 -- usr/src/cmd/ntfsprogs/CREDITS | 40 - usr/src/cmd/ntfsprogs/Makefile | 160 - usr/src/cmd/ntfsprogs/README | 9 - usr/src/cmd/ntfsprogs/THIRDPARTYLICENSE.descrip | 1 - usr/src/cmd/ntfsprogs/attrdef.c | 168 - usr/src/cmd/ntfsprogs/attrdef.h | 7 - usr/src/cmd/ntfsprogs/boot.c | 268 - usr/src/cmd/ntfsprogs/boot.h | 7 - usr/src/cmd/ntfsprogs/cluster.c | 119 - usr/src/cmd/ntfsprogs/cluster.h | 39 - usr/src/cmd/ntfsprogs/mkntfs.c | 4748 ------------------ usr/src/cmd/ntfsprogs/ntfscat.c | 441 -- usr/src/cmd/ntfsprogs/ntfscat.h | 46 - usr/src/cmd/ntfsprogs/ntfsclone.c | 1926 ------- usr/src/cmd/ntfsprogs/ntfscluster.c | 565 --- usr/src/cmd/ntfsprogs/ntfscluster.h | 63 - usr/src/cmd/ntfsprogs/ntfscmp.c | 1005 ---- usr/src/cmd/ntfsprogs/ntfscp.c | 584 --- usr/src/cmd/ntfsprogs/ntfsfix.c | 542 -- usr/src/cmd/ntfsprogs/ntfsinfo.c | 2305 --------- usr/src/cmd/ntfsprogs/ntfslabel.c | 412 -- usr/src/cmd/ntfsprogs/ntfsls.c | 719 --- usr/src/cmd/ntfsprogs/ntfsresize.c | 2501 ---------- usr/src/cmd/ntfsprogs/ntfsundelete.c | 2199 -------- usr/src/cmd/ntfsprogs/ntfsundelete.h | 111 - usr/src/cmd/ntfsprogs/sd.c | 600 --- usr/src/cmd/ntfsprogs/sd.h | 11 - usr/src/cmd/ntfsprogs/utils.c | 1057 ---- usr/src/cmd/ntfsprogs/utils.h | 100 - usr/src/cmd/parted/COPYING | 676 --- usr/src/cmd/parted/Makefile | 76 - usr/src/cmd/parted/README | 8 - usr/src/cmd/parted/THANKS.txt | 28 - usr/src/cmd/parted/THIRDPARTYLICENSE.descrip | 1 - usr/src/cmd/parted/command.c | 141 - usr/src/cmd/parted/command.h | 48 - usr/src/cmd/parted/parted.c | 2493 ---------- usr/src/cmd/parted/strlist.h | 66 - usr/src/cmd/parted/table.c | 243 - usr/src/cmd/parted/table.h | 52 - usr/src/cmd/parted/ui.c | 1542 ------ usr/src/cmd/parted/ui.h | 82 - usr/src/lib/Makefile | 3 - usr/src/lib/libntfs/COPYING | 340 -- usr/src/lib/libntfs/CREDITS | 40 - usr/src/lib/libntfs/Makefile | 124 - usr/src/lib/libntfs/Makefile.com | 89 - usr/src/lib/libntfs/README | 16 - usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip | 1 - usr/src/lib/libntfs/common/include/ntfs/attrib.h | 382 -- usr/src/lib/libntfs/common/include/ntfs/attrlist.h | 51 - usr/src/lib/libntfs/common/include/ntfs/bitmap.h | 134 - usr/src/lib/libntfs/common/include/ntfs/bootsect.h | 47 - usr/src/lib/libntfs/common/include/ntfs/collate.h | 38 - usr/src/lib/libntfs/common/include/ntfs/compat.h | 58 - usr/src/lib/libntfs/common/include/ntfs/compress.h | 33 - usr/src/lib/libntfs/common/include/ntfs/config.h | 313 -- usr/src/lib/libntfs/common/include/ntfs/crypto.h | 46 - usr/src/lib/libntfs/common/include/ntfs/debug.h | 63 - usr/src/lib/libntfs/common/include/ntfs/device.h | 128 - .../lib/libntfs/common/include/ntfs/device_io.h | 77 - usr/src/lib/libntfs/common/include/ntfs/dir.h | 112 - usr/src/lib/libntfs/common/include/ntfs/endians.h | 248 - usr/src/lib/libntfs/common/include/ntfs/index.h | 131 - usr/src/lib/libntfs/common/include/ntfs/inode.h | 215 - usr/src/lib/libntfs/common/include/ntfs/layout.h | 3063 ------------ usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h | 50 - usr/src/lib/libntfs/common/include/ntfs/list.h | 192 - usr/src/lib/libntfs/common/include/ntfs/logfile.h | 441 -- usr/src/lib/libntfs/common/include/ntfs/logging.h | 143 - usr/src/lib/libntfs/common/include/ntfs/mft.h | 116 - usr/src/lib/libntfs/common/include/ntfs/mst.h | 34 - usr/src/lib/libntfs/common/include/ntfs/ntfstime.h | 69 - usr/src/lib/libntfs/common/include/ntfs/runlist.h | 90 - usr/src/lib/libntfs/common/include/ntfs/security.h | 55 - usr/src/lib/libntfs/common/include/ntfs/support.h | 121 - usr/src/lib/libntfs/common/include/ntfs/types.h | 142 - usr/src/lib/libntfs/common/include/ntfs/unistr.h | 69 - usr/src/lib/libntfs/common/include/ntfs/version.h | 29 - usr/src/lib/libntfs/common/include/ntfs/volume.h | 247 - usr/src/lib/libntfs/common/libntfs/attrib.c | 5234 -------------------- usr/src/lib/libntfs/common/libntfs/attrlist.c | 320 -- usr/src/lib/libntfs/common/libntfs/bitmap.c | 249 - usr/src/lib/libntfs/common/libntfs/bootsect.c | 273 - usr/src/lib/libntfs/common/libntfs/collate.c | 220 - usr/src/lib/libntfs/common/libntfs/compat.c | 73 - usr/src/lib/libntfs/common/libntfs/compress.c | 553 --- usr/src/lib/libntfs/common/libntfs/crypto.c | 1519 ------ usr/src/lib/libntfs/common/libntfs/debug.c | 73 - usr/src/lib/libntfs/common/libntfs/device.c | 796 --- usr/src/lib/libntfs/common/libntfs/device_io.c | 46 - usr/src/lib/libntfs/common/libntfs/dir.c | 1773 ------- usr/src/lib/libntfs/common/libntfs/index.c | 1862 ------- usr/src/lib/libntfs/common/libntfs/inode.c | 1200 ----- usr/src/lib/libntfs/common/libntfs/lcnalloc.c | 858 ---- usr/src/lib/libntfs/common/libntfs/logfile.c | 769 --- usr/src/lib/libntfs/common/libntfs/logging.c | 644 --- usr/src/lib/libntfs/common/libntfs/mft.c | 1583 ------ usr/src/lib/libntfs/common/libntfs/misc.c | 64 - usr/src/lib/libntfs/common/libntfs/mst.c | 216 - usr/src/lib/libntfs/common/libntfs/runlist.c | 2154 -------- usr/src/lib/libntfs/common/libntfs/security.c | 272 - usr/src/lib/libntfs/common/libntfs/unistr.c | 776 --- usr/src/lib/libntfs/common/libntfs/unix_io.c | 321 -- usr/src/lib/libntfs/common/libntfs/version.c | 45 - usr/src/lib/libntfs/common/libntfs/volume.c | 1689 ------- usr/src/lib/libntfs/common/mapfile-vers | 134 - usr/src/lib/libparted/COPYING | 676 --- usr/src/lib/libparted/Makefile | 110 - usr/src/lib/libparted/Makefile.com | 132 - usr/src/lib/libparted/README | 22 - usr/src/lib/libparted/THANKS.txt | 28 - usr/src/lib/libparted/THIRDPARTYLICENSE.descrip | 1 - .../libparted/common/include/parted/constraint.h | 96 - .../lib/libparted/common/include/parted/crc32.h | 34 - .../lib/libparted/common/include/parted/debug.h | 89 - .../lib/libparted/common/include/parted/device.h | 150 - usr/src/lib/libparted/common/include/parted/disk.h | 348 -- .../lib/libparted/common/include/parted/endian.h | 85 - .../libparted/common/include/parted/exception.h | 116 - .../lib/libparted/common/include/parted/filesys.h | 116 - usr/src/lib/libparted/common/include/parted/geom.h | 83 - .../lib/libparted/common/include/parted/natmath.h | 108 - .../lib/libparted/common/include/parted/parted.h | 63 - .../lib/libparted/common/include/parted/solaris.h | 42 - .../lib/libparted/common/include/parted/timer.h | 65 - usr/src/lib/libparted/common/include/parted/unit.h | 93 - usr/src/lib/libparted/common/lib/__fpending.h | 34 - usr/src/lib/libparted/common/lib/basename.c | 129 - usr/src/lib/libparted/common/lib/close-stream.c | 76 - usr/src/lib/libparted/common/lib/close-stream.h | 2 - usr/src/lib/libparted/common/lib/closeout.c | 86 - usr/src/lib/libparted/common/lib/closeout.h | 33 - usr/src/lib/libparted/common/lib/config.h | 597 --- usr/src/lib/libparted/common/lib/configmake.h | 25 - usr/src/lib/libparted/common/lib/dirname.c | 85 - usr/src/lib/libparted/common/lib/dirname.h | 70 - usr/src/lib/libparted/common/lib/error.c | 339 -- usr/src/lib/libparted/common/lib/error.h | 66 - usr/src/lib/libparted/common/lib/exitfail.c | 26 - usr/src/lib/libparted/common/lib/exitfail.h | 20 - usr/src/lib/libparted/common/lib/full-write.c | 81 - usr/src/lib/libparted/common/lib/full-write.h | 35 - usr/src/lib/libparted/common/lib/getopt.c | 1191 ----- usr/src/lib/libparted/common/lib/getopt_int.h | 131 - usr/src/lib/libparted/common/lib/gettext.h | 270 - usr/src/lib/libparted/common/lib/localcharset.c | 460 -- usr/src/lib/libparted/common/lib/localcharset.h | 41 - usr/src/lib/libparted/common/lib/long-options.c | 89 - usr/src/lib/libparted/common/lib/long-options.h | 26 - usr/src/lib/libparted/common/lib/memcpy.c | 36 - usr/src/lib/libparted/common/lib/memmove.c | 26 - usr/src/lib/libparted/common/lib/memset.c | 28 - usr/src/lib/libparted/common/lib/quotearg.c | 697 --- usr/src/lib/libparted/common/lib/quotearg.h | 140 - usr/src/lib/libparted/common/lib/regcomp.c | 3832 -------------- usr/src/lib/libparted/common/lib/regex.c | 71 - usr/src/lib/libparted/common/lib/regex.h | 675 --- usr/src/lib/libparted/common/lib/regex_internal.c | 1741 ------- usr/src/lib/libparted/common/lib/regex_internal.h | 853 ---- usr/src/lib/libparted/common/lib/regexec.c | 4399 ---------------- usr/src/lib/libparted/common/lib/rpmatch.c | 79 - usr/src/lib/libparted/common/lib/safe-read.c | 78 - usr/src/lib/libparted/common/lib/safe-read.h | 35 - usr/src/lib/libparted/common/lib/safe-write.c | 19 - usr/src/lib/libparted/common/lib/safe-write.h | 25 - usr/src/lib/libparted/common/lib/strcspn.c | 41 - usr/src/lib/libparted/common/lib/stripslash.c | 45 - usr/src/lib/libparted/common/lib/strndup.c | 37 - usr/src/lib/libparted/common/lib/version-etc-fsf.c | 31 - usr/src/lib/libparted/common/lib/version-etc.c | 173 - usr/src/lib/libparted/common/lib/version-etc.h | 37 - usr/src/lib/libparted/common/lib/xalloc-die.c | 42 - usr/src/lib/libparted/common/lib/xalloc.h | 271 - usr/src/lib/libparted/common/lib/xmalloc.c | 123 - usr/src/lib/libparted/common/lib/xstrndup.c | 37 - usr/src/lib/libparted/common/lib/xstrndup.h | 25 - .../lib/libparted/common/libparted/arch/solaris.c | 1393 ------ .../lib/libparted/common/libparted/cs/constraint.c | 529 -- usr/src/lib/libparted/common/libparted/cs/geom.c | 474 -- .../lib/libparted/common/libparted/cs/natmath.c | 503 -- usr/src/lib/libparted/common/libparted/debug.c | 120 - usr/src/lib/libparted/common/libparted/device.c | 445 -- usr/src/lib/libparted/common/libparted/disk.c | 2265 --------- usr/src/lib/libparted/common/libparted/exception.c | 312 -- usr/src/lib/libparted/common/libparted/filesys.c | 782 --- .../lib/libparted/common/libparted/fs/amiga/affs.c | 462 -- .../lib/libparted/common/libparted/fs/amiga/affs.h | 19 - .../libparted/common/libparted/fs/amiga/amiga.c | 349 -- .../libparted/common/libparted/fs/amiga/amiga.h | 70 - .../lib/libparted/common/libparted/fs/amiga/apfs.c | 150 - .../lib/libparted/common/libparted/fs/amiga/apfs.h | 17 - .../lib/libparted/common/libparted/fs/amiga/asfs.c | 142 - .../lib/libparted/common/libparted/fs/amiga/asfs.h | 17 - .../common/libparted/fs/amiga/interface.c | 87 - .../lib/libparted/common/libparted/fs/ext2/ext2.c | 792 --- .../lib/libparted/common/libparted/fs/ext2/ext2.h | 249 - .../libparted/fs/ext2/ext2_block_relocator.c | 927 ---- .../common/libparted/fs/ext2/ext2_buffer.c | 446 -- .../libparted/common/libparted/fs/ext2/ext2_fs.h | 323 -- .../libparted/fs/ext2/ext2_inode_relocator.c | 599 --- .../libparted/common/libparted/fs/ext2/ext2_meta.c | 145 - .../libparted/common/libparted/fs/ext2/ext2_mkfs.c | 632 --- .../common/libparted/fs/ext2/ext2_resize.c | 730 --- .../libparted/common/libparted/fs/ext2/interface.c | 352 -- .../libparted/common/libparted/fs/ext2/parted_io.c | 135 - .../libparted/common/libparted/fs/ext2/parted_io.h | 27 - .../lib/libparted/common/libparted/fs/ext2/tune.c | 39 - .../lib/libparted/common/libparted/fs/ext2/tune.h | 29 - .../libparted/common/libparted/fs/fat/bootsector.c | 452 -- .../libparted/common/libparted/fs/fat/bootsector.h | 142 - .../lib/libparted/common/libparted/fs/fat/calc.c | 435 -- .../lib/libparted/common/libparted/fs/fat/calc.h | 77 - .../libparted/common/libparted/fs/fat/clstdup.c | 424 -- .../libparted/common/libparted/fs/fat/clstdup.h | 28 - .../libparted/common/libparted/fs/fat/context.c | 260 - .../libparted/common/libparted/fs/fat/context.h | 69 - .../lib/libparted/common/libparted/fs/fat/count.c | 403 -- .../lib/libparted/common/libparted/fs/fat/count.h | 55 - .../lib/libparted/common/libparted/fs/fat/fat.c | 887 ---- .../lib/libparted/common/libparted/fs/fat/fat.h | 168 - .../lib/libparted/common/libparted/fs/fat/fatio.c | 151 - .../lib/libparted/common/libparted/fs/fat/fatio.h | 48 - .../lib/libparted/common/libparted/fs/fat/resize.c | 877 ---- .../lib/libparted/common/libparted/fs/fat/table.c | 481 -- .../lib/libparted/common/libparted/fs/fat/table.h | 74 - .../libparted/common/libparted/fs/fat/traverse.c | 365 -- .../libparted/common/libparted/fs/fat/traverse.h | 73 - .../lib/libparted/common/libparted/fs/hfs/advfs.c | 328 -- .../lib/libparted/common/libparted/fs/hfs/advfs.h | 48 - .../libparted/common/libparted/fs/hfs/advfs_plus.c | 383 -- .../libparted/common/libparted/fs/hfs/advfs_plus.h | 51 - .../lib/libparted/common/libparted/fs/hfs/cache.c | 238 - .../lib/libparted/common/libparted/fs/hfs/cache.h | 117 - .../lib/libparted/common/libparted/fs/hfs/file.c | 228 - .../lib/libparted/common/libparted/fs/hfs/file.h | 41 - .../libparted/common/libparted/fs/hfs/file_plus.c | 273 - .../libparted/common/libparted/fs/hfs/file_plus.h | 60 - .../lib/libparted/common/libparted/fs/hfs/hfs.c | 1353 ----- .../lib/libparted/common/libparted/fs/hfs/hfs.h | 830 ---- .../libparted/common/libparted/fs/hfs/journal.c | 389 -- .../libparted/common/libparted/fs/hfs/journal.h | 44 - .../lib/libparted/common/libparted/fs/hfs/probe.c | 230 - .../lib/libparted/common/libparted/fs/hfs/probe.h | 43 - .../lib/libparted/common/libparted/fs/hfs/reloc.c | 670 --- .../lib/libparted/common/libparted/fs/hfs/reloc.h | 35 - .../libparted/common/libparted/fs/hfs/reloc_plus.c | 945 ---- .../libparted/common/libparted/fs/hfs/reloc_plus.h | 36 - .../lib/libparted/common/libparted/fs/jfs/jfs.c | 109 - .../common/libparted/fs/jfs/jfs_superblock.h | 144 - .../libparted/common/libparted/fs/jfs/jfs_types.h | 530 -- .../common/libparted/fs/linux_swap/linux_swap.c | 522 -- .../lib/libparted/common/libparted/fs/ntfs/ntfs.c | 599 --- .../common/libparted/fs/reiserfs/geom_dal.c | 138 - .../common/libparted/fs/reiserfs/geom_dal.h | 60 - .../common/libparted/fs/reiserfs/reiserfs.c | 866 ---- .../common/libparted/fs/reiserfs/reiserfs.h | 108 - .../common/libparted/fs/solaris_x86/solaris_x86.c | 171 - .../lib/libparted/common/libparted/fs/ufs/ufs.c | 324 -- .../common/libparted/fs/xfs/platform_defs.h | 117 - .../lib/libparted/common/libparted/fs/xfs/xfs.c | 119 - .../lib/libparted/common/libparted/fs/xfs/xfs_sb.h | 489 -- .../libparted/common/libparted/fs/xfs/xfs_types.h | 302 -- .../lib/libparted/common/libparted/labels/aix.c | 295 -- .../lib/libparted/common/libparted/labels/bsd.c | 633 --- .../lib/libparted/common/libparted/labels/dos.c | 2280 --------- .../lib/libparted/common/libparted/labels/dvh.c | 911 ---- .../lib/libparted/common/libparted/labels/dvh.h | 178 - .../libparted/common/libparted/labels/efi_crc32.c | 126 - .../lib/libparted/common/libparted/labels/gpt.c | 1538 ------ .../lib/libparted/common/libparted/labels/loop.c | 333 -- .../lib/libparted/common/libparted/labels/mac.c | 1629 ------ .../lib/libparted/common/libparted/labels/pc98.c | 896 ---- .../lib/libparted/common/libparted/labels/rdb.c | 1183 ----- .../lib/libparted/common/libparted/labels/sun.c | 868 ---- usr/src/lib/libparted/common/libparted/libparted.c | 351 -- usr/src/lib/libparted/common/libparted/timer.c | 245 - usr/src/lib/libparted/common/libparted/unit.c | 565 --- usr/src/lib/libparted/common/mapfile-vers | 156 - usr/src/man/man1m/Makefile | 17 +- usr/src/man/man1m/mkntfs.1m | 319 -- usr/src/man/man1m/ntfscat.1m | 217 - usr/src/man/man1m/ntfsclone.1m | 460 -- usr/src/man/man1m/ntfscluster.1m | 225 - usr/src/man/man1m/ntfscmp.1m | 104 - usr/src/man/man1m/ntfscp.1m | 199 - usr/src/man/man1m/ntfsfix.1m | 81 - usr/src/man/man1m/ntfsinfo.1m | 151 - usr/src/man/man1m/ntfslabel.1m | 133 - usr/src/man/man1m/ntfsls.1m | 204 - usr/src/man/man1m/ntfsprogs.1m | 185 - usr/src/man/man1m/ntfsresize.1m | 280 -- usr/src/man/man1m/ntfsundelete.1m | 476 -- usr/src/man/man1m/parted.1m | 347 -- usr/src/pkg/manifests/SUNWntfsprogs.mf | 6 +- usr/src/pkg/manifests/SUNWparted.mf | 6 +- .../manifests/system-file-system-ntfsprogs.mf} | 36 +- .../manifests/system-storage-parted.mf} | 21 +- 300 files changed, 22 insertions(+), 123384 deletions(-) delete mode 100644 usr/src/cmd/ntfsprogs/COPYING delete mode 100644 usr/src/cmd/ntfsprogs/CREDITS delete mode 100644 usr/src/cmd/ntfsprogs/Makefile delete mode 100644 usr/src/cmd/ntfsprogs/README delete mode 100644 usr/src/cmd/ntfsprogs/THIRDPARTYLICENSE.descrip delete mode 100644 usr/src/cmd/ntfsprogs/attrdef.c delete mode 100644 usr/src/cmd/ntfsprogs/attrdef.h delete mode 100644 usr/src/cmd/ntfsprogs/boot.c delete mode 100644 usr/src/cmd/ntfsprogs/boot.h delete mode 100644 usr/src/cmd/ntfsprogs/cluster.c delete mode 100644 usr/src/cmd/ntfsprogs/cluster.h delete mode 100644 usr/src/cmd/ntfsprogs/mkntfs.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfscat.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfscat.h delete mode 100644 usr/src/cmd/ntfsprogs/ntfsclone.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfscluster.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfscluster.h delete mode 100644 usr/src/cmd/ntfsprogs/ntfscmp.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfscp.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsfix.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsinfo.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfslabel.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsls.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsresize.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsundelete.c delete mode 100644 usr/src/cmd/ntfsprogs/ntfsundelete.h delete mode 100644 usr/src/cmd/ntfsprogs/sd.c delete mode 100644 usr/src/cmd/ntfsprogs/sd.h delete mode 100644 usr/src/cmd/ntfsprogs/utils.c delete mode 100644 usr/src/cmd/ntfsprogs/utils.h delete mode 100644 usr/src/cmd/parted/COPYING delete mode 100644 usr/src/cmd/parted/Makefile delete mode 100644 usr/src/cmd/parted/README delete mode 100644 usr/src/cmd/parted/THANKS.txt delete mode 100644 usr/src/cmd/parted/THIRDPARTYLICENSE.descrip delete mode 100644 usr/src/cmd/parted/command.c delete mode 100644 usr/src/cmd/parted/command.h delete mode 100644 usr/src/cmd/parted/parted.c delete mode 100644 usr/src/cmd/parted/strlist.h delete mode 100644 usr/src/cmd/parted/table.c delete mode 100644 usr/src/cmd/parted/table.h delete mode 100644 usr/src/cmd/parted/ui.c delete mode 100644 usr/src/cmd/parted/ui.h delete mode 100644 usr/src/lib/libntfs/COPYING delete mode 100644 usr/src/lib/libntfs/CREDITS delete mode 100644 usr/src/lib/libntfs/Makefile delete mode 100644 usr/src/lib/libntfs/Makefile.com delete mode 100644 usr/src/lib/libntfs/README delete mode 100644 usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/attrib.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/attrlist.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/bitmap.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/bootsect.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/collate.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/compat.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/compress.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/config.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/crypto.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/debug.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/device.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/device_io.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/dir.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/endians.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/index.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/inode.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/layout.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/list.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/logfile.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/logging.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/mft.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/mst.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/ntfstime.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/runlist.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/security.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/support.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/types.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/unistr.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/version.h delete mode 100644 usr/src/lib/libntfs/common/include/ntfs/volume.h delete mode 100644 usr/src/lib/libntfs/common/libntfs/attrib.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/attrlist.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/bitmap.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/bootsect.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/collate.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/compat.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/compress.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/crypto.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/debug.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/device.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/device_io.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/dir.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/index.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/inode.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/lcnalloc.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/logfile.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/logging.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/mft.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/misc.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/mst.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/runlist.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/security.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/unistr.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/unix_io.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/version.c delete mode 100644 usr/src/lib/libntfs/common/libntfs/volume.c delete mode 100644 usr/src/lib/libntfs/common/mapfile-vers delete mode 100644 usr/src/lib/libparted/COPYING delete mode 100644 usr/src/lib/libparted/Makefile delete mode 100644 usr/src/lib/libparted/Makefile.com delete mode 100644 usr/src/lib/libparted/README delete mode 100644 usr/src/lib/libparted/THANKS.txt delete mode 100644 usr/src/lib/libparted/THIRDPARTYLICENSE.descrip delete mode 100644 usr/src/lib/libparted/common/include/parted/constraint.h delete mode 100644 usr/src/lib/libparted/common/include/parted/crc32.h delete mode 100644 usr/src/lib/libparted/common/include/parted/debug.h delete mode 100644 usr/src/lib/libparted/common/include/parted/device.h delete mode 100644 usr/src/lib/libparted/common/include/parted/disk.h delete mode 100644 usr/src/lib/libparted/common/include/parted/endian.h delete mode 100644 usr/src/lib/libparted/common/include/parted/exception.h delete mode 100644 usr/src/lib/libparted/common/include/parted/filesys.h delete mode 100644 usr/src/lib/libparted/common/include/parted/geom.h delete mode 100644 usr/src/lib/libparted/common/include/parted/natmath.h delete mode 100644 usr/src/lib/libparted/common/include/parted/parted.h delete mode 100644 usr/src/lib/libparted/common/include/parted/solaris.h delete mode 100644 usr/src/lib/libparted/common/include/parted/timer.h delete mode 100644 usr/src/lib/libparted/common/include/parted/unit.h delete mode 100644 usr/src/lib/libparted/common/lib/__fpending.h delete mode 100644 usr/src/lib/libparted/common/lib/basename.c delete mode 100644 usr/src/lib/libparted/common/lib/close-stream.c delete mode 100644 usr/src/lib/libparted/common/lib/close-stream.h delete mode 100644 usr/src/lib/libparted/common/lib/closeout.c delete mode 100644 usr/src/lib/libparted/common/lib/closeout.h delete mode 100644 usr/src/lib/libparted/common/lib/config.h delete mode 100644 usr/src/lib/libparted/common/lib/configmake.h delete mode 100644 usr/src/lib/libparted/common/lib/dirname.c delete mode 100644 usr/src/lib/libparted/common/lib/dirname.h delete mode 100644 usr/src/lib/libparted/common/lib/error.c delete mode 100644 usr/src/lib/libparted/common/lib/error.h delete mode 100644 usr/src/lib/libparted/common/lib/exitfail.c delete mode 100644 usr/src/lib/libparted/common/lib/exitfail.h delete mode 100644 usr/src/lib/libparted/common/lib/full-write.c delete mode 100644 usr/src/lib/libparted/common/lib/full-write.h delete mode 100644 usr/src/lib/libparted/common/lib/getopt.c delete mode 100644 usr/src/lib/libparted/common/lib/getopt_int.h delete mode 100644 usr/src/lib/libparted/common/lib/gettext.h delete mode 100644 usr/src/lib/libparted/common/lib/localcharset.c delete mode 100644 usr/src/lib/libparted/common/lib/localcharset.h delete mode 100644 usr/src/lib/libparted/common/lib/long-options.c delete mode 100644 usr/src/lib/libparted/common/lib/long-options.h delete mode 100644 usr/src/lib/libparted/common/lib/memcpy.c delete mode 100644 usr/src/lib/libparted/common/lib/memmove.c delete mode 100644 usr/src/lib/libparted/common/lib/memset.c delete mode 100644 usr/src/lib/libparted/common/lib/quotearg.c delete mode 100644 usr/src/lib/libparted/common/lib/quotearg.h delete mode 100644 usr/src/lib/libparted/common/lib/regcomp.c delete mode 100644 usr/src/lib/libparted/common/lib/regex.c delete mode 100644 usr/src/lib/libparted/common/lib/regex.h delete mode 100644 usr/src/lib/libparted/common/lib/regex_internal.c delete mode 100644 usr/src/lib/libparted/common/lib/regex_internal.h delete mode 100644 usr/src/lib/libparted/common/lib/regexec.c delete mode 100644 usr/src/lib/libparted/common/lib/rpmatch.c delete mode 100644 usr/src/lib/libparted/common/lib/safe-read.c delete mode 100644 usr/src/lib/libparted/common/lib/safe-read.h delete mode 100644 usr/src/lib/libparted/common/lib/safe-write.c delete mode 100644 usr/src/lib/libparted/common/lib/safe-write.h delete mode 100644 usr/src/lib/libparted/common/lib/strcspn.c delete mode 100644 usr/src/lib/libparted/common/lib/stripslash.c delete mode 100644 usr/src/lib/libparted/common/lib/strndup.c delete mode 100644 usr/src/lib/libparted/common/lib/version-etc-fsf.c delete mode 100644 usr/src/lib/libparted/common/lib/version-etc.c delete mode 100644 usr/src/lib/libparted/common/lib/version-etc.h delete mode 100644 usr/src/lib/libparted/common/lib/xalloc-die.c delete mode 100644 usr/src/lib/libparted/common/lib/xalloc.h delete mode 100644 usr/src/lib/libparted/common/lib/xmalloc.c delete mode 100644 usr/src/lib/libparted/common/lib/xstrndup.c delete mode 100644 usr/src/lib/libparted/common/lib/xstrndup.h delete mode 100644 usr/src/lib/libparted/common/libparted/arch/solaris.c delete mode 100644 usr/src/lib/libparted/common/libparted/cs/constraint.c delete mode 100644 usr/src/lib/libparted/common/libparted/cs/geom.c delete mode 100644 usr/src/lib/libparted/common/libparted/cs/natmath.c delete mode 100644 usr/src/lib/libparted/common/libparted/debug.c delete mode 100644 usr/src/lib/libparted/common/libparted/device.c delete mode 100644 usr/src/lib/libparted/common/libparted/disk.c delete mode 100644 usr/src/lib/libparted/common/libparted/exception.c delete mode 100644 usr/src/lib/libparted/common/libparted/filesys.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/affs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/affs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/amiga.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/amiga.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/apfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/apfs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/asfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/asfs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/amiga/interface.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_block_relocator.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_buffer.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_fs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_inode_relocator.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_mkfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/ext2_resize.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/interface.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/tune.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ext2/tune.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/bootsector.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/bootsector.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/calc.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/calc.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/clstdup.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/clstdup.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/context.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/context.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/count.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/count.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/fat.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/fat.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/fatio.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/fatio.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/resize.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/table.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/table.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/traverse.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/fat/traverse.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/advfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/advfs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/cache.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/cache.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/file.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/file.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/hfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/hfs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/journal.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/journal.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/probe.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/probe.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/reloc.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/reloc.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/jfs/jfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/jfs/jfs_superblock.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/jfs/jfs_types.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/linux_swap/linux_swap.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ntfs/ntfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/solaris_x86/solaris_x86.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/ufs/ufs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/xfs/platform_defs.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/xfs/xfs.c delete mode 100644 usr/src/lib/libparted/common/libparted/fs/xfs/xfs_sb.h delete mode 100644 usr/src/lib/libparted/common/libparted/fs/xfs/xfs_types.h delete mode 100644 usr/src/lib/libparted/common/libparted/labels/aix.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/bsd.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/dos.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/dvh.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/dvh.h delete mode 100644 usr/src/lib/libparted/common/libparted/labels/efi_crc32.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/gpt.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/loop.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/mac.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/pc98.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/rdb.c delete mode 100644 usr/src/lib/libparted/common/libparted/labels/sun.c delete mode 100644 usr/src/lib/libparted/common/libparted/libparted.c delete mode 100644 usr/src/lib/libparted/common/libparted/timer.c delete mode 100644 usr/src/lib/libparted/common/libparted/unit.c delete mode 100644 usr/src/lib/libparted/common/mapfile-vers delete mode 100644 usr/src/man/man1m/mkntfs.1m delete mode 100644 usr/src/man/man1m/ntfscat.1m delete mode 100644 usr/src/man/man1m/ntfsclone.1m delete mode 100644 usr/src/man/man1m/ntfscluster.1m delete mode 100644 usr/src/man/man1m/ntfscmp.1m delete mode 100644 usr/src/man/man1m/ntfscp.1m delete mode 100644 usr/src/man/man1m/ntfsfix.1m delete mode 100644 usr/src/man/man1m/ntfsinfo.1m delete mode 100644 usr/src/man/man1m/ntfslabel.1m delete mode 100644 usr/src/man/man1m/ntfsls.1m delete mode 100644 usr/src/man/man1m/ntfsprogs.1m delete mode 100644 usr/src/man/man1m/ntfsresize.1m delete mode 100644 usr/src/man/man1m/ntfsundelete.1m delete mode 100644 usr/src/man/man1m/parted.1m rename usr/src/{lib/libparted/i386/Makefile => pkg/manifests/system-file-system-ntfsprogs.mf} (55%) rename usr/src/{lib/libntfs/i386/Makefile => pkg/manifests/system-storage-parted.mf} (73%) diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile index 45a41f1eff..5e2b65379b 100644 --- a/usr/src/cmd/Makefile +++ b/usr/src/cmd/Makefile @@ -477,8 +477,6 @@ i386_SUBDIRS= \ biosdev \ diskscan \ lms \ - ntfsprogs \ - parted \ rtc \ ucodeadm \ xvm diff --git a/usr/src/cmd/ntfsprogs/COPYING b/usr/src/cmd/ntfsprogs/COPYING deleted file mode 100644 index d60c31a97a..0000000000 --- a/usr/src/cmd/ntfsprogs/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. diff --git a/usr/src/cmd/ntfsprogs/CREDITS b/usr/src/cmd/ntfsprogs/CREDITS deleted file mode 100644 index 29bd3e4c85..0000000000 --- a/usr/src/cmd/ntfsprogs/CREDITS +++ /dev/null @@ -1,40 +0,0 @@ -The following people have contributed directly or indirectly to the Linux-NTFS -project. - -The list is sorted alphabetically, so please keep it this way! - -Please contact if you believe someone is -missing or if you prefer not to be listed. - -Alexei Alexandrov -Anton Altaparmakov -Albert D. Cahalan -Russ Christensen -Pete Curran -Mario Emmenlauer -Andras Erdei -Matthew J. Fanto -Yuval Fledel -Marcin Gibuła -Christophe Grenier -Csaba Henk -Ian Jackson -Max Khon -Carmelo Kintana -Jan Kratochvil -Lode Leroy -David Martínez Moreno -Giang Nguyen -Leonard Norrgård -Holger Ohmacht -Per Olofsson -Yura Pakhuchiy -Yuri Per -Richard Russon -Erik Sørnes -Szabolcs Szakacsits -zhanglinbao - -Configuration, compilation and installation system are originally based on -numerous different GNU and Gnome utilities and libraries so "Many thanks!" -to all the people who have participated in their creation! diff --git a/usr/src/cmd/ntfsprogs/Makefile b/usr/src/cmd/ntfsprogs/Makefile deleted file mode 100644 index 26ffffe100..0000000000 --- a/usr/src/cmd/ntfsprogs/Makefile +++ /dev/null @@ -1,160 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -MKNTFS= mkntfs -NTFSCAT= ntfscat -NTFSCLONE= ntfsclone -NTFSCLUSTER= ntfscluster -NTFSCMP= ntfscmp -NTFSCP= ntfscp -NTFSFIX= ntfsfix -NTFSINFO= ntfsinfo -NTFSLABEL= ntfslabel -NTFSLS= ntfsls -NTFSRESIZE= ntfsresize -NTFSUNDELETE= ntfsundelete - -include ../Makefile.cmd - -C99MODE= $(C99_ENABLE) -CERRWARN += -erroff=E_ATTRIBUTE_PARAM_UNDEFINED -CERRWARN += -erroff=E_ENUM_VAL_OVERFLOWS_INT_MAX -CERRWARN += -erroff=E_STRUCT_DERIVED_FROM_FLEX_MBR - -CPPFLAGS += -DHAVE_CONFIG_H \ - -I. \ - -I../../lib/libntfs/common/include/ntfs - -MKNTFSOBJS= attrdef.o boot.o sd.o mkntfs.o utils.o -NTFSCATOBJS= ntfscat.o utils.o -NTFSCLONEOBJS= ntfsclone.o utils.o -NTFSCLUSTEROBJS=ntfscluster.o cluster.o utils.o -NTFSCMPOBJS= ntfscmp.o utils.o -NTFSCPOBJS= ntfscp.o utils.o -NTFSFIXOBJS= ntfsfix.o utils.o -NTFSINFOOBJS= ntfsinfo.o utils.o -NTFSLABELOBJS= ntfslabel.o utils.o -NTFSLSOBJS= ntfsls.o utils.o -NTFSRESIZEOBJS= ntfsresize.o utils.o -NTFSUNDELETEOBJS=ntfsundelete.o utils.o - -LDLIBS += ../../lib/libntfs/i386/libntfs.so.10 - -ROOTPROG= $(MKNTFS:%=$(ROOTUSRSBIN)/%) \ - $(NTFSCAT:%=$(ROOTUSRSBIN)/%) \ - $(NTFSCLONE:%=$(ROOTUSRSBIN)/%) \ - $(NTFSCLUSTER:%=$(ROOTUSRSBIN)/%) \ - $(NTFSCMP:%=$(ROOTUSRSBIN)/%) \ - $(NTFSCP:%=$(ROOTUSRSBIN)/%) \ - $(NTFSFIX:%=$(ROOTUSRSBIN)/%) \ - $(NTFSINFO:%=$(ROOTUSRSBIN)/%) \ - $(NTFSLABEL:%=$(ROOTUSRSBIN)/%) \ - $(NTFSLS:%=$(ROOTUSRSBIN)/%) \ - $(NTFSRESIZE:%=$(ROOTUSRSBIN)/%) \ - $(NTFSUNDELETE:%=$(ROOTUSRSBIN)/%) - -.KEEP_STATE: -all: $(MKNTFS) $(NTFSCAT) $(NTFSCLONE) $(NTFSCLUSTER) \ - $(NTFSCMP) $(NTFSCP) $(NTFSFIX) $(NTFSINFO) \ - $(NTFSLABEL) $(NTFSLS) $(NTFSRESIZE) $(NTFSUNDELETE) - -all install: THIRDPARTYLICENSE - -CLOBBERFILES += THIRDPARTYLICENSE - -THIRDPARTYLICENSE: $(SRC)/common/GPLDISCLAIMER COPYING - $(RM) $@ - $(CAT) $(SRC)/common/GPLDISCLAIMER COPYING > $@ - -$(MKNTFS): $(MKNTFSOBJS) - $(LINK.c) -o $(MKNTFS) $(MKNTFSOBJS) $(LDLIBS) -luuid - $(POST_PROCESS) - -$(NTFSCAT): $(NTFSCATOBJS) - $(LINK.c) -o $(NTFSCAT) $(NTFSCATOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSCLONE): $(NTFSCLONEOBJS) - $(LINK.c) -o $(NTFSCLONE) $(NTFSCLONEOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSCLUSTER): $(NTFSCLUSTEROBJS) - $(LINK.c) -o $(NTFSCLUSTER) $(NTFSCLUSTEROBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSCMP): $(NTFSCMPOBJS) - $(LINK.c) -o $(NTFSCMP) $(NTFSCMPOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSCP): $(NTFSCPOBJS) - $(LINK.c) -o $(NTFSCP) $(NTFSCPOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSFIX): $(NTFSFIXOBJS) - $(LINK.c) -o $(NTFSFIX) $(NTFSFIXOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSINFO): $(NTFSINFOOBJS) - $(LINK.c) -o $(NTFSINFO) $(NTFSINFOOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSLABEL): $(NTFSLABELOBJS) - $(LINK.c) -o $(NTFSLABEL) $(NTFSLABELOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSLS): $(NTFSLSOBJS) - $(LINK.c) -o $(NTFSLS) $(NTFSLSOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSRESIZE): $(NTFSRESIZEOBJS) - $(LINK.c) -o $(NTFSRESIZE) $(NTFSRESIZEOBJS) $(LDLIBS) - $(POST_PROCESS) - -$(NTFSUNDELETE): $(NTFSUNDELETEOBJS) - $(LINK.c) -o $(NTFSUNDELETE) $(NTFSUNDELETEOBJS) $(LDLIBS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) $(MKNTFS) $(MKNTFSOBJS) \ - $(NTFSCAT) $(NTFSCATOBJS) \ - $(NTFSCLONE) $(NTFSCLONEOBJS) \ - $(NTFSCLUSTER) $(NTFSCLUSTEROBJS) \ - $(NTFSCMP) $(NTFSCMPOBJS) \ - $(NTFSCP) $(NTFSCPOBJS) \ - $(NTFSFIX) $(NTFSFIXOBJS) \ - $(NTFSINFO) $(NTFSINFOOBJS) \ - $(NTFSLABEL) $(NTFSLABELOBJS) \ - $(NTFSLS) $(NTFSLSOBJS) \ - $(NTFSRESIZE) $(NTFSRESIZEOBJS) \ - $(NTFSUNDELETE) $(NTFSUNDELETEOBJS) - -# -# This open source is exempted from lint -# -lint: - -include ../Makefile.targ diff --git a/usr/src/cmd/ntfsprogs/README b/usr/src/cmd/ntfsprogs/README deleted file mode 100644 index 58c4aec793..0000000000 --- a/usr/src/cmd/ntfsprogs/README +++ /dev/null @@ -1,9 +0,0 @@ -This is the Solaris ON port of ntfsprogs v2.0.0 -Please see http://www.linux-ntfs.org/ for more information. - -ntfsprogs has been broken into two pieces: src/lib/libntfs and src/cmd/ntfsprogs - -The Makefiles have all been replaced by ON Makefiles. - -This directory contains the necessary contents of ntfsprogs-2.0.0/ntfsprogs -ntfsmount is missing until FUSE has been integrated into ON. diff --git a/usr/src/cmd/ntfsprogs/THIRDPARTYLICENSE.descrip b/usr/src/cmd/ntfsprogs/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 6d2fc7f55a..0000000000 --- a/usr/src/cmd/ntfsprogs/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -ntfsprogs - NTFS utilities diff --git a/usr/src/cmd/ntfsprogs/attrdef.c b/usr/src/cmd/ntfsprogs/attrdef.c deleted file mode 100644 index 36501e5c27..0000000000 --- a/usr/src/cmd/ntfsprogs/attrdef.c +++ /dev/null @@ -1,168 +0,0 @@ -#include "attrdef.h" - -/** - * attrdef_ntfs3x_array - */ -const unsigned char attrdef_ntfs3x_array[2560] = { -0x24, 0x00, 0x53, 0x00, 0x54, 0x00, 0x41, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x41, 0x00, 0x52, 0x00, -0x44, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x4D, 0x00, -0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 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, 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, -0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x41, 0x00, 0x54, 0x00, 0x54, 0x00, 0x52, 0x00, 0x49, 0x00, 0x42, 0x00, 0x55, 0x00, -0x54, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x53, 0x00, 0x54, 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, 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, -0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x46, 0x00, 0x49, 0x00, 0x4C, 0x00, 0x45, 0x00, 0x5F, 0x00, 0x4E, 0x00, 0x41, 0x00, -0x4D, 0x00, 0x45, 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, 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, -0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, -0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x4F, 0x00, 0x42, 0x00, 0x4A, 0x00, 0x45, 0x00, 0x43, 0x00, 0x54, 0x00, 0x5F, 0x00, -0x49, 0x00, 0x44, 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, 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, -0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x53, 0x00, 0x45, 0x00, 0x43, 0x00, 0x55, 0x00, 0x52, 0x00, 0x49, 0x00, 0x54, 0x00, -0x59, 0x00, 0x5F, 0x00, 0x44, 0x00, 0x45, 0x00, 0x53, 0x00, 0x43, 0x00, 0x52, 0x00, 0x49, 0x00, -0x50, 0x00, 0x54, 0x00, 0x4F, 0x00, 0x52, 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, 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, -0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x56, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x55, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00, -0x4E, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x45, 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, 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, -0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x56, 0x00, 0x4F, 0x00, 0x4C, 0x00, 0x55, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x5F, 0x00, -0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, 0x52, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x54, 0x00, -0x49, 0x00, 0x4F, 0x00, 0x4E, 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, -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, -0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x44, 0x00, 0x41, 0x00, 0x54, 0x00, 0x41, 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, 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, 0x00, -0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x45, 0x00, 0x58, 0x00, 0x5F, 0x00, 0x52, 0x00, -0x4F, 0x00, 0x4F, 0x00, 0x54, 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, -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, -0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x44, 0x00, 0x45, 0x00, 0x58, 0x00, 0x5F, 0x00, 0x41, 0x00, -0x4C, 0x00, 0x4C, 0x00, 0x4F, 0x00, 0x43, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, -0x4E, 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, 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, -0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x42, 0x00, 0x49, 0x00, 0x54, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x50, 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, 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, -0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -0x24, 0x00, 0x52, 0x00, 0x45, 0x00, 0x50, 0x00, 0x41, 0x00, 0x52, 0x00, 0x53, 0x00, 0x45, 0x00, -0x5F, 0x00, 0x50, 0x00, 0x4F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x54, 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, 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, -0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x45, 0x00, 0x41, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00, -0x52, 0x00, 0x4D, 0x00, 0x41, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4F, 0x00, 0x4E, 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, 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, -0xD0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, -0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x45, 0x00, 0x41, 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, -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, 0x00, 0x00, 0x00, 0x00, 0x00, -0xE0, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, -0x24, 0x00, 0x4C, 0x00, 0x4F, 0x00, 0x47, 0x00, 0x47, 0x00, 0x45, 0x00, 0x44, 0x00, 0x5F, 0x00, -0x55, 0x00, 0x54, 0x00, 0x49, 0x00, 0x4C, 0x00, 0x49, 0x00, 0x54, 0x00, 0x59, 0x00, 0x5F, 0x00, -0x53, 0x00, 0x54, 0x00, 0x52, 0x00, 0x45, 0x00, 0x41, 0x00, 0x4D, 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, 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, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 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, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - diff --git a/usr/src/cmd/ntfsprogs/attrdef.h b/usr/src/cmd/ntfsprogs/attrdef.h deleted file mode 100644 index 0c664394e0..0000000000 --- a/usr/src/cmd/ntfsprogs/attrdef.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _NTFS_ATTRDEF_H_ -#define _NTFS_ATTRDEF_H_ - -extern const unsigned char attrdef_ntfs3x_array[2560]; - -#endif /* _NTFS_ATTRDEF_H_ */ - diff --git a/usr/src/cmd/ntfsprogs/boot.c b/usr/src/cmd/ntfsprogs/boot.c deleted file mode 100644 index 9272be9fb1..0000000000 --- a/usr/src/cmd/ntfsprogs/boot.c +++ /dev/null @@ -1,268 +0,0 @@ -#include "boot.h" - -/** - * boot_array - the first 4136 bytes of $Boot - * - * The first 4136 bytes of $Boot. The rest is just zero. Total 8192 bytes. - */ -const unsigned char boot_array[4136] = { -235, 82, 144, 78, 84, 70, 83, 32, 32, 32, 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 250, 51, 192, 142, 208, 188, 0, 124, 251, 104, 192, 7, - 31, 30, 104, 102, 0, 203, 136, 22, 14, 0, 102, 129, 62, 3, 0, 78, - 84, 70, 83, 117, 21, 180, 65, 187, 170, 85, 205, 19, 114, 12, 129, 251, - 85, 170, 117, 6, 247, 193, 1, 0, 117, 3, 233, 210, 0, 30, 131, 236, - 24, 104, 26, 0, 180, 72, 138, 22, 14, 0, 139, 244, 22, 31, 205, 19, -159, 131, 196, 24, 158, 88, 31, 114, 225, 59, 6, 11, 0, 117, 219, 163, - 15, 0, 193, 46, 15, 0, 4, 30, 90, 51, 219, 185, 0, 32, 43, 200, -102, 255, 6, 17, 0, 3, 22, 15, 0, 142, 194, 255, 6, 22, 0, 232, - 64, 0, 43, 200, 119, 239, 184, 0, 187, 205, 26, 102, 35, 192, 117, 45, -102, 129, 251, 84, 67, 80, 65, 117, 36, 129, 249, 2, 1, 114, 30, 22, -104, 7, 187, 22, 104, 112, 14, 22, 104, 9, 0, 102, 83, 102, 83, 102, - 85, 22, 22, 22, 104, 184, 1, 102, 97, 14, 7, 205, 26, 233, 106, 1, -144, 144, 102, 96, 30, 6, 102, 161, 17, 0, 102, 3, 6, 28, 0, 30, -102, 104, 0, 0, 0, 0, 102, 80, 6, 83, 104, 1, 0, 104, 16, 0, -180, 66, 138, 22, 14, 0, 22, 31, 139, 244, 205, 19, 102, 89, 91, 90, -102, 89, 102, 89, 31, 15, 130, 22, 0, 102, 255, 6, 17, 0, 3, 22, - 15, 0, 142, 194, 255, 14, 22, 0, 117, 188, 7, 31, 102, 97, 195, 160, -248, 1, 232, 8, 0, 160, 251, 1, 232, 2, 0, 235, 254, 180, 1, 139, -240, 172, 60, 0, 116, 9, 180, 14, 187, 7, 0, 205, 16, 235, 242, 195, - 13, 10, 65, 32, 100, 105, 115, 107, 32, 114, 101, 97, 100, 32, 101, 114, -114, 111, 114, 32, 111, 99, 99, 117, 114, 114, 101, 100, 0, 13, 10, 66, - 79, 79, 84, 77, 71, 82, 32, 105, 115, 32, 109, 105, 115, 115, 105, 110, -103, 0, 13, 10, 66, 79, 79, 84, 77, 71, 82, 32, 105, 115, 32, 99, -111, 109, 112, 114, 101, 115, 115, 101, 100, 0, 13, 10, 80, 114, 101, 115, -115, 32, 67, 116, 114, 108, 43, 65, 108, 116, 43, 68, 101, 108, 32, 116, -111, 32, 114, 101, 115, 116, 97, 114, 116, 13, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 128, 157, 178, 202, 0, 0, 85, 170, - 7, 0, 66, 0, 79, 0, 79, 0, 84, 0, 77, 0, 71, 0, 82, 0, - 4, 0, 36, 0, 73, 0, 51, 0, 48, 0, 0, 224, 0, 0, 0, 48, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 235, 34, 144, 144, 5, 0, 78, 0, 84, 0, - 76, 0, 68, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 15, 183, 6, 11, 0, -102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 163, 82, 2, 102, 139, 14, - 64, 0, 128, 249, 0, 15, 143, 14, 0, 246, 217, 102, 184, 1, 0, 0, - 0, 102, 211, 224, 235, 8, 144, 102, 161, 82, 2, 102, 247, 225, 102, 163, -102, 2, 102, 15, 183, 30, 11, 0, 102, 51, 210, 102, 247, 243, 102, 163, - 86, 2, 232, 149, 4, 102, 139, 14, 78, 2, 102, 137, 14, 38, 2, 102, - 3, 14, 102, 2, 102, 137, 14, 42, 2, 102, 3, 14, 102, 2, 102, 137, - 14, 46, 2, 102, 3, 14, 102, 2, 102, 137, 14, 62, 2, 102, 3, 14, -102, 2, 102, 137, 14, 70, 2, 102, 184, 144, 0, 0, 0, 102, 139, 14, - 38, 2, 232, 131, 9, 102, 11, 192, 15, 132, 83, 254, 102, 163, 50, 2, -102, 184, 160, 0, 0, 0, 102, 139, 14, 42, 2, 232, 106, 9, 102, 163, - 54, 2, 102, 184, 176, 0, 0, 0, 102, 139, 14, 46, 2, 232, 88, 9, -102, 163, 58, 2, 102, 161, 50, 2, 102, 11, 192, 15, 132, 32, 254, 103, -128, 120, 8, 0, 15, 133, 23, 254, 103, 102, 141, 80, 16, 103, 3, 66, - 4, 103, 102, 15, 182, 72, 12, 102, 137, 14, 114, 2, 103, 102, 139, 72, - 8, 102, 137, 14, 110, 2, 102, 161, 110, 2, 102, 15, 183, 14, 11, 0, -102, 51, 210, 102, 247, 241, 102, 163, 118, 2, 102, 161, 70, 2, 102, 3, - 6, 110, 2, 102, 163, 74, 2, 102, 131, 62, 54, 2, 0, 15, 132, 29, - 0, 102, 131, 62, 58, 2, 0, 15, 132, 196, 253, 102, 139, 30, 58, 2, - 30, 7, 102, 139, 62, 74, 2, 102, 161, 46, 2, 232, 224, 1, 102, 15, -183, 14, 0, 2, 102, 184, 2, 2, 0, 0, 232, 34, 8, 102, 11, 192, - 15, 133, 22, 0, 102, 15, 183, 14, 90, 2, 102, 184, 92, 2, 0, 0, -232, 12, 8, 102, 11, 192, 15, 132, 66, 12, 103, 102, 139, 0, 30, 7, -102, 139, 62, 62, 2, 232, 63, 6, 102, 161, 62, 2, 102, 187, 32, 0, - 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 228, - 0, 102, 133, 192, 15, 133, 35, 0, 102, 161, 62, 2, 102, 187, 128, 0, - 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 196, - 0, 102, 11, 192, 15, 133, 68, 0, 233, 241, 11, 102, 51, 210, 102, 185, -128, 0, 0, 0, 102, 161, 62, 2, 232, 202, 8, 102, 11, 192, 15, 132, -218, 11, 30, 7, 102, 139, 62, 62, 2, 232, 219, 5, 102, 161, 62, 2, -102, 187, 128, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, - 0, 0, 232, 128, 0, 102, 11, 192, 15, 132, 176, 11, 103, 102, 15, 183, - 88, 12, 102, 129, 227, 255, 0, 0, 0, 15, 133, 165, 11, 102, 139, 216, -104, 0, 32, 7, 102, 43, 255, 102, 161, 62, 2, 232, 0, 1, 104, 0, - 32, 7, 102, 43, 255, 102, 161, 62, 2, 232, 172, 10, 138, 22, 14, 0, -184, 232, 3, 142, 192, 141, 54, 11, 0, 43, 192, 104, 0, 32, 80, 203, - 6, 30, 102, 96, 102, 139, 218, 102, 15, 182, 14, 13, 0, 102, 247, 225, -102, 163, 17, 0, 102, 139, 195, 102, 247, 225, 163, 22, 0, 139, 223, 131, -227, 15, 140, 192, 102, 193, 239, 4, 3, 199, 80, 7, 232, 51, 252, 102, - 97, 144, 31, 7, 195, 103, 3, 64, 20, 103, 102, 131, 56, 255, 15, 132, - 76, 0, 103, 102, 57, 24, 15, 133, 51, 0, 102, 11, 201, 15, 133, 10, - 0, 103, 128, 120, 9, 0, 15, 133, 35, 0, 195, 103, 58, 72, 9, 15, -133, 26, 0, 102, 139, 240, 103, 3, 112, 10, 232, 151, 6, 102, 81, 30, - 7, 102, 139, 250, 243, 167, 102, 89, 15, 133, 1, 0, 195, 103, 102, 131, -120, 4, 0, 15, 132, 7, 0, 103, 102, 3, 64, 4, 235, 171, 102, 43, -192, 195, 102, 139, 243, 232, 108, 6, 103, 102, 3, 0, 103, 247, 64, 12, - 2, 0, 15, 133, 52, 0, 103, 102, 141, 80, 16, 103, 58, 74, 64, 15, -133, 24, 0, 103, 102, 141, 114, 66, 232, 73, 6, 102, 81, 30, 7, 102, -139, 251, 243, 167, 102, 89, 15, 133, 1, 0, 195, 103, 131, 120, 8, 0, - 15, 132, 6, 0, 103, 3, 64, 8, 235, 194, 102, 51, 192, 195, 103, 128, -123, 8, 0, 15, 133, 28, 0, 6, 30, 102, 96, 103, 102, 141, 83, 16, -103, 102, 139, 10, 102, 139, 243, 103, 3, 114, 4, 243, 164, 102, 97, 144, - 31, 7, 195, 102, 80, 103, 102, 141, 83, 16, 102, 133, 192, 15, 133, 10, - 0, 103, 102, 139, 74, 8, 102, 65, 235, 17, 144, 103, 102, 139, 66, 24, -102, 51, 210, 102, 247, 54, 82, 2, 102, 139, 200, 102, 43, 192, 102, 94, -232, 1, 0, 195, 6, 30, 102, 96, 103, 128, 123, 8, 1, 15, 132, 3, - 0, 233, 107, 251, 102, 131, 249, 0, 15, 133, 6, 0, 102, 97, 144, 31, - 7, 195, 102, 83, 102, 80, 102, 81, 102, 86, 102, 87, 6, 232, 145, 4, -102, 139, 209, 7, 102, 95, 102, 94, 102, 89, 102, 133, 192, 15, 132, 52, - 0, 102, 59, 202, 15, 141, 3, 0, 102, 139, 209, 232, 130, 254, 102, 43, -202, 102, 139, 218, 102, 139, 194, 102, 15, 182, 22, 13, 0, 102, 247, 226, -102, 15, 183, 22, 11, 0, 102, 247, 226, 102, 3, 248, 102, 88, 102, 3, -195, 102, 91, 235, 159, 102, 133, 246, 15, 132, 3, 251, 102, 81, 102, 87, - 6, 103, 102, 15, 182, 67, 9, 102, 133, 192, 15, 132, 32, 0, 102, 209, -224, 102, 43, 224, 102, 139, 252, 102, 84, 102, 86, 103, 102, 15, 183, 115, - 10, 102, 3, 243, 102, 139, 200, 243, 164, 102, 94, 235, 3, 144, 102, 80, -102, 80, 103, 102, 139, 3, 102, 80, 103, 102, 139, 67, 24, 102, 80, 103, -102, 139, 86, 32, 102, 133, 210, 15, 132, 11, 0, 102, 139, 254, 30, 7, -102, 139, 194, 232, 113, 3, 102, 139, 198, 102, 90, 102, 89, 102, 66, 102, - 81, 102, 86, 232, 63, 6, 102, 133, 192, 15, 132, 146, 250, 102, 94, 102, - 89, 102, 139, 254, 30, 7, 232, 78, 3, 102, 139, 198, 102, 139, 217, 102, - 89, 102, 90, 102, 81, 102, 86, 102, 209, 233, 232, 248, 253, 102, 133, 192, - 15, 132, 107, 250, 102, 94, 102, 89, 102, 3, 225, 7, 102, 95, 102, 89, -102, 139, 208, 102, 88, 102, 91, 102, 139, 218, 233, 245, 254, 6, 30, 102, - 96, 38, 103, 102, 15, 183, 95, 4, 38, 103, 102, 15, 183, 79, 6, 102, - 11, 201, 15, 132, 57, 250, 102, 3, 223, 102, 131, 195, 2, 102, 129, 199, -254, 1, 0, 0, 102, 73, 102, 11, 201, 15, 132, 23, 0, 38, 103, 139, - 3, 38, 103, 137, 7, 102, 131, 195, 2, 102, 129, 199, 0, 2, 0, 0, -102, 73, 235, 226, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 184, - 1, 0, 0, 0, 102, 163, 34, 2, 102, 161, 30, 2, 102, 3, 6, 102, - 2, 102, 163, 106, 2, 102, 3, 6, 102, 2, 102, 163, 78, 2, 102, 161, - 48, 0, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 139, 30, 78, 2, -102, 137, 7, 102, 163, 17, 0, 131, 195, 4, 102, 161, 86, 2, 102, 137, - 7, 163, 22, 0, 131, 195, 4, 102, 137, 30, 78, 2, 102, 139, 30, 30, - 2, 30, 7, 232, 92, 249, 102, 139, 251, 232, 81, 255, 102, 161, 30, 2, -102, 187, 32, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, - 0, 0, 232, 16, 253, 102, 11, 192, 15, 132, 25, 1, 102, 139, 216, 30, - 7, 102, 139, 62, 26, 2, 102, 51, 192, 232, 162, 253, 102, 139, 30, 26, - 2, 102, 129, 63, 128, 0, 0, 0, 15, 132, 235, 0, 3, 95, 4, 235, -240, 102, 83, 102, 139, 71, 16, 102, 247, 38, 86, 2, 102, 80, 102, 51, -210, 102, 15, 182, 30, 13, 0, 102, 247, 243, 102, 82, 232, 220, 0, 102, - 11, 192, 15, 132, 57, 249, 102, 139, 14, 86, 2, 102, 15, 182, 30, 13, - 0, 102, 247, 227, 102, 90, 102, 3, 194, 102, 139, 30, 78, 2, 102, 137, - 7, 131, 195, 4, 102, 15, 182, 6, 13, 0, 102, 43, 194, 102, 59, 193, - 15, 134, 3, 0, 102, 139, 193, 102, 137, 7, 102, 43, 200, 102, 90, 15, -132, 117, 0, 102, 3, 194, 102, 80, 102, 51, 210, 102, 15, 182, 30, 13, - 0, 102, 247, 243, 102, 81, 232, 130, 0, 102, 89, 102, 11, 192, 15, 132, -221, 248, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 139, 30, 78, 2, -102, 139, 23, 131, 195, 4, 102, 3, 23, 102, 59, 208, 15, 133, 21, 0, -102, 15, 182, 6, 13, 0, 102, 59, 193, 15, 134, 3, 0, 102, 139, 193, -102, 1, 7, 235, 165, 131, 195, 4, 102, 137, 30, 78, 2, 102, 137, 7, -131, 195, 4, 102, 15, 182, 6, 13, 0, 102, 59, 193, 15, 134, 3, 0, -102, 139, 193, 102, 137, 7, 235, 130, 131, 195, 4, 102, 255, 6, 34, 2, -102, 137, 30, 78, 2, 102, 91, 3, 95, 4, 102, 129, 63, 128, 0, 0, - 0, 15, 132, 12, 255, 102, 97, 144, 31, 7, 195, 102, 139, 208, 102, 139, - 14, 34, 2, 102, 139, 54, 106, 2, 102, 3, 54, 102, 2, 102, 82, 102, - 81, 102, 82, 102, 139, 30, 106, 2, 102, 139, 62, 86, 2, 102, 139, 4, -102, 163, 17, 0, 131, 198, 4, 102, 139, 4, 163, 22, 0, 131, 198, 4, - 30, 7, 232, 221, 247, 102, 43, 248, 15, 132, 8, 0, 247, 38, 11, 0, - 3, 216, 235, 217, 102, 139, 62, 106, 2, 30, 7, 232, 191, 253, 102, 161, -106, 2, 102, 187, 128, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 139, -209, 232, 129, 251, 102, 11, 192, 15, 132, 244, 247, 102, 139, 216, 102, 88, -102, 86, 232, 44, 1, 102, 94, 102, 11, 192, 15, 132, 5, 0, 102, 91, -102, 91, 195, 102, 89, 102, 90, 226, 132, 102, 51, 192, 195, 6, 30, 102, - 96, 102, 80, 102, 81, 102, 51, 210, 102, 15, 182, 30, 13, 0, 102, 247, -243, 102, 82, 102, 87, 232, 83, 255, 102, 95, 102, 11, 192, 15, 132, 174, -247, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 90, 102, 3, 194, 102, -163, 17, 0, 102, 89, 102, 15, 182, 30, 13, 0, 102, 59, 203, 15, 142, - 19, 0, 137, 30, 22, 0, 102, 43, 203, 102, 88, 102, 3, 195, 102, 80, -102, 81, 235, 20, 144, 102, 88, 102, 3, 193, 102, 80, 137, 14, 22, 0, -102, 185, 0, 0, 0, 0, 102, 81, 6, 102, 87, 139, 223, 131, 227, 15, -140, 192, 102, 193, 239, 4, 3, 199, 80, 7, 232, 5, 247, 102, 95, 7, -102, 3, 62, 82, 2, 102, 89, 102, 88, 102, 131, 249, 0, 15, 143, 112, -255, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 247, 38, 86, 2, -102, 139, 14, 86, 2, 232, 85, 255, 232, 210, 252, 102, 97, 144, 31, 7, -195, 6, 30, 102, 96, 102, 247, 38, 114, 2, 102, 139, 30, 54, 2, 102, -139, 14, 114, 2, 102, 139, 54, 42, 2, 30, 7, 102, 139, 62, 70, 2, -232, 129, 251, 232, 167, 252, 102, 97, 144, 31, 7, 195, 102, 80, 102, 83, -102, 81, 102, 139, 30, 74, 2, 102, 139, 200, 102, 193, 232, 3, 102, 131, -225, 7, 102, 3, 216, 102, 184, 1, 0, 0, 0, 102, 211, 224, 103, 132, - 3, 15, 132, 4, 0, 248, 235, 2, 144, 249, 102, 89, 102, 91, 102, 88, -195, 103, 128, 123, 8, 1, 15, 132, 4, 0, 102, 43, 192, 195, 103, 102, -141, 115, 16, 103, 102, 139, 86, 8, 102, 59, 194, 15, 135, 11, 0, 103, -102, 139, 22, 102, 59, 194, 15, 131, 4, 0, 102, 43, 192, 195, 103, 3, - 94, 16, 102, 43, 246, 103, 128, 59, 0, 15, 132, 62, 0, 232, 129, 0, -102, 3, 241, 232, 57, 0, 102, 3, 202, 102, 59, 193, 15, 140, 33, 0, -102, 139, 209, 102, 80, 103, 102, 15, 182, 11, 102, 139, 193, 102, 131, 224, - 15, 102, 193, 233, 4, 102, 3, 217, 102, 3, 216, 102, 67, 102, 88, 235, -196, 102, 43, 200, 102, 43, 194, 102, 3, 198, 195, 102, 43, 192, 195, 102, - 43, 201, 103, 138, 11, 128, 225, 15, 102, 131, 249, 0, 15, 133, 4, 0, -102, 43, 201, 195, 102, 83, 102, 82, 102, 3, 217, 103, 102, 15, 190, 19, -102, 73, 102, 75, 102, 131, 249, 0, 15, 132, 13, 0, 102, 193, 226, 8, -103, 138, 19, 102, 75, 102, 73, 235, 235, 102, 139, 202, 102, 90, 102, 91, -195, 102, 83, 102, 82, 102, 43, 210, 103, 138, 19, 102, 131, 226, 15, 102, - 43, 201, 103, 138, 11, 192, 233, 4, 102, 131, 249, 0, 15, 133, 8, 0, -102, 43, 201, 102, 90, 102, 91, 195, 102, 3, 218, 102, 3, 217, 103, 102, - 15, 190, 19, 102, 73, 102, 75, 102, 131, 249, 0, 15, 132, 13, 0, 102, -193, 226, 8, 103, 138, 19, 102, 75, 102, 73, 235, 235, 102, 139, 202, 102, - 90, 102, 91, 195, 102, 11, 201, 15, 133, 1, 0, 195, 102, 81, 102, 86, -103, 131, 62, 97, 15, 140, 12, 0, 103, 131, 62, 122, 15, 143, 4, 0, -103, 131, 46, 32, 102, 131, 198, 2, 226, 230, 102, 94, 102, 89, 195, 102, - 80, 102, 81, 102, 139, 208, 102, 161, 50, 2, 103, 102, 141, 88, 16, 103, - 3, 67, 4, 103, 102, 141, 64, 16, 102, 139, 218, 232, 68, 249, 102, 11, -192, 15, 132, 5, 0, 102, 89, 102, 89, 195, 102, 161, 54, 2, 102, 11, -192, 15, 133, 8, 0, 102, 89, 102, 89, 102, 51, 192, 195, 102, 139, 22, - 54, 2, 103, 102, 141, 82, 16, 103, 102, 139, 66, 24, 102, 51, 210, 102, -247, 54, 110, 2, 102, 51, 246, 102, 80, 102, 86, 102, 88, 102, 94, 102, - 59, 198, 15, 132, 58, 0, 102, 86, 102, 64, 102, 80, 102, 72, 232, 27, -254, 114, 232, 232, 235, 253, 102, 90, 102, 94, 102, 89, 102, 91, 102, 83, -102, 81, 102, 86, 102, 82, 102, 161, 70, 2, 103, 102, 141, 64, 24, 232, -208, 248, 102, 11, 192, 116, 196, 102, 89, 102, 89, 102, 89, 102, 89, 195, -102, 89, 102, 89, 102, 51, 192, 195, 102, 81, 102, 80, 102, 184, 5, 0, - 0, 0, 30, 7, 102, 139, 249, 232, 141, 253, 102, 139, 193, 102, 187, 32, - 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, - 51, 248, 102, 91, 102, 89, 102, 133, 192, 15, 133, 21, 0, 102, 139, 193, -102, 15, 183, 14, 16, 2, 102, 186, 18, 2, 0, 0, 232, 22, 248, 235, - 51, 144, 102, 51, 210, 102, 139, 193, 102, 139, 203, 102, 80, 102, 83, 232, - 35, 0, 102, 91, 102, 95, 102, 11, 192, 15, 132, 23, 0, 30, 7, 232, - 53, 253, 102, 139, 199, 102, 15, 183, 14, 16, 2, 102, 186, 18, 2, 0, - 0, 232, 225, 247, 195, 102, 82, 102, 81, 102, 187, 32, 0, 0, 0, 102, -185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 199, 247, 102, 11, -192, 15, 132, 99, 0, 102, 139, 216, 30, 7, 102, 139, 62, 26, 2, 102, - 51, 192, 232, 89, 248, 30, 7, 102, 139, 30, 26, 2, 102, 89, 102, 90, - 38, 102, 57, 15, 15, 133, 12, 0, 38, 102, 57, 87, 8, 15, 132, 49, - 0, 235, 19, 144, 38, 102, 131, 63, 255, 15, 132, 47, 0, 38, 131, 127, - 4, 0, 15, 132, 38, 0, 38, 102, 15, 183, 71, 4, 3, 216, 139, 195, - 37, 0, 128, 116, 203, 140, 192, 5, 0, 8, 142, 192, 129, 227, 255, 127, -235, 190, 38, 102, 139, 71, 16, 195, 102, 89, 102, 90, 102, 51, 192, 195, -102, 80, 102, 81, 102, 139, 199, 102, 193, 232, 4, 6, 89, 3, 200, 81, - 7, 102, 131, 231, 15, 102, 89, 102, 88, 195, 96, 6, 190, 189, 13, 191, - 0, 32, 30, 7, 185, 13, 0, 144, 243, 165, 7, 97, 195, 1, 35, 69, -103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 240, 225, 210, -195, 0, 0, 0, 0, 32, 32, 96, 139, 54, 24, 32, 38, 138, 5, 136, - 4, 71, 70, 102, 255, 6, 20, 32, 129, 254, 96, 32, 117, 6, 232, 91, - 0, 190, 32, 32, 226, 230, 137, 54, 24, 32, 97, 195, 102, 96, 139, 54, - 24, 32, 176, 128, 136, 4, 70, 50, 192, 129, 254, 96, 32, 117, 6, 232, - 58, 0, 190, 32, 32, 129, 254, 88, 32, 117, 233, 102, 51, 192, 102, 163, - 88, 32, 102, 161, 20, 32, 102, 193, 224, 3, 102, 15, 200, 102, 163, 92, - 32, 232, 24, 0, 187, 0, 32, 102, 139, 7, 102, 15, 200, 102, 137, 7, -131, 195, 4, 129, 251, 52, 32, 117, 238, 102, 97, 195, 102, 96, 187, 32, - 32, 102, 139, 7, 102, 15, 200, 102, 137, 7, 131, 195, 4, 129, 251, 96, - 32, 117, 238, 187, 0, 32, 102, 139, 15, 102, 139, 87, 4, 102, 139, 119, - 8, 102, 139, 127, 12, 102, 139, 111, 16, 187, 32, 32, 199, 6, 26, 32, - 48, 15, 198, 6, 28, 32, 20, 144, 83, 139, 30, 26, 32, 255, 23, 102, - 3, 71, 2, 91, 102, 3, 232, 102, 3, 47, 102, 139, 193, 102, 193, 192, - 5, 102, 3, 197, 102, 139, 239, 102, 139, 254, 102, 139, 242, 102, 193, 198, - 30, 102, 139, 209, 102, 139, 200, 102, 139, 7, 102, 51, 71, 8, 102, 51, - 71, 32, 102, 51, 71, 52, 102, 209, 192, 102, 137, 71, 64, 131, 195, 4, -254, 14, 28, 32, 117, 178, 131, 6, 26, 32, 6, 129, 62, 26, 32, 72, - 15, 117, 159, 187, 0, 32, 102, 1, 15, 102, 1, 87, 4, 102, 1, 119, - 8, 102, 1, 127, 12, 102, 1, 111, 16, 102, 97, 195, 102, 139, 198, 102, - 51, 199, 102, 35, 194, 102, 51, 199, 195, 102, 139, 194, 102, 51, 198, 102, - 51, 199, 195, 102, 83, 102, 139, 194, 102, 35, 198, 102, 139, 218, 102, 35, -223, 102, 11, 195, 102, 139, 222, 102, 35, 223, 102, 11, 195, 102, 91, 195, -252, 14, 153, 121, 130, 90, 9, 15, 161, 235, 217, 110, 19, 15, 220, 188, - 27, 143, 9, 15, 214, 193, 98, 202, 6, 30, 102, 96, 102, 51, 219, 184, - 0, 187, 205, 26, 102, 35, 192, 15, 133, 187, 0, 102, 129, 251, 84, 67, - 80, 65, 15, 133, 176, 0, 129, 249, 2, 1, 15, 130, 168, 0, 102, 97, -144, 31, 7, 6, 30, 102, 96, 103, 128, 123, 8, 0, 15, 133, 12, 0, -103, 102, 141, 83, 16, 103, 102, 139, 10, 235, 37, 144, 103, 102, 141, 83, - 16, 103, 102, 139, 74, 40, 102, 129, 249, 0, 0, 8, 0, 15, 131, 12, - 0, 103, 102, 139, 66, 44, 102, 35, 192, 15, 132, 3, 0, 102, 51, 201, - 14, 31, 232, 245, 253, 102, 35, 201, 15, 132, 50, 0, 102, 186, 0, 128, - 0, 0, 102, 59, 202, 15, 134, 31, 0, 102, 43, 202, 6, 102, 81, 102, - 87, 102, 82, 102, 139, 202, 232, 183, 253, 232, 251, 253, 102, 90, 102, 95, -102, 89, 7, 102, 3, 250, 235, 218, 232, 165, 253, 232, 233, 253, 232, 11, -254, 14, 7, 102, 187, 84, 67, 80, 65, 102, 191, 0, 32, 0, 0, 102, -185, 20, 0, 0, 0, 102, 184, 7, 187, 0, 0, 102, 186, 10, 0, 0, - 0, 102, 51, 246, 205, 26, 102, 97, 144, 31, 7, 195, 160, 249, 1, 233, - 64, 241, 160, 250, 1, 233, 58, 241 -}; diff --git a/usr/src/cmd/ntfsprogs/boot.h b/usr/src/cmd/ntfsprogs/boot.h deleted file mode 100644 index 45d79927f4..0000000000 --- a/usr/src/cmd/ntfsprogs/boot.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _NTFS_BOOT_H_ -#define _NTFS_BOOT_H_ - -extern const unsigned char boot_array[4136]; - -#endif /* _NTFS_BOOT_H_ */ - diff --git a/usr/src/cmd/ntfsprogs/cluster.c b/usr/src/cmd/ntfsprogs/cluster.c deleted file mode 100644 index 59d3fe7e5b..0000000000 --- a/usr/src/cmd/ntfsprogs/cluster.c +++ /dev/null @@ -1,119 +0,0 @@ -/** - * cluster - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2003 Richard Russon - * - * This function will locate the owner of any given sector or cluster range. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif - -#include "compat.h" -#include "cluster.h" -#include "utils.h" -#include "logging.h" - -/** - * cluster_find - */ -int cluster_find(ntfs_volume *vol, LCN c_begin, LCN c_end, cluster_cb *cb, void *data) -{ - int j; - int result = -1; - struct mft_search_ctx *m_ctx = NULL; - ntfs_attr_search_ctx *a_ctx = NULL; - ATTR_RECORD *rec; - runlist *runs; - - if (!vol || !cb) - return -1; - - m_ctx = mft_get_search_ctx(vol); - m_ctx->flags_search = FEMR_IN_USE | FEMR_BASE_RECORD; - - while (mft_next_record(m_ctx) == 0) { - - if (!(m_ctx->flags_match & FEMR_BASE_RECORD)) - continue; - - ntfs_log_verbose("Inode: %llu\n", (unsigned long long) - m_ctx->inode->mft_no); - - a_ctx = ntfs_attr_get_search_ctx(m_ctx->inode, NULL); - - while ((rec = find_attribute(AT_UNUSED, a_ctx))) { - - if (!rec->non_resident) { - ntfs_log_verbose("0x%02x skipped - attr is resident\n", a_ctx->attr->type); - continue; - } - - runs = ntfs_mapping_pairs_decompress(vol, a_ctx->attr, NULL); - if (!runs) { - ntfs_log_error("Couldn't read the data runs.\n"); - goto done; - } - - ntfs_log_verbose("\t[0x%02X]\n", a_ctx->attr->type); - - ntfs_log_verbose("\t\tVCN\tLCN\tLength\n"); - for (j = 0; runs[j].length > 0; j++) { - LCN a_begin = runs[j].lcn; - LCN a_end = a_begin + runs[j].length - 1; - - if (a_begin < 0) - continue; // sparse, discontiguous, etc - - ntfs_log_verbose("\t\t%lld\t%lld-%lld (%lld)\n", - (long long)runs[j].vcn, - (long long)runs[j].lcn, - (long long)(runs[j].lcn + - runs[j].length - 1), - (long long)runs[j].length); - //dprint list - - if ((a_begin > c_end) || (a_end < c_begin)) - continue; // before or after search range - - if ((*cb) (m_ctx->inode, a_ctx->attr, runs+j, data)) - return 1; - } - } - - ntfs_attr_put_search_ctx(a_ctx); - a_ctx = NULL; - } - - result = 0; -done: - ntfs_attr_put_search_ctx(a_ctx); - mft_put_search_ctx(m_ctx); - - return result; -} - diff --git a/usr/src/cmd/ntfsprogs/cluster.h b/usr/src/cmd/ntfsprogs/cluster.h deleted file mode 100644 index 4bc18276a5..0000000000 --- a/usr/src/cmd/ntfsprogs/cluster.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * cluster - Part of the Linux-NTFS project. - * - * Copyright (c) 2003 Richard Russon - * - * This function will locate the owner of any given sector or cluster range. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _CLUSTER_H_ -#define _CLUSTER_H_ - -#include "types.h" -#include "volume.h" - -typedef struct { - int x; -} ntfs_cluster; - -typedef int (cluster_cb)(ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run, void *data); - -int cluster_find(ntfs_volume *vol, LCN c_begin, LCN c_end, cluster_cb *cb, void *data); - -#endif /* _CLUSTER_H_ */ - diff --git a/usr/src/cmd/ntfsprogs/mkntfs.c b/usr/src/cmd/ntfsprogs/mkntfs.c deleted file mode 100644 index e23f6a7848..0000000000 --- a/usr/src/cmd/ntfsprogs/mkntfs.c +++ /dev/null @@ -1,4748 +0,0 @@ -/** - * mkntfs - Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2007 Anton Altaparmakov - * Copyright (c) 2001-2005 Richard Russon - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2005 Erik Sornes - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility will create an NTFS 1.2 or 3.1 volume on a user - * specified (block) device. - * - * Some things (option handling and determination of mount status) have been - * adapted from e2fsprogs-1.19 and lib/ext2fs/ismounted.c and misc/mke2fs.c in - * particular. - * - * 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 (in the main directory of the Linux-NTFS source - * in the file COPYING); if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_LIBGEN_H -#include -#endif -#ifdef ENABLE_UUID -#include -#endif - - -#ifdef HAVE_GETOPT_H -#include -#else - extern char *optarg; - extern int optind; -#endif - -#ifdef HAVE_LINUX_MAJOR_H -# include -# ifndef MAJOR -# define MAJOR(dev) ((dev) >> 8) -# define MINOR(dev) ((dev) & 0xff) -# endif -# ifndef IDE_DISK_MAJOR -# ifndef IDE0_MAJOR -# define IDE0_MAJOR 3 -# define IDE1_MAJOR 22 -# define IDE2_MAJOR 33 -# define IDE3_MAJOR 34 -# define IDE4_MAJOR 56 -# define IDE5_MAJOR 57 -# define IDE6_MAJOR 88 -# define IDE7_MAJOR 89 -# define IDE8_MAJOR 90 -# define IDE9_MAJOR 91 -# endif -# define IDE_DISK_MAJOR(M) \ - ((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \ - (M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \ - (M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \ - (M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \ - (M) == IDE8_MAJOR || (M) == IDE9_MAJOR) -# endif -# ifndef SCSI_DISK_MAJOR -# ifndef SCSI_DISK0_MAJOR -# define SCSI_DISK0_MAJOR 8 -# define SCSI_DISK1_MAJOR 65 -# define SCSI_DISK7_MAJOR 71 -# endif -# define SCSI_DISK_MAJOR(M) \ - ((M) == SCSI_DISK0_MAJOR || \ - ((M) >= SCSI_DISK1_MAJOR && \ - (M) <= SCSI_DISK7_MAJOR)) -# endif -#endif - -#include "compat.h" -#include "security.h" -#include "types.h" -#include "attrib.h" -#include "bitmap.h" -#include "bootsect.h" -#include "device.h" -#include "dir.h" -#include "mft.h" -#include "mst.h" -#include "runlist.h" -#include "utils.h" -#include "ntfstime.h" -#include "sd.h" -#include "boot.h" -#include "attrdef.h" -#include "version.h" -#include "logging.h" -#include "support.h" -#include "unistr.h" - -#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS -#error "No default device io operations! Cannot build mkntfs. \ -You need to run ./configure without the --disable-default-device-io-ops \ -switch if you want to be able to build the NTFS utilities." -#endif - -/* Page size on ia32. Can change to 8192 on Alpha. */ -#define NTFS_PAGE_SIZE 4096 - -static char EXEC_NAME[] = "mkntfs"; - -/** - * global variables - */ -static u8 *g_buf = NULL; -static int g_mft_bitmap_byte_size = 0; -static u8 *g_mft_bitmap = NULL; -static int g_lcn_bitmap_byte_size = 0; -static u8 *g_lcn_bitmap = NULL; -static runlist *g_rl_mft = NULL; -static runlist *g_rl_mft_bmp = NULL; -static runlist *g_rl_mftmirr = NULL; -static runlist *g_rl_logfile = NULL; -static runlist *g_rl_boot = NULL; -static runlist *g_rl_bad = NULL; -static INDEX_ALLOCATION *g_index_block = NULL; -static ntfs_volume *g_vol = NULL; -static int g_mft_size = 0; -static long long g_mft_lcn = 0; /* lcn of $MFT, $DATA attribute */ -static long long g_mftmirr_lcn = 0; /* lcn of $MFTMirr, $DATA */ -static long long g_logfile_lcn = 0; /* lcn of $LogFile, $DATA */ -static int g_logfile_size = 0; /* in bytes, determined from volume_size */ -static long long g_mft_zone_end = 0; /* Determined from volume_size and mft_zone_multiplier, in clusters */ -static long long g_num_bad_blocks = 0; /* Number of bad clusters */ -static long long *g_bad_blocks = NULL; /* Array of bad clusters */ - -/** - * struct mkntfs_options - */ -static struct mkntfs_options { - char *dev_name; /* Name of the device, or file, to use */ - BOOL enable_compression; /* -C, enables compression of all files on the volume by default. */ - BOOL quick_format; /* -f or -Q, fast format, don't zero the volume first. */ - BOOL force; /* -F, force fs creation. */ - long heads; /* -H, number of heads on device */ - BOOL disable_indexing; /* -I, disables indexing of file contents on the volume by default. */ - BOOL no_action; /* -n, do not write to device, only display what would be done. */ - long long part_start_sect; /* -p, start sector of partition on parent device */ - long sector_size; /* -s, in bytes, power of 2, default is 512 bytes. */ - long sectors_per_track; /* -S, number of sectors per track on device */ - BOOL use_epoch_time; /* -T, fake the time to be 00:00:00 UTC, Jan 1, 1970. */ - long mft_zone_multiplier; /* -z, value from 1 to 4. Default is 1. */ - long long num_sectors; /* size of device in sectors */ - long cluster_size; /* -c, format with this cluster-size */ - char *label; /* -L, volume label */ -} opts; - - -/** - * mkntfs_license - */ -static void mkntfs_license(void) -{ - ntfs_log_info("%s", ntfs_gpl); -} - -/** - * mkntfs_usage - */ -static void mkntfs_usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device [number-of-sectors]\n" -"\n" -"Basic options:\n" -" -f, --fast Perform a quick format\n" -" -Q, --quick Perform a quick format\n" -" -L, --label STRING Set the volume label\n" -" -C, --enable-compression Enable compression on the volume\n" -" -I, --no-indexing Disable indexing on the volume\n" -" -n, --no-action Do not write to disk\n" -"\n" -"Advanced options:\n" -" -c, --cluster-size BYTES Specify the cluster size for the volume\n" -" -s, --sector-size BYTES Specify the sector size for the device\n" -" -p, --partition-start SECTOR Specify the partition start sector\n" -" -H, --heads NUM Specify the number of heads\n" -" -S, --sectors-per-track NUM Specify the number of sectors per track\n" -" -z, --mft-zone-multiplier NUM Set the MFT zone multiplier\n" -" -T, --zero-time Fake the time to be 00:00 UTC, Jan 1, 1970\n" -" -F, --force Force execution despite errors\n" -"\n" -"Output options:\n" -" -q, --quiet Quiet execution\n" -" -v, --verbose Verbose execution\n" -" --debug Very verbose execution\n" -"\n" -"Help options:\n" -" -V, --version Display version\n" -" -l, --license Display licensing information\n" -" -h, --help Display this help\n" -"\n", basename(EXEC_NAME)); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * mkntfs_version - */ -static void mkntfs_version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s)\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - ntfs_log_info("Create an NTFS volume on a user specified (block) " - "device.\n\n"); - ntfs_log_info("Copyright (c) 2000-2007 Anton Altaparmakov\n"); - ntfs_log_info("Copyright (c) 2001-2005 Richard Russon\n"); - ntfs_log_info("Copyright (c) 2002-2006 Szabolcs Szakacsits\n"); - ntfs_log_info("Copyright (c) 2005 Erik Sornes\n"); - ntfs_log_info("Copyright (c) 2007 Yura Pakhuchiy\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - - -/** - * mkntfs_parse_long - */ -static BOOL mkntfs_parse_long(const char *string, const char *name, long *num) -{ - char *end = NULL; - long tmp; - - if (!string || !name || !num) - return FALSE; - - if (*num >= 0) { - ntfs_log_error("You may only specify the %s once.\n", name); - return FALSE; - } - - tmp = strtol(string, &end, 0); - if (end && *end) { - ntfs_log_error("Cannot understand the %s '%s'.\n", name, string); - return FALSE; - } else { - *num = tmp; - return TRUE; - } -} - -/** - * mkntfs_parse_llong - */ -static BOOL mkntfs_parse_llong(const char *string, const char *name, - long long *num) -{ - char *end = NULL; - long long tmp; - - if (!string || !name || !num) - return FALSE; - - if (*num >= 0) { - ntfs_log_error("You may only specify the %s once.\n", name); - return FALSE; - } - - tmp = strtoll(string, &end, 0); - if (end && *end) { - ntfs_log_error("Cannot understand the %s '%s'.\n", name, - string); - return FALSE; - } else { - *num = tmp; - return TRUE; - } -} - -/** - * mkntfs_init_options - */ -static void mkntfs_init_options(struct mkntfs_options *opts2) -{ - if (!opts2) - return; - - memset(opts2, 0, sizeof(*opts2)); - - /* Mark all the numeric options as "unset". */ - opts2->cluster_size = -1; - opts2->heads = -1; - opts2->mft_zone_multiplier = -1; - opts2->num_sectors = -1; - opts2->part_start_sect = -1; - opts2->sector_size = -1; - opts2->sectors_per_track = -1; -} - -/** - * mkntfs_parse_options - */ -static BOOL mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *opts2) -{ - static const char *sopt = "-c:CfFhH:IlL:np:qQs:S:TvVz:"; - static const struct option lopt[] = { - { "cluster-size", required_argument, NULL, 'c' }, - { "debug", no_argument, NULL, 'Z' }, - { "enable-compression", no_argument, NULL, 'C' }, - { "fast", no_argument, NULL, 'f' }, - { "force", no_argument, NULL, 'F' }, - { "heads", required_argument, NULL, 'H' }, - { "help", no_argument, NULL, 'h' }, - { "label", required_argument, NULL, 'L' }, - { "license", no_argument, NULL, 'l' }, - { "mft-zone-multiplier",required_argument, NULL, 'z' }, - { "no-action", no_argument, NULL, 'n' }, - { "no-indexing", no_argument, NULL, 'I' }, - { "partition-start", required_argument, NULL, 'p' }, - { "quick", no_argument, NULL, 'Q' }, - { "quiet", no_argument, NULL, 'q' }, - { "sector-size", required_argument, NULL, 's' }, - { "sectors-per-track", required_argument, NULL, 'S' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { "zero-time", no_argument, NULL, 'T' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - int lic = 0; - int err = 0; - int ver = 0; - - if (!argv || !opts2) { - ntfs_log_error("Internal error: invalid parameters to " - "mkntfs_options.\n"); - return FALSE; - } - - opterr = 0; /* We'll handle the errors, thank you. */ - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A device, or a number of sectors */ - if (!opts2->dev_name) - opts2->dev_name = argv[optind - 1]; - else if (!mkntfs_parse_llong(optarg, - "number of sectors", - &opts2->num_sectors)) - err++; - break; - case 'C': - opts2->enable_compression = TRUE; - break; - case 'c': - if (!mkntfs_parse_long(optarg, "cluster size", - &opts2->cluster_size)) - err++; - break; - case 'F': - opts2->force = TRUE; - break; - case 'f': /* fast */ - case 'Q': /* quick */ - opts2->quick_format = TRUE; - break; - case 'H': - if (!mkntfs_parse_long(optarg, "heads", &opts2->heads)) - err++; - break; - case 'h': - err++; /* display help */ - break; - case 'I': - opts2->disable_indexing = TRUE; - break; - case 'L': - if (!opts2->label) { - opts2->label = argv[optind-1]; - } else { - ntfs_log_error("You may only specify the label " - "once.\n"); - err++; - } - break; - case 'l': - lic++; /* display the license */ - break; - case 'n': - opts2->no_action = TRUE; - break; - case 'p': - if (!mkntfs_parse_llong(optarg, "partition start", - &opts2->part_start_sect)) - err++; - break; - case 'q': - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET | - NTFS_LOG_LEVEL_VERBOSE | - NTFS_LOG_LEVEL_PROGRESS); - break; - case 's': - if (!mkntfs_parse_long(optarg, "sector size", - &opts2->sector_size)) - err++; - break; - case 'S': - if (!mkntfs_parse_long(optarg, "sectors per track", - &opts2->sectors_per_track)) - err++; - break; - case 'T': - opts2->use_epoch_time = TRUE; - break; - case 'v': - ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET | - NTFS_LOG_LEVEL_VERBOSE | - NTFS_LOG_LEVEL_PROGRESS); - break; - case 'V': - ver++; /* display version info */ - break; - case 'Z': /* debug - turn on everything */ - ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | - NTFS_LOG_LEVEL_TRACE | - NTFS_LOG_LEVEL_VERBOSE | - NTFS_LOG_LEVEL_QUIET); - break; - case 'z': - if (!mkntfs_parse_long(optarg, "mft zone multiplier", - &opts2->mft_zone_multiplier)) - err++; - break; - default: - if (ntfs_log_parse_option (argv[optind-1])) - break; - if (((optopt == 'c') || (optopt == 'H') || - (optopt == 'L') || (optopt == 'p') || - (optopt == 's') || (optopt == 'S') || - (optopt == 'N') || (optopt == 'z')) && - (!optarg)) { - ntfs_log_error("Option '%s' requires an " - "argument.\n", argv[optind-1]); - } else if (optopt != '?') { - ntfs_log_error("Unknown option '%s'.\n", - argv[optind - 1]); - } - err++; - break; - } - } - - if (!err && !ver && !lic) { - if (opts2->dev_name == NULL) { - if (argc > 1) - ntfs_log_error("You must specify a device.\n"); - err++; - } - } - - if (ver) - mkntfs_version(); - if (lic) - mkntfs_license(); - if (err) - mkntfs_usage(); - - return (!err && !ver && !lic); -} - - -/** - * mkntfs_time - */ -static time_t mkntfs_time(void) -{ - if (!opts.use_epoch_time) - return time(NULL); - return 0; -} - -/** - * append_to_bad_blocks - */ -static BOOL append_to_bad_blocks(unsigned long long block) -{ - long long *new_buf; - - if (!(g_num_bad_blocks & 15)) { - new_buf = realloc(g_bad_blocks, (g_num_bad_blocks + 16) * - sizeof(long long)); - if (!new_buf) { - ntfs_log_perror("Reallocating memory for bad blocks " - "list failed"); - return FALSE; - } - g_bad_blocks = new_buf; - } - g_bad_blocks[g_num_bad_blocks++] = block; - return TRUE; -} - -/** - * mkntfs_write - */ -static long long mkntfs_write(struct ntfs_device *dev, - const void *b, long long count) -{ - long long bytes_written, total; - int retry; - - if (opts.no_action) - return count; - total = 0LL; - retry = 0; - do { - bytes_written = dev->d_ops->write(dev, b, count); - if (bytes_written == -1LL) { - retry = errno; - ntfs_log_perror("Error writing to %s", dev->d_name); - errno = retry; - return bytes_written; - } else if (!bytes_written) { - retry++; - } else { - count -= bytes_written; - total += bytes_written; - } - } while (count && retry < 3); - if (count) - ntfs_log_error("Failed to complete writing to %s after three retries." - "\n", dev->d_name); - return total; -} - -/** - * ntfs_rlwrite - Write data to disk on clusters found in a runlist. - * - * Write to disk the clusters contained in the runlist @rl taking the data - * from @val. Take @val_len bytes from @val and pad the rest with zeroes. - * - * If the @rl specifies a completely sparse file, @val is allowed to be NULL. - * - * @inited_size if not NULL points to an output variable which will contain - * the actual number of bytes written to disk. I.e. this will not include - * sparse bytes for example. - * - * Return the number of bytes written (minus padding) or -1 on error. Errno - * will be set to the error code. - */ -static s64 ntfs_rlwrite(struct ntfs_device *dev, const runlist *rl, - const u8 *val, const s64 val_len, s64 *inited_size) -{ - s64 bytes_written, total, length, delta; - int retry, i; - - if (inited_size) - *inited_size = 0LL; - if (opts.no_action) - return val_len; - total = 0LL; - delta = 0LL; - for (i = 0; rl[i].length; i++) { - length = rl[i].length * g_vol->cluster_size; - /* Don't write sparse runs. */ - if (rl[i].lcn == -1) { - total += length; - if (!val) - continue; - /* TODO: Check that *val is really zero at pos and len. */ - continue; - } - /* - * Break up the write into the real data write and then a write - * of zeroes between the end of the real data and the end of - * the (last) run. - */ - if (total + length > val_len) { - delta = length; - length = val_len - total; - delta -= length; - } - if (dev->d_ops->seek(dev, rl[i].lcn * g_vol->cluster_size, - SEEK_SET) == (off_t)-1) - return -1LL; - retry = 0; - do { - bytes_written = dev->d_ops->write(dev, val + total, - length); - if (bytes_written == -1LL) { - retry = errno; - ntfs_log_perror("Error writing to %s", - dev->d_name); - errno = retry; - return bytes_written; - } - if (bytes_written) { - length -= bytes_written; - total += bytes_written; - if (inited_size) - *inited_size += bytes_written; - } else { - retry++; - } - } while (length && retry < 3); - if (length) { - ntfs_log_error("Failed to complete writing to %s after three " - "retries.\n", dev->d_name); - return total; - } - } - if (delta) { - int eo; - char *b = ntfs_calloc(delta); - if (!b) - return -1; - bytes_written = mkntfs_write(dev, b, delta); - eo = errno; - free(b); - errno = eo; - if (bytes_written == -1LL) - return bytes_written; - } - return total; -} - -/** - * make_room_for_attribute - make room for an attribute inside an mft record - * @m: mft record - * @pos: position at which to make space - * @size: byte size to make available at this position - * - * @pos points to the attribute in front of which we want to make space. - * - * Return 0 on success or -errno on error. Possible error codes are: - * - * -ENOSPC There is not enough space available to complete - * operation. The caller has to make space before calling - * this. - * -EINVAL Can only occur if mkntfs was compiled with -DDEBUG. Means - * the input parameters were faulty. - */ -static int make_room_for_attribute(MFT_RECORD *m, char *pos, const u32 size) -{ - u32 biu; - - if (!size) - return 0; -#ifdef DEBUG - /* - * Rigorous consistency checks. Always return -EINVAL even if more - * appropriate codes exist for simplicity of parsing the return value. - */ - if (size != ((size + 7) & ~7)) { - ntfs_log_error("make_room_for_attribute() received non 8-byte aligned " - "size.\n"); - return -EINVAL; - } - if (!m || !pos) - return -EINVAL; - if (pos < (char*)m || pos + size < (char*)m || - pos > (char*)m + le32_to_cpu(m->bytes_allocated) || - pos + size > (char*)m + le32_to_cpu(m->bytes_allocated)) - return -EINVAL; - /* The -8 is for the attribute terminator. */ - if (pos - (char*)m > (int)le32_to_cpu(m->bytes_in_use) - 8) - return -EINVAL; -#endif - biu = le32_to_cpu(m->bytes_in_use); - /* Do we have enough space? */ - if (biu + size > le32_to_cpu(m->bytes_allocated)) - return -ENOSPC; - /* Move everything after pos to pos + size. */ - memmove(pos + size, pos, biu - (pos - (char*)m)); - /* Update mft record. */ - m->bytes_in_use = cpu_to_le32(biu + size); - return 0; -} - -/** - * deallocate_scattered_clusters - */ -static void deallocate_scattered_clusters(const runlist *rl) -{ - LCN j; - int i; - - if (!rl) - return; - /* Iterate over all runs in the runlist @rl. */ - for (i = 0; rl[i].length; i++) { - /* Skip sparse runs. */ - if (rl[i].lcn == -1LL) - continue; - /* Deallocate the current run. */ - for (j = rl[i].lcn; j < rl[i].lcn + rl[i].length; j++) - ntfs_bit_set(g_lcn_bitmap, j, 0); - } -} - -/** - * allocate_scattered_clusters - * @clusters: Amount of clusters to allocate. - * - * Allocate @clusters and create a runlist of the allocated clusters. - * - * Return the allocated runlist. Caller has to free the runlist when finished - * with it. - * - * On error return NULL and errno is set to the error code. - * - * TODO: We should be returning the size as well, but for mkntfs this is not - * necessary. - */ -static runlist * allocate_scattered_clusters(s64 clusters) -{ - runlist *rl = NULL, *rlt; - VCN vcn = 0LL; - LCN lcn, end, prev_lcn = 0LL; - int rlpos = 0; - int rlsize = 0; - s64 prev_run_len = 0LL; - char bit; - - end = g_vol->nr_clusters; - /* Loop until all clusters are allocated. */ - while (clusters) { - /* Loop in current zone until we run out of free clusters. */ - for (lcn = g_mft_zone_end; lcn < end; lcn++) { - bit = ntfs_bit_get_and_set(g_lcn_bitmap, lcn, 1); - if (bit) - continue; - /* - * Reallocate memory if necessary. Make sure we have - * enough for the terminator entry as well. - */ - if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) { - rlsize += 4096; /* PAGE_SIZE */ - rlt = realloc(rl, rlsize); - if (!rlt) - goto err_end; - rl = rlt; - } - /* Coalesce with previous run if adjacent LCNs. */ - if (prev_lcn == lcn - prev_run_len) { - rl[rlpos - 1].length = ++prev_run_len; - vcn++; - } else { - rl[rlpos].vcn = vcn++; - rl[rlpos].lcn = lcn; - prev_lcn = lcn; - rl[rlpos].length = 1LL; - prev_run_len = 1LL; - rlpos++; - } - /* Done? */ - if (!--clusters) { - /* Add terminator element and return. */ - rl[rlpos].vcn = vcn; - rl[rlpos].lcn = 0LL; - rl[rlpos].length = 0LL; - return rl; - } - - } - /* Switch to next zone, decreasing mft zone by factor 2. */ - end = g_mft_zone_end; - g_mft_zone_end >>= 1; - /* Have we run out of space on the volume? */ - if (g_mft_zone_end <= 0) - goto err_end; - } - return rl; -err_end: - if (rl) { - /* Add terminator element. */ - rl[rlpos].vcn = vcn; - rl[rlpos].lcn = -1LL; - rl[rlpos].length = 0LL; - /* Deallocate all allocated clusters. */ - deallocate_scattered_clusters(rl); - /* Free the runlist. */ - free(rl); - } - return NULL; -} - -/** - * ntfs_attr_find - find (next) attribute in mft record - * @type: attribute type to find - * @name: attribute name to find (optional, i.e. NULL means don't care) - * @name_len: attribute name length (only needed if @name present) - * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) - * @val: attribute value to find (optional, resident attributes only) - * @val_len: attribute value length - * @ctx: search context with mft record and attribute to search from - * - * You shouldn't need to call this function directly. Use lookup_attr() instead. - * - * ntfs_attr_find() takes a search context @ctx as parameter and searches the - * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an - * attribute of @type, optionally @name and @val. If found, ntfs_attr_find() - * returns 0 and @ctx->attr will point to the found attribute. - * - * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and - * @ctx->attr will point to the attribute before which the attribute being - * searched for would need to be inserted if such an action were to be desired. - * - * On actual error, ntfs_attr_find() returns -1 with errno set to the error - * code but not to ENOENT. In this case @ctx->attr is undefined and in - * particular do not rely on it not changing. - * - * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it - * is FALSE, the search begins after @ctx->attr. - * - * If @type is AT_UNUSED, return the first found attribute, i.e. one can - * enumerate all attributes by setting @type to AT_UNUSED and then calling - * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to - * indicate that there are no more entries. During the enumeration, each - * successful call of ntfs_attr_find() will return the next attribute in the - * mft record @ctx->mrec. - * - * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT. - * AT_END is not a valid attribute, its length is zero for example, thus it is - * safer to return error instead of success in this case. This also allows us - * to interoperate cleanly with ntfs_external_attr_find(). - * - * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present - * but not AT_UNNAMED search for a named attribute matching @name. Otherwise, - * match both named and unnamed attributes. - * - * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and - * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record - * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at - * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case - * sensitive. When @name is present, @name_len is the @name length in Unicode - * characters. - * - * If @name is not present (NULL), we assume that the unnamed attribute is - * being searched for. - * - * Finally, the resident attribute value @val is looked for, if present. - * If @val is not present (NULL), @val_len is ignored. - * - * ntfs_attr_find() only searches the specified mft record and it ignores the - * presence of an attribute list attribute (unless it is the one being searched - * for, obviously). If you need to take attribute lists into consideration, use - * ntfs_attr_lookup() instead (see below). This also means that you cannot use - * ntfs_attr_find() to search for extent records of non-resident attributes, as - * extents with lowest_vcn != 0 are usually described by the attribute list - * attribute only. - Note that it is possible that the first extent is only in - * the attribute list while the last extent is in the base mft record, so don't - * rely on being able to find the first extent in the base mft record. - * - * Warning: Never use @val when looking for attribute types which can be - * non-resident as this most likely will result in a crash! - */ -static int mkntfs_attr_find(const ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx) -{ - ATTR_RECORD *a; - ntfschar *upcase = g_vol->upcase; - u32 upcase_len = g_vol->upcase_len; - - /* - * Iterate over attributes in mft record starting at @ctx->attr, or the - * attribute following that, if @ctx->is_first is TRUE. - */ - if (ctx->is_first) { - a = ctx->attr; - ctx->is_first = FALSE; - } else { - a = (ATTR_RECORD*)((char*)ctx->attr + - le32_to_cpu(ctx->attr->length)); - } - for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) { - if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec + - le32_to_cpu(ctx->mrec->bytes_allocated)) - break; - ctx->attr = a; - if (((type != AT_UNUSED) && (le32_to_cpu(a->type) > - le32_to_cpu(type))) || - (a->type == AT_END)) { - errno = ENOENT; - return -1; - } - if (!a->length) - break; - /* If this is an enumeration return this attribute. */ - if (type == AT_UNUSED) - return 0; - if (a->type != type) - continue; - /* - * If @name is AT_UNNAMED we want an unnamed attribute. - * If @name is present, compare the two names. - * Otherwise, match any attribute. - */ - if (name == AT_UNNAMED) { - /* The search failed if the found attribute is named. */ - if (a->name_length) { - errno = ENOENT; - return -1; - } - } else if (name && !ntfs_names_are_equal(name, name_len, - (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)), - a->name_length, ic, upcase, upcase_len)) { - int rc; - - rc = ntfs_names_collate(name, name_len, - (ntfschar*)((char*)a + - le16_to_cpu(a->name_offset)), - a->name_length, 1, IGNORE_CASE, - upcase, upcase_len); - /* - * If @name collates before a->name, there is no - * matching attribute. - */ - if (rc == -1) { - errno = ENOENT; - return -1; - } - /* If the strings are not equal, continue search. */ - if (rc) - continue; - rc = ntfs_names_collate(name, name_len, - (ntfschar*)((char*)a + - le16_to_cpu(a->name_offset)), - a->name_length, 1, CASE_SENSITIVE, - upcase, upcase_len); - if (rc == -1) { - errno = ENOENT; - return -1; - } - if (rc) - continue; - } - /* - * The names match or @name not present and attribute is - * unnamed. If no @val specified, we have found the attribute - * and are done. - */ - if (!val) { - return 0; - /* @val is present; compare values. */ - } else { - int rc; - - rc = memcmp(val, (char*)a +le16_to_cpu(a->u.res.value_offset), - min(val_len, - le32_to_cpu(a->u.res.value_length))); - /* - * If @val collates before the current attribute's - * value, there is no matching attribute. - */ - if (!rc) { - u32 avl; - avl = le32_to_cpu(a->u.res.value_length); - if (val_len == avl) - return 0; - if (val_len < avl) { - errno = ENOENT; - return -1; - } - } else if (rc < 0) { - errno = ENOENT; - return -1; - } - } - } - ntfs_log_trace("File is corrupt. Run chkdsk.\n"); - errno = EIO; - return -1; -} - -/** - * ntfs_attr_lookup - find an attribute in an ntfs inode - * @type: attribute type to find - * @name: attribute name to find (optional, i.e. NULL means don't care) - * @name_len: attribute name length (only needed if @name present) - * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) - * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only) - * @val: attribute value to find (optional, resident attributes only) - * @val_len: attribute value length - * @ctx: search context with mft record and attribute to search from - * - * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must - * be the base mft record and @ctx must have been obtained from a call to - * ntfs_attr_get_search_ctx(). - * - * This function transparently handles attribute lists and @ctx is used to - * continue searches where they were left off at. - * - * If @type is AT_UNUSED, return the first found attribute, i.e. one can - * enumerate all attributes by setting @type to AT_UNUSED and then calling - * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT - * to indicate that there are no more entries. During the enumeration, each - * successful call of ntfs_attr_lookup() will return the next attribute, with - * the current attribute being described by the search context @ctx. - * - * If @type is AT_END, seek to the end of the base mft record ignoring the - * attribute list completely and return -1 with errno set to ENOENT. AT_END is - * not a valid attribute, its length is zero for example, thus it is safer to - * return error instead of success in this case. It should never be needed to - * do this, but we implement the functionality because it allows for simpler - * code inside ntfs_external_attr_find(). - * - * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present - * but not AT_UNNAMED search for a named attribute matching @name. Otherwise, - * match both named and unnamed attributes. - * - * After finishing with the attribute/mft record you need to call - * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any - * mapped extent inodes, etc). - * - * Return 0 if the search was successful and -1 if not, with errno set to the - * error code. - * - * On success, @ctx->attr is the found attribute, it is in mft record - * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this - * attribute with @ctx->base_* being the base mft record to which @ctx->attr - * belongs. If no attribute list attribute is present @ctx->al_entry and - * @ctx->base_* are NULL. - * - * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the - * attribute which collates just after the attribute being searched for in the - * base ntfs inode, i.e. if one wants to add the attribute to the mft record - * this is the correct place to insert it into, and if there is not enough - * space, the attribute should be placed in an extent mft record. - * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list - * at which the new attribute's attribute list entry should be inserted. The - * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL. - * The only exception to this is when @type is AT_END, in which case - * @ctx->al_entry is set to NULL also (see above). - * - * The following error codes are defined: - * ENOENT Attribute not found, not an error as such. - * EINVAL Invalid arguments. - * EIO I/O error or corrupt data structures found. - * ENOMEM Not enough memory to allocate necessary buffers. - */ -static int mkntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const VCN lowest_vcn __attribute__((unused)), const u8 *val, - const u32 val_len, ntfs_attr_search_ctx *ctx) -{ - ntfs_inode *base_ni; - - if (!ctx || !ctx->mrec || !ctx->attr) { - errno = EINVAL; - return -1; - } - if (ctx->base_ntfs_ino) - base_ni = ctx->base_ntfs_ino; - else - base_ni = ctx->ntfs_ino; - if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST) - return mkntfs_attr_find(type, name, name_len, ic, val, val_len, - ctx); - errno = EOPNOTSUPP; - return -1; -} - -/** - * insert_positioned_attr_in_mft_record - * - * Create a non-resident attribute with a predefined on disk location - * specified by the runlist @rl. The clusters specified by @rl are assumed to - * be allocated already. - * - * Return 0 on success and -errno on error. - */ -static int insert_positioned_attr_in_mft_record(MFT_RECORD *m, - const ATTR_TYPES type, const char *name, u32 name_len, - const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags, - const runlist *rl, const u8 *val, const s64 val_len) -{ - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - u16 hdr_size; - int asize, mpa_size, err, i; - s64 bw = 0, inited_size; - VCN highest_vcn; - ntfschar *uname = NULL; - int uname_len = 0; - /* - if (base record) - attr_lookup(); - else - */ - - uname = ntfs_str2ucs(name, &uname_len); - if (!uname) - return -errno; - - /* Check if the attribute is already there. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to allocate attribute search context.\n"); - err = -ENOMEM; - goto err_out; - } - if (ic == IGNORE_CASE) { - ntfs_log_error("FIXME: Hit unimplemented code path #1.\n"); - err = -EOPNOTSUPP; - goto err_out; - } - if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) { - err = -EEXIST; - goto err_out; - } - if (errno != ENOENT) { - ntfs_log_error("Corrupt inode.\n"); - err = -errno; - goto err_out; - } - a = ctx->attr; - if (flags & ATTR_COMPRESSION_MASK) { - ntfs_log_error("Compressed attributes not supported yet.\n"); - /* FIXME: Compress attribute into a temporary buffer, set */ - /* val accordingly and save the compressed size. */ - err = -EOPNOTSUPP; - goto err_out; - } - if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) { - ntfs_log_error("Encrypted/sparse attributes not supported.\n"); - err = -EOPNOTSUPP; - goto err_out; - } - if (flags & ATTR_COMPRESSION_MASK) { - hdr_size = 72; - /* FIXME: This compression stuff is all wrong. Never mind for */ - /* now. (AIA) */ - if (val_len) - mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */ - else - mpa_size = 0; - } else { - hdr_size = 64; - if (val_len) { - mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0); - if (mpa_size < 0) { - err = -errno; - ntfs_log_error("Failed to get size for mapping " - "pairs.\n"); - goto err_out; - } - } else { - mpa_size = 0; - } - } - /* Mapping pairs array and next attribute must be 8-byte aligned. */ - asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7; - /* Get the highest vcn. */ - for (i = 0, highest_vcn = 0LL; rl[i].length; i++) - highest_vcn += rl[i].length; - /* Does the value fit inside the allocated size? */ - if (highest_vcn * g_vol->cluster_size < val_len) { - ntfs_log_error("BUG: Allocated size is smaller than data size!\n"); - err = -EINVAL; - goto err_out; - } - err = make_room_for_attribute(m, (char*)a, asize); - if (err == -ENOSPC) { - /* - * FIXME: Make space! (AIA) - * can we make it non-resident? if yes, do that. - * does it fit now? yes -> do it. - * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident? - * yes -> make non-resident - * does it fit now? yes -> do it. - * make all attributes non-resident - * does it fit now? yes -> do it. - * m is a base record? yes -> allocate extension record - * does the new attribute fit in there? yes -> do it. - * split up runlist into extents and place each in an extension - * record. - * FIXME: the check for needing extension records should be - * earlier on as it is very quick: asize > m->bytes_allocated? - */ - err = -EOPNOTSUPP; - goto err_out; -#ifdef DEBUG - } else if (err == -EINVAL) { - ntfs_log_error("BUG(): in insert_positioned_attribute_in_mft_" - "record(): make_room_for_attribute() returned " - "error: EINVAL!\n"); - goto err_out; -#endif - } - a->type = type; - a->length = cpu_to_le32(asize); - a->non_resident = 1; - a->name_length = name_len; - a->name_offset = cpu_to_le16(hdr_size); - a->flags = flags; - a->instance = m->next_attr_instance; - m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance) - + 1) & 0xffff); - a->u.nonres.lowest_vcn = 0; - a->u.nonres.highest_vcn = cpu_to_sle64(highest_vcn - 1LL); - a->u.nonres.mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7)); - memset(a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1)); - /* FIXME: Allocated size depends on compression. */ - a->u.nonres.allocated_size = cpu_to_sle64(highest_vcn * g_vol->cluster_size); - a->u.nonres.data_size = cpu_to_sle64(val_len); - if (name_len) - memcpy((char*)a + hdr_size, uname, name_len << 1); - if (flags & ATTR_COMPRESSION_MASK) { - if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) { - ntfs_log_error("Unknown compression format. Reverting " - "to standard compression.\n"); - a->flags &= ~ATTR_COMPRESSION_MASK; - a->flags |= ATTR_IS_COMPRESSED; - } - a->u.nonres.compression_unit = 4; - inited_size = val_len; - /* FIXME: Set the compressed size. */ - a->u.nonres.compressed_size = 0; - /* FIXME: Write out the compressed data. */ - /* FIXME: err = build_mapping_pairs_compressed(); */ - err = -EOPNOTSUPP; - } else { - a->u.nonres.compression_unit = 0; - bw = ntfs_rlwrite(g_vol->u.dev, rl, val, val_len, &inited_size); - if (bw != val_len) { - ntfs_log_error("Error writing non-resident attribute " - "value.\n"); - return -errno; - } - err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size + - ((name_len + 7) & ~7), mpa_size, rl, 0, NULL); - } - a->u.nonres.initialized_size = cpu_to_sle64(inited_size); - if (err < 0 || bw != val_len) { - /* FIXME: Handle error. */ - /* deallocate clusters */ - /* remove attribute */ - if (err >= 0) - err = -EIO; - ntfs_log_error("insert_positioned_attr_in_mft_record failed " - "with error %i.\n", err < 0 ? err : (int)bw); - } -err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - ntfs_ucsfree(uname); - return err; -} - -/** - * insert_non_resident_attr_in_mft_record - * - * Return 0 on success and -errno on error. - */ -static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m, - const ATTR_TYPES type, const char *name, u32 name_len, - const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags, - const u8 *val, const s64 val_len) -{ - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - u16 hdr_size; - int asize, mpa_size, err, i; - runlist *rl = NULL; - s64 bw = 0; - ntfschar *uname = NULL; - int uname_len = 0; - /* - if (base record) - attr_lookup(); - else - */ - - uname = ntfs_str2ucs(name, &uname_len); - if (!uname) - return -errno; - - /* Check if the attribute is already there. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to allocate attribute search context.\n"); - err = -ENOMEM; - goto err_out; - } - if (ic == IGNORE_CASE) { - ntfs_log_error("FIXME: Hit unimplemented code path #2.\n"); - err = -EOPNOTSUPP; - goto err_out; - } - if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) { - err = -EEXIST; - goto err_out; - } - if (errno != ENOENT) { - ntfs_log_error("Corrupt inode.\n"); - err = -errno; - goto err_out; - } - a = ctx->attr; - if (flags & ATTR_COMPRESSION_MASK) { - ntfs_log_error("Compressed attributes not supported yet.\n"); - /* FIXME: Compress attribute into a temporary buffer, set */ - /* val accordingly and save the compressed size. */ - err = -EOPNOTSUPP; - goto err_out; - } - if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) { - ntfs_log_error("Encrypted/sparse attributes not supported.\n"); - err = -EOPNOTSUPP; - goto err_out; - } - if (val_len) { - rl = allocate_scattered_clusters((val_len + - g_vol->cluster_size - 1) / g_vol->cluster_size); - if (!rl) { - err = -errno; - ntfs_log_perror("Failed to allocate scattered clusters"); - goto err_out; - } - } else { - rl = NULL; - } - if (flags & ATTR_COMPRESSION_MASK) { - hdr_size = 72; - /* FIXME: This compression stuff is all wrong. Never mind for */ - /* now. (AIA) */ - if (val_len) - mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */ - else - mpa_size = 0; - } else { - hdr_size = 64; - if (val_len) { - mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0); - if (mpa_size < 0) { - err = -errno; - ntfs_log_error("Failed to get size for mapping " - "pairs.\n"); - goto err_out; - } - } else { - mpa_size = 0; - } - } - /* Mapping pairs array and next attribute must be 8-byte aligned. */ - asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7; - err = make_room_for_attribute(m, (char*)a, asize); - if (err == -ENOSPC) { - /* - * FIXME: Make space! (AIA) - * can we make it non-resident? if yes, do that. - * does it fit now? yes -> do it. - * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident? - * yes -> make non-resident - * does it fit now? yes -> do it. - * make all attributes non-resident - * does it fit now? yes -> do it. - * m is a base record? yes -> allocate extension record - * does the new attribute fit in there? yes -> do it. - * split up runlist into extents and place each in an extension - * record. - * FIXME: the check for needing extension records should be - * earlier on as it is very quick: asize > m->bytes_allocated? - */ - err = -EOPNOTSUPP; - goto err_out; -#ifdef DEBUG - } else if (err == -EINVAL) { - ntfs_log_error("BUG(): in insert_non_resident_attribute_in_" - "mft_record(): make_room_for_attribute() " - "returned error: EINVAL!\n"); - goto err_out; -#endif - } - a->type = type; - a->length = cpu_to_le32(asize); - a->non_resident = 1; - a->name_length = name_len; - a->name_offset = cpu_to_le16(hdr_size); - a->flags = flags; - a->instance = m->next_attr_instance; - m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance) - + 1) & 0xffff); - a->u.nonres.lowest_vcn = 0; - for (i = 0; rl[i].length; i++) - ; - a->u.nonres.highest_vcn = cpu_to_sle64(rl[i].vcn - 1); - a->u.nonres.mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7)); - memset(a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1)); - /* FIXME: Allocated size depends on compression. */ - a->u.nonres.allocated_size = cpu_to_sle64((val_len + (g_vol->cluster_size - 1)) & - ~(g_vol->cluster_size - 1)); - a->u.nonres.data_size = cpu_to_sle64(val_len); - a->u.nonres.initialized_size = cpu_to_sle64(val_len); - if (name_len) - memcpy((char*)a + hdr_size, uname, name_len << 1); - if (flags & ATTR_COMPRESSION_MASK) { - if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) { - ntfs_log_error("Unknown compression format. Reverting " - "to standard compression.\n"); - a->flags &= ~ATTR_COMPRESSION_MASK; - a->flags |= ATTR_IS_COMPRESSED; - } - a->u.nonres.compression_unit = 4; - /* FIXME: Set the compressed size. */ - a->u.nonres.compressed_size = 0; - /* FIXME: Write out the compressed data. */ - /* FIXME: err = build_mapping_pairs_compressed(); */ - err = -EOPNOTSUPP; - } else { - a->u.nonres.compression_unit = 0; - bw = ntfs_rlwrite(g_vol->u.dev, rl, val, val_len, NULL); - if (bw != val_len) { - ntfs_log_error("Error writing non-resident attribute " - "value.\n"); - return -errno; - } - err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size + - ((name_len + 7) & ~7), mpa_size, rl, 0, NULL); - } - if (err < 0 || bw != val_len) { - /* FIXME: Handle error. */ - /* deallocate clusters */ - /* remove attribute */ - if (err >= 0) - err = -EIO; - ntfs_log_error("insert_non_resident_attr_in_mft_record failed with " - "error %lld.\n", (long long) (err < 0 ? err : bw)); - } -err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - ntfs_ucsfree(uname); - free(rl); - return err; -} - -/** - * insert_resident_attr_in_mft_record - * - * Return 0 on success and -errno on error. - */ -static int insert_resident_attr_in_mft_record(MFT_RECORD *m, - const ATTR_TYPES type, const char *name, u32 name_len, - const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags, - const RESIDENT_ATTR_FLAGS res_flags, - const u8 *val, const u32 val_len) -{ - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - int asize, err; - ntfschar *uname = NULL; - int uname_len = 0; - /* - if (base record) - mkntfs_attr_lookup(); - else - */ - - uname = ntfs_str2ucs(name, &uname_len); - if (!uname) - return -errno; - - /* Check if the attribute is already there. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to allocate attribute search context.\n"); - err = -ENOMEM; - goto err_out; - } - if (ic == IGNORE_CASE) { - ntfs_log_error("FIXME: Hit unimplemented code path #3.\n"); - err = -EOPNOTSUPP; - goto err_out; - } - if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, val, val_len, - ctx)) { - err = -EEXIST; - goto err_out; - } - if (errno != ENOENT) { - ntfs_log_error("Corrupt inode.\n"); - err = -errno; - goto err_out; - } - a = ctx->attr; - /* sizeof(resident attribute record header) == 24 */ - asize = ((24 + ((name_len + 7) & ~7) + val_len) + 7) & ~7; - err = make_room_for_attribute(m, (char*)a, asize); - if (err == -ENOSPC) { - /* - * FIXME: Make space! (AIA) - * can we make it non-resident? if yes, do that. - * does it fit now? yes -> do it. - * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident? - * yes -> make non-resident - * does it fit now? yes -> do it. - * make all attributes non-resident - * does it fit now? yes -> do it. - * m is a base record? yes -> allocate extension record - * does the new attribute fit in there? yes -> do it. - * split up runlist into extents and place each in an extension - * record. - * FIXME: the check for needing extension records should be - * earlier on as it is very quick: asize > m->bytes_allocated? - */ - err = -EOPNOTSUPP; - goto err_out; - } -#ifdef DEBUG - if (err == -EINVAL) { - ntfs_log_error("BUG(): in insert_resident_attribute_in_mft_" - "record(): make_room_for_attribute() returned " - "error: EINVAL!\n"); - goto err_out; - } -#endif - a->type = type; - a->length = cpu_to_le32(asize); - a->non_resident = 0; - a->name_length = name_len; - if (type == AT_OBJECT_ID) - a->name_offset = const_cpu_to_le16(0); - else - a->name_offset = const_cpu_to_le16(24); - a->flags = flags; - a->instance = m->next_attr_instance; - m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance) - + 1) & 0xffff); - a->u.res.value_length = cpu_to_le32(val_len); - a->u.res.value_offset = cpu_to_le16(24 + ((name_len + 7) & ~7)); - a->u.res.resident_flags = res_flags; - a->u.res.reservedR = 0; - if (name_len) - memcpy((char*)a + 24, uname, name_len << 1); - if (val_len) - memcpy((char*)a + le16_to_cpu(a->u.res.value_offset), val, val_len); -err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - ntfs_ucsfree(uname); - return err; -} - - -/** - * add_attr_std_info - * - * Return 0 on success or -errno on error. - */ -static int add_attr_std_info(MFT_RECORD *m, const FILE_ATTR_FLAGS flags, - le32 security_id) -{ - STANDARD_INFORMATION si; - int err, sd_size; - - sd_size = 48; - - si.creation_time = utc2ntfs(mkntfs_time()); - si.last_data_change_time = si.creation_time; - si.last_mft_change_time = si.creation_time; - si.last_access_time = si.creation_time; - si.file_attributes = flags; /* already LE */ - si.u.v30.maximum_versions = cpu_to_le32(0); - si.u.v30.version_number = cpu_to_le32(0); - si.u.v30.class_id = cpu_to_le32(0); - si.u.v30.security_id = security_id; - if (si.u.v30.security_id != 0) - sd_size = 72; - /* FIXME: $Quota support... */ - si.u.v30.owner_id = cpu_to_le32(0); - si.u.v30.quota_charged = cpu_to_le64(0ULL); - /* FIXME: $UsnJrnl support... Not needed on fresh w2k3-volume */ - si.u.v30.usn = cpu_to_le64(0ULL); - /* NTFS 1.2: size of si = 48, NTFS 3.[01]: size of si = 72 */ - err = insert_resident_attr_in_mft_record(m, AT_STANDARD_INFORMATION, - NULL, 0, 0, 0, 0, (u8*)&si, sd_size); - if (err < 0) - ntfs_log_perror("add_attr_std_info failed"); - return err; -} - -/** - * add_attr_file_name - * - * Return 0 on success or -errno on error. - */ -static int add_attr_file_name(MFT_RECORD *m, const leMFT_REF parent_dir, - const s64 allocated_size, const s64 data_size, - const FILE_ATTR_FLAGS flags, const u16 packed_ea_size, - const u32 reparse_point_tag, const char *file_name, - const FILE_NAME_TYPE_FLAGS file_name_type) -{ - ntfs_attr_search_ctx *ctx; - STANDARD_INFORMATION *si; - FILE_NAME_ATTR *fn; - int i, fn_size; - ntfschar *uname; - - /* Check if the attribute is already there. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to get attribute search context.\n"); - return -ENOMEM; - } - if (mkntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, 0, 0, - NULL, 0, ctx)) { - int eo = errno; - ntfs_log_error("BUG: Standard information attribute not " - "present in file record.\n"); - ntfs_attr_put_search_ctx(ctx); - return -eo; - } - si = (STANDARD_INFORMATION*)((char*)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - i = (strlen(file_name) + 1) * sizeof(ntfschar); - fn_size = sizeof(FILE_NAME_ATTR) + i; - fn = ntfs_malloc(fn_size); - if (!fn) { - ntfs_attr_put_search_ctx(ctx); - return -errno; - } - fn->parent_directory = parent_dir; - - fn->creation_time = si->creation_time; - fn->last_data_change_time = si->last_data_change_time; - fn->last_mft_change_time = si->last_mft_change_time; - fn->last_access_time = si->last_access_time; - ntfs_attr_put_search_ctx(ctx); - - fn->allocated_size = cpu_to_sle64(allocated_size); - fn->data_size = cpu_to_sle64(data_size); - fn->file_attributes = flags; - /* These are in a union so can't have both. */ - if (packed_ea_size && reparse_point_tag) { - free(fn); - return -EINVAL; - } - if (packed_ea_size) { - fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size); - fn->u.s.reserved = cpu_to_le16(0); - } else { - fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag); - } - fn->file_name_type = file_name_type; - uname = fn->file_name; - i = ntfs_mbstoucs(file_name, &uname, i); - if (i < 1) { - free(fn); - return -EINVAL; - } - if (i > 0xff) { - free(fn); - return -ENAMETOOLONG; - } - /* No terminating null in file names. */ - fn->file_name_length = i; - fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar); - i = insert_resident_attr_in_mft_record(m, AT_FILE_NAME, NULL, 0, 0, - 0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size); - free(fn); - if (i < 0) - ntfs_log_error("add_attr_file_name failed: %s\n", strerror(-i)); - return i; -} - -#ifdef ENABLE_UUID - -/** - * add_attr_object_id - - * - * Note we insert only a basic object id which only has the GUID and none of - * the extended fields. This is because we currently only use this function - * when creating the object id for the volume. - * - * Return 0 on success or -errno on error. - */ -static int add_attr_object_id(MFT_RECORD *m, const GUID *object_id) -{ - OBJECT_ID_ATTR oi; - int err; - - oi = (OBJECT_ID_ATTR) { - .object_id = *object_id, - }; - err = insert_resident_attr_in_mft_record(m, AT_OBJECT_ID, NULL, - 0, 0, 0, 0, (u8*)&oi, sizeof(oi.object_id)); - if (err < 0) - ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err)); - return err; -} - -#endif - -/** - * add_attr_sd - * - * Create the security descriptor attribute adding the security descriptor @sd - * of length @sd_len to the mft record @m. - * - * Return 0 on success or -errno on error. - */ -static int add_attr_sd(MFT_RECORD *m, const u8 *sd, const s64 sd_len) -{ - int err; - - /* Does it fit? NO: create non-resident. YES: create resident. */ - if (le32_to_cpu(m->bytes_in_use) + 24 + sd_len > - le32_to_cpu(m->bytes_allocated)) - err = insert_non_resident_attr_in_mft_record(m, - AT_SECURITY_DESCRIPTOR, NULL, 0, 0, 0, sd, - sd_len); - else - err = insert_resident_attr_in_mft_record(m, - AT_SECURITY_DESCRIPTOR, NULL, 0, 0, 0, 0, sd, - sd_len); - if (err < 0) - ntfs_log_error("add_attr_sd failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_data - * - * Return 0 on success or -errno on error. - */ -static int add_attr_data(MFT_RECORD *m, const char *name, const u32 name_len, - const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags, - const u8 *val, const s64 val_len) -{ - int err; - - /* - * Does it fit? NO: create non-resident. YES: create resident. - * - * FIXME: Introduced arbitrary limit of mft record allocated size - 512. - * This is to get around the problem that if $Bitmap/$DATA becomes too - * big, but is just small enough to be resident, we would make it - * resident, and later run out of space when creating the other - * attributes and this would cause us to abort as making resident - * attributes non-resident is not supported yet. - * The proper fix is to support making resident attribute non-resident. - */ - if (le32_to_cpu(m->bytes_in_use) + 24 + val_len > - min(le32_to_cpu(m->bytes_allocated), - le32_to_cpu(m->bytes_allocated) - 512)) - err = insert_non_resident_attr_in_mft_record(m, AT_DATA, name, - name_len, ic, flags, val, val_len); - else - err = insert_resident_attr_in_mft_record(m, AT_DATA, name, - name_len, ic, flags, 0, val, val_len); - - if (err < 0) - ntfs_log_error("add_attr_data failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_data_positioned - * - * Create a non-resident data attribute with a predefined on disk location - * specified by the runlist @rl. The clusters specified by @rl are assumed to - * be allocated already. - * - * Return 0 on success or -errno on error. - */ -static int add_attr_data_positioned(MFT_RECORD *m, const char *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const ATTR_FLAGS flags, const runlist *rl, - const u8 *val, const s64 val_len) -{ - int err; - - err = insert_positioned_attr_in_mft_record(m, AT_DATA, name, name_len, - ic, flags, rl, val, val_len); - if (err < 0) - ntfs_log_error("add_attr_data_positioned failed: %s\n", - strerror(-err)); - return err; -} - -/** - * add_attr_vol_name - * - * Create volume name attribute specifying the volume name @vol_name as a null - * terminated char string of length @vol_name_len (number of characters not - * including the terminating null), which is converted internally to a little - * endian ntfschar string. The name is at least 1 character long and at most - * 0xff characters long (not counting the terminating null). - * - * Return 0 on success or -errno on error. - */ -static int add_attr_vol_name(MFT_RECORD *m, const char *vol_name, - const int vol_name_len __attribute__((unused))) -{ - ntfschar *uname = NULL; - int uname_len = 0; - int i; - - if (vol_name) { - uname_len = ntfs_mbstoucs(vol_name, &uname, 0); - if (uname_len < 0) - return -errno; - if (uname_len > 0xff) { - free(uname); - return -ENAMETOOLONG; - } - } - i = insert_resident_attr_in_mft_record(m, AT_VOLUME_NAME, NULL, 0, 0, - 0, 0, (u8*)uname, uname_len*sizeof(ntfschar)); - free(uname); - if (i < 0) - ntfs_log_error("add_attr_vol_name failed: %s\n", strerror(-i)); - return i; -} - -/** - * add_attr_vol_info - * - * Return 0 on success or -errno on error. - */ -static int add_attr_vol_info(MFT_RECORD *m, const VOLUME_FLAGS flags, - const u8 major_ver, const u8 minor_ver) -{ - VOLUME_INFORMATION vi; - int err; - - memset(&vi, 0, sizeof(vi)); - vi.major_ver = major_ver; - vi.minor_ver = minor_ver; - vi.flags = flags & VOLUME_FLAGS_MASK; - err = insert_resident_attr_in_mft_record(m, AT_VOLUME_INFORMATION, NULL, - 0, 0, 0, 0, (u8*)&vi, sizeof(vi)); - if (err < 0) - ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_index_root - * - * Return 0 on success or -errno on error. - */ -static int add_attr_index_root(MFT_RECORD *m, const char *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const ATTR_TYPES indexed_attr_type, - const COLLATION_RULES collation_rule, - const u32 index_block_size) -{ - INDEX_ROOT *r; - INDEX_ENTRY_HEADER *e; - int err, val_len; - - val_len = sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER); - r = ntfs_malloc(val_len); - if (!r) - return -errno; - r->type = (indexed_attr_type == AT_FILE_NAME) ? AT_FILE_NAME : 0; - if (indexed_attr_type == AT_FILE_NAME && - collation_rule != COLLATION_FILE_NAME) { - free(r); - ntfs_log_error("add_attr_index_root: indexed attribute is $FILE_NAME " - "but collation rule is not COLLATION_FILE_NAME.\n"); - return -EINVAL; - } - r->collation_rule = collation_rule; - r->index_block_size = cpu_to_le32(index_block_size); - if (index_block_size >= g_vol->cluster_size) { - if (index_block_size % g_vol->cluster_size) { - ntfs_log_error("add_attr_index_root: index block size is not " - "a multiple of the cluster size.\n"); - free(r); - return -EINVAL; - } - r->clusters_per_index_block = index_block_size / - g_vol->cluster_size; - } else { /* if (g_vol->cluster_size > index_block_size) */ - if (index_block_size & (index_block_size - 1)) { - ntfs_log_error("add_attr_index_root: index block size is not " - "a power of 2.\n"); - free(r); - return -EINVAL; - } - if (index_block_size < (u32)opts.sector_size) { - ntfs_log_error("add_attr_index_root: index block size " - "is smaller than the sector size.\n"); - free(r); - return -EINVAL; - } - r->clusters_per_index_block = index_block_size / - opts.sector_size; - } - memset(&r->reserved, 0, sizeof(r->reserved)); - r->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER)); - r->index.index_length = const_cpu_to_le32(sizeof(INDEX_HEADER) + - sizeof(INDEX_ENTRY_HEADER)); - r->index.allocated_size = r->index.index_length; - r->index.flags = SMALL_INDEX; - memset(&r->index.reserved, 0, sizeof(r->index.reserved)); - e = (INDEX_ENTRY_HEADER*)((u8*)&r->index + - le32_to_cpu(r->index.entries_offset)); - /* - * No matter whether this is a file index or a view as this is a - * termination entry, hence no key value / data is associated with it - * at all. Thus, we just need the union to be all zero. - */ - e->u.indexed_file = const_cpu_to_le64(0LL); - e->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER)); - e->key_length = const_cpu_to_le16(0); - e->flags = INDEX_ENTRY_END; - e->reserved = const_cpu_to_le16(0); - err = insert_resident_attr_in_mft_record(m, AT_INDEX_ROOT, name, - name_len, ic, 0, 0, (u8*)r, val_len); - free(r); - if (err < 0) - ntfs_log_error("add_attr_index_root failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_index_alloc - * - * Return 0 on success or -errno on error. - */ -static int add_attr_index_alloc(MFT_RECORD *m, const char *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const u8 *index_alloc_val, const u32 index_alloc_val_len) -{ - int err; - - err = insert_non_resident_attr_in_mft_record(m, AT_INDEX_ALLOCATION, - name, name_len, ic, 0, index_alloc_val, - index_alloc_val_len); - if (err < 0) - ntfs_log_error("add_attr_index_alloc failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_bitmap - * - * Return 0 on success or -errno on error. - */ -static int add_attr_bitmap(MFT_RECORD *m, const char *name, const u32 name_len, - const IGNORE_CASE_BOOL ic, const u8 *bitmap, - const u32 bitmap_len) -{ - int err; - - /* Does it fit? NO: create non-resident. YES: create resident. */ - if (le32_to_cpu(m->bytes_in_use) + 24 + bitmap_len > - le32_to_cpu(m->bytes_allocated)) - err = insert_non_resident_attr_in_mft_record(m, AT_BITMAP, name, - name_len, ic, 0, bitmap, bitmap_len); - else - err = insert_resident_attr_in_mft_record(m, AT_BITMAP, name, - name_len, ic, 0, 0, bitmap, bitmap_len); - - if (err < 0) - ntfs_log_error("add_attr_bitmap failed: %s\n", strerror(-err)); - return err; -} - -/** - * add_attr_bitmap_positioned - * - * Create a non-resident bitmap attribute with a predefined on disk location - * specified by the runlist @rl. The clusters specified by @rl are assumed to - * be allocated already. - * - * Return 0 on success or -errno on error. - */ -static int add_attr_bitmap_positioned(MFT_RECORD *m, const char *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const runlist *rl, const u8 *bitmap, const u32 bitmap_len) -{ - int err; - - err = insert_positioned_attr_in_mft_record(m, AT_BITMAP, name, name_len, - ic, 0, rl, bitmap, bitmap_len); - if (err < 0) - ntfs_log_error("add_attr_bitmap_positioned failed: %s\n", - strerror(-err)); - return err; -} - - -/** - * upgrade_to_large_index - * - * Create bitmap and index allocation attributes, modify index root - * attribute accordingly and move all of the index entries from the index root - * into the index allocation. - * - * Return 0 on success or -errno on error. - */ -static int upgrade_to_large_index(MFT_RECORD *m, const char *name, - u32 name_len, const IGNORE_CASE_BOOL ic, - INDEX_ALLOCATION **idx) -{ - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - INDEX_ROOT *r; - INDEX_ENTRY *re; - INDEX_ALLOCATION *ia_val = NULL; - ntfschar *uname = NULL; - int uname_len = 0; - u8 bmp[8]; - char *re_start, *re_end; - int i, err, index_block_size; - - uname = ntfs_str2ucs(name, &uname_len); - if (!uname) - return -errno; - - /* Find the index root attribute. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to allocate attribute search context.\n"); - ntfs_ucsfree(uname); - return -ENOMEM; - } - if (ic == IGNORE_CASE) { - ntfs_log_error("FIXME: Hit unimplemented code path #4.\n"); - err = -EOPNOTSUPP; - ntfs_ucsfree(uname); - goto err_out; - } - err = mkntfs_attr_lookup(AT_INDEX_ROOT, uname, uname_len, ic, 0, NULL, 0, - ctx); - ntfs_ucsfree(uname); - if (err) { - err = -ENOTDIR; - goto err_out; - } - a = ctx->attr; - if (a->non_resident || a->flags) { - err = -EINVAL; - goto err_out; - } - r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->u.res.value_offset)); - re_end = (char*)r + le32_to_cpu(a->u.res.value_length); - re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset); - re = (INDEX_ENTRY*)re_start; - index_block_size = le32_to_cpu(r->index_block_size); - memset(bmp, 0, sizeof(bmp)); - ntfs_bit_set(bmp, 0ULL, 1); - /* Bitmap has to be at least 8 bytes in size. */ - err = add_attr_bitmap(m, name, name_len, ic, bmp, sizeof(bmp)); - if (err) - goto err_out; - ia_val = ntfs_calloc(index_block_size); - if (!ia_val) { - err = -errno; - goto err_out; - } - /* Setup header. */ - ia_val->magic = magic_INDX; - ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION)); - if (index_block_size >= NTFS_BLOCK_SIZE) { - ia_val->usa_count = cpu_to_le16(index_block_size / - NTFS_BLOCK_SIZE + 1); - } else { - ia_val->usa_count = cpu_to_le16(1); - ntfs_log_error("Sector size is bigger than index block size. " - "Setting usa_count to 1. If Windows chkdsk " - "reports this as corruption, please email %s " - "stating that you saw this message and that " - "the filesystem created was corrupt. " - "Thank you.", NTFS_DEV_LIST); - } - /* Set USN to 1. */ - *(le16*)((char*)ia_val + le16_to_cpu(ia_val->usa_ofs)) = - cpu_to_le16(1); - ia_val->lsn = 0; - ia_val->index_block_vcn = 0; - ia_val->index.flags = LEAF_NODE; - /* Align to 8-byte boundary. */ - ia_val->index.entries_offset = cpu_to_le32((sizeof(INDEX_HEADER) + - le16_to_cpu(ia_val->usa_count) * 2 + 7) & ~7); - ia_val->index.allocated_size = cpu_to_le32(index_block_size - - (sizeof(INDEX_ALLOCATION) - sizeof(INDEX_HEADER))); - /* Find the last entry in the index root and save it in re. */ - while ((char*)re < re_end && !(re->flags & INDEX_ENTRY_END)) { - /* Next entry in index root. */ - re = (INDEX_ENTRY*)((char*)re + le16_to_cpu(re->length)); - } - /* Copy all the entries including the termination entry. */ - i = (char*)re - re_start + le16_to_cpu(re->length); - memcpy((char*)&ia_val->index + - le32_to_cpu(ia_val->index.entries_offset), re_start, i); - /* Finish setting up index allocation. */ - ia_val->index.index_length = cpu_to_le32(i + - le32_to_cpu(ia_val->index.entries_offset)); - /* Move the termination entry forward to the beginning if necessary. */ - if ((char*)re > re_start) { - memmove(re_start, (char*)re, le16_to_cpu(re->length)); - re = (INDEX_ENTRY*)re_start; - } - /* Now fixup empty index root with pointer to index allocation VCN 0. */ - r->index.flags = LARGE_INDEX; - re->flags |= INDEX_ENTRY_NODE; - if (le16_to_cpu(re->length) < sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)) - re->length = cpu_to_le16(le16_to_cpu(re->length) + sizeof(VCN)); - r->index.index_length = cpu_to_le32(le32_to_cpu(r->index.entries_offset) - + le16_to_cpu(re->length)); - r->index.allocated_size = r->index.index_length; - /* Resize index root attribute. */ - if (ntfs_resident_attr_value_resize(m, a, sizeof(INDEX_ROOT) - - sizeof(INDEX_HEADER) + - le32_to_cpu(r->index.allocated_size))) { - /* TODO: Remove the added bitmap! */ - /* Revert index root from index allocation. */ - err = -errno; - goto err_out; - } - /* Set VCN pointer to 0LL. */ - *(leVCN*)((char*)re + le16_to_cpu(re->length) - sizeof(VCN)) = 0; - err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)ia_val, index_block_size); - if (err) { - err = -errno; - ntfs_log_error("ntfs_mst_pre_write_fixup() failed in " - "upgrade_to_large_index.\n"); - goto err_out; - } - err = add_attr_index_alloc(m, name, name_len, ic, (u8*)ia_val, - index_block_size); - ntfs_mst_post_write_fixup((NTFS_RECORD*)ia_val); - if (err) { - /* TODO: Remove the added bitmap! */ - /* Revert index root from index allocation. */ - goto err_out; - } - *idx = ia_val; - ntfs_attr_put_search_ctx(ctx); - return 0; -err_out: - ntfs_attr_put_search_ctx(ctx); - free(ia_val); - return err; -} - -/** - * make_room_for_index_entry_in_index_block - * - * Create space of @size bytes at position @pos inside the index block @idx. - * - * Return 0 on success or -errno on error. - */ -static int make_room_for_index_entry_in_index_block(INDEX_BLOCK *idx, - INDEX_ENTRY *pos, u32 size) -{ - u32 biu; - - if (!size) - return 0; -#ifdef DEBUG - /* - * Rigorous consistency checks. Always return -EINVAL even if more - * appropriate codes exist for simplicity of parsing the return value. - */ - if (size != ((size + 7) & ~7)) { - ntfs_log_error("make_room_for_index_entry_in_index_block() received " - "non 8-byte aligned size.\n"); - return -EINVAL; - } - if (!idx || !pos) - return -EINVAL; - if ((char*)pos < (char*)idx || (char*)pos + size < (char*)idx || - (char*)pos > (char*)idx + sizeof(INDEX_BLOCK) - - sizeof(INDEX_HEADER) + - le32_to_cpu(idx->index.allocated_size) || - (char*)pos + size > (char*)idx + sizeof(INDEX_BLOCK) - - sizeof(INDEX_HEADER) + - le32_to_cpu(idx->index.allocated_size)) - return -EINVAL; - /* The - sizeof(INDEX_ENTRY_HEADER) is for the index terminator. */ - if ((char*)pos - (char*)&idx->index > - (int)le32_to_cpu(idx->index.index_length) - - (int)sizeof(INDEX_ENTRY_HEADER)) - return -EINVAL; -#endif - biu = le32_to_cpu(idx->index.index_length); - /* Do we have enough space? */ - if (biu + size > le32_to_cpu(idx->index.allocated_size)) - return -ENOSPC; - /* Move everything after pos to pos + size. */ - memmove((char*)pos + size, (char*)pos, biu - ((char*)pos - - (char*)&idx->index)); - /* Update index block. */ - idx->index.index_length = cpu_to_le32(biu + size); - return 0; -} - -/** - * ntfs_index_keys_compare - * - * not all types of COLLATION_RULES supported yet... - * added as needed.. (remove this comment when all are added) - */ -static int ntfs_index_keys_compare(u8 *key1, u8 *key2, int key1_length, - int key2_length, COLLATION_RULES collation_rule) -{ - u32 u1, u2; - int i; - - if (collation_rule == COLLATION_NTOFS_ULONG) { - /* i.e. $SII or $QUOTA-$Q */ - u1 = le32_to_cpup(key1); - u2 = le32_to_cpup(key2); - if (u1 < u2) - return -1; - if (u1 > u2) - return 1; - /* u1 == u2 */ - return 0; - } - if (collation_rule == COLLATION_NTOFS_ULONGS) { - /* i.e $OBJID-$O */ - i = 0; - while (i < min(key1_length, key2_length)) { - u1 = le32_to_cpup(key1 + i); - u2 = le32_to_cpup(key2 + i); - if (u1 < u2) - return -1; - if (u1 > u2) - return 1; - /* u1 == u2 */ - i += sizeof(u32); - } - if (key1_length < key2_length) - return -1; - if (key1_length > key2_length) - return 1; - return 0; - } - if (collation_rule == COLLATION_NTOFS_SECURITY_HASH) { - /* i.e. $SDH */ - u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->hash); - u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->hash); - if (u1 < u2) - return -1; - if (u1 > u2) - return 1; - /* u1 == u2 */ - u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->security_id); - u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->security_id); - if (u1 < u2) - return -1; - if (u1 > u2) - return 1; - return 0; - } - if (collation_rule == COLLATION_NTOFS_SID) { - /* i.e. $QUOTA-O */ - i = memcmp(key1, key2, min(key1_length, key2_length)); - if (!i) { - if (key1_length < key2_length) - return -1; - if (key1_length > key2_length) - return 1; - } - return i; - } - ntfs_log_critical("ntfs_index_keys_compare called without supported " - "collation rule.\n"); - return 0; /* Claim they're equal. What else can we do? */ -} - -/** - * insert_index_entry_in_res_dir_index - * - * i.e. insert an index_entry in some named index_root - * simplified search method, works for mkntfs - */ -static int insert_index_entry_in_res_dir_index(INDEX_ENTRY *idx, u32 idx_size, - MFT_RECORD *m, ntfschar *name, u32 name_size, ATTR_TYPES type) -{ - ntfs_attr_search_ctx *ctx; - INDEX_HEADER *idx_header; - INDEX_ENTRY *idx_entry, *idx_end; - ATTR_RECORD *a; - COLLATION_RULES collation_rule; - int err, i; - - err = 0; - /* does it fit ?*/ - if (g_vol->mft_record_size > idx_size + le32_to_cpu(m->bytes_allocated)) - return -ENOSPC; - /* find the INDEX_ROOT attribute:*/ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_error("Failed to allocate attribute search " - "context.\n"); - err = -ENOMEM; - goto err_out; - } - if (mkntfs_attr_lookup(AT_INDEX_ROOT, name, name_size, 0, 0, NULL, 0, - ctx)) { - err = -EEXIST; - goto err_out; - } - /* found attribute */ - a = (ATTR_RECORD*)ctx->attr; - collation_rule = ((INDEX_ROOT*)((u8*)a + - le16_to_cpu(a->u.res.value_offset)))->collation_rule; - idx_header = (INDEX_HEADER*)((u8*)a + le16_to_cpu(a->u.res.value_offset) - + 0x10); - idx_entry = (INDEX_ENTRY*)((u8*)idx_header + - le32_to_cpu(idx_header->entries_offset)); - idx_end = (INDEX_ENTRY*)((u8*)idx_entry + - le32_to_cpu(idx_header->index_length)); - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry. - */ - if (type == AT_FILE_NAME) { - while (((u8*)idx_entry < (u8*)idx_end) && - !(idx_entry->flags & INDEX_ENTRY_END)) { - i = ntfs_file_values_compare(&idx->key.file_name, - &idx_entry->key.file_name, 1, - IGNORE_CASE, g_vol->upcase, - g_vol->upcase_len); - /* - * If @file_name collates before ie->key.file_name, - * there is no matching index entry. - */ - if (i == -1) - break; - /* If file names are not equal, continue search. */ - if (i) - goto do_next; - if (idx->key.file_name.file_name_type != - FILE_NAME_POSIX || - idx_entry->key.file_name.file_name_type - != FILE_NAME_POSIX) - return -EEXIST; - i = ntfs_file_values_compare(&idx->key.file_name, - &idx_entry->key.file_name, 1, - CASE_SENSITIVE, g_vol->upcase, - g_vol->upcase_len); - if (!i) - return -EEXIST; - if (i == -1) - break; -do_next: - idx_entry = (INDEX_ENTRY*)((u8*)idx_entry + - le16_to_cpu(idx_entry->length)); - } - } else if (type == AT_UNUSED) { /* case view */ - while (((u8*)idx_entry < (u8*)idx_end) && - !(idx_entry->flags & INDEX_ENTRY_END)) { - i = ntfs_index_keys_compare((u8*)idx + 0x10, - (u8*)idx_entry + 0x10, - le16_to_cpu(idx->key_length), - le16_to_cpu(idx_entry->key_length), - collation_rule); - if (!i) - return -EEXIST; - if (i == -1) - break; - idx_entry = (INDEX_ENTRY*)((u8*)idx_entry + - le16_to_cpu(idx_entry->length)); - } - } else - return -EINVAL; - memmove((u8*)idx_entry + idx_size, (u8*)idx_entry, - le32_to_cpu(m->bytes_in_use) - - ((u8*)idx_entry - (u8*)m)); - memcpy((u8*)idx_entry, (u8*)idx, idx_size); - /* Adjust various offsets, etc... */ - m->bytes_in_use = cpu_to_le32(le32_to_cpu(m->bytes_in_use) + idx_size); - a->length = cpu_to_le32(le32_to_cpu(a->length) + idx_size); - a->u.res.value_length = cpu_to_le32(le32_to_cpu(a->u.res.value_length) + idx_size); - idx_header->index_length = cpu_to_le32( - le32_to_cpu(idx_header->index_length) + idx_size); - idx_header->allocated_size = cpu_to_le32( - le32_to_cpu(idx_header->allocated_size) + idx_size); -err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - return err; -} - -/** - * initialize_secure - * - * initializes $Secure's $SDH and $SII indexes from $SDS datastream - */ -static int initialize_secure(char *sds, u32 sds_size, MFT_RECORD *m) -{ - int err, sdh_size, sii_size; - SECURITY_DESCRIPTOR_HEADER *sds_header; - INDEX_ENTRY *idx_entry_sdh, *idx_entry_sii; - SDH_INDEX_DATA *sdh_data; - SII_INDEX_DATA *sii_data; - - sds_header = (SECURITY_DESCRIPTOR_HEADER*)sds; - sdh_size = sizeof(INDEX_ENTRY_HEADER); - sdh_size += sizeof(SDH_INDEX_KEY) + sizeof(SDH_INDEX_DATA); - sii_size = sizeof(INDEX_ENTRY_HEADER); - sii_size += sizeof(SII_INDEX_KEY) + sizeof(SII_INDEX_DATA); - idx_entry_sdh = ntfs_calloc(sizeof(INDEX_ENTRY)); - if (!idx_entry_sdh) - return -errno; - idx_entry_sii = ntfs_calloc(sizeof(INDEX_ENTRY)); - if (!idx_entry_sii) { - free(idx_entry_sdh); - return -errno; - } - err = 0; - - while ((char*)sds_header < (char*)sds + sds_size) { - if (!sds_header->length) - break; - /* SDH index entry */ - idx_entry_sdh->u.s.data_offset = const_cpu_to_le16(0x18); - idx_entry_sdh->u.s.data_length = const_cpu_to_le16(0x14); - idx_entry_sdh->u.s.reservedV = const_cpu_to_le32(0x00); - idx_entry_sdh->length = const_cpu_to_le16(0x30); - idx_entry_sdh->key_length = const_cpu_to_le16(0x08); - idx_entry_sdh->flags = const_cpu_to_le16(0x00); - idx_entry_sdh->reserved = const_cpu_to_le16(0x00); - idx_entry_sdh->key.sdh.hash = sds_header->hash; - idx_entry_sdh->key.sdh.security_id = sds_header->security_id; - sdh_data = (SDH_INDEX_DATA*)((u8*)idx_entry_sdh + - le16_to_cpu(idx_entry_sdh->u.s.data_offset)); - sdh_data->hash = sds_header->hash; - sdh_data->security_id = sds_header->security_id; - sdh_data->offset = sds_header->offset; - sdh_data->length = sds_header->length; - sdh_data->reserved_II = const_cpu_to_le32(0x00490049); - - /* SII index entry */ - idx_entry_sii->u.s.data_offset = const_cpu_to_le16(0x14); - idx_entry_sii->u.s.data_length = const_cpu_to_le16(0x14); - idx_entry_sii->u.s.reservedV = const_cpu_to_le32(0x00); - idx_entry_sii->length = const_cpu_to_le16(0x28); - idx_entry_sii->key_length = const_cpu_to_le16(0x04); - idx_entry_sii->flags = const_cpu_to_le16(0x00); - idx_entry_sii->reserved = const_cpu_to_le16(0x00); - idx_entry_sii->key.sii.security_id = sds_header->security_id; - sii_data = (SII_INDEX_DATA*)((u8*)idx_entry_sii + - le16_to_cpu(idx_entry_sii->u.s.data_offset)); - sii_data->hash = sds_header->hash; - sii_data->security_id = sds_header->security_id; - sii_data->offset = sds_header->offset; - sii_data->length = sds_header->length; - if ((err = insert_index_entry_in_res_dir_index(idx_entry_sdh, - sdh_size, m, NTFS_INDEX_SDH, 4, AT_UNUSED))) - break; - if ((err = insert_index_entry_in_res_dir_index(idx_entry_sii, - sii_size, m, NTFS_INDEX_SII, 4, AT_UNUSED))) - break; - sds_header = (SECURITY_DESCRIPTOR_HEADER*)((u8*)sds_header + - ((le32_to_cpu(sds_header->length) + 15) & ~15)); - } - free(idx_entry_sdh); - free(idx_entry_sii); - return err; -} - -/** - * initialize_quota - * - * initialize $Quota with the default quota index-entries. - */ -static int initialize_quota(MFT_RECORD *m) -{ - int o_size, q1_size, q2_size, err, i; - INDEX_ENTRY *idx_entry_o, *idx_entry_q1, *idx_entry_q2; - QUOTA_O_INDEX_DATA *idx_entry_o_data; - QUOTA_CONTROL_ENTRY *idx_entry_q1_data, *idx_entry_q2_data; - - err = 0; - /* q index entry num 1 */ - q1_size = 0x48; - idx_entry_q1 = ntfs_calloc(q1_size); - if (!idx_entry_q1) - return errno; - idx_entry_q1->u.s.data_offset = const_cpu_to_le16(0x14); - idx_entry_q1->u.s.data_length = const_cpu_to_le16(0x30); - idx_entry_q1->u.s.reservedV = const_cpu_to_le32(0x00); - idx_entry_q1->length = const_cpu_to_le16(0x48); - idx_entry_q1->key_length = const_cpu_to_le16(0x04); - idx_entry_q1->flags = const_cpu_to_le16(0x00); - idx_entry_q1->reserved = const_cpu_to_le16(0x00); - idx_entry_q1->key.owner_id = const_cpu_to_le32(0x01); - idx_entry_q1_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q1 - + le16_to_cpu(idx_entry_q1->u.s.data_offset)); - idx_entry_q1_data->version = const_cpu_to_le32(0x02); - idx_entry_q1_data->flags = QUOTA_FLAG_DEFAULT_LIMITS; - idx_entry_q1_data->bytes_used = const_cpu_to_le64(0x00); - idx_entry_q1_data->change_time = utc2ntfs(mkntfs_time()); - idx_entry_q1_data->threshold = cpu_to_sle64(-1); - idx_entry_q1_data->limit = cpu_to_sle64(-1); - idx_entry_q1_data->exceeded_time = 0; - err = insert_index_entry_in_res_dir_index(idx_entry_q1, q1_size, m, - NTFS_INDEX_Q, 2, AT_UNUSED); - free(idx_entry_q1); - if (err) - return err; - /* q index entry num 2 */ - q2_size = 0x58; - idx_entry_q2 = ntfs_calloc(q2_size); - if (!idx_entry_q2) - return errno; - idx_entry_q2->u.s.data_offset = const_cpu_to_le16(0x14); - idx_entry_q2->u.s.data_length = const_cpu_to_le16(0x40); - idx_entry_q2->u.s.reservedV = const_cpu_to_le32(0x00); - idx_entry_q2->length = const_cpu_to_le16(0x58); - idx_entry_q2->key_length = const_cpu_to_le16(0x04); - idx_entry_q2->flags = const_cpu_to_le16(0x00); - idx_entry_q2->reserved = const_cpu_to_le16(0x00); - idx_entry_q2->key.owner_id = QUOTA_FIRST_USER_ID; - idx_entry_q2_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q2 - + le16_to_cpu(idx_entry_q2->u.s.data_offset)); - idx_entry_q2_data->version = const_cpu_to_le32(0x02); - idx_entry_q2_data->flags = QUOTA_FLAG_DEFAULT_LIMITS; - idx_entry_q2_data->bytes_used = const_cpu_to_le64(0x00); - idx_entry_q2_data->change_time = utc2ntfs(mkntfs_time());; - idx_entry_q2_data->threshold = cpu_to_sle64(-1); - idx_entry_q2_data->limit = cpu_to_sle64(-1); - idx_entry_q2_data->exceeded_time = 0; - idx_entry_q2_data->sid.revision = 1; - idx_entry_q2_data->sid.sub_authority_count = 2; - for (i = 0; i < 5; i++) - idx_entry_q2_data->sid.identifier_authority.value[i] = 0; - idx_entry_q2_data->sid.identifier_authority.value[5] = 0x05; - idx_entry_q2_data->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - idx_entry_q2_data->sid.sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - err = insert_index_entry_in_res_dir_index(idx_entry_q2, q2_size, m, - NTFS_INDEX_Q, 2, AT_UNUSED); - free(idx_entry_q2); - if (err) - return err; - o_size = 0x28; - idx_entry_o = ntfs_calloc(o_size); - if (!idx_entry_o) - return errno; - idx_entry_o->u.s.data_offset = const_cpu_to_le16(0x20); - idx_entry_o->u.s.data_length = const_cpu_to_le16(0x04); - idx_entry_o->u.s.reservedV = const_cpu_to_le32(0x00); - idx_entry_o->length = const_cpu_to_le16(0x28); - idx_entry_o->key_length = const_cpu_to_le16(0x10); - idx_entry_o->flags = const_cpu_to_le16(0x00); - idx_entry_o->reserved = const_cpu_to_le16(0x00); - idx_entry_o->key.sid.revision = 0x01; - idx_entry_o->key.sid.sub_authority_count = 0x02; - for (i = 0; i < 5; i++) - idx_entry_o->key.sid.identifier_authority.value[i] = 0; - idx_entry_o->key.sid.identifier_authority.value[5] = 0x05; - idx_entry_o->key.sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - idx_entry_o->key.sid.sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - idx_entry_o_data = (QUOTA_O_INDEX_DATA*)((char*)idx_entry_o - + le16_to_cpu(idx_entry_o->u.s.data_offset)); - idx_entry_o_data->owner_id = QUOTA_FIRST_USER_ID; - /* 20 00 00 00 padding after here on ntfs 3.1. 3.0 is unchecked. */ - idx_entry_o_data->unknown = const_cpu_to_le32(32); - err = insert_index_entry_in_res_dir_index(idx_entry_o, o_size, m, - NTFS_INDEX_O, 2, AT_UNUSED); - free(idx_entry_o); - - return err; -} - -/** - * insert_file_link_in_dir_index - * - * Insert the fully completed FILE_NAME_ATTR @file_name which is inside - * the file with mft reference @file_ref into the index (allocation) block - * @idx (which belongs to @file_ref's parent directory). - * - * Return 0 on success or -errno on error. - */ -static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, leMFT_REF file_ref, - FILE_NAME_ATTR *file_name, u32 file_name_size) -{ - int err, i; - INDEX_ENTRY *ie; - char *index_end; - - /* - * Lookup dir entry @file_name in dir @idx to determine correct - * insertion location. FIXME: Using a very oversimplified lookup - * method which is sufficient for mkntfs but no good whatsoever in - * real world scenario. (AIA) - */ - - index_end = (char*)&idx->index + le32_to_cpu(idx->index.index_length); - ie = (INDEX_ENTRY*)((char*)&idx->index + - le32_to_cpu(idx->index.entries_offset)); - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry. - */ - while ((char*)ie < index_end && !(ie->flags & INDEX_ENTRY_END)) { -#if 0 -#ifdef DEBUG - ntfs_log_debug("file_name_attr1->file_name_length = %i\n", - file_name->file_name_length); - if (file_name->file_name_length) { - char *__buf = NULL; - i = ntfs_ucstombs((ntfschar*)&file_name->file_name, - file_name->file_name_length, &__buf, 0); - if (i < 0) - ntfs_log_debug("Name contains non-displayable " - "Unicode characters.\n"); - ntfs_log_debug("file_name_attr1->file_name = %s\n", - __buf); - free(__buf); - } - ntfs_log_debug("file_name_attr2->file_name_length = %i\n", - ie->key.file_name.file_name_length); - if (ie->key.file_name.file_name_length) { - char *__buf = NULL; - i = ntfs_ucstombs(ie->key.file_name.file_name, - ie->key.file_name.file_name_length + 1, &__buf, - 0); - if (i < 0) - ntfs_log_debug("Name contains non-displayable " - "Unicode characters.\n"); - ntfs_log_debug("file_name_attr2->file_name = %s\n", - __buf); - free(__buf); - } -#endif -#endif - i = ntfs_file_values_compare(file_name, - (FILE_NAME_ATTR*)&ie->key.file_name, 1, - IGNORE_CASE, g_vol->upcase, g_vol->upcase_len); - /* - * If @file_name collates before ie->key.file_name, there is no - * matching index entry. - */ - if (i == -1) - break; - /* If file names are not equal, continue search. */ - if (i) - goto do_next; - /* File names are equal when compared ignoring case. */ - /* - * If BOTH file names are in the POSIX namespace, do a case - * sensitive comparison as well. Otherwise the names match so - * we return -EEXIST. FIXME: There are problems with this in a - * real world scenario, when one is POSIX and one isn't, but - * fine for mkntfs where we don't use POSIX namespace at all - * and hence this following code is luxury. (AIA) - */ - if (file_name->file_name_type != FILE_NAME_POSIX || - ie->key.file_name.file_name_type != FILE_NAME_POSIX) - return -EEXIST; - i = ntfs_file_values_compare(file_name, - (FILE_NAME_ATTR*)&ie->key.file_name, 1, - CASE_SENSITIVE, g_vol->upcase, - g_vol->upcase_len); - if (i == -1) - break; - /* Complete match. Bugger. Can't insert. */ - if (!i) - return -EEXIST; -do_next: -#ifdef DEBUG - /* Next entry. */ - if (!ie->length) { - ntfs_log_debug("BUG: ie->length is zero, breaking out " - "of loop.\n"); - break; - } -#endif - ie = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length)); - }; - i = (sizeof(INDEX_ENTRY_HEADER) + file_name_size + 7) & ~7; - err = make_room_for_index_entry_in_index_block(idx, ie, i); - if (err) { - ntfs_log_error("make_room_for_index_entry_in_index_block " - "failed: %s\n", strerror(-err)); - return err; - } - /* Create entry in place and copy file name attribute value. */ - ie->u.indexed_file = file_ref; - ie->length = cpu_to_le16(i); - ie->key_length = cpu_to_le16(file_name_size); - ie->flags = cpu_to_le16(0); - ie->reserved = cpu_to_le16(0); - memcpy((char*)&ie->key.file_name, (char*)file_name, file_name_size); - return 0; -} - -/** - * create_hardlink_res - * - * Create a file_name_attribute in the mft record @m_file which points to the - * parent directory with mft reference @ref_parent. - * - * Then, insert an index entry with this file_name_attribute in the index - * root @idx of the index_root attribute of the parent directory. - * - * @ref_file is the mft reference of @m_file. - * - * Return 0 on success or -errno on error. - */ -static int create_hardlink_res(MFT_RECORD *m_parent, const leMFT_REF ref_parent, - MFT_RECORD *m_file, const leMFT_REF ref_file, - const s64 allocated_size, const s64 data_size, - const FILE_ATTR_FLAGS flags, const u16 packed_ea_size, - const u32 reparse_point_tag, const char *file_name, - const FILE_NAME_TYPE_FLAGS file_name_type) -{ - FILE_NAME_ATTR *fn; - int i, fn_size, idx_size; - INDEX_ENTRY *idx_entry_new; - ntfschar *uname; - - /* Create the file_name attribute. */ - i = (strlen(file_name) + 1) * sizeof(ntfschar); - fn_size = sizeof(FILE_NAME_ATTR) + i; - fn = ntfs_malloc(fn_size); - if (!fn) - return -errno; - fn->parent_directory = ref_parent; - /* FIXME: copy the creation_time from the std info */ - fn->creation_time = utc2ntfs(mkntfs_time()); - fn->last_data_change_time = fn->creation_time; - fn->last_mft_change_time = fn->creation_time; - fn->last_access_time = fn->creation_time; - fn->allocated_size = cpu_to_sle64(allocated_size); - fn->data_size = cpu_to_sle64(data_size); - fn->file_attributes = flags; - /* These are in a union so can't have both. */ - if (packed_ea_size && reparse_point_tag) { - free(fn); - return -EINVAL; - } - if (packed_ea_size) { - free(fn); - return -EINVAL; - } - if (packed_ea_size) { - fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size); - fn->u.s.reserved = cpu_to_le16(0); - } else { - fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag); - } - fn->file_name_type = file_name_type; - uname = fn->file_name; - i = ntfs_mbstoucs(file_name, &uname, i); - if (i < 1) { - free(fn); - return -EINVAL; - } - if (i > 0xff) { - free(fn); - return -ENAMETOOLONG; - } - /* No terminating null in file names. */ - fn->file_name_length = i; - fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar); - /* Increment the link count of @m_file. */ - i = le16_to_cpu(m_file->link_count); - if (i == 0xffff) { - ntfs_log_error("Too many hardlinks present already.\n"); - free(fn); - return -EINVAL; - } - m_file->link_count = cpu_to_le16(i + 1); - /* Add the file_name to @m_file. */ - i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0, 0, - 0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size); - if (i < 0) { - ntfs_log_error("create_hardlink failed adding file name " - "attribute: %s\n", strerror(-i)); - free(fn); - /* Undo link count increment. */ - m_file->link_count = cpu_to_le16( - le16_to_cpu(m_file->link_count) - 1); - return i; - } - /* Insert the index entry for file_name in @idx. */ - idx_size = (fn_size + 7) & ~7; - idx_entry_new = ntfs_calloc(idx_size + 0x10); - if (!idx_entry_new) - return -errno; - idx_entry_new->u.indexed_file = ref_file; - idx_entry_new->length = cpu_to_le16(idx_size + 0x10); - idx_entry_new->key_length = cpu_to_le16(fn_size); - memcpy((u8*)idx_entry_new + 0x10, (u8*)fn, fn_size); - i = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size + 0x10, - m_parent, NTFS_INDEX_I30, 4, AT_FILE_NAME); - if (i < 0) { - ntfs_log_error("create_hardlink failed inserting index entry: " - "%s\n", strerror(-i)); - /* FIXME: Remove the file name attribute from @m_file. */ - free(idx_entry_new); - free(fn); - /* Undo link count increment. */ - m_file->link_count = cpu_to_le16( - le16_to_cpu(m_file->link_count) - 1); - return i; - } - free(idx_entry_new); - free(fn); - return 0; -} - -/** - * create_hardlink - * - * Create a file_name_attribute in the mft record @m_file which points to the - * parent directory with mft reference @ref_parent. - * - * Then, insert an index entry with this file_name_attribute in the index - * block @idx of the index allocation attribute of the parent directory. - * - * @ref_file is the mft reference of @m_file. - * - * Return 0 on success or -errno on error. - */ -static int create_hardlink(INDEX_BLOCK *idx, const leMFT_REF ref_parent, - MFT_RECORD *m_file, const leMFT_REF ref_file, - const s64 allocated_size, const s64 data_size, - const FILE_ATTR_FLAGS flags, const u16 packed_ea_size, - const u32 reparse_point_tag, const char *file_name, - const FILE_NAME_TYPE_FLAGS file_name_type) -{ - FILE_NAME_ATTR *fn; - int i, fn_size; - ntfschar *uname; - - /* Create the file_name attribute. */ - i = (strlen(file_name) + 1) * sizeof(ntfschar); - fn_size = sizeof(FILE_NAME_ATTR) + i; - fn = ntfs_malloc(fn_size); - if (!fn) - return -errno; - fn->parent_directory = ref_parent; - /* FIXME: Is this correct? Or do we have to copy the creation_time */ - /* from the std info? */ - fn->creation_time = utc2ntfs(mkntfs_time()); - fn->last_data_change_time = fn->creation_time; - fn->last_mft_change_time = fn->creation_time; - fn->last_access_time = fn->creation_time; - fn->allocated_size = cpu_to_sle64(allocated_size); - fn->data_size = cpu_to_sle64(data_size); - fn->file_attributes = flags; - /* These are in a union so can't have both. */ - if (packed_ea_size && reparse_point_tag) { - free(fn); - return -EINVAL; - } - if (packed_ea_size) { - fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size); - fn->u.s.reserved = cpu_to_le16(0); - } else { - fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag); - } - fn->file_name_type = file_name_type; - uname = fn->file_name; - i = ntfs_mbstoucs(file_name, &uname, i); - if (i < 1) { - free(fn); - return -EINVAL; - } - if (i > 0xff) { - free(fn); - return -ENAMETOOLONG; - } - /* No terminating null in file names. */ - fn->file_name_length = i; - fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar); - /* Increment the link count of @m_file. */ - i = le16_to_cpu(m_file->link_count); - if (i == 0xffff) { - ntfs_log_error("Too many hardlinks present already.\n"); - free(fn); - return -EINVAL; - } - m_file->link_count = cpu_to_le16(i + 1); - /* Add the file_name to @m_file. */ - i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0, 0, - 0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size); - if (i < 0) { - ntfs_log_error("create_hardlink failed adding file name attribute: " - "%s\n", strerror(-i)); - free(fn); - /* Undo link count increment. */ - m_file->link_count = cpu_to_le16( - le16_to_cpu(m_file->link_count) - 1); - return i; - } - /* Insert the index entry for file_name in @idx. */ - i = insert_file_link_in_dir_index(idx, ref_file, fn, fn_size); - if (i < 0) { - ntfs_log_error("create_hardlink failed inserting index entry: %s\n", - strerror(-i)); - /* FIXME: Remove the file name attribute from @m_file. */ - free(fn); - /* Undo link count increment. */ - m_file->link_count = cpu_to_le16( - le16_to_cpu(m_file->link_count) - 1); - return i; - } - free(fn); - return 0; -} - -#ifdef ENABLE_UUID - -/** - * index_obj_id_insert - * - * Insert an index entry with the key @guid and data pointing to the mft record - * @ref in the $O index root of the mft record @m (which must be the mft record - * for $ObjId). - * - * Return 0 on success or -errno on error. - */ -static int index_obj_id_insert(MFT_RECORD *m, const GUID *guid, - const leMFT_REF ref) -{ - INDEX_ENTRY *idx_entry_new; - int data_ofs, idx_size, err; - OBJ_ID_INDEX_DATA *oi; - - /* - * Insert the index entry for the object id in the index. - * - * First determine the size of the index entry to be inserted. This - * consists of the index entry header, followed by the index key, i.e. - * the GUID, followed by the index data, i.e. OBJ_ID_INDEX_DATA. - */ - data_ofs = (sizeof(INDEX_ENTRY_HEADER) + sizeof(GUID) + 7) & ~7; - idx_size = (data_ofs + sizeof(OBJ_ID_INDEX_DATA) + 7) & ~7; - idx_entry_new = ntfs_calloc(idx_size); - if (!idx_entry_new) - return -errno; - idx_entry_new->u.s.data_offset = cpu_to_le16(data_ofs); - idx_entry_new->u.s.data_length = cpu_to_le16(sizeof(OBJ_ID_INDEX_DATA)); - idx_entry_new->length = cpu_to_le16(idx_size); - idx_entry_new->key_length = cpu_to_le16(sizeof(GUID)); - idx_entry_new->key.object_id = *guid; - oi = (OBJ_ID_INDEX_DATA*)((u8*)idx_entry_new + data_ofs); - oi->mft_reference = ref; - err = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size, m, - NTFS_INDEX_O, 2, AT_UNUSED); - free(idx_entry_new); - if (err < 0) { - ntfs_log_error("index_obj_id_insert failed inserting index " - "entry: %s\n", strerror(-err)); - return err; - } - return 0; -} - -#endif - -/** - * mkntfs_cleanup - */ -static void mkntfs_cleanup(void) -{ - /* Close the volume */ - if (g_vol) { - if (g_vol->u.dev) { - if (NDevOpen(g_vol->u.dev) && g_vol->u.dev->d_ops->close(g_vol->u.dev)) - ntfs_log_perror("Warning: Could not close %s", g_vol->u.dev->d_name); - ntfs_device_free(g_vol->u.dev); - } - free(g_vol->vol_name); - free(g_vol->attrdef); - free(g_vol->upcase); - free(g_vol); - g_vol = NULL; - } - - /* Free any memory we've used */ - free(g_bad_blocks); g_bad_blocks = NULL; - free(g_buf); g_buf = NULL; - free(g_index_block); g_index_block = NULL; - free(g_lcn_bitmap); g_lcn_bitmap = NULL; - free(g_mft_bitmap); g_mft_bitmap = NULL; - free(g_rl_bad); g_rl_bad = NULL; - free(g_rl_boot); g_rl_boot = NULL; - free(g_rl_logfile); g_rl_logfile = NULL; - free(g_rl_mft); g_rl_mft = NULL; - free(g_rl_mft_bmp); g_rl_mft_bmp = NULL; - free(g_rl_mftmirr); g_rl_mftmirr = NULL; -} - - -/** - * mkntfs_open_partition - - */ -static BOOL mkntfs_open_partition(ntfs_volume *vol) -{ - BOOL result = FALSE; - int i; - struct stat sbuf; - unsigned long mnt_flags; - - /* - * Allocate and initialize an ntfs device structure and attach it to - * the volume. - */ - vol->u.dev = ntfs_device_alloc(opts.dev_name, 0, &ntfs_device_default_io_ops, NULL); - if (!vol->u.dev) { - ntfs_log_perror("Could not create device"); - goto done; - } - - /* Open the device for reading or reading and writing. */ - if (opts.no_action) { - ntfs_log_quiet("Running in READ-ONLY mode!\n"); - i = O_RDONLY; - } else { - i = O_RDWR; - } - if (vol->u.dev->d_ops->open(vol->u.dev, i)) { - if (errno == ENOENT) - ntfs_log_error("The device doesn't exist; did you specify it correctly?\n"); - else - ntfs_log_perror("Could not open %s", vol->u.dev->d_name); - goto done; - } - /* Verify we are dealing with a block device. */ - if (vol->u.dev->d_ops->stat(vol->u.dev, &sbuf)) { - ntfs_log_perror("Error getting information about %s", vol->u.dev->d_name); - goto done; - } - - if (!S_ISBLK(sbuf.st_mode)) { - ntfs_log_error("%s is not a block device.\n", vol->u.dev->d_name); - if (!opts.force) { - ntfs_log_error("Refusing to make a filesystem here!\n"); - goto done; - } - if (!opts.num_sectors) { - if (!sbuf.st_size && !sbuf.st_blocks) { - ntfs_log_error("You must specify the number of sectors.\n"); - goto done; - } - if (opts.sector_size) { - if (sbuf.st_size) - opts.num_sectors = sbuf.st_size / opts.sector_size; - else - opts.num_sectors = ((s64)sbuf.st_blocks << 9) / opts.sector_size; - } else { - if (sbuf.st_size) - opts.num_sectors = sbuf.st_size / 512; - else - opts.num_sectors = sbuf.st_blocks; - opts.sector_size = 512; - } - } - ntfs_log_warning("mkntfs forced anyway.\n"); -#ifdef HAVE_LINUX_MAJOR_H - } else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && - MINOR(sbuf.st_rdev) % 64 == 0) || - (SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && - MINOR(sbuf.st_rdev) % 16 == 0)) { - ntfs_log_error("%s is entire device, not just one partition.\n", vol->u.dev->d_name); - if (!opts.force) { - ntfs_log_error("Refusing to make a filesystem here!\n"); - goto done; - } - ntfs_log_warning("mkntfs forced anyway.\n"); -#endif - } - /* Make sure the file system is not mounted. */ - if (ntfs_check_if_mounted(vol->u.dev->d_name, &mnt_flags)) { - ntfs_log_perror("Failed to determine whether %s is mounted", vol->u.dev->d_name); - } else if (mnt_flags & NTFS_MF_MOUNTED) { - ntfs_log_error("%s is mounted.\n", vol->u.dev->d_name); - if (!opts.force) { - ntfs_log_error("Refusing to make a filesystem here!\n"); - goto done; - } - ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is incorrect.\n"); - } - result = TRUE; -done: - return result; -} - -/** - * mkntfs_get_page_size - detect the system's memory page size. - */ -static long mkntfs_get_page_size(void) -{ - long page_size; -#ifdef _SC_PAGESIZE - page_size = sysconf(_SC_PAGESIZE); - if (page_size < 0) -#endif -#ifdef _SC_PAGE_SIZE - page_size = sysconf(_SC_PAGE_SIZE); - if (page_size < 0) -#endif - { - ntfs_log_warning("Failed to determine system page size. " - "Assuming safe default of 4096 bytes.\n"); - return 4096; - } - ntfs_log_debug("System page size is %li bytes.\n", page_size); - return page_size; -} - -/** - * mkntfs_override_vol_params - - */ -static BOOL mkntfs_override_vol_params(ntfs_volume *vol) -{ - s64 volume_size; - long page_size; - int i; - BOOL winboot = TRUE; - - /* If user didn't specify the sector size, determine it now. */ - if (opts.sector_size < 0) { - opts.sector_size = ntfs_device_sector_size_get(vol->u.dev); - if (opts.sector_size < 0) { - ntfs_log_warning("The sector size was not specified " - "for %s and it could not be obtained " - "automatically. It has been set to 512 " - "bytes.\n", vol->u.dev->d_name); - opts.sector_size = 512; - } - } - /* Validate sector size. */ - if ((opts.sector_size - 1) & opts.sector_size) { - ntfs_log_error("The sector size is invalid. It must be a " - "power of two, e.g. 512, 1024.\n"); - return FALSE; - } - if (opts.sector_size < 256 || opts.sector_size > 4096) { - ntfs_log_error("The sector size is invalid. The minimum size " - "is 256 bytes and the maximum is 4096 bytes.\n"); - return FALSE; - } - ntfs_log_debug("sector size = %ld bytes\n", opts.sector_size); - /* Now set the device block size to the sector size. */ - if (ntfs_device_block_size_set(vol->u.dev, opts.sector_size)) - ntfs_log_debug("Failed to set the device block size to the " - "sector size. This may cause problems when " - "creating the backup boot sector and also may " - "affect performance but should be harmless " - "otherwise. Error: %s\n", strerror(errno)); - /* If user didn't specify the number of sectors, determine it now. */ - if (opts.num_sectors < 0) { - opts.num_sectors = ntfs_device_size_get(vol->u.dev, - opts.sector_size); - if (opts.num_sectors <= 0) { - ntfs_log_error("Couldn't determine the size of %s. " - "Please specify the number of sectors " - "manually.\n", vol->u.dev->d_name); - return FALSE; - } - } - ntfs_log_debug("number of sectors = %lld (0x%llx)\n", opts.num_sectors, - opts.num_sectors); - /* - * Reserve the last sector for the backup boot sector unless the - * sector size is less than 512 bytes in which case reserve 512 bytes - * worth of sectors. - */ - i = 1; - if (opts.sector_size < 512) - i = 512 / opts.sector_size; - opts.num_sectors -= i; - /* If user didn't specify the partition start sector, determine it. */ - if (opts.part_start_sect < 0) { - opts.part_start_sect = ntfs_device_partition_start_sector_get( - vol->u.dev); - if (opts.part_start_sect < 0) { - ntfs_log_warning("The partition start sector was not " - "specified for %s and it could not be obtained " - "automatically. It has been set to 0.\n", - vol->u.dev->d_name); - opts.part_start_sect = 0; - winboot = FALSE; - } else if (opts.part_start_sect >> 32) { - ntfs_log_warning("The partition start sector specified " - "for %s and the automatically determined value " - "is too large. It has been set to 0.\n", - vol->u.dev->d_name); - opts.part_start_sect = 0; - winboot = FALSE; - } - } else if (opts.part_start_sect >> 32) { - ntfs_log_error("Invalid partition start sector. Maximum is " - "4294967295 (2^32-1).\n"); - return FALSE; - } - /* If user didn't specify the sectors per track, determine it now. */ - if (opts.sectors_per_track < 0) { - opts.sectors_per_track = ntfs_device_sectors_per_track_get( - vol->u.dev); - if (opts.sectors_per_track < 0) { - ntfs_log_warning("The number of sectors per track was " - "not specified for %s and it could not be " - "obtained automatically. It has been set to " - "0.\n", vol->u.dev->d_name); - opts.sectors_per_track = 0; - winboot = FALSE; - } else if (opts.sectors_per_track > 65535) { - ntfs_log_warning("The number of sectors per track was " - "not specified for %s and the automatically " - "determined value is too large. It has been " - "set to 0.\n", vol->u.dev->d_name); - opts.sectors_per_track = 0; - winboot = FALSE; - } - } else if (opts.sectors_per_track > 65535) { - ntfs_log_error("Invalid number of sectors per track. Maximum " - "is 65535.\n"); - return FALSE; - } - /* If user didn't specify the number of heads, determine it now. */ - if (opts.heads < 0) { - opts.heads = ntfs_device_heads_get(vol->u.dev); - if (opts.heads < 0) { - ntfs_log_warning("The number of heads was not " - "specified for %s and it could not be obtained " - "automatically. It has been set to 0.\n", - vol->u.dev->d_name); - opts.heads = 0; - winboot = FALSE; - } else if (opts.heads > 65535) { - ntfs_log_warning("The number of heads was not " - "specified for %s and the automatically " - "determined value is too large. It has been " - "set to 0.\n", vol->u.dev->d_name); - opts.heads = 0; - winboot = FALSE; - } - } else if (opts.heads > 65535) { - ntfs_log_error("Invalid number of heads. Maximum is 65535.\n"); - return FALSE; - } - volume_size = opts.num_sectors * opts.sector_size; - /* Validate volume size. */ - if (volume_size < (1 << 20)) { /* 1MiB */ - ntfs_log_error("Device is too small (%llikiB). Minimum NTFS " - "volume size is 1MiB.\n", volume_size / 1024); - return FALSE; - } - ntfs_log_debug("volume size = %llikiB\n", volume_size / 1024); - /* If user didn't specify the cluster size, determine it now. */ - if (!vol->cluster_size) { - /* - * Windows Vista always uses 4096 bytes as the default cluster - * size regardless of the volume size so we do it, too. - */ - vol->cluster_size = 4096; - /* For small volumes on devices with large sector sizes. */ - if (vol->cluster_size < (u32)opts.sector_size) - vol->cluster_size = opts.sector_size; - /* - * For huge volumes, grow the cluster size until the number of - * clusters fits into 32 bits or the cluster size exceeds the - * maximum limit of 64kiB. - */ - while (volume_size >> (ffs(vol->cluster_size) - 1 + 32)) { - vol->cluster_size <<= 1; - if (vol->cluster_size > 65535) { - ntfs_log_error("Device is too large to hold an " - "NTFS volume (maximum size is " - "256TiB).\n"); - return FALSE; - } - } - ntfs_log_quiet("Cluster size has been automatically set to %u " - "bytes.\n", (unsigned)vol->cluster_size); - } - /* Validate cluster size. */ - if (vol->cluster_size & (vol->cluster_size - 1)) { - ntfs_log_error("The cluster size is invalid. It must be a " - "power of two, e.g. 1024, 4096.\n"); - return FALSE; - } - if (vol->cluster_size < (u32)opts.sector_size) { - ntfs_log_error("The cluster size is invalid. It must be equal " - "to, or larger than, the sector size.\n"); - return FALSE; - } - if (vol->cluster_size > 128 * (u32)opts.sector_size) { - ntfs_log_error("The cluster size is invalid. It cannot be " - "more that 128 times the size of the sector " - "size.\n"); - return FALSE; - } - if (vol->cluster_size > 65536) { - ntfs_log_error("The cluster size is invalid. The maximum " - "cluster size is 65536 bytes (64kiB).\n"); - return FALSE; - } - vol->cluster_size_bits = ffs(vol->cluster_size) - 1; - ntfs_log_debug("cluster size = %u bytes\n", - (unsigned int)vol->cluster_size); - if (vol->cluster_size > 4096) { - if (opts.enable_compression) { - if (!opts.force) { - ntfs_log_error("Windows cannot use compression " - "when the cluster size is " - "larger than 4096 bytes.\n"); - return FALSE; - } - opts.enable_compression = 0; - } - ntfs_log_warning("Windows cannot use compression when the " - "cluster size is larger than 4096 bytes. " - "Compression has been disabled for this " - "volume.\n"); - } - vol->nr_clusters = volume_size / vol->cluster_size; - /* - * Check the cluster_size and num_sectors for consistency with - * sector_size and num_sectors. And check both of these for consistency - * with volume_size. - */ - if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) / - vol->cluster_size) || - (volume_size / opts.sector_size) != opts.num_sectors || - (volume_size / vol->cluster_size) != - vol->nr_clusters)) { - /* XXX is this code reachable? */ - ntfs_log_error("Illegal combination of volume/cluster/sector " - "size and/or cluster/sector number.\n"); - return FALSE; - } - ntfs_log_debug("number of clusters = %llu (0x%llx)\n", - vol->nr_clusters, vol->nr_clusters); - /* Number of clusters must fit within 32 bits (Win2k limitation). */ - if (vol->nr_clusters >> 32) { - if (vol->cluster_size >= 65536) { - ntfs_log_error("Device is too large to hold an NTFS " - "volume (maximum size is 256TiB).\n"); - return FALSE; - } - ntfs_log_error("Number of clusters exceeds 32 bits. Please " - "try again with a larger\ncluster size or " - "leave the cluster size unspecified and the " - "smallest possible cluster size for the size " - "of the device will be used.\n"); - return FALSE; - } - page_size = mkntfs_get_page_size(); - /* - * Set the mft record size. By default this is 1024 but it has to be - * at least as big as a sector and not bigger than a page on the system - * or the NTFS kernel driver will not be able to mount the volume. - * TODO: The mft record size should be user specifiable just like the - * "inode size" can be specified on other Linux/Unix file systems. - */ - vol->mft_record_size = 1024; - if (vol->mft_record_size < (u32)opts.sector_size) - vol->mft_record_size = opts.sector_size; - if (vol->mft_record_size > (unsigned long)page_size) - ntfs_log_warning("Mft record size (%u bytes) exceeds system " - "page size (%li bytes). You will not be able " - "to mount this volume using the NTFS kernel " - "driver.\n", (unsigned)vol->mft_record_size, - page_size); - vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; - ntfs_log_debug("mft record size = %u bytes\n", - (unsigned)vol->mft_record_size); - /* - * Set the index record size. By default this is 4096 but it has to be - * at least as big as a sector and not bigger than a page on the system - * or the NTFS kernel driver will not be able to mount the volume. - * FIXME: Should we make the index record size to be user specifiable? - */ - vol->indx_record_size = 4096; - if (vol->indx_record_size < (u32)opts.sector_size) - vol->indx_record_size = opts.sector_size; - if (vol->indx_record_size > (unsigned long)page_size) - ntfs_log_warning("Index record size (%u bytes) exceeds system " - "page size (%li bytes). You will not be able " - "to mount this volume using the NTFS kernel " - "driver.\n", (unsigned)vol->indx_record_size, - page_size); - vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1; - ntfs_log_debug("index record size = %u bytes\n", - (unsigned)vol->indx_record_size); - if (!winboot) { - ntfs_log_warning("To boot from a device, Windows needs the " - "'partition start sector', the 'sectors per " - "track' and the 'number of heads' to be " - "set.\n"); - ntfs_log_warning("Windows will not be able to boot from this " - "device.\n"); - } - return TRUE; -} - -/** - * mkntfs_initialize_bitmaps - - */ -static BOOL mkntfs_initialize_bitmaps(void) -{ - u64 i; - int mft_bitmap_size; - - /* Determine lcn bitmap byte size and allocate it. */ - g_lcn_bitmap_byte_size = (g_vol->nr_clusters + 7) >> 3; - /* Needs to be multiple of 8 bytes. */ - g_lcn_bitmap_byte_size = (g_lcn_bitmap_byte_size + 7) & ~7; - i = (g_lcn_bitmap_byte_size + g_vol->cluster_size - 1) & - ~(g_vol->cluster_size - 1); - ntfs_log_debug("g_lcn_bitmap_byte_size = %i, allocated = %llu\n", - g_lcn_bitmap_byte_size, i); - g_lcn_bitmap = ntfs_calloc(g_lcn_bitmap_byte_size); - if (!g_lcn_bitmap) - return FALSE; - /* - * $Bitmap can overlap the end of the volume. Any bits in this region - * must be set. This region also encompasses the backup boot sector. - */ - for (i = g_vol->nr_clusters; i < (u64)g_lcn_bitmap_byte_size << 3; i++) - ntfs_bit_set(g_lcn_bitmap, i, 1); - /* - * Mft size is 27 (NTFS 3.0+) mft records or one cluster, whichever is - * bigger. - */ - g_mft_size = 27; - g_mft_size *= g_vol->mft_record_size; - if (g_mft_size < (s32)g_vol->cluster_size) - g_mft_size = g_vol->cluster_size; - ntfs_log_debug("MFT size = %i (0x%x) bytes\n", g_mft_size, g_mft_size); - /* Determine mft bitmap size and allocate it. */ - mft_bitmap_size = g_mft_size / g_vol->mft_record_size; - /* Convert to bytes, at least one. */ - g_mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3; - /* Mft bitmap is allocated in multiples of 8 bytes. */ - g_mft_bitmap_byte_size = (g_mft_bitmap_byte_size + 7) & ~7; - ntfs_log_debug("mft_bitmap_size = %i, g_mft_bitmap_byte_size = %i\n", - mft_bitmap_size, g_mft_bitmap_byte_size); - g_mft_bitmap = ntfs_calloc(g_mft_bitmap_byte_size); - if (!g_mft_bitmap) - return FALSE; - /* Create runlist for mft bitmap. */ - g_rl_mft_bmp = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_mft_bmp) - return FALSE; - - g_rl_mft_bmp[0].vcn = 0LL; - /* Mft bitmap is right after $Boot's data. */ - i = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size; - g_rl_mft_bmp[0].lcn = i; - /* - * Size is always one cluster, even though valid data size and - * initialized data size are only 8 bytes. - */ - g_rl_mft_bmp[1].vcn = 1LL; - g_rl_mft_bmp[0].length = 1LL; - g_rl_mft_bmp[1].lcn = -1LL; - g_rl_mft_bmp[1].length = 0LL; - /* Allocate cluster for mft bitmap. */ - ntfs_bit_set(g_lcn_bitmap, i, 1); - return TRUE; -} - -/** - * mkntfs_initialize_rl_mft - - */ -static BOOL mkntfs_initialize_rl_mft(void) -{ - int i, j; - - /* If user didn't specify the mft lcn, determine it now. */ - if (!g_mft_lcn) { - /* - * We start at the higher value out of 16kiB and just after the - * mft bitmap. - */ - g_mft_lcn = g_rl_mft_bmp[0].lcn + g_rl_mft_bmp[0].length; - if (g_mft_lcn * g_vol->cluster_size < 16 * 1024) - g_mft_lcn = (16 * 1024 + g_vol->cluster_size - 1) / - g_vol->cluster_size; - } - ntfs_log_debug("$MFT logical cluster number = 0x%llx\n", g_mft_lcn); - /* Determine MFT zone size. */ - g_mft_zone_end = g_vol->nr_clusters; - switch (opts.mft_zone_multiplier) { /* % of volume size in clusters */ - case 4: - g_mft_zone_end = g_mft_zone_end >> 1; /* 50% */ - break; - case 3: - g_mft_zone_end = g_mft_zone_end * 3 >> 3;/* 37.5% */ - break; - case 2: - g_mft_zone_end = g_mft_zone_end >> 2; /* 25% */ - break; - case 1: - default: - g_mft_zone_end = g_mft_zone_end >> 3; /* 12.5% */ - break; - } - ntfs_log_debug("MFT zone size = %lldkiB\n", g_mft_zone_end << - g_vol->cluster_size_bits >> 10 /* >> 10 == / 1024 */); - /* - * The mft zone begins with the mft data attribute, not at the beginning - * of the device. - */ - g_mft_zone_end += g_mft_lcn; - /* Create runlist for mft. */ - g_rl_mft = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_mft) - return FALSE; - - g_rl_mft[0].vcn = 0LL; - g_rl_mft[0].lcn = g_mft_lcn; - /* rounded up division by cluster size */ - j = (g_mft_size + g_vol->cluster_size - 1) / g_vol->cluster_size; - g_rl_mft[1].vcn = j; - g_rl_mft[0].length = j; - g_rl_mft[1].lcn = -1LL; - g_rl_mft[1].length = 0LL; - /* Allocate clusters for mft. */ - for (i = 0; i < j; i++) - ntfs_bit_set(g_lcn_bitmap, g_mft_lcn + i, 1); - /* Determine mftmirr_lcn (middle of volume). */ - g_mftmirr_lcn = (opts.num_sectors * opts.sector_size >> 1) - / g_vol->cluster_size; - ntfs_log_debug("$MFTMirr logical cluster number = 0x%llx\n", - g_mftmirr_lcn); - /* Create runlist for mft mirror. */ - g_rl_mftmirr = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_mftmirr) - return FALSE; - - g_rl_mftmirr[0].vcn = 0LL; - g_rl_mftmirr[0].lcn = g_mftmirr_lcn; - /* - * The mft mirror is either 4kb (the first four records) or one cluster - * in size, which ever is bigger. In either case, it contains a - * byte-for-byte identical copy of the beginning of the mft (i.e. either - * the first four records (4kb) or the first cluster worth of records, - * whichever is bigger). - */ - j = (4 * g_vol->mft_record_size + g_vol->cluster_size - 1) / g_vol->cluster_size; - g_rl_mftmirr[1].vcn = j; - g_rl_mftmirr[0].length = j; - g_rl_mftmirr[1].lcn = -1LL; - g_rl_mftmirr[1].length = 0LL; - /* Allocate clusters for mft mirror. */ - for (i = 0; i < j; i++) - ntfs_bit_set(g_lcn_bitmap, g_mftmirr_lcn + i, 1); - g_logfile_lcn = g_mftmirr_lcn + j; - ntfs_log_debug("$LogFile logical cluster number = 0x%llx\n", - g_logfile_lcn); - return TRUE; -} - -/** - * mkntfs_initialize_rl_logfile - - */ -static BOOL mkntfs_initialize_rl_logfile(void) -{ - int i, j; - u64 volume_size; - - /* Create runlist for log file. */ - g_rl_logfile = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_logfile) - return FALSE; - - - volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits; - - g_rl_logfile[0].vcn = 0LL; - g_rl_logfile[0].lcn = g_logfile_lcn; - /* - * Determine logfile_size from volume_size (rounded up to a cluster), - * making sure it does not overflow the end of the volume. - */ - if (volume_size < 2048LL * 1024) /* < 2MiB */ - g_logfile_size = 256LL * 1024; /* -> 256kiB */ - else if (volume_size < 4000000LL) /* < 4MB */ - g_logfile_size = 512LL * 1024; /* -> 512kiB */ - else if (volume_size <= 200LL * 1024 * 1024) /* < 200MiB */ - g_logfile_size = 2048LL * 1024; /* -> 2MiB */ - else { - /* - * FIXME: The $LogFile size is 64 MiB upwards from 12GiB but - * the "200" divider below apparently approximates "100" or - * some other value as the volume size decreases. For example: - * Volume size LogFile size Ratio - * 8799808 46048 191.100 - * 8603248 45072 190.877 - * 7341704 38768 189.375 - * 6144828 32784 187.433 - * 4192932 23024 182.111 - */ - if (volume_size >= 12LL << 30) /* > 12GiB */ - g_logfile_size = 64 << 20; /* -> 64MiB */ - else - g_logfile_size = (volume_size / 200) & - ~(g_vol->cluster_size - 1); - } - j = g_logfile_size / g_vol->cluster_size; - while (g_rl_logfile[0].lcn + j >= g_vol->nr_clusters) { - /* - * $Logfile would overflow volume. Need to make it smaller than - * the standard size. It's ok as we are creating a non-standard - * volume anyway if it is that small. - */ - g_logfile_size >>= 1; - j = g_logfile_size / g_vol->cluster_size; - } - g_logfile_size = (g_logfile_size + g_vol->cluster_size - 1) & - ~(g_vol->cluster_size - 1); - ntfs_log_debug("$LogFile (journal) size = %ikiB\n", - g_logfile_size / 1024); - /* - * FIXME: The 256kiB limit is arbitrary. Should find out what the real - * minimum requirement for Windows is so it doesn't blue screen. - */ - if (g_logfile_size < 256 << 10) { - ntfs_log_error("$LogFile would be created with invalid size. " - "This is not allowed as it would cause Windows " - "to blue screen and during boot.\n"); - return FALSE; - } - g_rl_logfile[1].vcn = j; - g_rl_logfile[0].length = j; - g_rl_logfile[1].lcn = -1LL; - g_rl_logfile[1].length = 0LL; - /* Allocate clusters for log file. */ - for (i = 0; i < j; i++) - ntfs_bit_set(g_lcn_bitmap, g_logfile_lcn + i, 1); - return TRUE; -} - -/** - * mkntfs_initialize_rl_boot - - */ -static BOOL mkntfs_initialize_rl_boot(void) -{ - int i, j; - /* Create runlist for $Boot. */ - g_rl_boot = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_boot) - return FALSE; - - g_rl_boot[0].vcn = 0LL; - g_rl_boot[0].lcn = 0LL; - /* - * $Boot is always 8192 (0x2000) bytes or 1 cluster, whichever is - * bigger. - */ - j = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size; - g_rl_boot[1].vcn = j; - g_rl_boot[0].length = j; - g_rl_boot[1].lcn = -1LL; - g_rl_boot[1].length = 0LL; - /* Allocate clusters for $Boot. */ - for (i = 0; i < j; i++) - ntfs_bit_set(g_lcn_bitmap, 0LL + i, 1); - return TRUE; -} - -/** - * mkntfs_initialize_rl_bad - - */ -static BOOL mkntfs_initialize_rl_bad(void) -{ - /* Create runlist for $BadClus, $DATA named stream $Bad. */ - g_rl_bad = ntfs_malloc(2 * sizeof(runlist)); - if (!g_rl_bad) - return FALSE; - - g_rl_bad[0].vcn = 0LL; - g_rl_bad[0].lcn = -1LL; - /* - * $BadClus named stream $Bad contains the whole volume as a single - * sparse runlist entry. - */ - g_rl_bad[1].vcn = g_vol->nr_clusters; - g_rl_bad[0].length = g_vol->nr_clusters; - g_rl_bad[1].lcn = -1LL; - g_rl_bad[1].length = 0LL; - - /* TODO: Mark bad blocks as such. */ - return TRUE; -} - -/** - * mkntfs_fill_device_with_zeroes - - */ -static BOOL mkntfs_fill_device_with_zeroes(void) -{ - /* - * If not quick format, fill the device with 0s. - * FIXME: Except bad blocks! (AIA) - */ - int i; - ssize_t bw; - unsigned long long position; - float progress_inc = (float)g_vol->nr_clusters / 100; - u64 volume_size; - - volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits; - - ntfs_log_progress("Initializing device with zeroes: 0%%"); - for (position = 0; position < (unsigned long long)g_vol->nr_clusters; - position++) { - if (!(position % (int)(progress_inc+1))) { - ntfs_log_progress("\b\b\b\b%3.0f%%", position / - progress_inc); - } - bw = mkntfs_write(g_vol->u.dev, g_buf, g_vol->cluster_size); - if (bw != (ssize_t)g_vol->cluster_size) { - if (bw != -1 || errno != EIO) { - ntfs_log_error("This should not happen.\n"); - return FALSE; - } - if (!position) { - ntfs_log_error("Error: Cluster zero is bad. " - "Cannot create NTFS file " - "system.\n"); - return FALSE; - } - /* Add the baddie to our bad blocks list. */ - if (!append_to_bad_blocks(position)) - return FALSE; - ntfs_log_quiet("\nFound bad cluster (%lld). Adding to " - "list of bad blocks.\nInitializing " - "device with zeroes: %3.0f%%", position, - position / progress_inc); - /* Seek to next cluster. */ - g_vol->u.dev->d_ops->seek(g_vol->u.dev, - ((off_t)position + 1) * - g_vol->cluster_size, SEEK_SET); - } - } - ntfs_log_progress("\b\b\b\b100%%"); - position = (volume_size & (g_vol->cluster_size - 1)) / - opts.sector_size; - for (i = 0; (unsigned long)i < position; i++) { - bw = mkntfs_write(g_vol->u.dev, g_buf, opts.sector_size); - if (bw != opts.sector_size) { - if (bw != -1 || errno != EIO) { - ntfs_log_error("This should not happen.\n"); - return FALSE; - } else if (i + 1ull == position) { - ntfs_log_error("Error: Bad cluster found in " - "location reserved for system " - "file $Boot.\n"); - return FALSE; - } - /* Seek to next sector. */ - g_vol->u.dev->d_ops->seek(g_vol->u.dev, - opts.sector_size, SEEK_CUR); - } - } - ntfs_log_progress(" - Done.\n"); - return TRUE; -} - -/** - * mkntfs_sync_index_record - * - * (ERSO) made a function out of this, but the reason for doing that - * disappeared during coding.... - */ -static BOOL mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m, - ntfschar* name, u32 name_len) -{ - int i, err; - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - long long lw; - runlist *rl_index = NULL; - - i = 5 * sizeof(ntfschar); - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_perror("Failed to allocate attribute search context"); - return FALSE; - } - /* FIXME: This should be IGNORE_CASE! */ - if (mkntfs_attr_lookup(AT_INDEX_ALLOCATION, name, name_len, 0, 0, - NULL, 0, ctx)) { - ntfs_attr_put_search_ctx(ctx); - ntfs_log_error("BUG: $INDEX_ALLOCATION attribute not found.\n"); - return FALSE; - } - a = ctx->attr; - rl_index = ntfs_mapping_pairs_decompress(g_vol, a, NULL); - if (!rl_index) { - ntfs_attr_put_search_ctx(ctx); - ntfs_log_error("Failed to decompress runlist of $INDEX_ALLOCATION " - "attribute.\n"); - return FALSE; - } - if (sle64_to_cpu(a->u.nonres.initialized_size) < i) { - ntfs_attr_put_search_ctx(ctx); - free(rl_index); - ntfs_log_error("BUG: $INDEX_ALLOCATION attribute too short.\n"); - return FALSE; - } - ntfs_attr_put_search_ctx(ctx); - i = sizeof(INDEX_BLOCK) - sizeof(INDEX_HEADER) + - le32_to_cpu(idx->index.allocated_size); - err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)idx, i); - if (err) { - free(rl_index); - ntfs_log_error("ntfs_mst_pre_write_fixup() failed while " - "syncing index block.\n"); - return FALSE; - } - lw = ntfs_rlwrite(g_vol->u.dev, rl_index, (u8*)idx, i, NULL); - free(rl_index); - if (lw != i) { - ntfs_log_error("Error writing $INDEX_ALLOCATION.\n"); - return FALSE; - } - /* No more changes to @idx below here so no need for fixup: */ - /* ntfs_mst_post_write_fixup((NTFS_RECORD*)idx); */ - return TRUE; -} - -/** - * create_file_volume - - */ -static BOOL create_file_volume(MFT_RECORD *m, leMFT_REF root_ref, - VOLUME_FLAGS fl, const GUID *volume_guid -#ifndef ENABLE_UUID - __attribute__((unused)) -#endif - ) -{ - int i, err; - u8 *sd; - - ntfs_log_verbose("Creating $Volume (mft record 3)\n"); - m = (MFT_RECORD*)(g_buf + 3 * g_vol->mft_record_size); - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$Volume", FILE_NAME_WIN32_AND_DOS); - if (!err) { - init_system_file_sd(FILE_Volume, &sd, &i); - err = add_attr_sd(m, sd, i); - } - if (!err) - err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0); - if (!err) - err = add_attr_vol_name(m, g_vol->vol_name, g_vol->vol_name ? - strlen(g_vol->vol_name) : 0); - if (!err) { - if (fl & VOLUME_IS_DIRTY) - ntfs_log_quiet("Setting the volume dirty so check " - "disk runs on next reboot into " - "Windows.\n"); - err = add_attr_vol_info(m, fl, g_vol->major_ver, - g_vol->minor_ver); - } -#ifdef ENABLE_UUID - if (!err) - err = add_attr_object_id(m, volume_guid); -#endif - if (err < 0) { - ntfs_log_error("Couldn't create $Volume: %s\n", - strerror(-err)); - return FALSE; - } - return TRUE; -} - -/** - * create_backup_boot_sector - * - * Return 0 on success or -1 if it couldn't be created. - */ -static int create_backup_boot_sector(u8 *buff) -{ - const char *s; - ssize_t bw; - int size, e; - - ntfs_log_verbose("Creating backup boot sector.\n"); - /* - * Write the first max(512, opts.sector_size) bytes from buf to the - * last sector, but limit that to 8192 bytes of written data since that - * is how big $Boot is (and how big our buffer is).. - */ - size = 512; - if (size < opts.sector_size) - size = opts.sector_size; - if (size < opts.cluster_size) - size = opts.cluster_size; - if (g_vol->u.dev->d_ops->seek(g_vol->u.dev, (opts.num_sectors + 1) * - opts.sector_size - size, SEEK_SET) == (off_t)-1) { - ntfs_log_perror("Seek failed"); - goto bb_err; - } - if (size > 8192) - size = 8192; - bw = mkntfs_write(g_vol->u.dev, buff, size); - if (bw == size) - return 0; - e = errno; - if (bw == -1LL) - s = strerror(e); - else - s = "unknown error"; - /* At least some 2.4 kernels return EIO instead of ENOSPC. */ - if (bw != -1LL || (bw == -1LL && e != ENOSPC && e != EIO)) { - ntfs_log_critical("Couldn't write backup boot sector: %s\n", s); - return -1; - } -bb_err: - ntfs_log_error("Couldn't write backup boot sector. This is due to a " - "limitation in the\nLinux kernel. This is not a major " - "problem as Windows check disk will create the\n" - "backup boot sector when it is run on your next boot " - "into Windows.\n"); - return -1; -} - -/** - * mkntfs_create_root_structures - - */ -static BOOL mkntfs_create_root_structures(void) -{ - NTFS_BOOT_SECTOR *bs; - MFT_RECORD *m; - leMFT_REF root_ref; - leMFT_REF extend_ref; - int i; - int j; - int err; - u8 *sd; - FILE_ATTR_FLAGS extend_flags; - VOLUME_FLAGS volume_flags = 0; - int nr_sysfiles; - u8 *buf_log = NULL; - int buf_sds_first_size; - char *buf_sds; - - ntfs_log_quiet("Creating NTFS volume structures.\n"); - nr_sysfiles = 27; - /* - * Setup an empty mft record. Note, we can just give 0 as the mft - * reference as we are creating an NTFS 1.2 volume for which the mft - * reference is ignored by ntfs_mft_record_layout(). - * - * Copy the mft record onto all 16 records in the buffer and setup the - * sequence numbers of each system file to equal the mft record number - * of that file (only for $MFT is the sequence number 1 rather than 0). - */ - for (i = 0; i < nr_sysfiles; i++) { - if (ntfs_mft_record_layout(g_vol, 0, m = (MFT_RECORD *)(g_buf + - i * g_vol->mft_record_size))) { - ntfs_log_error("Failed to layout system mft records." - "\n"); - return FALSE; - } - if (i == 0 || i > 23) - m->sequence_number = cpu_to_le16(1); - else - m->sequence_number = cpu_to_le16(i); - } - /* - * If only one cluster contains all system files then - * fill the rest of it with empty, formatted records. - */ - if (nr_sysfiles * (s32)g_vol->mft_record_size < g_mft_size) { - for (i = nr_sysfiles; - i * (s32)g_vol->mft_record_size < g_mft_size; i++) { - m = (MFT_RECORD *)(g_buf + i * g_vol->mft_record_size); - if (ntfs_mft_record_layout(g_vol, 0, m)) { - ntfs_log_error("Failed to layout mft record." - "\n"); - return FALSE; - } - m->flags = cpu_to_le16(0); - m->sequence_number = cpu_to_le16(i); - } - } - /* - * Create the 16 system files, adding the system information attribute - * to each as well as marking them in use in the mft bitmap. - */ - for (i = 0; i < nr_sysfiles; i++) { - le32 file_attrs; - - m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size); - if (i < 16 || i > 23) { - m->mft_record_number = cpu_to_le32(i); - m->flags |= MFT_RECORD_IN_USE; - ntfs_bit_set(g_mft_bitmap, 0LL + i, 1); - } - file_attrs = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM; - if (i == FILE_root) { - file_attrs |= FILE_ATTR_ARCHIVE; - if (opts.disable_indexing) - file_attrs |= FILE_ATTR_NOT_CONTENT_INDEXED; - if (opts.enable_compression) - file_attrs |= FILE_ATTR_COMPRESSED; - } - /* setting specific security_id flag and */ - /* file permissions for ntfs 3.x */ - if (i == 0 || i == 1 || i == 2 || i == 6 || i == 8 || - i == 10) { - add_attr_std_info(m, file_attrs, - cpu_to_le32(0x0100)); - } else if (i == 9) { - file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT; - add_attr_std_info(m, file_attrs, - cpu_to_le32(0x0101)); - } else if (i == 11) { - add_attr_std_info(m, file_attrs, - cpu_to_le32(0x0101)); - } else if (i == 24 || i == 25 || i == 26) { - file_attrs |= FILE_ATTR_ARCHIVE; - file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT; - add_attr_std_info(m, file_attrs, - cpu_to_le32(0x0101)); - } else { - add_attr_std_info(m, file_attrs, - cpu_to_le32(0x00)); - } - } - /* The root directory mft reference. */ - root_ref = MK_LE_MREF(FILE_root, FILE_root); - extend_ref = MK_LE_MREF(11,11); - ntfs_log_verbose("Creating root directory (mft record 5)\n"); - m = (MFT_RECORD*)(g_buf + 5 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_DIRECTORY; - m->link_count = cpu_to_le16(le16_to_cpu(m->link_count) + 1); - err = add_attr_file_name(m, root_ref, 0LL, 0LL, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM | - FILE_ATTR_I30_INDEX_PRESENT, 0, 0, ".", - FILE_NAME_WIN32_AND_DOS); - if (!err) { - init_root_sd(&sd, &i); - err = add_attr_sd(m, sd, i); - } - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$I30", 4, 0, AT_FILE_NAME, - COLLATION_FILE_NAME, g_vol->indx_record_size); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = upgrade_to_large_index(m, "$I30", 4, 0, &g_index_block); - if (!err) { - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_perror("Failed to allocate attribute search " - "context"); - return FALSE; - } - /* There is exactly one file name so this is ok. */ - if (mkntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, - 0, ctx)) { - ntfs_attr_put_search_ctx(ctx); - ntfs_log_error("BUG: $FILE_NAME attribute not found." - "\n"); - return FALSE; - } - a = ctx->attr; - err = insert_file_link_in_dir_index(g_index_block, root_ref, - (FILE_NAME_ATTR*)((char*)a + - le16_to_cpu(a->u.res.value_offset)), - le32_to_cpu(a->u.res.value_length)); - ntfs_attr_put_search_ctx(ctx); - } - if (err) { - ntfs_log_error("Couldn't create root directory: %s\n", - strerror(-err)); - return FALSE; - } - /* Add all other attributes, on a per-file basis for clarity. */ - ntfs_log_verbose("Creating $MFT (mft record 0)\n"); - m = (MFT_RECORD*)g_buf; - err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_mft, g_buf, - g_mft_size); - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_MFT, 1), g_mft_size, - g_mft_size, FILE_ATTR_HIDDEN | - FILE_ATTR_SYSTEM, 0, 0, "$MFT", - FILE_NAME_WIN32_AND_DOS); - /* mft_bitmap is not modified in mkntfs; no need to sync it later. */ - if (!err) - err = add_attr_bitmap_positioned(m, NULL, 0, 0, g_rl_mft_bmp, - g_mft_bitmap, g_mft_bitmap_byte_size); - if (err < 0) { - ntfs_log_error("Couldn't create $MFT: %s\n", strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $MFTMirr (mft record 1)\n"); - m = (MFT_RECORD*)(g_buf + 1 * g_vol->mft_record_size); - err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_mftmirr, g_buf, - g_rl_mftmirr[0].length * g_vol->cluster_size); - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_MFTMirr, FILE_MFTMirr), - g_rl_mftmirr[0].length * g_vol->cluster_size, - g_rl_mftmirr[0].length * g_vol->cluster_size, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$MFTMirr", FILE_NAME_WIN32_AND_DOS); - if (err < 0) { - ntfs_log_error("Couldn't create $MFTMirr: %s\n", - strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $LogFile (mft record 2)\n"); - m = (MFT_RECORD*)(g_buf + 2 * g_vol->mft_record_size); - buf_log = ntfs_malloc(g_logfile_size); - if (!buf_log) - return FALSE; - memset(buf_log, -1, g_logfile_size); - err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_logfile, buf_log, - g_logfile_size); - free(buf_log); - buf_log = NULL; - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_LogFile, FILE_LogFile), - g_logfile_size, g_logfile_size, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$LogFile", FILE_NAME_WIN32_AND_DOS); - if (err < 0) { - ntfs_log_error("Couldn't create $LogFile: %s\n", - strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $AttrDef (mft record 4)\n"); - m = (MFT_RECORD*)(g_buf + 4 * g_vol->mft_record_size); - err = add_attr_data(m, NULL, 0, 0, 0, (u8*)g_vol->attrdef, - g_vol->attrdef_len); - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_AttrDef, FILE_AttrDef), - (g_vol->attrdef_len + g_vol->cluster_size - 1) & - ~(g_vol->cluster_size - 1), g_vol->attrdef_len, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$AttrDef", FILE_NAME_WIN32_AND_DOS); - if (!err) { - init_system_file_sd(FILE_AttrDef, &sd, &i); - err = add_attr_sd(m, sd, i); - } - if (err < 0) { - ntfs_log_error("Couldn't create $AttrDef: %s\n", - strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $Bitmap (mft record 6)\n"); - m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size); - /* the data attribute of $Bitmap must be non-resident or otherwise */ - /* windows 2003 will regard the volume as corrupt (ERSO) */ - if (!err) - err = insert_non_resident_attr_in_mft_record(m, - AT_DATA, NULL, 0, 0, 0, - g_lcn_bitmap, g_lcn_bitmap_byte_size); - - - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_Bitmap, FILE_Bitmap), - (g_lcn_bitmap_byte_size + g_vol->cluster_size - - 1) & ~(g_vol->cluster_size - 1), - g_lcn_bitmap_byte_size, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$Bitmap", FILE_NAME_WIN32_AND_DOS); - if (err < 0) { - ntfs_log_error("Couldn't create $Bitmap: %s\n", strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $Boot (mft record 7)\n"); - m = (MFT_RECORD*)(g_buf + 7 * g_vol->mft_record_size); - bs = ntfs_calloc(8192); - if (!bs) - return FALSE; - memcpy(bs, boot_array, sizeof(boot_array)); - /* - * Create the boot sector in bs. Note, that bs is already zeroed - * in the boot sector section and that it has the NTFS OEM id/magic - * already inserted, so no need to worry about these things. - */ - bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size); - bs->bpb.sectors_per_cluster = (u8)(g_vol->cluster_size / - opts.sector_size); - bs->bpb.media_type = 0xf8; /* hard disk */ - bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track); - ntfs_log_debug("sectors per track = %ld (0x%lx)\n", - opts.sectors_per_track, opts.sectors_per_track); - bs->bpb.heads = cpu_to_le16(opts.heads); - ntfs_log_debug("heads = %ld (0x%lx)\n", opts.heads, opts.heads); - bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect); - ntfs_log_debug("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect, - opts.part_start_sect); - bs->physical_drive = 0x80; /* boot from hard disk */ - bs->extended_boot_signature = 0x80; /* everybody sets this, so we do */ - bs->number_of_sectors = cpu_to_sle64(opts.num_sectors); - bs->mft_lcn = cpu_to_sle64(g_mft_lcn); - bs->mftmirr_lcn = cpu_to_sle64(g_mftmirr_lcn); - if (g_vol->mft_record_size >= g_vol->cluster_size) { - bs->clusters_per_mft_record = g_vol->mft_record_size / - g_vol->cluster_size; - } else { - bs->clusters_per_mft_record = -(ffs(g_vol->mft_record_size) - - 1); - if ((u32)(1 << -bs->clusters_per_mft_record) != - g_vol->mft_record_size) { - free(bs); - ntfs_log_error("BUG: calculated clusters_per_mft_record" - " is wrong (= 0x%x)\n", - bs->clusters_per_mft_record); - return FALSE; - } - } - ntfs_log_debug("clusters per mft record = %i (0x%x)\n", - bs->clusters_per_mft_record, - bs->clusters_per_mft_record); - if (g_vol->indx_record_size >= g_vol->cluster_size) { - bs->clusters_per_index_record = g_vol->indx_record_size / - g_vol->cluster_size; - } else { - bs->clusters_per_index_record = -g_vol->indx_record_size_bits; - if ((1 << -bs->clusters_per_index_record) != - (s32)g_vol->indx_record_size) { - free(bs); - ntfs_log_error("BUG: calculated " - "clusters_per_index_record is wrong " - "(= 0x%x)\n", - bs->clusters_per_index_record); - return FALSE; - } - } - ntfs_log_debug("clusters per index block = %i (0x%x)\n", - bs->clusters_per_index_record, - bs->clusters_per_index_record); - /* Generate a 64-bit random number for the serial number. */ - bs->volume_serial_number = cpu_to_le64(((u64)random() << 32) | - ((u64)random() & 0xffffffff)); - /* - * Leave zero for now as NT4 leaves it zero, too. If want it later, see - * ../libntfs/bootsect.c for how to calculate it. - */ - bs->checksum = cpu_to_le32(0); - /* Make sure the bootsector is ok. */ - if (!ntfs_boot_sector_is_ntfs(bs, TRUE)) { - free(bs); - ntfs_log_error("FATAL: Generated boot sector is invalid!\n"); - return FALSE; - } - err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_boot, (u8*)bs, - 8192); - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_Boot, FILE_Boot), - (8192 + g_vol->cluster_size - 1) & - ~(g_vol->cluster_size - 1), 8192, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$Boot", FILE_NAME_WIN32_AND_DOS); - if (!err) { - init_system_file_sd(FILE_Boot, &sd, &i); - err = add_attr_sd(m, sd, i); - } - if (err < 0) { - free(bs); - ntfs_log_error("Couldn't create $Boot: %s\n", strerror(-err)); - return FALSE; - } - if (create_backup_boot_sector((u8*)bs)) { - /* - * Pre-2.6 kernels couldn't access the last sector if it was - * odd and we failed to set the device block size to the sector - * size, hence we schedule chkdsk to create it. - */ - volume_flags |= VOLUME_IS_DIRTY; - } - free(bs); -#ifdef ENABLE_UUID - /* - * We cheat a little here and if the user has requested all times to be - * set to zero then we set the GUID to zero as well. This options is - * only used for development purposes so that should be fine. - */ - if (!opts.use_epoch_time) { - /* Generate a GUID for the volume. */ - uuid_generate((void*)&g_vol->guid); - } else - memset(&g_vol->guid, 0, sizeof(g_vol->guid)); -#endif - if (!create_file_volume(m, root_ref, volume_flags, &g_vol->guid)) - return FALSE; - ntfs_log_verbose("Creating $BadClus (mft record 8)\n"); - m = (MFT_RECORD*)(g_buf + 8 * g_vol->mft_record_size); - /* FIXME: This should be IGNORE_CASE */ - /* Create a sparse named stream of size equal to the volume size. */ - err = add_attr_data_positioned(m, "$Bad", 4, 0, 0, g_rl_bad, NULL, - g_vol->nr_clusters * g_vol->cluster_size); - if (!err) { - err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0); - } - if (!err) { - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_BadClus, FILE_BadClus), - 0LL, 0LL, FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, - 0, 0, "$BadClus", FILE_NAME_WIN32_AND_DOS); - } - if (err < 0) { - ntfs_log_error("Couldn't create $BadClus: %s\n", - strerror(-err)); - return FALSE; - } - /* create $Secure (NTFS 3.0+) */ - ntfs_log_verbose("Creating $Secure (mft record 9)\n"); - m = (MFT_RECORD*)(g_buf + 9 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_VIEW_INDEX; - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(9, 9), 0LL, 0LL, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM | - FILE_ATTR_VIEW_INDEX_PRESENT, 0, 0, - "$Secure", FILE_NAME_WIN32_AND_DOS); - buf_sds = NULL; - buf_sds_first_size = 0; - if (!err) { - int buf_sds_size; - - buf_sds_first_size = 0xfc; - buf_sds_size = 0x40000 + buf_sds_first_size; - buf_sds = ntfs_calloc(buf_sds_size); - if (!buf_sds) - return FALSE; - init_secure_sds(buf_sds); - memcpy(buf_sds + 0x40000, buf_sds, buf_sds_first_size); - err = add_attr_data(m, "$SDS", 4, 0, 0, (u8*)buf_sds, - buf_sds_size); - } - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$SDH", 4, 0, AT_UNUSED, - COLLATION_NTOFS_SECURITY_HASH, - g_vol->indx_record_size); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$SII", 4, 0, AT_UNUSED, - COLLATION_NTOFS_ULONG, g_vol->indx_record_size); - if (!err) - err = initialize_secure(buf_sds, buf_sds_first_size, m); - free(buf_sds); - if (err < 0) { - ntfs_log_error("Couldn't create $Secure: %s\n", - strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $UpCase (mft record 0xa)\n"); - m = (MFT_RECORD*)(g_buf + 0xa * g_vol->mft_record_size); - err = add_attr_data(m, NULL, 0, 0, 0, (u8*)g_vol->upcase, - g_vol->upcase_len << 1); - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(FILE_UpCase, FILE_UpCase), - ((g_vol->upcase_len << 1) + - g_vol->cluster_size - 1) & - ~(g_vol->cluster_size - 1), - g_vol->upcase_len << 1, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0, - "$UpCase", FILE_NAME_WIN32_AND_DOS); - if (err < 0) { - ntfs_log_error("Couldn't create $UpCase: %s\n", strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $Extend (mft record 11)\n"); - /* - * $Extend index must be resident. Otherwise, w2k3 will regard the - * volume as corrupt. (ERSO) - */ - m = (MFT_RECORD*)(g_buf + 11 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_DIRECTORY; - if (!err) - err = create_hardlink(g_index_block, root_ref, m, - MK_LE_MREF(11, 11), 0LL, 0LL, - FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM | - FILE_ATTR_I30_INDEX_PRESENT, 0, 0, - "$Extend", FILE_NAME_WIN32_AND_DOS); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$I30", 4, 0, AT_FILE_NAME, - COLLATION_FILE_NAME, g_vol->indx_record_size); - if (err < 0) { - ntfs_log_error("Couldn't create $Extend: %s\n", - strerror(-err)); - return FALSE; - } - /* NTFS reserved system files (mft records 0xc-0xf) */ - for (i = 0xc; i < 0x10; i++) { - ntfs_log_verbose("Creating system file (mft record 0x%x)\n", i); - m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size); - err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0); - if (!err) { - init_system_file_sd(i, &sd, &j); - err = add_attr_sd(m, sd, j); - } - if (err < 0) { - ntfs_log_error("Couldn't create system file %i (0x%x): " - "%s\n", i, i, strerror(-err)); - return FALSE; - } - } - /* create systemfiles for ntfs volumes (3.1) */ - /* starting with file 24 (ignoring file 16-23) */ - extend_flags = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM | - FILE_ATTR_ARCHIVE | FILE_ATTR_VIEW_INDEX_PRESENT; - ntfs_log_verbose("Creating $Quota (mft record 24)\n"); - m = (MFT_RECORD*)(g_buf + 24 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_4; - m->flags |= MFT_RECORD_IS_VIEW_INDEX; - if (!err) - err = create_hardlink_res((MFT_RECORD*)(g_buf + - 11 * g_vol->mft_record_size), extend_ref, m, - MK_LE_MREF(24, 1), 0LL, 0LL, extend_flags, - 0, 0, "$Quota", FILE_NAME_WIN32_AND_DOS); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$Q", 2, 0, AT_UNUSED, - COLLATION_NTOFS_ULONG, g_vol->indx_record_size); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$O", 2, 0, AT_UNUSED, - COLLATION_NTOFS_SID, g_vol->indx_record_size); - if (!err) - err = initialize_quota(m); - if (err < 0) { - ntfs_log_error("Couldn't create $Quota: %s\n", strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $ObjId (mft record 25)\n"); - m = (MFT_RECORD*)(g_buf + 25 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_4; - m->flags |= MFT_RECORD_IS_VIEW_INDEX; - if (!err) - err = create_hardlink_res((MFT_RECORD*)(g_buf + - 11 * g_vol->mft_record_size), extend_ref, - m, MK_LE_MREF(25, 1), 0LL, 0LL, - extend_flags, 0, 0, "$ObjId", - FILE_NAME_WIN32_AND_DOS); - - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$O", 2, 0, AT_UNUSED, - COLLATION_NTOFS_ULONGS, - g_vol->indx_record_size); -#ifdef ENABLE_UUID - if (!err) - err = index_obj_id_insert(m, &g_vol->guid, - MK_LE_MREF(FILE_Volume, FILE_Volume)); -#endif - if (err < 0) { - ntfs_log_error("Couldn't create $ObjId: %s\n", - strerror(-err)); - return FALSE; - } - ntfs_log_verbose("Creating $Reparse (mft record 26)\n"); - m = (MFT_RECORD*)(g_buf + 26 * g_vol->mft_record_size); - m->flags |= MFT_RECORD_IS_4; - m->flags |= MFT_RECORD_IS_VIEW_INDEX; - if (!err) - err = create_hardlink_res((MFT_RECORD*)(g_buf + - 11 * g_vol->mft_record_size), - extend_ref, m, MK_LE_MREF(26, 1), - 0LL, 0LL, extend_flags, 0, 0, - "$Reparse", FILE_NAME_WIN32_AND_DOS); - /* FIXME: This should be IGNORE_CASE */ - if (!err) - err = add_attr_index_root(m, "$R", 2, 0, AT_UNUSED, - COLLATION_NTOFS_ULONGS, g_vol->indx_record_size); - if (err < 0) { - ntfs_log_error("Couldn't create $Reparse: %s\n", - strerror(-err)); - return FALSE; - } - return TRUE; -} - -/** - * mkntfs_redirect - */ -static int mkntfs_redirect(struct mkntfs_options *opts2) -{ - int result = 1; - ntfs_attr_search_ctx *ctx = NULL; - long long lw, pos; - ATTR_RECORD *a; - MFT_RECORD *m; - int i, err; - - if (!opts2) { - ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n"); - goto done; - } - /* Initialize the random number generator with the current time. */ - srandom(mkntfs_time()); - /* Allocate and initialize ntfs_volume structure g_vol. */ - g_vol = ntfs_volume_alloc(); - if (!g_vol) { - ntfs_log_perror("Could not create volume"); - goto done; - } - /* Create NTFS 3.1 (Windows XP/Vista) volumes. */ - g_vol->major_ver = 3; - g_vol->minor_ver = 1; - /* Transfer some options to the volume. */ - if (opts.label) { - g_vol->vol_name = strdup(opts.label); - if (!g_vol->vol_name) { - ntfs_log_perror("Could not copy volume name"); - goto done; - } - } - if (opts.cluster_size >= 0) - g_vol->cluster_size = opts.cluster_size; - /* Length is in unicode characters. */ - g_vol->upcase_len = 65536; - g_vol->upcase = ntfs_malloc(g_vol->upcase_len * sizeof(ntfschar)); - if (!g_vol->upcase) - goto done; - ntfs_upcase_table_build(g_vol->upcase, - g_vol->upcase_len * sizeof(ntfschar)); - g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array)); - if (!g_vol->attrdef) { - ntfs_log_perror("Could not create attrdef structure"); - goto done; - } - memcpy(g_vol->attrdef, attrdef_ntfs3x_array, - sizeof(attrdef_ntfs3x_array)); - g_vol->attrdef_len = sizeof(attrdef_ntfs3x_array); - /* Open the partition. */ - if (!mkntfs_open_partition(g_vol)) - goto done; - /* - * Decide on the sector size, cluster size, mft record and index record - * sizes as well as the number of sectors/tracks/heads/size, etc. - */ - if (!mkntfs_override_vol_params(g_vol)) - goto done; - /* Initialize $Bitmap and $MFT/$BITMAP related stuff. */ - if (!mkntfs_initialize_bitmaps()) - goto done; - /* Initialize MFT & set g_logfile_lcn. */ - if (!mkntfs_initialize_rl_mft()) - goto done; - /* Initialize $LogFile. */ - if (!mkntfs_initialize_rl_logfile()) - goto done; - /* Initialize $Boot. */ - if (!mkntfs_initialize_rl_boot()) - goto done; - /* Allocate a buffer large enough to hold the mft. */ - g_buf = ntfs_calloc(g_mft_size); - if (!g_buf) - goto done; - /* Create runlist for $BadClus, $DATA named stream $Bad. */ - if (!mkntfs_initialize_rl_bad()) - goto done; - /* If not quick format, fill the device with 0s. */ - if (!opts.quick_format) { - if (!mkntfs_fill_device_with_zeroes()) - goto done; - } - /* Create NTFS volume structures. */ - if (!mkntfs_create_root_structures()) - goto done; - /* - * - Do not step onto bad blocks!!! - * - If any bad blocks were specified or found, modify $BadClus, - * allocating the bad clusters in $Bitmap. - * - C&w bootsector backup bootsector (backup in last sector of the - * partition). - * - If NTFS 3.0+, c&w $Secure file and $Extend directory with the - * corresponding special files in it, i.e. $ObjId, $Quota, $Reparse, - * and $UsnJrnl. And others? Or not all necessary? - * - RE: Populate $root with the system files (and $Extend directory if - * applicable). Possibly should move this as far to the top as - * possible and update during each subsequent c&w of each system file. - */ - ntfs_log_verbose("Syncing root directory index record.\n"); - if (!mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 * - g_vol->mft_record_size), NTFS_INDEX_I30, 4)) - goto done; - - ntfs_log_verbose("Syncing $Bitmap.\n"); - m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size); - - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_perror("Could not create an attribute search context"); - goto done; - } - - if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("BUG: $DATA attribute not found.\n"); - goto done; - } - - a = ctx->attr; - if (a->non_resident) { - runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL); - if (!rl) { - ntfs_log_error("ntfs_mapping_pairs_decompress() failed\n"); - goto done; - } - lw = ntfs_rlwrite(g_vol->u.dev, rl, g_lcn_bitmap, g_lcn_bitmap_byte_size, NULL); - err = errno; - free(rl); - if (lw != g_lcn_bitmap_byte_size) { - ntfs_log_error("ntfs_rlwrite: %s\n", lw == -1 ? - strerror(err) : "unknown error"); - goto done; - } - } else { - memcpy((char*)a + le16_to_cpu(a->u.res.value_offset), g_lcn_bitmap, le32_to_cpu(a->u.res.value_length)); - } - - /* - * No need to sync $MFT/$BITMAP as that has never been modified since - * its creation. - */ - ntfs_log_verbose("Syncing $MFT.\n"); - pos = g_mft_lcn * g_vol->cluster_size; - lw = 1; - for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) { - if (!opts.no_action) - lw = ntfs_mst_pwrite(g_vol->u.dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size); - if (lw != 1) { - ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ? - strerror(errno) : "unknown error"); - goto done; - } - pos += g_vol->mft_record_size; - } - ntfs_log_verbose("Updating $MFTMirr.\n"); - pos = g_mftmirr_lcn * g_vol->cluster_size; - lw = 1; - for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size / g_vol->mft_record_size; i++) { - m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size); - /* - * Decrement the usn by one, so it becomes the same as the one - * in $MFT once it is mst protected. - This is as we need the - * $MFTMirr to have the exact same byte by byte content as - * $MFT, rather than just equivalent meaning content. - */ - if (ntfs_mft_usn_dec(m)) { - ntfs_log_error("ntfs_mft_usn_dec"); - goto done; - } - if (!opts.no_action) - lw = ntfs_mst_pwrite(g_vol->u.dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size); - if (lw != 1) { - ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ? - strerror(errno) : "unknown error"); - goto done; - } - pos += g_vol->mft_record_size; - } - ntfs_log_verbose("Syncing device.\n"); - if (g_vol->u.dev->d_ops->sync(g_vol->u.dev)) { - ntfs_log_error("Syncing device. FAILED"); - goto done; - } - ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n"); - result = 0; -done: - ntfs_attr_put_search_ctx(ctx); - mkntfs_cleanup(); /* Device is unlocked and closed here */ - return result; -} - - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - int result = 1; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - utils_set_locale(); - - mkntfs_init_options(&opts); /* Set up the options */ - - if (!mkntfs_parse_options(argc, argv, &opts)) /* Read the command line options */ - goto done; - - result = mkntfs_redirect(&opts); -done: - return result; -} diff --git a/usr/src/cmd/ntfsprogs/ntfscat.c b/usr/src/cmd/ntfsprogs/ntfscat.c deleted file mode 100644 index 3fe604629d..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscat.c +++ /dev/null @@ -1,441 +0,0 @@ -/** - * ntfscat - Part of the Linux-NTFS project. - * - * Copyright (c) 2003-2005 Richard Russon - * Copyright (c) 2003-2005 Anton Altaparmakov - * Copyright (c) 2003-2005 Szabolcs Szakacsits - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility will concatenate files and print on the standard output. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "utils.h" -#include "volume.h" -#include "debug.h" -#include "dir.h" -#include "ntfscat.h" -#include "version.h" - -static const char *EXEC_NAME = "ntfscat"; -static struct options opts; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s) - Concatenate files and print " - "on the standard output.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - ntfs_log_info("Copyright (c) 2003-2005 Richard Russon\n"); - ntfs_log_info("Copyright (c) 2003-2005 Anton Altaparmakov\n"); - ntfs_log_info("Copyright (c) 2003-2005 Szabolcs Szakacsits\n"); - ntfs_log_info("Copyright (c) 2007 Yura Pakhuchiy\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device [file]\n\n" - " -a, --attribute TYPE Display this attribute type\n" - " -n, --attribute-name NAME Display this attribute name\n" - " -i, --inode NUM Display this inode\n\n" - " -f, --force Use less caution\n" - " -h, --help Print this help\n" - " -q, --quiet Less output\n" - " -V, --version Version information\n" - " -v, --verbose More output\n\n", -// Does not work for compressed files at present so leave undocumented... -// " -r --raw Display the raw data (e.g. for compressed or encrypted file)", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_attribute - Read an attribute name, or number - * @value: String to be parsed - * @attr: Resulting attribute id (on success) - * - * Read a string representing an attribute. It may be a decimal, octal or - * hexadecimal number, or the attribute name in full. The leading $ sign is - * optional. - * - * Return: 1 Success, a valid attribute name or number - * 0 Error, not an attribute name or number - */ -static int parse_attribute(const char *value, ATTR_TYPES *attr) -{ - static const char *attr_name[] = { - "$STANDARD_INFORMATION", - "$ATTRIBUTE_LIST", - "$FILE_NAME", - "$OBJECT_ID", - "$SECURITY_DESCRIPTOR", - "$VOLUME_NAME", - "$VOLUME_INFORMATION", - "$DATA", - "$INDEX_ROOT", - "$INDEX_ALLOCATION", - "$BITMAP", - "$REPARSE_POINT", - "$EA_INFORMATION", - "$EA", - "$PROPERTY_SET", - "$LOGGED_UTILITY_STREAM", - NULL - }; - - int i; - long num; - - for (i = 0; attr_name[i]; i++) { - if ((strcmp(value, attr_name[i]) == 0) || - (strcmp(value, attr_name[i] + 1) == 0)) { - *attr = (ATTR_TYPES)cpu_to_le32((i + 1) * 16); - return 1; - } - } - - num = strtol(value, NULL, 0); - if ((num > 0) && (num < 257)) { - *attr = (ATTR_TYPES)cpu_to_le32(num); - return 1; - } - - return 0; -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char **argv) -{ - static const char *sopt = "-a:fh?i:n:qVvr"; - static const struct option lopt[] = { - { "attribute", required_argument, NULL, 'a' }, - { "attribute-name", required_argument, NULL, 'n' }, - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "inode", required_argument, NULL, 'i' }, - { "quiet", no_argument, NULL, 'q' }, - { "version", no_argument, NULL, 'V' }, - { "verbose", no_argument, NULL, 'v' }, - { "raw", no_argument, NULL, 'r' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - ATTR_TYPES attr = AT_UNUSED; - - opterr = 0; /* We'll handle the errors, thank you. */ - - opts.inode = -1; - opts.attr = cpu_to_le32(-1); - opts.attr_name = NULL; - opts.attr_name_len = 0; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opts.device) { - opts.device = argv[optind - 1]; - } else if (!opts.file) { - opts.file = argv[optind - 1]; - } else { - ntfs_log_error("You must specify exactly one " - "file.\n"); - err++; - } - break; - case 'a': - if (opts.attr != cpu_to_le32(-1)) { - ntfs_log_error("You must specify exactly one " - "attribute.\n"); - } else if (parse_attribute(optarg, &attr) > 0) { - opts.attr = attr; - break; - } else { - ntfs_log_error("Couldn't parse attribute.\n"); - } - err++; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp (argv[optind-1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option (argv[optind-1])) - err++; - break; - } - help++; - break; - case 'i': - if (opts.inode != -1) - ntfs_log_error("You must specify exactly one inode.\n"); - else if (utils_parse_size(optarg, &opts.inode, FALSE)) - break; - else - ntfs_log_error("Couldn't parse inode number.\n"); - err++; - break; - - case 'n': - opts.attr_name_len = ntfs_mbstoucs(optarg, - &opts.attr_name, 0); - if (opts.attr_name_len < 0) { - ntfs_log_perror("Invalid attribute name '%s'", - optarg); - usage(); - } - - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 'V': - ver++; - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'r': - opts.raw = TRUE; - break; - default: - ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (opts.device == NULL) { - ntfs_log_error("You must specify a device.\n"); - err++; - - } else if (opts.file == NULL && opts.inode == -1) { - ntfs_log_error("You must specify a file or inode " - "with the -i option.\n"); - err++; - - } else if (opts.file != NULL && opts.inode != -1) { - ntfs_log_error("You can't specify both a file and inode.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at the " - "same time.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - -/** - * index_get_size - Find the INDX block size from the index root - * @inode: Inode of the directory to be checked - * - * Find the size of a directory's INDX block from the INDEX_ROOT attribute. - * - * Return: n Success, the INDX blocks are n bytes in size - * 0 Error, not a directory - */ -static int index_get_size(ntfs_inode *inode) -{ - ATTR_RECORD *attr90; - INDEX_ROOT *iroot; - - attr90 = find_first_attribute(AT_INDEX_ROOT, inode->mrec); - if (!attr90) - return 0; // not a directory - - iroot = (INDEX_ROOT*)((u8*)attr90 + le16_to_cpu(attr90->u.res.value_offset)); - return le32_to_cpu(iroot->index_block_size); -} - -/** - * cat - */ -static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type, - ntfschar *name, int namelen) -{ - const int bufsize = 4096; - char *buffer; - ntfs_attr *attr; - s64 bytes_read, written; - s64 offset; - u32 block_size; - - buffer = malloc(bufsize); - if (!buffer) - return 1; - - attr = ntfs_attr_open(inode, type, name, namelen); - if (!attr) { - ntfs_log_error("Cannot find attribute type 0x%x.\n", - le32_to_cpu(type)); - free(buffer); - return 1; - } - - if ((inode->mft_no < 2) && (attr->type == AT_DATA)) - block_size = vol->mft_record_size; - else if (attr->type == AT_INDEX_ALLOCATION) - block_size = index_get_size(inode); - else - block_size = 0; - - offset = 0; - for (;;) { - if (!opts.raw && block_size > 0) { - // These types have fixup - bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer); - if (bytes_read > 0) - bytes_read *= block_size; - } else { - bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer); - } - //ntfs_log_info("read %lld bytes\n", bytes_read); - if (bytes_read == -1) { - ntfs_log_perror("ERROR: Couldn't read file"); - break; - } - if (!bytes_read) - break; - - written = fwrite(buffer, 1, bytes_read, stdout); - if (written != bytes_read) { - ntfs_log_perror("ERROR: Couldn't output all data!"); - break; - } - offset += bytes_read; - } - - ntfs_attr_close(attr); - free(buffer); - return 0; -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - ntfs_volume *vol; - ntfs_inode *inode; - ATTR_TYPES attr; - int result = 1; - - ntfs_log_set_handler(ntfs_log_handler_stderr); - - if (!parse_options(argc, argv)) - return 1; - - utils_set_locale(); - - vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) { - ntfs_log_perror("ERROR: couldn't mount volume"); - return 1; - } - - if (opts.inode != -1) - inode = ntfs_inode_open(vol, opts.inode); - else - inode = ntfs_pathname_to_inode(vol, NULL, opts.file); - - if (!inode) { - ntfs_log_perror("ERROR: Couldn't open inode"); - return 1; - } - - attr = AT_DATA; - if (opts.attr != cpu_to_le32(-1)) - attr = opts.attr; - - result = cat(vol, inode, attr, opts.attr_name, opts.attr_name_len); - - ntfs_inode_close(inode); - ntfs_umount(vol, FALSE); - - return result; -} diff --git a/usr/src/cmd/ntfsprogs/ntfscat.h b/usr/src/cmd/ntfsprogs/ntfscat.h deleted file mode 100644 index cf474b4889..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscat.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * ntfscat - Part of the Linux-NTFS project. - * - * Copyright (c) 2003 Richard Russon - * Copyright (c) 2003 Anton Altaparmakov - * - * This utility will concatenate files and print on the standard output. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFSCAT_H_ -#define _NTFSCAT_H_ - -#include "types.h" -#include "layout.h" - -struct options { - char *device; /* Device/File to work with */ - char *file; /* File to display */ - s64 inode; /* Inode to work with */ - ATTR_TYPES attr; /* Attribute type to display */ - ntfschar *attr_name; /* Attribute name to display */ - int attr_name_len; /* Attribute name length */ - int force; /* Override common sense */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - BOOL raw; /* Raw data output */ -}; - -#endif /* _NTFSCAT_H_ */ - - diff --git a/usr/src/cmd/ntfsprogs/ntfsclone.c b/usr/src/cmd/ntfsprogs/ntfsclone.c deleted file mode 100644 index bb63475ef0..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsclone.c +++ /dev/null @@ -1,1926 +0,0 @@ -/** - * ntfsclone - Part of the Linux-NTFS project. - * - * Copyright (c) 2003-2006 Szabolcs Szakacsits - * Copyright (c) 2004-2006 Anton Altaparmakov - * Special image format support copyright (c) 2004 Per Olofsson - * - * Clone NTFS data and/or metadata to a sparse file, image, device or stdout. - * - * 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. - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_SYS_VFS_H -#include -#endif -#ifdef HAVE_SYS_STATVFS_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif - -/* - * FIXME: ntfsclone do bad things about endians handling. Fix it and remove - * this note and define. - */ -#define NTFS_DO_NOT_CHECK_ENDIANS - -#include "compat.h" -#include "debug.h" -#include "types.h" -#include "support.h" -#include "endians.h" -#include "bootsect.h" -#include "device.h" -#include "attrib.h" -#include "mst.h" -#include "volume.h" -#include "mft.h" -#include "bitmap.h" -#include "inode.h" -#include "index.h" -#include "dir.h" -#include "runlist.h" -#include "ntfstime.h" -#include "utils.h" -#include "version.h" - -#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE) -#define BLKGETSIZE _IO(0x12,96) /* Get device size in 512-byte blocks. */ -#endif -#if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64) -#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* Get device size in bytes. */ -#endif - -static const char *EXEC_NAME = "ntfsclone"; - -static const char *bad_sectors_warning_msg = -"*************************************************************************\n" -"* WARNING: The disk has bad sector. This means physical damage on the *\n" -"* disk surface caused by deterioration, manufacturing faults or other *\n" -"* reason. The reliability of the disk may stay stable or degrade fast. *\n" -"* Use the --rescue option to efficiently save as much data as possible! *\n" -"*************************************************************************\n"; - -static const char *dirty_volume_msg = -"Volume '%s' is scheduled for a check or it was shutdown \n" -"uncleanly. Please boot Windows or use the --force option to progress.\n"; - -static struct { - int verbose; - int quiet; - int debug; - int force; - int overwrite; - int std_out; - int blkdev_out; /* output file is block device */ - int metadata; /* metadata only cloning */ - int ignore_fs_check; - int rescue; - int save_image; - int restore_image; - char *output; - char *volume; -#ifdef __sun - struct statvfs stfs; -#else - struct statfs stfs; -#endif -} opt; - -struct bitmap { - s64 size; - u8 *bm; -}; - -struct progress_bar { - u64 start; - u64 stop; - int resolution; - float unit; -}; - -typedef struct { - ntfs_inode *ni; /* inode being processed */ - ntfs_attr_search_ctx *ctx; /* inode attribute being processed */ - s64 inuse; /* number of clusters in use */ -} ntfs_walk_clusters_ctx; - -typedef int (ntfs_walk_op)(ntfs_inode *ni, void *data); - -struct ntfs_walk_cluster { - ntfs_walk_op *inode_op; /* not implemented yet */ - ntfs_walk_clusters_ctx *image; -}; - - -static ntfs_volume *vol = NULL; -static struct bitmap lcn_bitmap; - -static int fd_in; -static int fd_out; -static FILE *msg_out = NULL; - -static int wipe = 0; -static unsigned int nr_used_mft_records = 0; -static unsigned int wiped_unused_mft_data = 0; -static unsigned int wiped_unused_mft = 0; -static unsigned int wiped_resident_data = 0; -static unsigned int wiped_timestamp_data = 0; - -static BOOL image_is_host_endian = FALSE; - -#define IMAGE_MAGIC "\0ntfsclone-image" -#define IMAGE_MAGIC_SIZE 16 - -/* This is the first endianness safe format version. */ -#define NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE 10 -#define NTFSCLONE_IMG_VER_MINOR_ENDIANNESS_SAFE 0 - -/* - * Set the version to 10.0 to avoid colisions with old ntfsclone which - * stupidly used the volume version as the image version... )-: I hope NTFS - * never reaches version 10.0 and if it does one day I hope no-one is using - * such an old ntfsclone by then... - * - * NOTE: Only bump the minor version if the image format and header are still - * backwards compatible. Otherwise always bump the major version. If in - * doubt, bump the major version. - */ -#define NTFSCLONE_IMG_VER_MAJOR 10 -#define NTFSCLONE_IMG_VER_MINOR 0 - -/* All values are in little endian. */ -#ifdef __sun -#pragma pack(1) -#endif -static struct image_hdr { - char magic[IMAGE_MAGIC_SIZE]; - u8 major_ver; - u8 minor_ver; - u32 cluster_size; - s64 device_size; - s64 nr_clusters; - s64 inuse; - u32 offset_to_image_data; /* From start of image_hdr. */ -} __attribute__((__packed__)) image_hdr; -#ifdef __sun -#pragma pack() -#endif - -#ifdef __sun -#define NTFSCLONE_IMG_HEADER_SIZE_OLD \ - (offsetof(struct image_hdr, offset_to_image_data)) -#else -#define NTFSCLONE_IMG_HEADER_SIZE_OLD \ - (offsetof(typeof(image_hdr), offset_to_image_data)) -#endif - -#define NTFS_MBYTE (1000 * 1000) - -#define ERR_PREFIX "ERROR" -#define PERR_PREFIX ERR_PREFIX "(%d): " -#define NERR_PREFIX ERR_PREFIX ": " - -#define LAST_METADATA_INODE 11 - -#define NTFS_MAX_CLUSTER_SIZE 65536 -#define NTFS_SECTOR_SIZE 512 - -#define rounded_up_division(a, b) (((a) + (b - 1)) / (b)) - -#define read_all(f, p, n) io_all((f), (p), (n), 0) -#define write_all(f, p, n) io_all((f), (p), (n), 1) - -__attribute__((format(printf, 1, 2))) -static void Printf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vfprintf(msg_out, fmt, ap); - va_end(ap); - fflush(msg_out); -} - -__attribute__((format(printf, 1, 2))) -static void perr_printf(const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - Printf(PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(msg_out, fmt, ap); - va_end(ap); - Printf(": %s\n", strerror(eo)); - fflush(msg_out); -} - -__attribute__((format(printf, 1, 2))) -static void err_printf(const char *fmt, ...) -{ - va_list ap; - - Printf(NERR_PREFIX); - va_start(ap, fmt); - vfprintf(msg_out, fmt, ap); - va_end(ap); - fflush(msg_out); -} - -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int err_exit(const char *fmt, ...) -{ - va_list ap; - - Printf(NERR_PREFIX); - va_start(ap, fmt); - vfprintf(msg_out, fmt, ap); - va_end(ap); - fflush(msg_out); - exit(1); -} - -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int perr_exit(const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - Printf(PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(msg_out, fmt, ap); - va_end(ap); - Printf(": %s\n", strerror(eo)); - fflush(msg_out); - exit(1); -} - - -__attribute__((noreturn)) -static void usage(void) -{ - fprintf(stderr, "\nUsage: %s [OPTIONS] SOURCE\n" - " Efficiently clone NTFS to a sparse file, image, device or standard output.\n" - "\n" - " -o, --output FILE Clone NTFS to the non-existent FILE\n" - " -O, --overwrite FILE Clone NTFS to FILE, overwriting if exists\n" - " -s, --save-image Save to the special image format\n" - " -r, --restore-image Restore from the special image format\n" - " --rescue Continue after disk read errors\n" - " -m, --metadata Clone *only* metadata (for NTFS experts)\n" - " --ignore-fs-check Ignore the filesystem check result\n" - " -f, --force Force to progress (DANGEROUS)\n" - " -h, --help Display this help\n" -#ifdef DEBUG - " -d, --debug Show debug information\n" -#endif - "\n" - " If FILE is '-' then send the image to the standard output. If SOURCE is '-'\n" - " and --restore-image is used then read the image from the standard input.\n" - "\n", EXEC_NAME); - fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home); - exit(1); -} - - -static void parse_options(int argc, char **argv) -{ - static const char *sopt = "-dfhmo:O:rs"; - static const struct option lopt[] = { -#ifdef DEBUG - { "debug", no_argument, NULL, 'd' }, -#endif - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "metadata", no_argument, NULL, 'm' }, - { "output", required_argument, NULL, 'o' }, - { "overwrite", required_argument, NULL, 'O' }, - { "restore-image", no_argument, NULL, 'r' }, - { "ignore-fs-check", no_argument, NULL, 'C' }, - { "rescue", no_argument, NULL, 'R' }, - { "save-image", no_argument, NULL, 's' }, - { NULL, 0, NULL, 0 } - }; - - int c; - - memset(&opt, 0, sizeof(opt)); - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (opt.volume) - usage(); - opt.volume = argv[optind-1]; - break; - case 'd': - opt.debug++; - break; - case 'f': - opt.force++; - break; - case 'h': - case '?': - usage(); - case 'm': - opt.metadata++; - break; - case 'O': - opt.overwrite++; - case 'o': - if (opt.output) - usage(); - opt.output = optarg; - break; - case 'r': - opt.restore_image++; - break; - case 'C': - opt.ignore_fs_check++; - break; - case 'R': - opt.rescue++; - break; - case 's': - opt.save_image++; - break; - default: - err_printf("Unknown option '%s'.\n", argv[optind-1]); - usage(); - } - } - - if (opt.output == NULL) { - err_printf("You must specify an output file.\n"); - usage(); - } - - if (strcmp(opt.output, "-") == 0) - opt.std_out++; - - if (opt.volume == NULL) { - err_printf("You must specify a device file.\n"); - usage(); - } - - if (opt.metadata && opt.save_image) - err_exit("Saving only metadata to an image is not " - "supported!\n"); - - if (opt.metadata && opt.restore_image) - err_exit("Restoring only metadata from an image is not " - "supported!\n"); - - if (opt.metadata && opt.std_out) - err_exit("Cloning only metadata to stdout isn't supported!\n"); - - if (opt.ignore_fs_check && !opt.metadata) - err_exit("Filesystem check can be ignored only for metadata " - "cloning!\n"); - - if (opt.save_image && opt.restore_image) - err_exit("Saving and restoring an image at the same time " - "is not supported!\n"); - - if (!opt.std_out) { - struct stat st; - - if (stat(opt.output, &st) == -1) { - if (errno != ENOENT) - perr_exit("Couldn't access '%s'", opt.output); - } else { - if (!opt.overwrite) - err_exit("Output file '%s' already exists.\n" - "Use option --overwrite if you want to" - " replace its content.\n", opt.output); - - if (S_ISBLK(st.st_mode)) { - opt.blkdev_out = 1; - if (opt.metadata) - err_exit("Cloning only metadata to a " - "block device isn't supported!\n"); - } - } - } - - msg_out = stdout; - - /* FIXME: this is a workaround for losing debug info if stdout != stderr - and for the uncontrollable verbose messages in libntfs. Ughhh. */ - if (opt.std_out) - msg_out = stderr; - else if (opt.debug) { - /* Redirect stderr to stdout, note fflush()es are essential! */ - fflush(stdout); - fflush(stderr); - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) { - perror("Failed to redirect stderr to stdout"); - exit(1); - } - fflush(stdout); - fflush(stderr); - } else { - fflush(stderr); - if (!freopen("/dev/null", "w", stderr)) - perr_exit("Failed to redirect stderr to /dev/null"); - } -} - -static void progress_init(struct progress_bar *p, u64 start, u64 stop, int res) -{ - p->start = start; - p->stop = stop; - p->unit = 100.0 / (stop - start); - p->resolution = res; -} - - -static void progress_update(struct progress_bar *p, u64 current) -{ - float percent = p->unit * current; - - if (current != p->stop) { - if ((current - p->start) % p->resolution) - return; - Printf("%6.2f percent completed\r", percent); - } else - Printf("100.00 percent completed\n"); - fflush(msg_out); -} - -static s64 is_critical_metadata(ntfs_walk_clusters_ctx *image, runlist *rl) -{ - s64 inode = image->ni->mft_no; - - if (inode <= LAST_METADATA_INODE) { - - /* Don't save bad sectors (both $Bad and unnamed are ignored */ - if (inode == FILE_BadClus && image->ctx->attr->type == AT_DATA) - return 0; - - if (inode != FILE_LogFile) - return rl->length; - - if (image->ctx->attr->type == AT_DATA) { - - /* Save at least the first 16 KiB of FILE_LogFile */ - s64 s = (s64)16384 - rl->vcn * vol->cluster_size; - if (s > 0) { - s = rounded_up_division(s, vol->cluster_size); - if (rl->length < s) - s = rl->length; - return s; - } - return 0; - } - } - - if (image->ctx->attr->type != AT_DATA) - return rl->length; - - return 0; -} - - -static int io_all(void *fd, void *buf, int count, int do_write) -{ - int i; - struct ntfs_device *dev = fd; - - while (count > 0) { - if (do_write) - i = write(*(int *)fd, buf, count); - else if (opt.restore_image) - i = read(*(int *)fd, buf, count); - else - i = dev->d_ops->read(dev, buf, count); - if (i < 0) { - if (errno != EAGAIN && errno != EINTR) - return -1; - } else { - count -= i; - buf = i + (char *) buf; - } - } - return 0; -} - - -static void rescue_sector(void *fd, off_t pos, void *buff) -{ - const char *badsector_magic = "BadSectoR\0"; - struct ntfs_device *dev = fd; - - if (opt.restore_image) { - if (lseek(*(int *)fd, pos, SEEK_SET) == (off_t)-1) - perr_exit("lseek"); - } else { - if (vol->u.dev->d_ops->seek(dev, pos, SEEK_SET) == (off_t)-1) - perr_exit("seek input"); - } - - if (read_all(fd, buff, NTFS_SECTOR_SIZE) == -1) { - Printf("WARNING: Can't read sector at %llu, lost data.\n", - (unsigned long long)pos); - memset(buff, '?', NTFS_SECTOR_SIZE); - memmove(buff, badsector_magic, sizeof(badsector_magic)); - } -} - - -static void copy_cluster(int rescue, u64 rescue_lcn) -{ - char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */ - /* vol is NULL if opt.restore_image is set */ - u32 csize = le32_to_cpu(image_hdr.cluster_size); - void *fd = (void *)&fd_in; - off_t rescue_pos; - - if (!opt.restore_image) { - csize = vol->cluster_size; - fd = vol->u.dev; - } - - rescue_pos = (off_t)(rescue_lcn * csize); - - if (read_all(fd, buff, csize) == -1) { - - if (errno != EIO) - perr_exit("read_all"); - else if (rescue){ - u32 i; - for (i = 0; i < csize; i += NTFS_SECTOR_SIZE) - rescue_sector(fd, rescue_pos + i, buff + i); - } else { - Printf("%s", bad_sectors_warning_msg); - err_exit("Disk is faulty, can't make full backup!"); - } - } - - if (opt.save_image) { - char cmd = 1; - if (write_all(&fd_out, &cmd, sizeof(cmd)) == -1) - perr_exit("write_all"); - } - - if (write_all(&fd_out, buff, csize) == -1) { - perr_printf("Write failed"); -#ifndef __sun - int err = errno; - if (errno == EIO && opt.stfs.f_type == 0x517b) - Printf("Apparently you tried to clone to a remote " - "Windows computer but they don't\nhave " - "efficient sparse file handling by default. " - "Please try a different method.\n"); -#endif /* !defined(__sun) */ - exit(1); - } -} - -static void lseek_to_cluster(s64 lcn) -{ - off_t pos; - - pos = (off_t)(lcn * vol->cluster_size); - - if (vol->u.dev->d_ops->seek(vol->u.dev, pos, SEEK_SET) == (off_t)-1) - perr_exit("lseek input"); - - if (opt.std_out || opt.save_image) - return; - - if (lseek(fd_out, pos, SEEK_SET) == (off_t)-1) - perr_exit("lseek output"); -} - -static void image_skip_clusters(s64 count) -{ - if (opt.save_image && count > 0) { -#ifdef __sun - s64 count_buf; -#else - typeof(count) count_buf; -#endif - char buff[1 + sizeof(count)]; - - buff[0] = 0; - count_buf = cpu_to_sle64(count); - memcpy(buff + 1, &count_buf, sizeof(count_buf)); - - if (write_all(&fd_out, buff, sizeof(buff)) == -1) - perr_exit("write_all"); - } -} - -static void dump_clusters(ntfs_walk_clusters_ctx *image, runlist *rl) -{ - s64 i, len; /* number of clusters to copy */ - - if (opt.std_out || !opt.metadata) - return; - - if (!(len = is_critical_metadata(image, rl))) - return; - - lseek_to_cluster(rl->lcn); - - /* FIXME: this could give pretty suboptimal performance */ - for (i = 0; i < len; i++) - copy_cluster(opt.rescue, rl->lcn + i); -} - -static void clone_ntfs(u64 nr_clusters) -{ - u64 cl, last_cl; /* current and last used cluster */ - void *buf; - u32 csize = vol->cluster_size; - u64 p_counter = 0; - struct progress_bar progress; - - if (opt.save_image) - Printf("Saving NTFS to image ...\n"); - else - Printf("Cloning NTFS ...\n"); - - buf = ntfs_calloc(csize); - if (!buf) - perr_exit("clone_ntfs"); - - progress_init(&progress, p_counter, nr_clusters, 100); - - if (opt.save_image) { - if (write_all(&fd_out, &image_hdr, - image_hdr.offset_to_image_data) == -1) - perr_exit("write_all"); - } - - for (last_cl = cl = 0; cl < (u64)vol->nr_clusters; cl++) { - - if (ntfs_bit_get(lcn_bitmap.bm, cl)) { - progress_update(&progress, ++p_counter); - lseek_to_cluster(cl); - image_skip_clusters(cl - last_cl - 1); - - copy_cluster(opt.rescue, cl); - last_cl = cl; - continue; - } - - if (opt.std_out && !opt.save_image) { - progress_update(&progress, ++p_counter); - if (write_all(&fd_out, buf, csize) == -1) - perr_exit("write_all"); - } - } - image_skip_clusters(cl - last_cl - 1); -} - -static void write_empty_clusters(s32 csize, s64 count, - struct progress_bar *progress, u64 *p_counter) -{ - s64 i; - char buff[NTFS_MAX_CLUSTER_SIZE]; - - memset(buff, 0, csize); - - for (i = 0; i < count; i++) { - if (write_all(&fd_out, buff, csize) == -1) - perr_exit("write_all"); - progress_update(progress, ++(*p_counter)); - } -} - -static void restore_image(void) -{ - s64 pos = 0, count; - s32 csize = le32_to_cpu(image_hdr.cluster_size); - char cmd; - u64 p_counter = 0; - struct progress_bar progress; - - Printf("Restoring NTFS from image ...\n"); - - progress_init(&progress, p_counter, opt.std_out ? - sle64_to_cpu(image_hdr.nr_clusters) : - sle64_to_cpu(image_hdr.inuse), - 100); - - while (pos < sle64_to_cpu(image_hdr.nr_clusters)) { - if (read_all(&fd_in, &cmd, sizeof(cmd)) == -1) - perr_exit("read_all"); - - if (cmd == 0) { - if (read_all(&fd_in, &count, sizeof(count)) == -1) - perr_exit("read_all"); - if (!image_is_host_endian) - count = sle64_to_cpu(count); - if (opt.std_out) - write_empty_clusters(csize, count, - &progress, &p_counter); - else { - if (lseek(fd_out, count * csize, SEEK_CUR) == - (off_t)-1) - perr_exit("restore_image: lseek"); - } - pos += count; - } else if (cmd == 1) { - copy_cluster(0, 0); - pos++; - progress_update(&progress, ++p_counter); - } else - err_exit("Invalid command code in image\n"); - } -} - -static void wipe_index_entry_timestams(INDEX_ENTRY *e) -{ - s64 timestamp = utc2ntfs(0); - - /* FIXME: can fall into infinite loop if corrupted */ - while (!(e->flags & INDEX_ENTRY_END)) { - - e->key.file_name.creation_time = timestamp; - e->key.file_name.last_data_change_time = timestamp; - e->key.file_name.last_mft_change_time = timestamp; - e->key.file_name.last_access_time = timestamp; - - wiped_timestamp_data += 32; - - e = (INDEX_ENTRY *)((u8 *)e + le16_to_cpu(e->length)); - } -} - -static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr) -{ - INDEX_ALLOCATION *indexa, *tmp_indexa; - INDEX_ENTRY *entry; - INDEX_ROOT *indexr; - u8 *bitmap, *byte; - int bit; - ntfs_attr *na; - ntfschar *name; - u32 name_len; - - indexr = ntfs_index_root_get(ni, attr); - if (!indexr) { - perr_printf("Failed to read $INDEX_ROOT attribute of inode " - "%lld", ni->mft_no); - return; - } - - if (indexr->type != AT_FILE_NAME) - goto out_indexr; - - name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)); - name_len = attr->name_length; - - byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL); - if (!byte) { - perr_printf("Failed to read $BITMAP attribute"); - goto out_indexr; - } - - na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, name, name_len); - if (!na) { - perr_printf("Failed to open $INDEX_ALLOCATION attribute"); - goto out_bitmap; - } - - if (!na->data_size) - goto out_na; - - tmp_indexa = indexa = ntfs_malloc(na->data_size); - if (!tmp_indexa) - goto out_na; - - if (ntfs_attr_pread(na, 0, na->data_size, indexa) != na->data_size) { - perr_printf("Failed to read $INDEX_ALLOCATION attribute"); - goto out_indexa; - } - - bit = 0; - while ((u8 *)tmp_indexa < (u8 *)indexa + na->data_size) { - if (*byte & (1 << bit)) { - if (ntfs_mst_post_read_fixup((NTFS_RECORD *)tmp_indexa, - le32_to_cpu( - indexr->index_block_size))) { - perr_printf("Damaged INDX record"); - goto out_indexa; - } - entry = (INDEX_ENTRY *)((u8 *)tmp_indexa + le32_to_cpu( - tmp_indexa->index.entries_offset) + 0x18); - - wipe_index_entry_timestams(entry); - - if (ntfs_mft_usn_dec((MFT_RECORD *)tmp_indexa)) - perr_exit("ntfs_mft_usn_dec"); - - if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)tmp_indexa, - le32_to_cpu( - indexr->index_block_size))) { - perr_printf("INDX write fixup failed"); - goto out_indexa; - } - } - tmp_indexa = (INDEX_ALLOCATION *)((u8 *)tmp_indexa + - le32_to_cpu(indexr->index_block_size)); - bit++; - if (bit > 7) { - bit = 0; - byte++; - } - } - - if (ntfs_rl_pwrite(vol, na->rl, 0, na->data_size, indexa) != na->data_size) - perr_printf("ntfs_rl_pwrite failed for inode %lld", ni->mft_no); -out_indexa: - free(indexa); -out_na: - ntfs_attr_close(na); -out_bitmap: - free(bitmap); -out_indexr: - free(indexr); -} - -static void wipe_index_root_timestamps(ATTR_RECORD *attr, s64 timestamp) -{ - INDEX_ENTRY *entry; - INDEX_ROOT *iroot; - - iroot = (INDEX_ROOT *)((u8 *)attr + le16_to_cpu(attr->u.res.value_offset)); - entry = (INDEX_ENTRY *)((u8 *)iroot + - le32_to_cpu(iroot->index.entries_offset) + 0x10); - - while (!(entry->flags & INDEX_ENTRY_END)) { - - if (iroot->type == AT_FILE_NAME) { - - entry->key.file_name.creation_time = timestamp; - entry->key.file_name.last_access_time = timestamp; - entry->key.file_name.last_data_change_time = timestamp; - entry->key.file_name.last_mft_change_time = timestamp; - - wiped_timestamp_data += 32; - - } else if (ntfs_names_are_equal(NTFS_INDEX_Q, - sizeof(NTFS_INDEX_Q) / 2 - 1, - (ntfschar *)((char *)attr + - le16_to_cpu(attr->name_offset)), - attr->name_length, 0, NULL, 0)) { - - QUOTA_CONTROL_ENTRY *quota_q; - - quota_q = (QUOTA_CONTROL_ENTRY *)((u8 *)entry + - le16_to_cpu(entry->u.s.data_offset)); - /* - * FIXME: no guarantee it's indeed /$Extend/$Quota:$Q. - * For now, as a minimal safeguard, we check only for - * quota version 2 ... - */ - if (le32_to_cpu(quota_q->version) == 2) { - quota_q->change_time = timestamp; - wiped_timestamp_data += 4; - } - } - - entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length)); - } -} - -#define WIPE_TIMESTAMPS(atype, attr, timestamp) \ -do { \ - atype *ats; \ - ats = (atype *)((char *)(attr) + le16_to_cpu((attr)->u.res.value_offset)); \ - \ - ats->creation_time = (timestamp); \ - ats->last_data_change_time = (timestamp); \ - ats->last_mft_change_time= (timestamp); \ - ats->last_access_time = (timestamp); \ - \ - wiped_timestamp_data += 32; \ - \ -} while (0) - -static void wipe_timestamps(ntfs_walk_clusters_ctx *image) -{ - ATTR_RECORD *a = image->ctx->attr; - s64 timestamp = utc2ntfs(0); - - if (a->type == AT_FILE_NAME) - WIPE_TIMESTAMPS(FILE_NAME_ATTR, a, timestamp); - - else if (a->type == AT_STANDARD_INFORMATION) - WIPE_TIMESTAMPS(STANDARD_INFORMATION, a, timestamp); - - else if (a->type == AT_INDEX_ROOT) - wipe_index_root_timestamps(a, timestamp); -} - -static void wipe_resident_data(ntfs_walk_clusters_ctx *image) -{ - ATTR_RECORD *a; - u32 i; - int n = 0; - u8 *p; - - a = image->ctx->attr; - p = (u8*)a + le16_to_cpu(a->u.res.value_offset); - - if (image->ni->mft_no <= LAST_METADATA_INODE) - return; - - if (a->type != AT_DATA) - return; - - for (i = 0; i < le32_to_cpu(a->u.res.value_length); i++) { - if (p[i]) { - p[i] = 0; - n++; - } - } - - wiped_resident_data += n; -} - -static void clone_logfile_parts(ntfs_walk_clusters_ctx *image, runlist *rl) -{ - s64 offset = 0, lcn, vcn; - - while (1) { - - vcn = offset / image->ni->vol->cluster_size; - lcn = ntfs_rl_vcn_to_lcn(rl, vcn); - if (lcn < 0) - break; - - lseek_to_cluster(lcn); - copy_cluster(opt.rescue, lcn); - - if (offset == 0) - offset = NTFS_BLOCK_SIZE >> 1; - else - offset <<= 1; - } -} - -static void walk_runs(struct ntfs_walk_cluster *walk) -{ - int i, j; - runlist *rl; - ATTR_RECORD *a; - ntfs_attr_search_ctx *ctx; - - ctx = walk->image->ctx; - a = ctx->attr; - - if (!a->non_resident) { - if (wipe) { - wipe_resident_data(walk->image); - wipe_timestamps(walk->image); - } - return; - } - - if (wipe && walk->image->ctx->attr->type == AT_INDEX_ALLOCATION) - wipe_index_allocation_timestamps(walk->image->ni, a); - - if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) - perr_exit("ntfs_decompress_mapping_pairs"); - - for (i = 0; rl[i].length; i++) { - s64 lcn = rl[i].lcn; - s64 lcn_length = rl[i].length; - - if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED) - continue; - - /* FIXME: ntfs_mapping_pairs_decompress should return error */ - if (lcn < 0 || lcn_length < 0) - err_exit("Corrupt runlist in inode %lld attr %x LCN " - "%llx length %llx\n", ctx->ntfs_ino->mft_no, - (unsigned int)le32_to_cpu(a->type), lcn, - lcn_length); - - if (!wipe) - dump_clusters(walk->image, rl + i); - - for (j = 0; j < lcn_length; j++) { - u64 k = (u64)lcn + j; - if (ntfs_bit_get_and_set(lcn_bitmap.bm, k, 1)) - err_exit("Cluster %llu referenced twice!\n" - "You didn't shutdown your Windows" - "properly?\n", (unsigned long long)k); - } - - walk->image->inuse += lcn_length; - } - if (!wipe && !opt.std_out && opt.metadata && - walk->image->ni->mft_no == FILE_LogFile && - walk->image->ctx->attr->type == AT_DATA) - clone_logfile_parts(walk->image, rl); - - free(rl); -} - - -static void walk_attributes(struct ntfs_walk_cluster *walk) -{ - ntfs_attr_search_ctx *ctx; - - if (!(ctx = ntfs_attr_get_search_ctx(walk->image->ni, NULL))) - perr_exit("ntfs_get_attr_search_ctx"); - - while (!ntfs_attrs_walk(ctx)) { - if (ctx->attr->type == AT_END) - break; - - walk->image->ctx = ctx; - walk_runs(walk); - } - - ntfs_attr_put_search_ctx(ctx); -} - - - -static void compare_bitmaps(struct bitmap *a) -{ - s64 i, pos, count; - int mismatch = 0; - u8 bm[NTFS_BUF_SIZE]; - - Printf("Accounting clusters ...\n"); - - pos = 0; - while (1) { - count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm); - if (count == -1) - perr_exit("Couldn't get $Bitmap $DATA"); - - if (count == 0) { - if (a->size > pos) - err_exit("$Bitmap size is smaller than expected" - " (%lld != %lld)\n", a->size, pos); - break; - } - - for (i = 0; i < count; i++, pos++) { - s64 cl; /* current cluster */ - - if (a->size <= pos) - goto done; - - if (a->bm[pos] == bm[i]) - continue; - - for (cl = pos * 8; cl < (pos + 1) * 8; cl++) { - char bit; - - bit = ntfs_bit_get(a->bm, cl); - if (bit == ntfs_bit_get(bm, i * 8 + cl % 8)) - continue; - - if (opt.ignore_fs_check) { - lseek_to_cluster(cl); - copy_cluster(opt.rescue, cl); - } - - if (++mismatch > 10) - continue; - - Printf("Cluster accounting failed at %lld " - "(0x%llx): %s cluster in $Bitmap\n", - (long long)cl, (unsigned long long)cl, - bit ? "missing" : "extra"); - } - } - } -done: - if (mismatch) { - Printf("Totally %d cluster accounting mismatches.\n", mismatch); - if (opt.ignore_fs_check) { - Printf("WARNING: The NTFS inconsistency was overruled " - "by the --ignore-fs-check option.\n"); - return; - } - err_exit("Filesystem check failed! Windows wasn't shutdown " - "properly or inconsistent\nfilesystem. Please run " - "chkdsk /f on Windows then reboot it TWICE.\n"); - } -} - - -static int wipe_data(char *p, int pos, int len) -{ - int wiped = 0; - - for (p += pos; --len >= 0;) { - if (p[len]) { - p[len] = 0; - wiped++; - } - } - - return wiped; -} - -static void wipe_unused_mft_data(ntfs_inode *ni) -{ - int unused; - MFT_RECORD *m = ni->mrec; - - /* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */ - if (ni->mft_no <= LAST_METADATA_INODE) - return; - - unused = le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use); - wiped_unused_mft_data += wipe_data((char *)m, - le32_to_cpu(m->bytes_in_use), unused); -} - -static void wipe_unused_mft(ntfs_inode *ni) -{ - int unused; - MFT_RECORD *m = ni->mrec; - - /* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */ - if (ni->mft_no <= LAST_METADATA_INODE) - return; - - unused = le32_to_cpu(m->bytes_in_use) - sizeof(MFT_RECORD); - wiped_unused_mft += wipe_data((char *)m, sizeof(MFT_RECORD), unused); -} - -static void mft_record_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni) -{ - if (ntfs_mft_usn_dec(ni->mrec)) - perr_exit("ntfs_mft_usn_dec"); - - if (ntfs_mft_record_write(volume, ni->mft_no, ni->mrec)) - perr_exit("ntfs_mft_record_write"); -} - -static void mft_inode_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni) -{ - s32 i; - - mft_record_write_with_same_usn(volume, ni); - - if (ni->nr_extents <= 0) - return; - - for (i = 0; i < ni->nr_extents; ++i) { - ntfs_inode *eni = ni->u.extent_nis[i]; - mft_record_write_with_same_usn(volume, eni); - } -} - -static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk) -{ - s64 inode = 0; - s64 last_mft_rec; - ntfs_inode *ni; - struct progress_bar progress; - - Printf("Scanning volume ...\n"); - - last_mft_rec = (volume->mft_na->initialized_size >> - volume->mft_record_size_bits) - 1; - progress_init(&progress, inode, last_mft_rec, 100); - - for (; inode <= last_mft_rec; inode++) { - - int err, deleted_inode; - MFT_REF mref = (MFT_REF)inode; - - progress_update(&progress, inode); - - /* FIXME: Terrible kludge for libntfs not being able to return - a deleted MFT record as inode */ - ni = ntfs_calloc(sizeof(ntfs_inode)); - if (!ni) - perr_exit("walk_clusters"); - - ni->vol = volume; - - err = ntfs_file_record_read(volume, mref, &ni->mrec, NULL); - if (err == -1) { - free(ni); - continue; - } - - deleted_inode = !(ni->mrec->flags & MFT_RECORD_IN_USE); - - if (deleted_inode) { - - ni->mft_no = MREF(mref); - if (wipe) { - wipe_unused_mft(ni); - wipe_unused_mft_data(ni); - mft_record_write_with_same_usn(volume, ni); - } - } - - free(ni->mrec); - free(ni); - - if (deleted_inode) - continue; - - if ((ni = ntfs_inode_open(volume, mref)) == NULL) { - /* FIXME: continue only if it make sense, e.g. - MFT record not in use based on $MFT bitmap */ - if (errno == EIO || errno == ENOENT) - continue; - perr_exit("Reading inode %lld failed", inode); - } - - if (wipe) - nr_used_mft_records++; - - if (ni->mrec->base_mft_record) - goto out; - - walk->image->ni = ni; - walk_attributes(walk); -out: - if (wipe) { - wipe_unused_mft_data(ni); - mft_inode_write_with_same_usn(volume, ni); - } - - if (ntfs_inode_close(ni)) - perr_exit("ntfs_inode_close for inode %lld", inode); - } - - return 0; -} - - -/* - * $Bitmap can overlap the end of the volume. Any bits in this region - * must be set. This region also encompasses the backup boot sector. - */ -static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm) -{ - for (; cluster < bm->size << 3; cluster++) - ntfs_bit_set(bm->bm, (u64)cluster, 1); -} - - -/* - * Allocate a block of memory with one bit for each cluster of the disk. - * All the bits are set to 0, except those representing the region beyond the - * end of the disk. - */ -static void setup_lcn_bitmap(void) -{ - /* Determine lcn bitmap byte size and allocate it. */ - lcn_bitmap.size = rounded_up_division(vol->nr_clusters, 8); - - lcn_bitmap.bm = ntfs_calloc(lcn_bitmap.size); - if (!lcn_bitmap.bm) - perr_exit("Failed to allocate internal buffer"); - - bitmap_file_data_fixup(vol->nr_clusters, &lcn_bitmap); -} - - -static s64 volume_size(ntfs_volume *volume, s64 nr_clusters) -{ - return nr_clusters * volume->cluster_size; -} - - -static void print_volume_size(const char *str, s64 bytes) -{ - Printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes, - (long long)rounded_up_division(bytes, NTFS_MBYTE)); -} - - -static void print_disk_usage(const char *spacer, u32 cluster_size, - s64 nr_clusters, s64 inuse) -{ - s64 total, used; - - total = nr_clusters * cluster_size; - used = inuse * cluster_size; - - Printf("Space in use %s: %lld MB (%.1f%%) ", spacer, - (long long)rounded_up_division(used, NTFS_MBYTE), - 100.0 * ((float)used / total)); - - Printf("\n"); -} - -static void print_image_info(void) -{ - Printf("Ntfsclone image version: %d.%d\n", - image_hdr.major_ver, image_hdr.minor_ver); - Printf("Cluster size : %u bytes\n", - (unsigned)le32_to_cpu(image_hdr.cluster_size)); - print_volume_size("Image volume size ", - sle64_to_cpu(image_hdr.nr_clusters) * - le32_to_cpu(image_hdr.cluster_size)); - Printf("Image device size : %lld bytes\n", - sle64_to_cpu(image_hdr.device_size)); - print_disk_usage(" ", le32_to_cpu(image_hdr.cluster_size), - sle64_to_cpu(image_hdr.nr_clusters), - sle64_to_cpu(image_hdr.inuse)); - Printf("Offset to image data : %u (0x%x) bytes\n", - (unsigned)le32_to_cpu(image_hdr.offset_to_image_data), - (unsigned)le32_to_cpu(image_hdr.offset_to_image_data)); -} - -static void check_if_mounted(const char *device, unsigned long new_mntflag) -{ - unsigned long mntflag; - - if (ntfs_check_if_mounted(device, &mntflag)) - perr_exit("Failed to check '%s' mount state", device); - - if (mntflag & NTFS_MF_MOUNTED) { - if (!(mntflag & NTFS_MF_READONLY)) - err_exit("Device '%s' is mounted read-write. " - "You must 'umount' it first.\n", device); - if (!new_mntflag) - err_exit("Device '%s' is mounted. " - "You must 'umount' it first.\n", device); - } -} - -/** - * mount_volume - - * - * First perform some checks to determine if the volume is already mounted, or - * is dirty (Windows wasn't shutdown properly). If everything is OK, then mount - * the volume (load the metadata into memory). - */ -static void mount_volume(unsigned long new_mntflag) -{ - check_if_mounted(opt.volume, new_mntflag); - - if (!(vol = ntfs_mount(opt.volume, new_mntflag))) { - - int err = errno; - - perr_printf("Opening '%s' as NTFS failed", opt.volume); - if (err == EINVAL) { - Printf("Apparently device '%s' doesn't have a " - "valid NTFS. Maybe you selected\nthe whole " - "disk instead of a partition (e.g. /dev/hda, " - "not /dev/hda1)?\n", opt.volume); - } - exit(1); - } - - if (NVolWasDirty(vol)) - if (opt.force-- <= 0) - err_exit(dirty_volume_msg, opt.volume); - - if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size) - err_exit("Cluster size %u is too large!\n", - (unsigned int)vol->cluster_size); - - Printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver); - if (ntfs_version_is_supported(vol)) - perr_exit("Unknown NTFS version"); - - Printf("Cluster size : %u bytes\n", - (unsigned int)vol->cluster_size); - print_volume_size("Current volume size", - volume_size(vol, vol->nr_clusters)); -} - -static struct ntfs_walk_cluster backup_clusters = { NULL, NULL }; - -static int device_offset_valid(int fd, s64 ofs) -{ - char ch; - - if (lseek(fd, ofs, SEEK_SET) >= 0 && read(fd, &ch, 1) == 1) - return 0; - return -1; -} - -static s64 device_size_get(int fd) -{ - s64 high, low; -#ifdef BLKGETSIZE64 - { u64 size; - - if (ioctl(fd, BLKGETSIZE64, &size) >= 0) { - ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu " - "(0x%llx).\n", (unsigned long long)size, - (unsigned long long)size); - return (s64)size; - } - } -#endif -#ifdef BLKGETSIZE - { unsigned long size; - - if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu " - "(0x%lx).\n", size, size); - return (s64)size * 512; - } - } -#endif -#ifdef FDGETPRM - { struct floppy_struct this_floppy; - - if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) { - ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu " - "(0x%lx).\n", this_floppy.size, - this_floppy.size); - return (s64)this_floppy.size * 512; - } - } -#endif - /* - * We couldn't figure it out by using a specialized ioctl, - * so do binary search to find the size of the device. - */ - low = 0LL; - for (high = 1024LL; !device_offset_valid(fd, high); high <<= 1) - low = high; - while (low < high - 1LL) { - const s64 mid = (low + high) / 2; - - if (!device_offset_valid(fd, mid)) - low = mid; - else - high = mid; - } - lseek(fd, 0LL, SEEK_SET); - return (low + 1LL); -} - -static void fsync_clone(int fd) -{ - Printf("Syncing ...\n"); - if (fsync(fd) && errno != EINVAL) - perr_exit("fsync"); -} - -static void set_filesize(s64 filesize) -{ - -#ifdef __sun - - if (fstatvfs(fd_out, &opt.stfs) == -1) - Printf("WARNING: Couldn't get filesystem type: " - "%s\n", strerror(errno)); - - if (strcmp(opt.stfs.f_basetype, "pcfs") == 0) - Printf("WARNING: You're using PCFS, it does not support " - "sparse files so the next operation might take " - "a while. You should consider using the more " - "efficient --save-image option of ntfsclone. Use " - "the --restore-image option to restore the image.\n"); - - if (ftruncate(fd_out, filesize) == -1) { - int err = errno; - perr_printf("ftruncate failed for file '%s'", opt.output); - Printf("Destination filesystem type is %s\n", - opt.stfs.f_basetype); - if (err == EFBIG || (err == EINVAL && filesize > 0)) - Printf("Your system or the destination filesystem " - "doesn't support large files.\n"); - exit(1); - } - -#else /* !defined(__sun) */ - - long fs_type = 0; /* Unknown filesystem type */ - - if (fstatfs(fd_out, &opt.stfs) == -1) - Printf("WARNING: Couldn't get filesystem type: " - "%s\n", strerror(errno)); - else - fs_type = opt.stfs.f_type; - - if (fs_type == 0x52654973) - Printf("WARNING: You're using ReiserFS, it has very poor " - "performance creating\nlarge sparse files. The next " - "operation might take a very long time!\n" - "Creating sparse output file ...\n"); - else if (fs_type == 0x517b) - Printf("WARNING: You're using SMBFS and if the remote share " - "isn't Samba but a Windows\ncomputer then the clone " - "operation will be very inefficient and may fail!\n"); - - if (ftruncate(fd_out, filesize) == -1) { - int err = errno; - perr_printf("ftruncate failed for file '%s'", opt.output); - if (fs_type) - Printf("Destination filesystem type is 0x%lx.\n", - (unsigned long)fs_type); - if (err == E2BIG) { - Printf("Your system or the destination filesystem " - "doesn't support large files.\n"); - if (fs_type == 0x517b) { - Printf("SMBFS needs minimum Linux kernel " - "version 2.4.25 and\n the 'lfs' option" - "\nfor smbmount to have large " - "file support.\n"); - } - } else if (err == EPERM) { - Printf("Apparently the destination filesystem doesn't " - "support sparse files.\nYou can overcome this " - "by using the more efficient --save-image " - "option\nof ntfsclone. Use the --restore-image " - "option to restore the image.\n"); - } - exit(1); - } - -#endif /* defined(__sun) */ -} - -static s64 open_image(void) -{ - if (strcmp(opt.volume, "-") == 0) { - if ((fd_in = fileno(stdin)) == -1) - perr_exit("fileno for stdout failed"); - } else { - if ((fd_in = open(opt.volume, O_RDONLY)) == -1) - perr_exit("failed to open image"); - } - if (read_all(&fd_in, &image_hdr, NTFSCLONE_IMG_HEADER_SIZE_OLD) == -1) - perr_exit("read_all"); - if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0) - err_exit("Input file is not an image! (invalid magic)\n"); - if (image_hdr.major_ver < NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE) { - image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR; - image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR; -#if (__BYTE_ORDER == __BIG_ENDIAN) - Printf("Old image format detected. If the image was created " - "on a little endian architecture it will not " - "work. Use a more recent version of " - "ntfsclone to recreate the image.\n"); - image_hdr.cluster_size = cpu_to_le32(image_hdr.cluster_size); - image_hdr.device_size = cpu_to_sle64(image_hdr.device_size); - image_hdr.nr_clusters = cpu_to_sle64(image_hdr.nr_clusters); - image_hdr.inuse = cpu_to_sle64(image_hdr.inuse); -#endif - image_hdr.offset_to_image_data = - const_cpu_to_le32((sizeof(image_hdr) + 7) & ~7); - image_is_host_endian = TRUE; - } else { -#ifdef __sun - u32 offset_to_image_data; -#else - typeof(image_hdr.offset_to_image_data) offset_to_image_data; -#endif - int delta; - - if (image_hdr.major_ver > NTFSCLONE_IMG_VER_MAJOR) - err_exit("Do not know how to handle image format " - "version %d.%d. Please obtain a " - "newer version of ntfsclone.\n", - image_hdr.major_ver, - image_hdr.minor_ver); - /* Read the image header data offset. */ - if (read_all(&fd_in, &offset_to_image_data, - sizeof(offset_to_image_data)) == -1) - perr_exit("read_all"); - image_hdr.offset_to_image_data = - le32_to_cpu(offset_to_image_data); - /* - * Read any fields from the header that we have not read yet so - * that the input stream is positioned correctly. This means - * we can support future minor versions that just extend the - * header in a backwards compatible way. - */ - delta = offset_to_image_data - (NTFSCLONE_IMG_HEADER_SIZE_OLD + - sizeof(image_hdr.offset_to_image_data)); - if (delta > 0) { - char *dummy_buf; - - dummy_buf = malloc(delta); - if (!dummy_buf) - perr_exit("malloc dummy_buffer"); - if (read_all(&fd_in, dummy_buf, delta) == -1) - perr_exit("read_all"); - } - } - return sle64_to_cpu(image_hdr.device_size); -} - -static s64 open_volume(void) -{ - s64 device_size; - - mount_volume(NTFS_MNT_RDONLY); - - device_size = ntfs_device_size_get(vol->u.dev, 1); - if (device_size <= 0) - err_exit("Couldn't get device size (%lld)!\n", device_size); - - print_volume_size("Current device size", device_size); - - if (device_size < vol->nr_clusters * vol->cluster_size) - err_exit("Current NTFS volume size is bigger than the device " - "size (%lld)!\nCorrupt partition table or incorrect " - "device partitioning?\n", device_size); - - return device_size; -} - -static void initialise_image_hdr(s64 device_size, s64 inuse) -{ - memcpy(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE); - image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR; - image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR; - image_hdr.cluster_size = cpu_to_le32(vol->cluster_size); - image_hdr.device_size = cpu_to_sle64(device_size); - image_hdr.nr_clusters = cpu_to_sle64(vol->nr_clusters); - image_hdr.inuse = cpu_to_sle64(inuse); - image_hdr.offset_to_image_data = cpu_to_le32((sizeof(image_hdr) + 7) & - ~7); -} - -static void check_output_device(s64 input_size) -{ - if (opt.blkdev_out) { - s64 dest_size = device_size_get(fd_out); - if (dest_size < input_size) - err_exit("Output device is too small (%lld) to fit the " - "NTFS image (%lld).\n", dest_size, input_size); - - check_if_mounted(opt.output, 0); - } else - set_filesize(input_size); -} - -static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni) -{ - ntfs_attr_search_ctx *ret; - - if ((ret = ntfs_attr_get_search_ctx(ni, NULL)) == NULL) - perr_printf("ntfs_attr_get_search_ctx"); - - return ret; -} - -/** - * lookup_data_attr - * - * Find the $DATA attribute (with or without a name) for the given ntfs inode. - */ -static ntfs_attr_search_ctx *lookup_data_attr(ntfs_inode *ni, const char *aname) -{ - ntfs_attr_search_ctx *ctx; - ntfschar *ustr; - int len = 0; - - if ((ctx = attr_get_search_ctx(ni)) == NULL) - return NULL; - - if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) { - perr_printf("Couldn't convert '%s' to Unicode", aname); - goto error_out; - } - - if (ntfs_attr_lookup(AT_DATA, ustr, len, 0, 0, NULL, 0, ctx)) { - perr_printf("ntfs_attr_lookup"); - goto error_out; - } - ntfs_ucsfree(ustr); - return ctx; -error_out: - ntfs_attr_put_search_ctx(ctx); - return NULL; -} - -static void ignore_bad_clusters(ntfs_walk_clusters_ctx *image) -{ - ntfs_inode *ni; - ntfs_attr_search_ctx *ctx = NULL; - runlist *rl, *rl_bad; - s64 nr_bad_clusters = 0; - - if (!(ni = ntfs_inode_open(vol, FILE_BadClus))) - perr_exit("ntfs_open_inode"); - - if ((ctx = lookup_data_attr(ni, "$Bad")) == NULL) - exit(1); - - if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL))) - perr_exit("ntfs_mapping_pairs_decompress"); - - for (rl = rl_bad; rl->length; rl++) { - s64 lcn = rl->lcn; - - if (lcn == LCN_HOLE || lcn < 0) - continue; - - for (; lcn < rl->lcn + rl->length; lcn++, nr_bad_clusters++) { - if (ntfs_bit_get_and_set(lcn_bitmap.bm, lcn, 0)) - image->inuse--; - } - } - if (nr_bad_clusters) - Printf("WARNING: The disk has %lld or more bad sectors" - " (hardware faults).\n", nr_bad_clusters); - free(rl_bad); - - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_close(ni)) - perr_exit("ntfs_inode_close failed for $BadClus"); -} - -static void check_dest_free_space(u64 src_bytes) -{ - u64 dest_bytes; - struct statvfs stvfs; - struct stat st; - - if (opt.metadata || opt.blkdev_out || opt.std_out) - return; - /* - * TODO: save_image needs a bit more space than src_bytes - * due to the free space encoding overhead. - */ - if (fstatvfs(fd_out, &stvfs) == -1) { - Printf("WARNING: Unknown free space on the destination: %s\n", - strerror(errno)); - return; - } - - /* If file is a FIFO then there is no point in checking the size. */ - if (!fstat(fd_out, &st)) { - if (S_ISFIFO(st.st_mode)) - return; - } else - Printf("WARNING: fstat failed: %s\n", strerror(errno)); - - dest_bytes = (u64)stvfs.f_frsize * stvfs.f_bfree; - if (!dest_bytes) - dest_bytes = (u64)stvfs.f_bsize * stvfs.f_bfree; - - if (dest_bytes < src_bytes) - err_exit("Destination doesn't have enough free space: " - "%llu MB < %llu MB\n", - rounded_up_division(dest_bytes, NTFS_MBYTE), - rounded_up_division(src_bytes, NTFS_MBYTE)); -} - -int main(int argc, char **argv) -{ - ntfs_walk_clusters_ctx image; - s64 device_size; /* input device size in bytes */ - s64 ntfs_size; - unsigned int wiped_total = 0; - - /* print to stderr, stdout can be an NTFS image ... */ - fprintf(stderr, "%s v%s (libntfs %s)\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - msg_out = stderr; - - parse_options(argc, argv); - - utils_set_locale(); - - if (opt.restore_image) { - device_size = open_image(); - ntfs_size = sle64_to_cpu(image_hdr.nr_clusters) * - le32_to_cpu(image_hdr.cluster_size); - } else { - device_size = open_volume(); - ntfs_size = vol->nr_clusters * vol->cluster_size; - } - // FIXME: This needs to be the cluster size... - ntfs_size += 512; /* add backup boot sector */ - - if (opt.std_out) { - if ((fd_out = fileno(stdout)) == -1) - perr_exit("fileno for stdout failed"); - } else { - /* device_size_get() might need to read() */ - int flags = O_RDWR; - - if (!opt.blkdev_out) { - flags |= O_CREAT | O_TRUNC; - if (!opt.overwrite) - flags |= O_EXCL; - } - - if ((fd_out = open(opt.output, flags, S_IRUSR | S_IWUSR)) == -1) - perr_exit("Opening file '%s' failed", opt.output); - - if (!opt.save_image) - check_output_device(ntfs_size); - } - - if (opt.restore_image) { - print_image_info(); - restore_image(); - fsync_clone(fd_out); - exit(0); - } - - setup_lcn_bitmap(); - memset(&image, 0, sizeof(image)); - backup_clusters.image = ℑ - - walk_clusters(vol, &backup_clusters); - compare_bitmaps(&lcn_bitmap); - print_disk_usage("", vol->cluster_size, vol->nr_clusters, image.inuse); - - check_dest_free_space(vol->cluster_size * image.inuse); - - ignore_bad_clusters(&image); - - if (opt.save_image) - initialise_image_hdr(device_size, image.inuse); - - /* FIXME: save backup boot sector */ - - if (opt.std_out || !opt.metadata) { - s64 nr_clusters_to_save = image.inuse; - if (opt.std_out && !opt.save_image) - nr_clusters_to_save = vol->nr_clusters; - - clone_ntfs(nr_clusters_to_save); - fsync_clone(fd_out); - exit(0); - } - - wipe = 1; - opt.volume = opt.output; - /* 'force' again mount for dirty volumes (e.g. after resize). - FIXME: use mount flags to avoid potential side-effects in future */ - opt.force++; - mount_volume(0); - - free(lcn_bitmap.bm); - setup_lcn_bitmap(); - memset(&image, 0, sizeof(image)); - backup_clusters.image = ℑ - - walk_clusters(vol, &backup_clusters); - - Printf("Num of MFT records = %10lld\n", - (long long)vol->mft_na->initialized_size >> - vol->mft_record_size_bits); - Printf("Num of used MFT records = %10u\n", nr_used_mft_records); - - Printf("Wiped unused MFT data = %10u\n", wiped_unused_mft_data); - Printf("Wiped deleted MFT data = %10u\n", wiped_unused_mft); - Printf("Wiped resident user data = %10u\n", wiped_resident_data); - Printf("Wiped timestamp data = %10u\n", wiped_timestamp_data); - - wiped_total += wiped_unused_mft_data; - wiped_total += wiped_unused_mft; - wiped_total += wiped_resident_data; - wiped_total += wiped_timestamp_data; - Printf("Wiped totally = %10u\n", wiped_total); - - fsync_clone(fd_out); - exit(0); -} diff --git a/usr/src/cmd/ntfsprogs/ntfscluster.c b/usr/src/cmd/ntfsprogs/ntfscluster.c deleted file mode 100644 index 64ee4af130..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscluster.c +++ /dev/null @@ -1,565 +0,0 @@ -/** - * ntfscluster - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2003 Richard Russon - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2005-2006 Szabolcs Szakacsits - * - * This utility will locate the owner of any given sector or cluster. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif - -#include "compat.h" -#include "ntfscluster.h" -#include "types.h" -#include "attrib.h" -#include "utils.h" -#include "volume.h" -#include "debug.h" -#include "dir.h" -#include "cluster.h" -#include "version.h" -#include "logging.h" - -static const char *EXEC_NAME = "ntfscluster"; -static struct options opts; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s) - Find the owner of any given sector or " - "cluster.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - ntfs_log_info("Copyright (c) 2002-2003 Richard Russon\n"); - ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n"); - ntfs_log_info("Copyright (c) 2005-2006 Szabolcs Szakacsits\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device\n" - " -i, --info Print information about the volume (default)\n" - "\n" - " -c, --cluster RANGE Look for objects in this range of clusters\n" - " -s, --sector RANGE Look for objects in this range of sectors\n" - " -I, --inode NUM Show information about this inode\n" - " -F, --filename NAME Show information about this file\n" - /* " -l, --last Find the last file on the volume\n" */ - "\n" - " -f, --force Use less caution\n" - " -q, --quiet Less output\n" - " -v, --verbose More output\n" - " -V, --version Version information\n" - " -h, --help Print this help\n\n", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char **argv) -{ - static const char *sopt = "-c:F:fh?I:ilqs:vV"; - static const struct option lopt[] = { - { "cluster", required_argument, NULL, 'c' }, - { "filename", required_argument, NULL, 'F' }, - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "info", no_argument, NULL, 'i' }, - { "inode", required_argument, NULL, 'I' }, - { "last", no_argument, NULL, 'l' }, - { "quiet", no_argument, NULL, 'q' }, - { "sector", required_argument, NULL, 's' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - char *end = NULL; - - opterr = 0; /* We'll handle the errors, thank you. */ - - opts.action = act_none; - opts.range_begin = -1; - opts.range_end = -1; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opts.device) { - opts.device = argv[optind-1]; - } else { - opts.device = NULL; - err++; - } - break; - - case 'c': - if ((opts.action == act_none) && - (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE))) - opts.action = act_cluster; - else - opts.action = act_error; - break; - case 'F': - if (opts.action == act_none) { - opts.action = act_file; - opts.filename = optarg; - } else { - opts.action = act_error; - } - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp (argv[optind-1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option (argv[optind-1])) - err++; - break; - } - help++; - break; - case 'I': - if (opts.action == act_none) { - opts.action = act_inode; - opts.inode = strtol(optarg, &end, 0); - if (end && *end) - err++; - } else { - opts.action = act_error; - } - break; - case 'i': - if (opts.action == act_none) - opts.action = act_info; - else - opts.action = act_error; - break; - case 'l': - if (opts.action == act_none) - opts.action = act_last; - else - opts.action = act_error; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 's': - if ((opts.action == act_none) && - (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE))) - opts.action = act_sector; - else - opts.action = act_error; - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - default: - if ((optopt == 'c') || (optopt == 's')) - ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]); - else - ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (opts.action == act_none) - opts.action = act_info; - if (opts.action == act_info) - opts.quiet = 0; - - if (opts.device == NULL) { - if (argc > 1) - ntfs_log_error("You must specify exactly one device.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at the same time.\n"); - err++; - } - - if (opts.action == act_error) { - ntfs_log_error("You may only specify one action: --info, --cluster, --sector or --last.\n"); - err++; - } else if (opts.range_begin > opts.range_end) { - ntfs_log_error("The range must be in ascending order.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - - -/** - * info - */ -static int info(ntfs_volume *vol) -{ - u64 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u; - int cb, sb, cps; - u64 uc = 0, mc = 0, fc = 0; - - struct mft_search_ctx *m_ctx; - ntfs_attr_search_ctx *a_ctx; - runlist_element *rl; - ATTR_RECORD *rec; - int z; - int inuse = 0; - - m_ctx = mft_get_search_ctx(vol); - m_ctx->flags_search = FEMR_IN_USE | FEMR_METADATA | FEMR_BASE_RECORD | FEMR_NOT_BASE_RECORD; - while (mft_next_record(m_ctx) == 0) { - - if (!(m_ctx->flags_match & FEMR_IN_USE)) - continue; - - inuse++; - - a_ctx = ntfs_attr_get_search_ctx(m_ctx->inode, NULL); - - while ((rec = find_attribute(AT_UNUSED, a_ctx))) { - - if (!rec->non_resident) - continue; - - rl = ntfs_mapping_pairs_decompress(vol, rec, NULL); - - for (z = 0; rl[z].length > 0; z++) - { - if (rl[z].lcn >= 0) { - if (m_ctx->flags_match & FEMR_METADATA) - mc += rl[z].length; - else - uc += rl[z].length; - } - - } - - free(rl); - } - - ntfs_attr_put_search_ctx(a_ctx); - } - mft_put_search_ctx(m_ctx); - - cb = vol->cluster_size_bits; - sb = vol->sector_size_bits; - cps = cb - sb; - - fc = vol->nr_clusters-mc-uc; - fc <<= cb; - mc <<= cb; - uc <<= cb; - - a = vol->sector_size; - b = vol->cluster_size; - c = 1 << cps; - d = vol->nr_clusters << cb; - e = vol->nr_clusters; - f = vol->nr_clusters >> cps; - g = vol->mft_na->initialized_size >> vol->mft_record_size_bits; - h = inuse; - i = h * 100 / g; - j = fc; - k = fc >> sb; - l = fc >> cb; - m = fc * 100 / b / e; - n = uc; - o = uc >> sb; - p = uc >> cb; - q = uc * 100 / b / e; - r = mc; - s = mc >> sb; - t = mc >> cb; - u = mc * 100 / b / e; - - ntfs_log_info("bytes per sector : %llu\n", (unsigned long long)a); - ntfs_log_info("bytes per cluster : %llu\n", (unsigned long long)b); - ntfs_log_info("sectors per cluster : %llu\n", (unsigned long long)c); - ntfs_log_info("bytes per volume : %llu\n", (unsigned long long)d); - ntfs_log_info("sectors per volume : %llu\n", (unsigned long long)e); - ntfs_log_info("clusters per volume : %llu\n", (unsigned long long)f); - ntfs_log_info("initialized mft records : %llu\n", (unsigned long long)g); - ntfs_log_info("mft records in use : %llu\n", (unsigned long long)h); - ntfs_log_info("mft records percentage : %llu\n", (unsigned long long)i); - ntfs_log_info("bytes of free space : %llu\n", (unsigned long long)j); - ntfs_log_info("sectors of free space : %llu\n", (unsigned long long)k); - ntfs_log_info("clusters of free space : %llu\n", (unsigned long long)l); - ntfs_log_info("percentage free space : %llu\n", (unsigned long long)m); - ntfs_log_info("bytes of user data : %llu\n", (unsigned long long)n); - ntfs_log_info("sectors of user data : %llu\n", (unsigned long long)o); - ntfs_log_info("clusters of user data : %llu\n", (unsigned long long)p); - ntfs_log_info("percentage user data : %llu\n", (unsigned long long)q); - ntfs_log_info("bytes of metadata : %llu\n", (unsigned long long)r); - ntfs_log_info("sectors of metadata : %llu\n", (unsigned long long)s); - ntfs_log_info("clusters of metadata : %llu\n", (unsigned long long)t); - ntfs_log_info("percentage metadata : %llu\n", (unsigned long long)u); - - return 0; -} - -/** - * dump_file - */ -static int dump_file(ntfs_volume *vol, ntfs_inode *ino) -{ - char buffer[1024]; - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *rec; - int i; - runlist *runs; - - utils_inode_get_name(ino, buffer, sizeof(buffer)); - - ntfs_log_info("Dump: %s\n", buffer); - - ctx = ntfs_attr_get_search_ctx(ino, NULL); - - while ((rec = find_attribute(AT_UNUSED, ctx))) { - ntfs_log_info(" 0x%02x - ", rec->type); - if (rec->non_resident) { - ntfs_log_info("non-resident\n"); - runs = ntfs_mapping_pairs_decompress(vol, rec, NULL); - if (runs) { - ntfs_log_info(" VCN LCN Length\n"); - for (i = 0; runs[i].length > 0; i++) { - ntfs_log_info(" %8lld %8lld %8lld\n", - (long long)runs[i].vcn, - (long long)runs[i].lcn, - (long long) - runs[i].length); - } - free(runs); - } - } else { - ntfs_log_info("resident\n"); - } - } - - ntfs_attr_put_search_ctx(ctx); - return 0; -} - -/** - * print_match - */ -static int print_match(ntfs_inode *ino, ATTR_RECORD *attr, - runlist_element *run, void *data __attribute__((unused))) -{ - char *buffer; - - if (!ino || !attr || !run) - return 1; - - buffer = malloc(MAX_PATH); - if (!buffer) { - ntfs_log_error("!buffer\n"); - return 1; - } - - utils_inode_get_name(ino, buffer, MAX_PATH); - ntfs_log_info("Inode %llu %s", (unsigned long long)ino->mft_no, buffer); - - utils_attr_get_name(ino->vol, attr, buffer, MAX_PATH); - ntfs_log_info("/%s\n", buffer); - - free(buffer); - return 0; -} - -/** - * find_last - */ -static int find_last(ntfs_inode *ino, ATTR_RECORD *attr, runlist_element *run, - void *data) -{ - struct match *m; - - if (!ino || !attr || !run || !data) - return 1; - - m = data; - - if ((run->lcn + run->length) > m->lcn) { - m->inum = ino->mft_no; - m->lcn = run->lcn + run->length; - } - - return 0; -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - ntfs_volume *vol; - ntfs_inode *ino = NULL; - struct match m; - int result = 1; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - if (!parse_options(argc, argv)) - return 1; - - utils_set_locale(); - - vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) - return 1; - - switch (opts.action) { - case act_sector: - if (opts.range_begin == opts.range_end) - ntfs_log_quiet("Searching for sector %llu\n", - (unsigned long long)opts.range_begin); - else - ntfs_log_quiet("Searching for sector range %llu-%llu\n", (unsigned long long)opts.range_begin, (unsigned long long)opts.range_end); - /* Convert to clusters */ - opts.range_begin >>= (vol->cluster_size_bits - vol->sector_size_bits); - opts.range_end >>= (vol->cluster_size_bits - vol->sector_size_bits); - result = cluster_find(vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL); - break; - case act_cluster: - if (opts.range_begin == opts.range_end) - ntfs_log_quiet("Searching for cluster %llu\n", - (unsigned long long)opts.range_begin); - else - ntfs_log_quiet("Searching for cluster range %llu-%llu\n", (unsigned long long)opts.range_begin, (unsigned long long)opts.range_end); - result = cluster_find(vol, opts.range_begin, opts.range_end, (cluster_cb*)&print_match, NULL); - break; - case act_file: - ino = ntfs_pathname_to_inode(vol, NULL, opts.filename); - if (ino) - result = dump_file(vol, ino); - break; - case act_inode: - ino = ntfs_inode_open(vol, opts.inode); - if (ino) { - result = dump_file(vol, ino); - ntfs_inode_close(ino); - } else { - ntfs_log_error("Cannot open inode %llu\n", - (unsigned long long)opts.inode); - } - break; - case act_last: - memset(&m, 0, sizeof(m)); - m.lcn = -1; - result = cluster_find(vol, 0, LONG_MAX, (cluster_cb*)&find_last, &m); - if (m.lcn >= 0) { - ino = ntfs_inode_open(vol, m.inum); - if (ino) { - result = dump_file(vol, ino); - ntfs_inode_close(ino); - } else { - ntfs_log_error("Cannot open inode %llu\n", - (unsigned long long) - opts.inode); - } - result = 0; - } else { - result = 1; - } - break; - case act_info: - default: - result = info(vol); - break; - } - - ntfs_umount(vol, FALSE); - return result; -} - - diff --git a/usr/src/cmd/ntfsprogs/ntfscluster.h b/usr/src/cmd/ntfsprogs/ntfscluster.h deleted file mode 100644 index 5a3d6b3c04..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscluster.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ntfscluster - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2003 Richard Russon - * - * This utility will locate the owner of any given sector or cluster. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFSCLUSTER_H_ -#define _NTFSCLUSTER_H_ - -#include "types.h" -#include "layout.h" - -enum action { - act_none, - act_info, - act_cluster, - act_sector, - act_inode, - act_file, - act_last, - act_error, -}; - -struct options { - char *device; /* Device/File to work with */ - enum action action; /* What to do */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int force; /* Override common sense */ - char *filename; /* File to examine */ - u64 inode; /* Inode to examine */ - s64 range_begin; /* Look for objects in this range */ - s64 range_end; -}; - -struct match { - u64 inum; /* Inode number */ - LCN lcn; /* Last cluster in use */ - ATTR_TYPES type; /* Attribute type */ - ntfschar *name; /* Attribute name */ - int name_len; /* Length of attribute name */ -}; - -#endif /* _NTFSCLUSTER_H_ */ - - diff --git a/usr/src/cmd/ntfsprogs/ntfscmp.c b/usr/src/cmd/ntfsprogs/ntfscmp.c deleted file mode 100644 index d247c259b0..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscmp.c +++ /dev/null @@ -1,1005 +0,0 @@ -/** - * ntfscmp - Part of the Linux-NTFS project. - * - * Copyright (c) 2005-2006 Szabolcs Szakacsits - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility compare two NTFS volumes. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "compat.h" -#include "utils.h" -#include "mst.h" -#include "version.h" -#include "support.h" - -static const char *EXEC_NAME = "ntfscmp"; - -static const char *invalid_ntfs_msg = -"Apparently device '%s' doesn't have a valid NTFS.\n" -"Maybe you selected the wrong partition? Or the whole disk instead of a\n" -"partition (e.g. /dev/hda, not /dev/hda1)?\n"; - -static const char *corrupt_volume_msg = -"Apparently you have a corrupted NTFS. Please run the filesystem checker\n" -"on Windows by invoking chkdsk /f. Don't forget the /f (force) parameter,\n" -"it's important! You probably also need to reboot Windows to take effect.\n"; - -static const char *hibernated_volume_msg = -"Apparently the NTFS partition is hibernated. Windows must be resumed and\n" -"turned off properly\n"; - - -static struct { - int debug; - int show_progress; - int verbose; - char *vol1; - char *vol2; -} opt; - - -#define NTFS_PROGBAR 0x0001 -#define NTFS_PROGBAR_SUPPRESS 0x0002 - -struct progress_bar { - u64 start; - u64 stop; - int resolution; - int flags; - float unit; -}; - -/* WARNING: don't modify the text, external tools grep for it */ -#define ERR_PREFIX "ERROR" -#define PERR_PREFIX ERR_PREFIX "(%d): " -#define NERR_PREFIX ERR_PREFIX ": " - -__attribute__((format(printf, 2, 3))) -static void perr_printf(int newline, const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - fprintf(stdout, PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fprintf(stdout, ": %s", strerror(eo)); - if (newline) - fprintf(stdout, "\n"); - fflush(stdout); - fflush(stderr); -} - -#define perr_print(...) perr_printf(0, __VA_ARGS__) -#define perr_println(...) perr_printf(1, __VA_ARGS__) - -__attribute__((format(printf, 1, 2))) -static void err_printf(const char *fmt, ...) -{ - va_list ap; - - fprintf(stdout, NERR_PREFIX); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fflush(stdout); - fflush(stderr); -} - -/** - * err_exit - * - * Print and error message and exit the program. - */ -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int err_exit(const char *fmt, ...) -{ - va_list ap; - - fprintf(stdout, NERR_PREFIX); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fflush(stdout); - fflush(stderr); - exit(1); -} - -/** - * perr_exit - * - * Print and error message and exit the program - */ -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int perr_exit(const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - fprintf(stdout, PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - printf(": %s\n", strerror(eo)); - fflush(stdout); - fflush(stderr); - exit(1); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -__attribute__((noreturn)) -static void usage(void) -{ - - printf("\nUsage: %s [OPTIONS] DEVICE1 DEVICE2\n" - " Compare two NTFS volumes and tell the differences.\n" - "\n" - " -P, --no-progress-bar Don't show progress bar\n" - " -v, --verbose More output\n" - " -h, --help Display this help\n" -#ifdef DEBUG - " -d, --debug Show debug information\n" -#endif - "\n", EXEC_NAME); - printf("%s%s", ntfs_bugs, ntfs_home); - exit(1); -} - - -static void parse_options(int argc, char **argv) -{ - static const char *sopt = "-dhPv"; - static const struct option lopt[] = { -#ifdef DEBUG - { "debug", no_argument, NULL, 'd' }, -#endif - { "help", no_argument, NULL, 'h' }, - { "no-progress-bar", no_argument, NULL, 'P' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } - }; - - int c; - - memset(&opt, 0, sizeof(opt)); - opt.show_progress = 1; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opt.vol1) { - opt.vol1 = argv[optind - 1]; - } else if (!opt.vol2) { - opt.vol2 = argv[optind - 1]; - } else { - err_printf("Too many arguments!\n"); - usage(); - } - break; -#ifdef DEBUG - case 'd': - opt.debug++; - break; -#endif - case 'h': - case '?': - usage(); - case 'P': - opt.show_progress = 0; - break; - case 'v': - opt.verbose++; - break; - default: - err_printf("Unknown option '%s'.\n", argv[optind - 1]); - usage(); - break; - } - } - - if (opt.vol1 == NULL || opt.vol2 == NULL) { - err_printf("You must specify exactly 2 volumes.\n"); - usage(); - } - - /* Redirect stderr to stdout, note fflush()es are essential! */ - fflush(stdout); - fflush(stderr); - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) { - perror("Failed to redirect stderr to stdout"); - exit(1); - } - fflush(stdout); - fflush(stderr); - -#ifdef DEBUG - if (!opt.debug) - if (!freopen("/dev/null", "w", stderr)) - perr_exit("Failed to redirect stderr to /dev/null"); -#endif -} - -static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni) -{ - ntfs_attr_search_ctx *ret; - - if ((ret = ntfs_attr_get_search_ctx(ni, NULL)) == NULL) - perr_println("ntfs_attr_get_search_ctx"); - - return ret; -} - -static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags) -{ - p->start = start; - p->stop = stop; - p->unit = 100.0 / (stop - start); - p->resolution = 100; - p->flags = flags; -} - -static void progress_update(struct progress_bar *p, u64 current) -{ - float percent; - - if (!(p->flags & NTFS_PROGBAR)) - return; - if (p->flags & NTFS_PROGBAR_SUPPRESS) - return; - - /* WARNING: don't modify the texts, external tools grep for them */ - percent = p->unit * current; - if (current != p->stop) { - if ((current - p->start) % p->resolution) - return; - printf("%6.2f percent completed\r", percent); - } else - printf("100.00 percent completed\n"); - fflush(stdout); -} - -static u64 inumber(ntfs_inode *ni) -{ - if (ni->nr_extents >= 0) - return ni->mft_no; - - return ni->u.base_ni->mft_no; -} - -static int inode_close(ntfs_inode *ni) -{ - if (ni == NULL) - return 0; - - if (ntfs_inode_close(ni)) { - perr_println("ntfs_inode_close: inode %llu", inumber(ni)); - return -1; - } - return 0; -} - -static inline s64 get_nr_mft_records(ntfs_volume *vol) -{ - return vol->mft_na->initialized_size >> vol->mft_record_size_bits; -} - -#define NTFSCMP_OK 0 -#define NTFSCMP_INODE_OPEN_ERROR 1 -#define NTFSCMP_INODE_OPEN_IO_ERROR 2 -#define NTFSCMP_INODE_OPEN_ENOENT_ERROR 3 -#define NTFSCMP_EXTENSION_RECORD 4 -#define NTFSCMP_INODE_CLOSE_ERROR 5 - -static const char *ntfscmp_errs[] = { - "OK", - "INODE_OPEN_ERROR", - "INODE_OPEN_IO_ERROR", - "INODE_OPEN_ENOENT_ERROR", - "EXTENSION_RECORD", - "INODE_CLOSE_ERROR", - "" -}; - - -static const char *err2string(int err) -{ - return ntfscmp_errs[err]; -} - -static const char *pret2str(void *p) -{ - if (p == NULL) - return "FAILED"; - return "OK"; -} - -static int inode_open(ntfs_volume *vol, MFT_REF mref, ntfs_inode **ni) -{ - *ni = ntfs_inode_open(vol, mref); - if (*ni == NULL) { - if (errno == EIO) - return NTFSCMP_INODE_OPEN_IO_ERROR; - if (errno == ENOENT) - return NTFSCMP_INODE_OPEN_ENOENT_ERROR; - - perr_println("Reading inode %lld failed", mref); - return NTFSCMP_INODE_OPEN_ERROR; - } - - if ((*ni)->mrec->base_mft_record) { - - if (inode_close(*ni) != 0) - return NTFSCMP_INODE_CLOSE_ERROR; - - return NTFSCMP_EXTENSION_RECORD; - } - - return NTFSCMP_OK; -} - -static ntfs_inode *base_inode(ntfs_attr_search_ctx *ctx) -{ - if (ctx->base_ntfs_ino) - return ctx->base_ntfs_ino; - - return ctx->ntfs_ino; -} - -static void print_inode(u64 inum) -{ - printf("Inode %llu ", inum); -} - -static void print_inode_ni(ntfs_inode *ni) -{ - print_inode(inumber(ni)); -} - -static void print_attribute_type(ATTR_TYPES atype) -{ - printf("attribute 0x%x", atype); -} - -static void print_attribute_name(char *name) -{ - if (name) - printf(":%s", name); -} - -#define GET_ATTR_NAME(a) \ - ((ntfschar *)(((u8 *)(a)) + le16_to_cpu((a)->name_offset))), \ - ((a)->name_length) - -static void free_name(char **name) -{ - if (*name) { - free(*name); - *name = NULL; - } -} - -static char *get_attr_name(u64 mft_no, - ATTR_TYPES atype, - const ntfschar *uname, - const int uname_len) -{ - char *name = NULL; - int name_len; - - if (atype == AT_END) - return NULL; - - name_len = ntfs_ucstombs(uname, uname_len, &name, 0); - if (name_len < 0) { - perr_print("ntfs_ucstombs"); - print_inode(mft_no); - print_attribute_type(atype); - puts(""); - exit(1); - - } else if (name_len > 0) - return name; - - free_name(&name); - return NULL; -} - -static char *get_attr_name_na(ntfs_attr *na) -{ - return get_attr_name(inumber(na->ni), na->type, na->name, na->name_len); -} - -static char *get_attr_name_ctx(ntfs_attr_search_ctx *ctx) -{ - u64 mft_no = inumber(ctx->ntfs_ino); - ATTR_TYPES atype = ctx->attr->type; - - return get_attr_name(mft_no, atype, GET_ATTR_NAME(ctx->attr)); -} - -static void print_attribute(ATTR_TYPES atype, char *name) -{ - print_attribute_type(atype); - print_attribute_name(name); - printf(" "); -} - -static void print_na(ntfs_attr *na) -{ - char *name = get_attr_name_na(na); - print_inode_ni(na->ni); - print_attribute(na->type, name); - free_name(&name); -} - -static void print_attribute_ctx(ntfs_attr_search_ctx *ctx) -{ - char *name = get_attr_name_ctx(ctx); - print_attribute(ctx->attr->type, name); - free_name(&name); -} - -static void print_ctx(ntfs_attr_search_ctx *ctx) -{ - char *name = get_attr_name_ctx(ctx); - print_inode_ni(base_inode(ctx)); - print_attribute(ctx->attr->type, name); - free_name(&name); -} - -static void print_differ(ntfs_attr *na) -{ - print_na(na); - printf("content: DIFFER\n"); -} - -static int cmp_buffer(u8 *buf1, u8 *buf2, long long int size, ntfs_attr *na) -{ - if (memcmp(buf1, buf2, size)) { - print_differ(na); - return -1; - } - return 0; -} - -struct cmp_ia { - INDEX_ALLOCATION *ia; - INDEX_ALLOCATION *tmp_ia; - u8 *bitmap; - u8 *byte; - s64 bm_size; -}; - -static int setup_cmp_ia(ntfs_attr *na, struct cmp_ia *cia) -{ - cia->bitmap = ntfs_attr_readall(na->ni, AT_BITMAP, na->name, - na->name_len, &cia->bm_size); - if (!cia->bitmap) { - perr_println("Failed to readall BITMAP"); - return -1; - } - cia->byte = cia->bitmap; - - cia->tmp_ia = cia->ia = ntfs_malloc(na->data_size); - if (!cia->tmp_ia) - goto free_bm; - - if (ntfs_attr_pread(na, 0, na->data_size, cia->ia) != na->data_size) { - perr_println("Failed to pread INDEX_ALLOCATION"); - goto free_ia; - } - - return 0; -free_ia: - free(cia->ia); -free_bm: - free(cia->bitmap); - return -1; -} - -static void cmp_index_allocation(ntfs_attr *na1, ntfs_attr *na2) -{ - struct cmp_ia cia1, cia2; - int bit, ret1, ret2; - u32 ib_size; - - if (setup_cmp_ia(na1, &cia1)) - return; - if (setup_cmp_ia(na2, &cia2)) - return; - /* - * FIXME: ia can be the same even if the bitmap sizes are different. - */ - if (cia1.bm_size != cia1.bm_size) - goto out; - - if (cmp_buffer(cia1.bitmap, cia2.bitmap, cia1.bm_size, na1)) - goto out; - - if (cmp_buffer((u8 *)cia1.ia, (u8 *)cia2.ia, 0x18, na1)) - goto out; - - ib_size = le32_to_cpu(cia1.ia->index.allocated_size) + 0x18; - - bit = 0; - while ((u8 *)cia1.tmp_ia < (u8 *)cia1.ia + na1->data_size) { - if (*cia1.byte & (1 << bit)) { - ret1 = ntfs_mst_post_read_fixup((NTFS_RECORD *) - cia1.tmp_ia, ib_size); - ret2 = ntfs_mst_post_read_fixup((NTFS_RECORD *) - cia2.tmp_ia, ib_size); - if (ret1 != ret2) { - print_differ(na1); - goto out; - } - - if (ret1 == -1) - continue; - - if (cmp_buffer(((u8 *)cia1.tmp_ia) + 0x18, - ((u8 *)cia2.tmp_ia) + 0x18, - le32_to_cpu(cia1.ia-> - index.index_length), na1)) - goto out; - } - - cia1.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia1.tmp_ia + ib_size); - cia2.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia2.tmp_ia + ib_size); - - bit++; - if (bit > 7) { - bit = 0; - cia1.byte++; - } - } -out: - free(cia1.ia); - free(cia2.ia); - free(cia1.bitmap); - free(cia2.bitmap); - return; -} - -static void cmp_attribute_data(ntfs_attr *na1, ntfs_attr *na2) -{ - s64 pos; - s64 count1 = 0, count2; - u8 buf1[NTFS_BUF_SIZE]; - u8 buf2[NTFS_BUF_SIZE]; - - for (pos = 0; pos <= na1->data_size; pos += count1) { - - count1 = ntfs_attr_pread(na1, pos, NTFS_BUF_SIZE, buf1); - count2 = ntfs_attr_pread(na2, pos, NTFS_BUF_SIZE, buf2); - - if (count1 != count2) { - print_na(na1); - printf("abrupt length: %lld != %lld ", - na1->data_size, na2->data_size); - printf("(count: %lld != %lld)", count1, count2); - puts(""); - return; - } - - if (count1 == -1) { - err_printf("%s read error: ", "cmp_attribute_data"); - print_na(na1); - printf("len = %lld, pos = %lld\n", na1->data_size, pos); - exit(1); - } - - if (count1 == 0) { - - if (pos + count1 == na1->data_size) - return; /* we are ready */ - - err_printf("%s read error before EOF: ", "cmp_attribute_data"); - print_na(na1); - printf("%lld != %lld\n", pos + count1, na1->data_size); - exit(1); - } - - if (cmp_buffer(buf1, buf2, count1, na1)) - return; - } - - err_printf("%s read overrun: ", "cmp_attribute_data"); - print_na(na1); - err_printf("(len = %lld, pos = %lld, count = %lld)\n", - na1->data_size, pos, count1); - exit(1); -} - -static int cmp_attribute_header(ATTR_RECORD *a1, ATTR_RECORD *a2) -{ - u32 header_size = offsetof(ATTR_RECORD, u.res.resident_end); - - if (a1->non_resident != a2->non_resident) - return 1; - - if (a1->non_resident) { - /* - * FIXME: includes paddings which are not handled by ntfsinfo! - */ - header_size = le32_to_cpu(a1->length); - } - - return memcmp(a1, a2, header_size); -} - -static void cmp_attribute(ntfs_attr_search_ctx *ctx1, - ntfs_attr_search_ctx *ctx2) -{ - ATTR_RECORD *a1 = ctx1->attr; - ATTR_RECORD *a2 = ctx2->attr; - ntfs_attr *na1, *na2; - - if (cmp_attribute_header(a1, a2)) { - print_ctx(ctx1); - printf("header: DIFFER\n"); - } - - na1 = ntfs_attr_open(base_inode(ctx1), a1->type, GET_ATTR_NAME(a1)); - na2 = ntfs_attr_open(base_inode(ctx2), a2->type, GET_ATTR_NAME(a2)); - - if ((!na1 && na2) || (na1 && !na2)) { - print_ctx(ctx1); - printf("open: %s != %s\n", pret2str(na1), pret2str(na2)); - goto close_attribs; - } - - if (na1 == NULL) - goto close_attribs; - - if (na1->data_size != na2->data_size) { - print_na(na1); - printf("length: %lld != %lld\n", na1->data_size, na2->data_size); - goto close_attribs; - } - - if (ntfs_inode_badclus_bad(inumber(ctx1->ntfs_ino), ctx1->attr) == 1) { - /* - * If difference exists then it's already reported at the - * attribute header since the mapping pairs must differ. - */ - return; - } - - if (na1->type == AT_INDEX_ALLOCATION) - cmp_index_allocation(na1, na2); - else - cmp_attribute_data(na1, na2); - -close_attribs: - ntfs_attr_close(na1); - ntfs_attr_close(na2); -} - -static void vprint_attribute(ATTR_TYPES atype, char *name) -{ - if (!opt.verbose) - return; - - printf("0x%x", atype); - if (name) - printf(":%s", name); - printf(" "); -} - -static void print_attributes(ntfs_inode *ni, - ATTR_TYPES atype1, - ATTR_TYPES atype2, - char *name1, - char *name2) -{ - if (!opt.verbose) - return; - - printf("Walking inode %llu attributes: ", inumber(ni)); - vprint_attribute(atype1, name1); - vprint_attribute(atype2, name2); - printf("\n"); -} - -static int new_name(ntfs_attr_search_ctx *ctx, char *prev_name) -{ - int ret = 0; - char *name = get_attr_name_ctx(ctx); - - if (prev_name && name) { - if (strcmp(prev_name, name) != 0) - ret = 1; - } else if (prev_name || name) - ret = 1; - - free_name(&name); - return ret; - -} - -static int new_attribute(ntfs_attr_search_ctx *ctx, - ATTR_TYPES prev_atype, - char *prev_name) -{ - if (!prev_atype && !prev_name) - return 1; - - if (!ctx->attr->non_resident) - return 1; - - if (prev_atype != ctx->attr->type) - return 1; - - if (new_name(ctx, prev_name)) - return 1; - - if (opt.verbose) { - print_inode(base_inode(ctx)->mft_no); - print_attribute_ctx(ctx); - printf("record %llu lowest_vcn %lld: SKIPPED\n", - ctx->ntfs_ino->mft_no, ctx->attr->u.nonres.lowest_vcn); - } - - return 0; -} - -static void set_prev(char **prev_name, ATTR_TYPES *prev_atype, - char *name, ATTR_TYPES atype) -{ - free_name(prev_name); - if (name) { - *prev_name = strdup(name); - if (!*prev_name) - perr_exit("strdup error"); - } - - *prev_atype = atype; -} - -static void set_cmp_attr(ntfs_attr_search_ctx *ctx, ATTR_TYPES *atype, char **name) -{ - *atype = ctx->attr->type; - - free_name(name); - *name = get_attr_name_ctx(ctx); -} - -static int next_attr(ntfs_attr_search_ctx *ctx, ATTR_TYPES *atype, char **name, - int *err) -{ - int ret; - - ret = ntfs_attrs_walk(ctx); - *err = errno; - if (ret) { - *atype = AT_END; - free_name(name); - } else - set_cmp_attr(ctx, atype, name); - - return ret; -} - -static int cmp_attributes(ntfs_inode *ni1, ntfs_inode *ni2) -{ - int ret = -1; - int old_ret1, ret1 = 0, ret2 = 0; - int errno1 = 0, errno2 = 0; - char *prev_name = NULL, *name1 = NULL, *name2 = NULL; - ATTR_TYPES old_atype1, prev_atype = 0, atype1, atype2; - ntfs_attr_search_ctx *ctx1, *ctx2; - - if (!(ctx1 = attr_get_search_ctx(ni1))) - return -1; - if (!(ctx2 = attr_get_search_ctx(ni2))) - goto out; - - set_cmp_attr(ctx1, &atype1, &name1); - set_cmp_attr(ctx2, &atype2, &name2); - - while (1) { - - old_atype1 = atype1; - old_ret1 = ret1; - if (!ret1 && (le32_to_cpu(atype1) <= le32_to_cpu(atype2) || - ret2)) - ret1 = next_attr(ctx1, &atype1, &name1, &errno1); - if (!ret2 && (le32_to_cpu(old_atype1) >= le32_to_cpu(atype2) || - old_ret1)) - ret2 = next_attr(ctx2, &atype2, &name2, &errno2); - - print_attributes(ni1, atype1, atype2, name1, name2); - - if (ret1 && ret2) { - if (errno1 != errno2) { - print_inode_ni(ni1); - printf("attribute walk (errno): %d != %d\n", - errno1, errno2); - } - break; - } - - if (ret2 || le32_to_cpu(atype1) < le32_to_cpu(atype2)) { - if (new_attribute(ctx1, prev_atype, prev_name)) { - print_ctx(ctx1); - printf("presence: EXISTS != MISSING\n"); - set_prev(&prev_name, &prev_atype, name1, - atype1); - } - - } else if (ret1 || le32_to_cpu(atype1) > le32_to_cpu(atype2)) { - if (new_attribute(ctx2, prev_atype, prev_name)) { - print_ctx(ctx2); - printf("presence: MISSING != EXISTS \n"); - set_prev(&prev_name, &prev_atype, name2, atype2); - } - - } else /* atype1 == atype2 */ { - if (new_attribute(ctx1, prev_atype, prev_name)) { - cmp_attribute(ctx1, ctx2); - set_prev(&prev_name, &prev_atype, name1, atype1); - } - } - } - - free_name(&prev_name); - ret = 0; - ntfs_attr_put_search_ctx(ctx2); -out: - ntfs_attr_put_search_ctx(ctx1); - return ret; -} - -static int cmp_inodes(ntfs_volume *vol1, ntfs_volume *vol2) -{ - u64 inode; - int ret1, ret2; - ntfs_inode *ni1, *ni2; - struct progress_bar progress; - int pb_flags = 0; /* progress bar flags */ - u64 nr_mft_records, nr_mft_records2; - - if (opt.show_progress) - pb_flags |= NTFS_PROGBAR; - - nr_mft_records = get_nr_mft_records(vol1); - nr_mft_records2 = get_nr_mft_records(vol2); - - if (nr_mft_records != nr_mft_records2) { - - printf("Number of mft records: %lld != %lld\n", - nr_mft_records, nr_mft_records2); - - if (nr_mft_records > nr_mft_records2) - nr_mft_records = nr_mft_records2; - } - - progress_init(&progress, 0, nr_mft_records - 1, pb_flags); - progress_update(&progress, 0); - - for (inode = 0; inode < nr_mft_records; inode++) { - - ret1 = inode_open(vol1, (MFT_REF)inode, &ni1); - ret2 = inode_open(vol2, (MFT_REF)inode, &ni2); - - if (ret1 != ret2) { - print_inode(inode); - printf("open: %s != %s\n", - err2string(ret1), err2string(ret2)); - goto close_inodes; - } - - if (ret1 != NTFSCMP_OK) - goto close_inodes; - - if (cmp_attributes(ni1, ni2) != 0) { - inode_close(ni1); - inode_close(ni2); - return -1; - } -close_inodes: - if (inode_close(ni1) != 0) - return -1; - if (inode_close(ni2) != 0) - return -1; - - progress_update(&progress, inode); - } - return 0; -} - -static ntfs_volume *mount_volume(const char *volume) -{ - unsigned long mntflag; - ntfs_volume *vol = NULL; - - if (ntfs_check_if_mounted(volume, &mntflag)) { - perr_println("Failed to check '%s' mount state", volume); - printf("Probably /etc/mtab is missing. It's too risky to " - "continue. You might try\nan another Linux distro.\n"); - exit(1); - } - if (mntflag & NTFS_MF_MOUNTED) { - if (!(mntflag & NTFS_MF_READONLY)) - err_exit("Device '%s' is mounted read-write. " - "You must 'umount' it first.\n", volume); - } - - vol = ntfs_mount(volume, NTFS_MNT_RDONLY); - if (vol == NULL) { - - int err = errno; - - perr_println("Opening '%s' as NTFS failed", volume); - if (err == EINVAL) - printf(invalid_ntfs_msg, volume); - else if (err == EIO) - puts(corrupt_volume_msg); - else if (err == EPERM) - puts(hibernated_volume_msg); - exit(1); - } - - return vol; -} - -int main(int argc, char **argv) -{ - ntfs_volume *vol1; - ntfs_volume *vol2; - - printf("%s v%s (libntfs %s)\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - - parse_options(argc, argv); - - utils_set_locale(); - - vol1 = mount_volume(opt.vol1); - vol2 = mount_volume(opt.vol2); - - if (cmp_inodes(vol1, vol2) != 0) - exit(1); - - ntfs_umount(vol1, FALSE); - ntfs_umount(vol2, FALSE); - - exit(0); -} - diff --git a/usr/src/cmd/ntfsprogs/ntfscp.c b/usr/src/cmd/ntfsprogs/ntfscp.c deleted file mode 100644 index 0019667a1e..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfscp.c +++ /dev/null @@ -1,584 +0,0 @@ -/** - * ntfscp - Part of the Linux-NTFS project. - * - * Copyright (c) 2004-2007 Yura Pakhuchiy - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2006 Hil Liao - * - * This utility will copy file to an NTFS volume. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#include -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_LIBGEN_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "utils.h" -#include "volume.h" -#include "dir.h" -#include "debug.h" -#include "version.h" -#include "logging.h" - -struct options { - char *device; /* Device/File to work with */ - char *src_file; /* Source file */ - char *dest_file; /* Destination file */ - char *attr_name; /* Write to attribute with this name. */ - int force; /* Override common sense */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int noaction; /* Do not write to disk */ - ATTR_TYPES attribute; /* Write to this attribute. */ - int inode; /* Treat dest_file as inode number. */ -}; - -static const char *EXEC_NAME = "ntfscp"; -static struct options opts; -static volatile sig_atomic_t caught_terminate = 0; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s) - Copy file to an NTFS " - "volume.\n\n", EXEC_NAME, VERSION, ntfs_libntfs_version()); - ntfs_log_info("Copyright (c) 2004-2007 Yura Pakhuchiy\n"); - ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n"); - ntfs_log_info("Copyright (c) 2006 Hil Liao\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device src_file dest_file\n\n" - " -a, --attribute NUM Write to this attribute\n" - " -i, --inode Treat dest_file as inode number\n" - " -f, --force Use less caution\n" - " -h, --help Print this help\n" - " -N, --attr-name NAME Write to attribute with this name\n" - " -n, --no-action Do not write to disk\n" - " -q, --quiet Less output\n" - " -V, --version Version information\n" - " -v, --verbose More output\n\n", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char **argv) -{ - static const char *sopt = "-a:ifh?N:nqVv"; - static const struct option lopt[] = { - { "attribute", required_argument, NULL, 'a' }, - { "inode", no_argument, NULL, 'i' }, - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "attr-name", required_argument, NULL, 'N' }, - { "no-action", no_argument, NULL, 'n' }, - { "quiet", no_argument, NULL, 'q' }, - { "version", no_argument, NULL, 'V' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } - }; - - char *s; - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - s64 attr; - - opts.device = NULL; - opts.src_file = NULL; - opts.dest_file = NULL; - opts.attr_name = NULL; - opts.inode = 0; - opts.attribute = AT_DATA; - - opterr = 0; /* We'll handle the errors, thank you. */ - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opts.device) { - opts.device = argv[optind - 1]; - } else if (!opts.src_file) { - opts.src_file = argv[optind - 1]; - } else if (!opts.dest_file) { - opts.dest_file = argv[optind - 1]; - } else { - ntfs_log_error("You must specify exactly two " - "files.\n"); - err++; - } - break; - case 'a': - if (opts.attribute != AT_DATA) { - ntfs_log_error("You can specify only one " - "attribute.\n"); - err++; - break; - } - - attr = strtol(optarg, &s, 0); - if (*s) { - ntfs_log_error("Couldn't parse attribute.\n"); - err++; - } else - opts.attribute = (ATTR_TYPES)cpu_to_le32(attr); - break; - case 'i': - opts.inode++; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp(argv[optind - 1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option(argv[optind - 1])) - err++; - break; - } - help++; - break; - case 'N': - if (opts.attr_name) { - ntfs_log_error("You can specify only one " - "attribute name.\n"); - err++; - } else - opts.attr_name = argv[optind - 1]; - break; - case 'n': - opts.noaction++; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 'V': - ver++; - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - default: - ntfs_log_error("Unknown option '%s'.\n", - argv[optind - 1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (!opts.device) { - ntfs_log_error("You must specify a device.\n"); - err++; - } else if (!opts.src_file) { - ntfs_log_error("You must specify a source file.\n"); - err++; - } else if (!opts.dest_file) { - ntfs_log_error("You must specify a destination " - "file.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose " - "at the same time.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - -/** - * signal_handler - Handle SIGINT and SIGTERM: abort write, sync and exit. - */ -static void signal_handler(int arg __attribute__((unused))) -{ - caught_terminate++; -} - -/** - * Create a regular file under the given directory inode - * - * It is a wrapper function to ntfs_create(...) - * - * Return: the created file inode - */ -static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni, - const char *filename) -{ - ntfschar *ufilename; - /* inode to the file that is being created */ - ntfs_inode *ni; - int ufilename_len; - - /* ntfs_mbstoucs(...) will allocate memory for ufilename if it's NULL */ - ufilename = NULL; - ufilename_len = ntfs_mbstoucs(filename, &ufilename, 0); - if (ufilename_len == -1) { - ntfs_log_perror("ERROR: Failed to convert '%s' to unicode", - filename); - return NULL; - } - ni = ntfs_create(dir_ni, ufilename, ufilename_len, S_IFREG); - free(ufilename); - return ni; -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - FILE *in; - ntfs_volume *vol; - ntfs_inode *out; - ntfs_attr *na; - int flags = 0; - int result = 1; - s64 new_size; - u64 offset; - char *buf; - s64 br, bw; - ntfschar *attr_name; - int attr_name_len = 0; - - ntfs_log_set_handler(ntfs_log_handler_stderr); - - if (!parse_options(argc, argv)) - return 1; - - utils_set_locale(); - - /* Set SIGINT handler. */ - if (signal(SIGINT, signal_handler) == SIG_ERR) { - ntfs_log_perror("Failed to set SIGINT handler"); - return 1; - } - /* Set SIGTERM handler. */ - if (signal(SIGTERM, signal_handler) == SIG_ERR) { - ntfs_log_perror("Failed to set SIGTERM handler"); - return 1; - } - - if (opts.noaction) - flags = NTFS_MNT_RDONLY; - if (opts.force) - flags |= NTFS_MNT_FORCE; - - vol = utils_mount_volume(opts.device, flags); - if (!vol) { - ntfs_log_perror("ERROR: couldn't mount volume"); - return 1; - } - - if (NVolWasDirty(vol) && !opts.force) - goto umount; - - { - struct stat fst; - if (stat(opts.src_file, &fst) == -1) { - ntfs_log_perror("ERROR: Couldn't stat source file"); - goto umount; - } - new_size = fst.st_size; - } - ntfs_log_verbose("New file size: %lld\n", new_size); - - in = fopen(opts.src_file, "r"); - if (!in) { - ntfs_log_perror("ERROR: Couldn't open source file"); - goto umount; - } - - if (opts.inode) { - s64 inode_num; - char *s; - - inode_num = strtoll(opts.dest_file, &s, 0); - if (*s) { - ntfs_log_error("ERROR: Couldn't parse inode number.\n"); - goto close_src; - } - out = ntfs_inode_open(vol, inode_num); - } else - out = ntfs_pathname_to_inode(vol, NULL, opts.dest_file); - if (!out) { - /* Copy the file if the dest_file's parent dir can be opened. */ - char *parent_dirname; - char *filename; - ntfs_inode *dir_ni; - ntfs_inode *ni; - int dest_path_len; - char *dirname_last_whack; - - filename = basename(opts.dest_file); - dest_path_len = strlen(opts.dest_file); - parent_dirname = strdup(opts.dest_file); - if (!parent_dirname) { - ntfs_log_perror("strdup() failed"); - goto close_src; - } - dirname_last_whack = strrchr(parent_dirname, '/'); - if (dirname_last_whack) { - dirname_last_whack[1] = 0; - dir_ni = ntfs_pathname_to_inode(vol, NULL, - parent_dirname); - } else { - ntfs_log_verbose("Target path does not contain '/'. " - "Using root directory as parent.\n"); - dir_ni = ntfs_inode_open(vol, FILE_root); - } - if (dir_ni) { - if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { - /* Remove the last '/' for estetic reasons. */ - dirname_last_whack[0] = 0; - ntfs_log_error("The file '%s' already exists " - "and is not a directory. " - "Aborting.\n", parent_dirname); - free(parent_dirname); - ntfs_inode_close(dir_ni); - goto close_src; - } - ntfs_log_verbose("Creating a new file '%s' under '%s'" - "\n", filename, parent_dirname); - ni = ntfs_new_file(dir_ni, filename); - ntfs_inode_close(dir_ni); - if (!ni) { - ntfs_log_perror("Failed to create '%s' under " - "'%s'", filename, - parent_dirname); - free(parent_dirname); - goto close_src; - } - out = ni; - } else { - ntfs_log_perror("ERROR: Couldn't open '%s'", - parent_dirname); - free(parent_dirname); - goto close_src; - } - free(parent_dirname); - } - /* The destination is a directory. */ - if ((out->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !opts.inode) { - char *filename; - char *overwrite_filename; - int overwrite_filename_len; - ntfs_inode *ni; - ntfs_inode *dir_ni; - int filename_len; - int dest_dirname_len; - - filename = basename(opts.src_file); - dir_ni = out; - filename_len = strlen(filename); - dest_dirname_len = strlen(opts.dest_file); - overwrite_filename_len = filename_len+dest_dirname_len + 2; - overwrite_filename = malloc(overwrite_filename_len); - if (!overwrite_filename) { - ntfs_log_perror("ERROR: Failed to allocate %i bytes " - "memory for the overwrite filename", - overwrite_filename_len); - ntfs_inode_close(out); - goto close_src; - } - strcpy(overwrite_filename, opts.dest_file); - if (opts.dest_file[dest_dirname_len - 1] != '/') { - strcat(overwrite_filename, "/"); - } - strcat(overwrite_filename, filename); - ni = ntfs_pathname_to_inode(vol, NULL, overwrite_filename); - /* Does a file with the same name exist in the dest dir? */ - if (ni) { - ntfs_log_verbose("Destination path has a file with " - "the same name\nOverwriting the file " - "'%s'\n", overwrite_filename); - ntfs_inode_close(out); - out = ni; - } else { - ntfs_log_verbose("Creating a new file '%s' under " - "'%s'\n", filename, opts.dest_file); - ni = ntfs_new_file(dir_ni, filename); - ntfs_inode_close(dir_ni); - if (!ni) { - ntfs_log_perror("ERROR: Failed to create the " - "destination file under '%s'", - opts.dest_file); - free(overwrite_filename); - goto close_src; - } - out = ni; - } - free(overwrite_filename); - } - - attr_name = ntfs_str2ucs(opts.attr_name, &attr_name_len); - if (!attr_name) { - ntfs_log_perror("ERROR: Failed to parse attribute name '%s'", - opts.attr_name); - goto close_dst; - } - - na = ntfs_attr_open(out, opts.attribute, attr_name, attr_name_len); - if (!na) { - if (errno != ENOENT) { - ntfs_log_perror("ERROR: Couldn't open attribute"); - goto close_dst; - } - /* Requested attribute isn't present, add it. */ - if (ntfs_attr_add(out, opts.attribute, attr_name, - attr_name_len, NULL, 0)) { - ntfs_log_perror("ERROR: Couldn't add attribute"); - goto close_dst; - } - na = ntfs_attr_open(out, opts.attribute, attr_name, - attr_name_len); - if (!na) { - ntfs_log_perror("ERROR: Couldn't open just added " - "attribute"); - goto close_dst; - } - } - ntfs_ucsfree(attr_name); - - ntfs_log_verbose("Old file size: %lld\n", na->data_size); - if (na->data_size != new_size) { - if (__ntfs_attr_truncate(na, new_size, FALSE)) { - ntfs_log_perror("ERROR: Couldn't resize attribute"); - goto close_attr; - } - } - - buf = malloc(NTFS_BUF_SIZE); - if (!buf) { - ntfs_log_perror("ERROR: malloc failed"); - goto close_attr; - } - - ntfs_log_verbose("Starting write.\n"); - offset = 0; - while (!feof(in)) { - if (caught_terminate) { - ntfs_log_error("SIGTERM or SIGINT received. " - "Aborting write.\n"); - break; - } - br = fread(buf, 1, NTFS_BUF_SIZE, in); - if (!br) { - if (!feof(in)) ntfs_log_perror("ERROR: fread failed"); - break; - } - bw = ntfs_attr_pwrite(na, offset, br, buf); - if (bw != br) { - ntfs_log_perror("ERROR: ntfs_attr_pwrite failed"); - break; - } - offset += bw; - } - ntfs_log_verbose("Syncing.\n"); - result = 0; - free(buf); -close_attr: - ntfs_attr_close(na); -close_dst: - while (ntfs_inode_close(out)) { - if (errno != EBUSY) { - ntfs_log_error("Sync failed. Run chkdsk.\n"); - break; - } - ntfs_log_error("Device busy. Will retry sync in 3 seconds.\n"); - sleep(3); - } -close_src: - fclose(in); -umount: - ntfs_umount(vol, FALSE); - ntfs_log_verbose("Done.\n"); - return result; -} diff --git a/usr/src/cmd/ntfsprogs/ntfsfix.c b/usr/src/cmd/ntfsprogs/ntfsfix.c deleted file mode 100644 index dd1d1f7585..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsfix.c +++ /dev/null @@ -1,542 +0,0 @@ -/** - * ntfsfix - Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility fixes some common NTFS problems, resets the NTFS journal file - * and schedules an NTFS consistency check for the first boot into Windows. - * - * Anton Altaparmakov - * - * 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 (in the main directory of the Linux-NTFS source - * in the file COPYING); if not, write to the Free Software Foundation, - * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * WARNING: This program might not work on architectures which do not allow - * unaligned access. For those, the program would need to start using - * get/put_unaligned macros (#include ), but not doing it yet, - * since NTFS really mostly applies to ia32 only, which does allow unaligned - * accesses. We might not actually have a problem though, since the structs are - * defined as being packed so that might be enough for gcc to insert the - * correct code. - * - * If anyone using a non-little endian and/or an aligned access only CPU tries - * this program please let me know whether it works or not! - * - * Anton Altaparmakov - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "mft.h" -#include "device.h" -#include "logfile.h" -#include "utils.h" -#include "version.h" -#include "logging.h" - -#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS -# error "No default device io operations! Cannot build ntfsfix. \ -You need to run ./configure without the --disable-default-device-io-ops \ -switch if you want to be able to build the NTFS utilities." -#endif - -static const char *EXEC_NAME = "ntfsfix"; -static const char *OK = "OK\n"; -static const char *FAILED = "FAILED\n"; - -static struct { - char *volume; -} opt; - -/** - * usage - */ -__attribute__((noreturn)) -static int usage(void) -{ - ntfs_log_info("%s v%s (libntfs %s)\n" - "\n" - "Usage: %s [options] device\n" - " Attempt to fix an NTFS partition.\n" - "\n" - " -h, --help Display this help\n" - " -V, --version Display version information\n" - "\n" - "For example: %s /dev/hda6\n\n", - EXEC_NAME, VERSION, ntfs_libntfs_version(), EXEC_NAME, - EXEC_NAME); - ntfs_log_info("%s%s", ntfs_bugs, ntfs_home); - exit(1); -} - -/** - * version - */ -__attribute__((noreturn)) -static void version(void) -{ - ntfs_log_info("%s v%s\n\n" - "Attempt to fix an NTFS partition.\n\n" - "Copyright (c) 2000-2006 Anton Altaparmakov\n" - "Copyright (c) 2002-2006 Szabolcs Szakacsits\n" - "Copyright (c) 2007 Yura Pakhuchiy\n\n", - EXEC_NAME, VERSION); - ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home); - exit(1); -} - -/** - * parse_options - */ -static void parse_options(int argc, char **argv) -{ - int c; - static const char *sopt = "-hV"; - static const struct option lopt[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - memset(&opt, 0, sizeof(opt)); - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opt.volume) - opt.volume = argv[optind - 1]; - else { - ntfs_log_info("ERROR: Too many arguments.\n"); - usage(); - } - break; - case 'h': - case '?': - usage(); - case 'V': - version(); - default: - ntfs_log_info("ERROR: Unknown option '%s'.\n", argv[optind - 1]); - usage(); - } - } - - if (opt.volume == NULL) { - ntfs_log_info("ERROR: You must specify a device.\n"); - usage(); - } -} - -/** - * OLD_ntfs_volume_set_flags - */ -static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const le16 flags) -{ - MFT_RECORD *m = NULL; - ATTR_RECORD *a; - VOLUME_INFORMATION *c; - ntfs_attr_search_ctx *ctx; - int ret = -1; /* failure */ - - if (!vol) { - errno = EINVAL; - return -1; - } - if (ntfs_file_record_read(vol, FILE_Volume, &m, NULL)) { - ntfs_log_perror("Failed to read $Volume"); - return -1; - } - /* Sanity check */ - if (!(m->flags & MFT_RECORD_IN_USE)) { - ntfs_log_error("$Volume has been deleted. Cannot handle this " - "yet. Run chkdsk to fix this.\n"); - errno = EIO; - goto err_exit; - } - /* Get a pointer to the volume information attribute. */ - ctx = ntfs_attr_get_search_ctx(NULL, m); - if (!ctx) { - ntfs_log_debug("Failed to allocate attribute search " - "context.\n"); - goto err_exit; - } - if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, - 0, ctx)) { - ntfs_log_error("Attribute $VOLUME_INFORMATION was not found in " - "$Volume!\n"); - goto err_out; - } - a = ctx->attr; - /* Sanity check. */ - if (a->non_resident) { - ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident " - "(and it isn't)!\n"); - errno = EIO; - goto err_out; - } - /* Get a pointer to the value of the attribute. */ - c = (VOLUME_INFORMATION*)(le16_to_cpu(a->u.res.value_offset) + (char*)a); - /* Sanity checks. */ - if ((char*)c + le32_to_cpu(a->u.res.value_length) > - (char*)m + le32_to_cpu(m->bytes_in_use) || - le16_to_cpu(a->u.res.value_offset) + - le32_to_cpu(a->u.res.value_length) > le32_to_cpu(a->length)) { - ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is " - "corrupt!\n"); - errno = EIO; - goto err_out; - } - /* Set the volume flags. */ - vol->flags = c->flags = flags; - if (ntfs_mft_record_write(vol, FILE_Volume, m)) { - ntfs_log_perror("Error writing $Volume"); - goto err_out; - } - ret = 0; /* success */ -err_out: - ntfs_attr_put_search_ctx(ctx); -err_exit: - free(m); - return ret; -} - -/** - * set_dirty_flag - */ -static int set_dirty_flag(ntfs_volume *vol) -{ - le16 flags; - - if (NVolWasDirty(vol)) - return 0; - ntfs_log_info("Setting required flags on partition... "); - /* - * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run - * and fix it for us. - */ - flags = vol->flags | VOLUME_IS_DIRTY; - if (OLD_ntfs_volume_set_flags(vol, flags)) { - ntfs_log_info(FAILED); - ntfs_log_error("Error setting volume flags.\n"); - return -1; - } - vol->flags = flags; - NVolSetWasDirty(vol); - ntfs_log_info(OK); - return 0; -} - -/** - * empty_journal - */ -static int empty_journal(ntfs_volume *vol) -{ - if (NVolLogFileEmpty(vol)) - return 0; - ntfs_log_info("Going to empty the journal ($LogFile)... "); - if (ntfs_logfile_reset(vol)) { - ntfs_log_info(FAILED); - ntfs_log_perror("Failed to reset $LogFile"); - return -1; - } - ntfs_log_info(OK); - return 0; -} - -/** - * fix_mftmirr - */ -static int fix_mftmirr(ntfs_volume *vol) -{ - s64 l, br; - unsigned char *m, *m2; - int i, ret = -1; /* failure */ - BOOL done; - - ntfs_log_info("\nProcessing $MFT and $MFTMirr...\n"); - - /* Load data from $MFT and $MFTMirr and compare the contents. */ - m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits); - if (!m) { - ntfs_log_perror("Failed to allocate memory"); - return -1; - } - m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits); - if (!m2) { - ntfs_log_perror("Failed to allocate memory"); - free(m); - return -1; - } - - ntfs_log_info("Reading $MFT... "); - l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size, - vol->mft_record_size, m); - if (l != vol->mftmirr_size) { - ntfs_log_info(FAILED); - if (l != -1) - errno = EIO; - ntfs_log_perror("Failed to read $MFT"); - goto error_exit; - } - ntfs_log_info(OK); - - ntfs_log_info("Reading $MFTMirr... "); - l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size, - vol->mft_record_size, m2); - if (l != vol->mftmirr_size) { - ntfs_log_info(FAILED); - if (l != -1) - errno = EIO; - ntfs_log_perror("Failed to read $MFTMirr"); - goto error_exit; - } - ntfs_log_info(OK); - - /* - * FIXME: Need to actually check the $MFTMirr for being real. Otherwise - * we might corrupt the partition if someone is experimenting with - * software RAID and the $MFTMirr is not actually in the position we - * expect it to be... )-: - * FIXME: We should emit a warning it $MFTMirr is damaged and ask - * user whether to recreate it from $MFT or whether to abort. - The - * warning needs to include the danger of software RAID arrays. - * Maybe we should go as far as to detect whether we are running on a - * MD disk and if yes then bomb out right at the start of the program? - */ - - ntfs_log_info("Comparing $MFTMirr to $MFT... "); - done = FALSE; - for (i = 0; i < vol->mftmirr_size; ++i) { - MFT_RECORD *mrec, *mrec2; - const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", - "$Volume", "$AttrDef", "root directory", "$Bitmap", - "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" }; - const char *s; - BOOL use_mirr; - - if (i < 12) - s = ESTR[i]; - else if (i < 16) - s = "system file"; - else - s = "mft record"; - - use_mirr = FALSE; - mrec = (MFT_RECORD*)(m + i * vol->mft_record_size); - if (mrec->flags & MFT_RECORD_IN_USE) { - if (ntfs_is_baad_record(mrec->magic)) { - ntfs_log_info(FAILED); - ntfs_log_error("$MFT error: Incomplete multi " - "sector transfer detected in " - "%s.\nCannot handle this yet. " - ")-:\n", s); - goto error_exit; - } - if (!ntfs_is_mft_record(mrec->magic)) { - ntfs_log_info(FAILED); - ntfs_log_error("$MFT error: Invalid mft " - "record for %s.\nCannot " - "handle this yet. )-:\n", s); - goto error_exit; - } - } - mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size); - if (mrec2->flags & MFT_RECORD_IN_USE) { - if (ntfs_is_baad_record(mrec2->magic)) { - ntfs_log_info(FAILED); - ntfs_log_error("$MFTMirr error: Incomplete " - "multi sector transfer " - "detected in %s.\n", s); - goto error_exit; - } - if (!ntfs_is_mft_record(mrec2->magic)) { - ntfs_log_info(FAILED); - ntfs_log_error("$MFTMirr error: Invalid mft " - "record for %s.\n", s); - goto error_exit; - } - /* $MFT is corrupt but $MFTMirr is ok, use $MFTMirr. */ - if (!(mrec->flags & MFT_RECORD_IN_USE) && - !ntfs_is_mft_record(mrec->magic)) - use_mirr = TRUE; - } - if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) { - if (!done) { - done = TRUE; - ntfs_log_info(FAILED); - } - ntfs_log_info("Correcting differences in $MFT%s " - "record %d...", use_mirr ? "" : "Mirr", - i); - br = ntfs_mft_record_write(vol, i, - use_mirr ? mrec2 : mrec); - if (br) { - ntfs_log_info(FAILED); - ntfs_log_perror("Error correcting $MFT%s", - use_mirr ? "" : "Mirr"); - goto error_exit; - } - ntfs_log_info(OK); - } - } - if (!done) - ntfs_log_info(OK); - ntfs_log_info("Processing of $MFT and $MFTMirr completed " - "successfully.\n"); - ret = 0; -error_exit: - free(m); - free(m2); - return ret; -} - -/** - * fix_mount - */ -static int fix_mount(void) -{ - int ret = -1; /* failure */ - ntfs_volume *vol; - struct ntfs_device *dev; - - ntfs_log_info("Attempting to correct errors... "); - - dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops, - NULL); - if (!dev) { - ntfs_log_info(FAILED); - ntfs_log_perror("Failed to allocate device"); - return -1; - } - vol = ntfs_volume_startup(dev, 0); - if (!vol) { - ntfs_log_info(FAILED); - ntfs_log_perror("Failed to startup volume"); - ntfs_log_error("Volume is corrupt. You should run chkdsk.\n"); - ntfs_device_free(dev); - return -1; - } - if (fix_mftmirr(vol) < 0) - goto error_exit; - if (set_dirty_flag(vol) < 0) - goto error_exit; - if (empty_journal(vol) < 0) - goto error_exit; - ret = 0; -error_exit: - /* ntfs_umount() will invoke ntfs_device_free() for us. */ - if (ntfs_umount(vol, 0)) - ntfs_umount(vol, 1); - return ret; -} - -/** - * main - */ -int main(int argc, char **argv) -{ - ntfs_volume *vol; - unsigned long mnt_flags; - int ret = 1; /* failure */ - BOOL force = FALSE; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - parse_options(argc, argv); - - if (!ntfs_check_if_mounted(opt.volume, &mnt_flags)) { - if ((mnt_flags & NTFS_MF_MOUNTED) && - !(mnt_flags & NTFS_MF_READONLY) && !force) { - ntfs_log_error("Refusing to operate on read-write " - "mounted device %s.\n", opt.volume); - exit(1); - } - } else - ntfs_log_perror("Failed to determine whether %s is mounted", - opt.volume); - /* Attempt a full mount first. */ - ntfs_log_info("Mounting volume... "); - vol = ntfs_mount(opt.volume, 0); - if (vol) { - ntfs_log_info(OK); - ntfs_log_info("Processing of $MFT and $MFTMirr completed " - "successfully.\n"); - } else { - ntfs_log_info(FAILED); - exit(1); /* XXX remove before use */ - if (fix_mount() < 0) - exit(1); - vol = ntfs_mount(opt.volume, 0); - if (!vol) { - ntfs_log_perror("Remount failed"); - exit(1); - } - } - /* So the unmount does not clear it again. */ - NVolSetWasDirty(vol); - /* Check NTFS version is ok for us (in $Volume) */ - ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver, - vol->minor_ver); - if (ntfs_version_is_supported(vol)) { - ntfs_log_error("Error: Unknown NTFS version.\n"); - goto error_exit; - } - if (vol->major_ver >= 3) { - /* - * FIXME: If on NTFS 3.0+, check for presence of the usn - * journal and stamp it if present. - */ - } - /* FIXME: We should be marking the quota out of date, too. */ - /* That's all for now! */ - ntfs_log_info("NTFS partition %s was processed successfully.\n", - vol->u.dev->d_name); - /* Set return code to 0. */ - ret = 0; -error_exit: - if (ntfs_umount(vol, 0)) - ntfs_umount(vol, 1); - return ret; -} - diff --git a/usr/src/cmd/ntfsprogs/ntfsinfo.c b/usr/src/cmd/ntfsprogs/ntfsinfo.c deleted file mode 100644 index 8791d57351..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsinfo.c +++ /dev/null @@ -1,2305 +0,0 @@ -/** - * ntfsinfo - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2004 Matthew J. Fanto - * Copyright (c) 2002-2006 Anton Altaparmakov - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2003-2006 Szabolcs Szakacsits - * Copyright (c) 2004-2005 Yuval Fledel - * Copyright (c) 2004-2007 Yura Pakhuchiy - * Copyright (c) 2005 Cristian Klein - * - * This utility will dump a file's attributes. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * TODO LIST: - * - Better error checking. (focus on ntfs_dump_volume) - * - Comment things better. - * - More things at verbose mode. - * - Dump ACLs when security_id exists (NTFS 3+ only). - * - Clean ups. - * - Internationalization. - * - Add more Indexed Attr Types. - * - Make formatting look more like www.flatcap.org/ntfs/info - * - * Still not dumping certain attributes. Need to find the best - * way to output some of these attributes. - * - * Still need to do: - * $REPARSE_POINT/$SYMBOLIC_LINK - * $LOGGED_UTILITY_STREAM - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "mft.h" -#include "attrib.h" -#include "layout.h" -#include "inode.h" -#include "index.h" -#include "utils.h" -#include "security.h" -#include "mst.h" -#include "dir.h" -#include "ntfstime.h" -#include "version.h" -#include "support.h" - -static const char *EXEC_NAME = "ntfsinfo"; - -static struct options { - const char *device; /* Device/File to work with */ - const char *filename; /* Resolve this filename to mft number */ - s64 inode; /* Info for this inode */ - int debug; /* Debug output */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int force; /* Override common sense */ - int notime; /* Don't report timestamps at all */ - int mft; /* Dump information about the volume as well */ -} opts; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - printf("\n%s v%s (libntfs %s) - Display information about an NTFS " - "Volume.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - printf("Copyright (c)\n"); - printf(" 2002-2004 Matthew J. Fanto\n"); - printf(" 2002-2006 Anton Altaparmakov\n"); - printf(" 2002-2005 Richard Russon\n"); - printf(" 2003-2006 Szabolcs Szakacsits\n"); - printf(" 2003 Leonard Norrgård\n"); - printf(" 2004-2005 Yuval Fledel\n"); - printf(" 2004-2007 Yura Pakhuchiy\n"); - printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - printf("\nUsage: %s [options] device\n" - " -i, --inode NUM Display information about this inode\n" - " -F, --file FILE Display information about this file (absolute path)\n" - " -m, --mft Dump information about the volume\n" - " -t, --notime Don't report timestamps\n" - "\n" - " -f, --force Use less caution\n" - " -q, --quiet Less output\n" - " -v, --verbose More output\n" - " -V, --version Display version information\n" - " -h, --help Display this help\n" -#ifdef DEBUG - " -d, --debug Show debug information\n" -#endif - "\n", - EXEC_NAME); - printf("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char *argv[]) -{ - static const char *sopt = "-:dfhi:F:mqtTvV"; - static const struct option lopt[] = { -#ifdef DEBUG - { "debug", no_argument, NULL, 'd' }, -#endif - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "inode", required_argument, NULL, 'i' }, - { "file", required_argument, NULL, 'F' }, - { "quiet", no_argument, NULL, 'q' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { "notime", no_argument, NULL, 'T' }, - { "mft", no_argument, NULL, 'm' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - - opterr = 0; /* We'll handle the errors, thank you. */ - - opts.inode = -1; - opts.filename = NULL; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: - if (!opts.device) - opts.device = optarg; - else - err++; - break; - case 'd': - opts.debug++; - break; - case 'i': - if ((opts.inode != -1) || - (!utils_parse_size(optarg, &opts.inode, FALSE))) { - err++; - } - break; - case 'F': - if (opts.filename == NULL) { - /* The inode can not be resolved here, - store the filename */ - opts.filename = argv[optind-1]; - } else { - /* "-F" can't appear more than once */ - err++; - } - break; - case 'f': - opts.force++; - break; - case 'h': - help++; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 't': - opts.notime++; - break; - case 'T': - /* 'T' is deprecated, notify */ - ntfs_log_error("Option 'T' is deprecated, it was " - "replaced by 't'.\n"); - err++; - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - case 'm': - opts.mft++; - break; - case '?': - if (optopt=='?') { - help++; - continue; - } - if (ntfs_log_parse_option(argv[optind-1])) - continue; - ntfs_log_error("Unknown option '%s'.\n", - argv[optind-1]); - err++; - break; - case ':': - ntfs_log_error("Option '%s' requires an " - "argument.\n", argv[optind-1]); - err++; - break; - default: - ntfs_log_error("Unhandled option case: %d.\n", c); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (opts.device == NULL) { - if (argc > 1) - ntfs_log_error("You must specify exactly one " - "device.\n"); - err++; - } - - if ((opts.inode == -1) && (opts.filename == NULL) && !opts.mft) { - if (argc > 1) - ntfs_log_error("You must specify an inode to " - "learn about.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose " - "at the same time.\n"); - err++; - } - - if ((opts.inode != -1) && (opts.filename != NULL)) { - if (argc > 1) - ntfs_log_error("You may not specify --inode " - "and --file together.\n"); - err++; - } - - } - -#ifdef DEBUG - if (!opts.debug) - if (!freopen("/dev/null", "w", stderr)) { - ntfs_log_perror("Failed to freopen stderr to /dev/null"); - exit(1); - } -#endif - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - - -/* *************** utility functions ******************** */ -/** - * ntfsinfo_time_to_str() - - * @sle_ntfs_clock: on disk time format in 100ns units since 1st jan 1601 - * in little-endian format - * - * Return char* in a format 'Thu Jan 1 00:00:00 1970'. - * No need to free the returned memory. - * - * Example of usage: - * char *time_str = ntfsinfo_time_to_str( - * sle64_to_cpu(standard_attr->creation_time)); - * printf("\tFile Creation Time:\t %s", time_str); - */ -static char *ntfsinfo_time_to_str(const sle64 sle_ntfs_clock) -{ - time_t unix_clock = ntfs2utc(sle_ntfs_clock); - return ctime(&unix_clock); -} - -/** - * ntfs_attr_get_name() - * @attr: a valid attribute record - * - * return multi-byte string containing the attribute name if exist. the user - * is then responsible of freeing that memory. - * null if no name exists (attr->name_length==0). no memory allocated. - * null if cannot convert to multi-byte string. errno would contain the - * error id. no memory allocated in that case - */ -static char *ntfs_attr_get_name_mbs(ATTR_RECORD *attr) -{ - ntfschar *ucs_attr_name; - char *mbs_attr_name = NULL; - int mbs_attr_name_size; - - /* Get name in unicode. */ - ucs_attr_name = ntfs_attr_get_name(attr); - /* Convert unicode to printable format. */ - mbs_attr_name_size = ntfs_ucstombs(ucs_attr_name, attr->name_length, - &mbs_attr_name, 0); - if (mbs_attr_name_size > 0) - return mbs_attr_name; - else - return NULL; -} - - -/* *************** functions for dumping global info ******************** */ -/** - * ntfs_dump_volume - dump information about the volume - */ -static void ntfs_dump_volume(ntfs_volume *vol) -{ - printf("Volume Information \n"); - printf("\tName of device: %s\n", vol->u.dev->d_name); - printf("\tDevice state: %lu\n", vol->u.dev->d_state); - printf("\tVolume Name: %s\n", vol->vol_name); - printf("\tVolume State: %lu\n", vol->state); - printf("\tVolume Version: %u.%u\n", vol->major_ver, vol->minor_ver); - printf("\tSector Size: %hu\n", vol->sector_size); - printf("\tCluster Size: %u\n", (unsigned int)vol->cluster_size); - printf("\tVolume Size in Clusters: %lld\n", - (long long)vol->nr_clusters); - - printf("MFT Information \n"); - printf("\tMFT Record Size: %u\n", (unsigned int)vol->mft_record_size); - printf("\tMFT Zone Multiplier: %u\n", vol->mft_zone_multiplier); - printf("\tMFT Data Position: %lld\n", (long long)vol->mft_data_pos); - printf("\tMFT Zone Start: %lld\n", (long long)vol->mft_zone_start); - printf("\tMFT Zone End: %lld\n", (long long)vol->mft_zone_end); - printf("\tMFT Zone Position: %lld\n", (long long)vol->mft_zone_pos); - printf("\tCurrent Position in First Data Zone: %lld\n", - (long long)vol->data1_zone_pos); - printf("\tCurrent Position in Second Data Zone: %lld\n", - (long long)vol->data2_zone_pos); - printf("\tLCN of Data Attribute for FILE_MFT: %lld\n", - (long long)vol->mft_lcn); - printf("\tFILE_MFTMirr Size: %d\n", vol->mftmirr_size); - printf("\tLCN of Data Attribute for File_MFTMirr: %lld\n", - (long long)vol->mftmirr_lcn); - printf("\tSize of Attribute Definition Table: %d\n", - (int)vol->attrdef_len); - - printf("FILE_Bitmap Information \n"); - printf("\tFILE_Bitmap MFT Record Number: %llu\n", - (unsigned long long)vol->lcnbmp_ni->mft_no); - printf("\tState of FILE_Bitmap Inode: %lu\n", vol->lcnbmp_ni->state); - printf("\tLength of Attribute List: %u\n", - (unsigned int)vol->lcnbmp_ni->attr_list_size); - printf("\tAttribute List: %s\n", vol->lcnbmp_ni->attr_list); - printf("\tNumber of Attached Extent Inodes: %d\n", - (int)vol->lcnbmp_ni->nr_extents); - /* FIXME: need to add code for the union if nr_extens != 0, but - i dont know if it will ever != 0 with FILE_Bitmap */ - - printf("FILE_Bitmap Data Attribute Information\n"); - printf("\tDecompressed Runlist: not done yet\n"); - printf("\tBase Inode: %llu\n", - (unsigned long long)vol->lcnbmp_na->ni->mft_no); - printf("\tAttribute Types: not done yet\n"); - //printf("\tAttribute Name: %s\n", vol->lcnbmp_na->name); - printf("\tAttribute Name Length: %u\n", - (unsigned int)vol->lcnbmp_na->name_len); - printf("\tAttribute State: %lu\n", vol->lcnbmp_na->state); - printf("\tAttribute Allocated Size: %lld\n", - (long long)vol->lcnbmp_na->allocated_size); - printf("\tAttribute Data Size: %lld\n", - (long long)vol->lcnbmp_na->data_size); - printf("\tAttribute Initialized Size: %lld\n", - (long long)vol->lcnbmp_na->initialized_size); - printf("\tAttribute Compressed Size: %lld\n", - (long long)vol->lcnbmp_na->compressed_size); - printf("\tCompression Block Size: %u\n", - (unsigned int)vol->lcnbmp_na->compression_block_size); - printf("\tCompression Block Size Bits: %u\n", - vol->lcnbmp_na->compression_block_size_bits); - printf("\tCompression Block Clusters: %u\n", - vol->lcnbmp_na->compression_block_clusters); - - //TODO: Still need to add a few more attributes -} - -/** - * ntfs_dump_flags - Dump flags for STANDARD_INFORMATION and FILE_NAME. - * @type: dump flags for this attribute type - * @flags: flags for dumping - */ -static void ntfs_dump_flags(const char *indent, ATTR_TYPES type, le32 flags) -{ - printf("%sFile attributes:\t", indent); - if (flags & FILE_ATTR_READONLY) { - printf(" READONLY"); - flags &= ~FILE_ATTR_READONLY; - } - if (flags & FILE_ATTR_HIDDEN) { - printf(" HIDDEN"); - flags &= ~FILE_ATTR_HIDDEN; - } - if (flags & FILE_ATTR_SYSTEM) { - printf(" SYSTEM"); - flags &= ~FILE_ATTR_SYSTEM; - } - if (flags & FILE_ATTR_DIRECTORY) { - printf(" DIRECTORY"); - flags &= ~FILE_ATTR_DIRECTORY; - } - if (flags & FILE_ATTR_ARCHIVE) { - printf(" ARCHIVE"); - flags &= ~FILE_ATTR_ARCHIVE; - } - if (flags & FILE_ATTR_DEVICE) { - printf(" DEVICE"); - flags &= ~FILE_ATTR_DEVICE; - } - if (flags & FILE_ATTR_NORMAL) { - printf(" NORMAL"); - flags &= ~FILE_ATTR_NORMAL; - } - if (flags & FILE_ATTR_TEMPORARY) { - printf(" TEMPORARY"); - flags &= ~FILE_ATTR_TEMPORARY; - } - if (flags & FILE_ATTR_SPARSE_FILE) { - printf(" SPARSE_FILE"); - flags &= ~FILE_ATTR_SPARSE_FILE; - } - if (flags & FILE_ATTR_REPARSE_POINT) { - printf(" REPARSE_POINT"); - flags &= ~FILE_ATTR_REPARSE_POINT; - } - if (flags & FILE_ATTR_COMPRESSED) { - printf(" COMPRESSED"); - flags &= ~FILE_ATTR_COMPRESSED; - } - if (flags & FILE_ATTR_OFFLINE) { - printf(" OFFLINE"); - flags &= ~FILE_ATTR_OFFLINE; - } - if (flags & FILE_ATTR_NOT_CONTENT_INDEXED) { - printf(" NOT_CONTENT_INDEXED"); - flags &= ~FILE_ATTR_NOT_CONTENT_INDEXED; - } - if (flags & FILE_ATTR_ENCRYPTED) { - printf(" ENCRYPTED"); - flags &= ~FILE_ATTR_ENCRYPTED; - } - /* We know that FILE_ATTR_I30_INDEX_PRESENT only exists on $FILE_NAME, - and in case we are wrong, let it appear as UNKNOWN */ - if (type == AT_FILE_NAME) { - if (flags & FILE_ATTR_I30_INDEX_PRESENT) { - printf(" I30_INDEX"); - flags &= ~FILE_ATTR_I30_INDEX_PRESENT; - } - } - if (flags & FILE_ATTR_VIEW_INDEX_PRESENT) { - printf(" VIEW_INDEX"); - flags &= ~FILE_ATTR_VIEW_INDEX_PRESENT; - } - if (flags) - printf(" UNKNOWN: 0x%08x", (unsigned int)le32_to_cpu(flags)); - /* Print all the flags in hex. */ - printf(" (0x%08x)\n", (unsigned)le32_to_cpu(flags)); -} - -/** - * ntfs_dump_namespace - */ -static void ntfs_dump_namespace(const char *indent, u8 file_name_type) -{ - const char *mbs_file_type; - - /* name space */ - switch (file_name_type) { - case FILE_NAME_POSIX: - mbs_file_type = "POSIX"; - break; - case FILE_NAME_WIN32: - mbs_file_type = "Win32"; - break; - case FILE_NAME_DOS: - mbs_file_type = "DOS"; - break; - case FILE_NAME_WIN32_AND_DOS: - mbs_file_type = "Win32 & DOS"; - break; - default: - mbs_file_type = "(unknown)"; - } - printf("%sNamespace:\t\t %s\n", indent, mbs_file_type); -} - -/* *************** functions for dumping attributes ******************** */ -/** - * ntfs_dump_standard_information - */ -static void ntfs_dump_attr_standard_information(ATTR_RECORD *attr) -{ - STANDARD_INFORMATION *standard_attr = NULL; - u32 value_length; - - standard_attr = (STANDARD_INFORMATION*)((char *)attr + - le16_to_cpu(attr->u.res.value_offset)); - - /* time conversion stuff */ - if (!opts.notime) { - char *ntfs_time_str = NULL; - - ntfs_time_str = ntfsinfo_time_to_str(standard_attr->creation_time); - printf("\tFile Creation Time:\t %s",ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str( - standard_attr->last_data_change_time); - printf("\tFile Altered Time:\t %s",ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str( - standard_attr->last_mft_change_time); - printf("\tMFT Changed Time:\t %s",ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str(standard_attr->last_access_time); - printf("\tLast Accessed Time:\t %s",ntfs_time_str); - } - ntfs_dump_flags("\t", attr->type, standard_attr->file_attributes); - - value_length = le32_to_cpu(attr->u.res.value_length); - if (value_length == 48) { - /* Only 12 reserved bytes here */ - } else if (value_length == 72) { - printf("\tMaximum versions:\t %u \n", (unsigned int) - le32_to_cpu(standard_attr->u.v30.maximum_versions)); - printf("\tVersion number:\t\t %u \n", (unsigned int) - le32_to_cpu(standard_attr->u.v30.version_number)); - printf("\tClass ID:\t\t %u \n", - (unsigned int)le32_to_cpu(standard_attr->u.v30.class_id)); - printf("\tUser ID:\t\t %u (0x%x)\n", - (unsigned int)le32_to_cpu(standard_attr->u.v30.owner_id), - (unsigned int)le32_to_cpu(standard_attr->u.v30.owner_id)); - printf("\tSecurity ID:\t\t %u (0x%x)\n", - (unsigned int)le32_to_cpu(standard_attr->u.v30.security_id), - (unsigned int)le32_to_cpu(standard_attr->u.v30.security_id)); - printf("\tQuota charged:\t\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(standard_attr->u.v30.quota_charged), - (unsigned long long) - le64_to_cpu(standard_attr->u.v30.quota_charged)); - printf("\tUpdate Sequence Number:\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(standard_attr->u.v30.usn), - (unsigned long long) - le64_to_cpu(standard_attr->u.v30.usn)); - } else { - printf("\tSize of STANDARD_INFORMATION is %u (0x%x). It " - "should be either 72 or 48, something is " - "wrong...\n", (unsigned int)value_length, - (unsigned)value_length); - } -} - -static void ntfs_dump_bytes(u8 *buf, int start, int stop) -{ - int i; - - for (i = start; i < stop; i++) { - printf("%02x ", buf[i]); - } -} - -/** - * ntfs_dump_attr_list() - */ -static void ntfs_dump_attr_list(ATTR_RECORD *attr, ntfs_volume *vol) -{ - ATTR_LIST_ENTRY *entry; - u8 *value; - s64 l; - - if (!opts.verbose) - return; - - l = ntfs_get_attribute_value_length(attr); - if (!l) { - ntfs_log_perror("ntfs_get_attribute_value_length failed"); - return; - } - value = ntfs_malloc(l); - if (!value) - return; - - l = ntfs_get_attribute_value(vol, attr, value); - if (!l) { - ntfs_log_perror("ntfs_get_attribute_value failed"); - free(value); - return; - } - printf("\tDumping attribute list:"); - entry = (ATTR_LIST_ENTRY *) value; - for (;(u8 *)entry < (u8 *) value + l; entry = (ATTR_LIST_ENTRY *) - ((u8 *) entry + le16_to_cpu(entry->length))) { - printf("\n"); - printf("\t\tAttribute type:\t0x%x\n", - (unsigned int)le32_to_cpu(entry->type)); - printf("\t\tRecord length:\t%u (0x%x)\n", - (unsigned)le16_to_cpu(entry->length), - (unsigned)le16_to_cpu(entry->length)); - printf("\t\tName length:\t%u (0x%x)\n", - (unsigned)entry->name_length, - (unsigned)entry->name_length); - printf("\t\tName offset:\t%u (0x%x)\n", - (unsigned)entry->name_offset, - (unsigned)entry->name_offset); - printf("\t\tStarting VCN:\t%lld (0x%llx)\n", - (long long)sle64_to_cpu(entry->lowest_vcn), - (unsigned long long) - sle64_to_cpu(entry->lowest_vcn)); - printf("\t\tMFT reference:\t%lld (0x%llx)\n", - (unsigned long long) - MREF_LE(entry->mft_reference), - (unsigned long long) - MREF_LE(entry->mft_reference)); - printf("\t\tInstance:\t%u (0x%x)\n", - (unsigned)le16_to_cpu(entry->instance), - (unsigned)le16_to_cpu(entry->instance)); - printf("\t\tName:\t\t"); - if (entry->name_length) { - char *name = NULL; - int name_size; - - name_size = ntfs_ucstombs(entry->name, - entry->name_length, &name, 0); - - if (name_size > 0) { - printf("%s\n", name); - free(name); - } else - ntfs_log_perror("ntfs_ucstombs failed"); - } else - printf("unnamed\n"); - printf("\t\tPadding:\t"); - ntfs_dump_bytes((u8 *)entry, entry->name_offset + - sizeof(ntfschar) * entry->name_length, - le16_to_cpu(entry->length)); - printf("\n"); - } - free(value); - printf("\tEnd of attribute list reached.\n"); -} - -/** - * ntfs_dump_filename() - */ -static void ntfs_dump_filename(const char *indent, - FILE_NAME_ATTR *file_name_attr) -{ - printf("%sParent directory:\t %lld (0x%llx)\n", indent, - (long long)MREF_LE(file_name_attr->parent_directory), - (long long)MREF_LE(file_name_attr->parent_directory)); - /* time stuff */ - if (!opts.notime) { - char *ntfs_time_str; - - ntfs_time_str = ntfsinfo_time_to_str( - file_name_attr->creation_time); - printf("%sFile Creation Time:\t %s", indent, ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str( - file_name_attr->last_data_change_time); - printf("%sFile Altered Time:\t %s", indent, ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str( - file_name_attr->last_mft_change_time); - printf("%sMFT Changed Time:\t %s", indent, ntfs_time_str); - - ntfs_time_str = ntfsinfo_time_to_str( - file_name_attr->last_access_time); - printf("%sLast Accessed Time:\t %s", indent, ntfs_time_str); - } - /* other basic stuff about the file */ - printf("%sAllocated Size:\t\t %lld (0x%llx)\n", indent, (long long) - sle64_to_cpu(file_name_attr->allocated_size), - (unsigned long long) - sle64_to_cpu(file_name_attr->allocated_size)); - printf("%sData Size:\t\t %lld (0x%llx)\n", indent, - (long long)sle64_to_cpu(file_name_attr->data_size), - (unsigned long long) - sle64_to_cpu(file_name_attr->data_size)); - printf("%sFilename Length:\t %d (0x%x)\n", indent, - (unsigned)file_name_attr->file_name_length, - (unsigned)file_name_attr->file_name_length); - ntfs_dump_flags(indent, AT_FILE_NAME, file_name_attr->file_attributes); - if (file_name_attr->file_attributes & FILE_ATTR_REPARSE_POINT && - file_name_attr->u.reparse_point_tag) - printf("%sReparse point tag:\t 0x%x\n", indent, (unsigned) - le32_to_cpu(file_name_attr->u.reparse_point_tag)); - else if (file_name_attr->u.reparse_point_tag) { - printf("%sEA Length:\t\t %d (0x%x)\n", indent, (unsigned) - le16_to_cpu(file_name_attr->u.s.packed_ea_size), - (unsigned) - le16_to_cpu(file_name_attr->u.s.packed_ea_size)); - if (file_name_attr->u.s.reserved) - printf("%sReserved:\t\t %d (0x%x)\n", indent, - (unsigned) - le16_to_cpu(file_name_attr->u.s.reserved), - (unsigned) - le16_to_cpu(file_name_attr->u.s.reserved)); - } - /* The filename. */ - ntfs_dump_namespace(indent, file_name_attr->file_name_type); - if (file_name_attr->file_name_length > 0) { - /* but first we need to convert the little endian unicode string - into a printable format */ - char *mbs_file_name = NULL; - int mbs_file_name_size; - - mbs_file_name_size = ntfs_ucstombs(file_name_attr->file_name, - file_name_attr->file_name_length,&mbs_file_name,0); - - if (mbs_file_name_size>0) { - printf("%sFilename:\t\t '%s'\n", indent, mbs_file_name); - free(mbs_file_name); - } else { - /* an error occurred, errno holds the reason - notify the user */ - ntfs_log_perror("ntfsinfo error: could not parse file name"); - } - } else { - printf("%sFile Name:\t\t unnamed?!?\n", indent); - } -} - -/** - * ntfs_dump_attr_file_name() - */ -static void ntfs_dump_attr_file_name(ATTR_RECORD *attr) -{ - ntfs_dump_filename("\t", (FILE_NAME_ATTR*)((u8*)attr + - le16_to_cpu(attr->u.res.value_offset))); -} - -/** - * ntfs_dump_object_id - * - * dump the $OBJECT_ID attribute - not present on all systems - */ -static void ntfs_dump_attr_object_id(ATTR_RECORD *attr,ntfs_volume *vol) -{ - OBJECT_ID_ATTR *obj_id_attr = NULL; - - obj_id_attr = (OBJECT_ID_ATTR *)((u8*)attr + - le16_to_cpu(attr->u.res.value_offset)); - - if (vol->major_ver >= 3.0) { - u32 value_length; - char printable_GUID[37]; - - value_length = le32_to_cpu(attr->u.res.value_length); - - /* Object ID is mandatory. */ - ntfs_guid_to_mbs(&obj_id_attr->object_id, printable_GUID); - printf("\tObject ID:\t\t %s\n", printable_GUID); - - /* Dump Birth Volume ID. */ - if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero( - &obj_id_attr->u.s.birth_volume_id)) { - ntfs_guid_to_mbs(&obj_id_attr->u.s.birth_volume_id, - printable_GUID); - printf("\tBirth Volume ID:\t\t %s\n", printable_GUID); - } else - printf("\tBirth Volume ID:\t missing\n"); - - /* Dumping Birth Object ID */ - if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero( - &obj_id_attr->u.s.birth_object_id)) { - ntfs_guid_to_mbs(&obj_id_attr->u.s.birth_object_id, - printable_GUID); - printf("\tBirth Object ID:\t\t %s\n", printable_GUID); - } else - printf("\tBirth Object ID:\t missing\n"); - - /* Dumping Domain_id - reserved for now */ - if ((value_length > sizeof(GUID)) && !ntfs_guid_is_zero( - &obj_id_attr->u.s.domain_id)) { - ntfs_guid_to_mbs(&obj_id_attr->u.s.domain_id, - printable_GUID); - printf("\tDomain ID:\t\t\t %s\n", printable_GUID); - } else - printf("\tDomain ID:\t\t missing\n"); - } else - printf("\t$OBJECT_ID not present. Only NTFS versions > 3.0\n" - "\thave $OBJECT_ID. Your version of NTFS is %d.\n", - vol->major_ver); -} - -/** - * ntfs_dump_acl - * - * given an acl, print it in a beautiful & lovely way. - */ -static void ntfs_dump_acl(const char *prefix, ACL *acl) -{ - unsigned int i; - u16 ace_count; - ACCESS_ALLOWED_ACE *ace; - - printf("%sRevision\t %u\n", prefix, acl->revision); - - /* - * Do not recalculate le16_to_cpu every iteration (minor speedup on - * big-endian machines. - */ - ace_count = le16_to_cpu(acl->ace_count); - - /* initialize 'ace' to the first ace (if any) */ - ace = (ACCESS_ALLOWED_ACE *)((char *)acl + 8); - - /* iterate through ACE's */ - for (i = 1; i <= ace_count; i++) { - const char *ace_type; - char *sid; - - /* set ace_type. */ - switch (ace->type) { - case ACCESS_ALLOWED_ACE_TYPE: - ace_type = "allow"; - break; - case ACCESS_DENIED_ACE_TYPE: - ace_type = "deny"; - break; - case SYSTEM_AUDIT_ACE_TYPE: - ace_type = "audit"; - break; - default: - ace_type = "unknown"; - break; - } - - printf("%sACE:\t\t type:%s flags:0x%x access:0x%x\n", prefix, - ace_type, (unsigned int)ace->flags, - (unsigned int)le32_to_cpu(ace->mask)); - /* get a SID string */ - sid = ntfs_sid_to_mbs(&ace->sid, NULL, 0); - printf("%s\t\t SID: %s\n", prefix, sid); - free(sid); - - /* proceed to next ACE */ - ace = (ACCESS_ALLOWED_ACE *)(((char *)ace) + - le16_to_cpu(ace->size)); - } -} - - -static void ntfs_dump_security_descriptor(SECURITY_DESCRIPTOR_ATTR *sec_desc, - const char *indent) -{ - char *sid; - - printf("%s\tRevision:\t\t %u\n", indent, sec_desc->revision); - - /* TODO: parse the flags */ - printf("%s\tControl:\t\t 0x%04x\n", indent, - le16_to_cpu(sec_desc->control)); - - if (~sec_desc->control & SE_SELF_RELATIVE) { - SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)sec_desc; - - printf("%s\tOwner SID pointer:\t %p\n", indent, sd->owner); - printf("%s\tGroup SID pointer:\t %p\n", indent, sd->group); - printf("%s\tSACL pointer:\t\t %p\n", indent, sd->sacl); - printf("%s\tDACL pointer:\t\t %p\n", indent, sd->dacl); - - return; - } - - if (sec_desc->owner) { - sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc + - le32_to_cpu(sec_desc->owner)), NULL, 0); - printf("%s\tOwner SID:\t\t %s\n", indent, sid); - free(sid); - } else - printf("%s\tOwner SID:\t\t missing\n", indent); - - if (sec_desc->group) { - sid = ntfs_sid_to_mbs((SID *)((char *)sec_desc + - le32_to_cpu(sec_desc->group)), NULL, 0); - printf("%s\tGroup SID:\t\t %s\n", indent, sid); - free(sid); - } else - printf("%s\tGroup SID:\t\t missing\n", indent); - - printf("%s\tSystem ACL:\t\t ", indent); - if (sec_desc->control & SE_SACL_PRESENT) { - if (sec_desc->control & SE_SACL_DEFAULTED) { - printf("defaulted"); - } - printf("\n"); - ntfs_dump_acl(indent ? "\t\t\t" : "\t\t", - (ACL *)((char *)sec_desc + - le32_to_cpu(sec_desc->sacl))); - } else { - printf("missing\n"); - } - - printf("%s\tDiscretionary ACL:\t ", indent); - if (sec_desc->control & SE_DACL_PRESENT) { - if (sec_desc->control & SE_SACL_DEFAULTED) { - printf("defaulted"); - } - printf("\n"); - ntfs_dump_acl(indent ? "\t\t\t" : "\t\t", - (ACL *)((char *)sec_desc + - le32_to_cpu(sec_desc->dacl))); - } else { - printf("missing\n"); - } -} - -/** - * ntfs_dump_security_descriptor() - * - * dump the security information about the file - */ -static void ntfs_dump_attr_security_descriptor(ATTR_RECORD *attr, ntfs_volume *vol) -{ - SECURITY_DESCRIPTOR_ATTR *sec_desc_attr; - - if (attr->non_resident) { - /* FIXME: We don't handle fragmented mapping pairs case. */ - runlist *rl = ntfs_mapping_pairs_decompress(vol, attr, NULL); - if (rl) { - s64 data_size, bytes_read; - - data_size = sle64_to_cpu(attr->u.nonres.data_size); - sec_desc_attr = ntfs_malloc(data_size); - if (!sec_desc_attr) { - free(rl); - return; - } - bytes_read = ntfs_rl_pread(vol, rl, 0, - data_size, sec_desc_attr); - if (bytes_read != data_size) { - ntfs_log_error("ntfsinfo error: could not " - "read security descriptor\n"); - free(rl); - free(sec_desc_attr); - return; - } - free(rl); - } else { - ntfs_log_error("ntfsinfo error: could not " - "decompress runlist\n"); - return; - } - } else { - sec_desc_attr = (SECURITY_DESCRIPTOR_ATTR *)((u8*)attr + - le16_to_cpu(attr->u.res.value_offset)); - } - - ntfs_dump_security_descriptor(sec_desc_attr, ""); - - if (attr->non_resident) - free(sec_desc_attr); -} - -/** - * ntfs_dump_volume_name() - * - * dump the name of the volume the inode belongs to - */ -static void ntfs_dump_attr_volume_name(ATTR_RECORD *attr) -{ - ntfschar *ucs_vol_name = NULL; - - if (le32_to_cpu(attr->u.res.value_length) > 0) { - char *mbs_vol_name = NULL; - int mbs_vol_name_size; - /* calculate volume name position */ - ucs_vol_name = (ntfschar*)((u8*)attr + - le16_to_cpu(attr->u.res.value_offset)); - /* convert the name to current locale multibyte sequence */ - mbs_vol_name_size = ntfs_ucstombs(ucs_vol_name, - le32_to_cpu(attr->u.res.value_length) / - sizeof(ntfschar), &mbs_vol_name, 0); - - if (mbs_vol_name_size>0) { - /* output the converted name. */ - printf("\tVolume Name:\t\t '%s'\n", mbs_vol_name); - free(mbs_vol_name); - } else - ntfs_log_perror("ntfsinfo error: could not parse " - "volume name"); - } else - printf("\tVolume Name:\t\t unnamed\n"); -} - -/** - * ntfs_dump_volume_information() - * - * dump the information for the volume the inode belongs to - * - */ -static void ntfs_dump_attr_volume_information(ATTR_RECORD *attr) -{ - VOLUME_INFORMATION *vol_information = NULL; - - vol_information = (VOLUME_INFORMATION*)((char *)attr+ - le16_to_cpu(attr->u.res.value_offset)); - - printf("\tVolume Version:\t\t %d.%d\n", vol_information->major_ver, - vol_information->minor_ver); - printf("\tVolume Flags:\t\t "); - if (vol_information->flags & VOLUME_IS_DIRTY) - printf("DIRTY "); - if (vol_information->flags & VOLUME_RESIZE_LOG_FILE) - printf("RESIZE_LOG "); - if (vol_information->flags & VOLUME_UPGRADE_ON_MOUNT) - printf("UPG_ON_MOUNT "); - if (vol_information->flags & VOLUME_MOUNTED_ON_NT4) - printf("MOUNTED_NT4 "); - if (vol_information->flags & VOLUME_DELETE_USN_UNDERWAY) - printf("DEL_USN "); - if (vol_information->flags & VOLUME_REPAIR_OBJECT_ID) - printf("REPAIR_OBJID "); - if (vol_information->flags & VOLUME_CHKDSK_UNDERWAY) - printf("CHKDSK_UNDERWAY "); - if (vol_information->flags & VOLUME_MODIFIED_BY_CHKDSK) - printf("MOD_BY_CHKDSK "); - if (vol_information->flags & VOLUME_FLAGS_MASK) { - printf("(0x%04x)\n", - (unsigned)le16_to_cpu(vol_information->flags)); - } else - printf("none set (0x0000)\n"); - if (vol_information->flags & (~VOLUME_FLAGS_MASK)) - printf("\t\t\t\t Unknown Flags: 0x%04x\n", - le16_to_cpu(vol_information->flags & - (~VOLUME_FLAGS_MASK))); -} - -static ntfschar NTFS_DATA_SDS[5] = { const_cpu_to_le16('$'), - const_cpu_to_le16('S'), const_cpu_to_le16('D'), - const_cpu_to_le16('S'), const_cpu_to_le16('\0') }; - -static void ntfs_dump_sds_entry(SECURITY_DESCRIPTOR_HEADER *sds) -{ - SECURITY_DESCRIPTOR_RELATIVE *sd; - - ntfs_log_verbose("\n"); - ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n", - (unsigned)le32_to_cpu(sds->hash)); - ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(sds->security_id), - (unsigned)le32_to_cpu(sds->security_id)); - ntfs_log_verbose("\t\tOffset:\t\t\t %llu (0x%llx)\n", - (unsigned long long)le64_to_cpu(sds->offset), - (unsigned long long)le64_to_cpu(sds->offset)); - ntfs_log_verbose("\t\tLength:\t\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(sds->length), - (unsigned)le32_to_cpu(sds->length)); - - sd = (SECURITY_DESCRIPTOR_RELATIVE *)((char *)sds + - sizeof(SECURITY_DESCRIPTOR_HEADER)); - - ntfs_dump_security_descriptor(sd, "\t"); -} - -static void ntfs_dump_sds(ATTR_RECORD *attr, ntfs_inode *ni) -{ - SECURITY_DESCRIPTOR_HEADER *sds, *sd; - ntfschar *name; - int name_len; - s64 data_size; - u64 inode; - - inode = ni->mft_no; - if (ni->nr_extents < 0) - inode = ni->u.base_ni->mft_no; - if (FILE_Secure != inode) - return; - - name_len = attr->name_length; - if (!name_len) - return; - - name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)); - if (!ntfs_names_are_equal(NTFS_DATA_SDS, sizeof(NTFS_DATA_SDS) / 2 - 1, - name, name_len, 0, NULL, 0)) - return; - - sd = sds = ntfs_attr_readall(ni, AT_DATA, name, name_len, &data_size); - if (!sd) { - ntfs_log_perror("Failed to read $SDS attribute"); - return; - } - /* - * FIXME: The right way is based on the indexes, so we couldn't - * miss real entries. For now, dump until it makes sense. - */ - while (sd->length && sd->hash && - le64_to_cpu(sd->offset) < (u64)data_size && - le32_to_cpu(sd->length) < (u64)data_size && - le64_to_cpu(sd->offset) + - le32_to_cpu(sd->length) < (u64)data_size) { - ntfs_dump_sds_entry(sd); - sd = (SECURITY_DESCRIPTOR_HEADER *)((char*)sd + - ((le32_to_cpu(sd->length) + 15) & ~15)); - } - free(sds); -} - -static const char *get_attribute_type_name(le32 type) -{ - switch (type) { - case AT_UNUSED: return "$UNUSED"; - case AT_STANDARD_INFORMATION: return "$STANDARD_INFORMATION"; - case AT_ATTRIBUTE_LIST: return "$ATTRIBUTE_LIST"; - case AT_FILE_NAME: return "$FILE_NAME"; - case AT_OBJECT_ID: return "$OBJECT_ID"; - case AT_SECURITY_DESCRIPTOR: return "$SECURITY_DESCRIPTOR"; - case AT_VOLUME_NAME: return "$VOLUME_NAME"; - case AT_VOLUME_INFORMATION: return "$VOLUME_INFORMATION"; - case AT_DATA: return "$DATA"; - case AT_INDEX_ROOT: return "$INDEX_ROOT"; - case AT_INDEX_ALLOCATION: return "$INDEX_ALLOCATION"; - case AT_BITMAP: return "$BITMAP"; - case AT_REPARSE_POINT: return "$REPARSE_POINT"; - case AT_EA_INFORMATION: return "$EA_INFORMATION"; - case AT_EA: return "$EA"; - case AT_PROPERTY_SET: return "$PROPERTY_SET"; - case AT_LOGGED_UTILITY_STREAM: return "$LOGGED_UTILITY_STREAM"; - case AT_END: return "$END"; - } - - return "$UNKNOWN"; -} - -static const char * ntfs_dump_lcn(LCN lcn) -{ - switch (lcn) { - case LCN_HOLE: - return "\t"; - case LCN_RL_NOT_MAPPED: - return ""; - case LCN_ENOENT: - return "\t"; - case LCN_EINVAL: - return "\t"; - case LCN_EIO: - return "\t"; - default: - ntfs_log_error("Invalid LCN value %llx passed to " - "ntfs_dump_lcn().\n", lcn); - return "???\t"; - } -} - -static void ntfs_dump_attribute_header(ntfs_attr_search_ctx *ctx, - ntfs_volume *vol) -{ - ATTR_RECORD *a = ctx->attr; - - printf("Dumping attribute %s (0x%x) from mft record %lld (0x%llx)\n", - get_attribute_type_name(a->type), - (unsigned)le32_to_cpu(a->type), - (unsigned long long)ctx->ntfs_ino->mft_no, - (unsigned long long)ctx->ntfs_ino->mft_no); - - ntfs_log_verbose("\tAttribute length:\t %u (0x%x)\n", - (unsigned)le32_to_cpu(a->length), - (unsigned)le32_to_cpu(a->length)); - printf("\tResident: \t\t %s\n", a->non_resident ? "No" : "Yes"); - ntfs_log_verbose("\tName length:\t\t %u (0x%x)\n", - (unsigned)a->name_length, (unsigned)a->name_length); - ntfs_log_verbose("\tName offset:\t\t %u (0x%x)\n", - (unsigned)le16_to_cpu(a->name_offset), - (unsigned)le16_to_cpu(a->name_offset)); - - /* Dump the attribute (stream) name */ - if (a->name_length) { - char *attribute_name = NULL; - - attribute_name = ntfs_attr_get_name_mbs(a); - if (attribute_name) { - printf("\tAttribute name:\t\t '%s'\n", attribute_name); - free(attribute_name); - } else - ntfs_log_perror("Error: couldn't parse attribute name"); - } - - /* TODO: parse the flags */ - printf("\tAttribute flags:\t 0x%04x\n", - (unsigned)le16_to_cpu(a->flags)); - printf("\tAttribute instance:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(a->instance), - (unsigned)le16_to_cpu(a->instance)); - - /* Resident attribute */ - if (!a->non_resident) { - printf("\tData size:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(a->u.res.value_length), - (unsigned)le32_to_cpu(a->u.res.value_length)); - ntfs_log_verbose("\tData offset:\t\t %u (0x%x)\n", - (unsigned)le16_to_cpu(a->u.res.value_offset), - (unsigned)le16_to_cpu(a->u.res.value_offset)); - /* TODO: parse the flags */ - printf("\tResident flags:\t\t 0x%02x\n", - (unsigned)a->u.res.resident_flags); - ntfs_log_verbose("\tReservedR:\t\t %d (0x%x)\n", - (unsigned)a->u.res.reservedR, (unsigned)a->u.res.reservedR); - return; - } - - /* Non-resident attribute */ - ntfs_log_verbose("\tLowest VCN\t\t %lld (0x%llx)\n", - (long long)sle64_to_cpu(a->u.nonres.lowest_vcn), - (unsigned long long)sle64_to_cpu(a->u.nonres.lowest_vcn)); - ntfs_log_verbose("\tHighest VCN:\t\t %lld (0x%llx)\n", - (long long)sle64_to_cpu(a->u.nonres.highest_vcn), - (unsigned long long)sle64_to_cpu(a->u.nonres.highest_vcn)); - ntfs_log_verbose("\tMapping pairs offset:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(a->u.nonres.mapping_pairs_offset), - (unsigned)le16_to_cpu(a->u.nonres.mapping_pairs_offset)); - printf("\tCompression unit:\t %u (0x%x)\n", - (unsigned)a->u.nonres.compression_unit, - (unsigned)a->u.nonres.compression_unit); - /* TODO: dump the 5 reserved bytes here in verbose mode */ - - if (!a->u.nonres.lowest_vcn) { - printf("\tData size:\t\t %llu (0x%llx)\n", - (long long)sle64_to_cpu(a->u.nonres.data_size), - (unsigned long long)sle64_to_cpu(a->u.nonres.data_size)); - printf("\tAllocated size:\t\t %llu (0x%llx)\n", - (long long)sle64_to_cpu(a->u.nonres.allocated_size), - (unsigned long long) - sle64_to_cpu(a->u.nonres.allocated_size)); - printf("\tInitialized size:\t %llu (0x%llx)\n", - (long long)sle64_to_cpu(a->u.nonres.initialized_size), - (unsigned long long) - sle64_to_cpu(a->u.nonres.initialized_size)); - if (a->u.nonres.compression_unit || a->flags & ATTR_IS_COMPRESSED || - a->flags & ATTR_IS_SPARSE) - printf("\tCompressed size:\t %llu (0x%llx)\n", - (signed long long) - sle64_to_cpu(a->u.nonres.compressed_size), - (signed long long) - sle64_to_cpu(a->u.nonres.compressed_size)); - } - - if (opts.verbose) { - runlist *rl; - - rl = ntfs_mapping_pairs_decompress(vol, a, NULL); - if (rl) { - runlist *rlc = rl; - - // TODO: Switch this to properly aligned hex... - printf("\tRunlist:\tVCN\t\tLCN\t\tLength\n"); - while (rlc->length) { - if (rlc->lcn >= 0) - printf("\t\t\t0x%llx\t\t0x%llx\t\t" - "0x%llx\n", rlc->vcn, - rlc->lcn, rlc->length); - else - printf("\t\t\t0x%llx\t\t%s\t" - "0x%llx\n", rlc->vcn, - ntfs_dump_lcn(rlc->lcn), - rlc->length); - rlc++; - } - free(rl); - } else - ntfs_log_error("Error: couldn't decompress runlist\n"); - } -} - -/** - * ntfs_dump_data_attr() - * - * dump some info about the data attribute if it's metadata - */ -static void ntfs_dump_attr_data(ATTR_RECORD *attr, ntfs_inode *ni) -{ - if (opts.verbose) - ntfs_dump_sds(attr, ni); -} - -typedef enum { - INDEX_ATTR_UNKNOWN, - INDEX_ATTR_DIRECTORY_I30, - INDEX_ATTR_SECURE_SII, - INDEX_ATTR_SECURE_SDH, - INDEX_ATTR_OBJID_O, - INDEX_ATTR_REPARSE_R, - INDEX_ATTR_QUOTA_O, - INDEX_ATTR_QUOTA_Q, -} INDEX_ATTR_TYPE; - -static void ntfs_dump_index_key(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type) -{ - char *sid; - char printable_GUID[37]; - - switch (type) { - case INDEX_ATTR_SECURE_SII: - ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n", - (unsigned) - le32_to_cpu(entry->key.sii.security_id), - (unsigned) - le32_to_cpu(entry->key.sii.security_id)); - break; - case INDEX_ATTR_SECURE_SDH: - ntfs_log_verbose("\t\tKey hash:\t\t 0x%08x\n", - (unsigned)le32_to_cpu(entry->key.sdh.hash)); - ntfs_log_verbose("\t\tKey security id:\t %u (0x%x)\n", - (unsigned) - le32_to_cpu(entry->key.sdh.security_id), - (unsigned) - le32_to_cpu(entry->key.sdh.security_id)); - break; - case INDEX_ATTR_OBJID_O: - ntfs_guid_to_mbs(&entry->key.object_id, printable_GUID); - ntfs_log_verbose("\t\tKey GUID:\t\t %s\n", printable_GUID); - break; - case INDEX_ATTR_REPARSE_R: - ntfs_log_verbose("\t\tKey reparse tag:\t 0x%08x\n", (unsigned) - le32_to_cpu(entry->key.reparse.reparse_tag)); - ntfs_log_verbose("\t\tKey file id:\t\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(entry->key.reparse.file_id), - (unsigned long long) - le64_to_cpu(entry->key.reparse.file_id)); - break; - case INDEX_ATTR_QUOTA_O: - sid = ntfs_sid_to_mbs(&entry->key.sid, NULL, 0); - ntfs_log_verbose("\t\tKey SID:\t\t %s\n", sid); - free(sid); - break; - case INDEX_ATTR_QUOTA_Q: - ntfs_log_verbose("\t\tKey owner id:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(entry->key.owner_id), - (unsigned)le32_to_cpu(entry->key.owner_id)); - break; - default: - ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n", - (unsigned)type); - break; - } -} - -#ifdef __sun -#pragma pack(1) -#endif -typedef union { - SII_INDEX_DATA sii; /* $SII index data in $Secure */ - SDH_INDEX_DATA sdh; /* $SDH index data in $Secure */ - QUOTA_O_INDEX_DATA quota_o; /* $O index data in $Quota */ - QUOTA_CONTROL_ENTRY quota_q; /* $Q index data in $Quota */ -} __attribute__((__packed__)) INDEX_ENTRY_DATA; -#ifdef __sun -#pragma pack() -#endif - -static void ntfs_dump_index_data(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type) -{ - INDEX_ENTRY_DATA *data; - - data = (INDEX_ENTRY_DATA *)((u8 *)entry + - le16_to_cpu(entry->u.s.data_offset)); - - switch (type) { - case INDEX_ATTR_SECURE_SII: - ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n", - (unsigned)le32_to_cpu(data->sii.hash)); - ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->sii.security_id), - (unsigned)le32_to_cpu(data->sii.security_id)); - ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(data->sii.offset), - (unsigned long long) - le64_to_cpu(data->sii.offset)); - ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->sii.length), - (unsigned)le32_to_cpu(data->sii.length)); - break; - case INDEX_ATTR_SECURE_SDH: - ntfs_log_verbose("\t\tHash:\t\t\t 0x%08x\n", - (unsigned)le32_to_cpu(data->sdh.hash)); - ntfs_log_verbose("\t\tSecurity id:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->sdh.security_id), - (unsigned)le32_to_cpu(data->sdh.security_id)); - ntfs_log_verbose("\t\tOffset in $SDS:\t\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(data->sdh.offset), - (unsigned long long) - le64_to_cpu(data->sdh.offset)); - ntfs_log_verbose("\t\tLength in $SDS:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->sdh.length), - (unsigned)le32_to_cpu(data->sdh.length)); - ntfs_log_verbose("\t\tUnknown (padding):\t 0x%08x\n", - (unsigned)le32_to_cpu(data->sdh.reserved_II)); - break; - case INDEX_ATTR_OBJID_O: { - OBJ_ID_INDEX_DATA *object_id_data; - char printable_GUID[37]; - - object_id_data = (OBJ_ID_INDEX_DATA*)((u8*)entry + - le16_to_cpu(entry->u.s.data_offset)); - ntfs_log_verbose("\t\tMFT Number:\t\t 0x%llx\n", - (unsigned long long) - MREF_LE(object_id_data->mft_reference)); - ntfs_log_verbose("\t\tMFT Sequence Number:\t 0x%x\n", - (unsigned) - MSEQNO_LE(object_id_data->mft_reference)); - ntfs_guid_to_mbs(&object_id_data->u.s.birth_volume_id, - printable_GUID); - ntfs_log_verbose("\t\tBirth volume id GUID:\t %s\n", - printable_GUID); - ntfs_guid_to_mbs(&object_id_data->u.s.birth_object_id, - printable_GUID); - ntfs_log_verbose("\t\tBirth object id GUID:\t %s\n", - printable_GUID); - ntfs_guid_to_mbs(&object_id_data->u.s.domain_id, printable_GUID); - ntfs_log_verbose("\t\tDomain id GUID:\t\t %s\n", - printable_GUID); - } - break; - case INDEX_ATTR_REPARSE_R: - /* TODO */ - break; - case INDEX_ATTR_QUOTA_O: - ntfs_log_verbose("\t\tOwner id:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->quota_o.owner_id), - (unsigned)le32_to_cpu(data->quota_o.owner_id)); - ntfs_log_verbose("\t\tUnknown:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(data->quota_o.unknown), - (unsigned)le32_to_cpu(data->quota_o.unknown)); - break; - case INDEX_ATTR_QUOTA_Q: - ntfs_log_verbose("\t\tVersion:\t\t %u\n", - (unsigned)le32_to_cpu(data->quota_q.version)); - ntfs_log_verbose("\t\tQuota flags:\t\t 0x%08x\n", - (unsigned)le32_to_cpu(data->quota_q.flags)); - ntfs_log_verbose("\t\tBytes used:\t\t %llu (0x%llx)\n", - (unsigned long long) - le64_to_cpu(data->quota_q.bytes_used), - (unsigned long long) - le64_to_cpu(data->quota_q.bytes_used)); - ntfs_log_verbose("\t\tLast changed:\t\t %s", - ntfsinfo_time_to_str( - data->quota_q.change_time)); - ntfs_log_verbose("\t\tThreshold:\t\t %lld (0x%llx)\n", - (unsigned long long) - sle64_to_cpu(data->quota_q.threshold), - (unsigned long long) - sle64_to_cpu(data->quota_q.threshold)); - ntfs_log_verbose("\t\tLimit:\t\t\t %lld (0x%llx)\n", - (unsigned long long) - sle64_to_cpu(data->quota_q.limit), - (unsigned long long) - sle64_to_cpu(data->quota_q.limit)); - ntfs_log_verbose("\t\tExceeded time:\t\t %lld (0x%llx)\n", - (unsigned long long) - sle64_to_cpu(data->quota_q.exceeded_time), - (unsigned long long) - sle64_to_cpu(data->quota_q.exceeded_time)); - if (le16_to_cpu(entry->u.s.data_length) > 48) { - char *sid; - sid = ntfs_sid_to_mbs(&data->quota_q.sid, NULL, 0); - ntfs_log_verbose("\t\tOwner SID:\t\t %s\n", sid); - free(sid); - } - break; - default: - ntfs_log_verbose("\t\tIndex attr type is UNKNOWN: \t 0x%08x\n", - (unsigned)type); - break; - } -} - -/** - * ntfs_dump_index_entries() - * - * dump sequence of index_entries and return number of entries dumped. - */ -static int ntfs_dump_index_entries(INDEX_ENTRY *entry, INDEX_ATTR_TYPE type) -{ - int numb_entries = 1; - while (1) { - if (!opts.verbose) { - if (entry->flags & INDEX_ENTRY_END) - break; - entry = (INDEX_ENTRY *)((u8 *)entry + - le16_to_cpu(entry->length)); - numb_entries++; - continue; - } - ntfs_log_verbose("\t\tEntry length:\t\t %u (0x%x)\n", - (unsigned)le16_to_cpu(entry->length), - (unsigned)le16_to_cpu(entry->length)); - ntfs_log_verbose("\t\tKey length:\t\t %u (0x%x)\n", - (unsigned)le16_to_cpu(entry->key_length), - (unsigned)le16_to_cpu(entry->key_length)); - ntfs_log_verbose("\t\tIndex entry flags:\t 0x%02x\n", - (unsigned)le16_to_cpu(entry->flags)); - - if (entry->flags & INDEX_ENTRY_NODE) - ntfs_log_verbose("\t\tSubnode VCN:\t\t %lld (0x%llx)\n", - ntfs_ie_get_vcn(entry), - ntfs_ie_get_vcn(entry)); - if (entry->flags & INDEX_ENTRY_END) - break; - - switch (type) { - case INDEX_ATTR_DIRECTORY_I30: - ntfs_log_verbose("\t\tFILE record number:\t %llu " - "(0x%llx)\n", (unsigned long long) - MREF_LE(entry->u.indexed_file), - (unsigned long long) - MREF_LE(entry->u.indexed_file)); - ntfs_dump_filename("\t\t", &entry->key.file_name); - break; - default: - ntfs_log_verbose("\t\tData offset:\t\t %u (0x%x)\n", - (unsigned) - le16_to_cpu(entry->u.s.data_offset), - (unsigned) - le16_to_cpu(entry->u.s.data_offset)); - ntfs_log_verbose("\t\tData length:\t\t %u (0x%x)\n", - (unsigned) - le16_to_cpu(entry->u.s.data_length), - (unsigned) - le16_to_cpu(entry->u.s.data_length)); - ntfs_dump_index_key(entry, type); - ntfs_log_verbose("\t\tKey Data:\n"); - ntfs_dump_index_data(entry, type); - break; - } - if (!entry->length) { - ntfs_log_verbose("\tWARNING: Corrupt index entry, " - "skipping the remainder of this index " - "block.\n"); - break; - } - entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length)); - numb_entries++; - ntfs_log_verbose("\n"); - } - ntfs_log_verbose("\tEnd of index block reached\n"); - return numb_entries; -} - -#define COMPARE_INDEX_NAMES(attr, name) \ - ntfs_names_are_equal((name), sizeof(name) / 2 - 1, \ - (ntfschar*)((char*)(attr) + le16_to_cpu((attr)->name_offset)), \ - (attr)->name_length, 0, NULL, 0) - -static INDEX_ATTR_TYPE get_index_attr_type(ntfs_inode *ni, ATTR_RECORD *attr, - INDEX_ROOT *index_root) -{ - char file_name[64]; - - if (!attr->name_length) - return INDEX_ATTR_UNKNOWN; - - if (index_root->type) { - if (index_root->type == AT_FILE_NAME) - return INDEX_ATTR_DIRECTORY_I30; - else - /* weird, this should be illegal */ - ntfs_log_error("Unknown index attribute type: 0x%0X\n", - index_root->type); - return INDEX_ATTR_UNKNOWN; - } - - if (utils_is_metadata(ni) <= 0) - return INDEX_ATTR_UNKNOWN; - if (utils_inode_get_name(ni, file_name, sizeof(file_name)) <= 0) - return INDEX_ATTR_UNKNOWN; - - if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SDH)) - return INDEX_ATTR_SECURE_SDH; - else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII)) - return INDEX_ATTR_SECURE_SII; - else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_SII)) - return INDEX_ATTR_SECURE_SII; - else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_Q)) - return INDEX_ATTR_QUOTA_Q; - else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_R)) - return INDEX_ATTR_REPARSE_R; - else if (COMPARE_INDEX_NAMES(attr, NTFS_INDEX_O)) { - if (!strcmp(file_name, "/$Extend/$Quota")) - return INDEX_ATTR_QUOTA_O; - else if (!strcmp(file_name, "/$Extend/$ObjId")) - return INDEX_ATTR_OBJID_O; - } - - return INDEX_ATTR_UNKNOWN; -} - -static void ntfs_dump_index_attr_type(INDEX_ATTR_TYPE type) -{ - if (type == INDEX_ATTR_DIRECTORY_I30) - printf("DIRECTORY_I30"); - else if (type == INDEX_ATTR_SECURE_SDH) - printf("SECURE_SDH"); - else if (type == INDEX_ATTR_SECURE_SII) - printf("SECURE_SII"); - else if (type == INDEX_ATTR_OBJID_O) - printf("OBJID_O"); - else if (type == INDEX_ATTR_QUOTA_O) - printf("QUOTA_O"); - else if (type == INDEX_ATTR_QUOTA_Q) - printf("QUOTA_Q"); - else if (type == INDEX_ATTR_REPARSE_R) - printf("REPARSE_R"); - else - printf("UNKNOWN"); - printf("\n"); -} - -static void ntfs_dump_index_header(const char *indent, INDEX_HEADER *idx) -{ - printf("%sEntries Offset:\t\t %u (0x%x)\n", indent, - (unsigned)le32_to_cpu(idx->entries_offset), - (unsigned)le32_to_cpu(idx->entries_offset)); - printf("%sIndex Size:\t\t %u (0x%x)\n", indent, - (unsigned)le32_to_cpu(idx->index_length), - (unsigned)le32_to_cpu(idx->index_length)); - printf("%sAllocated Size:\t\t %u (0x%x)\n", indent, - (unsigned)le32_to_cpu(idx->allocated_size), - (unsigned)le32_to_cpu(idx->allocated_size)); - printf("%sIndex header flags:\t 0x%02x\n", indent, idx->flags); - - /* FIXME: there are 3 reserved bytes here */ -} - -/** - * ntfs_dump_attr_index_root() - * - * dump the index_root attribute - */ -static void ntfs_dump_attr_index_root(ATTR_RECORD *attr, ntfs_inode *ni) -{ - INDEX_ATTR_TYPE type; - INDEX_ROOT *index_root = NULL; - INDEX_ENTRY *entry; - - index_root = (INDEX_ROOT*)((u8*)attr + le16_to_cpu(attr->u.res.value_offset)); - - /* attr_type dumping */ - type = get_index_attr_type(ni, attr, index_root); - printf("\tIndexed Attr Type:\t "); - ntfs_dump_index_attr_type(type); - - /* collation rule dumping */ - printf("\tCollation Rule:\t\t %u (0x%x)\n", - (unsigned)le32_to_cpu(index_root->collation_rule), - (unsigned)le32_to_cpu(index_root->collation_rule)); -/* COLLATION_BINARY, COLLATION_FILE_NAME, COLLATION_UNICODE_STRING, - COLLATION_NTOFS_ULONG, COLLATION_NTOFS_SID, - COLLATION_NTOFS_SECURITY_HASH, COLLATION_NTOFS_ULONGS */ - - printf("\tIndex Block Size:\t %u (0x%x)\n", - (unsigned)le32_to_cpu(index_root->index_block_size), - (unsigned)le32_to_cpu(index_root->index_block_size)); - printf("\tClusters Per Block:\t %u (0x%x)\n", - (unsigned)index_root->clusters_per_index_block, - (unsigned)index_root->clusters_per_index_block); - - ntfs_dump_index_header("\t", &index_root->index); - - entry = (INDEX_ENTRY*)((u8*)index_root + - le32_to_cpu(index_root->index.entries_offset) + 0x10); - ntfs_log_verbose("\tDumping index root:\n"); - printf("\tIndex entries total:\t %d\n", - ntfs_dump_index_entries(entry, type)); -} - -static void ntfs_dump_usa_lsn(const char *indent, MFT_RECORD *mrec) -{ - printf("%sUpd. Seq. Array Off.:\t %u (0x%x)\n", indent, - (unsigned)le16_to_cpu(mrec->usa_ofs), - (unsigned)le16_to_cpu(mrec->usa_ofs)); - printf("%sUpd. Seq. Array Count:\t %u (0x%x)\n", indent, - (unsigned)le16_to_cpu(mrec->usa_count), - (unsigned)le16_to_cpu(mrec->usa_count)); - printf("%sUpd. Seq. Number:\t %u (0x%x)\n", indent, - (unsigned)le16_to_cpup((u16 *)((u8 *)mrec + - le16_to_cpu(mrec->usa_ofs))), - (unsigned)le16_to_cpup((u16 *)((u8 *)mrec + - le16_to_cpu(mrec->usa_ofs)))); - printf("%sLogFile Seq. Number:\t 0x%llx\n", indent, - (unsigned long long)sle64_to_cpu(mrec->lsn)); -} - - -static s32 ntfs_dump_index_block(INDEX_BLOCK *ib, INDEX_ATTR_TYPE type, - u32 ib_size) -{ - INDEX_ENTRY *entry; - - if (ntfs_mst_post_read_fixup((NTFS_RECORD*)ib, ib_size)) { - ntfs_log_perror("Damaged INDX record"); - return -1; - } - ntfs_log_verbose("\tDumping index block:\n"); - if (opts.verbose) - ntfs_dump_usa_lsn("\t\t", (MFT_RECORD*)ib); - - ntfs_log_verbose("\t\tNode VCN:\t\t %lld (0x%llx)\n", - (unsigned long long)sle64_to_cpu(ib->index_block_vcn), - (unsigned long long)sle64_to_cpu(ib->index_block_vcn)); - - entry = (INDEX_ENTRY*)((u8*)ib + - le32_to_cpu(ib->index.entries_offset) + 0x18); - - if (opts.verbose) { - ntfs_dump_index_header("\t\t", &ib->index); - printf("\n"); - } - - return ntfs_dump_index_entries(entry, type); -} - -/** - * ntfs_dump_attr_index_allocation() - * - * dump context of the index_allocation attribute - */ -static void ntfs_dump_attr_index_allocation(ATTR_RECORD *attr, ntfs_inode *ni) -{ - INDEX_ALLOCATION *allocation, *tmp_alloc; - INDEX_ROOT *ir; - INDEX_ATTR_TYPE type; - int total_entries = 0; - int total_indx_blocks = 0; - u8 *bitmap, *byte; - int bit; - ntfschar *name; - u32 name_len; - s64 data_size; - - ir = ntfs_index_root_get(ni, attr); - if (!ir) { - ntfs_log_perror("Failed to read $INDEX_ROOT attribute"); - return; - } - - type = get_index_attr_type(ni, attr, ir); - - name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)); - name_len = attr->name_length; - - byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL); - if (!byte) { - ntfs_log_perror("Failed to read $BITMAP attribute"); - goto out_index_root; - } - - tmp_alloc = allocation = ntfs_attr_readall(ni, AT_INDEX_ALLOCATION, - name, name_len, &data_size); - if (!tmp_alloc) { - ntfs_log_perror("Failed to read $INDEX_ALLOCATION attribute"); - goto out_bitmap; - } - - bit = 0; - while ((u8 *)tmp_alloc < (u8 *)allocation + data_size) { - if (*byte & (1 << bit)) { - int entries; - - entries = ntfs_dump_index_block(tmp_alloc, type, - le32_to_cpu( - ir->index_block_size)); - if (entries != -1) { - total_entries += entries; - total_indx_blocks++; - ntfs_log_verbose("\tIndex entries:\t\t %d\n", - entries); - } - } - tmp_alloc = (INDEX_ALLOCATION *)((u8 *)tmp_alloc + - le32_to_cpu( - ir->index_block_size)); - bit++; - if (bit > 7) { - bit = 0; - byte++; - } - } - - printf("\tIndex entries total:\t %d\n", total_entries); - printf("\tINDX blocks total:\t %d\n", total_indx_blocks); - - free(allocation); -out_bitmap: - free(bitmap); -out_index_root: - free(ir); -} - -/** - * ntfs_dump_attr_bitmap() - * - * dump the bitmap attribute - */ -static void ntfs_dump_attr_bitmap(ATTR_RECORD *attr __attribute__((unused))) -{ - /* TODO */ -} - -/** - * ntfs_dump_attr_reparse_point() - * - * of ntfs 3.x dumps the reparse_point attribute - */ -static void ntfs_dump_attr_reparse_point(ATTR_RECORD *attr __attribute__((unused))) -{ - /* TODO */ -} - -/** - * ntfs_dump_attr_ea_information() - * - * dump the ea_information attribute - */ -static void ntfs_dump_attr_ea_information(ATTR_RECORD *attr) -{ - EA_INFORMATION *ea_info; - - ea_info = (EA_INFORMATION*)((u8*)attr + - le16_to_cpu(attr->u.res.value_offset)); - printf("\tPacked EA length:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(ea_info->ea_length), - (unsigned)le16_to_cpu(ea_info->ea_length)); - printf("\tNEED_EA count:\t\t %u (0x%x)\n", - (unsigned)le16_to_cpu(ea_info->need_ea_count), - (unsigned)le16_to_cpu(ea_info->need_ea_count)); - printf("\tUnpacked EA length:\t %u (0x%x)\n", - (unsigned)le32_to_cpu(ea_info->ea_query_length), - (unsigned)le32_to_cpu(ea_info->ea_query_length)); -} - -/** - * ntfs_dump_attr_ea() - * - * dump the ea attribute - */ -static void ntfs_dump_attr_ea(ATTR_RECORD *attr, ntfs_volume *vol) -{ - EA_ATTR *ea; - u8 *buf = NULL; - s64 data_size; - - if (attr->non_resident) { - runlist *rl; - - data_size = sle64_to_cpu(attr->u.nonres.data_size); - if (!opts.verbose) - return; - /* FIXME: We don't handle fragmented mapping pairs case. */ - rl = ntfs_mapping_pairs_decompress(vol, attr, NULL); - if (rl) { - s64 bytes_read; - - buf = ntfs_malloc(data_size); - if (!buf) { - free(rl); - return; - } - bytes_read = ntfs_rl_pread(vol, rl, 0, data_size, buf); - if (bytes_read != data_size) { - ntfs_log_perror("ntfs_rl_pread failed"); - free(buf); - free(rl); - return; - } - free(rl); - ea = (EA_ATTR*)buf; - } else { - ntfs_log_perror("ntfs_mapping_pairs_decompress failed"); - return; - } - } else { - data_size = le32_to_cpu(attr->u.res.value_length); - if (!opts.verbose) - return; - ea = (EA_ATTR*)((u8*)attr + le16_to_cpu(attr->u.res.value_offset)); - } - while (1) { - printf("\n\tEA flags:\t\t "); - if (ea->flags) { - if (ea->flags == NEED_EA) - printf("NEED_EA\n"); - else - printf("Unknown (0x%02x)\n", - (unsigned)ea->flags); - } else - printf("NONE\n"); - printf("\tName length:\t %d (0x%x)\n", - (unsigned)ea->name_length, - (unsigned)ea->name_length); - printf("\tValue length:\t %d (0x%x)\n", - (unsigned)le16_to_cpu(ea->value_length), - (unsigned)le16_to_cpu(ea->value_length)); - printf("\tName:\t\t '%s'\n", ea->name); - printf("\tValue:\t\t "); - if (ea->name_length == 11 && - !strncmp((const char*)"SETFILEBITS", - (const char*)ea->name, 11)) - printf("0%o\n", (unsigned)le32_to_cpu(*(le32*) - (ea->name + ea->name_length + 1))); - else - printf("'%s'\n", ea->name + ea->name_length + 1); - if (ea->next_entry_offset) - ea = (EA_ATTR*)((u8*)ea + - le32_to_cpu(ea->next_entry_offset)); - else - break; - if ((u8*)ea - buf >= data_size) - break; - } - free(buf); -} - -/** - * ntfs_dump_attr_property_set() - * - * dump the property_set attribute - */ -static void ntfs_dump_attr_property_set(ATTR_RECORD *attr __attribute__((unused))) -{ - /* TODO */ -} - -static void ntfs_hex_dump(void *buf,unsigned int length); - -/** - * ntfs_dump_attr_logged_utility_stream() - * - * dump the property_set attribute - */ -static void ntfs_dump_attr_logged_utility_stream(ATTR_RECORD *attr, - ntfs_inode *ni) -{ - char *buf; - s64 size; - - if (!opts.verbose) - return; - buf = ntfs_attr_readall(ni, AT_LOGGED_UTILITY_STREAM, - ntfs_attr_get_name(attr), attr->name_length, &size); - if (buf) - ntfs_hex_dump(buf, size); - free(buf); - /* TODO */ -} - -/** - * ntfs_hex_dump - */ -static void ntfs_hex_dump(void *buf,unsigned int length) -{ - unsigned int i=0; - while (i126)) { - c = '.'; - } - printf("%c",c); - } - - /* end line */ - printf("\n"); - i=j; - } -} - -/** - * ntfs_dump_attr_unknown - */ -static void ntfs_dump_attr_unknown(ATTR_RECORD *attr) -{ - printf("===== Please report this unknown attribute type to %s =====\n", - NTFS_DEV_LIST); - - if (!attr->non_resident) { - /* hex dump */ - printf("\tDumping some of the attribute data:\n"); - ntfs_hex_dump((u8*)attr + le16_to_cpu(attr->u.res.value_offset), - (le32_to_cpu(attr->u.res.value_length) > 128) ? - 128 : le32_to_cpu(attr->u.res.value_length)); - } -} - -/** - * ntfs_dump_inode_general_info - */ -static void ntfs_dump_inode_general_info(ntfs_inode *inode) -{ - MFT_RECORD *mrec = inode->mrec; - le16 inode_flags = mrec->flags; - - printf("Dumping Inode %llu (0x%llx)\n", - (long long)inode->mft_no, - (unsigned long long)inode->mft_no); - - ntfs_dump_usa_lsn("", mrec); - printf("MFT Record Seq. Numb.:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(mrec->sequence_number), - (unsigned)le16_to_cpu(mrec->sequence_number)); - printf("Number of Hard Links:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(mrec->link_count), - (unsigned)le16_to_cpu(mrec->link_count)); - printf("Attribute Offset:\t %u (0x%x)\n", - (unsigned)le16_to_cpu(mrec->attrs_offset), - (unsigned)le16_to_cpu(mrec->attrs_offset)); - - printf("MFT Record Flags:\t "); - if (inode_flags) { - if (MFT_RECORD_IN_USE & inode_flags) { - printf("IN_USE "); - inode_flags &= ~MFT_RECORD_IN_USE; - } - if (MFT_RECORD_IS_DIRECTORY & inode_flags) { - printf("DIRECTORY "); - inode_flags &= ~MFT_RECORD_IS_DIRECTORY; - } - /* The meaning of IS_4 is illusive but not its existence. */ - if (MFT_RECORD_IS_4 & inode_flags) { - printf("IS_4 "); - inode_flags &= ~MFT_RECORD_IS_4; - } - if (MFT_RECORD_IS_VIEW_INDEX & inode_flags) { - printf("VIEW_INDEX "); - inode_flags &= ~MFT_RECORD_IS_VIEW_INDEX; - } - if (inode_flags) - printf("UNKNOWN: 0x%04x", (unsigned)le16_to_cpu( - inode_flags)); - } else { - printf("none"); - } - printf("\n"); - - printf("Bytes Used:\t\t %u (0x%x) bytes\n", - (unsigned)le32_to_cpu(mrec->bytes_in_use), - (unsigned)le32_to_cpu(mrec->bytes_in_use)); - printf("Bytes Allocated:\t %u (0x%x) bytes\n", - (unsigned)le32_to_cpu(mrec->bytes_allocated), - (unsigned)le32_to_cpu(mrec->bytes_allocated)); - - if (mrec->base_mft_record) { - printf("Base MFT Record:\t %llu (0x%llx)\n", - (unsigned long long) - MREF_LE(mrec->base_mft_record), - (unsigned long long) - MREF_LE(mrec->base_mft_record)); - } - printf("Next Attribute Instance: %u (0x%x)\n", - (unsigned)le16_to_cpu(mrec->next_attr_instance), - (unsigned)le16_to_cpu(mrec->next_attr_instance)); - - printf("MFT Padding:\t"); - ntfs_dump_bytes((u8 *)mrec, le16_to_cpu(mrec->usa_ofs) + - 2 * le16_to_cpu(mrec->usa_count), - le16_to_cpu(mrec->attrs_offset)); - printf("\n"); -} - -/** - * ntfs_get_file_attributes - */ -static void ntfs_dump_file_attributes(ntfs_inode *inode) -{ - ntfs_attr_search_ctx *ctx = NULL; - - /* then start enumerating attributes - see ntfs_attr_lookup documentation for detailed explanation */ - ctx = ntfs_attr_get_search_ctx(inode, NULL); - while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { - if (ctx->attr->type == AT_END || ctx->attr->type == AT_UNUSED) { - printf("Weird: %s attribute type was found, please " - "report this.\n", - get_attribute_type_name( - ctx->attr->type)); - continue; - } - - ntfs_dump_attribute_header(ctx, inode->vol); - - switch (ctx->attr->type) { - case AT_STANDARD_INFORMATION: - ntfs_dump_attr_standard_information(ctx->attr); - break; - case AT_ATTRIBUTE_LIST: - ntfs_dump_attr_list(ctx->attr, inode->vol); - break; - case AT_FILE_NAME: - ntfs_dump_attr_file_name(ctx->attr); - break; - case AT_OBJECT_ID: - ntfs_dump_attr_object_id(ctx->attr, inode->vol); - break; - case AT_SECURITY_DESCRIPTOR: - ntfs_dump_attr_security_descriptor(ctx->attr, - inode->vol); - break; - case AT_VOLUME_NAME: - ntfs_dump_attr_volume_name(ctx->attr); - break; - case AT_VOLUME_INFORMATION: - ntfs_dump_attr_volume_information(ctx->attr); - break; - case AT_DATA: - ntfs_dump_attr_data(ctx->attr, inode); - break; - case AT_INDEX_ROOT: - ntfs_dump_attr_index_root(ctx->attr, inode); - break; - case AT_INDEX_ALLOCATION: - ntfs_dump_attr_index_allocation(ctx->attr, inode); - break; - case AT_BITMAP: - ntfs_dump_attr_bitmap(ctx->attr); - break; - case AT_REPARSE_POINT: - ntfs_dump_attr_reparse_point(ctx->attr); - break; - case AT_EA_INFORMATION: - ntfs_dump_attr_ea_information(ctx->attr); - break; - case AT_EA: - ntfs_dump_attr_ea(ctx->attr, inode->vol); - break; - case AT_PROPERTY_SET: - ntfs_dump_attr_property_set(ctx->attr); - break; - case AT_LOGGED_UTILITY_STREAM: - ntfs_dump_attr_logged_utility_stream(ctx->attr, inode); - break; - default: - ntfs_dump_attr_unknown(ctx->attr); - } - } - - /* if we exited the loop before we're done - notify the user */ - if (errno != ENOENT) { - ntfs_log_perror("ntfsinfo error: stopped before finished " - "enumerating attributes"); - } else { - printf("End of inode reached\n"); - } - - /* close all data-structures we used */ - ntfs_attr_put_search_ctx(ctx); - ntfs_inode_close(inode); -} - -/** - * main() - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char **argv) -{ - ntfs_volume *vol; - - setlinebuf(stdout); - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - if (!parse_options(argc, argv)) { - printf("Failed to parse command line options\n"); - exit(1); - } - - utils_set_locale(); - - vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) { - printf("Failed to open '%s'.\n", opts.device); - exit(1); - } - - /* - * if opts.mft is not 0, then we will print out information about - * the volume, such as the sector size and whatnot. - */ - if (opts.mft) - ntfs_dump_volume(vol); - - if ((opts.inode != -1) || opts.filename) { - ntfs_inode *inode; - /* obtain the inode */ - if (opts.filename) { - inode = ntfs_pathname_to_inode(vol, NULL, - opts.filename); - } else { - inode = ntfs_inode_open(vol, MK_MREF(opts.inode, 0)); - } - - /* dump the inode information */ - if (inode) { - /* general info about the inode's mft record */ - ntfs_dump_inode_general_info(inode); - /* dump attributes */ - ntfs_dump_file_attributes(inode); - } else { - /* can't open inode */ - /* - * note: when the specified inode does not exist, either - * EIO or or ESPIPE is returned, we should notify better - * in those cases - */ - ntfs_log_perror("Error loading node"); - } - } - - ntfs_umount(vol, FALSE); - return 0; -} - diff --git a/usr/src/cmd/ntfsprogs/ntfslabel.c b/usr/src/cmd/ntfsprogs/ntfslabel.c deleted file mode 100644 index 6c753015a9..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfslabel.c +++ /dev/null @@ -1,412 +0,0 @@ -/** - * ntfslabel - Part of the Linux-NTFS project. - * - * Copyright (c) 2002 Matthew J. Fanto - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2002-2003 Richard Russon - * - * This utility will display/change the label on an NTFS partition. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_LOCALE_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif - -#include "compat.h" -#include "debug.h" -#include "mft.h" -#include "utils.h" -#include "version.h" -#include "logging.h" - -static const char *EXEC_NAME = "ntfslabel"; - -static struct options { - char *device; /* Device/File to work with */ - char *label; /* Set the label to this */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int force; /* Override common sense */ - int noaction; /* Do not write to disk */ -} opts; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s) - Display, or set, the label for an " - "NTFS Volume.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - ntfs_log_info("Copyright (c)\n"); - ntfs_log_info(" 2002 Matthew J. Fanto\n"); - ntfs_log_info(" 2002-2005 Anton Altaparmakov\n"); - ntfs_log_info(" 2002-2003 Richard Russon\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device [label]\n" - " -n, --no-action Do not write to disk\n" - " -f, --force Use less caution\n" - " -q, --quiet Less output\n" - " -v, --verbose More output\n" - " -V, --version Display version information\n" - " -h, --help Display this help\n\n", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char *argv[]) -{ - static const char *sopt = "-fh?nqvV"; - static const struct option lopt[] = { - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "no-action", no_argument, NULL, 'n' }, - { "quiet", no_argument, NULL, 'q' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 }, - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - - opterr = 0; /* We'll handle the errors, thank you. */ - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!err && !opts.device) - opts.device = argv[optind-1]; - else if (!err && !opts.label) - opts.label = argv[optind-1]; - else - err++; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp (argv[optind-1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option (argv[optind-1])) - err++; - break; - } - help++; - break; - case 'n': - opts.noaction++; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - default: - ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (opts.device == NULL) { - if (argc > 1) - ntfs_log_error("You must specify a device.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at " - "the same time.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - - -/** - * print_label - display the current label of a mounted ntfs partition. - * @dev: device to read the label from - * @mnt_flags: mount flags of the device or 0 if not mounted - * @mnt_point: mount point of the device or NULL - * - * Print the label of the device @dev. - */ -static int print_label(ntfs_volume *vol, unsigned long mnt_flags) -{ - int result = 0; - //XXX significant? - if ((mnt_flags & (NTFS_MF_MOUNTED | NTFS_MF_READONLY)) == - NTFS_MF_MOUNTED) { - ntfs_log_error("%s is mounted read-write, results may be " - "unreliable.\n", opts.device); - result = 1; - } - - ntfs_log_info("%s\n", vol->vol_name); - return result; -} - -/** - * resize_resident_attribute_value - resize a resident attribute - * @m: mft record containing attribute to resize - * @a: attribute record (inside @m) which to resize - * @new_vsize: the new attribute value size to resize the attribute to - * - * Return 0 on success and -1 with errno = ENOSPC if not enough space in the - * mft record. - */ -static int resize_resident_attribute_value(MFT_RECORD *m, ATTR_RECORD *a, - const u32 new_vsize) -{ - int new_alen, new_muse; - - /* New attribute length and mft record bytes used. */ - new_alen = (le16_to_cpu(a->u.res.value_offset) + new_vsize + 7) & ~7; - new_muse = le32_to_cpu(m->bytes_in_use) - le32_to_cpu(a->length) + - new_alen; - /* Check for sufficient space. */ - if ((u32)new_muse > le32_to_cpu(m->bytes_allocated)) { - errno = ENOSPC; - return -1; - } - /* Move attributes behind @a to their new location. */ - memmove((char*)a + new_alen, (char*)a + le32_to_cpu(a->length), - le32_to_cpu(m->bytes_in_use) - ((char*)a - (char*)m) - - le32_to_cpu(a->length)); - /* Adjust @m to reflect change in used space. */ - m->bytes_in_use = cpu_to_le32(new_muse); - /* Adjust @a to reflect new value size. */ - a->length = cpu_to_le32(new_alen); - a->u.res.value_length = cpu_to_le32(new_vsize); - return 0; -} - -/** - * change_label - change the current label on a device - * @dev: device to change the label on - * @mnt_flags: mount flags of the device or 0 if not mounted - * @mnt_point: mount point of the device or NULL - * @label: the new label - * - * Change the label on the device @dev to @label. - */ -static int change_label(ntfs_volume *vol, unsigned long mnt_flags, char *label, BOOL force) -{ - ntfs_attr_search_ctx *ctx; - ntfschar *new_label = NULL; - ATTR_RECORD *a; - int label_len; - int result = 0; - - //XXX significant? - if (mnt_flags & NTFS_MF_MOUNTED) { - /* If not the root fs or mounted read/write, refuse change. */ - if (!(mnt_flags & NTFS_MF_ISROOT) || - !(mnt_flags & NTFS_MF_READONLY)) { - if (!force) { - ntfs_log_error("Refusing to change label on " - "read-%s mounted device %s.\n", - mnt_flags & NTFS_MF_READONLY ? - "only" : "write", opts.device); - return 1; - } - } - } - ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); - if (!ctx) { - ntfs_log_perror("Failed to get attribute search context"); - goto err_out; - } - if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, - ctx)) { - if (errno != ENOENT) { - ntfs_log_perror("Lookup of $VOLUME_NAME attribute failed"); - goto err_out; - } - /* The volume name attribute does not exist. Need to add it. */ - a = NULL; - } else { - a = ctx->attr; - if (a->non_resident) { - ntfs_log_error("Error: Attribute $VOLUME_NAME must be " - "resident.\n"); - goto err_out; - } - } - label_len = ntfs_mbstoucs(label, &new_label, 0); - if (label_len == -1) { - ntfs_log_perror("Unable to convert label string to Unicode"); - goto err_out; - } - label_len *= sizeof(ntfschar); - if (label_len > 0x100) { - ntfs_log_error("New label is too long. Maximum %u characters " - "allowed. Truncating excess characters.\n", - (unsigned)(0x100 / sizeof(ntfschar))); - label_len = 0x100; - new_label[label_len / sizeof(ntfschar)] = 0; - } - if (a) { - if (resize_resident_attribute_value(ctx->mrec, a, label_len)) { - ntfs_log_perror("Error resizing resident attribute"); - goto err_out; - } - } else { - /* sizeof(resident attribute record header) == 24 */ - int asize = (24 + label_len + 7) & ~7; - u32 biu = le32_to_cpu(ctx->mrec->bytes_in_use); - if (biu + asize > le32_to_cpu(ctx->mrec->bytes_allocated)) { - errno = ENOSPC; - ntfs_log_perror("Error adding resident attribute"); - goto err_out; - } - a = ctx->attr; - memmove((u8*)a + asize, a, biu - ((u8*)a - (u8*)ctx->mrec)); - ctx->mrec->bytes_in_use = cpu_to_le32(biu + asize); - a->type = AT_VOLUME_NAME; - a->length = cpu_to_le32(asize); - a->non_resident = 0; - a->name_length = 0; - a->name_offset = cpu_to_le16(24); - a->flags = cpu_to_le16(0); - a->instance = ctx->mrec->next_attr_instance; - ctx->mrec->next_attr_instance = cpu_to_le16((le16_to_cpu( - ctx->mrec->next_attr_instance) + 1) & 0xffff); - a->u.res.value_length = cpu_to_le32(label_len); - a->u.res.value_offset = a->name_offset; - a->u.res.resident_flags = 0; - a->u.res.reservedR = 0; - } - memcpy((u8*)a + le16_to_cpu(a->u.res.value_offset), new_label, label_len); - if (!opts.noaction && ntfs_inode_sync(vol->vol_ni)) { - ntfs_log_perror("Error writing MFT Record to disk"); - goto err_out; - } - result = 0; -err_out: - free(new_label); - return result; -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char **argv) -{ - unsigned long mnt_flags = 0; - int result = 0; - ntfs_volume *vol; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - if (!parse_options(argc, argv)) - return 1; - - utils_set_locale(); - - if (!opts.label) - opts.noaction++; - - vol = utils_mount_volume(opts.device, - (opts.noaction ? NTFS_MNT_RDONLY : 0) | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) - return 1; - - if (opts.label) - result = change_label(vol, mnt_flags, opts.label, opts.force); - else - result = print_label(vol, mnt_flags); - - ntfs_umount(vol, FALSE); - return result; -} - diff --git a/usr/src/cmd/ntfsprogs/ntfsls.c b/usr/src/cmd/ntfsprogs/ntfsls.c deleted file mode 100644 index 9264878ff8..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsls.c +++ /dev/null @@ -1,719 +0,0 @@ -/** - * ntfsls - Part of the Linux-NTFS project. - * - * Copyright (c) 2003 Lode Leroy - * Copyright (c) 2003-2005 Anton Altaparmakov - * Copyright (c) 2003 Richard Russon - * Copyright (c) 2004 Carmelo Kintana - * Copyright (c) 2004 Giang Nguyen - * - * This utility will list a directory's files. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "mft.h" -#include "attrib.h" -#include "layout.h" -#include "inode.h" -#include "utils.h" -#include "dir.h" -#include "list.h" -#include "ntfstime.h" -#include "version.h" -#include "logging.h" - -static const char *EXEC_NAME = "ntfsls"; - -/** - * To hold sub-directory information for recursive listing. - * @depth: the level of this dir relative to opts.path - */ -struct dir { - struct list_head list; - ntfs_inode *ni; - char name[MAX_PATH]; - int depth; -}; - -/** - * path_component - to store path component strings - * - * @name: string pointer - * - * NOTE: @name is not directly allocated memory. It simply points to the - * character array name in struct dir. - */ -struct path_component { - struct list_head list; - const char *name; -}; - -/* The list of sub-dirs is like a "horizontal" tree. The root of - * the tree is opts.path, but it is not part of the list because - * that's not necessary. The rules of the list are (in order of - * precedence): - * 1. directories immediately follow their parent. - * 2. siblings are next to one another. - * - * For example, if: - * 1. opts.path is / - * 2. / has 2 sub-dirs: dir1 and dir2 - * 3. dir1 has 2 sub-dirs: dir11 and dir12 - * 4. dir2 has 0 sub-dirs - * then the list will be: - * dummy head -> dir1 -> dir11 -> dir12 -> dir2 - * - * dir_list_insert_pos keeps track of where to insert a sub-dir - * into the list. - */ -static struct list_head *dir_list_insert_pos = NULL; - -/* The global depth relative to opts.path. - * ie: opts.path has depth 0, a sub-dir of opts.path has depth 1 - */ -static int depth = 0; - -static struct options { - char *device; /* Device/File to work with */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int force; /* Override common sense */ - int all; - int system; - int dos; - int lng; - int inode; - int classify; - int recursive; - const char *path; -} opts; - -typedef struct { - ntfs_volume *vol; -} ntfsls_dirent; - -static int list_dir_entry(ntfsls_dirent * dirent, const ntfschar * name, - const int name_len, const int name_type, - const s64 pos, const MFT_REF mref, - const unsigned dt_type); - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - printf("\n%s v%s (libntfs %s) - Display information about an NTFS " - "Volume.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - printf("Copyright (c) 2003 Lode Leroy\n"); - printf("Copyright (c) 2003-2005 Anton Altaparmakov\n"); - printf("Copyright (c) 2003 Richard Russon\n"); - printf("Copyright (c) 2004 Carmelo Kintana\n"); - printf("Copyright (c) 2004 Giang Nguyen\n"); - printf("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - printf("\nUsage: %s [options] device\n" - "\n" - " -a, --all Display all files\n" - " -F, --classify Display classification\n" - " -f, --force Use less caution\n" - " -h, --help Display this help\n" - " -i, --inode Display inode numbers\n" - " -l, --long Display long info\n" - " -p, --path PATH Directory whose contents to list\n" - " -q, --quiet Less output\n" - " -R, --recursive Recursively list subdirectories\n" - " -s, --system Display system files\n" - " -V, --version Display version information\n" - " -v, --verbose More output\n" - " -x, --dos Use short (DOS 8.3) names\n" - "\n", - EXEC_NAME); - - printf("NOTE: If neither -a nor -s is specified, the program defaults to -a.\n\n"); - - printf("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char *argv[]) -{ - static const char *sopt = "-aFfh?ilp:qRsVvx"; - static const struct option lopt[] = { - { "all", no_argument, NULL, 'a' }, - { "classify", no_argument, NULL, 'F' }, - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "inode", no_argument, NULL, 'i' }, - { "long", no_argument, NULL, 'l' }, - { "path", required_argument, NULL, 'p' }, - { "recursive", no_argument, NULL, 'R' }, - { "quiet", no_argument, NULL, 'q' }, - { "system", no_argument, NULL, 's' }, - { "version", no_argument, NULL, 'V' }, - { "verbose", no_argument, NULL, 'v' }, - { "dos", no_argument, NULL, 'x' }, - { NULL, 0, NULL, 0 }, - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - - opterr = 0; /* We'll handle the errors, thank you. */ - - memset(&opts, 0, sizeof(opts)); - opts.device = NULL; - opts.path = "/"; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: - if (!opts.device) - opts.device = optarg; - else - err++; - break; - case 'p': - opts.path = optarg; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp (argv[optind-1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option (argv[optind-1])) - err++; - break; - } - help++; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - case 'x': - opts.dos = 1; - break; - case 'l': - opts.lng++; - break; - case 'i': - opts.inode++; - break; - case 'F': - opts.classify++; - break; - case 'a': - opts.all++; - break; - case 's': - opts.system++; - break; - case 'R': - opts.recursive++; - break; - default: - ntfs_log_error("Unknown option '%s'.\n", argv[optind - 1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - /* defaults to -a if -s is not specified */ - if (!opts.system) - opts.all++; - - if (help || ver) - opts.quiet = 0; - else { - if (opts.device == NULL) { - if (argc > 1) - ntfs_log_error("You must specify exactly one " - "device.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at the " - "same time.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - -/** - * free_dir - free one dir - * @tofree: the dir to free - * - * Close the inode and then free the dir - */ -static void free_dir(struct dir *tofree) -{ - if (tofree) { - if (tofree->ni) { - ntfs_inode_close(tofree->ni); - tofree->ni = NULL; - } - free(tofree); - } -} - -/** - * free_dirs - walk the list of dir's and free each of them - * @dir_list: the list_head of any entry in the list - * - * Iterate over @dir_list, calling free_dir on each entry - */ -static void free_dirs(struct list_head *dir_list) -{ - struct dir *tofree = NULL; - struct list_head *walker = NULL; - - if (dir_list) { - list_for_each(walker, dir_list) { - free_dir(tofree); - tofree = list_entry(walker, struct dir, list); - } - - free_dir(tofree); - } -} - -/** - * readdir_recursive - list a directory and sub-directories encountered - * @ni: ntfs inode of the directory to list - * @pos: current position in directory - * @dirent: context for filldir callback supplied by the caller - * - * For each directory, print its path relative to opts.path. List a directory, - * then list each of its sub-directories. - * - * Returns 0 on success or -1 on error. - * - * NOTE: Assumes recursive option. Currently no limit on the depths of - * recursion. - */ -static int readdir_recursive(ntfs_inode * ni, s64 * pos, ntfsls_dirent * dirent) -{ - /* list of dirs to "ls" recursively */ - static struct dir dirs = { - .list = LIST_HEAD_INIT(dirs.list), - .ni = NULL, - .name = {0}, - .depth = 0 - }; - - static struct path_component paths = { - .list = LIST_HEAD_INIT(paths.list), - .name = NULL - }; - - static struct path_component base_comp; - - struct dir *subdir = NULL; - struct dir *tofree = NULL; - struct path_component comp; - struct path_component *tempcomp = NULL; - struct list_head *dir_walker = NULL; - struct list_head *comp_walker = NULL; - s64 pos2 = 0; - int ni_depth = depth; - int result = 0; - - if (list_empty(&dirs.list)) { - base_comp.name = opts.path; - list_add(&base_comp.list, &paths.list); - dir_list_insert_pos = &dirs.list; - printf("%s:\n", opts.path); - } - - depth++; - - result = ntfs_readdir(ni, pos, dirent, (ntfs_filldir_t) list_dir_entry); - - if (result == 0) { - list_add_tail(&comp.list, &paths.list); - - /* for each of ni's sub-dirs: list in this iteration, then - free at the top of the next iteration or outside of loop */ - list_for_each(dir_walker, &dirs.list) { - if (tofree) { - free_dir(tofree); - tofree = NULL; - } - subdir = list_entry(dir_walker, struct dir, list); - - /* subdir is not a subdir of ni */ - if (subdir->depth != ni_depth + 1) - break; - - pos2 = 0; - dir_list_insert_pos = &dirs.list; - if (!subdir->ni) { - subdir->ni = - ntfs_pathname_to_inode(ni->vol, ni, - subdir->name); - - if (!subdir->ni) { - ntfs_log_error - ("ntfsls::readdir_recursive(): cannot get inode from pathname.\n"); - result = -1; - break; - } - } - puts(""); - - comp.name = subdir->name; - - /* print relative path header */ - list_for_each(comp_walker, &paths.list) { - tempcomp = - list_entry(comp_walker, - struct path_component, list); - printf("%s", tempcomp->name); - if (tempcomp != &comp - && *tempcomp->name != PATH_SEP - && (!opts.classify - || tempcomp == &base_comp)) - putchar(PATH_SEP); - } - puts(":"); - - result = readdir_recursive(subdir->ni, &pos2, dirent); - - if (result) - break; - - tofree = subdir; - list_del(dir_walker); - } - - list_del(&comp.list); - } - - if (tofree) - free_dir(tofree); - - /* if at the outer-most readdir_recursive, then clean up */ - if (ni_depth == 0) { - free_dirs(&dirs.list); - } - - depth--; - - return result; -} - -/** - * list_dir_entry - * - * FIXME: Should we print errors as we go along? (AIA) - */ -static int list_dir_entry(ntfsls_dirent * dirent, const ntfschar * name, - const int name_len, const int name_type, - const s64 pos __attribute__((unused)), - const MFT_REF mref, const unsigned dt_type) -{ - char *filename = NULL; - int result = 0; - - struct dir *dir = NULL; - - filename = calloc(1, MAX_PATH); - if (!filename) - return -1; - - if (ntfs_ucstombs(name, name_len, &filename, MAX_PATH) < 0) { - ntfs_log_error("Cannot represent filename in current locale.\n"); - goto free; - } - - result = 0; // These are successful - if ((MREF(mref) < FILE_first_user) && (!opts.system)) - goto free; - if (name_type == FILE_NAME_POSIX && !opts.all) - goto free; - if (((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_WIN32) && - opts.dos) - goto free; - if (((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_DOS) && - !opts.dos) - goto free; - if (dt_type == NTFS_DT_DIR && opts.classify) - sprintf(filename + strlen(filename), "/"); - - if (dt_type == NTFS_DT_DIR && opts.recursive - && strcmp(filename, ".") && strcmp(filename, "./") - && strcmp(filename, "..") && strcmp(filename, "../")) - { - dir = (struct dir *)calloc(1, sizeof(struct dir)); - - if (!dir) { - ntfs_log_error("Failed to allocate for subdir.\n"); - result = -1; - goto free; - } - - strcpy(dir->name, filename); - dir->ni = NULL; - dir->depth = depth; - } - - if (!opts.lng) { - if (!opts.inode) - printf("%s\n", filename); - else - printf("%7llu %s\n", (unsigned long long)MREF(mref), - filename); - result = 0; - } else { - s64 filesize = 0; - ntfs_inode *ni; - ntfs_attr_search_ctx *ctx = NULL; - FILE_NAME_ATTR *file_name_attr; - ATTR_RECORD *attr; - time_t ntfs_time; - char t_buf[26]; - - result = -1; // Everything else is bad - - ni = ntfs_inode_open(dirent->vol, mref); - if (!ni) - goto release; - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - goto release; - - if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, - 0, ctx)) - goto release; - attr = ctx->attr; - - file_name_attr = (FILE_NAME_ATTR *)((char *)attr + - le16_to_cpu(attr->u.res.value_offset)); - if (!file_name_attr) - goto release; - - ntfs_time = ntfs2utc(file_name_attr->last_data_change_time); - strcpy(t_buf, ctime(&ntfs_time)); - memmove(t_buf+16, t_buf+19, 5); - t_buf[21] = '\0'; - - if (dt_type != NTFS_DT_DIR) { - if (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, - NULL, 0, ctx)) - filesize = ntfs_get_attribute_value_length( - ctx->attr); - } - - if (opts.inode) - printf("%7llu %8lld %s %s\n", - (unsigned long long)MREF(mref), - (long long)filesize, t_buf + 4, - filename); - else - printf("%8lld %s %s\n", (long long)filesize, t_buf + 4, - filename); - - if (dir) { - dir->ni = ni; - ni = NULL; /* so release does not close inode */ - } - - result = 0; -release: - /* Release attribute search context and close the inode. */ - if (ctx) - ntfs_attr_put_search_ctx(ctx); - if (ni) - ntfs_inode_close(ni); - } - - if (dir) { - if (result == 0) { - list_add(&dir->list, dir_list_insert_pos); - dir_list_insert_pos = &dir->list; - } else { - free(dir); - dir = NULL; - } - } - -free: - free(filename); - return result; -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, parsing mount options failed - * 2 Error, mount attempt failed - * 3 Error, failed to open root directory - * 4 Error, failed to open directory in search path - */ -int main(int argc, char **argv) -{ - s64 pos; - ntfs_volume *vol; - ntfs_inode *ni; - ntfsls_dirent dirent; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - if (!parse_options(argc, argv)) { - // FIXME: Print error... (AIA) - return 1; - } - - utils_set_locale(); - - vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) { - // FIXME: Print error... (AIA) - return 2; - } - - ni = ntfs_pathname_to_inode(vol, NULL, opts.path); - if (!ni) { - // FIXME: Print error... (AIA) - ntfs_umount(vol, FALSE); - return 3; - } - - /* - * We now are at the final path component. If it is a file just - * list it. If it is a directory, list its contents. - */ - pos = 0; - memset(&dirent, 0, sizeof(dirent)); - dirent.vol = vol; - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - if (opts.recursive) - readdir_recursive(ni, &pos, &dirent); - else - ntfs_readdir(ni, &pos, &dirent, - (ntfs_filldir_t) list_dir_entry); - // FIXME: error checking... (AIA) - } else { - ATTR_RECORD *rec; - FILE_NAME_ATTR *attr; - ntfs_attr_search_ctx *ctx; - int space = 4; - ntfschar *name = NULL; - int name_len = 0;; - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return -1; - - while ((rec = find_attribute(AT_FILE_NAME, ctx))) { - /* We know this will always be resident. */ - attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->u.res.value_offset)); - - if (attr->file_name_type < space) { - name = attr->file_name; - name_len = attr->file_name_length; - space = attr->file_name_type; - } - } - - list_dir_entry(&dirent, name, name_len, space, pos, ni->mft_no, - NTFS_DT_REG); - // FIXME: error checking... (AIA) - - ntfs_attr_put_search_ctx(ctx); - } - - /* Finished with the inode; release it. */ - ntfs_inode_close(ni); - - ntfs_umount(vol, FALSE); - return 0; -} - diff --git a/usr/src/cmd/ntfsprogs/ntfsresize.c b/usr/src/cmd/ntfsprogs/ntfsresize.c deleted file mode 100644 index fe96836b33..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsresize.c +++ /dev/null @@ -1,2501 +0,0 @@ -/** - * ntfsresize - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2002-2003 Richard Russon - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility will resize an NTFS volume without data loss. - * - * WARNING FOR DEVELOPERS!!! Several external tools grep for text messages - * to control execution thus if you would like to change any message - * then PLEASE think twice before doing so then don't modify it. Thanks! - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif - -#include "compat.h" -#include "debug.h" -#include "types.h" -#include "support.h" -#include "endians.h" -#include "bootsect.h" -#include "device.h" -#include "attrib.h" -#include "volume.h" -#include "mft.h" -#include "bitmap.h" -#include "inode.h" -#include "runlist.h" -#include "utils.h" -#include "version.h" - -static const char *EXEC_NAME = "ntfsresize"; - -static const char *resize_warning_msg = -"WARNING: Every sanity check passed and only the dangerous operations left.\n" -"Make sure that important data has been backed up! Power outage or computer\n" -"crash may result major data loss!\n"; - -static const char *resize_important_msg = -#ifdef __sun -"When booted, Windows will check the file system and may reboot.\n" -"If you are running this from inside parted, STOP reading now.\n" -"Otherwise, you can go on to shrink the device with fdisk or parted.\n" -#else -"You can go on to shrink the device for example with Linux fdisk.\n" -#endif -"IMPORTANT: When recreating the partition, make sure that you\n" -" 1) create it at the same disk sector (use sector as the unit!)\n" -" 2) create it with the same partition type (usually 7, HPFS/NTFS)\n" -" 3) do not make it smaller than the new NTFS filesystem size\n" -" 4) set the bootable flag for the partition if it existed before\n" -"Otherwise you won't be able to access NTFS or can't boot from the disk!\n" -"If you make a mistake and don't have a partition table backup then you\n" -"can recover the partition table by TestDisk or Parted's rescue mode.\n"; - -static const char *invalid_ntfs_msg = -"The device '%s' doesn't have a valid NTFS.\n" -"Maybe you selected the wrong partition? Or the whole disk instead of a\n" -"partition (e.g. /dev/hda, not /dev/hda1)? This error might also occur\n" -"if the disk was incorrectly repartitioned (see the ntfsresize FAQ).\n"; - -static const char *corrupt_volume_msg = -"NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n" -"The usage of the /f parameter is very IMPORTANT! No modification was\n" -"and will be made to NTFS by this software until it gets repaired.\n"; - -static const char *hibernated_volume_msg = -"The NTFS partition is hibernated. Windows must be resumed and turned off\n" -"properly, so resizing could be done safely.\n"; - -static const char *unclean_journal_msg = -"The NTFS journal file is unclean. Please shutdown Windows properly before\n" -"using this software! Note, if you have run chkdsk previously then boot\n" -"Windows again which will automatically initialize the journal correctly.\n"; - -static const char *opened_volume_msg = -"This software has detected that the NTFS volume is already opened by another\n" -"software thus it refuses to progress to preserve data consistency.\n"; - -static const char *bad_sectors_warning_msg = -"****************************************************************************\n" -"* WARNING: The disk has bad sector. This means physical damage on the disk *\n" -"* surface caused by deterioration, manufacturing faults or other reason. *\n" -"* The reliability of the disk may stay stable or degrade fast. We suggest *\n" -"* making a full backup urgently by running 'ntfsclone --rescue ...' then *\n" -"* run 'chkdsk /f /r' on Windows and rebooot it TWICE! Then you can resize *\n" -"* NTFS safely by additionally using the --bad-sectors option of ntfsresize.*\n" -"****************************************************************************\n"; - -static const char *many_bad_sectors_msg = -"***************************************************************************\n" -"* WARNING: The disk has many bad sectors. This means physical damage *\n" -"* on the disk surface caused by deterioration, manufacturing faults or *\n" -"* other reason. We suggest to get a replacement disk as soon as possible. *\n" -"***************************************************************************\n"; - -static struct { - int verbose; - int debug; - int ro_flag; - int force; - int info; - int show_progress; - int badsectors; - s64 bytes; - char *volume; -} opt; - -struct bitmap { - s64 size; - u8 *bm; -}; - -#define NTFS_PROGBAR 0x0001 -#define NTFS_PROGBAR_SUPPRESS 0x0002 - -struct progress_bar { - u64 start; - u64 stop; - int resolution; - int flags; - float unit; -}; - -struct llcn_t { - s64 lcn; /* last used LCN for a "special" file/attr type */ - s64 inode; /* inode using it */ -}; - -#define NTFSCK_PROGBAR 0x0001 - -typedef struct { - ntfs_inode *ni; /* inode being processed */ - ntfs_attr_search_ctx *ctx; /* inode attribute being processed */ - s64 inuse; /* num of clusters in use */ - int multi_ref; /* num of clusters referenced many times */ - int outsider; /* num of clusters outside the volume */ - int show_outsider; /* controls showing the above information */ - int flags; - struct bitmap lcn_bitmap; -} ntfsck_t; - -typedef struct { - ntfs_volume *vol; - ntfs_inode *ni; /* inode being processed */ - s64 new_volume_size; /* in clusters; 0 = --info w/o --size */ - MFT_REF mref; /* mft reference */ - MFT_RECORD *mrec; /* mft record */ - ntfs_attr_search_ctx *ctx; /* inode attribute being processed */ - u64 relocations; /* num of clusters to relocate */ - s64 inuse; /* num of clusters in use */ - runlist mftmir_rl; /* $MFTMirr AT_DATA's new position */ - s64 mftmir_old; /* $MFTMirr AT_DATA's old LCN */ - int dirty_inode; /* some inode data got relocated */ - int shrink; /* shrink = 1, enlarge = 0 */ - s64 badclusters; /* num of physically dead clusters */ - VCN mft_highest_vcn; /* used for relocating the $MFT */ - struct progress_bar progress; - struct bitmap lcn_bitmap; - /* Temporary statistics until all case is supported */ - struct llcn_t last_mft; - struct llcn_t last_mftmir; - struct llcn_t last_multi_mft; - struct llcn_t last_sparse; - struct llcn_t last_compressed; - struct llcn_t last_lcn; - s64 last_unsupp; /* last unsupported cluster */ -} ntfs_resize_t; - -/* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster - allocation related structure, attached to ntfs_resize_t */ -static s64 max_free_cluster_range = 0; - -#define NTFS_MBYTE (1000 * 1000) - -/* WARNING: don't modify the text, external tools grep for it */ -#define ERR_PREFIX "ERROR" -#define PERR_PREFIX ERR_PREFIX "(%d): " -#define NERR_PREFIX ERR_PREFIX ": " - -#define DIRTY_NONE (0) -#define DIRTY_INODE (1) -#define DIRTY_ATTRIB (2) - -#define NTFS_MAX_CLUSTER_SIZE (65536) - -static s64 rounded_up_division(s64 numer, s64 denom) -{ - return (numer + (denom - 1)) / denom; -} - -/** - * perr_printf - * - * Print an error message. - */ -__attribute__((format(printf, 1, 2))) -static void perr_printf(const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - fprintf(stdout, PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fprintf(stdout, ": %s\n", strerror(eo)); - fflush(stdout); - fflush(stderr); -} - -__attribute__((format(printf, 1, 2))) -static void err_printf(const char *fmt, ...) -{ - va_list ap; - - fprintf(stdout, NERR_PREFIX); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fflush(stdout); - fflush(stderr); -} - -/** - * err_exit - * - * Print and error message and exit the program. - */ -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int err_exit(const char *fmt, ...) -{ - va_list ap; - - fprintf(stdout, NERR_PREFIX); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - fflush(stdout); - fflush(stderr); - exit(1); -} - -/** - * perr_exit - * - * Print and error message and exit the program - */ -__attribute__((noreturn)) -__attribute__((format(printf, 1, 2))) -static int perr_exit(const char *fmt, ...) -{ - va_list ap; - int eo = errno; - - fprintf(stdout, PERR_PREFIX, eo); - va_start(ap, fmt); - vfprintf(stdout, fmt, ap); - va_end(ap); - printf(": %s\n", strerror(eo)); - fflush(stdout); - fflush(stderr); - exit(1); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -__attribute__((noreturn)) -static void usage(void) -{ - - printf("\nUsage: %s [OPTIONS] DEVICE\n" - " Resize an NTFS volume non-destructively, safely move any data if needed.\n" - "\n" - " -i, --info Estimate the smallest shrunken size possible\n" - " -s, --size SIZE Resize volume to SIZE[k|M|G] bytes\n" - "\n" - " -n, --no-action Do not write to disk\n" - " -b, --bad-sectors Support disks having bad sectors\n" - " -f, --force Force to progress\n" - " -P, --no-progress-bar Don't show progress bar\n" - " -v, --verbose More output\n" - " -V, --version Display version information\n" - " -h, --help Display this help\n" -#ifdef DEBUG - " -d, --debug Show debug information\n" -#endif - "\n" - " The options -i and -s are mutually exclusive. If both options are\n" - " omitted then the NTFS volume will be enlarged to the DEVICE size.\n" - "\n", EXEC_NAME); - printf("%s%s", ntfs_bugs, ntfs_home); - printf("Ntfsresize FAQ: http://linux-ntfs.sourceforge.net/info/ntfsresize.html\n"); - exit(1); -} - -/** - * proceed_question - * - * Force the user to confirm an action before performing it. - * Copy-paste from e2fsprogs - */ -static void proceed_question(void) -{ - char buf[256]; - const char *short_yes = "yY"; - - fflush(stdout); - fflush(stderr); - printf("Are you sure you want to proceed (y/[n])? "); - buf[0] = 0; - fgets(buf, sizeof(buf), stdin); - if (!strchr(short_yes, buf[0])) { - printf("OK quitting. NO CHANGES have been made to your " - "NTFS volume.\n"); - exit(1); - } -} - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - printf("\nResize an NTFS Volume, without data loss.\n\n"); - printf("Copyright (c) 2002-2006 Szabolcs Szakacsits\n"); - printf("Copyright (c) 2002-2005 Anton Altaparmakov\n"); - printf("Copyright (c) 2002-2003 Richard Russon\n"); - printf("Copyright (c) 2007 Yura Pakhuchiy\n"); - printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * get_new_volume_size - * - * Convert a user-supplied string into a size. Without any suffix the number - * will be assumed to be in bytes. If the number has a suffix of k, M or G it - * will be scaled up by 1000, 1000000, or 1000000000. - */ -static s64 get_new_volume_size(char *s) -{ - s64 size; - char *suffix; - int prefix_kind = 1000; - - size = strtoll(s, &suffix, 10); - if (size <= 0 || errno == ERANGE) - err_exit("Illegal new volume size\n"); - - if (!*suffix) - return size; - - if (strlen(suffix) == 2 && suffix[1] == 'i') - prefix_kind = 1024; - else if (strlen(suffix) > 1) - usage(); - - /* We follow the SI prefixes: - http://physics.nist.gov/cuu/Units/prefixes.html - http://physics.nist.gov/cuu/Units/binary.html - Disk partitioning tools use prefixes as, - k M G - fdisk 2.11x- 2^10 2^20 10^3*2^20 - fdisk 2.11y+ 10^3 10^6 10^9 - cfdisk 10^3 10^6 10^9 - sfdisk 2^10 2^20 - parted 2^10 2^20 (may change) - fdisk (DOS) 2^10 2^20 - */ - /* FIXME: check for overflow */ - switch (*suffix) { - case 'G': - size *= prefix_kind; - case 'M': - size *= prefix_kind; - case 'k': - size *= prefix_kind; - break; - default: - usage(); - } - - return size; -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char **argv) -{ - static const char *sopt = "-bdfhinPs:vV"; - static const struct option lopt[] = { - { "bad-sectors",no_argument, NULL, 'b' }, -#ifdef DEBUG - { "debug", no_argument, NULL, 'd' }, -#endif - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "info", no_argument, NULL, 'i' }, - { "no-action", no_argument, NULL, 'n' }, - { "no-progress-bar", no_argument, NULL, 'P' }, - { "size", required_argument, NULL, 's' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - int c; - int err = 0; - int ver = 0; - int help = 0; - - memset(&opt, 0, sizeof(opt)); - opt.show_progress = 1; - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!err && !opt.volume) - opt.volume = argv[optind-1]; - else - err++; - break; - case 'b': - opt.badsectors++; - break; - case 'd': - opt.debug++; - break; - case 'f': - opt.force++; - break; - case 'h': - case '?': - help++; - break; - case 'i': - opt.info++; - break; - case 'n': - opt.ro_flag = NTFS_MNT_RDONLY; - break; - case 'P': - opt.show_progress = 0; - break; - case 's': - if (!err && (opt.bytes == 0)) - opt.bytes = get_new_volume_size(optarg); - else - err++; - break; - case 'v': - opt.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - default: - if (optopt == 's') { - printf("Option '%s' requires an argument.\n", argv[optind-1]); - } else { - printf("Unknown option '%s'.\n", argv[optind-1]); - } - err++; - break; - } - } - - if (!help && !ver) { - if (opt.volume == NULL) { - if (argc > 1) - printf("You must specify exactly one device.\n"); - err++; - } - if (opt.info) { - opt.ro_flag = NTFS_MNT_RDONLY; - if (opt.bytes) { - printf(NERR_PREFIX "Options --info and --size " - "can't be used together.\n"); - usage(); - } - } - } - - /* Redirect stderr to stdout, note fflush()es are essential! */ - fflush(stdout); - fflush(stderr); - if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) - perr_exit("Failed to redirect stderr to stdout"); - fflush(stdout); - fflush(stderr); - -#ifdef DEBUG - if (!opt.debug) - if (!freopen("/dev/null", "w", stderr)) - perr_exit("Failed to redirect stderr to /dev/null"); -#endif - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - -static void print_advise(ntfs_volume *vol, s64 supp_lcn) -{ - s64 old_b, new_b, freed_b, old_mb, new_mb, freed_mb; - - old_b = vol->nr_clusters * vol->cluster_size; - old_mb = rounded_up_division(old_b, NTFS_MBYTE); - - /* Take the next supported cluster (free or relocatable) - plus reserve a cluster for the backup boot sector */ - supp_lcn += 2; - - if (supp_lcn > vol->nr_clusters) { - err_printf("Very rare fragmentation type detected. " - "Sorry, it's not supported yet.\n" - "Try to defragment your NTFS, perhaps it helps.\n"); - exit(1); - } - - new_b = supp_lcn * vol->cluster_size; - new_mb = rounded_up_division(new_b, NTFS_MBYTE); - freed_b = (vol->nr_clusters - supp_lcn + 1) * vol->cluster_size; - freed_mb = freed_b / NTFS_MBYTE; - - /* WARNING: don't modify the text, external tools grep for it */ - printf("You might resize at %lld bytes ", (long long)new_b); - if ((new_mb * NTFS_MBYTE) < old_b) - printf("or %lld MB ", (long long)new_mb); - - printf("(freeing "); - if (freed_mb && (old_mb - new_mb)) - printf("%lld MB", (long long)(old_mb - new_mb)); - else - printf("%lld bytes", (long long)freed_b); - printf(").\n"); - - printf("Please make a test run using both the -n and -s options " - "before real resizing!\n"); -} - -static void rl_set(runlist *rl, VCN vcn, LCN lcn, s64 len) -{ - rl->vcn = vcn; - rl->lcn = lcn; - rl->length = len; -} - -static int rl_items(runlist *rl) -{ - int i = 0; - - while (rl[i++].length) - ; - - return i; -} - -static void dump_run(runlist_element *r) -{ - ntfs_log_verbose(" %8lld %8lld (0x%08llx) %lld\n", (long long)r->vcn, - (long long)r->lcn, (long long)r->lcn, - (long long)r->length); -} - -static void dump_runlist(runlist *rl) -{ - while (rl->length) - dump_run(rl++); -} - -/** - * nr_clusters_to_bitmap_byte_size - * - * Take the number of clusters in the volume and calculate the size of $Bitmap. - * The size must be always a multiple of 8 bytes. - */ -static s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters) -{ - s64 bm_bsize; - - bm_bsize = rounded_up_division(nr_clusters, 8); - bm_bsize = (bm_bsize + 7) & ~7; - - return bm_bsize; -} - -static void collect_resize_constraints(ntfs_resize_t *resize, runlist *rl) -{ - s64 inode, last_lcn; - ATTR_FLAGS flags; - ATTR_TYPES atype; - struct llcn_t *llcn = NULL; - int ret, supported = 0; - - last_lcn = rl->lcn + (rl->length - 1); - - inode = resize->ni->mft_no; - flags = resize->ctx->attr->flags; - atype = resize->ctx->attr->type; - - if ((ret = ntfs_inode_badclus_bad(inode, resize->ctx->attr)) != 0) { - if (ret == -1) - perr_exit("Bad sector list check failed"); - return; - } - - if (inode == FILE_Bitmap) { - llcn = &resize->last_lcn; - if (atype == AT_DATA && NInoAttrList(resize->ni)) - err_exit("Highly fragmented $Bitmap isn't supported yet."); - - supported = 1; - - } else if (inode == FILE_MFT) { - llcn = &resize->last_mft; - /* - * First run of $MFT AT_DATA isn't supported yet. - */ - if (atype != AT_DATA || rl->vcn) - supported = 1; - - } else if (NInoAttrList(resize->ni)) { - llcn = &resize->last_multi_mft; - - if (inode != FILE_MFTMirr) - supported = 1; - - } else if (flags & ATTR_IS_SPARSE) { - llcn = &resize->last_sparse; - supported = 1; - - } else if (flags & ATTR_IS_COMPRESSED) { - llcn = &resize->last_compressed; - supported = 1; - - } else if (inode == FILE_MFTMirr) { - llcn = &resize->last_mftmir; - supported = 1; - - /* Fragmented $MFTMirr DATA attribute isn't supported yet */ - if (atype == AT_DATA) - if (rl[1].length != 0 || rl->vcn) - supported = 0; - } else { - llcn = &resize->last_lcn; - supported = 1; - } - - if (llcn->lcn < last_lcn) { - llcn->lcn = last_lcn; - llcn->inode = inode; - } - - if (supported) - return; - - if (resize->last_unsupp < last_lcn) - resize->last_unsupp = last_lcn; -} - - -static void collect_relocation_info(ntfs_resize_t *resize, runlist *rl) -{ - s64 lcn, lcn_length, start, len, inode; - s64 new_vol_size; /* (last LCN on the volume) + 1 */ - - lcn = rl->lcn; - lcn_length = rl->length; - inode = resize->ni->mft_no; - new_vol_size = resize->new_volume_size; - - if (lcn + lcn_length <= new_vol_size) - return; - - if (inode == FILE_Bitmap && resize->ctx->attr->type == AT_DATA) - return; - - start = lcn; - len = lcn_length; - - if (lcn < new_vol_size) { - start = new_vol_size; - len = lcn_length - (new_vol_size - lcn); - - if (!opt.info && (inode == FILE_MFTMirr)) { - err_printf("$MFTMirr can't be split up yet. Please try " - "a different size.\n"); - print_advise(resize->vol, lcn + lcn_length - 1); - exit(1); - } - } - - resize->relocations += len; - - if (!opt.info || !resize->new_volume_size) - return; - - printf("Relocation needed for inode %8lld attr 0x%x LCN 0x%08llx " - "length %6lld\n", (long long)inode, - (unsigned int)le32_to_cpu(resize->ctx->attr->type), - (unsigned long long)start, (long long)len); -} - -/** - * build_lcn_usage_bitmap - * - * lcn_bitmap has one bit for each cluster on the disk. Initially, lcn_bitmap - * has no bits set. As each attribute record is read the bits in lcn_bitmap are - * checked to ensure that no other file already references that cluster. - * - * This serves as a rudimentary "chkdsk" operation. - */ -static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck) -{ - s64 inode; - ATTR_RECORD *a; - runlist *rl; - int i, j; - struct bitmap *lcn_bitmap = &fsck->lcn_bitmap; - - a = fsck->ctx->attr; - inode = fsck->ni->mft_no; - - if (!a->non_resident) - return; - - if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) { - int err = errno; - perr_printf("ntfs_decompress_mapping_pairs"); - if (err == EIO) - printf("%s", corrupt_volume_msg); - exit(1); - } - - - for (i = 0; rl[i].length; i++) { - s64 lcn = rl[i].lcn; - s64 lcn_length = rl[i].length; - - /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */ - if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED) - continue; - - /* FIXME: ntfs_mapping_pairs_decompress should return error */ - if (lcn < 0 || lcn_length <= 0) - err_exit("Corrupt runlist in inode %lld attr %x LCN " - "%llx length %llx\n", inode, - (unsigned int)le32_to_cpu(a->type), lcn, - lcn_length); - - for (j = 0; j < lcn_length; j++) { - u64 k = (u64)lcn + j; - - if (k >= (u64)vol->nr_clusters) { - long long outsiders = lcn_length - j; - - fsck->outsider += outsiders; - - if (++fsck->show_outsider <= 10 || opt.verbose) - printf("Outside of the volume reference" - " for inode %lld at %lld:%lld\n", - inode, (long long)k, outsiders); - - break; - } - - if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) { - if (++fsck->multi_ref <= 10 || opt.verbose) - printf("Cluster %lld is referenced " - "multiple times!\n", - (long long)k); - continue; - } - } - fsck->inuse += lcn_length; - } - free(rl); -} - - -static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec) -{ - ntfs_attr_search_ctx *ret; - - if ((ret = ntfs_attr_get_search_ctx(ni, mrec)) == NULL) - perr_printf("ntfs_attr_get_search_ctx"); - - return ret; -} - -/** - * walk_attributes - * - * For a given MFT Record, iterate through all its attributes. Any non-resident - * data runs will be marked in lcn_bitmap. - */ -static int walk_attributes(ntfs_volume *vol, ntfsck_t *fsck) -{ - if (!(fsck->ctx = attr_get_search_ctx(fsck->ni, NULL))) - return -1; - - while (!ntfs_attrs_walk(fsck->ctx)) { - if (fsck->ctx->attr->type == AT_END) - break; - build_lcn_usage_bitmap(vol, fsck); - } - - ntfs_attr_put_search_ctx(fsck->ctx); - return 0; -} - -/** - * compare_bitmaps - * - * Compare two bitmaps. In this case, $Bitmap as read from the disk and - * lcn_bitmap which we built from the MFT Records. - */ -static void compare_bitmaps(ntfs_volume *vol, struct bitmap *a) -{ - s64 i, pos, count; - int mismatch = 0; - int backup_boot = 0; - u8 bm[NTFS_BUF_SIZE]; - - printf("Accounting clusters ...\n"); - - pos = 0; - while (1) { - count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm); - if (count == -1) - perr_exit("Couldn't get $Bitmap $DATA"); - - if (count == 0) { - if (a->size > pos) - err_exit("$Bitmap size is smaller than expected" - " (%lld != %lld)\n", a->size, pos); - break; - } - - for (i = 0; i < count; i++, pos++) { - s64 cl; /* current cluster */ - - if (a->size <= pos) - goto done; - - if (a->bm[pos] == bm[i]) - continue; - - for (cl = pos * 8; cl < (pos + 1) * 8; cl++) { - char bit; - - bit = ntfs_bit_get(a->bm, cl); - if (bit == ntfs_bit_get(bm, i * 8 + cl % 8)) - continue; - - if (!mismatch && !bit && !backup_boot && - cl == vol->nr_clusters / 2) { - /* FIXME: call also boot sector check */ - backup_boot = 1; - printf("Found backup boot sector in " - "the middle of the volume.\n"); - continue; - } - - if (++mismatch > 10 && !opt.verbose) - continue; - - printf("Cluster accounting failed at %lld " - "(0x%llx): %s cluster in " - "$Bitmap\n", (long long)cl, - (unsigned long long)cl, - bit ? "missing" : "extra"); - } - } - } -done: - if (mismatch) { - printf("Filesystem check failed! Totally %d cluster " - "accounting mismatches.\n", mismatch); - err_printf("%s", corrupt_volume_msg); - exit(1); - } -} - -/** - * progress_init - * - * Create and scale our progress bar. - */ -static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags) -{ - p->start = start; - p->stop = stop; - p->unit = 100.0 / (stop - start); - p->resolution = 100; - p->flags = flags; -} - -/** - * progress_update - * - * Update the progress bar and tell the user. - */ -static void progress_update(struct progress_bar *p, u64 current) -{ - float percent; - - if (!(p->flags & NTFS_PROGBAR)) - return; - if (p->flags & NTFS_PROGBAR_SUPPRESS) - return; - - /* WARNING: don't modify the texts, external tools grep for them */ - percent = p->unit * current; - if (current != p->stop) { - if ((current - p->start) % p->resolution) - return; - printf("%6.2f percent completed\r", percent); - } else - printf("100.00 percent completed\n"); - fflush(stdout); -} - -static int inode_close(ntfs_inode *ni) -{ - if (ntfs_inode_close(ni)) { - perr_printf("ntfs_inode_close for inode %llu", - (unsigned long long)ni->mft_no); - return -1; - } - return 0; -} - -/** - * walk_inodes - * - * Read each record in the MFT, skipping the unused ones, and build up a bitmap - * from all the non-resident attributes. - */ -static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck) -{ - s64 nr_mft_records, inode = 0; - ntfs_inode *ni; - struct progress_bar progress; - int pb_flags = 0; /* progress bar flags */ - - /* WARNING: don't modify the text, external tools grep for it */ - printf("Checking filesystem consistency ...\n"); - - if (fsck->flags & NTFSCK_PROGBAR) - pb_flags |= NTFS_PROGBAR; - - nr_mft_records = vol->mft_na->initialized_size >> - vol->mft_record_size_bits; - - progress_init(&progress, inode, nr_mft_records - 1, pb_flags); - - for (; inode < nr_mft_records; inode++) { - progress_update(&progress, inode); - - if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) { - /* FIXME: continue only if it make sense, e.g. - MFT record not in use based on $MFT bitmap */ - if (errno == EIO || errno == ENOENT) - continue; - perr_printf("Reading inode %lld failed", inode); - return -1; - } - - if (ni->mrec->base_mft_record) - goto close_inode; - - fsck->ni = ni; - if (walk_attributes(vol, fsck) != 0) { - inode_close(ni); - return -1; - } -close_inode: - if (inode_close(ni) != 0) - return -1; - } - return 0; -} - -static void build_resize_constraints(ntfs_resize_t *resize) -{ - s64 i; - runlist *rl; - - if (!resize->ctx->attr->non_resident) - return; - - if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, - resize->ctx->attr, NULL))) - perr_exit("ntfs_decompress_mapping_pairs"); - - for (i = 0; rl[i].length; i++) { - /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */ - if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED) - continue; - - collect_resize_constraints(resize, rl + i); - if (resize->shrink) - collect_relocation_info(resize, rl + i); - } - free(rl); -} - -static void resize_constraints_by_attributes(ntfs_resize_t *resize) -{ - if (!(resize->ctx = attr_get_search_ctx(resize->ni, NULL))) - exit(1); - - while (!ntfs_attrs_walk(resize->ctx)) { - if (resize->ctx->attr->type == AT_END) - break; - build_resize_constraints(resize); - } - - ntfs_attr_put_search_ctx(resize->ctx); -} - -static void set_resize_constraints(ntfs_resize_t *resize) -{ - s64 nr_mft_records, inode; - ntfs_inode *ni; - - printf("Collecting resizing constraints ...\n"); - - nr_mft_records = resize->vol->mft_na->initialized_size >> - resize->vol->mft_record_size_bits; - - for (inode = 0; inode < nr_mft_records; inode++) { - - ni = ntfs_inode_open(resize->vol, (MFT_REF)inode); - if (ni == NULL) { - if (errno == EIO || errno == ENOENT) - continue; - perr_exit("Reading inode %lld failed", inode); - } - - if (ni->mrec->base_mft_record) - goto close_inode; - - resize->ni = ni; - resize_constraints_by_attributes(resize); -close_inode: - if (inode_close(ni) != 0) - exit(1); - } -} - -static void rl_fixup(runlist **rl) -{ - runlist *tmp = *rl; - - if (tmp->lcn == LCN_RL_NOT_MAPPED) { - s64 unmapped_len = tmp->length; - - ntfs_log_verbose("Skip unmapped run at the beginning ...\n"); - - if (!tmp->length) - err_exit("Empty unmapped runlist! Please report!\n"); - (*rl)++; - for (tmp = *rl; tmp->length; tmp++) - tmp->vcn -= unmapped_len; - } - - for (tmp = *rl; tmp->length; tmp++) { - if (tmp->lcn == LCN_RL_NOT_MAPPED) { - ntfs_log_verbose("Skip unmapped run at the end ...\n"); - - if (tmp[1].length) - err_exit("Unmapped runlist in the middle! " - "Please report!\n"); - tmp->lcn = LCN_ENOENT; - tmp->length = 0; - } - } -} - -static void replace_attribute_runlist(ntfs_volume *vol, - ntfs_attr_search_ctx *ctx, - runlist *rl) -{ - int mp_size, l; - void *mp; - ATTR_RECORD *a = ctx->attr; - - rl_fixup(&rl); - - if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0)) == -1) - perr_exit("ntfs_get_size_for_mapping_pairs"); - - if (a->name_length) { - u16 name_offs = le16_to_cpu(a->name_offset); - u16 mp_offs = le16_to_cpu(a->u.nonres.mapping_pairs_offset); - - if (name_offs >= mp_offs) - err_exit("Attribute name is after mapping pairs! " - "Please report!\n"); - } - - /* CHECKME: don't trust mapping_pairs is always the last item in the - attribute, instead check for the real size/space */ - l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->u.nonres.mapping_pairs_offset); - if (mp_size > l) { - s64 remains_size; - char *next_attr; - - ntfs_log_verbose("Enlarging attribute header ...\n"); - - mp_size = (mp_size + 7) & ~7; - - ntfs_log_verbose("Old mp size : %d\n", l); - ntfs_log_verbose("New mp size : %d\n", mp_size); - ntfs_log_verbose("Bytes in use : %u\n", (unsigned int) - le32_to_cpu(ctx->mrec->bytes_in_use)); - - next_attr = (char *)a + le32_to_cpu(a->length); - l = mp_size - l; - - ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int) - le32_to_cpu(ctx->mrec->bytes_in_use)); - ntfs_log_verbose("Bytes allocated : %u\n", (unsigned int) - le32_to_cpu(ctx->mrec->bytes_allocated)); - - remains_size = le32_to_cpu(ctx->mrec->bytes_in_use); - remains_size -= (next_attr - (char *)ctx->mrec); - - ntfs_log_verbose("increase : %d\n", l); - ntfs_log_verbose("shift : %lld\n", - (long long)remains_size); - - if (le32_to_cpu(ctx->mrec->bytes_in_use) + l > - le32_to_cpu(ctx->mrec->bytes_allocated)) - err_exit("Extended record needed (%u > %u), not yet " - "supported!\nPlease try to free less space.\n", - (unsigned int)le32_to_cpu(ctx->mrec-> - bytes_in_use) + l, - (unsigned int)le32_to_cpu(ctx->mrec-> - bytes_allocated)); - - memmove(next_attr + l, next_attr, remains_size); - ctx->mrec->bytes_in_use = cpu_to_le32(l + - le32_to_cpu(ctx->mrec->bytes_in_use)); - a->length = cpu_to_le32(le32_to_cpu(a->length) + l); - } - - mp = ntfs_calloc(mp_size); - if (!mp) - perr_exit("ntfsc_calloc couldn't get memory"); - - if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl, 0, NULL)) - perr_exit("ntfs_mapping_pairs_build"); - - memmove((u8*)a + le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp, mp_size); - - free(mp); -} - -static void set_bitmap_range(struct bitmap *bm, s64 pos, s64 length, u8 bit) -{ - while (length--) - ntfs_bit_set(bm->bm, pos++, bit); -} - -static void set_bitmap_clusters(struct bitmap *bm, runlist *rl, u8 bit) -{ - for (; rl->length; rl++) - set_bitmap_range(bm, rl->lcn, rl->length, bit); -} - -static void release_bitmap_clusters(struct bitmap *bm, runlist *rl) -{ - max_free_cluster_range = 0; - set_bitmap_clusters(bm, rl, 0); -} - -static void set_max_free_zone(s64 length, s64 end, runlist_element *rle) -{ - if (length > rle->length) { - rle->lcn = end - length; - rle->length = length; - } -} - -static int find_free_cluster(struct bitmap *bm, - runlist_element *rle, - s64 nr_vol_clusters, - int hint) -{ - /* FIXME: get rid of this 'static' variable */ - static s64 pos = 0; - s64 i, items = rle->length; - s64 free_zone = 0; - - if (pos >= nr_vol_clusters) - pos = 0; - if (!max_free_cluster_range) - max_free_cluster_range = nr_vol_clusters; - rle->lcn = rle->length = 0; - if (hint) - pos = nr_vol_clusters / 2; - i = pos; - - do { - if (!ntfs_bit_get(bm->bm, i)) { - if (++free_zone == items) { - set_max_free_zone(free_zone, i + 1, rle); - break; - } - } else { - set_max_free_zone(free_zone, i, rle); - free_zone = 0; - } - if (++i == nr_vol_clusters) { - set_max_free_zone(free_zone, i, rle); - i = free_zone = 0; - } - if (rle->length == max_free_cluster_range) - break; - } while (i != pos); - - if (i) - set_max_free_zone(free_zone, i, rle); - - if (!rle->lcn) { - errno = ENOSPC; - return -1; - } - if (rle->length < items && rle->length < max_free_cluster_range) { - max_free_cluster_range = rle->length; - ntfs_log_verbose("Max free range: %7lld \n", - (long long)max_free_cluster_range); - } - pos = rle->lcn + items; - if (pos == nr_vol_clusters) - pos = 0; - - set_bitmap_range(bm, rle->lcn, rle->length, 1); - return 0; -} - -static runlist *alloc_cluster(struct bitmap *bm, - s64 items, - s64 nr_vol_clusters, - int hint) -{ - runlist_element rle; - runlist *rl = NULL; - int rl_size, runs = 0; - s64 vcn = 0; - - if (items <= 0) { - errno = EINVAL; - return NULL; - } - - while (items > 0) { - - if (runs) - hint = 0; - rle.length = items; - if (find_free_cluster(bm, &rle, nr_vol_clusters, hint) == -1) - return NULL; - - rl_size = (runs + 2) * sizeof(runlist_element); - if (!(rl = (runlist *)realloc(rl, rl_size))) - return NULL; - - rl_set(rl + runs, vcn, rle.lcn, rle.length); - - vcn += rle.length; - items -= rle.length; - runs++; - } - - rl_set(rl + runs, vcn, -1LL, 0LL); - - if (runs > 1) { - ntfs_log_verbose("Multi-run allocation: \n"); - dump_runlist(rl); - } - return rl; -} - -static int read_all(struct ntfs_device *dev, void *buf, int count) -{ - int i; - - while (count > 0) { - - i = count; - if (!NDevReadOnly(dev)) - i = dev->d_ops->read(dev, buf, count); - - if (i < 0) { - if (errno != EAGAIN && errno != EINTR) - return -1; - } else if (i > 0) { - count -= i; - buf = i + (char *)buf; - } else - err_exit("Unexpected end of file!\n"); - } - return 0; -} - -static int write_all(struct ntfs_device *dev, void *buf, int count) -{ - int i; - - while (count > 0) { - - i = count; - if (!NDevReadOnly(dev)) - i = dev->d_ops->write(dev, buf, count); - - if (i < 0) { - if (errno != EAGAIN && errno != EINTR) - return -1; - } else { - count -= i; - buf = i + (char *)buf; - } - } - return 0; -} - -/** - * write_mft_record - * - * Write an MFT Record back to the disk. If the read-only command line option - * was given, this function will do nothing. - */ -static int write_mft_record(ntfs_volume *v, const MFT_REF mref, MFT_RECORD *buf) -{ - if (ntfs_mft_record_write(v, mref, buf)) - perr_exit("ntfs_mft_record_write"); - -// if (v->u.dev->d_ops->sync(v->u.dev) == -1) -// perr_exit("Failed to sync device"); - - return 0; -} - -static void lseek_to_cluster(ntfs_volume *vol, s64 lcn) -{ - off_t pos; - pos = (off_t)(lcn * vol->cluster_size); - if (vol->u.dev->d_ops->seek(vol->u.dev, pos, SEEK_SET) == (off_t)-1) - perr_exit("seek failed to position %lld", lcn); -} - -static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len) -{ - s64 i; - char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */ - ntfs_volume *vol = resize->vol; - - for (i = 0; i < len; i++) { - - lseek_to_cluster(vol, src + i); - - if (read_all(vol->u.dev, buff, vol->cluster_size) == -1) { - perr_printf("Failed to read from the disk"); - if (errno == EIO) - printf("%s", bad_sectors_warning_msg); - exit(1); - } - - lseek_to_cluster(vol, dest + i); - - if (write_all(vol->u.dev, buff, vol->cluster_size) == -1) { - perr_printf("Failed to write to the disk"); - if (errno == EIO) - printf("%s", bad_sectors_warning_msg); - exit(1); - } - - resize->relocations++; - progress_update(&resize->progress, resize->relocations); - } -} - -static void relocate_clusters(ntfs_resize_t *r, runlist *dest_rl, s64 src_lcn) -{ - /* collect_shrink_constraints() ensured $MFTMir DATA is one run */ - if (r->mref == FILE_MFTMirr && r->ctx->attr->type == AT_DATA) { - if (!r->mftmir_old) { - r->mftmir_rl.lcn = dest_rl->lcn; - r->mftmir_rl.length = dest_rl->length; - r->mftmir_old = src_lcn; - } else - err_exit("Multi-run $MFTMirr. Please report!\n"); - } - - for (; dest_rl->length; src_lcn += dest_rl->length, dest_rl++) - copy_clusters(r, dest_rl->lcn, src_lcn, dest_rl->length); -} - -static void rl_split_run(runlist **rl, int run, s64 pos) -{ - runlist *rl_new, *rle_new, *rle; - int items, new_size, size_head, size_tail; - s64 len_head, len_tail; - - items = rl_items(*rl); - new_size = (items + 1) * sizeof(runlist_element); - size_head = run * sizeof(runlist_element); - size_tail = (items - run - 1) * sizeof(runlist_element); - - rl_new = ntfs_malloc(new_size); - if (!rl_new) - perr_exit("ntfs_malloc"); - - rle_new = rl_new + run; - rle = *rl + run; - - memmove(rl_new, *rl, size_head); - memmove(rle_new + 2, rle + 1, size_tail); - - len_tail = rle->length - (pos - rle->lcn); - len_head = rle->length - len_tail; - - rl_set(rle_new, rle->vcn, rle->lcn, len_head); - rl_set(rle_new + 1, rle->vcn + len_head, rle->lcn + len_head, len_tail); - - ntfs_log_verbose("Splitting run at cluster %lld:\n", (long long)pos); - dump_run(rle); dump_run(rle_new); dump_run(rle_new + 1); - - free(*rl); - *rl = rl_new; -} - -static void rl_insert_at_run(runlist **rl, int run, runlist *ins) -{ - int items, ins_items; - int new_size, size_tail; - runlist *rle; - s64 vcn; - - items = rl_items(*rl); - ins_items = rl_items(ins) - 1; - new_size = ((items - 1) + ins_items) * sizeof(runlist_element); - size_tail = (items - run - 1) * sizeof(runlist_element); - - if (!(*rl = (runlist *)realloc(*rl, new_size))) - perr_exit("realloc"); - - rle = *rl + run; - - memmove(rle + ins_items, rle + 1, size_tail); - - for (vcn = rle->vcn; ins->length; rle++, vcn += ins->length, ins++) { - rl_set(rle, vcn, ins->lcn, ins->length); -// dump_run(rle); - } - - return; - - /* FIXME: fast path if ins_items = 1 */ -// (*rl + run)->lcn = ins->lcn; -} - -static void relocate_run(ntfs_resize_t *resize, runlist **rl, int run) -{ - s64 lcn, lcn_length; - s64 new_vol_size; /* (last LCN on the volume) + 1 */ - runlist *relocate_rl; /* relocate runlist to relocate_rl */ - int hint; - - lcn = (*rl + run)->lcn; - lcn_length = (*rl + run)->length; - new_vol_size = resize->new_volume_size; - - if (lcn + lcn_length <= new_vol_size) - return; - - if (lcn < new_vol_size) { - rl_split_run(rl, run, new_vol_size); - return; - } - - hint = (resize->mref == FILE_MFTMirr) ? 1 : 0; - if (!(relocate_rl = alloc_cluster(&resize->lcn_bitmap, lcn_length, - new_vol_size, hint))) - perr_exit("Cluster allocation failed for %llu:%lld", - resize->mref, lcn_length); - - /* FIXME: check $MFTMirr DATA isn't multi-run (or support it) */ - ntfs_log_verbose("Relocate record %7llu:0x%x:%08lld:0x%08llx:0x%08llx " - "--> 0x%08llx\n", (unsigned long long)resize->mref, - (unsigned int)le32_to_cpu(resize->ctx->attr->type), - (long long)lcn_length, - (unsigned long long)(*rl + run)->vcn, - (unsigned long long)lcn, - (unsigned long long)relocate_rl->lcn); - - relocate_clusters(resize, relocate_rl, lcn); - rl_insert_at_run(rl, run, relocate_rl); - - /* We don't release old clusters in the bitmap, that area isn't - used by the allocator and will be truncated later on */ - free(relocate_rl); - - resize->dirty_inode = DIRTY_ATTRIB; -} - -static void relocate_attribute(ntfs_resize_t *resize) -{ - ATTR_RECORD *a; - runlist *rl; - int i; - - a = resize->ctx->attr; - - if (!a->non_resident) - return; - - if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, a, NULL))) - perr_exit("ntfs_decompress_mapping_pairs"); - - for (i = 0; rl[i].length; i++) { - s64 lcn = rl[i].lcn; - s64 lcn_length = rl[i].length; - - if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED) - continue; - - /* FIXME: ntfs_mapping_pairs_decompress should return error */ - if (lcn < 0 || lcn_length <= 0) - err_exit("Corrupt runlist in MTF %llu attr %x LCN " - "%llx length %llx\n", resize->mref, - (unsigned int)le32_to_cpu(a->type), - lcn, lcn_length); - - relocate_run(resize, &rl, i); - } - - if (resize->dirty_inode == DIRTY_ATTRIB) { - replace_attribute_runlist(resize->vol, resize->ctx, rl); - resize->dirty_inode = DIRTY_INODE; - } - - free(rl); -} - -static int is_mftdata(ntfs_resize_t *resize) -{ - if (resize->ctx->attr->type != AT_DATA) - return 0; - - if (resize->mref == 0) - return 1; - - if (MREF_LE(resize->mrec->base_mft_record) == 0 && - MSEQNO_LE(resize->mrec->base_mft_record) != 0) - return 1; - - return 0; -} - -static int handle_mftdata(ntfs_resize_t *resize, int do_mftdata) -{ - ATTR_RECORD *attr = resize->ctx->attr; - VCN highest_vcn, lowest_vcn; - - if (do_mftdata) { - - if (!is_mftdata(resize)) - return 0; - - highest_vcn = sle64_to_cpu(attr->u.nonres.highest_vcn); - lowest_vcn = sle64_to_cpu(attr->u.nonres.lowest_vcn); - - if (resize->mft_highest_vcn != highest_vcn) - return 0; - - if (lowest_vcn == 0) - resize->mft_highest_vcn = lowest_vcn; - else - resize->mft_highest_vcn = lowest_vcn - 1; - - } else if (is_mftdata(resize)) { - - highest_vcn = sle64_to_cpu(attr->u.nonres.highest_vcn); - - if (resize->mft_highest_vcn < highest_vcn) - resize->mft_highest_vcn = highest_vcn; - - return 0; - } - - return 1; -} - -static void relocate_attributes(ntfs_resize_t *resize, int do_mftdata) -{ - int ret; - - if (!(resize->ctx = attr_get_search_ctx(NULL, resize->mrec))) - exit(1); - - while (!ntfs_attrs_walk(resize->ctx)) { - if (resize->ctx->attr->type == AT_END) - break; - - if (handle_mftdata(resize, do_mftdata) == 0) - continue; - - ret = ntfs_inode_badclus_bad(resize->mref, resize->ctx->attr); - if (ret == -1) - perr_exit("Bad sector list check failed"); - else if (ret == 1) - continue; - - if (resize->mref == FILE_Bitmap && - resize->ctx->attr->type == AT_DATA) - continue; - - relocate_attribute(resize); - } - - ntfs_attr_put_search_ctx(resize->ctx); -} - -static void relocate_inode(ntfs_resize_t *resize, MFT_REF mref, int do_mftdata) -{ - if (ntfs_file_record_read(resize->vol, mref, &resize->mrec, NULL)) { - /* FIXME: continue only if it make sense, e.g. - MFT record not in use based on $MFT bitmap */ - if (errno == EIO || errno == ENOENT) - return; - perr_exit("ntfs_file_record_record"); - } - - if (!(resize->mrec->flags & MFT_RECORD_IN_USE)) - return; - - resize->mref = mref; - resize->dirty_inode = DIRTY_NONE; - - relocate_attributes(resize, do_mftdata); - - if (resize->dirty_inode == DIRTY_INODE) { -// if (vol->u.dev->d_ops->sync(vol->u.dev) == -1) -// perr_exit("Failed to sync device"); - if (write_mft_record(resize->vol, mref, resize->mrec)) - perr_exit("Couldn't update record %llu", mref); - } -} - -static void relocate_inodes(ntfs_resize_t *resize) -{ - s64 nr_mft_records; - MFT_REF mref; - VCN highest_vcn; - - printf("Relocating needed data ...\n"); - - progress_init(&resize->progress, 0, resize->relocations, resize->progress.flags); - resize->relocations = 0; - - resize->mrec = ntfs_malloc(resize->vol->mft_record_size); - if (!resize->mrec) - perr_exit("ntfs_malloc failed"); - - nr_mft_records = resize->vol->mft_na->initialized_size >> - resize->vol->mft_record_size_bits; - - for (mref = 0; mref < (MFT_REF)nr_mft_records; mref++) - relocate_inode(resize, mref, 0); - - while (1) { - highest_vcn = resize->mft_highest_vcn; - mref = nr_mft_records; - do { - relocate_inode(resize, --mref, 1); - if (resize->mft_highest_vcn == 0) - goto done; - } while (mref); - - if (highest_vcn == resize->mft_highest_vcn) - err_exit("Sanity check failed! Highest_vcn = %lld. " - "Please report!\n", highest_vcn); - } -done: - free(resize->mrec); -} - -static void print_hint(ntfs_volume *vol, const char *s, struct llcn_t llcn) -{ - s64 runs_b, runs_mb; - - if (llcn.lcn == 0) - return; - - runs_b = llcn.lcn * vol->cluster_size; - runs_mb = rounded_up_division(runs_b, NTFS_MBYTE); - printf("%-19s: %9lld MB %8lld\n", s, (long long)runs_mb, - (long long)llcn.inode); -} - -/** - * advise_on_resize - * - * The metadata file $Bitmap has one bit for each cluster on disk. This has - * already been read into lcn_bitmap. By looking for the last used cluster on - * the disk, we can work out by how much we can shrink the volume. - */ -static void advise_on_resize(ntfs_resize_t *resize) -{ - ntfs_volume *vol = resize->vol; - - if (opt.verbose) { - printf("Estimating smallest shrunken size supported ...\n"); - printf("File feature Last used at By inode\n"); - print_hint(vol, "$MFT", resize->last_mft); - print_hint(vol, "Multi-Record", resize->last_multi_mft); - print_hint(vol, "$MFTMirr", resize->last_mftmir); - print_hint(vol, "Compressed", resize->last_compressed); - print_hint(vol, "Sparse", resize->last_sparse); - print_hint(vol, "Ordinary", resize->last_lcn); - } - - print_advise(vol, resize->last_unsupp); -} - - -static void rl_expand(runlist **rl, const VCN last_vcn) -{ - int len; - runlist *p = *rl; - - len = rl_items(p) - 1; - if (len <= 0) - err_exit("rl_expand: bad runlist length: %d\n", len); - - if (p[len].vcn > last_vcn) - err_exit("rl_expand: length is already more than requested " - "(%lld > %lld)\n", p[len].vcn, last_vcn); - - if (p[len - 1].lcn == LCN_HOLE) { - - p[len - 1].length += last_vcn - p[len].vcn; - p[len].vcn = last_vcn; - - } else if (p[len - 1].lcn >= 0) { - - p = realloc(*rl, (++len + 1) * sizeof(runlist_element)); - if (!p) - perr_exit("rl_expand: realloc"); - - p[len - 1].lcn = LCN_HOLE; - p[len - 1].length = last_vcn - p[len - 1].vcn; - rl_set(p + len, last_vcn, LCN_ENOENT, 0LL); - *rl = p; - - } else - err_exit("rl_expand: bad LCN: %lld\n", p[len - 1].lcn); -} - -static void rl_truncate(runlist **rl, const VCN last_vcn) -{ - int len; - VCN vcn; - - len = rl_items(*rl) - 1; - if (len <= 0) - err_exit("rl_truncate: bad runlist length: %d\n", len); - - vcn = (*rl)[len].vcn; - - if (vcn < last_vcn) - rl_expand(rl, last_vcn); - - else if (vcn > last_vcn) - if (ntfs_rl_truncate(rl, last_vcn) == -1) - perr_exit("ntfs_rl_truncate"); -} - -/** - * bitmap_file_data_fixup - * - * $Bitmap can overlap the end of the volume. Any bits in this region - * must be set. This region also encompasses the backup boot sector. - */ -static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm) -{ - for (; cluster < bm->size << 3; cluster++) - ntfs_bit_set(bm->bm, (u64)cluster, 1); -} - -/** - * truncate_badclust_bad_attr - * - * The metadata file $BadClus needs to be shrunk. - * - * FIXME: this function should go away and instead using a generalized - * "truncate_bitmap_data_attr()" - */ -static void truncate_badclust_bad_attr(ntfs_resize_t *resize) -{ - ATTR_RECORD *a; - runlist *rl_bad; - s64 nr_clusters = resize->new_volume_size; - ntfs_volume *vol = resize->vol; - - a = resize->ctx->attr; - if (!a->non_resident) - /* FIXME: handle resident attribute value */ - err_exit("Resident attribute in $BadClust isn't supported!\n"); - - if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, a, NULL))) - perr_exit("ntfs_mapping_pairs_decompress"); - - rl_truncate(&rl_bad, nr_clusters); - - a->u.nonres.highest_vcn = cpu_to_sle64(nr_clusters - 1LL); - a->u.nonres.allocated_size = cpu_to_sle64(nr_clusters * vol->cluster_size); - a->u.nonres.data_size = cpu_to_sle64(nr_clusters * vol->cluster_size); - - replace_attribute_runlist(vol, resize->ctx, rl_bad); - - free(rl_bad); -} - -/** - * realloc_bitmap_data_attr - * - * Reallocate the metadata file $Bitmap. It must be large enough for one bit - * per cluster of the shrunken volume. Also it must be a of 8 bytes in size. - */ -static void realloc_bitmap_data_attr(ntfs_resize_t *resize, - runlist **rl, - s64 nr_bm_clusters) -{ - s64 i; - ntfs_volume *vol = resize->vol; - ATTR_RECORD *a = resize->ctx->attr; - s64 new_size = resize->new_volume_size; - struct bitmap *bm = &resize->lcn_bitmap; - - if (!(*rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) - perr_exit("ntfs_mapping_pairs_decompress"); - - release_bitmap_clusters(bm, *rl); - free(*rl); - - for (i = vol->nr_clusters; i < new_size; i++) - ntfs_bit_set(bm->bm, i, 0); - - if (!(*rl = alloc_cluster(bm, nr_bm_clusters, new_size, 0))) - perr_exit("Couldn't allocate $Bitmap clusters"); -} - -static void realloc_lcn_bitmap(ntfs_resize_t *resize, s64 bm_bsize) -{ - u8 *tmp; - - if (!(tmp = realloc(resize->lcn_bitmap.bm, bm_bsize))) - perr_exit("realloc"); - - resize->lcn_bitmap.bm = tmp; - resize->lcn_bitmap.size = bm_bsize; - bitmap_file_data_fixup(resize->new_volume_size, &resize->lcn_bitmap); -} - -/** - * truncate_bitmap_data_attr - */ -static void truncate_bitmap_data_attr(ntfs_resize_t *resize) -{ - ATTR_RECORD *a; - runlist *rl; - s64 bm_bsize, size; - s64 nr_bm_clusters; - ntfs_volume *vol = resize->vol; - - a = resize->ctx->attr; - if (!a->non_resident) - /* FIXME: handle resident attribute value */ - err_exit("Resident attribute in $Bitmap isn't supported!\n"); - - bm_bsize = nr_clusters_to_bitmap_byte_size(resize->new_volume_size); - nr_bm_clusters = rounded_up_division(bm_bsize, vol->cluster_size); - - if (resize->shrink) { - realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters); - realloc_lcn_bitmap(resize, bm_bsize); - } else { - realloc_lcn_bitmap(resize, bm_bsize); - realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters); - } - - a->u.nonres.highest_vcn = cpu_to_sle64(nr_bm_clusters - 1LL); - a->u.nonres.allocated_size = cpu_to_sle64(nr_bm_clusters * vol->cluster_size); - a->u.nonres.data_size = cpu_to_sle64(bm_bsize); - a->u.nonres.initialized_size = cpu_to_sle64(bm_bsize); - - replace_attribute_runlist(vol, resize->ctx, rl); - - /* - * FIXME: update allocated/data sizes and timestamps in $FILE_NAME - * attribute too, for now chkdsk will do this for us. - */ - - size = ntfs_rl_pwrite(vol, rl, 0, bm_bsize, resize->lcn_bitmap.bm); - if (bm_bsize != size) { - if (size == -1) - perr_exit("Couldn't write $Bitmap"); - err_exit("Couldn't write full $Bitmap file (%lld from %lld)\n", - (long long)size, (long long)bm_bsize); - } - - free(rl); -} - -/** - * lookup_data_attr - * - * Find the $DATA attribute (with or without a name) for the given MFT reference - * (inode number). - */ -static void lookup_data_attr(ntfs_volume *vol, - MFT_REF mref, - const char *aname, - ntfs_attr_search_ctx **ctx) -{ - ntfs_inode *ni; - ntfschar *ustr; - int len = 0; - - if (!(ni = ntfs_inode_open(vol, mref))) - perr_exit("ntfs_open_inode"); - - if (!(*ctx = attr_get_search_ctx(ni, NULL))) - exit(1); - - if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) { - perr_printf("Couldn't convert '%s' to Unicode", aname); - exit(1); - } - - if (ntfs_attr_lookup(AT_DATA, ustr, len, 0, 0, NULL, 0, *ctx)) - perr_exit("ntfs_lookup_attr"); - - ntfs_ucsfree(ustr); -} - -static int check_bad_sectors(ntfs_volume *vol) -{ - ntfs_attr_search_ctx *ctx; - ntfs_inode *base_ni; - runlist *rl; - s64 i, badclusters = 0; - - ntfs_log_verbose("Checking for bad sectors ...\n"); - - lookup_data_attr(vol, FILE_BadClus, "$Bad", &ctx); - - base_ni = ctx->base_ntfs_ino; - if (!base_ni) - base_ni = ctx->ntfs_ino; - - if (NInoAttrList(base_ni)) { - err_printf("Hopelessly many bad sectors has been detected!\n"); - printf("%s", many_bad_sectors_msg); - exit(1); - } - - if (!ctx->attr->non_resident) - err_exit("Resident attribute in $BadClust! Please report to " - "%s\n", NTFS_DEV_LIST); - /* - * FIXME: The below would be partial for non-base records in the - * not yet supported multi-record case. Alternatively use audited - * ntfs_attr_truncate after an umount & mount. - */ - if (!(rl = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL))) - perr_exit("Decompressing $BadClust:$Bad mapping pairs failed"); - - for (i = 0; rl[i].length; i++) { - /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */ - if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED) - continue; - - badclusters += rl[i].length; - ntfs_log_verbose("Bad cluster: %#8llx - %#llx (%lld)\n", - rl[i].lcn, rl[i].lcn + rl[i].length - 1, - rl[i].length); - } - - if (badclusters) { - printf("%sThis software has detected that the disk has at least" - " %lld bad sector%s.\n", - !opt.badsectors ? NERR_PREFIX : "WARNING: ", - badclusters, badclusters - 1 ? "s" : ""); - if (!opt.badsectors) { - printf("%s", bad_sectors_warning_msg); - exit(1); - } else - printf("WARNING: Bad sectors can cause reliability " - "problems and massive data loss!!!\n"); - } - - free(rl); - ntfs_attr_put_search_ctx(ctx); - - return badclusters; -} - -/** - * truncate_badclust_file - * - * Shrink the $BadClus file to match the new volume size. - */ -static void truncate_badclust_file(ntfs_resize_t *resize) -{ - printf("Updating $BadClust file ...\n"); - - lookup_data_attr(resize->vol, FILE_BadClus, "$Bad", &resize->ctx); - /* FIXME: sanity_check_attr(ctx->attr); */ - truncate_badclust_bad_attr(resize); - - if (write_mft_record(resize->vol, resize->ctx->ntfs_ino->mft_no, - resize->ctx->mrec)) - perr_exit("Couldn't update $BadClust"); - - ntfs_attr_put_search_ctx(resize->ctx); -} - -/** - * truncate_bitmap_file - * - * Shrink the $Bitmap file to match the new volume size. - */ -static void truncate_bitmap_file(ntfs_resize_t *resize) -{ - printf("Updating $Bitmap file ...\n"); - - lookup_data_attr(resize->vol, FILE_Bitmap, NULL, &resize->ctx); - truncate_bitmap_data_attr(resize); - - if (write_mft_record(resize->vol, resize->ctx->ntfs_ino->mft_no, - resize->ctx->mrec)) - perr_exit("Couldn't update $Bitmap"); - - ntfs_attr_put_search_ctx(resize->ctx); -} - -/** - * setup_lcn_bitmap - * - * Allocate a block of memory with one bit for each cluster of the disk. - * All the bits are set to 0, except those representing the region beyond the - * end of the disk. - */ -static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters) -{ - /* Determine lcn bitmap byte size and allocate it. */ - bm->size = rounded_up_division(nr_clusters, 8); - - bm->bm = ntfs_calloc(bm->size); - if (!bm->bm) - return -1; - - bitmap_file_data_fixup(nr_clusters, bm); - return 0; -} - -/** - * update_bootsector - * - * FIXME: should be done using ntfs_* functions - */ -static void update_bootsector(ntfs_resize_t *r) -{ - NTFS_BOOT_SECTOR bs; - s64 bs_size = sizeof(NTFS_BOOT_SECTOR); - ntfs_volume *vol = r->vol; - - printf("Updating Boot record ...\n"); - - if (vol->u.dev->d_ops->seek(vol->u.dev, 0, SEEK_SET) == (off_t)-1) - perr_exit("lseek"); - - if (vol->u.dev->d_ops->read(vol->u.dev, &bs, bs_size) == -1) - perr_exit("read() error"); - - bs.number_of_sectors = cpu_to_sle64(r->new_volume_size * - bs.bpb.sectors_per_cluster); - - if (r->mftmir_old) { - r->progress.flags |= NTFS_PROGBAR_SUPPRESS; - copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old, - r->mftmir_rl.length); - bs.mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn); - r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS; - } - - if (vol->u.dev->d_ops->seek(vol->u.dev, 0, SEEK_SET) == (off_t)-1) - perr_exit("lseek"); - - if (!opt.ro_flag) - if (vol->u.dev->d_ops->write(vol->u.dev, &bs, bs_size) == -1) - perr_exit("write() error"); -} - -/** - * vol_size - */ -static s64 vol_size(ntfs_volume *v, s64 nr_clusters) -{ - /* add one sector_size for the backup boot sector */ - return nr_clusters * v->cluster_size + v->sector_size; -} - -/** - * print_vol_size - * - * Print the volume size in bytes and decimal megabytes. - */ -static void print_vol_size(const char *str, s64 bytes) -{ - printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes, - (long long)rounded_up_division(bytes, NTFS_MBYTE)); -} - -/** - * print_disk_usage - * - * Display the amount of disk space in use. - */ -static void print_disk_usage(ntfs_volume *vol, s64 nr_used_clusters) -{ - s64 total, used; - - total = vol->nr_clusters * vol->cluster_size; - used = nr_used_clusters * vol->cluster_size; - - /* WARNING: don't modify the text, external tools grep for it */ - printf("Space in use : %lld MB (%.1f%%)\n", - (long long)rounded_up_division(used, NTFS_MBYTE), - 100.0 * ((float)used / total)); -} - -static void print_num_of_relocations(ntfs_resize_t *resize) -{ - s64 relocations = resize->relocations * resize->vol->cluster_size; - - printf("Needed relocations : %lld (%lld MB)\n", - (long long)resize->relocations, (long long) - rounded_up_division(relocations, NTFS_MBYTE)); -} - -/** - * mount_volume - * - * First perform some checks to determine if the volume is already mounted, or - * is dirty (Windows wasn't shutdown properly). If everything is OK, then mount - * the volume (load the metadata into memory). - */ -static ntfs_volume *mount_volume(void) -{ - unsigned long mntflag; - ntfs_volume *vol = NULL; - - if (ntfs_check_if_mounted(opt.volume, &mntflag)) { - perr_printf("Failed to check '%s' mount state", opt.volume); - printf("Probably /etc/mtab is missing. It's too risky to " - "continue. You might try\nan another Linux distro.\n"); - exit(1); - } - if (mntflag & NTFS_MF_MOUNTED) { - if (!(mntflag & NTFS_MF_READONLY)) - err_exit("Device '%s' is mounted read-write. " - "You must 'umount' it first.\n", opt.volume); - if (!opt.ro_flag) - err_exit("Device '%s' is mounted. " - "You must 'umount' it first.\n", opt.volume); - } - /* - * Pass NTFS_MNT_FORENSIC so that the mount process does not modify the - * volume at all. We will do the logfile emptying and dirty setting - * later if needed. - */ - if (!(vol = ntfs_mount(opt.volume, opt.ro_flag | NTFS_MNT_FORENSIC))) { - int err = errno; - - perr_printf("Opening '%s' as NTFS failed", opt.volume); - if (err == EINVAL) - printf(invalid_ntfs_msg, opt.volume); - else if (err == EIO) - printf("%s", corrupt_volume_msg); - else if (err == EPERM) - printf("%s", hibernated_volume_msg); - else if (err == EOPNOTSUPP) - printf("%s", unclean_journal_msg); - else if (err == EBUSY) - printf("%s", opened_volume_msg); - exit(1); - } - - if (NVolWasDirty(vol)) - if (opt.force-- <= 0) - err_exit("Volume is scheduled for check.\nRun chkdsk /f" - " and please try again, or see option -f.\n"); - - if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size) - err_exit("Cluster size %u is too large!\n", - (unsigned int)vol->cluster_size); - - printf("Device name : %s\n", opt.volume); - printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver); - if (ntfs_version_is_supported(vol)) - perr_exit("Unknown NTFS version"); - - printf("Cluster size : %u bytes\n", - (unsigned int)vol->cluster_size); - print_vol_size("Current volume size", vol_size(vol, vol->nr_clusters)); - - return vol; -} - -/** - * prepare_volume_fixup - * - * Set the volume's dirty flag and wipe the filesystem journal. When Windows - * boots it will automatically run chkdsk to check for any problems. If the - * read-only command line option was given, this function will do nothing. - */ -static void prepare_volume_fixup(ntfs_volume *vol) -{ - printf("Schedule chkdsk for NTFS consistency check at Windows boot " - "time ...\n"); - vol->flags |= VOLUME_IS_DIRTY; - if (ntfs_volume_write_flags(vol, vol->flags)) - perr_exit("Failed to set the volume dirty"); - NVolSetWasDirty(vol); - if (vol->u.dev->d_ops->sync(vol->u.dev) == -1) - perr_exit("Failed to sync device"); - printf("Resetting $LogFile ... (this might take a while)\n"); - if (ntfs_logfile_reset(vol)) - perr_exit("Failed to reset $LogFile"); - if (vol->u.dev->d_ops->sync(vol->u.dev) == -1) - perr_exit("Failed to sync device"); -} - -static void set_disk_usage_constraint(ntfs_resize_t *resize) -{ - /* last lcn for a filled up volume (no empty space) */ - s64 last = resize->inuse - 1; - - if (resize->last_unsupp < last) - resize->last_unsupp = last; -} - -static void check_resize_constraints(ntfs_resize_t *resize) -{ - s64 new_size = resize->new_volume_size; - - /* FIXME: resize.shrink true also if only -i is used */ - if (!resize->shrink) - return; - - if (resize->inuse == resize->vol->nr_clusters) - err_exit("Volume is full. To shrink it, " - "delete unused files.\n"); - - if (opt.info) - return; - - /* FIXME: reserve some extra space so Windows can boot ... */ - if (new_size < resize->inuse) - err_exit("New size can't be less than the space already" - " occupied by data.\nYou either need to delete unused" - " files or see the -i option.\n"); - - if (new_size <= resize->last_unsupp) - err_exit("The fragmentation type, you have, isn't " - "supported yet. Rerun ntfsresize\nwith " - "the -i option to estimate the smallest " - "shrunken volume size supported.\n"); - - print_num_of_relocations(resize); -} - -static void check_cluster_allocation(ntfs_volume *vol, ntfsck_t *fsck) -{ - memset(fsck, 0, sizeof(ntfsck_t)); - - if (opt.show_progress) - fsck->flags |= NTFSCK_PROGBAR; - - if (setup_lcn_bitmap(&fsck->lcn_bitmap, vol->nr_clusters) != 0) - perr_exit("Failed to setup allocation bitmap"); - if (build_allocation_bitmap(vol, fsck) != 0) - exit(1); - if (fsck->outsider || fsck->multi_ref) { - err_printf("Filesystem check failed!\n"); - if (fsck->outsider) - err_printf("%d clusters are referenced outside " - "of the volume.\n", fsck->outsider); - if (fsck->multi_ref) - err_printf("%d clusters are referenced multiply" - " times.\n", fsck->multi_ref); - printf("%s", corrupt_volume_msg); - exit(1); - } - - compare_bitmaps(vol, &fsck->lcn_bitmap); -} - -int main(int argc, char **argv) -{ - ntfsck_t fsck; - ntfs_resize_t resize; - s64 new_size = 0; /* in clusters; 0 = --info w/o --size */ - s64 device_size; /* in bytes */ - ntfs_volume *vol; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - printf("%s v%s (libntfs %s)\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - - if (!parse_options(argc, argv)) - return 1; - - utils_set_locale(); - - if (!(vol = mount_volume())) - err_exit("Couldn't open volume '%s'!\n", opt.volume); - - device_size = ntfs_device_size_get(vol->u.dev, vol->sector_size); - device_size *= vol->sector_size; - if (device_size <= 0) - err_exit("Couldn't get device size (%lld)!\n", device_size); - - print_vol_size("Current device size", device_size); - - if (device_size < vol->nr_clusters * vol->cluster_size) - err_exit("Current NTFS volume size is bigger than the device " - "size!\nCorrupt partition table or incorrect device " - "partitioning?\n"); - - if (!opt.bytes && !opt.info) - opt.bytes = device_size; - - /* Take the integer part: don't make the volume bigger than requested */ - new_size = opt.bytes / vol->cluster_size; - - /* Backup boot sector at the end of device isn't counted in NTFS - volume size thus we have to reserve space for it. */ - if (new_size) - --new_size; - - if (!opt.info) { - print_vol_size("New volume size ", vol_size(vol, new_size)); - if (device_size < opt.bytes) - err_exit("New size can't be bigger than the device size" - ".\nIf you want to enlarge NTFS then first " - "enlarge the device size by e.g. fdisk.\n"); - } - - if (!opt.info && (new_size == vol->nr_clusters || - (opt.bytes == device_size && - new_size == vol->nr_clusters - 1))) { - printf("Nothing to do: NTFS volume size is already OK.\n"); - exit(0); - } - - memset(&resize, 0, sizeof(resize)); - resize.vol = vol; - resize.new_volume_size = new_size; - /* This is also true if --info was used w/o --size (new_size = 0) */ - if (new_size < vol->nr_clusters) - resize.shrink = 1; - if (opt.show_progress) - resize.progress.flags |= NTFS_PROGBAR; - /* - * Checking and __reporting__ of bad sectors must be done before cluster - * allocation check because chkdsk doesn't fix $Bitmap's w/ bad sectors - * thus users would (were) quite confused why chkdsk doesn't work. - */ - resize.badclusters = check_bad_sectors(vol); - - check_cluster_allocation(vol, &fsck); - - print_disk_usage(vol, fsck.inuse); - - resize.inuse = fsck.inuse; - resize.lcn_bitmap = fsck.lcn_bitmap; - - set_resize_constraints(&resize); - set_disk_usage_constraint(&resize); - check_resize_constraints(&resize); - - if (opt.info) { - advise_on_resize(&resize); - exit(0); - } - - if (opt.force-- <= 0 && !opt.ro_flag) { - printf("%s", resize_warning_msg); - proceed_question(); - } - - /* FIXME: performance - relocate logfile here if it's needed */ - prepare_volume_fixup(vol); - - if (resize.relocations) - relocate_inodes(&resize); - - truncate_badclust_file(&resize); - truncate_bitmap_file(&resize); - update_bootsector(&resize); - - /* We don't create backup boot sector because we don't know where the - partition will be split. The scheduled chkdsk will fix it */ - - if (opt.ro_flag) { - printf("The read-only test run ended successfully.\n"); - exit(0); - } - - /* WARNING: don't modify the texts, external tools grep for them */ - printf("Syncing device ...\n"); - if (vol->u.dev->d_ops->sync(vol->u.dev) == -1) - perr_exit("fsync"); - - printf("Successfully resized NTFS on device '%s'.\n", vol->u.dev->d_name); - if (resize.shrink) - printf("%s", resize_important_msg); - - return 0; -} diff --git a/usr/src/cmd/ntfsprogs/ntfsundelete.c b/usr/src/cmd/ntfsprogs/ntfsundelete.c deleted file mode 100644 index 5b75aa0016..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsundelete.c +++ /dev/null @@ -1,2199 +0,0 @@ -/** - * ntfsundelete - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2004-2005 Holger Ohmacht - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility will recover deleted files from an NTFS volume. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifdef HAVE_FEATURES_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_UTIME_H -#include -#endif -#include - -#if !defined(REG_NOERROR) || (REG_NOERROR != 0) -#define REG_NOERROR 0 -#endif - -#include "compat.h" -#include "ntfsundelete.h" -#include "bootsect.h" -#include "mft.h" -#include "attrib.h" -#include "layout.h" -#include "inode.h" -#include "device.h" -#include "utils.h" -#include "debug.h" -#include "ntfstime.h" -#include "version.h" -#include "logging.h" - -static const char *EXEC_NAME = "ntfsundelete"; -static const char *MFTFILE = "mft"; -static const char *UNNAMED = ""; -static const char *NONE = ""; -static const char *UNKNOWN = "unknown"; -static struct options opts; - -typedef struct -{ - u32 begin; - u32 end; -} range; - -static short with_regex; /* Flag Regular expression available */ -static short avoid_duplicate_printing; /* Flag No duplicate printing of file infos */ -static range *ranges; /* Array containing all Inode-Ranges for undelete */ -static long nr_entries; /* Number of range entries */ - -/** - * parse_inode_arg - parses the inode expression - * - * Parses the optarg after parameter -u for valid ranges - * - * Return: Number of correct inode specifications or -1 for error - */ -static int parse_inode_arg(void) -{ - int p; - u32 imax; - u32 range_begin; - u32 range_end; - u32 range_temp; - u32 inode; - char *opt_arg_ptr; - char *opt_arg_temp; - char *opt_arg_end1; - char *opt_arg_end2; - - /* Check whether optarg is available or not */ - nr_entries = 0; - if (optarg == NULL) - return (0); /* bailout if no optarg */ - - /* init variables */ - p = strlen(optarg); - imax = p; - opt_arg_ptr = optarg; - opt_arg_end1 = optarg; - opt_arg_end2 = &(optarg[p]); - - /* alloc mem for range table */ - ranges = (range *) malloc((p + 1) * sizeof(range)); - if (ranges == NULL) { - ntfs_log_error("ERROR: Couldn't alloc mem for parsing inodes!\n"); - return (-1); - } - - /* loop */ - while ((opt_arg_end1 != opt_arg_end2) && (p > 0)) { - /* Try to get inode */ - inode = strtoul(opt_arg_ptr, &opt_arg_end1, 0); - p--; - - /* invalid char at begin */ - if ((opt_arg_ptr == opt_arg_end1) || (opt_arg_ptr == opt_arg_end2)) { - ntfs_log_error("ERROR: Invalid Number: %s\n", opt_arg_ptr); - return (-1); - } - - /* RANGE - Check for range */ - if (opt_arg_end1[0] == '-') { - /* get range end */ - opt_arg_temp = opt_arg_end1; - opt_arg_end1 = & (opt_arg_temp[1]); - if (opt_arg_temp >= opt_arg_end2) { - ntfs_log_error("ERROR: Missing range end!\n"); - return (-1); - } - range_begin = inode; - - /* get count */ - range_end = strtoul(opt_arg_end1, &opt_arg_temp, 0); - if (opt_arg_temp == opt_arg_end1) { - ntfs_log_error("ERROR: Invalid Number: %s\n", opt_arg_temp); - return (-1); - } - - /* check for correct values */ - if (range_begin > range_end) { - range_temp = range_end; - range_end = range_begin; - range_begin = range_temp; - } - - /* put into struct */ - ranges[nr_entries].begin = range_begin; - ranges[nr_entries].end = range_end; - nr_entries++; - - /* Last check */ - opt_arg_ptr = & (opt_arg_temp[1]); - if (opt_arg_ptr >= opt_arg_end2) - break; - } else if (opt_arg_end1[0] == ',') { - /* SINGLE VALUE, BUT CONTINUING */ - /* put inode into range list */ - ranges[nr_entries].begin = inode; - ranges[nr_entries].end = inode; - nr_entries++; - - /* Next inode */ - opt_arg_ptr = & (opt_arg_end1[1]); - if (opt_arg_ptr >= opt_arg_end2) { - ntfs_log_error("ERROR: Missing new value at end of input!\n"); - return (-1); - } - continue; - } else { /* SINGLE VALUE, END */ - ranges[nr_entries].begin = inode; - ranges[nr_entries].end = inode; - nr_entries++; - } - } - return (nr_entries); -} - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs %s) - Recover deleted files from an " - "NTFS Volume.\n\n", EXEC_NAME, VERSION, - ntfs_libntfs_version()); - ntfs_log_info("Copyright (c) 2002-2005 Richard Russon\n" - "Copyright (c) 2004-2005 Holger Ohmacht\n" - "Copyright (c) 2005 Anton Altaparmakov\n" - "Copyright (c) 2007 Yura Pakhuchiy\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device\n" - " -s, --scan Scan for files (default)\n" - " -p, --percentage NUM Minimum percentage recoverable\n" - " -m, --match PATTERN Only work on files with matching names\n" - " -C, --case Case sensitive matching\n" - " -S, --size RANGE Match files of this size\n" - " -t, --time SINCE Last referenced since this time\n" - "\n" - " -u, --undelete Undelete mode\n" - " -i, --inodes RANGE Recover these inodes\n" - //" -I, --interactive Interactive mode\n" - " -o, --output FILE Save with this filename\n" - " -O, --optimistic Undelete in-use clusters as well\n" - " -d, --destination DIR Destination directory\n" - " -b, --byte NUM Fill missing parts with this byte\n" - " -T, --truncate Truncate 100%% recoverable file to exact size.\n" - " -P, --parent Show parent directory\n" - "\n" - " -c, --copy RANGE Write a range of MFT records to a file\n" - "\n" - " -f, --force Use less caution\n" - " -q, --quiet Less output\n" - " -v, --verbose More output\n" - " -V, --version Display version information\n" - " -h, --help Display this help\n\n", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * transform - Convert a shell style pattern to a regex - * @pattern: String to be converted - * @regex: Resulting regular expression is put here - * - * This will transform patterns, such as "*.doc" to true regular expressions. - * The function will also place '^' and '$' around the expression to make it - * behave as the user would expect - * - * Before After - * . \. - * * .* - * ? . - * - * Notes: - * The returned string must be freed by the caller. - * If transform fails, @regex will not be changed. - * - * Return: 1, Success, the string was transformed - * 0, An error occurred - */ -static int transform(const char *pattern, char **regex) -{ - char *result; - int length, i, j; - - if (!pattern || !regex) - return 0; - - length = strlen(pattern); - if (length < 1) { - ntfs_log_error("Pattern to transform is empty\n"); - return 0; - } - - for (i = 0; pattern[i]; i++) { - if ((pattern[i] == '*') || (pattern[i] == '.')) - length++; - } - - result = malloc(length + 3); - if (!result) { - ntfs_log_error("Couldn't allocate memory in transform()\n"); - return 0; - } - - result[0] = '^'; - - for (i = 0, j = 1; pattern[i]; i++, j++) { - if (pattern[i] == '*') { - result[j] = '.'; - j++; - result[j] = '*'; - } else if (pattern[i] == '.') { - result[j] = '\\'; - j++; - result[j] = '.'; - } else if (pattern[i] == '?') { - result[j] = '.'; - } else { - result[j] = pattern[i]; - } - } - - result[j] = '$'; - result[j+1] = 0; - ntfs_log_debug("Pattern '%s' replaced with regex '%s'.\n", pattern, - result); - - *regex = result; - return 1; -} - -/** - * parse_time - Convert a time abbreviation to seconds - * @string: The string to be converted - * @since: The absolute time referred to - * - * Strings representing times will be converted into a time_t. The numbers will - * be regarded as seconds unless suffixed. - * - * Suffix Description - * [yY] Year - * [mM] Month - * [wW] Week - * [dD] Day - * [sS] Second - * - * Therefore, passing "1W" will return the time_t representing 1 week ago. - * - * Notes: - * Only the first character of the suffix is read. - * If parse_time fails, @since will not be changed - * - * Return: 1 Success - * 0 Error, the string was malformed - */ -static int parse_time(const char *value, time_t *since) -{ - long long result; - time_t now; - char *suffix = NULL; - - if (!value || !since) - return -1; - - ntfs_log_trace("Parsing time '%s' ago.\n", value); - - result = strtoll(value, &suffix, 10); - if (result < 0 || errno == ERANGE) { - ntfs_log_error("Invalid time '%s'.\n", value); - return 0; - } - - if (!suffix) { - ntfs_log_error("Internal error, strtoll didn't return a suffix.\n"); - return 0; - } - - if (strlen(suffix) > 1) { - ntfs_log_error("Invalid time suffix '%s'. Use Y, M, W, D or H.\n", suffix); - return 0; - } - - switch (suffix[0]) { - case 'y': case 'Y': result *= 12; - case 'm': case 'M': result *= 4; - case 'w': case 'W': result *= 7; - case 'd': case 'D': result *= 24; - case 'h': case 'H': result *= 3600; - case 0: - break; - - default: - ntfs_log_error("Invalid time suffix '%s'. Use Y, M, W, D or H.\n", suffix); - return 0; - } - - now = time(NULL); - - ntfs_log_debug("Time now = %lld, Time then = %lld.\n", (long long) now, - (long long) result); - *since = now - result; - return 1; -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char *argv[]) -{ - static const char *sopt = "-b:Cc:d:fh?i:m:o:OPp:sS:t:TuqvV"; - static const struct option lopt[] = { - { "byte", required_argument, NULL, 'b' }, - { "case", no_argument, NULL, 'C' }, - { "copy", required_argument, NULL, 'c' }, - { "destination", required_argument, NULL, 'd' }, - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - { "inodes", required_argument, NULL, 'i' }, - //{ "interactive", no_argument, NULL, 'I' }, - { "match", required_argument, NULL, 'm' }, - { "optimistic", no_argument, NULL, 'O' }, - { "output", required_argument, NULL, 'o' }, - { "parent", no_argument, NULL, 'P' }, - { "percentage", required_argument, NULL, 'p' }, - { "quiet", no_argument, NULL, 'q' }, - { "scan", no_argument, NULL, 's' }, - { "size", required_argument, NULL, 'S' }, - { "time", required_argument, NULL, 't' }, - { "truncate", no_argument, NULL, 'T' }, - { "undelete", no_argument, NULL, 'u' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - char *end = NULL; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - - opterr = 0; /* We'll handle the errors, thank you. */ - - opts.mode = MODE_NONE; - opts.uinode = -1; - opts.percent = -1; - opts.fillbyte = -1; - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opts.device) { - opts.device = argv[optind-1]; - } else { - opts.device = NULL; - err++; - } - break; - case 'b': - if (opts.fillbyte == (char)-1) { - end = NULL; - opts.fillbyte = strtol(optarg, &end, 0); - if (end && *end) - err++; - } else { - err++; - } - break; - case 'C': - opts.match_case++; - break; - case 'c': - if (opts.mode == MODE_NONE) { - if (!utils_parse_range(optarg, - &opts.mft_begin, &opts.mft_end, TRUE)) - err++; - opts.mode = MODE_COPY; - } else { - opts.mode = MODE_ERROR; - } - break; - case 'd': - if (!opts.dest) - opts.dest = optarg; - else - err++; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (ntfs_log_parse_option (argv[optind-1])) - break; - help++; - break; - case 'i': - end = NULL; - /* parse inodes */ - if (parse_inode_arg() == -1) - err++; - if (end && *end) - err++; - break; - case 'm': - if (!opts.match) { - if (!transform(optarg, &opts.match)) { - err++; - } else { - /* set regex-flag on true ;) */ - with_regex= 1; - } - } else { - err++; - } - break; - case 'o': - if (!opts.output) { - opts.output = optarg; - } else { - err++; - } - break; - case 'O': - if (!opts.optimistic) { - opts.optimistic++; - } else { - err++; - } - break; - case 'P': - if (!opts.parent) { - opts.parent++; - } else { - err++; - } - break; - case 'p': - if (opts.percent == -1) { - end = NULL; - opts.percent = strtol(optarg, &end, 0); - if (end && ((*end != '%') && (*end != 0))) - err++; - } else { - err++; - } - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 's': - if (opts.mode == MODE_NONE) - opts.mode = MODE_SCAN; - else - opts.mode = MODE_ERROR; - break; - case 'S': - if ((opts.size_begin > 0) || (opts.size_end > 0) || - !utils_parse_range(optarg, &opts.size_begin, - &opts.size_end, TRUE)) { - err++; - } - break; - case 't': - if (opts.since == 0) { - if (!parse_time(optarg, &opts.since)) - err++; - } else { - err++; - } - break; - case 'T': - opts.truncate++; - break; - case 'u': - if (opts.mode == MODE_NONE) { - opts.mode = MODE_UNDELETE; - } else { - opts.mode = MODE_ERROR; - } - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - case 'V': - ver++; - break; - default: - if (((optopt == 'b') || (optopt == 'c') || - (optopt == 'd') || (optopt == 'm') || - (optopt == 'o') || (optopt == 'p') || - (optopt == 'S') || (optopt == 't') || - (optopt == 'u')) && (!optarg)) { - ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]); - } else { - ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]); - } - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if (opts.device == NULL) { - if (argc > 1) - ntfs_log_error("You must specify exactly one device.\n"); - err++; - } - - if (opts.mode == MODE_NONE) { - opts.mode = MODE_SCAN; - } - - switch (opts.mode) { - case MODE_SCAN: - if (opts.output || opts.dest || opts.truncate || - (opts.fillbyte != (char)-1)) { - ntfs_log_error("Scan can only be used with --percent, " - "--match, --ignore-case, --size and --time.\n"); - err++; - } - if (opts.match_case && !opts.match) { - ntfs_log_error("The --case option doesn't make sense without the --match option\n"); - err++; - } - break; - - case MODE_UNDELETE: - /*if ((opts.percent != -1) || (opts.size_begin > 0) || (opts.size_end > 0)) { - ntfs_log_error("Undelete can only be used with " - "--output, --destination, --byte and --truncate.\n"); - err++; - }*/ - break; - case MODE_COPY: - if ((opts.fillbyte != (char)-1) || opts.truncate || - (opts.percent != -1) || - opts.match || opts.match_case || - (opts.size_begin > 0) || - (opts.size_end > 0)) { - ntfs_log_error("Copy can only be used with --output and --destination.\n"); - err++; - } - break; - default: - ntfs_log_error("You can only select one of Scan, Undelete or Copy.\n"); - err++; - } - - if ((opts.percent < -1) || (opts.percent > 100)) { - ntfs_log_error("Percentage value must be in the range 0 - 100.\n"); - err++; - } - - if (opts.quiet) { - if (opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at the same time.\n"); - err++; - } else if (opts.mode == MODE_SCAN) { - ntfs_log_error("You may not use --quiet when scanning a volume.\n"); - err++; - } - } - - if (opts.parent && !opts.verbose) { - ntfs_log_error("To use --parent, you must also use --verbose.\n"); - err++; - } - } - - if (opts.fillbyte == (char)-1) - opts.fillbyte = 0; - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - -/** - * free_file - Release the resources used by a file object - * @file: The unwanted file object - * - * This will free up the memory used by a file object and iterate through the - * object's children, freeing their resources too. - * - * Return: none - */ -static void free_file(struct ufile *file) -{ - struct list_head *item, *tmp; - - if (!file) - return; - - list_for_each_safe(item, tmp, &file->name) { /* List of filenames */ - struct filename *f = list_entry(item, struct filename, list); - ntfs_log_debug("freeing filename '%s'", f->name ? f->name : - NONE); - if (f->name) - free(f->name); - if (f->parent_name) { - ntfs_log_debug(" and parent filename '%s'", - f->parent_name); - free(f->parent_name); - } - ntfs_log_debug(".\n"); - free(f); - } - - list_for_each_safe(item, tmp, &file->data) { /* List of data streams */ - struct data *d = list_entry(item, struct data, list); - ntfs_log_debug("Freeing data stream '%s'.\n", d->name ? - d->name : UNNAMED); - if (d->name) - free(d->name); - if (d->runlist) - free(d->runlist); - free(d); - } - - free(file->mft); - free(file); -} - -/** - * verify_parent - confirm a record is parent of a file - * @name: a filename of the file - * @rec: the mft record of the possible parent - * - * Check that @rec is the parent of the file represented by @name. - * If @rec is a directory, but it is created after @name, then we - * can't determine whether @rec is really @name's parent. - * - * Return: @rec's filename, either same name space as @name or lowest space. - * NULL if can't determine parenthood or on error. - */ -static FILE_NAME_ATTR* verify_parent(struct filename* name, MFT_RECORD* rec) -{ - ATTR_RECORD *attr30; - FILE_NAME_ATTR *filename_attr = NULL, *lowest_space_name = NULL; - ntfs_attr_search_ctx *ctx; - int found_same_space = 1; - - if (!name || !rec) - return NULL; - - if (!(rec->flags & MFT_RECORD_IS_DIRECTORY)) { - return NULL; - } - - ctx = ntfs_attr_get_search_ctx(NULL, rec); - if (!ctx) { - ntfs_log_error("ERROR: Couldn't create a search context.\n"); - return NULL; - } - - attr30 = find_attribute(AT_FILE_NAME, ctx); - if (!attr30) { - return NULL; - } - - filename_attr = (FILE_NAME_ATTR*)((char*)attr30 + le16_to_cpu(attr30->u.res.value_offset)); - /* if name is older than this dir -> can't determine */ - if (ntfs2utc(filename_attr->creation_time) > name->date_c) { - return NULL; - } - - if (filename_attr->file_name_type != name->name_space) { - found_same_space = 0; - lowest_space_name = filename_attr; - - while (!found_same_space && (attr30 = find_attribute(AT_FILE_NAME, ctx))) { - filename_attr = (FILE_NAME_ATTR*)((char*)attr30 + le16_to_cpu(attr30->u.res.value_offset)); - - if (filename_attr->file_name_type == name->name_space) { - found_same_space = 1; - } else { - if (filename_attr->file_name_type < lowest_space_name->file_name_type) { - lowest_space_name = filename_attr; - } - } - } - } - - ntfs_attr_put_search_ctx(ctx); - - return (found_same_space ? filename_attr : lowest_space_name); -} - -/** - * get_parent_name - Find the name of a file's parent. - * @name: the filename whose parent's name to find - */ -static void get_parent_name(struct filename* name, ntfs_volume* vol) -{ - ntfs_attr* mft_data; - MFT_RECORD* rec; - FILE_NAME_ATTR* filename_attr; - long long inode_num; - - if (!name || !vol) - return; - - rec = calloc(1, vol->mft_record_size); - if (!rec) { - ntfs_log_error("ERROR: Couldn't allocate memory in " - "get_parent_name()\n"); - return; - } - - mft_data = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); - if (!mft_data) { - ntfs_log_perror("ERROR: Couldn't open $MFT/$DATA"); - } else { - inode_num = MREF_LE(name->parent_mref); - - if (ntfs_attr_pread(mft_data, vol->mft_record_size * inode_num, - vol->mft_record_size, rec) < 1) { - ntfs_log_error("ERROR: Couldn't read MFT Record %lld" - ".\n", inode_num); - } else if ((filename_attr = verify_parent(name, rec))) { - if (ntfs_ucstombs(filename_attr->file_name, - filename_attr->file_name_length, - &name->parent_name, 0) < 0) { - ntfs_log_debug("ERROR: Couldn't translate " - "filename to current " - "locale.\n"); - name->parent_name = NULL; - } - } - } - - if (mft_data) { - ntfs_attr_close(mft_data); - } - - if (rec) { - free(rec); - } - - return; -} - -/** - * get_filenames - Read an MFT Record's $FILENAME attributes - * @file: The file object to work with - * - * A single file may have more than one filename. This is quite common. - * Windows creates a short DOS name for each long name, e.g. LONGFI~1.XYZ, - * LongFiLeName.xyZ. - * - * The filenames that are found are put in filename objects and added to a - * linked list of filenames in the file object. For convenience, the unicode - * filename is converted into the current locale and stored in the filename - * object. - * - * One of the filenames is picked (the one with the lowest numbered namespace) - * and its locale friendly name is put in pref_name. - * - * Return: n The number of $FILENAME attributes found - * -1 Error - */ -static int get_filenames(struct ufile *file, ntfs_volume* vol) -{ - ATTR_RECORD *rec; - FILE_NAME_ATTR *attr; - ntfs_attr_search_ctx *ctx; - struct filename *name; - int count = 0; - int space = 4; - - if (!file) - return -1; - - ctx = ntfs_attr_get_search_ctx(NULL, file->mft); - if (!ctx) - return -1; - - while ((rec = find_attribute(AT_FILE_NAME, ctx))) { - /* We know this will always be resident. */ - attr = (FILE_NAME_ATTR *)((char *)rec + - le16_to_cpu(rec->u.res.value_offset)); - - name = calloc(1, sizeof(*name)); - if (!name) { - ntfs_log_error("ERROR: Couldn't allocate memory in " - "get_filenames().\n"); - count = -1; - break; - } - - name->uname = attr->file_name; - name->uname_len = attr->file_name_length; - name->name_space = attr->file_name_type; - name->size_alloc = sle64_to_cpu(attr->allocated_size); - name->size_data = sle64_to_cpu(attr->data_size); - name->flags = attr->file_attributes; - - name->date_c = ntfs2utc(attr->creation_time); - name->date_a = ntfs2utc(attr->last_data_change_time); - name->date_m = ntfs2utc(attr->last_mft_change_time); - name->date_r = ntfs2utc(attr->last_access_time); - - if (ntfs_ucstombs(name->uname, name->uname_len, &name->name, - 0) < 0) { - ntfs_log_debug("ERROR: Couldn't translate filename to " - "current locale.\n"); - } - - name->parent_name = NULL; - - if (opts.parent) { - name->parent_mref = attr->parent_directory; - get_parent_name(name, vol); - } - - if (name->name_space < space) { - file->pref_name = name->name; - file->pref_pname = name->parent_name; - space = name->name_space; - } - - file->max_size = max(file->max_size, name->size_alloc); - file->max_size = max(file->max_size, name->size_data); - - list_add_tail(&name->list, &file->name); - count++; - } - - ntfs_attr_put_search_ctx(ctx); - ntfs_log_debug("File has %d names.\n", count); - return count; -} - -/** - * get_data - Read an MFT Record's $DATA attributes - * @file: The file object to work with - * @vol: An ntfs volume obtained from ntfs_mount - * - * A file may have more than one data stream. All files will have an unnamed - * data stream which contains the file's data. Some Windows applications store - * extra information in a separate stream. - * - * The streams that are found are put in data objects and added to a linked - * list of data streams in the file object. - * - * Return: n The number of $FILENAME attributes found - * -1 Error - */ -static int get_data(struct ufile *file, ntfs_volume *vol) -{ - ATTR_RECORD *rec; - ntfs_attr_search_ctx *ctx; - int count = 0; - struct data *data; - - if (!file) - return -1; - - ctx = ntfs_attr_get_search_ctx(NULL, file->mft); - if (!ctx) - return -1; - - while ((rec = find_attribute(AT_DATA, ctx))) { - data = calloc(1, sizeof(*data)); - if (!data) { - ntfs_log_error("ERROR: Couldn't allocate memory in " - "get_data().\n"); - count = -1; - break; - } - - data->resident = !rec->non_resident; - data->compressed = (rec->flags & ATTR_IS_COMPRESSED) ? 1 : 0; - data->encrypted = (rec->flags & ATTR_IS_ENCRYPTED) ? 1 : 0; - - if (rec->name_length) { - data->uname = (ntfschar *)((char *)rec + - le16_to_cpu(rec->name_offset)); - data->uname_len = rec->name_length; - - if (ntfs_ucstombs(data->uname, data->uname_len, - &data->name, 0) < 0) { - ntfs_log_error("ERROR: Cannot translate name " - "into current locale.\n"); - } - } - - if (data->resident) { - data->size_data = le32_to_cpu(rec->u.res.value_length); - data->data = (char*)rec + - le16_to_cpu(rec->u.res.value_offset); - } else { - data->size_alloc = sle64_to_cpu(rec->u.nonres.allocated_size); - data->size_data = sle64_to_cpu(rec->u.nonres.data_size); - data->size_init = sle64_to_cpu(rec->u.nonres.initialized_size); - data->size_vcn = sle64_to_cpu(rec->u.nonres.highest_vcn) + 1; - } - - data->runlist = ntfs_mapping_pairs_decompress(vol, rec, NULL); - if (!data->runlist) { - ntfs_log_debug("Couldn't decompress the data runs.\n"); - } - - file->max_size = max(file->max_size, data->size_data); - file->max_size = max(file->max_size, data->size_init); - - list_add_tail(&data->list, &file->data); - count++; - } - - ntfs_attr_put_search_ctx(ctx); - ntfs_log_debug("File has %d data streams.\n", count); - return count; -} - -/** - * read_record - Read an MFT record into memory - * @vol: An ntfs volume obtained from ntfs_mount - * @record: The record number to read - * - * Read the specified MFT record and gather as much information about it as - * possible. - * - * Return: Pointer A ufile object containing the results - * NULL Error - */ -static struct ufile * read_record(ntfs_volume *vol, long long record) -{ - ATTR_RECORD *attr10, *attr20, *attr90; - struct ufile *file; - ntfs_attr *mft; - - if (!vol) - return NULL; - - file = calloc(1, sizeof(*file)); - if (!file) { - ntfs_log_error("ERROR: Couldn't allocate memory in read_record()\n"); - return NULL; - } - - INIT_LIST_HEAD(&file->name); - INIT_LIST_HEAD(&file->data); - file->inode = record; - - file->mft = malloc(vol->mft_record_size); - if (!file->mft) { - ntfs_log_error("ERROR: Couldn't allocate memory in read_record()\n"); - free_file(file); - return NULL; - } - - mft = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); - if (!mft) { - ntfs_log_perror("ERROR: Couldn't open $MFT/$DATA"); - free_file(file); - return NULL; - } - - if (ntfs_attr_mst_pread(mft, vol->mft_record_size * record, 1, vol->mft_record_size, file->mft) < 1) { - ntfs_log_error("ERROR: Couldn't read MFT Record %lld.\n", record); - ntfs_attr_close(mft); - free_file(file); - return NULL; - } - - ntfs_attr_close(mft); - mft = NULL; - - attr10 = find_first_attribute(AT_STANDARD_INFORMATION, file->mft); - attr20 = find_first_attribute(AT_ATTRIBUTE_LIST, file->mft); - attr90 = find_first_attribute(AT_INDEX_ROOT, file->mft); - - ntfs_log_debug("Attributes present: %s %s %s.\n", attr10?"0x10":"", - attr20?"0x20":"", attr90?"0x90":""); - - if (attr10) { - STANDARD_INFORMATION *si; - si = (STANDARD_INFORMATION *) ((char *) attr10 + le16_to_cpu(attr10->u.res.value_offset)); - file->date = ntfs2utc(si->last_data_change_time); - } - - if (attr20 || !attr10) - file->attr_list = 1; - if (attr90) - file->directory = 1; - - if (get_filenames(file, vol) < 0) { - ntfs_log_error("ERROR: Couldn't get filenames.\n"); - } - if (get_data(file, vol) < 0) { - ntfs_log_error("ERROR: Couldn't get data streams.\n"); - } - - return file; -} - -/** - * calc_percentage - Calculate how much of the file is recoverable - * @file: The file object to work with - * @vol: An ntfs volume obtained from ntfs_mount - * - * Read through all the $DATA streams and determine if each cluster in each - * stream is still free disk space. This is just measuring the potential for - * recovery. The data may have still been overwritten by a another file which - * was then deleted. - * - * Files with a resident $DATA stream will have a 100% potential. - * - * N.B. If $DATA attribute spans more than one MFT record (i.e. badly - * fragmented) then only the data in this segment will be used for the - * calculation. - * - * N.B. Currently, compressed and encrypted files cannot be recovered, so they - * will return 0%. - * - * Return: n The percentage of the file that _could_ be recovered - * -1 Error - */ -static int calc_percentage(struct ufile *file, ntfs_volume *vol) -{ - runlist_element *rl = NULL; - struct list_head *pos; - struct data *data; - long long i, j; - long long start, end; - int clusters_inuse, clusters_free; - int percent = 0; - - if (!file || !vol) - return -1; - - if (file->directory) { - ntfs_log_debug("Found a directory: not recoverable.\n"); - return 0; - } - - if (list_empty(&file->data)) { - ntfs_log_verbose("File has no data streams.\n"); - return 0; - } - - list_for_each(pos, &file->data) { - data = list_entry(pos, struct data, list); - clusters_inuse = 0; - clusters_free = 0; - - if (data->encrypted) { - ntfs_log_verbose("File is encrypted, recovery is " - "impossible.\n"); - continue; - } - - if (data->compressed) { - ntfs_log_verbose("File is compressed, recovery not yet " - "implemented.\n"); - continue; - } - - if (data->resident) { - ntfs_log_verbose("File is resident, therefore " - "recoverable.\n"); - percent = 100; - data->percent = 100; - continue; - } - - rl = data->runlist; - if (!rl) { - ntfs_log_verbose("File has no runlist, hence no data." - "\n"); - continue; - } - - if (rl[0].length <= 0) { - ntfs_log_verbose("File has an empty runlist, hence no " - "data.\n"); - continue; - } - - if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */ - ntfs_log_verbose("Missing segment at beginning, %lld " - "clusters\n", (long long)rl[0].length); - clusters_inuse += rl[0].length; - rl++; - } - - for (i = 0; rl[i].length > 0; i++) { - if (rl[i].lcn == LCN_RL_NOT_MAPPED) { - ntfs_log_verbose("Missing segment at end, %lld " - "clusters\n", - (long long)rl[i].length); - clusters_inuse += rl[i].length; - continue; - } - - if (rl[i].lcn == LCN_HOLE) { - clusters_free += rl[i].length; - continue; - } - - start = rl[i].lcn; - end = rl[i].lcn + rl[i].length; - - for (j = start; j < end; j++) { - if (utils_cluster_in_use(vol, j)) - clusters_inuse++; - else - clusters_free++; - } - } - - if ((clusters_inuse + clusters_free) == 0) { - ntfs_log_error("ERROR: Unexpected error whilst " - "calculating percentage for inode %lld\n", - file->inode); - continue; - } - - data->percent = (clusters_free * 100) / - (clusters_inuse + clusters_free); - - percent = max(percent, data->percent); - } - - ntfs_log_verbose("File is %d%% recoverable\n", percent); - return percent; -} - -/** - * dump_record - Print everything we know about an MFT record - * @file: The file to work with - * - * Output the contents of the file object. This will print everything that has - * been read from the MFT record, or implied by various means. - * - * Because of the redundant nature of NTFS, there will be some duplication of - * information, though it will have been read from different sources. - * - * N.B. If the filename is missing, or couldn't be converted to the current - * locale, "" will be displayed. - * - * Return: none - */ -static void dump_record(struct ufile *file) -{ - char buffer[20]; - const char *name; - struct list_head *item; - int i; - - if (!file) - return; - - ntfs_log_quiet("MFT Record %lld\n", file->inode); - ntfs_log_quiet("Type: %s\n", (file->directory) ? "Directory" : "File"); - strftime(buffer, sizeof(buffer), "%F %R", localtime(&file->date)); - ntfs_log_quiet("Date: %s\n", buffer); - - if (file->attr_list) - ntfs_log_quiet("Metadata may span more than one MFT record\n"); - - list_for_each(item, &file->name) { - struct filename *f = list_entry(item, struct filename, list); - - if (f->name) - name = f->name; - else - name = NONE; - - ntfs_log_quiet("Filename: (%d) %s\n", f->name_space, f->name); - ntfs_log_quiet("File Flags: "); - if (f->flags & FILE_ATTR_SYSTEM) - ntfs_log_quiet("System "); - if (f->flags & FILE_ATTR_DIRECTORY) - ntfs_log_quiet("Directory "); - if (f->flags & FILE_ATTR_SPARSE_FILE) - ntfs_log_quiet("Sparse "); - if (f->flags & FILE_ATTR_REPARSE_POINT) - ntfs_log_quiet("Reparse "); - if (f->flags & FILE_ATTR_COMPRESSED) - ntfs_log_quiet("Compressed "); - if (f->flags & FILE_ATTR_ENCRYPTED) - ntfs_log_quiet("Encrypted "); - if (!(f->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_DIRECTORY | - FILE_ATTR_SPARSE_FILE | FILE_ATTR_REPARSE_POINT | - FILE_ATTR_COMPRESSED | FILE_ATTR_ENCRYPTED))) { - ntfs_log_quiet("%s", NONE); - } - - ntfs_log_quiet("\n"); - - if (opts.parent) { - ntfs_log_quiet("Parent: %s\n", f->parent_name ? - f->parent_name : ""); - } - - ntfs_log_quiet("Size alloc: %lld\n", f->size_alloc); - ntfs_log_quiet("Size data: %lld\n", f->size_data); - - strftime(buffer, sizeof(buffer), "%F %R", - localtime(&f->date_c)); - ntfs_log_quiet("Date C: %s\n", buffer); - strftime(buffer, sizeof(buffer), "%F %R", - localtime(&f->date_a)); - ntfs_log_quiet("Date A: %s\n", buffer); - strftime(buffer, sizeof(buffer), "%F %R", - localtime(&f->date_m)); - ntfs_log_quiet("Date M: %s\n", buffer); - strftime(buffer, sizeof(buffer), "%F %R", - localtime(&f->date_r)); - ntfs_log_quiet("Date R: %s\n", buffer); - } - - ntfs_log_quiet("Data Streams:\n"); - list_for_each(item, &file->data) { - struct data *d = list_entry(item, struct data, list); - ntfs_log_quiet("Name: %s\n", (d->name) ? d->name : UNNAMED); - ntfs_log_quiet("Flags: "); - if (d->resident) ntfs_log_quiet("Resident\n"); - if (d->compressed) ntfs_log_quiet("Compressed\n"); - if (d->encrypted) ntfs_log_quiet("Encrypted\n"); - if (!d->resident && !d->compressed && !d->encrypted) - ntfs_log_quiet("None\n"); - else - ntfs_log_quiet("\n"); - - ntfs_log_quiet("Size alloc: %lld\n", d->size_alloc); - ntfs_log_quiet("Size data: %lld\n", d->size_data); - ntfs_log_quiet("Size init: %lld\n", d->size_init); - ntfs_log_quiet("Size vcn: %lld\n", d->size_vcn); - - ntfs_log_quiet("Data runs:\n"); - if ((!d->runlist) || (d->runlist[0].length <= 0)) { - ntfs_log_quiet(" None\n"); - } else { - for (i = 0; d->runlist[i].length > 0; i++) { - ntfs_log_quiet(" %lld @ %lld\n", - (long long)d->runlist[i].length, - (long long)d->runlist[i].lcn); - } - } - - ntfs_log_quiet("Amount potentially recoverable %d%%\n", - d->percent); - } - - ntfs_log_quiet("________________________________________\n\n"); -} - -/** - * list_record - Print a one line summary of the file - * @file: The file to work with - * - * Print a one line description of a file. - * - * Inode Flags %age Date Size Filename - * - * The output will contain the file's inode number (MFT Record), some flags, - * the percentage of the file that is recoverable, the last modification date, - * the size and the filename. - * - * The flags are F/D = File/Directory, N/R = Data is (Non-)Resident, - * C = Compressed, E = Encrypted, ! = Metadata may span multiple records. - * - * N.B. The file size is stored in many forms in several attributes. This - * display the largest it finds. - * - * N.B. If the filename is missing, or couldn't be converted to the current - * locale, "" will be displayed. - * - * Return: none - */ -static void list_record(struct ufile *file) -{ - char buffer[20]; - struct list_head *item; - const char *name = NULL; - long long size = 0; - int percent = 0; - - char flagd = '.', flagr = '.', flagc = '.', flagx = '.'; - - strftime(buffer, sizeof(buffer), "%F", localtime(&file->date)); - - if (file->attr_list) - flagx = '!'; - - if (file->directory) - flagd = 'D'; - else - flagd = 'F'; - - list_for_each(item, &file->data) { - struct data *d = list_entry(item, struct data, list); - - if (!d->name) { - if (d->resident) - flagr = 'R'; - else - flagr = 'N'; - if (d->compressed) - flagc = 'C'; - if (d->encrypted) - flagc = 'E'; - - percent = max(percent, d->percent); - } - - size = max(size, d->size_data); - size = max(size, d->size_init); - } - - if (file->pref_name) - name = file->pref_name; - else - name = NONE; - - ntfs_log_quiet("%-8lld %c%c%c%c %3d%% %s %9lld %s\n", - file->inode, flagd, flagr, flagc, flagx, - percent, buffer, size, name); - -} - -/** - * name_match - Does a file have a name matching a regex - * @re: The regular expression object - * @file: The file to be tested - * - * Iterate through the file's $FILENAME attributes and compare them against the - * regular expression, created with regcomp. - * - * Return: 1 There is a matching filename. - * 0 There is no match. - */ -static int name_match(regex_t *re, struct ufile *file) -{ - struct list_head *item; - int result; - - if (!re || !file) - return 0; - - list_for_each(item, &file->name) { - struct filename *f = list_entry(item, struct filename, list); - - if (!f->name) - continue; - result = regexec(re, f->name, 0, NULL, 0); - if (result < 0) { - ntfs_log_perror("Couldn't compare filename with regex"); - return 0; - } else if (result == REG_NOERROR) { - ntfs_log_debug("Found a matching filename.\n"); - return 1; - } - } - - ntfs_log_debug("Filename '%s' doesn't match regex.\n", file->pref_name); - return 0; -} - -/** - * write_data - Write out a block of data - * @fd: File descriptor to write to - * @buffer: Data to write - * @bufsize: Amount of data to write - * - * Write a block of data to a file descriptor. - * - * Return: -1 Error, something went wrong - * 0 Success, all the data was written - */ -static unsigned int write_data(int fd, const char *buffer, - unsigned int bufsize) -{ - ssize_t result1, result2; - - if (!buffer) { - errno = EINVAL; - return -1; - } - - result1 = write(fd, buffer, bufsize); - if ((result1 == (ssize_t) bufsize) || (result1 < 0)) - return result1; - - /* Try again with the rest of the buffer */ - buffer += result1; - bufsize -= result1; - - result2 = write(fd, buffer, bufsize); - if (result2 < 0) - return result1; - - return result1 + result2; -} - -/** - * create_pathname - Create a path/file from some components - * @dir: Directory in which to create the file (optional) - * @name: Filename to give the file (optional) - * @stream: Name of the stream (optional) - * @buffer: Store the result here - * @bufsize: Size of buffer - * - * Create a filename from various pieces. The output will be of the form: - * dir/file - * dir/file:stream - * file - * file:stream - * - * All the components are optional. If the name is missing, "unknown" will be - * used. If the directory is missing the file will be created in the current - * directory. If the stream name is present it will be appended to the - * filename, delimited by a colon. - * - * N.B. If the buffer isn't large enough the name will be truncated. - * - * Return: n Length of the allocated name - */ -static int create_pathname(const char *dir, const char *name, - const char *stream, char *buffer, int bufsize) -{ - if (!name) - name = UNKNOWN; - - if (dir) - if (stream) - snprintf(buffer, bufsize, "%s/%s:%s", dir, name, stream); - else - snprintf(buffer, bufsize, "%s/%s", dir, name); - else - if (stream) - snprintf(buffer, bufsize, "%s:%s", name, stream); - else - snprintf(buffer, bufsize, "%s", name); - - return strlen(buffer); -} - -/** - * open_file - Open a file to write to - * @pathname: Path, name and stream of the file to open - * - * Create a file and return the file descriptor. - * - * N.B. If option force is given and existing file will be overwritten. - * - * Return: -1 Error, failed to create the file - * n Success, this is the file descriptor - */ -static int open_file(const char *pathname) -{ - int flags; - - ntfs_log_verbose("Creating file: %s\n", pathname); - - if (opts.force) - flags = O_RDWR | O_CREAT | O_TRUNC; - else - flags = O_RDWR | O_CREAT | O_EXCL; - - return open(pathname, flags, S_IRUSR | S_IWUSR); -} - -/** - * set_date - Set the file's date and time - * @pathname: Path and name of the file to alter - * @date: Date and time to set - * - * Give a file a particular date and time. - * - * Return: 1 Success, set the file's date and time - * 0 Error, failed to change the file's date and time - */ -static int set_date(const char *pathname, time_t date) -{ - struct utimbuf ut; - - if (!pathname) - return 0; - - ut.actime = date; - ut.modtime = date; - if (utime(pathname, &ut)) { - ntfs_log_error("ERROR: Couldn't set the file's date and time\n"); - return 0; - } - return 1; -} - -/** - * undelete_file - Recover a deleted file from an NTFS volume - * @vol: An ntfs volume obtained from ntfs_mount - * @inode: MFT Record number to be recovered - * - * Read an MFT Record and try an recover any data associated with it. Some of - * the clusters may be in use; these will be filled with zeros or the fill byte - * supplied in the options. - * - * Each data stream will be recovered and saved to a file. The file's name will - * be the original filename and it will be written to the current directory. - * Any named data stream will be saved as filename:streamname. - * - * The output file's name and location can be altered by using the command line - * options. - * - * N.B. We cannot tell if someone has overwritten some of the data since the - * file was deleted. - * - * Return: 0 Error, something went wrong - * 1 Success, the data was recovered - */ -static int undelete_file(ntfs_volume *vol, long long inode) -{ - char pathname[256]; - char *buffer = NULL; - unsigned int bufsize; - struct ufile *file; - int i, j; - long long start, end; - runlist_element *rl; - struct list_head *item; - int fd = -1; - long long k; - int result = 0; - char *name; - long long cluster_count; /* I'll need this variable (see below). +mabs */ - - if (!vol) - return 0; - - /* try to get record */ - file = read_record(vol, inode); - if (!file || !file->mft) { - ntfs_log_error("Can't read info from mft record %lld.\n", inode); - return 0; - } - - /* if flag was not set, print file informations */ - if (avoid_duplicate_printing == 0) { - if (opts.verbose) { - dump_record(file); - } else { - list_record(file); - //ntfs_log_quiet("\n"); - } - } - - bufsize = vol->cluster_size; - buffer = malloc(bufsize); - if (!buffer) - goto free; - - /* calc_percentage() must be called before dump_record() or - * list_record(). Otherwise, when undeleting, a file will always be - * listed as 0% recoverable even if successfully undeleted. +mabs - */ - if (file->mft->flags & MFT_RECORD_IN_USE) { - ntfs_log_error("Record is in use by the mft\n"); - if (!opts.force) { - free(buffer); - free_file(file); - return 0; - } - ntfs_log_verbose("Forced to continue.\n"); - } - - if (calc_percentage(file, vol) == 0) { - ntfs_log_quiet("File has no recoverable data.\n"); - goto free; - } - - if (list_empty(&file->data)) { - ntfs_log_quiet("File has no data. There is nothing to recover.\n"); - goto free; - } - - list_for_each(item, &file->data) { - struct data *d = list_entry(item, struct data, list); - - if (opts.output) - name = opts.output; - else - name = file->pref_name; - - create_pathname(opts.dest, name, d->name, pathname, sizeof(pathname)); - if (d->resident) { - fd = open_file(pathname); - if (fd < 0) { - ntfs_log_perror("Couldn't create file"); - goto free; - } - - ntfs_log_verbose("File has resident data.\n"); - if (write_data(fd, d->data, d->size_data) < d->size_data) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - - if (close(fd) < 0) { - ntfs_log_perror("Close failed"); - } - fd = -1; - } else { - rl = d->runlist; - if (!rl) { - ntfs_log_verbose("File has no runlist, hence no data.\n"); - continue; - } - - if (rl[0].length <= 0) { - ntfs_log_verbose("File has an empty runlist, hence no data.\n"); - continue; - } - - fd = open_file(pathname); - if (fd < 0) { - ntfs_log_perror("Couldn't create output file"); - goto free; - } - - if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */ - ntfs_log_verbose("Missing segment at beginning, %lld " - "clusters.\n", - (long long)rl[0].length); - memset(buffer, opts.fillbyte, bufsize); - for (k = 0; k < rl[0].length * vol->cluster_size; k += bufsize) { - if (write_data(fd, buffer, bufsize) < bufsize) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - } - } - - cluster_count = 0LL; - for (i = 0; rl[i].length > 0; i++) { - - if (rl[i].lcn == LCN_RL_NOT_MAPPED) { - ntfs_log_verbose("Missing segment at end, " - "%lld clusters.\n", - (long long)rl[i].length); - memset(buffer, opts.fillbyte, bufsize); - for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) { - if (write_data(fd, buffer, bufsize) < bufsize) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - cluster_count++; - } - continue; - } - - if (rl[i].lcn == LCN_HOLE) { - ntfs_log_verbose("File has a sparse section.\n"); - memset(buffer, 0, bufsize); - for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) { - if (write_data(fd, buffer, bufsize) < bufsize) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - } - continue; - } - - start = rl[i].lcn; - end = rl[i].lcn + rl[i].length; - - for (j = start; j < end; j++) { - if (utils_cluster_in_use(vol, j) && !opts.optimistic) { - memset(buffer, opts.fillbyte, bufsize); - if (write_data(fd, buffer, bufsize) < bufsize) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - } else { - if (ntfs_cluster_read(vol, j, 1, buffer) < 1) { - ntfs_log_perror("Read failed"); - close(fd); - goto free; - } - if (write_data(fd, buffer, bufsize) < bufsize) { - ntfs_log_perror("Write failed"); - close(fd); - goto free; - } - cluster_count++; - } - } - } - ntfs_log_quiet("\n"); - - /* - * The following block of code implements the --truncate option. - * Its semantics are as follows: - * IF opts.truncate is set AND data stream currently being recovered is - * non-resident AND data stream has no holes (100% recoverability) AND - * 0 <= (data->size_alloc - data->size_data) <= vol->cluster_size AND - * cluster_count * vol->cluster_size == data->size_alloc THEN file - * currently being written is truncated to data->size_data bytes before - * it's closed. - * This multiple checks try to ensure that only files with consistent - * values of size/occupied clusters are eligible for truncation. Note - * that resident streams need not be truncated, since the original code - * already recovers their exact length. +mabs - */ - if (opts.truncate) { - if (d->percent == 100 && d->size_alloc >= d->size_data && - (d->size_alloc - d->size_data) <= (long long)vol->cluster_size && - cluster_count * (long long)vol->cluster_size == d->size_alloc) { - if (ftruncate(fd, (off_t)d->size_data)) - ntfs_log_perror("Truncation failed"); - } else ntfs_log_quiet("Truncation not performed because file has an " - "inconsistent $MFT record.\n"); - } - - if (close(fd) < 0) { - ntfs_log_perror("Close failed"); - } - fd = -1; - - } - set_date(pathname, file->date); - if (d->name) - ntfs_log_quiet("Undeleted '%s:%s' successfully.\n", file->pref_name, d->name); - else - ntfs_log_quiet("Undeleted '%s' successfully.\n", file->pref_name); - } - result = 1; -free: - if (buffer) - free(buffer); - free_file(file); - return result; -} - -/** - * scan_disk - Search an NTFS volume for files that could be undeleted - * @vol: An ntfs volume obtained from ntfs_mount - * - * Read through all the MFT entries looking for deleted files. For each one - * determine how much of the data lies in unused disk space. - * - * The list can be filtered by name, size and date, using command line options. - * - * Return: -1 Error, something went wrong - * n Success, the number of recoverable files - */ -static int scan_disk(ntfs_volume *vol) -{ - s64 nr_mft_records; - const int BUFSIZE = 8192; - char *buffer = NULL; - int results = 0; - ntfs_attr *attr; - long long size; - long long bmpsize; - int i, j, k, b; - int percent; - struct ufile *file; - regex_t re; - - if (!vol) - return -1; - - attr = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0); - if (!attr) { - ntfs_log_perror("ERROR: Couldn't open $MFT/$BITMAP"); - return -1; - } - bmpsize = attr->initialized_size; - - buffer = malloc(BUFSIZE); - if (!buffer) { - ntfs_log_error("ERROR: Couldn't allocate memory in scan_disk()\n"); - results = -1; - goto out; - } - - if (opts.match) { - int flags = REG_NOSUB; - - if (!opts.match_case) - flags |= REG_ICASE; - if (regcomp(&re, opts.match, flags)) { - ntfs_log_error("ERROR: Couldn't create a regex.\n"); - goto out; - } - } - - nr_mft_records = vol->mft_na->initialized_size >> - vol->mft_record_size_bits; - - ntfs_log_quiet("Inode Flags %%age Date Size Filename\n"); - ntfs_log_quiet("---------------------------------------------------------------\n"); - for (i = 0; i < bmpsize; i += BUFSIZE) { - long long read_count = min((bmpsize - i), BUFSIZE); - size = ntfs_attr_pread(attr, i, read_count, buffer); - if (size < 0) - break; - - for (j = 0; j < size; j++) { - b = buffer[j]; - for (k = 0; k < 8; k++, b>>=1) { - if (((i+j)*8+k) >= nr_mft_records) - goto done; - if (b & 1) - continue; - file = read_record(vol, (i+j)*8+k); - if (!file) { - ntfs_log_error("Couldn't read MFT Record %d.\n", (i+j)*8+k); - continue; - } - - if ((opts.since > 0) && (file->date <= opts.since)) - goto skip; - if (opts.match && !name_match(&re, file)) - goto skip; - if (opts.size_begin && (opts.size_begin > file->max_size)) - goto skip; - if (opts.size_end && (opts.size_end < file->max_size)) - goto skip; - - percent = calc_percentage(file, vol); - if ((opts.percent == -1) || (percent >= opts.percent)) { - if (opts.verbose) - dump_record(file); - else - list_record(file); - - /* Was -u specified with no inode - so undelete file by regex */ - if (opts.mode == MODE_UNDELETE) { - if (!undelete_file(vol, file->inode)) - ntfs_log_verbose("ERROR: Failed to undelete " - "inode %lli\n!", - file->inode); - ntfs_log_info("\n"); - } - } - if (((opts.percent == -1) && (percent > 0)) || - ((opts.percent > 0) && (percent >= opts.percent))) { - results++; - } -skip: - free_file(file); - } - } - } -done: - ntfs_log_quiet("\nFiles with potentially recoverable content: %d\n", - results); -out: - if (opts.match) - regfree(&re); - free(buffer); - if (attr) - ntfs_attr_close(attr); - return results; -} - -/** - * copy_mft - Write a range of MFT Records to a file - * @vol: An ntfs volume obtained from ntfs_mount - * @mft_begin: First MFT Record to save - * @mft_end: Last MFT Record to save - * - * Read a number of MFT Records and write them to a file. - * - * Return: 0 Success, all the records were written - * 1 Error, something went wrong - */ -static int copy_mft(ntfs_volume *vol, long long mft_begin, long long mft_end) -{ - s64 nr_mft_records; - char pathname[256]; - ntfs_attr *mft; - char *buffer; - const char *name; - long long i; - int result = 1; - int fd; - - if (!vol) - return 1; - - if (mft_end < mft_begin) { - ntfs_log_error("Range to copy is backwards.\n"); - return 1; - } - - buffer = malloc(vol->mft_record_size); - if (!buffer) { - ntfs_log_error("Couldn't allocate memory in copy_mft()\n"); - return 1; - } - - mft = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); - if (!mft) { - ntfs_log_perror("Couldn't open $MFT/$DATA"); - goto free; - } - - name = opts.output; - if (!name) { - name = MFTFILE; - ntfs_log_debug("No output filename, defaulting to '%s'.\n", - name); - } - - create_pathname(opts.dest, name, NULL, pathname, sizeof(pathname)); - fd = open_file(pathname); - if (fd < 0) { - ntfs_log_perror("Couldn't open output file '%s'", name); - goto attr; - } - - nr_mft_records = vol->mft_na->initialized_size >> - vol->mft_record_size_bits; - - mft_end = min(mft_end, nr_mft_records - 1); - - ntfs_log_debug("MFT records:\n"); - ntfs_log_debug("\tTotal: %8lld\n", nr_mft_records); - ntfs_log_debug("\tBegin: %8lld\n", mft_begin); - ntfs_log_debug("\tEnd: %8lld\n", mft_end); - - for (i = mft_begin; i <= mft_end; i++) { - if (ntfs_attr_pread(mft, vol->mft_record_size * i, - vol->mft_record_size, buffer) < vol->mft_record_size) { - ntfs_log_perror("Couldn't read MFT Record %lld", i); - goto close; - } - - if (write_data(fd, buffer, vol->mft_record_size) < vol->mft_record_size) { - ntfs_log_perror("Write failed"); - goto close; - } - } - - ntfs_log_verbose("Read %lld MFT Records\n", mft_end - mft_begin + 1); - result = 0; -close: - close(fd); -attr: - ntfs_attr_close(mft); -free: - free(buffer); - return result; -} - -/** - * handle_undelete - * - * Handles the undelete - */ -static int handle_undelete(ntfs_volume *vol) -{ - int result = 1; - int i; - unsigned long long inode; - - /* Check whether (an) inode(s) was specified or at least a regex! */ - if (nr_entries == 0) { - if (with_regex == 0) { - ntfs_log_error("ERROR: NO inode(s) AND NO match-regex " - "specified!\n"); - } else { - avoid_duplicate_printing= 1; - result = !scan_disk(vol); - if (result) - ntfs_log_verbose("ERROR: Failed to scan device " - "'%s'.\n", opts.device); - } - } else { - /* Normal undelete by specifying inode(s) */ - ntfs_log_quiet("Inode Flags %%age Date Size Filename\n"); - ntfs_log_quiet("---------------------------------------------------------------\n"); - - /* loop all given inodes */ - for (i = 0; i < nr_entries; i++) { - for (inode = ranges[i].begin; inode <= ranges[i].end; inode ++) { - /* Now undelete file */ - result = !undelete_file(vol, inode); - if (result) - ntfs_log_verbose("ERROR: Failed to " - "undelete inode %lli\n!", inode); - } - } - } - return (result); -} - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - ntfs_volume *vol; - int result = 1; - - ntfs_log_set_handler(ntfs_log_handler_outerr); - - with_regex = 0; - avoid_duplicate_printing = 0; - - if (!parse_options(argc, argv)) - goto free; - - utils_set_locale(); - - vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY | - (opts.force ? NTFS_MNT_FORCE : 0)); - if (!vol) - return 1; - - /* handling of the different modes */ - switch (opts.mode) { - /* Scanning */ - case MODE_SCAN: - result = !scan_disk(vol); - if (result) - ntfs_log_verbose("ERROR: Failed to scan device '%s'.\n", - opts.device); - break; - - /* Undelete-handling */ - case MODE_UNDELETE: - result= handle_undelete(vol); - break; - - /* Handling of copy mft */ - case MODE_COPY: - result = !copy_mft(vol, opts.mft_begin, opts.mft_end); - if (result) - ntfs_log_verbose("ERROR: Failed to read MFT blocks " - "%lld-%lld.\n", opts.mft_begin, - min((vol->mft_na->initialized_size >> - vol->mft_record_size_bits) , opts.mft_end)); - break; - default: - ; /* Cannot happen */ - } - - ntfs_umount(vol, FALSE); -free: - if (opts.match) - free(opts.match); - - return result; -} - diff --git a/usr/src/cmd/ntfsprogs/ntfsundelete.h b/usr/src/cmd/ntfsprogs/ntfsundelete.h deleted file mode 100644 index 529587b73c..0000000000 --- a/usr/src/cmd/ntfsprogs/ntfsundelete.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * ntfsundelete - Part of the Linux-NTFS project. - * - * Copyright (c) 2002 Richard Russon - * Copyright (c) 2007 Yura Pakhuchiy - * - * This utility will recover deleted files from an NTFS volume. - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFSUNDELETE_H_ -#define _NTFSUNDELETE_H_ - -#include "types.h" -#include "list.h" -#include "runlist.h" - -enum optmode { - MODE_NONE = 0, - MODE_SCAN, - MODE_UNDELETE, - MODE_COPY, - MODE_ERROR -}; - -struct options { - char *device; /* Device/File to work with */ - enum optmode mode; /* Scan / Undelete / Copy */ - int percent; /* Minimum recoverability */ - int uinode; /* Undelete this inode */ - char *dest; /* Save file to this directory */ - char *output; /* With this filename */ - char *match; /* Pattern for filename matching */ - int match_case; /* Case sensitive matching */ - int truncate; /* Truncate files to exact size. */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int force; /* Override common sense */ - int optimistic; /* Undelete in-use clusters as well */ - int parent; /* Show parent directory */ - time_t since; /* Since this time */ - s64 size_begin; /* Range for file size */ - s64 size_end; - s64 mft_begin; /* Range for mft copy */ - s64 mft_end; - char fillbyte; /* Use for unrecoverable sections */ -}; - -struct filename { - struct list_head list; /* Previous/Next links */ - ntfschar *uname; /* Filename in unicode */ - int uname_len; /* and its length */ - long long size_alloc; /* Allocated size (multiple of cluster size) */ - long long size_data; /* Actual size of data */ - FILE_ATTR_FLAGS flags; - time_t date_c; /* Time created */ - time_t date_a; /* altered */ - time_t date_m; /* mft record changed */ - time_t date_r; /* read */ - char *name; /* Filename in current locale */ - FILE_NAME_TYPE_FLAGS name_space; - leMFT_REF parent_mref; - char *parent_name; -}; - -struct data { - struct list_head list; /* Previous/Next links */ - char *name; /* Stream name in current locale */ - ntfschar *uname; /* Unicode stream name */ - int uname_len; /* and its length */ - int resident; /* Stream is resident */ - int compressed; /* Stream is compressed */ - int encrypted; /* Stream is encrypted */ - long long size_alloc; /* Allocated size (multiple of cluster size) */ - long long size_data; /* Actual size of data */ - long long size_init; /* Initialised size, may be less than data size */ - long long size_vcn; /* Highest VCN in the data runs */ - runlist_element *runlist; /* Decoded data runs */ - int percent; /* Amount potentially recoverable */ - void *data; /* If resident, a pointer to the data */ -}; - -struct ufile { - long long inode; /* MFT record number */ - time_t date; /* Last modification date/time */ - struct list_head name; /* A list of filenames */ - struct list_head data; /* A list of data streams */ - char *pref_name; /* Preferred filename */ - char *pref_pname; /* parent filename */ - long long max_size; /* Largest size we find */ - int attr_list; /* MFT record may be one of many */ - int directory; /* MFT record represents a directory */ - MFT_RECORD *mft; /* Raw MFT record */ -}; - -#endif /* _NTFSUNDELETE_H_ */ - diff --git a/usr/src/cmd/ntfsprogs/sd.c b/usr/src/cmd/ntfsprogs/sd.c deleted file mode 100644 index a43ebf9c99..0000000000 --- a/usr/src/cmd/ntfsprogs/sd.c +++ /dev/null @@ -1,600 +0,0 @@ -#include "compat.h" -#include "types.h" -#include "layout.h" -#include "sd.h" - -/** - * init_system_file_sd - - * - * NTFS 3.1 - System files security decriptors - * ===================================================== - * - * Create the security descriptor for system file number @sys_file_no and - * return a pointer to the descriptor. - * - * Note the root directory system file (".") is very different and handled by a - * different function. - * - * The sd is returned in *@sd_val and has length *@sd_val_len. - * - * Do NOT free *@sd_val as it is static memory. This also means that you can - * only use *@sd_val until the next call to this function. - */ -void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len) -{ - static u8 sd_array[0x68]; - SECURITY_DESCRIPTOR_RELATIVE *sd; - ACL *acl; - ACCESS_ALLOWED_ACE *aa_ace; - SID *sid; - - if (sys_file_no < 0) { - *sd_val = NULL; - *sd_val_len = 0; - return; - } - *sd_val = sd_array; - sd = (SECURITY_DESCRIPTOR_RELATIVE*)&sd_array; - sd->revision = 1; - sd->alignment = 0; - sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; - *sd_val_len = 0x64; - sd->owner = const_cpu_to_le32(0x48); - sd->group = const_cpu_to_le32(0x54); - sd->sacl = const_cpu_to_le32(0); - sd->dacl = const_cpu_to_le32(0x14); - /* - * Now at offset 0x14, as specified in the security descriptor, we have - * the DACL. - */ - acl = (ACL*)((char*)sd + le32_to_cpu(sd->dacl)); - acl->revision = 2; - acl->alignment1 = 0; - acl->size = const_cpu_to_le16(0x34); - acl->ace_count = const_cpu_to_le16(2); - acl->alignment2 = const_cpu_to_le16(0); - /* - * Now at offset 0x1c, just after the DACL's ACL, we have the first - * ACE of the DACL. The type of the ACE is access allowed. - */ - aa_ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); - aa_ace->type = ACCESS_ALLOWED_ACE_TYPE; - aa_ace->flags = 0; - aa_ace->size = const_cpu_to_le16(0x14); - switch (sys_file_no) { - case FILE_AttrDef: - case FILE_Boot: - aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | - FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA; - break; - default: - aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_WRITE | - FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | - FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA | - FILE_WRITE_DATA | FILE_READ_DATA; - break; - } - aa_ace->sid.revision = 1; - aa_ace->sid.sub_authority_count = 1; - aa_ace->sid.identifier_authority.value[0] = 0; - aa_ace->sid.identifier_authority.value[1] = 0; - aa_ace->sid.identifier_authority.value[2] = 0; - aa_ace->sid.identifier_authority.value[3] = 0; - aa_ace->sid.identifier_authority.value[4] = 0; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - aa_ace->sid.identifier_authority.value[5] = 5; - aa_ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - /* - * Now at offset 0x30 within security descriptor, just after the first - * ACE of the DACL. All system files, except the root directory, have - * a second ACE. - */ - /* The second ACE of the DACL. Type is access allowed. */ - aa_ace = (ACCESS_ALLOWED_ACE*)((char*)aa_ace + - le16_to_cpu(aa_ace->size)); - aa_ace->type = ACCESS_ALLOWED_ACE_TYPE; - aa_ace->flags = 0; - aa_ace->size = const_cpu_to_le16(0x18); - /* Only $AttrDef and $Boot behave differently to everything else. */ - switch (sys_file_no) { - case FILE_AttrDef: - case FILE_Boot: - aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | - FILE_READ_ATTRIBUTES | FILE_READ_EA | - FILE_READ_DATA; - break; - default: - aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ | - FILE_WRITE_ATTRIBUTES | - FILE_READ_ATTRIBUTES | FILE_WRITE_EA | - FILE_READ_EA | FILE_APPEND_DATA | - FILE_WRITE_DATA | FILE_READ_DATA; - break; - } - aa_ace->sid.revision = 1; - aa_ace->sid.sub_authority_count = 2; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - aa_ace->sid.identifier_authority.value[0] = 0; - aa_ace->sid.identifier_authority.value[1] = 0; - aa_ace->sid.identifier_authority.value[2] = 0; - aa_ace->sid.identifier_authority.value[3] = 0; - aa_ace->sid.identifier_authority.value[4] = 0; - aa_ace->sid.identifier_authority.value[5] = 5; - aa_ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - aa_ace->sid.sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - /* - * Now at offset 0x48 into the security descriptor, as specified in the - * security descriptor, we now have the owner SID. - */ - sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); - sid->revision = 1; - sid->sub_authority_count = 1; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - /* - * Now at offset 0x54 into the security descriptor, as specified in the - * security descriptor, we have the group SID. - */ - sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); - sid->revision = 1; - sid->sub_authority_count = 2; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); -} - -/** - * init_root_sd - - * - * Creates the security_descriptor for the root folder on ntfs 3.1 as created - * by Windows Vista (when the format is done from the disk management MMC - * snap-in, note this is different from the format done from the disk - * properties in Windows Explorer). - */ -void init_root_sd(u8 **sd_val, int *sd_val_len) -{ - SECURITY_DESCRIPTOR_RELATIVE *sd; - ACL *acl; - ACCESS_ALLOWED_ACE *ace; - SID *sid; - - static char sd_array[0x102c]; - *sd_val_len = 0x102c; - *sd_val = (u8*)&sd_array; - - //security descriptor relative - sd = (SECURITY_DESCRIPTOR_RELATIVE*)sd_array; - sd->revision = SECURITY_DESCRIPTOR_REVISION; - sd->alignment = 0; - sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; - sd->owner = const_cpu_to_le32(0x1014); - sd->group = const_cpu_to_le32(0x1020); - sd->sacl = 0; - sd->dacl = const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE)); - - //acl - acl = (ACL*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); - acl->revision = ACL_REVISION; - acl->alignment1 = 0; - acl->size = const_cpu_to_le16(0x1000); - acl->ace_count = const_cpu_to_le16(0x08); - acl->alignment2 = 0; - - //ace1 - ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = 0; - ace->size = const_cpu_to_le16(0x18); - ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES | - FILE_LIST_DIRECTORY | FILE_WRITE_DATA | - FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA | - FILE_TRAVERSE | FILE_DELETE_CHILD | - FILE_READ_ATTRIBUTES; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - //ace2 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | - INHERIT_ONLY_ACE; - ace->size = const_cpu_to_le16(0x18); - ace->mask = GENERIC_ALL; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - //ace3 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = 0; - ace->size = const_cpu_to_le16(0x14); - ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES | - FILE_LIST_DIRECTORY | FILE_WRITE_DATA | - FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA | - FILE_TRAVERSE | FILE_DELETE_CHILD | - FILE_READ_ATTRIBUTES; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - - //ace4 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | - INHERIT_ONLY_ACE; - ace->size = const_cpu_to_le16(0x14); - ace->mask = GENERIC_ALL; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - - //ace5 - ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = 0; - ace->size = const_cpu_to_le16(0x14); - ace->mask = SYNCHRONIZE | READ_CONTROL | DELETE | - FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | - FILE_TRAVERSE | FILE_WRITE_EA | FILE_READ_EA | - FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE | - FILE_LIST_DIRECTORY; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID); - - //ace6 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | - INHERIT_ONLY_ACE; - ace->size = const_cpu_to_le16(0x14); - ace->mask = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID); - - //ace7 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = 0; - ace->size = const_cpu_to_le16(0x18); - ace->mask = SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES | - FILE_TRAVERSE | FILE_READ_EA | FILE_LIST_DIRECTORY; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS); - - //ace8 - ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | - INHERIT_ONLY_ACE; - ace->size = const_cpu_to_le16(0x18); - ace->mask = GENERIC_READ | GENERIC_EXECUTE; - ace->sid.revision = SID_REVISION; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS); - - //owner sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); - sid->revision = 0x01; - sid->sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - - //group sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); - sid->revision = 0x01; - sid->sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); -} - -/** - * init_secure_sds - - * - * NTFS 3.1 - System files security decriptors - * =========================================== - * Create the security descriptor entries in $SDS data stream like they - * are in a partition, newly formatted with windows 2003 - */ -void init_secure_sds(char *sd_val) -{ - SECURITY_DESCRIPTOR_HEADER *sds; - SECURITY_DESCRIPTOR_RELATIVE *sd; - ACL *acl; - ACCESS_ALLOWED_ACE *ace; - SID *sid; - -/* - * security descriptor #1 - */ - //header - sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val); - sds->hash = const_cpu_to_le32(0xF80312F0); - sds->security_id = const_cpu_to_le32(0x0100); - sds->offset = const_cpu_to_le64(0x00); - sds->length = const_cpu_to_le32(0x7C); - //security descriptor relative - sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + - sizeof(SECURITY_DESCRIPTOR_HEADER)); - sd->revision = 0x01; - sd->alignment = 0x00; - sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; - sd->owner = const_cpu_to_le32(0x48); - sd->group = const_cpu_to_le32(0x58); - sd->sacl = const_cpu_to_le32(0x00); - sd->dacl = const_cpu_to_le32(0x14); - - //acl - acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); - acl->revision = 0x02; - acl->alignment1 = 0x00; - acl->size = const_cpu_to_le16(0x34); - acl->ace_count = const_cpu_to_le16(0x02); - acl->alignment2 = 0x00; - - //ace1 - ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); - ace->type = 0x00; - ace->flags = 0x00; - ace->size = const_cpu_to_le16(0x14); - ace->mask = const_cpu_to_le32(0x120089); - ace->sid.revision = 0x01; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - //ace2 - ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); - ace->type = 0x00; - ace->flags = 0x00; - ace->size = const_cpu_to_le16(0x18); - ace->mask = const_cpu_to_le32(0x120089); - ace->sid.revision = 0x01; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - //owner sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); - sid->revision = 0x01; - sid->sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - //group sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); - sid->revision = 0x01; - sid->sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); -/* - * security descriptor #2 - */ - //header - sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80); - sds->hash = const_cpu_to_le32(0xB32451); - sds->security_id = const_cpu_to_le32(0x0101); - sds->offset = const_cpu_to_le64(0x80); - sds->length = const_cpu_to_le32(0x7C); - - //security descriptor relative - sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds + - sizeof(SECURITY_DESCRIPTOR_HEADER)); - sd->revision = 0x01; - sd->alignment = 0x00; - sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT; - sd->owner = const_cpu_to_le32(0x48); - sd->group = const_cpu_to_le32(0x58); - sd->sacl = const_cpu_to_le32(0x00); - sd->dacl = const_cpu_to_le32(0x14); - - //acl - acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE)); - acl->revision = 0x02; - acl->alignment1 = 0x00; - acl->size = const_cpu_to_le16(0x34); - acl->ace_count = const_cpu_to_le16(0x02); - acl->alignment2 = 0x00; - - //ace1 - ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL)); - ace->type = 0x00; - ace->flags = 0x00; - ace->size = const_cpu_to_le16(0x14); - ace->mask = const_cpu_to_le32(0x12019F); - ace->sid.revision = 0x01; - ace->sid.sub_authority_count = 0x01; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID); - //ace2 - ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size)); - ace->type = 0x00; - ace->flags = 0x00; - ace->size = const_cpu_to_le16(0x18); - ace->mask = const_cpu_to_le32(0x12019F); - ace->sid.revision = 0x01; - ace->sid.sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - ace->sid.identifier_authority.value[0] = 0; - ace->sid.identifier_authority.value[1] = 0; - ace->sid.identifier_authority.value[2] = 0; - ace->sid.identifier_authority.value[3] = 0; - ace->sid.identifier_authority.value[4] = 0; - ace->sid.identifier_authority.value[5] = 5; - ace->sid.sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - ace->sid.sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - //owner sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->owner)); - sid->revision = 0x01; - sid->sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - //group sid - sid = (SID*)((char*)sd + le32_to_cpu(sd->group)); - sid->revision = 0x01; - sid->sub_authority_count = 0x02; - /* SECURITY_NT_SID_AUTHORITY (S-1-5) */ - sid->identifier_authority.value[0] = 0; - sid->identifier_authority.value[1] = 0; - sid->identifier_authority.value[2] = 0; - sid->identifier_authority.value[3] = 0; - sid->identifier_authority.value[4] = 0; - sid->identifier_authority.value[5] = 5; - sid->sub_authority[0] = - const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); - sid->sub_authority[1] = - const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); - - return; -} diff --git a/usr/src/cmd/ntfsprogs/sd.h b/usr/src/cmd/ntfsprogs/sd.h deleted file mode 100644 index 7ad3e6a79c..0000000000 --- a/usr/src/cmd/ntfsprogs/sd.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _NTFS_SD_H_ -#define _NTFS_SD_H_ - -#include "types.h" - -void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len); -void init_root_sd(u8 **sd_val, int *sd_val_len); -void init_secure_sds(char *sd_val); - -#endif /* _NTFS_SD_H_ */ - diff --git a/usr/src/cmd/ntfsprogs/utils.c b/usr/src/cmd/ntfsprogs/utils.c deleted file mode 100644 index d35533de22..0000000000 --- a/usr/src/cmd/ntfsprogs/utils.c +++ /dev/null @@ -1,1057 +0,0 @@ -/** - * utils.c - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2003-2006 Anton Altaparmakov - * Copyright (c) 2003 Lode Leroy - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * A set of shared functions for ntfs utilities - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_LOCALE_H -#include -#endif -#ifdef HAVE_LIBINTL_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif -#ifdef HAVE_CTYPE_H -#include -#endif - -#include "compat.h" -#include "utils.h" -#include "types.h" -#include "volume.h" -#include "debug.h" -#include "dir.h" -#include "version.h" -#include "logging.h" - -const char *ntfs_bugs = "Developers' email address: "NTFS_DEV_LIST"\n"; -const char *ntfs_home = "Linux NTFS homepage: http://www.linux-ntfs.org\n"; -const char *ntfs_gpl = "This program is free software, released under the GNU " - "General Public License\nand you are welcome to redistribute it under " - "certain conditions. It comes with\nABSOLUTELY NO WARRANTY; for " - "details read the GNU General Public License to be\nfound in the file " - "\"COPYING\" distributed with this program, or online at:\n" - "http://www.gnu.org/copyleft/gpl.html\n"; - -static const char *invalid_ntfs_msg = -"The device '%s' doesn't have a valid NTFS.\n" -"Maybe you selected the wrong device? Or the whole disk instead of a\n" -"partition (e.g. /dev/hda, not /dev/hda1)? Or the other way around?\n"; - -static const char *corrupt_volume_msg = -"NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n" -"The usage of the /f parameter is very IMPORTANT! No modification was\n" -"made to NTFS by this software.\n"; - -static const char *hibernated_volume_msg = -"The NTFS partition is hibernated. Please resume Windows and turned it \n" -"off properly, so mounting could be done safely.\n"; - -static const char *unclean_journal_msg = -"Access is denied because the NTFS journal file is unclean. Choices are:\n" -" A) Shutdown Windows properly.\n" -" B) Click the 'Safely Remove Hardware' icon in the Windows taskbar\n" -" notification area before disconnecting the device.\n" -" C) Use 'Eject' from Windows Explorer to safely remove the device.\n" -" D) If you ran chkdsk previously then boot Windows again which will\n" -" automatically initialize the journal.\n" -" E) Submit 'force' option (WARNING: This solution it not recommended).\n" -" F) ntfsmount: Mount the volume read-only by using the 'ro' mount option.\n"; - -static const char *opened_volume_msg = -"Access is denied because the NTFS volume is already exclusively opened.\n" -"The volume may be already mounted, or another software may use it which\n" -"could be identified for example by the help of the 'fuser' command.\n"; - -static const char *dirty_volume_msg = -"Volume is scheduled for check.\n" -"Please boot into Windows TWICE, or use the 'force' option.\n" -"NOTE: If you had not scheduled check and last time accessed this volume\n" -"using ntfsmount and shutdown system properly, then init scripts in your\n" -"distribution are broken. Please report to your distribution developers\n" -"(NOT to us!) that init scripts kill ntfsmount or mount.ntfs-fuse during\n" -"shutdown instead of proper umount.\n"; - -static const char *fakeraid_msg = -"You seem to have a SoftRAID/FakeRAID hardware and must use an activated,\n" -"different device under /dev/mapper, (e.g. /dev/mapper/nvidia_eahaabcc1)\n" -"to mount NTFS. Please see the 'dmraid' documentation for help.\n"; - -/** - * utils_set_locale - */ -int utils_set_locale(void) -{ - const char *locale; - - locale = setlocale(LC_ALL, ""); - if (!locale) { - locale = setlocale(LC_ALL, NULL); - ntfs_log_error("Failed to set locale, using default '%s'.\n", - locale); - return 1; - } else { - return 0; - } -} - -/** - * utils_valid_device - Perform some safety checks on the device, before start - * @name: Full pathname of the device/file to work with - * @force: Continue regardless of problems - * - * Check that the name refers to a device and that is isn't already mounted. - * These checks can be overridden by using the force option. - * - * Return: 1 Success, we can continue - * 0 Error, we cannot use this device - */ -int utils_valid_device(const char *name, int force) -{ - unsigned long mnt_flags = 0; - struct stat st; - -#ifdef __CYGWIN32__ - /* FIXME: This doesn't work for Cygwin, so just return success. */ - return 1; -#endif - if (!name) { - errno = EINVAL; - return 0; - } - - if (stat(name, &st) == -1) { - if (errno == ENOENT) - ntfs_log_error("The device %s doesn't exist\n", name); - else - ntfs_log_perror("Error getting information about %s", - name); - return 0; - } - - /* Make sure the file system is not mounted. */ - if (ntfs_check_if_mounted(name, &mnt_flags)) { - ntfs_log_perror("Failed to determine whether %s is mounted", - name); - if (!force) { - ntfs_log_error("Use the force option to ignore this " - "error.\n"); - return 0; - } - ntfs_log_warning("Forced to continue.\n"); - } else if (mnt_flags & NTFS_MF_MOUNTED) { - if (!force) { - ntfs_log_error("%s", opened_volume_msg); - ntfs_log_error("You can use force option to avoid this " - "check, but this is not recommended\n" - "and may lead to data corruption.\n"); - return 0; - } - ntfs_log_warning("Forced to continue.\n"); - } - - return 1; -} - -/** - * utils_mount_volume - Mount an NTFS volume - */ -ntfs_volume * utils_mount_volume(const char *device, ntfs_mount_flags flags) -{ - ntfs_volume *vol; - - if (!device) { - errno = EINVAL; - return NULL; - } - - if (!utils_valid_device(device, flags & NTFS_MNT_FORCE)) - return NULL; - - vol = ntfs_mount(device, flags); - if (!vol) { - ntfs_log_perror("Failed to mount '%s'", device); - if (errno == EINVAL) - ntfs_log_error(invalid_ntfs_msg, device); - else if (errno == EIO) - ntfs_log_error("%s", corrupt_volume_msg); - else if (errno == EPERM) - ntfs_log_error("%s", hibernated_volume_msg); - else if (errno == EOPNOTSUPP) - ntfs_log_error("%s", unclean_journal_msg); - else if (errno == EBUSY) - ntfs_log_error("%s", opened_volume_msg); - else if (errno == ENXIO) - ntfs_log_error("%s", fakeraid_msg); - return NULL; - } - - if (NVolWasDirty(vol)) { - if (!(flags & NTFS_MNT_FORCE)) { - ntfs_log_error("%s", dirty_volume_msg); - ntfs_umount(vol, FALSE); - return NULL; - } - ntfs_log_error("WARNING: Dirty volume mount was forced by the " - "'force' mount option.\n"); - } - return vol; -} - -/** - * utils_parse_size - Convert a string representing a size - * @value: String to be parsed - * @size: Parsed size - * @scale: Whether or not to allow a suffix to scale the value - * - * Read a string and convert it to a number. Strings may be suffixed to scale - * them. Any number without a suffix is assumed to be in bytes. - * - * Suffix Description Multiple - * [tT] Terabytes 10^12 - * [gG] Gigabytes 10^9 - * [mM] Megabytes 10^6 - * [kK] Kilobytes 10^3 - * - * Notes: - * Only the first character of the suffix is read. - * The multipliers are decimal thousands, not binary: 1000, not 1024. - * If parse_size fails, @size will not be changed - * - * Return: 1 Success - * 0 Error, the string was malformed - */ -int utils_parse_size(const char *value, s64 *size, BOOL scale) -{ - long long result; - char *suffix = NULL; - - if (!value || !size) { - errno = EINVAL; - return 0; - } - - ntfs_log_debug("Parsing size '%s'.\n", value); - - result = strtoll(value, &suffix, 0); - if (result < 0 || errno == ERANGE) { - ntfs_log_error("Invalid size '%s'.\n", value); - return 0; - } - - if (!suffix) { - ntfs_log_error("Internal error, strtoll didn't return a suffix.\n"); - return 0; - } - - if (scale) { - switch (suffix[0]) { - case 't': case 'T': result *= 1000; - case 'g': case 'G': result *= 1000; - case 'm': case 'M': result *= 1000; - case 'k': case 'K': result *= 1000; - case '-': case 0: - break; - default: - ntfs_log_error("Invalid size suffix '%s'. Use T, G, M, or K.\n", suffix); - return 0; - } - } else { - if ((suffix[0] != '-') && (suffix[0] != 0)) { - ntfs_log_error("Invalid number '%.*s'.\n", (int)(suffix - value + 1), value); - return 0; - } - } - - ntfs_log_debug("Parsed size = %lld.\n", result); - *size = result; - return 1; -} - -/** - * utils_parse_range - Convert a string representing a range of numbers - * @string: The string to be parsed - * @start: The beginning of the range will be stored here - * @finish: The end of the range will be stored here - * - * Read a string of the form n-m. If the lower end is missing, zero will be - * substituted. If the upper end is missing LONG_MAX will be used. If the - * string cannot be parsed correctly, @start and @finish will not be changed. - * - * Return: 1 Success, a valid string was found - * 0 Error, the string was not a valid range - */ -int utils_parse_range(const char *string, s64 *start, s64 *finish, BOOL scale) -{ - s64 a, b; - char *middle; - - if (!string || !start || !finish) { - errno = EINVAL; - return 0; - } - - middle = strchr(string, '-'); - if (string == middle) { - ntfs_log_debug("Range has no beginning, defaulting to 0.\n"); - a = 0; - } else { - if (!utils_parse_size(string, &a, scale)) - return 0; - } - - if (middle) { - if (middle[1] == 0) { - b = LONG_MAX; // XXX ULLONG_MAX - ntfs_log_debug("Range has no end, defaulting to %lld.\n", b); - } else { - if (!utils_parse_size(middle+1, &b, scale)) - return 0; - } - } else { - b = a; - } - - ntfs_log_debug("Range '%s' = %lld - %lld\n", string, a, b); - - *start = a; - *finish = b; - return 1; -} - -/** - * find_attribute - Find an attribute of the given type - * @type: An attribute type, e.g. AT_FILE_NAME - * @ctx: A search context, created using ntfs_get_attr_search_ctx - * - * Using the search context to keep track, find the first/next occurrence of a - * given attribute type. - * - * N.B. This will return a pointer into @mft. As long as the search context - * has been created without an inode, it won't overflow the buffer. - * - * Return: Pointer Success, an attribute was found - * NULL Error, no matching attributes were found - */ -ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx) -{ - if (!ctx) { - errno = EINVAL; - return NULL; - } - - if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) { - ntfs_log_debug("find_attribute didn't find an attribute of type: 0x%02x.\n", type); - return NULL; /* None / no more of that type */ - } - - ntfs_log_debug("find_attribute found an attribute of type: 0x%02x.\n", type); - return ctx->attr; -} - -/** - * find_first_attribute - Find the first attribute of a given type - * @type: An attribute type, e.g. AT_FILE_NAME - * @mft: A buffer containing a raw MFT record - * - * Search through a raw MFT record for an attribute of a given type. - * The return value is a pointer into the MFT record that was supplied. - * - * N.B. This will return a pointer into @mft. The pointer won't stray outside - * the buffer, since we created the search context without an inode. - * - * Return: Pointer Success, an attribute was found - * NULL Error, no matching attributes were found - */ -ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft) -{ - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *rec; - - if (!mft) { - errno = EINVAL; - return NULL; - } - - ctx = ntfs_attr_get_search_ctx(NULL, mft); - if (!ctx) { - ntfs_log_error("Couldn't create a search context.\n"); - return NULL; - } - - rec = find_attribute(type, ctx); - ntfs_attr_put_search_ctx(ctx); - if (rec) - ntfs_log_debug("find_first_attribute: found attr of type 0x%02x.\n", type); - else - ntfs_log_debug("find_first_attribute: didn't find attr of type 0x%02x.\n", type); - return rec; -} - -/** - * utils_inode_get_name - * - * using inode - * get filename - * add name to list - * get parent - * if parent is 5 (/) stop - * get inode of parent - */ -#define max_path 20 -int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize) -{ - // XXX option: names = posix/win32 or dos - // flags: path, filename, or both - - - ntfs_volume *vol; - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *rec; - FILE_NAME_ATTR *attr; - int name_space; - MFT_REF parent = FILE_root; - char *names[max_path + 1];// XXX ntfs_malloc? and make max bigger? - int i, len, offset = 0; - - if (!inode || !buffer) { - errno = EINVAL; - return 0; - } - - vol = inode->vol; - - //ntfs_log_debug("sizeof(char*) = %d, sizeof(names) = %d\n", sizeof(char*), sizeof(names)); - memset(names, 0, sizeof(names)); - - for (i = 0; i < max_path; i++) { - - ctx = ntfs_attr_get_search_ctx(inode, NULL); - if (!ctx) { - ntfs_log_error("Couldn't create a search context.\n"); - return 0; - } - - //ntfs_log_debug("i = %d, inode = %p (%lld)\n", i, inode, inode->mft_no); - - name_space = 4; - while ((rec = find_attribute(AT_FILE_NAME, ctx))) { - /* We know this will always be resident. */ - attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->u.res.value_offset)); - - if (attr->file_name_type > name_space) { //XXX find the ... - continue; - } - - name_space = attr->file_name_type; - parent = le64_to_cpu(attr->parent_directory); - - if (names[i]) { - free(names[i]); - names[i] = NULL; - } - - if (ntfs_ucstombs(attr->file_name, attr->file_name_length, - &names[i], 0) < 0) { - char *temp; - ntfs_log_error("Couldn't translate filename to current locale.\n"); - temp = ntfs_malloc(30); - if (!temp) - return 0; - snprintf(temp, 30, "", (unsigned - long long)inode->mft_no); - names[i] = temp; - } - - //ntfs_log_debug("names[%d] %s\n", i, names[i]); - //ntfs_log_debug("parent = %lld\n", MREF(parent)); - } - - ntfs_attr_put_search_ctx(ctx); - - if (i > 0) /* Don't close the original inode */ - ntfs_inode_close(inode); - - if (MREF(parent) == FILE_root) { /* The root directory, stop. */ - //ntfs_log_debug("inode 5\n"); - break; - } - - inode = ntfs_inode_open(vol, parent); - if (!inode) { - ntfs_log_error("Couldn't open inode %llu.\n", - (unsigned long long)MREF(parent)); - break; - } - } - - if (i >= max_path) { - /* If we get into an infinite loop, we'll end up here. */ - ntfs_log_error("The directory structure is too deep (over %d) nested directories.\n", max_path); - return 0; - } - - /* Assemble the names in the correct order. */ - for (i = max_path; i >= 0; i--) { - if (!names[i]) - continue; - - len = snprintf(buffer + offset, bufsize - offset, "%c%s", PATH_SEP, names[i]); - if (len >= (bufsize - offset)) { - ntfs_log_error("Pathname was truncated.\n"); - break; - } - - offset += len; - } - - /* Free all the allocated memory */ - for (i = 0; i < max_path; i++) - free(names[i]); - - ntfs_log_debug("Pathname: %s\n", buffer); - - return 1; -} -#undef max_path - -/** - * utils_attr_get_name - */ -int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize) -{ - int len, namelen; - char *name; - ATTR_DEF *attrdef; - - // flags: attr, name, or both - if (!attr || !buffer) { - errno = EINVAL; - return 0; - } - - attrdef = ntfs_attr_find_in_attrdef(vol, attr->type); - if (attrdef) { - name = NULL; - namelen = ntfs_ucsnlen(attrdef->name, sizeof(attrdef->name)); - if (ntfs_ucstombs(attrdef->name, namelen, &name, 0) < 0) { - ntfs_log_error("Couldn't translate attribute type to " - "current locale.\n"); - // ? - return 0; - } - len = snprintf(buffer, bufsize, "%s", name); - } else { - ntfs_log_error("Unknown attribute type 0x%02x\n", attr->type); - len = snprintf(buffer, bufsize, ""); - } - - if (len >= bufsize) { - ntfs_log_error("Attribute type was truncated.\n"); - return 0; - } - - if (!attr->name_length) { - return 0; - } - - buffer += len; - bufsize -= len; - - name = NULL; - namelen = attr->name_length; - if (ntfs_ucstombs((ntfschar *)((char *)attr + le16_to_cpu( - attr->name_offset)), namelen, &name, 0) < 0) { - ntfs_log_error("Couldn't translate attribute name to current " - "locale.\n"); - // ? - len = snprintf(buffer, bufsize, ""); - return 0; - } - - len = snprintf(buffer, bufsize, "(%s)", name); - free(name); - - if (len >= bufsize) { - ntfs_log_error("Attribute name was truncated.\n"); - return 0; - } - - return 0; -} - -/** - * utils_cluster_in_use - Determine if a cluster is in use - * @vol: An ntfs volume obtained from ntfs_mount - * @lcn: The Logical Cluster Number to test - * - * The metadata file $Bitmap has one binary bit representing each cluster on - * disk. The bit will be set for each cluster that is in use. The function - * reads the relevant part of $Bitmap into a buffer and tests the bit. - * - * This function has a static buffer in which it caches a section of $Bitmap. - * If the lcn, being tested, lies outside the range, the buffer will be - * refreshed. @bmplcn stores offset to the first bit (in bits) stored in the - * buffer. - * - * NOTE: Be very carefull with shifts by 3 everywhere in this function. - * - * Return: 1 Cluster is in use - * 0 Cluster is free space - * -1 Error occurred - */ -int utils_cluster_in_use(ntfs_volume *vol, long long lcn) -{ - static unsigned char buffer[512]; - static long long bmplcn = -(sizeof(buffer) << 3); - int byte, bit; - ntfs_attr *attr; - - if (!vol) { - errno = EINVAL; - return -1; - } - - /* Does lcn lie in the section of $Bitmap we already have cached? */ - if ((lcn < bmplcn) || (lcn >= (bmplcn + (sizeof(buffer) << 3)))) { - ntfs_log_debug("Bit lies outside cache.\n"); - attr = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); - if (!attr) { - ntfs_log_perror("Couldn't open $Bitmap"); - return -1; - } - - /* Mark the buffer as in use, in case the read is shorter. */ - memset(buffer, 0xFF, sizeof(buffer)); - bmplcn = lcn & (~((sizeof(buffer) << 3) - 1)); - - if (ntfs_attr_pread(attr, (bmplcn >> 3), sizeof(buffer), - buffer) < 0) { - ntfs_log_perror("Couldn't read $Bitmap"); - ntfs_attr_close(attr); - return -1; - } - - ntfs_log_debug("Reloaded bitmap buffer.\n"); - ntfs_attr_close(attr); - } - - bit = 1 << (lcn & 7); - byte = (lcn >> 3) & (sizeof(buffer) - 1); - ntfs_log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, " - "in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] & - bit); - - return (buffer[byte] & bit); -} - -/** - * utils_mftrec_in_use - Determine if a MFT Record is in use - * @vol: An ntfs volume obtained from ntfs_mount - * @mref: MFT Reference (inode number) - * - * The metadata file $BITMAP has one binary bit representing each record in the - * MFT. The bit will be set for each record that is in use. The function - * reads the relevant part of $BITMAP into a buffer and tests the bit. - * - * This function has a static buffer in which it caches a section of $BITMAP. - * If the mref, being tested, lies outside the range, the buffer will be - * refreshed. - * - * Return: 1 MFT Record is in use - * 0 MFT Record is unused - * -1 Error occurred - */ -int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref) -{ - static u8 buffer[512]; - static s64 bmpmref = -sizeof(buffer) - 1; /* Which bit of $BITMAP is in the buffer */ - int byte, bit; - - ntfs_log_trace("Entering.\n"); - - if (!vol) { - errno = EINVAL; - return -1; - } - - /* Does mref lie in the section of $Bitmap we already have cached? */ - if (((s64)MREF(mref) < bmpmref) || ((s64)MREF(mref) >= (bmpmref + - (sizeof(buffer) << 3)))) { - ntfs_log_debug("Bit lies outside cache.\n"); - - /* Mark the buffer as not in use, in case the read is shorter. */ - memset(buffer, 0, sizeof(buffer)); - bmpmref = mref & (~((sizeof(buffer) << 3) - 1)); - - if (ntfs_attr_pread(vol->mftbmp_na, (bmpmref>>3), sizeof(buffer), buffer) < 0) { - ntfs_log_perror("Couldn't read $MFT/$BITMAP"); - return -1; - } - - ntfs_log_debug("Reloaded bitmap buffer.\n"); - } - - bit = 1 << (mref & 7); - byte = (mref >> 3) & (sizeof(buffer) - 1); - ntfs_log_debug("cluster = %lld, bmpmref = %lld, byte = %d, bit = %d, in use %d\n", mref, bmpmref, byte, bit, buffer[byte] & bit); - - return (buffer[byte] & bit); -} - -/** - * __metadata - */ -static int __metadata(ntfs_volume *vol, u64 num) -{ - if (num <= FILE_UpCase) - return 1; - if (!vol) - return -1; - if ((vol->major_ver == 3) && (num == FILE_Extend)) - return 1; - - return 0; -} - -/** - * utils_is_metadata - Determine if an inode represents a metadata file - * @inode: An ntfs inode to be tested - * - * A handful of files in the volume contain filesystem data - metadata. - * They can be identified by their inode number (offset in MFT/$DATA) or by - * their parent. - * - * Return: 1 inode is a metadata file - * 0 inode is not a metadata file - * -1 Error occurred - */ -int utils_is_metadata(ntfs_inode *inode) -{ - ntfs_volume *vol; - ATTR_RECORD *rec; - FILE_NAME_ATTR *attr; - MFT_RECORD *file; - u64 num; - - if (!inode) { - errno = EINVAL; - return -1; - } - - vol = inode->vol; - if (!vol) - return -1; - - num = inode->mft_no; - if (__metadata(vol, num) == 1) - return 1; - - file = inode->mrec; - if (file && (file->base_mft_record != 0)) { - num = MREF_LE(file->base_mft_record); - if (__metadata(vol, num) == 1) - return 1; - } - file = inode->mrec; - - rec = find_first_attribute(AT_FILE_NAME, inode->mrec); - if (!rec) - return -1; - - /* We know this will always be resident. */ - attr = (FILE_NAME_ATTR *)((char *)rec + le16_to_cpu(rec->u.res.value_offset)); - - num = MREF_LE(attr->parent_directory); - if ((num != FILE_root) && (__metadata(vol, num) == 1)) - return 1; - - return 0; -} - -/** - * utils_dump_mem - Display a block of memory in hex and ascii - * @buf: Buffer to be displayed - * @start: Offset into @buf to start from - * @length: Number of bytes to display - * @flags: Options to change the style of the output - * - * Display a block of memory in a tradition hex-dump manner. - * Optionally the ascii part can be turned off. - * - * The flags, described fully in utils.h, default to 0 (DM_DEFAULTS). - * Examples are: DM_INDENT (indent the output by one tab); DM_RED (colour the - * output); DM_NO_ASCII (only print the hex values). - */ -void utils_dump_mem(void *buf, int start, int length, int flags) -{ - int off, i, s, e, col; - u8 *mem = buf; - - s = start & ~15; // round down - e = (start + length + 15) & ~15; // round up - - for (off = s; off < e; off += 16) { - col = 30; - if (flags & DM_RED) - col += 1; - if (flags & DM_GREEN) - col += 2; - if (flags & DM_BLUE) - col += 4; - if (flags & DM_INDENT) - ntfs_log_debug("\t"); - if (flags & DM_BOLD) - ntfs_log_debug("\e[01m"); - if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD)) - ntfs_log_debug("\e[%dm", col); - if (off == s) - ntfs_log_debug("%6.6x ", start); - else - ntfs_log_debug("%6.6x ", off); - - for (i = 0; i < 16; i++) { - if ((i == 8) && (!(flags & DM_NO_DIVIDER))) - ntfs_log_debug(" -"); - if (((off+i) >= start) && ((off+i) < (start+length))) - ntfs_log_debug(" %02X", mem[off+i]); - else - ntfs_log_debug(" "); - } - if (!(flags & DM_NO_ASCII)) { - ntfs_log_debug(" "); - for (i = 0; i < 16; i++) { - if (((off+i) < start) || ((off+i) >= (start+length))) - ntfs_log_debug(" "); - else if (isprint(mem[off + i])) - ntfs_log_debug("%c", mem[off + i]); - else - ntfs_log_debug("."); - } - } - if (flags & (DM_RED | DM_BLUE | DM_GREEN | DM_BOLD)) - ntfs_log_debug("\e[0m"); - ntfs_log_debug("\n"); - } -} - - -/** - * mft_get_search_ctx - */ -struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol) -{ - struct mft_search_ctx *ctx; - - if (!vol) { - errno = EINVAL; - return NULL; - } - - ctx = calloc(1, sizeof *ctx); - - ctx->mft_num = -1; - ctx->vol = vol; - - return ctx; -} - -/** - * mft_put_search_ctx - */ -void mft_put_search_ctx(struct mft_search_ctx *ctx) -{ - if (!ctx) - return; - if (ctx->inode) - ntfs_inode_close(ctx->inode); - free(ctx); -} - -/** - * mft_next_record - */ -int mft_next_record(struct mft_search_ctx *ctx) -{ - s64 nr_mft_records; - ATTR_RECORD *attr10 = NULL; - ATTR_RECORD *attr20 = NULL; - ATTR_RECORD *attr80 = NULL; - ntfs_attr_search_ctx *attr_ctx; - - if (!ctx) { - errno = EINVAL; - return -1; - } - - if (ctx->inode) { - ntfs_inode_close(ctx->inode); - ctx->inode = NULL; - } - - nr_mft_records = ctx->vol->mft_na->initialized_size >> - ctx->vol->mft_record_size_bits; - - for (ctx->mft_num++; (s64)ctx->mft_num < nr_mft_records; ctx->mft_num++) { - int in_use; - - ctx->flags_match = 0; - in_use = utils_mftrec_in_use(ctx->vol, (MFT_REF) ctx->mft_num); - if (in_use == -1) { - ntfs_log_error("Error reading inode %llu. Aborting.\n", - (unsigned long long)ctx->mft_num); - return -1; - } - - if (in_use) { - ctx->flags_match |= FEMR_IN_USE; - - ctx->inode = ntfs_inode_open(ctx->vol, (MFT_REF) ctx->mft_num); - if (ctx->inode == NULL) { - ntfs_log_error("Error reading inode %llu.\n", (unsigned - long long) ctx->mft_num); - continue; - } - - attr10 = find_first_attribute(AT_STANDARD_INFORMATION, ctx->inode->mrec); - attr20 = find_first_attribute(AT_ATTRIBUTE_LIST, ctx->inode->mrec); - attr80 = find_first_attribute(AT_DATA, ctx->inode->mrec); - - if (attr10) - ctx->flags_match |= FEMR_BASE_RECORD; - else - ctx->flags_match |= FEMR_NOT_BASE_RECORD; - - if (attr20) - ctx->flags_match |= FEMR_BASE_RECORD; - - if (attr80) - ctx->flags_match |= FEMR_FILE; - - if (ctx->flags_search & FEMR_DIR) { - attr_ctx = ntfs_attr_get_search_ctx(ctx->inode, NULL); - if (attr_ctx) { - if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, 0, 0, NULL, 0, attr_ctx) == 0) - ctx->flags_match |= FEMR_DIR; - - ntfs_attr_put_search_ctx(attr_ctx); - } else { - ntfs_log_error("Couldn't create a search context.\n"); - return -1; - } - } - - switch (utils_is_metadata(ctx->inode)) { - case 1: ctx->flags_match |= FEMR_METADATA; break; - case 0: ctx->flags_match |= FEMR_NOT_METADATA; break; - default: - ctx->flags_match |= FEMR_NOT_METADATA; break; - //ntfs_log_error("Error reading inode %lld.\n", ctx->mft_num); - //return -1; - } - - } else { // !in_use - ntfs_attr *mft; - - ctx->flags_match |= FEMR_NOT_IN_USE; - - ctx->inode = calloc(1, sizeof(*ctx->inode)); - if (!ctx->inode) { - ntfs_log_error("Out of memory. Aborting.\n"); - return -1; - } - - ctx->inode->mft_no = ctx->mft_num; - ctx->inode->vol = ctx->vol; - ctx->inode->mrec = ntfs_malloc(ctx->vol->mft_record_size); - if (!ctx->inode->mrec) { - free(ctx->inode); // == ntfs_inode_close - return -1; - } - - mft = ntfs_attr_open(ctx->vol->mft_ni, AT_DATA, - AT_UNNAMED, 0); - if (!mft) { - ntfs_log_perror("Couldn't open $MFT/$DATA"); - // free / close - return -1; - } - - if (ntfs_attr_pread(mft, ctx->vol->mft_record_size * ctx->mft_num, ctx->vol->mft_record_size, ctx->inode->mrec) < ctx->vol->mft_record_size) { - ntfs_log_perror("Couldn't read MFT Record %llu", - (unsigned long long) ctx->mft_num); - // free / close - ntfs_attr_close(mft); - return -1; - } - - ntfs_attr_close(mft); - } - - if (ctx->flags_match & ctx->flags_search) { - break; - } - - if (ntfs_inode_close(ctx->inode)) { - ntfs_log_error("Error closing inode %llu.\n", - (unsigned long long)ctx->mft_num); - return -errno; - } - - ctx->inode = NULL; - } - - return (ctx->inode == NULL); -} - - diff --git a/usr/src/cmd/ntfsprogs/utils.h b/usr/src/cmd/ntfsprogs/utils.h deleted file mode 100644 index a38f43104d..0000000000 --- a/usr/src/cmd/ntfsprogs/utils.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * utils.h - Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2004 Anton Altaparmakov - * - * A set of shared functions for ntfs utilities - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_UTILS_H_ -#define _NTFS_UTILS_H_ - -#include "config.h" - -#include "types.h" -#include "layout.h" -#include "volume.h" - -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif - -extern const char *ntfs_bugs; -extern const char *ntfs_home; -extern const char *ntfs_gpl; - -int utils_set_locale(void); -int utils_parse_size(const char *value, s64 *size, BOOL scale); -int utils_parse_range(const char *string, s64 *start, s64 *finish, BOOL scale); -int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize); -int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize); -int utils_cluster_in_use(ntfs_volume *vol, long long lcn); -int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref); -int utils_is_metadata(ntfs_inode *inode); -void utils_dump_mem(void *buf, int start, int length, int flags); - -ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx); -ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft); - -int utils_valid_device(const char *name, int force); -ntfs_volume * utils_mount_volume(const char *device, ntfs_mount_flags flags); - -/** - * defines... - * if *not in use* then the other flags are ignored? - */ -#define FEMR_IN_USE (1 << 0) -#define FEMR_NOT_IN_USE (1 << 1) -#define FEMR_FILE (1 << 2) // $DATA -#define FEMR_DIR (1 << 3) // $INDEX_ROOT, "$I30" -#define FEMR_METADATA (1 << 4) -#define FEMR_NOT_METADATA (1 << 5) -#define FEMR_BASE_RECORD (1 << 6) -#define FEMR_NOT_BASE_RECORD (1 << 7) -#define FEMR_ALL_RECORDS 0xFF - -/** - * struct mft_search_ctx - */ -struct mft_search_ctx { - int flags_search; - int flags_match; - ntfs_inode *inode; - ntfs_volume *vol; - u64 mft_num; -}; - -struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol); -void mft_put_search_ctx(struct mft_search_ctx *ctx); -int mft_next_record(struct mft_search_ctx *ctx); - -// Flags for dump mem -#define DM_DEFAULTS 0 -#define DM_NO_ASCII (1 << 0) -#define DM_NO_DIVIDER (1 << 1) -#define DM_INDENT (1 << 2) -#define DM_RED (1 << 3) -#define DM_GREEN (1 << 4) -#define DM_BLUE (1 << 5) -#define DM_BOLD (1 << 6) - -#endif /* _NTFS_UTILS_H_ */ diff --git a/usr/src/cmd/parted/COPYING b/usr/src/cmd/parted/COPYING deleted file mode 100644 index 4432540474..0000000000 --- a/usr/src/cmd/parted/COPYING +++ /dev/null @@ -1,676 +0,0 @@ - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - diff --git a/usr/src/cmd/parted/Makefile b/usr/src/cmd/parted/Makefile deleted file mode 100644 index d3aff3828f..0000000000 --- a/usr/src/cmd/parted/Makefile +++ /dev/null @@ -1,76 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -PROG= parted - -include ../Makefile.cmd - -C99MODE= $(C99_ENABLE) -CERRWARN += -erroff=E_EXTERN_INLINE_UNDEFINED -CERRWARN += -erroff=E_ARG_INCOMPATIBLE_WITH_ARG -CERRWARN += -_gcc=-Wno-unused-function - -srcdir= . - -CPPFLAGS += -I. \ - -I../../lib/libparted/common/lib \ - -I../../lib/libparted/common/include - -ARFLAGS= cq - -OBJS= command.o parted.o strlist.o table.o ui.o - -SRCS= $(OBJS:%.o=$(srcdir)/%.c) - -LDLIBS += ../../lib/libparted/i386/libparted.so.8 - -ROOTPROG= $(PROG:%=$(ROOTUSRSBIN)/%) - -.KEEP_STATE: -all: $(PROG) - -all install: THIRDPARTYLICENSE - -CLOBBERFILES += THIRDPARTYLICENSE - -THIRDPARTYLICENSE: $(SRC)/common/GPLDISCLAIMER COPYING - $(RM) $@ - $(CAT) $(SRC)/common/GPLDISCLAIMER COPYING > $@ - -$(PROG): $(OBJS) - $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS) - $(POST_PROCESS) - -install: all $(ROOTPROG) - -clean: - $(RM) $(OBJS) - -# -# This open source is exempted from lint -# -lint: - -include ../Makefile.targ diff --git a/usr/src/cmd/parted/README b/usr/src/cmd/parted/README deleted file mode 100644 index e035552376..0000000000 --- a/usr/src/cmd/parted/README +++ /dev/null @@ -1,8 +0,0 @@ -This is the Solaris ON port of GNU Parted v1.8.8 -For more information, please see http://www.gnu.org/software/parted/ - -parted has been broken into two pieces: src/lib/libparted and src/cmd/parted - -The Makefiles have all been replaced by ON Makefiles. - -This directory contains the contents of parted-1.8.8/parted diff --git a/usr/src/cmd/parted/THANKS.txt b/usr/src/cmd/parted/THANKS.txt deleted file mode 100644 index 466ccaca55..0000000000 --- a/usr/src/cmd/parted/THANKS.txt +++ /dev/null @@ -1,28 +0,0 @@ -In no particular order: - - * Jonathan duSaint for binary unit support and more. - * Kamil Ignacak for help with the migration of the API documentation. - * Conectiva, www.conectiva.com, for sponsoring Parted's development (in the -past). Eliphas, beber (aka Pato), baretta, fuganti, claudio, olive (anyone -else?) - * Stefan Kanthak <101.33761@germanynet.de> for lots of info on boot-loaders, -and some corrections to the documentation - * Fabian Emmes for RPM spec file, help with hidden -partitions and autoconfusion :-) - and lots of other misc. help. - * Falk Hueffner for bug fixes. - * Kevin Lindsay for lots of bug reports, etc. - * John Weismiller for lots of bug reports, etc. - * Andries Brouwer for advice on BIOS geometry - * Simon Kirby for advice on BIOS geometry - * Glenn McGrath - * Timshel Knoll for Debian stuff - * Tim Waugh for bug reports and fixes - * My friends for helping with testing: Tristan Zwalf, Menaka Lashitha Bandara, -Thomas Hambleton - * Ryan Weaver for parted.spec.in patches - * Benjamin Herrenschmidt for answering all of our questions -on Mac's - * Ethan Benson for lots of advice / testing on ppc - * Charles Stevenson - ppc stuff - * heaps of people we left out! - diff --git a/usr/src/cmd/parted/THIRDPARTYLICENSE.descrip b/usr/src/cmd/parted/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 1cafc40dc0..0000000000 --- a/usr/src/cmd/parted/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -GNU Parted - Partition Editor diff --git a/usr/src/cmd/parted/command.c b/usr/src/cmd/parted/command.c deleted file mode 100644 index a3ae7c0450..0000000000 --- a/usr/src/cmd/parted/command.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "command.h" -#include "ui.h" - -#include - -#include -#include -#include "xalloc.h" - -Command* -command_create (const StrList* names, - int (*method) (PedDevice** dev), - const StrList* summary, - const StrList* help, - const int non_interactive) -{ - Command* cmd; - - cmd = xmalloc (sizeof (Command)); - - if (non_interactive) - cmd->non_interactive = 1; - else - cmd->non_interactive = 0; - - cmd->names = (StrList*) names; - cmd->method = method; - cmd->summary = (StrList*) summary; - cmd->help = (StrList*) help; - - return cmd; -} - -void -command_destroy (Command* cmd) -{ - str_list_destroy (cmd->names); - str_list_destroy (cmd->summary); - str_list_destroy (cmd->help); - free (cmd); -} - -void -command_register (Command** list, Command* cmd) -{ - int i; - - for (i = 0; list [i]; i++); - - list [i] = cmd; - list [i + 1] = (Command*) NULL; -} - -Command* -command_get (Command** list, char* name) -{ - int i; - int partial_match = -1; - int ambiguous = 0; - - if (!name) - return NULL; - - for (i=0; list [i]; i++) { - switch (str_list_match_any (list [i]->names, name)) { - case 2: - return list [i]; - - case 1: - if (!ambiguous) { - if (partial_match == -1) { - partial_match = i; - } else { - partial_match = -1; - ambiguous = 1; - } - } - } - } - - if (partial_match == -1) - return NULL; - else - return list [partial_match]; -} - -StrList* -command_get_names (Command** list) -{ - Command** walk; - StrList* result = NULL; - - for (walk = list; *walk; walk++) - result = str_list_join (result, - str_list_duplicate ((*walk)->names)); - return result; -} - -void -command_print_summary (Command* cmd) -{ - fputs (" ", stdout); - str_list_print_wrap (cmd->summary, screen_width(), 2, 8); - putchar ('\n'); -} - -void -command_print_help (Command* cmd) -{ - command_print_summary (cmd); - if (cmd->help) { - fputs ("\n\t", stdout); - str_list_print_wrap (cmd->help, screen_width(), 8, 8); - } -} - -int -command_run (Command* cmd, PedDevice** dev) -{ - return cmd->method (dev); -} - diff --git a/usr/src/cmd/parted/command.h b/usr/src/cmd/parted/command.h deleted file mode 100644 index 82de853ea2..0000000000 --- a/usr/src/cmd/parted/command.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef COMMAND_H_INCLUDED -#define COMMAND_H_INCLUDED - -#include -#include "strlist.h" - -typedef struct { - StrList* names; - int (*method) (PedDevice** dev); - StrList* summary; - StrList* help; - int non_interactive:1; -} Command; - -extern Command* command_create (const StrList* names, - int (*method) (PedDevice** dev), - const StrList* summary, - const StrList* help, - int non_interactive); -extern void command_destroy (Command* cmd); -void command_register (Command** list, Command* cmd); - -extern Command* command_get (Command** list, char* name); -extern StrList* command_get_names (Command** list); -extern void command_print_summary (Command* cmd); -extern void command_print_help (Command* cmd); -extern int command_run (Command* cmd, PedDevice** dev); - -#endif /* COMMAND_H_INCLUDED */ - diff --git a/usr/src/cmd/parted/parted.c b/usr/src/cmd/parted/parted.c deleted file mode 100644 index d8e937f32e..0000000000 --- a/usr/src/cmd/parted/parted.c +++ /dev/null @@ -1,2493 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. - */ - -#include - -#include "closeout.h" -#include "configmake.h" -#include "version-etc.h" -#include "command.h" -#include "ui.h" -#include "table.h" - -#define AUTHORS \ - "" - -/* The official name of this program (e.g., no `g' prefix). */ -#define PROGRAM_NAME "parted" - -#define N_(String) String -#if ENABLE_NLS -# include -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "xalloc.h" - -#ifdef ENABLE_MTRACE -#include -#endif - -#include - -/* minimum amount of free space to leave, or maximum amount to gobble up */ -#define MIN_FREESPACE (1000 * 2) /* 1000k */ - -static int MEGABYTE_SECTORS (PedDevice* dev) -{ - return PED_MEGABYTE_SIZE / dev->sector_size; -} - -/* For long options that have no equivalent short option, use a - non-character as a pseudo short option, starting with CHAR_MAX + 1. */ -enum -{ - PRETEND_INPUT_TTY = CHAR_MAX + 1, -}; - - -typedef struct { - time_t last_update; - time_t predicted_time_left; -} TimerContext; - -static struct option options[] = { - /* name, has-arg, string-return-val, char-return-val */ - {"help", 0, NULL, 'h'}, - {"list", 0, NULL, 'l'}, - {"machine", 0, NULL, 'm'}, - {"script", 0, NULL, 's'}, - {"version", 0, NULL, 'v'}, - {"-pretend-input-tty", 0, NULL, PRETEND_INPUT_TTY}, - {NULL, 0, NULL, 0} -}; - -static char* options_help [][2] = { - {"help", N_("displays this help message")}, - {"list", N_("lists partition layout on all block devices")}, - {"machine", N_("displays machine parseable output")}, - {"script", N_("never prompts for user intervention")}, - {"version", N_("displays the version")}, - {NULL, NULL} -}; - -char *program_name; - -int opt_script_mode = 0; -int pretend_input_tty = 0; -int opt_machine_mode = 0; -int disk_is_modified = 0; -int is_toggle_mode = 0; - -static char* number_msg = N_( -"NUMBER is the partition number used by Linux. On MS-DOS disk labels, the " -"primary partitions number from 1 to 4, logical partitions from 5 onwards.\n"); - -static char* label_type_msg_start = N_("LABEL-TYPE is one of: "); -static char* flag_msg_start = N_("FLAG is one of: "); -static char* unit_msg_start = N_("UNIT is one of: "); -static char* part_type_msg = N_("PART-TYPE is one of: primary, logical, " - "extended\n"); -static char* fs_type_msg_start = N_("FS-TYPE is one of: "); -static char* start_end_msg = N_("START and END are disk locations, such as " - "4GB or 10%. Negative values count from the end of the disk. " - "For example, -1s specifies exactly the last sector.\n"); -static char* state_msg = N_("STATE is one of: on, off\n"); -static char* device_msg = N_("DEVICE is usually /dev/hda or /dev/sda\n"); -static char* name_msg = N_("NAME is any word you want\n"); -static char* resize_msg_start = N_("The partition must have one of the " - "following FS-TYPEs: "); - -static char* copyright_msg = N_( -"Copyright (C) 1998 - 2006 Free Software Foundation, Inc.\n" -"This program is free software, covered by the GNU General Public License.\n" -"\n" -"This program is distributed in the hope that it will be useful,\n" -"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" -"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" -"GNU General Public License for more details.\n\n"); - -static char* label_type_msg; -static char* flag_msg; -static char* unit_msg; - -static char* mkfs_fs_type_msg; -static char* mkpart_fs_type_msg; -static char* resize_fs_type_msg; - -static Command* commands [256] = {NULL}; -static PedTimer* g_timer; -static TimerContext timer_context; - -static int _print_list (); -static void _done (PedDevice* dev); - -static void -_timer_handler (PedTimer* timer, void* context) -{ - TimerContext* tcontext = (TimerContext*) context; - int draw_this_time; - - if (opt_script_mode || !isatty(fileno(stdout))) - return; - - if (tcontext->last_update != timer->now && timer->now > timer->start) { - tcontext->predicted_time_left - = timer->predicted_end - timer->now; - tcontext->last_update = timer->now; - draw_this_time = 1; - } else { - draw_this_time = 0; - } - - if (draw_this_time) { - wipe_line (); - - if (timer->state_name) - printf ("%s... ", timer->state_name); - printf (_("%0.f%%\t(time left %.2d:%.2d)"), - 100.0 * timer->frac, - (int) (tcontext->predicted_time_left / 60), - (int) (tcontext->predicted_time_left % 60)); - - fflush (stdout); - } -} - -static int -_partition_warn_busy (PedPartition* part) -{ - char* path; - - if (ped_partition_is_busy (part)) { - path = ped_partition_get_path (part); - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Partition %s is being used. You must unmount it " - "before you modify it with Parted."), - path); - ped_free (path); - return 0; - } - return 1; -} - -static int -_disk_warn_busy (PedDisk* disk) -{ - if (ped_device_is_busy (disk->dev)) - return ped_exception_throw ( - (opt_script_mode - ? PED_EXCEPTION_ERROR - : PED_EXCEPTION_WARNING), - PED_EXCEPTION_IGNORE_CANCEL, - _("Partition(s) on %s are being used."), - disk->dev->path) == PED_EXCEPTION_IGNORE; - - return 1; -} - -static int -_partition_warn_loss () -{ - return ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_YES_NO, - _("The existing file system will be destroyed and " - "all data on the partition will be lost. Do " - "you want to continue?"), - NULL) == PED_EXCEPTION_YES; -} - -static int -_disk_warn_loss (PedDisk* disk) -{ - return ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_YES_NO, - _("The existing disk label on %s will be destroyed " - "and all data on this disk will be lost. Do you " - "want to continue?"), - disk->dev->path) == PED_EXCEPTION_YES; -} - -/* This function changes "sector" to "new_sector" if the new value lies - * within the required range. - */ -static int -snap (PedSector* sector, PedSector new_sector, PedGeometry* range) -{ - PED_ASSERT (ped_geometry_test_sector_inside (range, *sector), return 0); - if (!ped_geometry_test_sector_inside (range, new_sector)) - return 0; - *sector = new_sector; - return 1; -} - -typedef enum { - MOVE_NO = 0, - MOVE_STILL = 1, - MOVE_UP = 2, - MOVE_DOWN = 4 -} EMoves; - -enum { /* Don't change these values */ - SECT_START = 0, - SECT_END = -1 -}; - -/* Find the prefered way to adjust the sector s inside range. - * If a move isn't allowed or is out of range it can't be selected. - * what contains SECT_START if the sector to adjust is a start sector - * or SECT_END if it's an end one. - * The prefered move is to the nearest allowed boundary of the part - * partition (if at equal distance: to start if SECT_START or to end - * if SECT_END). - * The distance is returned in dist. - */ -static EMoves -prefer_snap (PedSector s, int what, PedGeometry* range, EMoves* allow, - PedPartition* part, PedSector* dist) -{ - PedSector up_dist = -1, down_dist = -1; - PedSector new_sect; - EMoves move; - - PED_ASSERT (what == SECT_START || what == SECT_END, return 0); - - if (!(*allow & (MOVE_UP | MOVE_DOWN))) { - *dist = 0; - return MOVE_STILL; - } - - if (*allow & MOVE_UP) { - new_sect = part->geom.end + 1 + what; - if (ped_geometry_test_sector_inside (range, new_sect)) - up_dist = new_sect - s; - else - *allow &= ~MOVE_UP; - } - - if (*allow & MOVE_DOWN) { - new_sect = part->geom.start + what; - if (ped_geometry_test_sector_inside (range, new_sect)) - down_dist = s - new_sect; - else - *allow &= ~MOVE_DOWN; - } - - move = MOVE_STILL; - if ((*allow & MOVE_UP) && (*allow & MOVE_DOWN)) { - if (down_dist < up_dist || (down_dist == up_dist - && what == SECT_START) ) - move = MOVE_DOWN; - else if (up_dist < down_dist || (down_dist == up_dist - && what == SECT_END) ) - move = MOVE_UP; - else - PED_ASSERT (0, return 0); - } else if (*allow & MOVE_UP) - move = MOVE_UP; - else if (*allow & MOVE_DOWN) - move = MOVE_DOWN; - - *dist = ( move == MOVE_DOWN ? down_dist : - ( move == MOVE_UP ? up_dist : - 0 ) ); - return move; -} - -/* Snaps a partition to nearby partition boundaries. This is useful for - * gobbling up small amounts of free space, and also for reinterpreting small - * changes to a partition as non-changes (eg: perhaps the user only wanted to - * resize the end of a partition). - * Note that this isn't the end of the story... this function is - * always called before the constraint solver kicks in. So you don't need to - * worry too much about inadvertantly creating overlapping partitions, etc. - */ -static void -snap_to_boundaries (PedGeometry* new_geom, PedGeometry* old_geom, - PedDisk* disk, - PedGeometry* start_range, PedGeometry* end_range) -{ - PedPartition* start_part; - PedPartition* end_part; - PedSector start = new_geom->start; - PedSector end = new_geom->end; - PedSector start_dist = -1, end_dist = -1; - EMoves start_allow, end_allow, start_want, end_want; - int adjacent; - - start_want = end_want = MOVE_NO; - start_allow = end_allow = MOVE_STILL | MOVE_UP | MOVE_DOWN; - - start_part = ped_disk_get_partition_by_sector (disk, start); - end_part = ped_disk_get_partition_by_sector (disk, end); - adjacent = (start_part->geom.end + 1 == end_part->geom.start); - - /* If we can snap to old_geom, then we will... */ - /* and this will enforce the snapped positions */ - if (old_geom) { - if (snap (&start, old_geom->start, start_range)) - start_allow = MOVE_STILL; - if (snap (&end, old_geom->end, end_range)) - end_allow = MOVE_STILL; - } - - /* If start and end are on the same partition, we */ - /* don't allow them to cross. */ - if (start_part == end_part) { - start_allow &= ~MOVE_UP; - end_allow &= ~MOVE_DOWN; - } - - /* Let's find our way */ - start_want = prefer_snap (start, SECT_START, start_range, &start_allow, - start_part, &start_dist ); - end_want = prefer_snap (end, SECT_END, end_range, &end_allow, - end_part, &end_dist ); - - PED_ASSERT (start_dist >= 0 && end_dist >= 0, return); - - /* If start and end are on adjacent partitions, */ - /* and if they would prefer crossing, then refrain */ - /* the farthest to do so. */ - if (adjacent && start_want == MOVE_UP && end_want == MOVE_DOWN) { - if (end_dist < start_dist) { - start_allow &= ~MOVE_UP; - start_want = prefer_snap (start, SECT_START, - start_range, &start_allow, - start_part, &start_dist ); - PED_ASSERT (start_dist >= 0, return); - } else { - end_allow &= ~MOVE_DOWN; - end_want = prefer_snap (end, SECT_END, - end_range, &end_allow, - end_part, &end_dist ); - PED_ASSERT (end_dist >= 0, return); - } - } - - /* New positions */ - start = ( start_want == MOVE_DOWN ? start_part->geom.start : - ( start_want == MOVE_UP ? start_part->geom.end + 1 : - start ) ); - end = ( end_want == MOVE_DOWN ? end_part->geom.start - 1 : - ( end_want == MOVE_UP ? end_part->geom.end : - end ) ); - PED_ASSERT (ped_geometry_test_sector_inside(start_range,start), return); - PED_ASSERT (ped_geometry_test_sector_inside (end_range, end), return); - PED_ASSERT (start <= end, - PED_DEBUG (0, "start = %d, end = %d\n", start, end)); - ped_geometry_set (new_geom, start, end - start + 1); -} - -/* This functions constructs a constraint from the following information: - * start, is_start_exact, end, is_end_exact. - * - * If is_start_exact == 1, then the constraint requires start be as given in - * "start". Otherwise, the constraint does not set any requirements on the - * start. - */ -static PedConstraint* -constraint_from_start_end (PedDevice* dev, PedGeometry* range_start, - PedGeometry* range_end) -{ - return ped_constraint_new (ped_alignment_any, ped_alignment_any, - range_start, range_end, 1, dev->length); -} - -static PedConstraint* -constraint_intersect_and_destroy (PedConstraint* a, PedConstraint* b) -{ - PedConstraint* result = ped_constraint_intersect (a, b); - ped_constraint_destroy (a); - ped_constraint_destroy (b); - return result; -} - -void -help_on (char* topic) -{ - Command* cmd; - - cmd = command_get (commands, topic); - if (!cmd) return; - - command_print_help (cmd); -} - -static int -do_check (PedDevice** dev) -{ - PedDisk* disk; - PedFileSystem* fs; - PedPartition* part = NULL; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (!_partition_warn_busy (part)) - goto error_destroy_disk; - - if (!ped_disk_check (disk)) - goto error_destroy_disk; - - fs = ped_file_system_open (&part->geom); - if (!fs) - goto error_destroy_disk; - if (!ped_file_system_check (fs, g_timer)) - goto error_close_fs; - ped_file_system_close (fs); - ped_disk_destroy (disk); - return 1; - -error_close_fs: - ped_file_system_close (fs); -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_cp (PedDevice** dev) -{ - PedDisk* src_disk; - PedDisk* dst_disk; - PedPartition* src = NULL; - PedPartition* dst = NULL; - PedFileSystem* src_fs; - PedFileSystem* dst_fs; - PedFileSystemType* dst_fs_type; - - dst_disk = ped_disk_new (*dev); - if (!dst_disk) - goto error; - - src_disk = dst_disk; - if (!command_line_is_integer ()) { - if (!command_line_get_disk (_("Source device?"), &src_disk)) - goto error_destroy_disk; - } - - if (!command_line_get_partition (_("Source partition number?"), - src_disk, &src)) - goto error_destroy_disk; - if (src->type == PED_PARTITION_EXTENDED) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't copy an extended partition.")); - goto error_destroy_disk; - } - if (!_partition_warn_busy (src)) - goto error_destroy_disk; - - if (!command_line_get_partition (_("Destination partition number?"), - dst_disk, &dst)) - goto error_destroy_disk; - if (!_partition_warn_busy (dst)) - goto error_destroy_disk; - -/* do the copy */ - src_fs = ped_file_system_open (&src->geom); - if (!src_fs) - goto error_destroy_disk; - dst_fs = ped_file_system_copy (src_fs, &dst->geom, g_timer); - if (!dst_fs) - goto error_close_src_fs; - dst_fs_type = dst_fs->type; /* may be different to src_fs->type */ - ped_file_system_close (src_fs); - ped_file_system_close (dst_fs); - -/* update the partition table, close disks */ - if (!ped_partition_set_system (dst, dst_fs_type)) - goto error_destroy_disk; - if (!ped_disk_commit (dst_disk)) - goto error_destroy_disk; - if (src_disk != dst_disk) - ped_disk_destroy (src_disk); - ped_disk_destroy (dst_disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_close_src_fs: - ped_file_system_close (src_fs); -error_destroy_disk: - if (src_disk && src_disk != dst_disk) - ped_disk_destroy (src_disk); - ped_disk_destroy (dst_disk); -error: - return 0; -} - -void -print_commands_help () -{ - int i; - - for (i=0; commands [i]; i++) - command_print_summary (commands [i]); -} - -void -print_options_help () -{ - int i; - - for (i=0; options_help [i][0]; i++) { - printf (" -%c, --%-23.23s %s\n", - options_help [i][0][0], - options_help [i][0], - _(options_help [i][1])); - } -} - -int -do_help (PedDevice** dev) -{ - if (command_line_get_word_count ()) { - char* word = command_line_pop_word (); - if (word) { - help_on (word); - free (word); - } - } else { - print_commands_help(); - } - return 1; -} - -static int -do_mklabel (PedDevice** dev) -{ - PedDisk* disk; - const PedDiskType* type = ped_disk_probe (*dev); - - ped_exception_fetch_all (); - disk = ped_disk_new (*dev); - if (!disk) ped_exception_catch (); - ped_exception_leave_all (); - - if (disk) { - if (!_disk_warn_busy (disk)) - goto error_destroy_disk; - if (!opt_script_mode && !_disk_warn_loss (disk)) - goto error_destroy_disk; - - ped_disk_destroy (disk); - } - - if (!command_line_get_disk_type (_("New disk label type?"), &type)) - goto error; - - disk = ped_disk_new_fresh (*dev, type); - if (!disk) - goto error; - - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - ped_disk_destroy (disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_mkfs (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part = NULL; - const PedFileSystemType* type = ped_file_system_type_get ("ext2"); - PedFileSystem* fs; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!opt_script_mode && !_partition_warn_loss()) - goto error_destroy_disk; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (!_partition_warn_busy (part)) - goto error_destroy_disk; - if (!command_line_get_fs_type (_("File system type?"), &type)) - goto error_destroy_disk; - - fs = ped_file_system_create (&part->geom, type, g_timer); - if (!fs) - goto error_destroy_disk; - ped_file_system_close (fs); - - if (!ped_partition_set_system (part, type)) - goto error_destroy_disk; - if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) - ped_partition_set_flag (part, PED_PARTITION_LBA, 1); - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - ped_disk_destroy (disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_mkpart (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part; - PedPartitionType part_type; - const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); - PedSector start = 0, end = 0; - PedGeometry *range_start = NULL, *range_end = NULL; - PedConstraint* user_constraint; - PedConstraint* dev_constraint; - PedConstraint* final_constraint; - char* peek_word; - char* part_name = NULL; - char *start_usr = NULL, *end_usr = NULL; - char *start_sol = NULL, *end_sol = NULL; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { - part_type = PED_PARTITION_NORMAL; - } else { - if (!command_line_get_part_type (_("Partition type?"), - disk, &part_type)) - goto error_destroy_disk; - } - - if (ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_PARTITION_NAME)) - part_name = command_line_get_word (_("Partition name?"), - "", NULL, 1); - - peek_word = command_line_peek_word (); - if (part_type == PED_PARTITION_EXTENDED - || (peek_word && isdigit (peek_word[0]))) { - fs_type = NULL; - } else { - if (!command_line_get_fs_type (_("File system type?"), - &fs_type)) - goto error_destroy_disk; - } - if (peek_word) - ped_free (peek_word); - - if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) - goto error_destroy_disk; - if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) - goto error_destroy_disk; - - /* processing starts here */ - part = ped_partition_new (disk, part_type, fs_type, start, end); - if (!part) - goto error_destroy_disk; - - snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end); - - /* create constraints */ - user_constraint = constraint_from_start_end (*dev, range_start, - range_end); - PED_ASSERT (user_constraint != NULL, return 0); - - dev_constraint = ped_device_get_constraint (*dev); - PED_ASSERT (dev_constraint != NULL, return 0); - - final_constraint = ped_constraint_intersect (user_constraint, - dev_constraint); - if (!final_constraint) - goto error_destroy_simple_constraints; - - /* subject to partition constraint */ - ped_exception_fetch_all(); - if (!ped_disk_add_partition (disk, part, final_constraint)) { - ped_exception_leave_all(); - - if (ped_disk_add_partition (disk, part, - ped_constraint_any (*dev))) { - start_usr = ped_unit_format (*dev, start); - end_usr = ped_unit_format (*dev, end); - start_sol = ped_unit_format (*dev, part->geom.start); - end_sol = ped_unit_format (*dev, part->geom.end); - - switch (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_YES_NO, - _("You requested a partition from %s to %s.\n" - "The closest location we can manage is " - "%s to %s. " - "Is this still acceptable to you?"), - start_usr, end_usr, start_sol, end_sol)) - { - case PED_EXCEPTION_YES: - /* all is well in this state */ - break; - case PED_EXCEPTION_NO: - case PED_EXCEPTION_UNHANDLED: - default: - /* undo partition addition */ - goto error_remove_part; - } - } else { - goto error_remove_part; - } - } else { - ped_exception_leave_all(); - } - ped_exception_catch(); - - /* set minor attributes */ - if (part_name) - PED_ASSERT (ped_partition_set_name (part, part_name), return 0); - if (!ped_partition_set_system (part, fs_type)) - goto error_destroy_disk; - if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) - ped_partition_set_flag (part, PED_PARTITION_LBA, 1); - - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - - /* clean up */ - ped_constraint_destroy (final_constraint); - ped_constraint_destroy (user_constraint); - ped_constraint_destroy (dev_constraint); - - ped_disk_destroy (disk); - - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if (start_usr != NULL) - ped_free (start_usr); - if (end_usr != NULL) - ped_free (end_usr); - if (start_sol != NULL) - ped_free (start_sol); - if (end_sol != NULL) - ped_free (end_sol); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_remove_part: - ped_disk_remove_partition (disk, part); - ped_constraint_destroy (final_constraint); -error_destroy_simple_constraints: - ped_constraint_destroy (user_constraint); - ped_constraint_destroy (dev_constraint); - ped_partition_destroy (part); -error_destroy_disk: - ped_disk_destroy (disk); -error: - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if (start_usr != NULL) - ped_free (start_usr); - if (end_usr != NULL) - ped_free (end_usr); - if (start_sol != NULL) - ped_free (start_sol); - if (end_sol != NULL) - ped_free (end_sol); - - return 0; -} - -static int -do_mkpartfs (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part; - PedPartitionType part_type; - const PedFileSystemType* fs_type = ped_file_system_type_get ("ext2"); - PedSector start = 0, end = 0; - PedGeometry *range_start = NULL, *range_end = NULL; - PedConstraint* user_constraint; - PedConstraint* dev_constraint; - PedConstraint* final_constraint; - PedFileSystem* fs; - char* part_name = NULL; - char *start_usr = NULL, *end_usr = NULL; - char *start_sol = NULL, *end_sol = NULL; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) { - part_type = PED_PARTITION_NORMAL; - } else { - if (!command_line_get_part_type (_("Partition type?"), - disk, &part_type)) - goto error_destroy_disk; - } - - if (ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_PARTITION_NAME)) - part_name = command_line_get_word (_("Partition name?"), - "", NULL, 1); - - if (part_type == PED_PARTITION_EXTENDED) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("An extended partition cannot hold a file system. " - "Did you want mkpart?")); - goto error_destroy_disk; - } - - if (!command_line_get_fs_type (_("File system type?"), &fs_type)) - goto error_destroy_disk; - if (!command_line_get_sector (_("Start?"), *dev, &start, - &range_start)) - goto error_destroy_disk; - if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) - goto error_destroy_disk; - - /* attempt to create the partition now */ - part = ped_partition_new (disk, part_type, fs_type, start, end); - if (!part) - goto error_destroy_disk; - - snap_to_boundaries (&part->geom, NULL, disk, range_start, range_end); - - /* create constraints */ - user_constraint = constraint_from_start_end (*dev, range_start, - range_end); - PED_ASSERT (user_constraint != NULL, return 0); - - dev_constraint = ped_device_get_constraint (*dev); - PED_ASSERT (dev_constraint != NULL, return 0); - - final_constraint = ped_constraint_intersect (user_constraint, - dev_constraint); - if (!final_constraint) - goto error_destroy_simple_constraints; - - /* subject to partition constraint */ - ped_exception_fetch_all(); - if (!ped_disk_add_partition (disk, part, final_constraint)) { - ped_exception_leave_all(); - - if (ped_disk_add_partition (disk, part, - ped_constraint_any (*dev))) { - start_usr = ped_unit_format (*dev, start); - end_usr = ped_unit_format (*dev, end); - start_sol = ped_unit_format (*dev, part->geom.start); - end_sol = ped_unit_format (*dev, part->geom.end); - - switch (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_YES_NO, - _("You requested a partition from %s to %s.\n" - "The closest location we can manage is " - "%s to %s. " - "Is this still acceptable to you?"), - start_usr, end_usr, start_sol, end_sol)) { - case PED_EXCEPTION_YES: - /* all is well in this state */ - break; - case PED_EXCEPTION_NO: - case PED_EXCEPTION_UNHANDLED: - default: - /* undo partition addition */ - goto error_remove_part; - } - } else { - goto error_remove_part; - } - } else { - ped_exception_leave_all(); - } - ped_exception_catch(); - - /* set LBA flag automatically if available */ - if (ped_partition_is_flag_available (part, PED_PARTITION_LBA)) - ped_partition_set_flag (part, PED_PARTITION_LBA, 1); - - /* fs creation */ - fs = ped_file_system_create (&part->geom, fs_type, g_timer); - if (!fs) - goto error_destroy_disk; - ped_file_system_close (fs); - - if (!ped_partition_set_system (part, fs_type)) - goto error_destroy_disk; - - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - - /* clean up */ - ped_constraint_destroy (final_constraint); - ped_constraint_destroy (user_constraint); - ped_constraint_destroy (dev_constraint); - - ped_disk_destroy (disk); - - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if (start_usr != NULL) - ped_free (start_usr); - if (end_usr != NULL) - ped_free (end_usr); - if (start_sol != NULL) - ped_free (start_sol); - if (end_sol != NULL) - ped_free (end_sol); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_remove_part: - ped_disk_remove_partition (disk, part); - ped_constraint_destroy (final_constraint); -error_destroy_simple_constraints: - ped_constraint_destroy (user_constraint); - ped_constraint_destroy (dev_constraint); - ped_partition_destroy (part); -error_destroy_disk: - ped_disk_destroy (disk); -error: - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if (start_usr != NULL) - ped_free (start_usr); - if (end_usr != NULL) - ped_free (end_usr); - if (start_sol != NULL) - ped_free (start_sol); - if (end_sol != NULL) - ped_free (end_sol); - - return 0; -} - -static int -do_move (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part = NULL; - PedFileSystem* fs; - PedFileSystem* fs_copy; - PedConstraint* constraint; - PedSector start = 0, end = 0; - PedGeometry *range_start = NULL, *range_end = NULL; - PedGeometry old_geom, new_geom; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (!_partition_warn_busy (part)) - goto error_destroy_disk; - if (part->type == PED_PARTITION_EXTENDED) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't move an extended partition.")); - goto error_destroy_disk; - } - old_geom = part->geom; - fs = ped_file_system_open (&old_geom); - if (!fs) - goto error_destroy_disk; - - /* get new target */ - if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) - goto error_close_fs; - end = start + old_geom.length - 1; - if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) - goto error_close_fs; - - /* set / test on "disk" */ - if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1)) - goto error_close_fs; - snap_to_boundaries (&new_geom, NULL, disk, range_start, range_end); - - constraint = constraint_intersect_and_destroy ( - ped_file_system_get_copy_constraint (fs, *dev), - constraint_from_start_end(*dev,range_start,range_end)); - if (!ped_disk_set_partition_geom (disk, part, constraint, - new_geom.start, new_geom.end)) - goto error_destroy_constraint; - ped_constraint_destroy (constraint); - if (ped_geometry_test_overlap (&old_geom, &part->geom)) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't move a partition onto itself. Try using " - "resize, perhaps?")); - goto error_close_fs; - } - - /* do the move */ - fs_copy = ped_file_system_copy (fs, &part->geom, g_timer); - if (!fs_copy) - goto error_close_fs; - ped_file_system_close (fs_copy); - ped_file_system_close (fs); - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - ped_disk_destroy (disk); - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_constraint: - ped_constraint_destroy (constraint); -error_close_fs: - ped_file_system_close (fs); -error_destroy_disk: - ped_disk_destroy (disk); -error: - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - return 0; -} - -static int -do_name (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part = NULL; - char* name; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - - name = command_line_get_word (_("Partition name?"), - ped_partition_get_name (part), NULL, 0); - if (!name) - goto error_destroy_disk; - if (!ped_partition_set_name (part, name)) - goto error_free_name; - free (name); - - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - ped_disk_destroy (disk); - return 1; - -error_free_name: - free (name); -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static char* -partition_print_flags (PedPartition* part) -{ - PedPartitionFlag flag; - int first_flag; - const char* name; - char* res = ped_malloc(1); - void* _res = res; - - *res = '\0'; - - first_flag = 1; - for (flag = ped_partition_flag_next (0); flag; - flag = ped_partition_flag_next (flag)) { - if (ped_partition_get_flag (part, flag)) { - if (first_flag) - first_flag = 0; - else { - _res = res; - ped_realloc (&_res, strlen (res) - + 1 + 2); - res = _res; - strncat (res, ", ", 2); - } - - name = _(ped_partition_flag_get_name (flag)); - _res = res; - ped_realloc (&_res, strlen (res) + 1 - + strlen (name)); - res = _res; - strncat (res, name, 21); - } - } - - return res; -} - -/* Prints a sector out, first in compact form, and then with a percentage. - * Eg: 32Gb (40%) - */ -static void -print_sector_compact_and_percent (PedSector sector, PedDevice* dev) -{ - char* compact; - char* percent; - - if (ped_unit_get_default() == PED_UNIT_PERCENT) - compact = ped_unit_format (dev, sector); - else - compact = ped_unit_format_custom (dev, sector, - PED_UNIT_COMPACT); - - percent = ped_unit_format_custom (dev, sector, PED_UNIT_PERCENT); - - printf ("%s (%s)\n", compact, percent); - - ped_free (compact); - ped_free (percent); -} - -static int -partition_print (PedPartition* part) -{ - PedFileSystem* fs; - PedConstraint* resize_constraint; - char* flags; - - fs = ped_file_system_open (&part->geom); - if (!fs) - return 1; - - putchar ('\n'); - - flags = partition_print_flags (part); - - printf (_("Minor: %d\n"), part->num); - printf (_("Flags: %s\n"), flags); - printf (_("File System: %s\n"), fs->type->name); - fputs (_("Size: "), stdout); - print_sector_compact_and_percent (part->geom.length, part->geom.dev); - - resize_constraint = ped_file_system_get_resize_constraint (fs); - if (resize_constraint) { - fputs (_("Minimum size: "), stdout); - print_sector_compact_and_percent (resize_constraint->min_size, - part->geom.dev); - fputs (_("Maximum size: "), stdout); - print_sector_compact_and_percent (resize_constraint->max_size, - part->geom.dev); - ped_constraint_destroy (resize_constraint); - } - - putchar ('\n'); - - ped_free (flags); - ped_file_system_close (fs); - - return 1; -} - -static int -do_print (PedDevice** dev) -{ - PedUnit default_unit; - PedDisk* disk; - Table* table; - int has_extended; - int has_name; - int has_devices_arg = 0; - int has_free_arg = 0; - int has_list_arg = 0; - int has_num_arg = 0; - char* transport[13] = {"unknown", "scsi", "ide", "dac960", - "cpqarray", "file", "ataraid", "i2o", - "ubd", "dasd", "viodasd", "sx8", "dm"}; - char* peek_word; - char* start; - char* end; - char* size; - const char* name; - char* tmp; - wchar_t* table_rendered; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - peek_word = command_line_peek_word (); - if (peek_word) { - if (strncmp (peek_word, "devices", 7) == 0) { - command_line_pop_word(); - has_devices_arg = 1; - } - else if (strncmp (peek_word, "free", 4) == 0) { - command_line_pop_word (); - has_free_arg = 1; - } - else if (strncmp (peek_word, "list", 4) == 0 || - strncmp (peek_word, "all", 3) == 0) { - command_line_pop_word(); - has_list_arg = 1; - } - else - has_num_arg = isdigit(peek_word[0]); - - ped_free (peek_word); - } - - if (has_devices_arg) { - char* dev_name; - PedDevice* current_dev = NULL; - - ped_device_probe_all(); - - while ((current_dev = ped_device_get_next(current_dev))) { - end = ped_unit_format_byte (current_dev, - current_dev->length - * current_dev->sector_size); - printf ("%s (%s)\n", current_dev->path, end); - ped_free (end); - } - - dev_name = xstrdup ((*dev)->path); - ped_device_free_all (); - - *dev = ped_device_get (dev_name); - if (!*dev) - return 0; - if (!ped_device_open (*dev)) - return 0; - - ped_free (dev_name); - - return 1; - } - - else if (has_list_arg) - return _print_list (); - - else if (has_num_arg) { - PedPartition* part = NULL; - int status = 0; - if (command_line_get_partition ("", disk, &part)) - status = partition_print (part); - ped_disk_destroy (disk); - return status; - } - - start = ped_unit_format (*dev, 0); - default_unit = ped_unit_get_default (); - end = ped_unit_format_byte (*dev, (*dev)->length * (*dev)->sector_size - - (default_unit == PED_UNIT_CHS || - default_unit == PED_UNIT_CYLINDER)); - - if (opt_machine_mode) { - switch (default_unit) { - case PED_UNIT_CHS: puts ("CHS;"); - break; - case PED_UNIT_CYLINDER: puts ("CYL;"); - break; - default: puts ("BYT;"); - break; - - } - printf ("%s:%s:%s:%lld:%lld:%s:%s;\n", - (*dev)->path, end, transport[(*dev)->type], - (*dev)->sector_size, (*dev)->phys_sector_size, - disk->type->name, (*dev)->model); - } else { - printf (_("Model: %s (%s)\n"), - (*dev)->model, transport[(*dev)->type]); - printf (_("Disk %s: %s\n"), (*dev)->path, end); - printf (_("Sector size (logical/physical): %lldB/%lldB\n"), - (*dev)->sector_size, (*dev)->phys_sector_size); - } - - ped_free (start); - ped_free (end); - - if (ped_unit_get_default () == PED_UNIT_CHS - || ped_unit_get_default () == PED_UNIT_CYLINDER) { - PedCHSGeometry* chs = &(*dev)->bios_geom; - char* cyl_size = ped_unit_format_custom (*dev, - chs->heads * chs->sectors, - PED_UNIT_KILOBYTE); - - if (opt_machine_mode) { - printf ("%d:%d:%d:%s;\n", - chs->cylinders, chs->heads, chs->sectors, cyl_size); - } else { - printf (_("BIOS cylinder,head,sector geometry: %d,%d,%d. " - "Each cylinder is %s.\n"), - chs->cylinders, chs->heads, chs->sectors, cyl_size); - } - - ped_free (cyl_size); - } - - if (!opt_machine_mode) { - printf (_("Partition Table: %s\n"), disk->type->name); - putchar ('\n'); - } - - has_extended = ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_EXTENDED); - has_name = ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_PARTITION_NAME); - - - PedPartition* part; - if (!opt_machine_mode) { - StrList *row1; - - if (ped_unit_get_default() == PED_UNIT_CHS) { - row1 = str_list_create (_("Number"), _("Start"), - _("End"), NULL); - } else { - row1 = str_list_create (_("Number"), _("Start"), - _("End"), _("Size"), NULL); - } - - if (has_extended) - str_list_append (row1, _("Type")); - - str_list_append (row1, _("File system")); - - if (has_name) - str_list_append (row1, _("Name")); - - str_list_append (row1, _("Flags")); - - - table = table_new (str_list_length(row1)); - - table_add_row_from_strlist (table, row1); - - for (part = ped_disk_next_partition (disk, NULL); part; - part = ped_disk_next_partition (disk, part)) { - - if ((!has_free_arg && !ped_partition_is_active(part)) || - part->type & PED_PARTITION_METADATA) - continue; - - tmp = ped_malloc (4); - - if (part->num >= 0) - sprintf (tmp, "%2d ", part->num); - else - sprintf (tmp, "%2s ", ""); - - StrList *row = str_list_create (tmp, NULL); - - start = ped_unit_format (*dev, part->geom.start); - end = ped_unit_format_byte ( - *dev, - (part->geom.end + 1) * (*dev)->sector_size - 1); - size = ped_unit_format (*dev, part->geom.length); - if (ped_unit_get_default() == PED_UNIT_CHS) { - str_list_append (row, start); - str_list_append (row, end); - } else { - str_list_append (row, start); - str_list_append (row, end); - str_list_append (row, size); - } - - if (!(part->type & PED_PARTITION_FREESPACE)) { - if (has_extended) { - name = ped_partition_type_get_name (part->type); - str_list_append (row, name); - } - - str_list_append (row, part->fs_type ? - part->fs_type->name : ""); - - if (has_name) { - name = ped_partition_get_name (part); - str_list_append (row, name); - } - - str_list_append (row, partition_print_flags (part)); - } else { - if (has_extended) - str_list_append (row, ""); - str_list_append (row, _("Free Space")); - if (has_name) - str_list_append (row, ""); - str_list_append (row, ""); - } - - //PED_ASSERT (row.cols == caption.cols) - table_add_row_from_strlist (table, row); - str_list_destroy (row); - } - - table_rendered = table_render (table); -#ifdef ENABLE_NLS - printf("%ls\n", table_rendered); -#else - printf("%s\n", table_rendered); -#endif - ped_free (table_rendered); - table_destroy (table); - str_list_destroy (row1); - - } else { - - for (part = ped_disk_next_partition (disk, NULL); part; - part = ped_disk_next_partition (disk, part)) { - - if ((!has_free_arg && !ped_partition_is_active(part)) || - part->type & PED_PARTITION_METADATA) - continue; - - if (part->num >= 0) - printf ("%d:", part->num); - else - fputs ("1:", stdout); - - printf ("%s:", ped_unit_format (*dev, part->geom.start)); - printf ("%s:", ped_unit_format_byte ( - *dev, - (part->geom.end + 1) * - (*dev)->sector_size - 1)); - - if (ped_unit_get_default() != PED_UNIT_CHS) - printf ("%s:", ped_unit_format (*dev, - part->geom.length)); - - if (!(part->type & PED_PARTITION_FREESPACE)) { - - if (part->fs_type) - printf ("%s:", part->fs_type->name); - else - putchar (':'); - - if (has_name) - printf ("%s:", _(ped_partition_get_name (part))); - else - putchar (':'); - - printf ("%s;\n", partition_print_flags (part)); - - } else { - puts ("free;"); - } - } - } - - ped_disk_destroy (disk); - - return 1; - - ped_disk_destroy (disk); -error: - return 0; -} - -static int -_print_list () -{ - PedDevice *current_dev = NULL; - - ped_device_probe_all(); - - while ((current_dev = ped_device_get_next(current_dev))) { - do_print (¤t_dev); - putchar ('\n'); - } - - return 1; -} - -static int -do_quit (PedDevice** dev) -{ - _done (*dev); - exit (0); -} - -static PedPartitionType -_disk_get_part_type_for_sector (PedDisk* disk, PedSector sector) -{ - PedPartition* extended; - - extended = ped_disk_extended_partition (disk); - if (!extended - || !ped_geometry_test_sector_inside (&extended->geom, sector)) - return 0; - - return PED_PARTITION_LOGICAL; -} - -/* This function checks if "part" contains a file system, and returs - * 0 if either no file system was found, or the user declined to add it. - * 1 if a file system was found, and the user chose to add it. - * -1 if the user chose to cancel the entire search. - */ -static int -_rescue_add_partition (PedPartition* part) -{ - const PedFileSystemType* fs_type; - PedGeometry* probed; - PedExceptionOption ex_opt; - PedConstraint* constraint; - char* found_start; - char* found_end; - - fs_type = ped_file_system_probe (&part->geom); - if (!fs_type) - return 0; - probed = ped_file_system_probe_specific (fs_type, &part->geom); - if (!probed) - return 0; - - if (!ped_geometry_test_inside (&part->geom, probed)) { - ped_geometry_destroy (probed); - return 0; - } - - constraint = ped_constraint_exact (probed); - if (!ped_disk_set_partition_geom (part->disk, part, constraint, - probed->start, probed->end)) { - ped_constraint_destroy (constraint); - return 0; - } - ped_constraint_destroy (constraint); - - found_start = ped_unit_format (probed->dev, probed->start); - found_end = ped_unit_format (probed->dev, probed->end); - ex_opt = ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_YES_NO_CANCEL, - _("A %s %s partition was found at %s -> %s. " - "Do you want to add it to the partition table?"), - fs_type->name, ped_partition_type_get_name (part->type), - found_start, found_end); - ped_geometry_destroy (probed); - ped_free (found_start); - ped_free (found_end); - - switch (ex_opt) { - case PED_EXCEPTION_CANCEL: return -1; - case PED_EXCEPTION_NO: return 0; - default: break; - } - - ped_partition_set_system (part, fs_type); - ped_disk_commit (part->disk); - return 1; -} - -/* hack: we only iterate through the start, since most (all) fs's have their - * superblocks at the start. We'll need to change this if we generalize - * for RAID, or something... - */ -static int -_rescue_pass (PedDisk* disk, PedGeometry* start_range, PedGeometry* end_range) -{ - PedSector start; - PedGeometry start_geom_exact; - PedGeometry entire_dev; - PedConstraint constraint; - PedPartition* part; - PedPartitionType part_type; - - part_type = _disk_get_part_type_for_sector ( - disk, (start_range->start + end_range->end) / 2); - - ped_geometry_init (&entire_dev, disk->dev, 0, disk->dev->length); - - ped_timer_reset (g_timer); - ped_timer_set_state_name (g_timer, _("searching for file systems")); - for (start = start_range->start; start <= start_range->end; start++) { - ped_timer_update (g_timer, 1.0 * (start - start_range->start) - / start_range->length); - - ped_geometry_init (&start_geom_exact, disk->dev, start, 1); - ped_constraint_init ( - &constraint, ped_alignment_any, ped_alignment_any, - &start_geom_exact, &entire_dev, - 1, disk->dev->length); - part = ped_partition_new (disk, part_type, NULL, start, - end_range->end); - if (!part) { - ped_constraint_done (&constraint); - continue; - } - - ped_exception_fetch_all (); - if (ped_disk_add_partition (disk, part, &constraint)) { - ped_exception_leave_all (); - switch (_rescue_add_partition (part)) { - case 1: - ped_constraint_done (&constraint); - return 1; - - case 0: - ped_disk_remove_partition (disk, part); - break; - - case -1: - goto error_remove_partition; - } - } else { - ped_exception_leave_all (); - } - ped_partition_destroy (part); - ped_constraint_done (&constraint); - } - ped_timer_update (g_timer, 1.0); - - return 1; - -error_remove_partition: - ped_disk_remove_partition (disk, part); - ped_partition_destroy (part); - ped_constraint_done (&constraint); - return 0; -} - -static int -do_rescue (PedDevice** dev) -{ - PedDisk* disk; - PedSector start = 0, end = 0; - PedSector fuzz; - PedGeometry probe_start_region; - PedGeometry probe_end_region; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_sector (_("Start?"), *dev, &start, NULL)) - goto error_destroy_disk; - if (!command_line_get_sector (_("End?"), *dev, &end, NULL)) - goto error_destroy_disk; - - fuzz = PED_MAX (PED_MIN ((end - start) / 10, MEGABYTE_SECTORS(*dev)), - MEGABYTE_SECTORS(*dev) * 16); - - ped_geometry_init (&probe_start_region, *dev, - PED_MAX(start - fuzz, 0), - PED_MIN(2 * fuzz, (*dev)->length - (start - fuzz))); - ped_geometry_init (&probe_end_region, *dev, - PED_MAX(end - fuzz, 0), - PED_MIN(2 * fuzz, (*dev)->length - (end - fuzz))); - - if (!_rescue_pass (disk, &probe_start_region, &probe_end_region)) - goto error_destroy_disk; - - ped_disk_destroy (disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_resize (PedDevice** dev) -{ - PedDisk *disk; - PedPartition *part = NULL; - PedFileSystem *fs; - PedConstraint *constraint; - PedSector start, end; - PedGeometry *range_start = NULL, *range_end = NULL; - PedGeometry new_geom; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (part->type != PED_PARTITION_EXTENDED) { - if (!_partition_warn_busy (part)) - goto error_destroy_disk; - } - - start = part->geom.start; - end = part->geom.end; - if (!command_line_get_sector (_("Start?"), *dev, &start, &range_start)) - goto error_destroy_disk; - if (!command_line_get_sector (_("End?"), *dev, &end, &range_end)) - goto error_destroy_disk; - - if (!ped_geometry_init (&new_geom, *dev, start, end - start + 1)) - goto error_destroy_disk; - snap_to_boundaries (&new_geom, &part->geom, disk, - range_start, range_end); - - if (part->type == PED_PARTITION_EXTENDED) { - constraint = constraint_from_start_end (*dev, - range_start, range_end); - if (!ped_disk_set_partition_geom (disk, part, constraint, - new_geom.start, new_geom.end)) - goto error_destroy_constraint; - ped_partition_set_system (part, NULL); - } else { - fs = ped_file_system_open (&part->geom); - if (!fs) - goto error_destroy_disk; - constraint = constraint_intersect_and_destroy ( - ped_file_system_get_resize_constraint (fs), - constraint_from_start_end ( - *dev, range_start, range_end)); - if (!ped_disk_set_partition_geom (disk, part, constraint, - new_geom.start, new_geom.end)) - goto error_close_fs; - if (!ped_file_system_resize (fs, &part->geom, g_timer)) - goto error_close_fs; - /* may have changed... eg fat16 -> fat32 */ - ped_partition_set_system (part, fs->type); - ped_file_system_close (fs); - } - - ped_disk_commit (disk); - ped_constraint_destroy (constraint); - ped_disk_destroy (disk); - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_close_fs: - ped_file_system_close (fs); -error_destroy_constraint: - ped_constraint_destroy (constraint); -error_destroy_disk: - ped_disk_destroy (disk); -error: - if (range_start != NULL) - ped_geometry_destroy (range_start); - if (range_end != NULL) - ped_geometry_destroy (range_end); - return 0; -} - -static int -do_rm (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part = NULL; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (!_partition_warn_busy (part)) - goto error_destroy_disk; - - ped_disk_delete_partition (disk, part); - ped_disk_commit (disk); - ped_disk_destroy (disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_select (PedDevice** dev) -{ - PedDevice* new_dev = *dev; - - if (!command_line_get_device (_("New device?"), &new_dev)) - return 0; - if (!ped_device_open (new_dev)) - return 0; - - ped_device_close (*dev); - *dev = new_dev; - print_using_dev (*dev); - return 1; -} - -static int -do_set (PedDevice** dev) -{ - PedDisk* disk; - PedPartition* part = NULL; - PedPartitionFlag flag; - int state; - - disk = ped_disk_new (*dev); - if (!disk) - goto error; - - if (!command_line_get_partition (_("Partition number?"), disk, &part)) - goto error_destroy_disk; - if (!command_line_get_part_flag (_("Flag to Invert?"), part, &flag)) - goto error_destroy_disk; - state = (ped_partition_get_flag (part, flag) == 0 ? 1 : 0); - - if (!is_toggle_mode) { - if (!command_line_get_state (_("New state?"), &state)) - goto error_destroy_disk; - } - - if (!ped_partition_set_flag (part, flag, state)) - goto error_destroy_disk; - if (!ped_disk_commit (disk)) - goto error_destroy_disk; - ped_disk_destroy (disk); - - if ((*dev)->type != PED_DEVICE_FILE) - disk_is_modified = 1; - - return 1; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return 0; -} - -static int -do_toggle (PedDevice **dev) -{ - int result; - - is_toggle_mode = 1; - result = do_set (dev); - is_toggle_mode = 0; - - return result; -} - -static int -do_unit (PedDevice** dev) -{ - PedUnit unit = ped_unit_get_default (); - if (!command_line_get_unit (_("Unit?"), &unit)) - return 0; - ped_unit_set_default (unit); - return 1; -} - -static int -do_version (PedDevice** dev) -{ - printf ("\n%s\n%s", - prog_name, - _(copyright_msg)); - return 1; -} - -static void -_init_messages () -{ - StrList* list; - int first; - PedFileSystemType* fs_type; - PedDiskType* disk_type; - PedPartitionFlag part_flag; - PedUnit unit; - -/* flags */ - first = 1; - list = str_list_create (_(flag_msg_start), NULL); - for (part_flag = ped_partition_flag_next (0); part_flag; - part_flag = ped_partition_flag_next (part_flag)) { - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, - _(ped_partition_flag_get_name (part_flag))); - } - str_list_append (list, "\n"); - - flag_msg = str_list_convert (list); - str_list_destroy (list); - -/* units */ - first = 1; - list = str_list_create (_(unit_msg_start), NULL); - for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) { - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, ped_unit_get_name (unit)); - } - str_list_append (list, "\n"); - - unit_msg = str_list_convert (list); - str_list_destroy (list); - -/* disk type */ - list = str_list_create (_(label_type_msg_start), NULL); - - first = 1; - for (disk_type = ped_disk_type_get_next (NULL); - disk_type; disk_type = ped_disk_type_get_next (disk_type)) { - if (disk_type->ops->write == NULL) - continue; - - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, disk_type->name); - } - str_list_append (list, "\n"); - - label_type_msg = str_list_convert (list); - str_list_destroy (list); - -/* mkfs - file system types */ - list = str_list_create (_(fs_type_msg_start), NULL); - - first = 1; - for (fs_type = ped_file_system_type_get_next (NULL); - fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { - if (fs_type->ops->create == NULL) - continue; - - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, fs_type->name); - } - str_list_append (list, "\n"); - - mkfs_fs_type_msg = str_list_convert (list); - str_list_destroy (list); - -/* mkpart - file system types */ - list = str_list_create (_(fs_type_msg_start), NULL); - - first = 1; - for (fs_type = ped_file_system_type_get_next (NULL); - fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, fs_type->name); - } - str_list_append (list, "\n"); - - mkpart_fs_type_msg = str_list_convert (list); - str_list_destroy (list); - -/* resize - file system types */ - list = str_list_create (_(resize_msg_start), NULL); - - first = 1; - for (fs_type = ped_file_system_type_get_next (NULL); - fs_type; fs_type = ped_file_system_type_get_next (fs_type)) { - if (fs_type->ops->resize == NULL) - continue; - - if (first) - first = 0; - else - str_list_append (list, ", "); - str_list_append (list, fs_type->name); - } - str_list_append (list, "\n"); - - resize_fs_type_msg = str_list_convert (list); - str_list_destroy (list); -} - -static void -_done_messages () -{ - free (flag_msg); - free (mkfs_fs_type_msg); - free (mkpart_fs_type_msg); - free (resize_fs_type_msg); - free (label_type_msg); -} - -static void -_init_commands () -{ - command_register (commands, command_create ( - str_list_create_unique ("check", _("check"), NULL), - do_check, - str_list_create ( -_("check NUMBER do a simple check on the file " - "system"), -NULL), - str_list_create (_(number_msg), NULL), 1)); - - command_register (commands, command_create ( - str_list_create_unique ("cp", _("cp"), NULL), - do_cp, - str_list_create ( -_("cp [FROM-DEVICE] FROM-NUMBER TO-NUMBER copy file system to another " - "partition"), -NULL), - str_list_create (_(number_msg), _(device_msg), NULL), 1)); - - command_register (commands, command_create ( - str_list_create_unique ("help", _("help"), NULL), - do_help, - str_list_create ( -_("help [COMMAND] print general help, or help " - "on COMMAND"), -NULL), - NULL, 1)); - - command_register (commands, command_create ( - str_list_create_unique ("mklabel", _("mklabel"), "mktable", _("mktable"), NULL), - do_mklabel, - str_list_create ( -_("mklabel,mktable LABEL-TYPE create a new disklabel " - "(partition table)"), -NULL), - str_list_create (label_type_msg, NULL), 1)); - - command_register (commands, command_create ( - str_list_create_unique ("mkfs", _("mkfs"), NULL), - do_mkfs, - str_list_create ( -_("mkfs NUMBER FS-TYPE make a FS-TYPE file " - "system on partititon NUMBER"), -NULL), - str_list_create (_(number_msg), _(mkfs_fs_type_msg), NULL), 1)); - - command_register (commands, command_create ( - str_list_create_unique ("mkpart", _("mkpart"), NULL), - do_mkpart, - str_list_create ( -_("mkpart PART-TYPE [FS-TYPE] START END make a partition"), -NULL), - str_list_create (_(part_type_msg), - _(mkpart_fs_type_msg), - _(start_end_msg), - "\n", -_("'mkpart' makes a partition without creating a new file system on the " - "partition. FS-TYPE may be specified to set an appropriate partition ID.\n"), -NULL), 1)); - - command_register (commands, command_create ( - str_list_create_unique ("mkpartfs", _("mkpartfs"), NULL), - do_mkpartfs, - str_list_create ( -_("mkpartfs PART-TYPE FS-TYPE START END make a partition with a " - "file system"), -NULL), - str_list_create (_(part_type_msg), _(start_end_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("move", _("move"), NULL), - do_move, - str_list_create ( -_("move NUMBER START END move partition NUMBER"), -NULL), - str_list_create (_(number_msg), _(start_end_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("name", _("name"), NULL), - do_name, - str_list_create ( -_("name NUMBER NAME name partition NUMBER as NAME"), -NULL), - str_list_create (_(number_msg), _(name_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("print", _("print"), NULL), - do_print, - str_list_create ( -_("print [devices|free|list,all|NUMBER] display the partition table, " - "available devices, free space, all found partitions, or a particular " - "partition"), -NULL), - str_list_create ( -_("Without arguments, 'print' displays the entire partition table. However " - "with the following arguments it performs various other actions.\n"), -_(" devices : display all active block devices\n"), -_(" free : display information about free unpartitioned space on the " - "current block device\n"), -_(" list, all : display the partition tables of all active block devices\n"), -_(" NUMBER : display more detailed information about this particular " - "partition\n"), -NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("quit", _("quit"), NULL), - do_quit, - str_list_create ( -_("quit exit program"), -NULL), - NULL, 1)); - -command_register (commands, command_create ( - str_list_create_unique ("rescue", _("rescue"), NULL), - do_rescue, - str_list_create ( -_("rescue START END rescue a lost partition near " -"START and END"), -NULL), - str_list_create (_(start_end_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("resize", _("resize"), NULL), - do_resize, - str_list_create ( -_("resize NUMBER START END resize partition NUMBER and " -"its file system"), -NULL), - str_list_create (_(number_msg), - _(start_end_msg), - _(resize_fs_type_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("rm", _("rm"), NULL), - do_rm, - str_list_create ( -_("rm NUMBER delete partition NUMBER"), -NULL), - str_list_create (_(number_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("select", _("select"), NULL), - do_select, - str_list_create ( -_("select DEVICE choose the device to edit"), -NULL), - str_list_create (_(device_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("set", _("set"), NULL), - do_set, - str_list_create ( -_("set NUMBER FLAG STATE change the FLAG on partition " - "NUMBER"), -NULL), - str_list_create (_(number_msg), flag_msg, _(state_msg), NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("toggle", _("toggle"), NULL), - do_toggle, - str_list_create ( -_("toggle [NUMBER [FLAG]] toggle the state of FLAG on " - "partition NUMBER"), -NULL), - str_list_create (_(number_msg), flag_msg, NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("unit", _("unit"), NULL), - do_unit, - str_list_create ( -_("unit UNIT set the default unit to UNIT"), -NULL), - str_list_create (unit_msg, NULL), 1)); - -command_register (commands, command_create ( - str_list_create_unique ("version", _("version"), NULL), - do_version, - str_list_create ( -_("version display the version number " -"and copyright information of GNU Parted"), -NULL), - str_list_create ( -_("'version' displays copyright and version information corresponding to this " -"copy of GNU Parted\n"), -NULL), 1)); - -} - -static void -_done_commands () -{ -Command** walk; - -for (walk = commands; *walk; walk++) { - command_destroy (*walk); - *walk = NULL; -} -} - -static void -_init_i18n () -{ -/* intialize i18n */ -#ifdef ENABLE_NLS -setlocale(LC_ALL, ""); -bindtextdomain(PACKAGE, LOCALEDIR); -textdomain(PACKAGE); -#endif /* ENABLE_NLS */ -} - -void -_version () -{ - version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, VERSION, AUTHORS, - (char *) NULL); -} - -static int -_parse_options (int* argc_ptr, char*** argv_ptr) -{ -int opt, help = 0, list = 0, version = 0, wrong = 0; - -while (1) -{ - opt = getopt_long (*argc_ptr, *argv_ptr, "hilmsv", - options, NULL); - if (opt == -1) - break; - - switch (opt) { - case 'h': help = 1; break; - case 'l': list = 1; break; - case 'm': opt_machine_mode = 1; break; - case 's': opt_script_mode = 1; break; - case 'v': version = 1; break; - case PRETEND_INPUT_TTY: - pretend_input_tty = 1; - break; - default: wrong = 1; break; - } -} - -if (wrong == 1) { - fprintf (stderr, - _("Usage: %s [-hlmsv] [DEVICE [COMMAND [PARAMETERS]]...]\n"), - program_name); - return 0; -} - -if (version == 1) { - _version (); - exit (EXIT_SUCCESS); -} - -if (help == 1) { - help_msg (); - exit (EXIT_SUCCESS); -} - -if (list == 1) { - _print_list (); - exit (EXIT_SUCCESS); -} - -*argc_ptr -= optind; -*argv_ptr += optind; -return 1; -} - -static PedDevice* -_choose_device (int* argc_ptr, char*** argv_ptr) -{ -PedDevice* dev; - -/* specified on comand line? */ -if (*argc_ptr) { - dev = ped_device_get ((*argv_ptr) [0]); - if (!dev) - return NULL; - (*argc_ptr)--; - (*argv_ptr)++; -} else { -retry: - ped_device_probe_all (); - dev = ped_device_get_next (NULL); - if (!dev) { - if (ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_CANCEL, - _("No device found")) - == PED_EXCEPTION_RETRY) - goto retry; - else - return NULL; - } -} - -if (!ped_device_open (dev)) - return NULL; -return dev; -} - -static PedDevice* -_init (int* argc_ptr, char*** argv_ptr) -{ -PedDevice* dev; - -#ifdef ENABLE_MTRACE -mtrace(); -#endif - -_init_i18n (); -if (!init_ui ()) - goto error; -_init_messages (); -_init_commands (); - -if (!_parse_options (argc_ptr, argv_ptr)) - goto error_done_commands; - -#ifdef HAVE_GETUID - if (getuid() != 0 && !opt_script_mode) { - puts (_("WARNING: You are not superuser. Watch out for " - "permissions.")); - } -#endif - -dev = _choose_device (argc_ptr, argv_ptr); -if (!dev) - goto error_done_commands; - -g_timer = ped_timer_new (_timer_handler, &timer_context); -if (!g_timer) - goto error_done_commands; -timer_context.last_update = 0; - -return dev; - -error_done_commands: -_done_commands (); -_done_messages (); -done_ui (); -error: -return NULL; -} - -static void -_done (PedDevice* dev) -{ -if (dev->boot_dirty && dev->type != PED_DEVICE_FILE) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK, - _("You should reinstall your boot loader before " - "rebooting. Read section 4 of the Parted User " - "documentation for more information.")); -} - -#if !defined(__sun) -if (!opt_script_mode && !opt_machine_mode && disk_is_modified) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, - _("You may need to update /etc/fstab.\n")); -} -#endif - -ped_device_close (dev); - -ped_timer_destroy (g_timer); -_done_commands (); -_done_messages (); -done_ui(); -} - -int -main (int argc, char** argv) -{ - PedDevice* dev; - int status; - - program_name = argv[0]; - atexit (close_stdout); - - dev = _init (&argc, &argv); - if (!dev) - return 1; - - if (argc || opt_script_mode) - status = non_interactive_mode (&dev, commands, argc, argv); - else - status = interactive_mode (&dev, commands); - - _done (dev); - - return !status; -} diff --git a/usr/src/cmd/parted/strlist.h b/usr/src/cmd/parted/strlist.h deleted file mode 100644 index 81f8e8e9f7..0000000000 --- a/usr/src/cmd/parted/strlist.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef STRLIST_H_INCLUDED -#define STRLIST_H_INCLUDED - -#include - -#ifndef ENABLE_NLS -# define L_(str) str -# ifdef wchar_t -# undef wchar_t -# endif -# define wchar_t char -#endif - -typedef struct _StrList StrList; -struct _StrList { - StrList* next; - const wchar_t* str; -}; - -extern char* language; -extern char* gettext_charset; -extern char* term_charset; - -extern StrList* str_list_create (const char* first, ...); -extern StrList* str_list_create_unique (const char* first, ...); -extern void str_list_destroy (StrList* list); -extern void str_list_destroy_node (StrList* list); - -extern StrList* str_list_duplicate (const StrList* list); -extern StrList* str_list_duplicate_node (const StrList* list); -extern StrList* str_list_insert (StrList* list, const char* str); -extern StrList* str_list_append (StrList* list, const char* str); -extern StrList* str_list_append_unique (StrList* list, const char* str); -extern StrList* str_list_join (StrList* a, StrList* b); -extern char* str_list_convert (const StrList* list); -extern char* str_list_convert_node (const StrList* list); - -extern void str_list_print (const StrList* list); -extern void str_list_print_wrap (const StrList* list, int line_length, - int offset, int indent); -extern int str_list_match_any (const StrList* list, const char* str); -extern int str_list_match_node (const StrList* list, const char* str); -extern StrList* str_list_match (const StrList* list, const char* str); - -extern int str_list_length (const StrList* list); - -#endif /* STRLIST_H_INCLUDED */ - diff --git a/usr/src/cmd/parted/table.c b/usr/src/cmd/parted/table.c deleted file mode 100644 index 0a5ed6a409..0000000000 --- a/usr/src/cmd/parted/table.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * TODO: - make right and centered alignment possible - */ -/* - parted - a frontend to libparted - Copyright (C) 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#include - -#include -#include - -#include -#include -#include - -#include "xalloc.h" -#include "strlist.h" - -#ifdef ENABLE_NLS -# define L_(str) L##str -#else -# define L_(str) str -# ifdef wchar_t -# undef wchar_t -# endif -# define wchar_t char -# define wcslen strlen -# define wcswidth strnlen -# define wcscat strcat -# define wcsdup xstrdup -#endif - - -static const unsigned int MAX_WIDTH = 512; -static const wchar_t* DELIMITER = L_(" "); -static const wchar_t* COLSUFFIX = L_("\n"); - -typedef struct -{ - unsigned int ncols; - unsigned int nrows; - wchar_t*** rows; - int* widths; -} Table; - - -Table* table_new(int ncols) -{ - assert ( ncols >= 0 ); - - Table *t = xmalloc (sizeof(*t)); - - t->ncols = ncols; - t->nrows = 0; - t->rows = (wchar_t***)NULL; - t->widths = NULL; - - return t; -} - - -void table_destroy (Table* t) -{ - unsigned int r, c; - - assert (t); - assert (t->ncols > 0); - - for (r = 0; r < t->nrows; ++r) - { - for (c = 0; c < t->ncols; ++c) - free (t->rows[r][c]); - free (t->rows[r]); - } - - if (t->rows) - free (t->rows); - - if (t->widths) - free (t->widths); - - free (t); -} - - -static int max (int x, int y) -{ - return x > y ? x : y; -} - - -static void table_calc_column_widths (Table* t) -{ - unsigned int r, c; - - assert(t); - assert(t->ncols > 0); - - if (!t->widths) - t->widths = xmalloc (t->ncols * sizeof(t->widths[0])); - - for (c = 0; c < t->ncols; ++c) - t->widths[c] = 0; - - for (r = 0; r < t->nrows; ++r) - for (c = 0; c < t->ncols; ++c) - { - t->widths[c] = max ( t->widths[c], - wcswidth(t->rows[r][c], - MAX_WIDTH) ); - } -} - - -/* - * add a row which is a string array of ncols elements. - * 'row' will get freed by table_destroy; you must not free it - * yourself. - */ -void table_add_row (Table* t, wchar_t** row) -{ - assert(t); - - /*unsigned int i; - fputs ("adding row: ", stdout); - for (i = 0; i < t->ncols; ++i) - printf("[%s]", row[i]); - putchar ('\n');*/ - - t->rows = xrealloc (t->rows, (t->nrows + 1) * sizeof(wchar_t***)); - - t->rows[t->nrows] = row; - - ++t->nrows; - - table_calc_column_widths (t); -} - - -void table_add_row_from_strlist (Table* t, StrList* list) -{ - wchar_t** row = xmalloc (str_list_length(list) * sizeof(*row)); - int i = 0; - - while (list) - { - row[i] = wcsdup (list->str); - if (row[i] == NULL) - xalloc_die (); - - - list = list->next; - ++i; - } - - table_add_row (t, row); -} - - -/* render a row */ -static void table_render_row (Table* t, int rownum, int ncols, wchar_t** s) -{ - wchar_t** row = t->rows[rownum]; - int len = 1, i; - size_t newsize; - - assert(t); - assert(s != NULL); - - for (i = 0; i < ncols; ++i) - len += t->widths[i] + wcslen(DELIMITER); - - len += wcslen(COLSUFFIX); - - newsize = (wcslen(*s) + len + 1) * sizeof(wchar_t); - *s = xrealloc (*s, newsize); - - for (i = 0; i < ncols; ++i) - { - int j; - int nspaces = max(t->widths[i] - wcswidth(row[i], MAX_WIDTH), - 0); - wchar_t* pad = xmalloc ((nspaces + 1) * sizeof(*pad)); - - for (j = 0; j < nspaces; ++j) - pad[j] = L' '; - - pad[nspaces] = L_('\0'); - - wcscat (*s, row[i]); - wcscat (*s, pad); - if (i + 1 < ncols) - wcscat (*s, DELIMITER); - - free (pad); - pad = NULL; - } - - wcscat (*s, COLSUFFIX); -} - - -/* - * Render the rows. - * \p s must be a null-terminated string. - */ -static void table_render_rows (Table* t, wchar_t** s) -{ - unsigned int i; - - assert (**s == L_('\0')); - for (i = 0; i < t->nrows; ++i) - table_render_row (t, i, t->ncols, s); -} - -/* - * Render the table to a string. - * You are responsible for freeing the returned string. - */ -wchar_t* table_render(Table* t) -{ - wchar_t* s = xmalloc (sizeof(*s)); - - *s = L_('\0'); - table_render_rows (t, &s); - return s; -} diff --git a/usr/src/cmd/parted/table.h b/usr/src/cmd/parted/table.h deleted file mode 100644 index 9dc8ac77e5..0000000000 --- a/usr/src/cmd/parted/table.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include - -#include - -#include "strlist.h" - -#ifdef ENABLE_NLS -# include -#else -# ifdef wchar_t -# undef wchar_t -# endif -# define wchar_t char -#endif - - -/* opaque data type */ -typedef void Table; - -Table* table_new(int ncols); -void table_destroy (Table* t); - -/* - * you must not free neither 'row' nor 'list' - * -- this will be done by table_destroy() - */ -void table_add_row (Table* t, wchar_t** row); -void table_add_row_from_strlist (Table* t, StrList* list); - -wchar_t* table_render(Table* t); - diff --git a/usr/src/cmd/parted/ui.c b/usr/src/cmd/parted/ui.c deleted file mode 100644 index a53643fa41..0000000000 --- a/usr/src/cmd/parted/ui.c +++ /dev/null @@ -1,1542 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2001, 2002, 2006, 2007 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include "command.h" -#include "strlist.h" -#include "ui.h" -#include "error.h" - -#define N_(String) String -#if ENABLE_NLS -# include -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#ifdef HAVE_LIBREADLINE - -#ifdef HAVE_TERMCAP_H -#include -#else -extern int tgetnum (char* key); -#endif - -#include -#include - -#ifndef HAVE_RL_COMPLETION_MATCHES -#define rl_completion_matches completion_matches -#endif - -#ifndef rl_compentry_func_t -#define rl_compentry_func_t void -#endif - -#endif /* HAVE_LIBREADLINE */ - -#ifndef SA_SIGINFO -# ifndef HAVE_SIGACTION - -struct sigaction { -}; - -static inline int -sigaction (int signum, const struct* sigaction, struct* sigaction) -{ -} - -# endif /* HAVE_SIGACTON */ - -struct siginfo_t { - int si_code; -}; - -#endif /* SA_SIGINFO */ - -#ifndef SEGV_MAPERR -# define SEGV_MAPERR (INTMAX - 1) -#endif - -#ifndef SEGV_ACCERR -# define SEGV_ACCERR (INTMAX - 2) -#endif - -#ifndef FPE_INTDIV -# define FPE_INTDIV (INTMAX - 1) -#endif - -#ifndef FPE_INTOVF -# define FPE_INTOVF (INTMAX - 2) -#endif - -#ifndef FPE_FLTDIV -# define FPE_FLTDIV (INTMAX - 3) -#endif - -#ifndef FPE_FLTOVF -# define FPE_FLTOVF (INTMAX - 4) -#endif - -#ifndef FPE_FLTUND -# define FPE_FLTUND (INTMAX - 5) -#endif - -#ifndef FPE_FLTRES -# define FPE_FLTRES (INTMAX - 6) -#endif - -#ifndef FPE_FLTINV -# define FPE_FLTINV (INTMAX - 7) -#endif - -#ifndef FPE_FLTSUB -# define FPE_FLTSUB (INTMAX - 8) -#endif - -#ifndef ILL_ILLOPC -# define ILL_ILLOPC (INTMAX - 1) -#endif - -#ifndef ILL_ILLOPN -# define ILL_ILLOPN (INTMAX - 2) -#endif - -#ifndef ILL_ILLADR -# define ILL_ILLADR (INTMAX - 3) -#endif - -#ifndef ILL_ILLTRP -# define ILL_ILLTRP (INTMAX - 4) -#endif - -#ifndef ILL_PRVOPC -# define ILL_PRVOPC (INTMAX - 5) -#endif - -#ifndef ILL_PRVREG -# define ILL_PRVREG (INTMAX - 6) -#endif - -#ifndef ILL_COPROC -# define ILL_COPROC (INTMAX - 7) -#endif - -#ifndef ILL_BADSTK -# define ILL_BADSTK (INTMAX - 8) -#endif - -char* prog_name = "GNU Parted " VERSION "\n"; - -static char* banner_msg = N_( -"Welcome to GNU Parted! Type 'help' to view a list of commands.\n"); - -static char* usage_msg = N_( -"Usage: parted [OPTION]... [DEVICE [COMMAND [PARAMETERS]...]...]\n" -"Apply COMMANDs with PARAMETERS to DEVICE. If no COMMAND(s) are given, " -"run in\ninteractive mode.\n"); - -static char* bug_msg = N_( -"\n\nYou found a bug in GNU Parted! Here's what you have to do:\n\n" -"Don't panic! The bug has most likely not affected any of your data.\n" -"Help us to fix this bug by doing the following:\n\n" -"Check whether the bug has already been fixed by checking\n" -"the last version of GNU Parted that you can find at:\n\n" -"\thttp://ftp.gnu.org/gnu/parted/\n\n" -"Please check this version prior to bug reporting.\n\n" -"If this has not been fixed yet or if you don't know how to check,\n" -"please visit the GNU Parted website:\n\n" -"\thttp://www.gnu.org/software/parted\n\n" -"for further information.\n\n" -"Your report should contain the version of this release (%s)\n" -"along with the error message below, the output of\n\n" -"\tparted DEVICE unit co print unit s print\n\n" -"and the following history of commands you entered.\n" -"Also include any additional information about your setup you\n" -"consider important.\n"); - -#define MAX_WORDS 1024 - -static StrList* command_line; -static Command** commands; -static StrList* ex_opt_str [64]; -static StrList* on_list; -static StrList* off_list; -static StrList* on_off_list; -static StrList* fs_type_list; -static StrList* disk_type_list; - -static struct { - const StrList* possibilities; - const StrList* cur_pos; - int in_readline; - sigjmp_buf jmp_state; -} readline_state; - -static struct sigaction sig_segv; -static struct sigaction sig_int; -static struct sigaction sig_fpe; -static struct sigaction sig_ill; - -volatile int got_ctrl_c = 0; /* used in exception_handler */ - -int -screen_width () -{ - int width = 0; - - if (opt_script_mode || pretend_input_tty) - return 32768; /* no wrapping ;) */ - -/* HACK: don't specify termcap separately - it'll annoy the users. */ -#ifdef HAVE_LIBREADLINE - width = tgetnum ("co"); -#endif - - if (width <= 0) - width = 80; - - return width; -} - -void -wipe_line () -{ - if (opt_script_mode) - return; - - /* yuck */ - fputs ("\r " - " \r", stdout); -} - -#ifdef HAVE_LIBREADLINE -/* returns matching commands for text */ -static char* -command_generator (char* text, int state) -{ - if (!state) - readline_state.cur_pos = readline_state.possibilities; - - while (readline_state.cur_pos) { - const StrList* cur = readline_state.cur_pos; - readline_state.cur_pos = cur->next; - if (str_list_match_node (cur, text)) - return str_list_convert_node (cur); - } - - return NULL; -} - -/* completion function for readline() */ -char** -complete_function (char* text, int start, int end) -{ - return rl_completion_matches (text, - (rl_compentry_func_t*) command_generator); -} - -static void -_add_history_unique (const char* line) -{ - HIST_ENTRY* last_entry = current_history (); - if (!strlen (line)) - return; - if (!last_entry || strcmp (last_entry->line, line)) - add_history ((char*) line); -} - -/* Prints command history, to be used before aborting */ -static void -_dump_history () -{ - int i = 0; - HIST_ENTRY** all_entries = history_list (); - - fputs (_("\nCommand History:\n"), stdout); - while (all_entries[i]) { - puts(all_entries[i++]->line); - } -} - -#else - -/* Print nothing because Readline is absent. */ -static inline void -_dump_history (void) -{ -} - -#endif /* HAVE_LIBREADLINE */ - -static void -mask_signal() -{ - sigset_t curr; - sigset_t prev; - - sigfillset(&curr); - sigprocmask(SIG_SETMASK, &curr, &prev); -} - -/* Resets the environment by jumping to the initial state - * saved during ui intitialisation. - * Pass 1 as the parameter if you want to quit parted, - * 0 if you just want to reset to the command prompt. - */ -static void -reset_env (int quit) -{ - int in_readline = readline_state.in_readline; - - readline_state.in_readline = 0; - - if (in_readline) { - putchar ('\n'); - if (quit) - exit (0); - - siglongjmp (readline_state.jmp_state, 1); - } -} - -/* Signal handler for SIGINT using 'sigaction'. */ -static void -sa_sigint_handler (int signum, siginfo_t* info, void *ucontext) -{ - if (info) - sigaction (SIGINT, &sig_int, NULL); - - got_ctrl_c = 1; - reset_env (0); -} - -/* Signal handler for SIGINT using 'signal'. */ -static void -s_sigint_handler (int signum) -{ - signal (SIGINT, &s_sigint_handler); - mask_signal (); - sa_sigint_handler (signum, NULL, NULL); -} - -/* Signal handler for SIGSEGV using 'sigaction'. */ -static void -sa_sigsegv_handler (int signum, siginfo_t* info, void* ucontext) -{ - printf (bug_msg, VERSION); - _dump_history (); - - if (!info) - abort (); - - sigaction (SIGSEGV, &sig_segv, NULL); - - switch (info->si_code) { - - case SEGV_MAPERR: - fputs(_("\nError: SEGV_MAPERR (Address not mapped " - "to object)\n"), stdout); - PED_ASSERT(0, break); /* Force a backtrace */ - break; - - case SEGV_ACCERR: - fputs(_("\nError: SEGV_ACCERR (Invalid permissions " - "for mapped object)\n"), stdout); - break; - - default: - fputs(_("\nError: A general SIGSEGV signal was " - "encountered.\n"), stdout); - PED_ASSERT(0, break); /* Force a backtrace */ - break; - } - - abort (); -} - -/* Signal handler for SIGSEGV using 'signal'. */ -static void -s_sigsegv_handler (int signum) -{ - signal (SIGSEGV, &s_sigsegv_handler); - mask_signal (); - sa_sigsegv_handler (signum, NULL, NULL); -} - -/* Signal handler for SIGFPE using 'sigaction'. */ -static void -sa_sigfpe_handler (int signum, siginfo_t* info, void* ucontext) -{ - printf (bug_msg, VERSION); - _dump_history (); - - if (!info) - abort (); - - sigaction (SIGFPE, &sig_fpe, NULL); - - switch (info->si_code) { - - case FPE_INTDIV: - fputs(_("\nError: FPE_INTDIV (Integer: " - "divide by zero)"), stdout); - break; - - case FPE_INTOVF: - fputs(_("\nError: FPE_INTOVF (Integer: " - "overflow)"), stdout); - break; - - case FPE_FLTDIV: - fputs(_("\nError: FPE_FLTDIV (Float: " - "divide by zero)"), stdout); - break; - - case FPE_FLTOVF: - fputs(_("\nError: FPE_FLTOVF (Float: " - "overflow)"), stdout); - break; - - case FPE_FLTUND: - fputs(_("\nError: FPE_FLTUND (Float: " - "underflow)"), stdout); - break; - - case FPE_FLTRES: - fputs(_("\nError: FPE_FLTRES (Float: " - "inexact result)"), stdout); - break; - - case FPE_FLTINV: - fputs(_("\nError: FPE_FLTINV (Float: " - "invalid operation)"), stdout); - break; - - case FPE_FLTSUB: - fputs(_("\nError: FPE_FLTSUB (Float: " - "subscript out of range)"), stdout); - break; - - default: - fputs(_("\nError: A general SIGFPE signal " - "was encountered."), stdout); - break; - - } - - abort (); -} - -/* Signal handler for SIGFPE using 'signal'. */ -static void -s_sigfpe_handler (int signum) -{ - signal (SIGFPE, &s_sigfpe_handler); - mask_signal (); - sa_sigfpe_handler (signum, NULL, NULL); -} - -/* Signal handler for SIGILL using 'sigaction'. */ -static void -sa_sigill_handler (int signum, siginfo_t* info, void* ucontext) -{ - printf (bug_msg, VERSION); - _dump_history (); - - if (!info) - abort(); - - sigaction (SIGILL, &sig_ill, NULL); - - switch (info->si_code) { - - case ILL_ILLOPC: - fputs(_("\nError: ILL_ILLOPC " - "(Illegal Opcode)"), stdout); - break; - - case ILL_ILLOPN: - fputs(_("\nError: ILL_ILLOPN " - "(Illegal Operand)"), stdout); - break; - - case ILL_ILLADR: - fputs(_("\nError: ILL_ILLADR " - "(Illegal addressing mode)"), stdout); - break; - - case ILL_ILLTRP: - fputs(_("\nError: ILL_ILLTRP " - "(Illegal Trap)"), stdout); - break; - - case ILL_PRVOPC: - fputs(_("\nError: ILL_PRVOPC " - "(Privileged Opcode)"), stdout); - break; - - case ILL_PRVREG: - fputs(_("\nError: ILL_PRVREG " - "(Privileged Register)"), stdout); - break; - - case ILL_COPROC: - fputs(_("\nError: ILL_COPROC " - "(Coprocessor Error)"), stdout); - break; - - case ILL_BADSTK: - fputs(_("\nError: ILL_BADSTK " - "(Internal Stack Error)"), stdout); - break; - - default: - fputs(_("\nError: A general SIGILL " - "signal was encountered."), stdout); - break; - } - - abort (); -} - -/* Signal handler for SIGILL using 'signal'. */ -static void -s_sigill_handler (int signum) -{ - signal (SIGILL, &s_sigill_handler); - mask_signal (); - sa_sigill_handler (signum, NULL, NULL); -} - -static char* -_readline (const char* prompt, const StrList* possibilities) -{ - char* line; - - readline_state.possibilities = possibilities; - readline_state.cur_pos = NULL; - readline_state.in_readline = 1; - - if (sigsetjmp (readline_state.jmp_state,1)) - return NULL; - - wipe_line (); -#ifdef HAVE_LIBREADLINE - if (!opt_script_mode) { - /* XXX: why isn't prompt const? */ - line = readline ((char*) prompt); - if (line) - _add_history_unique (line); - } else -#endif - { - fputs (prompt, stdout); - fflush (stdout); - line = (char*) malloc (256); - if (fgets (line, 256, stdin) && strcmp (line, "") != 0) { -#ifndef HAVE_LIBREADLINE - /* Echo the input line, to be consistent with - how readline-5.2 works. */ - fputs (line, stdout); - fflush (stdout); -#endif - line [strlen (line) - 1] = 0; /* kill trailing CR */ - } else { - free (line); - line = NULL; - } - } - - readline_state.in_readline = 0; - return line; -} - -static PedExceptionOption -option_get_next (PedExceptionOption options, PedExceptionOption current) -{ - PedExceptionOption i; - - if (current == 0) - i = PED_EXCEPTION_OPTION_FIRST; - else - i = current * 2; - - for (; i <= options; i *= 2) { - if (options & i) - return i; - } - return 0; -} - -static void -_print_exception_text (PedException* ex) -{ - StrList* text; - - wipe_line (); - - if (ex->type == PED_EXCEPTION_BUG) { - printf (bug_msg, VERSION); - text = str_list_create ("\n", ex->message, "\n\n", NULL); - } else { - text = str_list_create ( - _(ped_exception_get_type_string (ex->type)), - ": ", ex->message, "\n", NULL); - } - - str_list_print_wrap (text, screen_width (), 0, 0); - str_list_destroy (text); -} - -static PedExceptionOption -exception_handler (PedException* ex) -{ - PedExceptionOption opt; - - _print_exception_text (ex); - - /* only one choice? Take it ;-) */ - opt = option_get_next (ex->options, 0); - if (!option_get_next (ex->options, opt)) - return opt; - - /* script-mode: don't handle the exception */ - if (opt_script_mode || (!isatty (0) && !pretend_input_tty)) - return PED_EXCEPTION_UNHANDLED; - - got_ctrl_c = 0; - - do { - opt = command_line_get_ex_opt ("", ex->options); - } while (opt == PED_EXCEPTION_UNHANDLED - && (isatty (0) || pretend_input_tty) && !got_ctrl_c); - - if (got_ctrl_c) { - got_ctrl_c = 0; - opt = PED_EXCEPTION_UNHANDLED; - } - - return opt; -} - -void -command_line_push_word (const char* word) -{ - command_line = str_list_append (command_line, word); -} - -char* -command_line_pop_word () -{ - char* result; - StrList* next; - - PED_ASSERT (command_line != NULL, return NULL); - - result = str_list_convert_node (command_line); - next = command_line->next; - - str_list_destroy_node (command_line); - command_line = next; - return result; -} - -void -command_line_flush () -{ - str_list_destroy (command_line); - command_line = NULL; -} - -char* -command_line_peek_word () -{ - if (command_line) - return str_list_convert_node (command_line); - else - return NULL; -} - -int -command_line_get_word_count () -{ - return str_list_length (command_line); -} - -static int -_str_is_spaces (const char* str) -{ - while (isspace (*str)) - str++; - - return *str == 0; -} - -/* "multi_word mode" is the "normal" mode... many words can be typed, - * delimited by spaces, etc. - * In single-word mode, only one word is parsed per line. - * Leading and trailing spaces are removed. For example: " a b c " - * is a single word "a b c". The motivation for this mode is partition - * names, etc. In single-word mode, the empty string is a word. - * (but not in multi-word mode). - */ -void -command_line_push_line (const char* line, int multi_word) -{ - int quoted = 0; - char quote_char = 0; - char this_word [256]; - int i; - - do { - while (*line == ' ') - line++; - - i = 0; - for (; *line; line++) { - if (*line == ' ' && !quoted) { - if (multi_word) - break; - - /* single word: check for trailing spaces + eol */ - if (_str_is_spaces (line)) - break; - } - - if (!quoted && strchr ("'\"", *line)) { - quoted = 1; - quote_char = *line; - continue; - } - - if (quoted && *line == quote_char) { - quoted = 0; - continue; - } - - /* hack: escape characters */ - if (quoted && line[0] == '\\' && line[1]) - line++; - - this_word [i++] = *line; - } - if (i || !multi_word) { - this_word [i] = 0; - command_line_push_word (this_word); - } - } while (*line && multi_word); -} - -static char* -realloc_and_cat (char* str, const char* append) -{ - int length = strlen (str) + strlen (append) + 1; - char* new_str = realloc (str, length); - - strcat (new_str, append); - return new_str; -} - -static char* -_construct_prompt (const char* head, const char* def, - const StrList* possibilities) -{ - char* prompt = strdup (head); - - if (def && possibilities) - PED_ASSERT (str_list_match_any (possibilities, def), - return NULL); - - if (possibilities && str_list_length (possibilities) < 8) { - const StrList* walk; - - if (strlen (prompt)) - prompt = realloc_and_cat (prompt, " "); - - for (walk = possibilities; walk; walk = walk->next) { - if (walk != possibilities) - prompt = realloc_and_cat (prompt, "/"); - - if (def && str_list_match_node (walk, def) == 2) { - prompt = realloc_and_cat (prompt, "["); - prompt = realloc_and_cat (prompt, def); - prompt = realloc_and_cat (prompt, "]"); - } else { - char* text = str_list_convert_node (walk); - prompt = realloc_and_cat (prompt, text); - free (text); - } - } - prompt = realloc_and_cat (prompt, "? "); - } else if (def) { - if (strlen (prompt)) - prompt = realloc_and_cat (prompt, " "); - prompt = realloc_and_cat (prompt, "["); - prompt = realloc_and_cat (prompt, def); - prompt = realloc_and_cat (prompt, "]? "); - } else { - if (strlen (prompt)) - prompt = realloc_and_cat (prompt, " "); - } - - return prompt; -} - -void -command_line_prompt_words (const char* prompt, const char* def, - const StrList* possibilities, int multi_word) -{ - char* line; - char* real_prompt; - char* _def = (char*) def; - int _def_needs_free = 0; - - if (!def && str_list_length (possibilities) == 1) { - _def = str_list_convert_node (possibilities); - _def_needs_free = 1; - } - - if (opt_script_mode) { - if (_def) - command_line_push_line (_def, 0); - return; - } - - do { - real_prompt = _construct_prompt (prompt, _def, possibilities); - line = _readline (real_prompt, possibilities); - free (real_prompt); - if (!line) - break; - - if (!strlen (line)) { - if (_def) - command_line_push_line (_def, 0); - } else { - command_line_push_line (line, multi_word); - } - free (line); - } while (!command_line_get_word_count () && !_def); - - if (_def_needs_free) - free (_def); -} - -/** - * Get a word from command line. - * - * \param possibilities a StrList of valid strings, NULL if all are valid. - * \param multi_word whether multiple words are allowed. - * - * \return The word(s), or NULL if empty. - */ -char* -command_line_get_word (const char* prompt, const char* def, - const StrList* possibilities, int multi_word) -{ - do { - if (command_line_get_word_count ()) { - char* result = command_line_pop_word (); - StrList* result_node; - - if (!possibilities) - return result; - - result_node = str_list_match (possibilities, result); - if (result_node == NULL) - error (0, 0, _("invalid token: %s"), result); - free (result); - if (result_node) - return str_list_convert_node (result_node); - - command_line_flush (); - if (opt_script_mode) - return NULL; - } - - command_line_prompt_words (prompt, def, possibilities, - multi_word); - } while (command_line_get_word_count ()); - - return NULL; -} - -int -command_line_get_integer (const char* prompt, int* value) -{ - char def_str [10]; - char* input; - int valid; - - snprintf (def_str, 10, "%d", *value); - input = command_line_get_word (prompt, *value ? def_str : NULL, - NULL, 1); - if (!input) - return 0; - valid = sscanf (input, "%d", value); - free (input); - return valid; -} - -int -command_line_get_sector (const char* prompt, PedDevice* dev, PedSector* value, - PedGeometry** range) -{ - char* def_str; - char* input; - int valid; - - def_str = ped_unit_format (dev, *value); - input = command_line_get_word (prompt, *value ? def_str : NULL, - NULL, 1); - - /* def_str might have rounded *value a little bit. If the user picked - * the default, make sure the selected sector is identical to the - * default. - */ - if (input && *value && !strcmp (input, def_str)) { - if (range) { - *range = ped_geometry_new (dev, *value, 1); - ped_free (def_str); - return *range != NULL; - } - - ped_free (def_str); - return 1; - } - - ped_free (def_str); - if (!input) { - *value = 0; - if (range) - *range = NULL; - return 0; - } - - valid = ped_unit_parse (input, dev, value, range); - - free (input); - return valid; -} - -int -command_line_get_state (const char* prompt, int* value) -{ - char* def_word; - char* input; - - if (*value) - def_word = str_list_convert_node (on_list); - else - def_word = str_list_convert_node (off_list); - input = command_line_get_word (prompt, def_word, on_off_list, 1); - free (def_word); - if (!input) - return 0; - if (str_list_match_any (on_list, input)) - *value = 1; - else - *value = 0; - free (input); - return 1; -} - -int -command_line_get_device (const char* prompt, PedDevice** value) -{ - char* def_dev_name = *value ? (*value)->path : NULL; - char* dev_name; - PedDevice* dev; - - dev_name = command_line_get_word (prompt, def_dev_name, NULL, 1); - if (!dev_name) - return 0; - - dev = ped_device_get (dev_name); - free (dev_name); - if (!dev) - return 0; - - *value = dev; - return 1; -} - -int -command_line_get_disk (const char* prompt, PedDisk** value) -{ - PedDevice* dev = *value ? (*value)->dev : NULL; - - if (!command_line_get_device (prompt, &dev)) - return 0; - - if (dev != (*value)->dev) { - PedDisk* new_disk = ped_disk_new (dev); - if (!new_disk) - return 0; - *value = new_disk; - } - return 1; -} - -int -command_line_get_partition (const char* prompt, PedDisk* disk, - PedPartition** value) -{ - PedPartition* part; - - /* Flawed logic, doesn't seem to work?! - check = ped_disk_next_partition (disk, part); - part = ped_disk_next_partition (disk, check); - - if (part == NULL) { - - *value = check; - printf (_("The (only) primary partition has " - "been automatically selected\n")); - return 1; - - } else { - */ - int num = (*value) ? (*value)->num : 0; - - if (!command_line_get_integer (prompt, &num)) { - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Expecting a partition number.")); - return 0; - } - - part = ped_disk_get_partition (disk, num); - - if (!part) { - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Partition doesn't exist.")); - return 0; - } - - *value = part; - return 1; - //} -} - -int -command_line_get_fs_type (const char* prompt, const PedFileSystemType*(* value)) -{ - char* fs_type_name; - PedFileSystemType* fs_type; - - fs_type_name = command_line_get_word (prompt, - *value ? (*value)->name : NULL, - fs_type_list, 1); - if (!fs_type_name) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Expecting a file system type.")); - return 0; - } - - fs_type = ped_file_system_type_get (fs_type_name); - if (!fs_type) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Unknown file system type \"%s\"."), - fs_type_name); - return 0; - } - - free (fs_type_name); - *value = fs_type; - return 1; -} - -int -command_line_get_disk_type (const char* prompt, const PedDiskType*(* value)) -{ - char* disk_type_name; - - disk_type_name = command_line_get_word (prompt, - *value ? (*value)->name : NULL, - disk_type_list, 1); - if (!disk_type_name) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Expecting a disk label type.")); - return 0; - } - - *value = ped_disk_type_get (disk_type_name); - free (disk_type_name); - PED_ASSERT (*value != NULL, return 0); - return 1; -} - -int -command_line_get_part_flag (const char* prompt, const PedPartition* part, - PedPartitionFlag* flag) -{ - StrList* opts = NULL; - PedPartitionFlag walk = 0; - char* flag_name; - - while ( (walk = ped_partition_flag_next (walk)) ) { - if (ped_partition_is_flag_available (part, walk)) { - const char* walk_name; - - walk_name = ped_partition_flag_get_name (walk); - opts = str_list_append (opts, walk_name); - opts = str_list_append_unique (opts, _(walk_name)); - } - } - - flag_name = command_line_get_word (prompt, NULL, opts, 1); - str_list_destroy (opts); - - if (flag_name) { - *flag = ped_partition_flag_get_by_name (flag_name); - ped_free (flag_name); - return 1; - } else - return 0; -} - -static int -_can_create_primary (const PedDisk* disk) -{ - int i; - - for (i = 1; i <= ped_disk_get_max_primary_partition_count (disk); i++) { - if (!ped_disk_get_partition (disk, i)) - return 1; - } - - return 0; -} - -static int -_can_create_extended (const PedDisk* disk) -{ - if (!_can_create_primary (disk)) - return 0; - - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) - return 0; - - if (ped_disk_extended_partition (disk)) - return 0; - - return 1; -} - -static int -_can_create_logical (const PedDisk* disk) -{ - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)) - return 0; - - return ped_disk_extended_partition (disk) != 0; -} - -int -command_line_get_part_type (const char* prompt, const PedDisk* disk, - PedPartitionType* type) -{ - StrList* opts = NULL; - char* type_name; - - if (_can_create_primary (disk)) { - opts = str_list_append_unique (opts, "primary"); - opts = str_list_append_unique (opts, _("primary")); - } - if (_can_create_extended (disk)) { - opts = str_list_append_unique (opts, "extended"); - opts = str_list_append_unique (opts, _("extended")); - } - if (_can_create_logical (disk)) { - opts = str_list_append_unique (opts, "logical"); - opts = str_list_append_unique (opts, _("logical")); - } - if (!opts) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't create any more partitions.")); - return 0; - } - - type_name = command_line_get_word (prompt, NULL, opts, 1); - str_list_destroy (opts); - - if (!type_name) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Expecting a partition type.")); - return 0; - } - - if (!strcmp (type_name, "primary") - || !strcmp (type_name, _("primary"))) { - *type = 0; - } - if (!strcmp (type_name, "extended") - || !strcmp (type_name, _("extended"))) { - *type = PED_PARTITION_EXTENDED; - } - if (!strcmp (type_name, "logical") - || !strcmp (type_name, _("logical"))) { - *type = PED_PARTITION_LOGICAL; - } - - free (type_name); - return 1; -} - -PedExceptionOption -command_line_get_ex_opt (const char* prompt, PedExceptionOption options) -{ - StrList* options_strlist = NULL; - PedExceptionOption opt; - char* opt_name; - - for (opt = option_get_next (options, 0); opt; - opt = option_get_next (options, opt)) { - options_strlist = str_list_append_unique (options_strlist, - _(ped_exception_get_option_string (opt))); - options_strlist = str_list_append_unique (options_strlist, - ped_exception_get_option_string (opt)); - } - - opt_name = command_line_get_word (prompt, NULL, options_strlist, 1); - if (!opt_name) - return PED_EXCEPTION_UNHANDLED; - str_list_destroy (options_strlist); - - opt = PED_EXCEPTION_OPTION_FIRST; - while (1) { - if (strcmp (opt_name, - ped_exception_get_option_string (opt)) == 0) - break; - if (strcmp (opt_name, - _(ped_exception_get_option_string (opt))) == 0) - break; - opt = option_get_next (options, opt); - } - free (opt_name); - return opt; -} - -int -command_line_get_unit (const char* prompt, PedUnit* unit) -{ - StrList* opts = NULL; - PedUnit walk; - char* unit_name; - const char* default_unit_name; - - for (walk = PED_UNIT_FIRST; walk <= PED_UNIT_LAST; walk++) - opts = str_list_append (opts, ped_unit_get_name (walk)); - - default_unit_name = ped_unit_get_name (ped_unit_get_default ()); - unit_name = command_line_get_word (prompt, default_unit_name, opts, 1); - str_list_destroy (opts); - - if (unit_name) { - *unit = ped_unit_get_by_name (unit_name); - free (unit_name); - return 1; - } else - return 0; -} - -int -command_line_is_integer () -{ - char* word; - int is_integer; - int scratch; - - word = command_line_peek_word (); - if (!word) - return 0; - - is_integer = sscanf (word, "%d", &scratch); - free (word); - return is_integer; -} - -static int -init_ex_opt_str () -{ - int i; - PedExceptionOption opt; - - for (i = 0; (1 << i) <= PED_EXCEPTION_OPTION_LAST; i++) { - opt = (1 << i); - ex_opt_str [i] - = str_list_create ( - ped_exception_get_option_string (opt), - _(ped_exception_get_option_string (opt)), - NULL); - if (!ex_opt_str [i]) - return 0; - } - - ex_opt_str [i] = NULL; - return 1; -} - -static void -done_ex_opt_str () -{ - int i; - - for (i=0; ex_opt_str [i]; i++) - str_list_destroy (ex_opt_str [i]); -} - -static int -init_state_str () -{ - on_list = str_list_create_unique (_("on"), "on", NULL); - off_list = str_list_create_unique (_("off"), "off", NULL); - on_off_list = str_list_join (str_list_duplicate (on_list), - str_list_duplicate (off_list)); - return 1; -} - -static void -done_state_str () -{ - str_list_destroy (on_list); - str_list_destroy (off_list); - str_list_destroy (on_off_list); -} - -static int -init_fs_type_str () -{ - PedFileSystemType* walk; - - fs_type_list = NULL; - - for (walk = ped_file_system_type_get_next (NULL); walk; - walk = ped_file_system_type_get_next (walk)) - { - fs_type_list = str_list_insert (fs_type_list, walk->name); - if (!fs_type_list) - return 0; - } - - return 1; -} - -static int -init_disk_type_str () -{ - PedDiskType* walk; - - disk_type_list = NULL; - - for (walk = ped_disk_type_get_next (NULL); walk; - walk = ped_disk_type_get_next (walk)) - { - disk_type_list = str_list_insert (disk_type_list, walk->name); - if (!disk_type_list) - return 0; - } - - return 1; -} - -int -init_ui () -{ - if (!init_ex_opt_str () - || !init_state_str () - || !init_fs_type_str () - || !init_disk_type_str ()) - return 0; - ped_exception_set_handler (exception_handler); - -#ifdef HAVE_LIBREADLINE - rl_initialize (); - rl_attempted_completion_function = (CPPFunction*) complete_function; - readline_state.in_readline = 0; -#endif - -#ifdef SA_SIGINFO - sigset_t curr; - sigfillset (&curr); - - sig_segv.sa_sigaction = &sa_sigsegv_handler; - sig_int.sa_sigaction = &sa_sigint_handler; - sig_fpe.sa_sigaction = &sa_sigfpe_handler; - sig_ill.sa_sigaction = &sa_sigill_handler; - - sig_segv.sa_mask = - sig_int.sa_mask = - sig_fpe.sa_mask = - sig_ill.sa_mask = curr; - - sig_segv.sa_flags = - sig_int.sa_flags = - sig_fpe.sa_flags = - sig_ill.sa_flags = SA_SIGINFO; - - sigaction (SIGSEGV, &sig_segv, NULL); - sigaction (SIGINT, &sig_int, NULL); - sigaction (SIGFPE, &sig_fpe, NULL); - sigaction (SIGILL, &sig_ill, NULL); -#else - signal (SIGSEGV, s_sigsegv_handler); - signal (SIGINT, s_sigint_handler); - signal (SIGFPE, s_sigfpe_handler); - signal (SIGILL, s_sigill_handler); -#endif /* SA_SIGINFO */ - - return 1; -} - -void -done_ui () -{ - ped_exception_set_handler (NULL); - done_ex_opt_str (); - done_state_str (); - str_list_destroy (fs_type_list); - str_list_destroy (disk_type_list); -} - -void -help_msg () -{ - fputs (_(usage_msg), stdout); - - putchar ('\n'); - fputs (_("OPTIONs:"), stdout); - putchar ('\n'); - print_options_help (); - - putchar ('\n'); - fputs (_("COMMANDs:"), stdout); - putchar ('\n'); - print_commands_help (); - exit (0); -} - -void -print_using_dev (PedDevice* dev) -{ - printf (_("Using %s\n"), dev->path); -} - -int -interactive_mode (PedDevice** dev, Command* cmd_list[]) -{ - StrList* list; - StrList* command_names = command_get_names (cmd_list); - - commands = cmd_list; /* FIXME yucky, nasty, evil hack */ - - fputs (prog_name, stdout); - - print_using_dev (*dev); - - list = str_list_create (_(banner_msg), NULL); - str_list_print_wrap (list, screen_width (), 0, 0); - str_list_destroy (list); - - while (1) { - char* word; - Command* cmd; - - while (!command_line_get_word_count ()) { - if (feof (stdin)) { - putchar ('\n'); - return 1; - } - command_line_prompt_words ("(parted)", NULL, - command_names, 1); - } - - word = command_line_pop_word (); - if (word) { - cmd = command_get (commands, word); - free (word); - if (cmd) { - if (!command_run (cmd, dev)) - command_line_flush (); - } else - print_commands_help (); - } - } - - return 1; -} - - -int -non_interactive_mode (PedDevice** dev, Command* cmd_list[], - int argc, char* argv[]) -{ - int i; - Command* cmd; - - commands = cmd_list; /* FIXME yucky, nasty, evil hack */ - - for (i = 0; i < argc; i++) - command_line_push_line (argv [i], 1); - - while (command_line_get_word_count ()) { - char* word; - - word = command_line_pop_word (); - if (!word) - break; - - cmd = command_get (commands, word); - free (word); - if (!cmd) { - help_msg (); - goto error; - } - if (!(cmd->non_interactive)) { - fputs(_("This command does not make sense in " - "non-interactive mode.\n"), stdout); - exit(1); - goto error; - } - - if (!command_run (cmd, dev)) - goto error; - } - return 1; - -error: - return 0; -} diff --git a/usr/src/cmd/parted/ui.h b/usr/src/cmd/parted/ui.h deleted file mode 100644 index f5cf760abf..0000000000 --- a/usr/src/cmd/parted/ui.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - parted - a frontend to libparted - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef UI_H_INCLUDED -#define UI_H_INCLUDED - -#include "strlist.h" - -extern char* prog_name; - -extern int init_ui (); -extern int non_interactive_mode (PedDevice** dev, Command* cmd_list[], - int argc, char* argv[]); -extern int interactive_mode (PedDevice** dev, Command* cmd_list[]); -extern void done_ui (); - -extern int screen_width (); -extern void wipe_line (); - -extern void command_line_push_word (const char* word); -extern char* command_line_pop_word (); -extern char* command_line_peek_word (); -extern void command_line_flush (); -extern int command_line_get_word_count (); -extern void command_line_prompt_words (const char* prompt, const char* def, - const StrList* possibilities, - int multi_word); -extern char* command_line_get_word (const char* prompt, const char* def, - const StrList* possibilities, - int multi_word); -extern int command_line_get_integer (const char* prompt, int* value); -extern int command_line_get_sector (const char* prompt, PedDevice* dev, - PedSector* value, PedGeometry** range); -extern int command_line_get_state (const char* prompt, int* value); -extern int command_line_get_device (const char* prompt, PedDevice** value); -extern int command_line_get_disk (const char* prompt, PedDisk** value); -extern int command_line_get_partition (const char* prompt, PedDisk* disk, - PedPartition** value); -extern int command_line_get_fs_type (const char* prompt, - const PedFileSystemType*(* value)); -extern int command_line_get_disk_type (const char* prompt, - const PedDiskType*(* value)); -extern int command_line_get_part_flag (const char* prompt, - const PedPartition* part, - PedPartitionFlag* flag); -extern int command_line_get_part_type (const char* prompt, const PedDisk* disk, - PedPartitionType* type); -extern PedExceptionOption command_line_get_ex_opt (const char* prompt, - PedExceptionOption options); -extern int command_line_get_unit (const char* prompt, PedUnit* unit); - -extern int command_line_is_integer (); -extern int command_line_is_sector (); - -extern void help_msg (); - -extern void print_using_dev (PedDevice* dev); - -/* in parted.c */ -extern int opt_script_mode; -extern int pretend_input_tty; - -extern void print_options_help (); -extern void print_commands_help (); - - -#endif /* UI_H_INCLUDED */ diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile index fe579b4c9d..3cea7e1efa 100644 --- a/usr/src/lib/Makefile +++ b/usr/src/lib/Makefile @@ -264,8 +264,6 @@ SUBDIRS += \ $($(MACH)_SUBDIRS) i386_SUBDIRS= \ - libntfs \ - libparted \ libfdisk \ libsaveargs @@ -505,7 +503,6 @@ HDRSUBDIRS= \ $($(MACH)_HDRSUBDIRS) i386_HDRSUBDIRS= \ - libparted \ libfdisk \ libsaveargs diff --git a/usr/src/lib/libntfs/COPYING b/usr/src/lib/libntfs/COPYING deleted file mode 100644 index d60c31a97a..0000000000 --- a/usr/src/lib/libntfs/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. diff --git a/usr/src/lib/libntfs/CREDITS b/usr/src/lib/libntfs/CREDITS deleted file mode 100644 index 29bd3e4c85..0000000000 --- a/usr/src/lib/libntfs/CREDITS +++ /dev/null @@ -1,40 +0,0 @@ -The following people have contributed directly or indirectly to the Linux-NTFS -project. - -The list is sorted alphabetically, so please keep it this way! - -Please contact if you believe someone is -missing or if you prefer not to be listed. - -Alexei Alexandrov -Anton Altaparmakov -Albert D. Cahalan -Russ Christensen -Pete Curran -Mario Emmenlauer -Andras Erdei -Matthew J. Fanto -Yuval Fledel -Marcin Gibuła -Christophe Grenier -Csaba Henk -Ian Jackson -Max Khon -Carmelo Kintana -Jan Kratochvil -Lode Leroy -David Martínez Moreno -Giang Nguyen -Leonard Norrgård -Holger Ohmacht -Per Olofsson -Yura Pakhuchiy -Yuri Per -Richard Russon -Erik Sørnes -Szabolcs Szakacsits -zhanglinbao - -Configuration, compilation and installation system are originally based on -numerous different GNU and Gnome utilities and libraries so "Many thanks!" -to all the people who have participated in their creation! diff --git a/usr/src/lib/libntfs/Makefile b/usr/src/lib/libntfs/Makefile deleted file mode 100644 index 67cdafcfff..0000000000 --- a/usr/src/lib/libntfs/Makefile +++ /dev/null @@ -1,124 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -include ../Makefile.lib - -SUBDIRS = $(MACH) - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -delete := TARGET= delete -install := TARGET= install -_msg := TARGET= _msg -package := TARGET= package - -LIBRARY= libntfs.a -TEXT_DOMAIN= SUNW_OST_OSLIB -XGETFLAGS= -a -POFILE= $(LIBRARY:.a=.po) -POFILES= generic.po - -SED= sed -GREP= grep - -.KEEP_STATE: - -all clean delete install package: $(SUBDIRS) -clobber: $(SUBDIRS) - $(RM) $(CLOBBERFILES) - -all install: THIRDPARTYLICENSE - -CLOBBERFILES += THIRDPARTYLICENSE - -THIRDPARTYLICENSE: $(SRC)/common/GPLDISCLAIMER COPYING - $(RM) $@ - $(CAT) $(SRC)/common/GPLDISCLAIMER COPYING > $@ - -# definitions for install_h target -HDRS= ../common/include/ntfs/attrib.h \ - ../common/include/ntfs/attrlist.h \ - ../common/include/ntfs/bitmap.h \ - ../common/include/ntfs/bootsect.h \ - ../common/include/ntfs/collate.h \ - ../common/include/ntfs/compat.h \ - ../common/include/ntfs/compress.h \ - ../common/include/ntfs/crypto.h \ - ../common/include/ntfs/debug.h \ - ../common/include/ntfs/device.h \ - ../common/include/ntfs/device_io.h \ - ../common/include/ntfs/dir.h \ - ../common/include/ntfs/endians.h \ - ../common/include/ntfs/index.h \ - ../common/include/ntfs/inode.h \ - ../common/include/ntfs/layout.h \ - ../common/include/ntfs/lcnalloc.h \ - ../common/include/ntfs/list.h \ - ../common/include/ntfs/logfile.h \ - ../common/include/ntfs/logging.h \ - ../common/include/ntfs/mft.h \ - ../common/include/ntfs/mst.h \ - ../common/include/ntfs/ntfstime.h \ - ../common/include/ntfs/runlist.h \ - ../common/include/ntfs/security.h \ - ../common/include/ntfs/support.h \ - ../common/include/ntfs/types.h \ - ../common/include/ntfs/unistr.h \ - ../common/include/ntfs/version.h \ - ../common/include/ntfs/volume.h -ROOTHDRDIR= $(ROOT)/usr/include -ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%) -CHECKHDRS= $(HDRS:%.h=%.check) - -# install rule for install_h target -$(ROOTHDRDIR)/%: % - $(INS.file) - -install_h: $(ROOTHDRS) - -check: $(CHECKHDRS) - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN) - -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ - -$(POFILES): - $(RM) messages.po - $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* - $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ - $(RM) messages.po - -$(MSGDOMAIN): - $(INS.dir) - -FRC: diff --git a/usr/src/lib/libntfs/Makefile.com b/usr/src/lib/libntfs/Makefile.com deleted file mode 100644 index 181f6f5e68..0000000000 --- a/usr/src/lib/libntfs/Makefile.com +++ /dev/null @@ -1,89 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY= libntfs.a -VERS= .10 - -# -# All relative to SRCDIR -# - -LIBNTFSDIR= libntfs - -OBJECTS= $(LIBNTFSDIR)/attrib.o \ - $(LIBNTFSDIR)/attrlist.o \ - $(LIBNTFSDIR)/bitmap.o \ - $(LIBNTFSDIR)/bootsect.o \ - $(LIBNTFSDIR)/collate.o \ - $(LIBNTFSDIR)/compat.o \ - $(LIBNTFSDIR)/compress.o \ - $(LIBNTFSDIR)/crypto.o \ - $(LIBNTFSDIR)/debug.o \ - $(LIBNTFSDIR)/device.o \ - $(LIBNTFSDIR)/device_io.o \ - $(LIBNTFSDIR)/dir.o \ - $(LIBNTFSDIR)/index.o \ - $(LIBNTFSDIR)/inode.o \ - $(LIBNTFSDIR)/lcnalloc.o \ - $(LIBNTFSDIR)/logfile.o \ - $(LIBNTFSDIR)/logging.o \ - $(LIBNTFSDIR)/mft.o \ - $(LIBNTFSDIR)/misc.o \ - $(LIBNTFSDIR)/mst.o \ - $(LIBNTFSDIR)/runlist.o \ - $(LIBNTFSDIR)/security.o \ - $(LIBNTFSDIR)/unistr.o \ - $(LIBNTFSDIR)/version.o \ - $(LIBNTFSDIR)/volume.o - -# include library definitions -include ../../Makefile.lib - -SRCDIR = ../common - -C99MODE= $(C99_ENABLE) -CERRWARN += -erroff=E_ENUM_VAL_OVERFLOWS_INT_MAX -CERRWARN += -erroff=E_STRUCT_DERIVED_FROM_FLEX_MBR -CERRWARN += -erroff=E_END_OF_LOOP_CODE_NOT_REACHED -CERRWARN += -erroff=E_LOOP_NOT_ENTERED_AT_TOP - -LIBS = $(DYNLIB) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -DHAVE_CONFIG_H \ - -DLTVERSION_LIBNTFS=\"10:0:0\" \ - -I$(SRCDIR)/include/ntfs -DYNFLAGS += $(ZINTERPOSE) -LDLIBS += -lc - -.KEEP_STATE: - -# -# This open source is exempted from lint -# -lint: - -# include library targets -include ../../Makefile.targ diff --git a/usr/src/lib/libntfs/README b/usr/src/lib/libntfs/README deleted file mode 100644 index 80efa88af0..0000000000 --- a/usr/src/lib/libntfs/README +++ /dev/null @@ -1,16 +0,0 @@ -This is the Solaris ON port of ntfsprogs v2.0.0 -Please see http://www.linux-ntfs.org/ for more information. - -ntfsprogs has been broken into two pieces: src/lib/libntfs and src/cmd/ntfsprogs - -The Makefiles have all been replaced by ON Makefiles. - -The common directory contains these subdirectories from ntfsprogs-2.0.0: -include and libntfs - -$(SUBDIR)/config.status: $(SUBDIR)/configure - cd src; \ - MAKE=gmake ./configure CFLAGS=-I$(ROOT)/usr/include \ - LDFLAGS="-L$(ROOT)/lib -L$(ROOT)/usr/lib -Wl,-Bdirect -Wl,-M$(MAPFILE.NE -S) -Wl,-zignore" \ - --disable-dependency-tracking diff --git a/usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip b/usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 6d2fc7f55a..0000000000 --- a/usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -ntfsprogs - NTFS utilities diff --git a/usr/src/lib/libntfs/common/include/ntfs/attrib.h b/usr/src/lib/libntfs/common/include/ntfs/attrib.h deleted file mode 100644 index dcca5427ea..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/attrib.h +++ /dev/null @@ -1,382 +0,0 @@ -/* - * attrib.h - Exports for attribute handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2004-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_ATTRIB_H -#define _NTFS_ATTRIB_H - -/* Forward declarations */ -typedef struct _ntfs_attr ntfs_attr; -typedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx; - -#include "list.h" -#include "types.h" -#include "inode.h" -#include "unistr.h" -#include "runlist.h" -#include "volume.h" -#include "debug.h" -#include "logging.h" -#include "crypto.h" - -extern ntfschar AT_UNNAMED[]; - -/** - * enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn() - * - * Special return values for ntfs_rl_vcn_to_lcn() and ntfs_attr_vcn_to_lcn(). - * - * TODO: Describe them. - */ -typedef enum { - LCN_HOLE = -1, /* Keep this as highest value or die! */ - LCN_RL_NOT_MAPPED = -2, - LCN_ENOENT = -3, - LCN_EINVAL = -4, - LCN_EIO = -5, -} ntfs_lcn_special_values; - -/** - * struct ntfs_attr_search_ctx - search context used in attribute search functions - * @mrec: buffer containing mft record to search - * @attr: attribute record in @mrec where to begin/continue search - * @is_first: if true lookup_attr() begins search with @attr, else after @attr - * - * Structure must be initialized to zero before the first call to one of the - * attribute search functions. Initialize @mrec to point to the mft record to - * search, and @attr to point to the first attribute within @mrec (not necessary - * if calling the _first() functions), and set @is_first to TRUE (not necessary - * if calling the _first() functions). - * - * If @is_first is TRUE, the search begins with @attr. If @is_first is FALSE, - * the search begins after @attr. This is so that, after the first call to one - * of the search attribute functions, we can call the function again, without - * any modification of the search context, to automagically get the next - * matching attribute. - */ -struct _ntfs_attr_search_ctx { - MFT_RECORD *mrec; - ATTR_RECORD *attr; - BOOL is_first; - ntfs_inode *ntfs_ino; - ATTR_LIST_ENTRY *al_entry; - ntfs_inode *base_ntfs_ino; - MFT_RECORD *base_mrec; - ATTR_RECORD *base_attr; -}; - -extern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx); -extern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, - MFT_RECORD *mrec); -extern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx); - -extern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const VCN lowest_vcn, const u8 *val, const u32 val_len, - ntfs_attr_search_ctx *ctx); - -extern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol, - const ATTR_TYPES type); - -/** - * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode - * @ctx: initialised attribute search context - * - * Syntactic sugar for walking attributes in an inode. - * - * Return 0 on success and -1 on error with errno set to the error code from - * ntfs_attr_lookup(). - * - * Example: When you want to enumerate all attributes in an open ntfs inode - * @ni, you can simply do: - * - * int err; - * ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL); - * if (!ctx) - * // Error code is in errno. Handle this case. - * while (!(err = ntfs_attrs_walk(ctx))) { - * ATTR_RECORD *attr = ctx->attr; - * // attr now contains the next attribute. Do whatever you want - * // with it and then just continue with the while loop. - * } - * if (err && errno != ENOENT) - * // Ooops. An error occurred! You should handle this case. - * // Now finished with all attributes in the inode. - */ -static __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx) -{ - return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0, - NULL, 0, ctx); -} - -/** - * struct ntfs_attr - ntfs in memory non-resident attribute structure - * @rl: if not NULL, the decompressed runlist - * @ni: base ntfs inode to which this attribute belongs - * @type: attribute type - * @name: Unicode name of the attribute - * @name_len: length of @name in Unicode characters - * @state: NTFS attribute specific flags describing this attribute - * @allocated_size: copy from the attribute record - * @data_size: copy from the attribute record - * @initialized_size: copy from the attribute record - * @compressed_size: copy from the attribute record - * @compression_block_size: size of a compression block (cb) - * @compression_block_size_bits: log2 of the size of a cb - * @compression_block_clusters: number of clusters per cb - * @crypto: (valid only for encrypted) see description below - * - * This structure exists purely to provide a mechanism of caching the runlist - * of an attribute. If you want to operate on a particular attribute extent, - * you should not be using this structure at all. If you want to work with a - * resident attribute, you should not be using this structure at all. As a - * fail-safe check make sure to test NAttrNonResident() and if it is false, you - * know you shouldn't be using this structure. - * - * If you want to work on a resident attribute or on a specific attribute - * extent, you should use ntfs_lookup_attr() to retrieve the attribute (extent) - * record, edit that, and then write back the mft record (or set the - * corresponding ntfs inode dirty for delayed write back). - * - * @rl is the decompressed runlist of the attribute described by this - * structure. Obviously this only makes sense if the attribute is not resident, - * i.e. NAttrNonResident() is true. If the runlist hasn't been decompressed yet - * @rl is NULL, so be prepared to cope with @rl == NULL. - * - * @ni is the base ntfs inode of the attribute described by this structure. - * - * @type is the attribute type (see layout.h for the definition of ATTR_TYPES), - * @name and @name_len are the little endian Unicode name and the name length - * in Unicode characters of the attribute, respectively. - * - * @state contains NTFS attribute specific flags describing this attribute - * structure. See ntfs_attr_state_bits above. - * - * @crypto points to private structure of crypto code. You should not access - * fields of this structure, but you can check whether it is NULL or not. If it - * is not NULL, then we successfully obtained FEK (File Encryption Key) and - * ntfs_attr_p{read,write} calls probably would succeed. If it is NULL, then we - * failed to obtain FEK (do not have corresponding PFX file, wrong password, - * etc..) or library was compiled without crypto support. Attribute size can be - * changed without knowledge of FEK, so you can use ntfs_attr_truncate in any - * case. - * NOTE: This field valid only if attribute encrypted (eg., NAttrEncrypted - * returns non-zero). - */ -struct _ntfs_attr { - runlist_element *rl; - ntfs_inode *ni; - ATTR_TYPES type; - ntfschar *name; - u32 name_len; - unsigned long state; - s64 allocated_size; - s64 data_size; - s64 initialized_size; - s64 compressed_size; - u32 compression_block_size; - u8 compression_block_size_bits; - u8 compression_block_clusters; - ntfs_crypto_attr *crypto; - struct list_head list_entry; - int nr_references; -}; - -/** - * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr - * structure - */ -typedef enum { - NA_Initialized, /* 1: structure is initialized. */ - NA_NonResident, /* 1: Attribute is not resident. */ -} ntfs_attr_state_bits; - -#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state) -#define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state) -#define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state) - -#define NAttrInitialized(na) test_nattr_flag(na, Initialized) -#define NAttrSetInitialized(na) set_nattr_flag(na, Initialized) -#define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized) - -#define NAttrNonResident(na) test_nattr_flag(na, NonResident) -#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident) -#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident) - -#define GenNAttrIno(func_name,flag) \ -static inline int NAttr##func_name(ntfs_attr *na) \ -{ \ - if (na->type == AT_DATA && na->name == AT_UNNAMED) \ - return (na->ni->flags & FILE_ATTR_##flag) ? 1 : 0; \ - return 0; \ -} \ -static inline void NAttrSet##func_name(ntfs_attr *na) \ -{ \ - if (na->type == AT_DATA && na->name == AT_UNNAMED) \ - na->ni->flags |= FILE_ATTR_##flag; \ - else \ - ntfs_log_trace("BUG! Should be called only for " \ - "unnamed data attribute.\n"); \ -} \ -static inline void NAttrClear##func_name(ntfs_attr *na) \ -{ \ - if (na->type == AT_DATA && na->name == AT_UNNAMED) \ - na->ni->flags &= ~FILE_ATTR_##flag; \ -} - -GenNAttrIno(Compressed, COMPRESSED) -GenNAttrIno(Encrypted, ENCRYPTED) -GenNAttrIno(Sparse, SPARSE_FILE) - -#ifndef __sun -/** - * union attr_val - Union of all known attribute values - * - * For convenience. Used in the attr structure. - */ -typedef union { - u8 _default; /* Unnamed u8 to serve as default when just using - a_val without specifying any of the below. */ - STANDARD_INFORMATION std_inf; - ATTR_LIST_ENTRY al_entry; - FILE_NAME_ATTR filename; - OBJECT_ID_ATTR obj_id; - SECURITY_DESCRIPTOR_ATTR sec_desc; - VOLUME_NAME vol_name; - VOLUME_INFORMATION vol_inf; - DATA_ATTR data; - INDEX_ROOT index_root; - INDEX_BLOCK index_blk; - BITMAP_ATTR bmp; - REPARSE_POINT reparse; - EA_INFORMATION ea_inf; - EA_ATTR ea; - PROPERTY_SET property_set; - LOGGED_UTILITY_STREAM logged_util_stream; - EFS_ATTR_HEADER efs; -} attr_val; -#endif /* __sun */ - -extern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, - const BOOL compressed, const BOOL encrypted, const BOOL sparse, - const s64 allocated_size, const s64 data_size, - const s64 initialized_size, const s64 compressed_size, - const u8 compression_unit); - -extern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len); -extern void ntfs_attr_close(ntfs_attr *na); - -extern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, - void *b); -extern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, - const void *b); - -extern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len, s64 *data_size); - -extern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, - const s64 bk_cnt, const u32 bk_size, void *dst); -extern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, - s64 bk_cnt, const u32 bk_size, void *src); - -extern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn); -extern int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn); -extern int ntfs_attr_map_whole_runlist(ntfs_attr *na); - -extern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn); -extern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn); - -extern int ntfs_attr_size_bounds_check(const ntfs_volume *vol, - const ATTR_TYPES type, const s64 size); -extern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, - const ATTR_TYPES type); -extern int ntfs_attr_can_be_resident(const ntfs_volume *vol, - const ATTR_TYPES type); - -extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size); - -extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, u32 size, - ATTR_FLAGS flags); -extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, - ATTR_FLAGS flags); -extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx); - -extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, s64 size); -extern int ntfs_attr_rm(ntfs_attr *na); - -extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); - -extern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, - const u32 new_size); - -extern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni); -extern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra); - -extern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn); - -extern int __ntfs_attr_truncate(ntfs_attr *na, const s64 newsize, BOOL sparse); -extern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize); - -extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len); - -static __inline__ ntfschar *ntfs_attr_get_name(ATTR_RECORD *attr) -{ - return (ntfschar*)((u8*)attr + le16_to_cpu(attr->name_offset)); -} - -// FIXME / TODO: Above here the file is cleaned up. (AIA) -/** - * get_attribute_value_length - return the length of the value of an attribute - * @a: pointer to a buffer containing the attribute record - * - * Return the byte size of the attribute value of the attribute @a (as it - * would be after eventual decompression and filling in of holes if sparse). - * If we return 0, check errno. If errno is 0 the actual length was 0, - * otherwise errno describes the error. - * - * FIXME: Describe possible errnos. - */ -s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a); - -/** - * get_attribute_value - return the attribute value of an attribute - * @vol: volume on which the attribute is present - * @a: attribute to get the value of - * @b: destination buffer for the attribute value - * - * Make a copy of the attribute value of the attribute @a into the destination - * buffer @b. Note, that the size of @b has to be at least equal to the value - * returned by get_attribute_value_length(@a). - * - * Return number of bytes copied. If this is zero check errno. If errno is 0 - * then nothing was read due to a zero-length attribute value, otherwise - * errno describes the error. - */ -s64 ntfs_get_attribute_value(const ntfs_volume *vol, const ATTR_RECORD *a, - u8 *b); - -#endif /* defined _NTFS_ATTRIB_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/attrlist.h b/usr/src/lib/libntfs/common/include/ntfs/attrlist.h deleted file mode 100644 index ff450d09bf..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/attrlist.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * attrlist.h - Exports for attribute list attribute handling. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * Copyright (c) 2004 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_ATTRLIST_H -#define _NTFS_ATTRLIST_H - -#include "attrib.h" - -extern int ntfs_attrlist_need(ntfs_inode *ni); - -extern int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr); -extern int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx); - -/** - * ntfs_attrlist_mark_dirty - set the attribute list dirty - * @ni: ntfs inode which base inode contain dirty attribute list - * - * Set the attribute list dirty so it is written out later (at the latest at - * ntfs_inode_close() time). - * - * This function cannot fail. - */ -static __inline__ void ntfs_attrlist_mark_dirty(ntfs_inode *ni) -{ - if (ni->nr_extents == -1) - NInoAttrListSetDirty(ni->u.base_ni); - else - NInoAttrListSetDirty(ni); -} - -#endif /* defined _NTFS_ATTRLIST_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/bitmap.h b/usr/src/lib/libntfs/common/include/ntfs/bitmap.h deleted file mode 100644 index f6d16f1923..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/bitmap.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * bitmap.h - Exports for bitmap handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_BITMAP_H -#define _NTFS_BITMAP_H - -#include "types.h" -#include "attrib.h" - -/* - * NOTES: - * - * - Operations are 8-bit only to ensure the functions work both on little - * and big endian machines! So don't make them 32-bit ops! - * - bitmap starts at bit = 0 and ends at bit = bitmap size - 1. - * - _Caller_ has to make sure that the bit to operate on is less than the - * size of the bitmap. - */ - -/** - * ntfs_bit_set - set a bit in a field of bits - * @bitmap: field of bits - * @bit: bit to set - * @new_value: value to set bit to (0 or 1) - * - * Set the bit @bit in the @bitmap to @new_value. Ignore all errors. - */ -static __inline__ void ntfs_bit_set(u8 *bitmap, const u64 bit, - const u8 new_value) -{ - if (!bitmap || new_value > 1) - return; - if (!new_value) - bitmap[bit >> 3] &= ~(1 << (bit & 7)); - else - bitmap[bit >> 3] |= (1 << (bit & 7)); -} - -/** - * ntfs_bit_get - get value of a bit in a field of bits - * @bitmap: field of bits - * @bit: bit to get - * - * Get and return the value of the bit @bit in @bitmap (0 or 1). - * Return -1 on error. - */ -static __inline__ char ntfs_bit_get(const u8 *bitmap, const u64 bit) -{ - if (!bitmap) - return -1; - return (bitmap[bit >> 3] >> (bit & 7)) & 1; -} - -static __inline__ void ntfs_bit_change(u8 *bitmap, const u64 bit) -{ - if (!bitmap) - return; - bitmap[bit >> 3] ^= 1 << (bit & 7); -} - -/** - * ntfs_bit_get_and_set - get value of a bit in a field of bits and set it - * @bitmap: field of bits - * @bit: bit to get/set - * @new_value: value to set bit to (0 or 1) - * - * Return the value of the bit @bit and set it to @new_value (0 or 1). - * Return -1 on error. - */ -static __inline__ char ntfs_bit_get_and_set(u8 *bitmap, const u64 bit, - const u8 new_value) -{ - register u8 old_bit, shift; - - if (!bitmap || new_value > 1) - return -1; - shift = bit & 7; - old_bit = (bitmap[bit >> 3] >> shift) & 1; - if (new_value != old_bit) - bitmap[bit >> 3] ^= 1 << shift; - return old_bit; -} - -extern int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count); -extern int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count); - -/** - * ntfs_bitmap_set_bit - set a bit in a bitmap - * @na: attribute containing the bitmap - * @bit: bit to set - * - * Set the @bit in the bitmap described by the attribute @na. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -static __inline__ int ntfs_bitmap_set_bit(ntfs_attr *na, s64 bit) -{ - return ntfs_bitmap_set_run(na, bit, 1); -} - -/** - * ntfs_bitmap_clear_bit - clear a bit in a bitmap - * @na: attribute containing the bitmap - * @bit: bit to clear - * - * Clear @bit in the bitmap described by the attribute @na. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit) -{ - return ntfs_bitmap_clear_run(na, bit, 1); -} - -#endif /* defined _NTFS_BITMAP_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/bootsect.h b/usr/src/lib/libntfs/common/include/ntfs/bootsect.h deleted file mode 100644 index af0da7a945..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/bootsect.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * bootsect.h - Exports for bootsector record handling. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2000-2002 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_BOOTSECT_H -#define _NTFS_BOOTSECT_H - -#include "types.h" -#include "volume.h" -#include "layout.h" - -/** - * is_boot_sector_ntfs - check a boot sector for describing an ntfs volume - * @b: buffer containing the boot sector - * @silent: if 1 don't display progress information - * - * This function checks the boot sector in @b for describing a valid ntfs - * volume. Return TRUE if @b is a valid NTFS boot sector or FALSE otherwise. - * If silent is FALSE, progress output will be output to stdout. If silent is - * TRUE no output to stdout will occur. Errors/warnings to stderr will occur - * disregarding the value of silent (but only if configure was run with - * --enable-debug). - */ -extern BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b, BOOL silent); -extern int ntfs_boot_sector_parse(ntfs_volume *vol, - const NTFS_BOOT_SECTOR *bs); - -#endif /* defined _NTFS_BOOTSECT_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/collate.h b/usr/src/lib/libntfs/common/include/ntfs/collate.h deleted file mode 100644 index 1c00ebd77e..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/collate.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * collate.h - Defines for NTFS collation handling. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2004 Anton Altaparmakov - * Copyright (c) 2005 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_COLLATE_H -#define _NTFS_COLLATE_H - -#include "types.h" -#include "volume.h" - -#define NTFS_COLLATION_ERROR (-2) - -extern BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr); - -extern int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, - const void *data1, size_t data1_len, - const void *data2, size_t data2_len); - -#endif /* _NTFS_COLLATE_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/compat.h b/usr/src/lib/libntfs/common/include/ntfs/compat.h deleted file mode 100644 index 7c1f5f11fe..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/compat.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * compat.h - Tweaks for Windows compatibility. - * - * Copyright (c) 2002 Richard Russon - * Copyright (c) 2002-2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_COMPAT_H -#define _NTFS_COMPAT_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WINDOWS - -#ifndef HAVE_FFS -#define HAVE_FFS -extern int ffs(int i); -#endif /* HAVE_FFS */ - -#define HAVE_STDIO_H /* mimic config.h */ -#define HAVE_STDARG_H - -#define atoll _atoi64 -#define fdatasync commit -#define __inline__ inline -#define __attribute__(X) /*nothing*/ - -#else /* !defined WINDOWS */ - -#ifndef O_BINARY -#define O_BINARY 0 /* unix is binary by default */ -#endif - -#endif /* defined WINDOWS */ - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#endif /* defined _NTFS_COMPAT_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/compress.h b/usr/src/lib/libntfs/common/include/ntfs/compress.h deleted file mode 100644 index 93df37afc8..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/compress.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * compress.h - Exports for compressed attribute handling. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_COMPRESS_H -#define _NTFS_COMPRESS_H - -#include "types.h" -#include "attrib.h" - -extern s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, - void *b); - -#endif /* defined _NTFS_COMPRESS_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/config.h b/usr/src/lib/libntfs/common/include/ntfs/config.h deleted file mode 100644 index 4c6c18efff..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/config.h +++ /dev/null @@ -1,313 +0,0 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define this to 1 if you want to enable support of encrypted files in - libntfs and utilities. */ -/* #undef ENABLE_CRYPTO */ - -/* Define this to 1 if you want to enable generation of DCE compliant UUIDs. - */ -#define ENABLE_UUID 1 - -/* Define to 1 if you have the `atexit' function. */ -#define HAVE_ATEXIT 1 - -/* Define to 1 if you have the `basename' function. */ -#define HAVE_BASENAME 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BYTESWAP_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */ -/* #undef HAVE_DOPRNT */ - -/* Define to 1 if you have the `dup2' function. */ -#define HAVE_DUP2 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_ENDIAN_H */ - -/* 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_FCNTL_H 1 - -/* Define to 1 if you have the `fdatasync' function. */ -#define HAVE_FDATASYNC 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_FEATURES_H */ - -/* Define to 1 if you have the `getmntent' function. */ -#define HAVE_GETMNTENT - -/* Define to 1 if you have the header file. */ -#define HAVE_GETOPT_H 1 - -/* Define to 1 if you have the `getopt_long' function. */ -#define HAVE_GETOPT_LONG 1 - -/* Define to 1 if you have the `hasmntopt' function. */ -#define HAVE_HASMNTOPT 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIBGEN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIBINTL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_FD_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_HDREG_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_LINUX_MAJOR_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MACHINE_ENDIAN_H */ - -/* Define to 1 if mbrtowc and mbstate_t are properly declared. */ -#define HAVE_MBRTOWC 1 - -/* Define to 1 if you have the `mbsinit' function. */ -#define HAVE_MBSINIT 1 - -/* Define to 1 if you have the `memmove' function. */ -/* #undef HAVE_MEMMOVE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -/* #undef HAVE_MEMSET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_MNTENT_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_PWD_H 1 - -/* Define to 1 if you have the `realpath' function. */ -#define HAVE_REALPATH 1 - -/* Define to 1 if you have the `regcomp' function. */ -#define HAVE_REGCOMP 1 - -/* Define to 1 if you have the `setlocale' function. */ -#define HAVE_SETLOCALE 1 - -/* Define to 1 if you have the `setxattr' function. */ -/* #undef HAVE_SETXATTR */ - -/* Define to 1 if `stat' has the bug that it succeeds when given the - zero-length file name argument. */ -/* #undef HAVE_STAT_EMPTY_STRING_BUG */ - -/* Define to 1 if you have the header file. */ -#define HAVE_STDARG_H 1 - -/* Define to 1 if stdbool.h conforms to C99. */ -#define HAVE_STDBOOL_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDDEF_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 `strcasecmp' function. */ -#define HAVE_STRCASECMP 1 - -/* Define to 1 if you have the `strchr' function. */ -/* #undef HAVE_STRCHR */ - -/* Define to 1 if you have the `strdup' function. */ -/* #undef HAVE_STRDUP */ - -/* Define to 1 if you have the `strerror' function. */ -#define HAVE_STRERROR 1 - -/* Define to 1 if you have the `strftime' function. */ -/* #undef HAVE_STRFTIME */ - -/* 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 `strtol' function. */ -#define HAVE_STRTOL 1 - -/* Define to 1 if you have the `strtoul' function. */ -#define HAVE_STRTOUL 1 - -/* Define to 1 if `st_blocks' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_BLOCKS 1 - -/* Define to 1 if `st_rdev' is member of `struct stat'. */ -#define HAVE_STRUCT_STAT_ST_RDEV 1 - -/* Define to 1 if your `struct stat' has `st_blocks'. Deprecated, use - `HAVE_STRUCT_STAT_ST_BLOCKS' instead. */ -#define HAVE_ST_BLOCKS 1 - -/* Define to 1 if you have the `sysconf' function. */ -#define HAVE_SYSCONF 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYSLOG_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_BYTEORDER_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_ENDIAN_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_IOCTL_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_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STATVFS_H 1 - -/* 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_SYSMACROS_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_VFS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if you have the `utime' function. */ -#define HAVE_UTIME 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UTIME_H 1 - -/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */ -#define HAVE_UTIME_NULL 1 - -/* Define to 1 if you have the `vprintf' function. */ -/* #undef HAVE_VPRINTF */ - -/* Define to 1 if you have the header file. */ -#define HAVE_WCHAR_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_WINDOWS_H */ - -/* Define to 1 if the system has the type `_Bool'. */ -#define HAVE__BOOL 1 - -/* Define to 1 if `lstat' dereferences a symlink specified with a trailing - slash. */ -#define LSTAT_FOLLOWS_SLASHED_SYMLINK 1 - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Define this if you do not want the NTFS library to provide default device - io operations. This means that you cannot use ntfs_mount() but have to use - ntfs_device_mount() and provide your own device operations. */ -/* #undef NO_NTFS_DEVICE_DEFAULT_IO_OPS */ - -/* Name of package */ -#define PACKAGE "ntfsprogs" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "linux-ntfs-dev@lists.sourceforge.net" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "ntfsprogs" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "ntfsprogs 2.0.0" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "ntfsprogs" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "2.0.0" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -#define VERSION "2.0.0" - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to 1 if your processor stores words with the least significant byte - first (like Intel and VAX, unlike Motorola and SPARC). */ -#define WORDS_LITTLEENDIAN 1 - -/* Number of bits in a file offset, on hosts where this is settable. */ -#define _FILE_OFFSET_BITS 64 - -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to `long int' if does not define. */ -/* #undef off_t */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/crypto.h b/usr/src/lib/libntfs/common/include/ntfs/crypto.h deleted file mode 100644 index a4b72435c1..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/crypto.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * crypto.h - Exports for dealing with encrypted files. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2007 Yura Pakhuchiy - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_CRYPTO_H -#define _NTFS_CRYPTO_H - -extern ntfschar NTFS_EFS[5]; - -/* - * This is our Big Secret (TM) structure, so do not allow anyone even read it - * values. ;-) In fact, it is private because exist only in libntfs version - * compiled with cryptography support, so users can not depend on it. - */ -typedef struct _ntfs_crypto_attr ntfs_crypto_attr; - -/* - * These functions should not be used directly. They are called for encrypted - * attributes from corresponding functions without _crypto_ part. - */ - -extern int ntfs_crypto_attr_open(ntfs_attr *na); -extern void ntfs_crypto_attr_close(ntfs_attr *na); - -extern s64 ntfs_crypto_attr_pread(ntfs_attr *na, const s64 pos, s64 count, - void *b); - -#endif /* _NTFS_CRYPTO_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/debug.h b/usr/src/lib/libntfs/common/include/ntfs/debug.h deleted file mode 100644 index 0dd411420b..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/debug.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * debug.h - Debugging output functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_DEBUG_H -#define _NTFS_DEBUG_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "logging.h" - -struct _runlist_element; - -#ifndef DEBUG -static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl __attribute__((unused))) {} -#define NTFS_ON_DEBUG(x) -#else -extern void ntfs_debug_runlist_dump(const struct _runlist_element *rl); -#define NTFS_ON_DEBUG(x) (x) -#endif - -#if defined(__GNUC__) - -#define NTFS_BUG(msg) \ -{ \ - int ___i; \ - ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \ - ntfs_log_debug("Forcing segmentation fault!"); \ - ___i = ((int*)NULL)[1]; \ -} - -#else /* not __GNUC__ */ - -#define NTFS_BUG(msg) \ -{ \ - int ___i; \ - ntfs_log_critical("Bug in %s(): %s\n", "unknown", msg); \ - ntfs_log_debug("Forcing segmentation fault!"); \ - ___i = ((int*)NULL)[1]; \ -} - -#endif /* __GNUC__ */ - -#endif /* defined _NTFS_DEBUG_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/device.h b/usr/src/lib/libntfs/common/include/ntfs/device.h deleted file mode 100644 index eeadf13e7a..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/device.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * device.h - Exports for low level device io. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_DEVICE_H -#define _NTFS_DEVICE_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "device_io.h" -#include "types.h" -#include "support.h" -#include "volume.h" - -/** - * enum ntfs_device_state_bits - - * - * Defined bits for the state field in the ntfs_device structure. - */ -typedef enum { - ND_Open, /* 1: Device is open. */ - ND_ReadOnly, /* 1: Device is read-only. */ - ND_Dirty, /* 1: Device is dirty, needs sync. */ - ND_Block, /* 1: Device is a block device. */ -} ntfs_device_state_bits; - -#define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state) -#define set_ndev_flag(nd, flag) set_bit(ND_##flag, (nd)->d_state) -#define clear_ndev_flag(nd, flag) clear_bit(ND_##flag, (nd)->d_state) - -#define NDevOpen(nd) test_ndev_flag(nd, Open) -#define NDevSetOpen(nd) set_ndev_flag(nd, Open) -#define NDevClearOpen(nd) clear_ndev_flag(nd, Open) - -#define NDevReadOnly(nd) test_ndev_flag(nd, ReadOnly) -#define NDevSetReadOnly(nd) set_ndev_flag(nd, ReadOnly) -#define NDevClearReadOnly(nd) clear_ndev_flag(nd, ReadOnly) - -#define NDevDirty(nd) test_ndev_flag(nd, Dirty) -#define NDevSetDirty(nd) set_ndev_flag(nd, Dirty) -#define NDevClearDirty(nd) clear_ndev_flag(nd, Dirty) - -#define NDevBlock(nd) test_ndev_flag(nd, Block) -#define NDevSetBlock(nd) set_ndev_flag(nd, Block) -#define NDevClearBlock(nd) clear_ndev_flag(nd, Block) - -/** - * struct ntfs_device - - * - * The ntfs device structure defining all operations needed to access the low - * level device underlying the ntfs volume. - */ -struct ntfs_device { - struct ntfs_device_operations *d_ops; /* Device operations. */ - unsigned long d_state; /* State of the device. */ - char *d_name; /* Name of device. */ - void *d_private; /* Private data used by the - device operations. */ -}; - -struct stat; - -/** - * struct ntfs_device_operations - - * - * The ntfs device operations defining all operations that can be performed on - * the low level device described by an ntfs device structure. - */ -struct ntfs_device_operations { - int (*open)(struct ntfs_device *dev, int flags); - int (*close)(struct ntfs_device *dev); - s64 (*seek)(struct ntfs_device *dev, s64 offset, int whence); - s64 (*read)(struct ntfs_device *dev, void *buf, s64 count); - s64 (*write)(struct ntfs_device *dev, const void *buf, s64 count); - s64 (*pread)(struct ntfs_device *dev, void *buf, s64 count, s64 offset); - s64 (*pwrite)(struct ntfs_device *dev, const void *buf, s64 count, - s64 offset); - int (*sync)(struct ntfs_device *dev); - int (*stat)(struct ntfs_device *dev, struct stat *buf); - int (*ioctl)(struct ntfs_device *dev, int request, void *argp); -}; - -extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state, - struct ntfs_device_operations *dops, void *priv_data); -extern int ntfs_device_free(struct ntfs_device *dev); - -extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, - void *b); -extern s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, - const void *b); - -extern s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count, - const u32 bksize, void *b); -extern s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, - const u32 bksize, void *b); - -extern s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, - const s64 count, void *b); -extern s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn, - const s64 count, const void *b); - -extern s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size); -extern s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev); -extern int ntfs_device_heads_get(struct ntfs_device *dev); -extern int ntfs_device_sectors_per_track_get(struct ntfs_device *dev); -extern int ntfs_device_sector_size_get(struct ntfs_device *dev); -extern int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size); - -#endif /* defined _NTFS_DEVICE_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/device_io.h b/usr/src/lib/libntfs/common/include/ntfs/device_io.h deleted file mode 100644 index 6665b68050..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/device_io.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * device_io.h - Exports for default device io. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_DEVICE_IO_H -#define _NTFS_DEVICE_IO_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS - -#ifndef __CYGWIN32__ - -/* Not on Cygwin; use standard Unix style low level device operations. */ -#define ntfs_device_default_io_ops ntfs_device_unix_io_ops - -#else /* __CYGWIN32__ */ - -#ifndef HDIO_GETGEO -# define HDIO_GETGEO 0x301 -/** - * struct hd_geometry - - */ -struct hd_geometry { - unsigned char heads; - unsigned char sectors; - unsigned short cylinders; - unsigned long start; -}; -#endif -#ifndef BLKGETSIZE -# define BLKGETSIZE 0x1260 -#endif -#ifndef BLKSSZGET -# define BLKSSZGET 0x1268 -#endif -#ifndef BLKGETSIZE64 -# define BLKGETSIZE64 0x80041272 -#endif -#ifndef BLKBSZSET -# define BLKBSZSET 0x40041271 -#endif - -/* On Cygwin; use Win32 low level device operations. */ -#define ntfs_device_default_io_ops ntfs_device_win32_io_ops - -#endif /* __CYGWIN32__ */ - - -/* Forward declaration. */ -struct ntfs_device_operations; - -extern struct ntfs_device_operations ntfs_device_default_io_ops; - -#endif /* NO_NTFS_DEVICE_DEFAULT_IO_OPS */ - -#endif /* defined _NTFS_DEVICE_IO_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/dir.h b/usr/src/lib/libntfs/common/include/ntfs/dir.h deleted file mode 100644 index 5299861b81..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/dir.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * dir.h - Exports for directory handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2002 Anton Altaparmakov - * Copyright (c) 2005-2006 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_DIR_H -#define _NTFS_DIR_H - -#include "types.h" - -#define PATH_SEP '/' - -#ifndef MAX_PATH -#define MAX_PATH 1024 -#endif - -/* - * We do not have these under DJGPP, so define our version that do not conflict - * with other S_IFs defined under DJGPP. - */ -#ifdef DJGPP -#ifndef S_IFLNK -#define S_IFLNK 0120000 -#endif -#ifndef S_ISLNK -#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#endif -#ifndef S_IFSOCK -#define S_IFSOCK 0140000 -#endif -#ifndef S_ISSOCK -#define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -#endif -#endif - -/* - * The little endian Unicode strings $I30, $SII, $SDH, $O, $Q, $R - * as a global constant. - */ -extern ntfschar NTFS_INDEX_I30[5]; -extern ntfschar NTFS_INDEX_SII[5]; -extern ntfschar NTFS_INDEX_SDH[5]; -extern ntfschar NTFS_INDEX_O[3]; -extern ntfschar NTFS_INDEX_Q[3]; -extern ntfschar NTFS_INDEX_R[3]; - -extern u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, - const ntfschar *uname, const int uname_len); - -extern u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent, - const char *pathname); -extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, - const char *pathname); - -extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type); -extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, - ntfschar *name, u8 name_len, dev_t type, dev_t dev); -extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, - ntfschar *name, u8 name_len, ntfschar *target, u8 target_len); - -extern int ntfs_delete(ntfs_inode **pni, ntfs_inode *dir_ni, ntfschar *name, - u8 name_len); - -extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, - u8 name_len); - -/* - * File types (adapted from include ) - */ -#define NTFS_DT_UNKNOWN 0 -#define NTFS_DT_FIFO 1 -#define NTFS_DT_CHR 2 -#define NTFS_DT_DIR 4 -#define NTFS_DT_BLK 6 -#define NTFS_DT_REG 8 -#define NTFS_DT_LNK 10 -#define NTFS_DT_SOCK 12 -#define NTFS_DT_WHT 14 - -/* - * This is the "ntfs_filldir" function type, used by ntfs_readdir() to let - * the caller specify what kind of dirent layout it wants to have. - * This allows the caller to read directories into their application or - * to have different dirent layouts depending on the binary type. - */ -typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name, - const int name_len, const int name_type, const s64 pos, - const MFT_REF mref, const unsigned dt_type); - -extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, - void *dirent, ntfs_filldir_t filldir); - -#endif /* defined _NTFS_DIR_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/endians.h b/usr/src/lib/libntfs/common/include/ntfs/endians.h deleted file mode 100644 index b3426df30e..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/endians.h +++ /dev/null @@ -1,248 +0,0 @@ -/* - * endians.h - Definitions related to handling of byte ordering. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2000-2005 Anton Altaparmakov - * Copyright (c) 2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_ENDIANS_H -#define _NTFS_ENDIANS_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* - * Notes: - * We define the conversion functions including typecasts since the - * defaults don't necessarily perform appropriate typecasts. - * Also, using our own functions means that we can change them if it - * turns out that we do need to use the unaligned access macros on - * architectures requiring aligned memory accesses... - */ - -#ifdef HAVE_ENDIAN_H -#include -#endif -#ifdef HAVE_SYS_ENDIAN_H -#include -#endif -#ifdef HAVE_MACHINE_ENDIAN_H -#include -#endif -#ifdef HAVE_SYS_BYTEORDER_H -#include -#endif -#ifdef HAVE_SYS_PARAM_H -#include -#endif - -#ifndef __BYTE_ORDER -# if defined(_BYTE_ORDER) -# define __BYTE_ORDER _BYTE_ORDER -# define __LITTLE_ENDIAN _LITTLE_ENDIAN -# define __BIG_ENDIAN _BIG_ENDIAN -# elif defined(BYTE_ORDER) -# define __BYTE_ORDER BYTE_ORDER -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __BIG_ENDIAN BIG_ENDIAN -# elif defined(__BYTE_ORDER__) -# define __BYTE_ORDER __BYTE_ORDER__ -# define __LITTLE_ENDIAN __LITTLE_ENDIAN__ -# define __BIG_ENDIAN __BIG_ENDIAN__ -# elif (defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \ - defined(WORDS_LITTLEENDIAN) -# define __BYTE_ORDER 1 -# define __LITTLE_ENDIAN 1 -# define __BIG_ENDIAN 0 -# elif (!defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)) || \ - defined(WORDS_BIGENDIAN) -# define __BYTE_ORDER 0 -# define __LITTLE_ENDIAN 1 -# define __BIG_ENDIAN 0 -# else -# error "__BYTE_ORDER is not defined." -# endif -#endif - -#define __ntfs_bswap_constant_16(x) \ - (u16)((((u16)(x) & 0xff00) >> 8) | \ - (((u16)(x) & 0x00ff) << 8)) - -#define __ntfs_bswap_constant_32(x) \ - (u32)((((u32)(x) & 0xff000000u) >> 24) | \ - (((u32)(x) & 0x00ff0000u) >> 8) | \ - (((u32)(x) & 0x0000ff00u) << 8) | \ - (((u32)(x) & 0x000000ffu) << 24)) - -#define __ntfs_bswap_constant_64(x) \ - (u64)((((u64)(x) & 0xff00000000000000ull) >> 56) | \ - (((u64)(x) & 0x00ff000000000000ull) >> 40) | \ - (((u64)(x) & 0x0000ff0000000000ull) >> 24) | \ - (((u64)(x) & 0x000000ff00000000ull) >> 8) | \ - (((u64)(x) & 0x00000000ff000000ull) << 8) | \ - (((u64)(x) & 0x0000000000ff0000ull) << 24) | \ - (((u64)(x) & 0x000000000000ff00ull) << 40) | \ - (((u64)(x) & 0x00000000000000ffull) << 56)) - -#ifdef HAVE_BYTESWAP_H -# include -#else -# define bswap_16(x) __ntfs_bswap_constant_16(x) -# define bswap_32(x) __ntfs_bswap_constant_32(x) -# define bswap_64(x) __ntfs_bswap_constant_64(x) -#endif - -#if defined(__LITTLE_ENDIAN) && (__BYTE_ORDER == __LITTLE_ENDIAN) - -#define __le16_to_cpu(x) ((__force u16)(x)) -#define __le32_to_cpu(x) ((__force u32)(x)) -#define __le64_to_cpu(x) ((__force u64)(x)) - -#define __cpu_to_le16(x) ((__force le16)(x)) -#define __cpu_to_le32(x) ((__force le32)(x)) -#define __cpu_to_le64(x) ((__force le64)(x)) - -#define __constant_le16_to_cpu(x) ((__force u16)(x)) -#define __constant_le32_to_cpu(x) ((__force u32)(x)) -#define __constant_le64_to_cpu(x) ((__force u64)(x)) - -#define __constant_cpu_to_le16(x) ((__force le16)(x)) -#define __constant_cpu_to_le32(x) ((__force le32)(x)) -#define __constant_cpu_to_le64(x) ((__force le64)(x)) - -#elif defined(__BIG_ENDIAN) && (__BYTE_ORDER == __BIG_ENDIAN) - -#define __le16_to_cpu(x) bswap_16((__force u16)(x)) -#define __le32_to_cpu(x) bswap_32((__force u16)(x)) -#define __le64_to_cpu(x) bswap_64((__force u16)(x)) - -#define __cpu_to_le16(x) (__force le16)bswap_16((__force u16)(x)) -#define __cpu_to_le32(x) (__force le32)bswap_32((__force u32)(x)) -#define __cpu_to_le64(x) (__force le64)bswap_64((__force u64)(x)) - -#define __constant_le16_to_cpu(x) __ntfs_bswap_constant_16((__force u16)(x)) -#define __constant_le32_to_cpu(x) __ntfs_bswap_constant_32((__force u32)(x)) -#define __constant_le64_to_cpu(x) __ntfs_bswap_constant_64((__force u64)(x)) - -#define __constant_cpu_to_le16(x) \ - (__force le16)__ntfs_bswap_constant_16((__force u16)(x)) -#define __constant_cpu_to_le32(x) \ - (__force le32)__ntfs_bswap_constant_32((__force u32)(x)) -#define __constant_cpu_to_le64(x) \ - (__force le64)__ntfs_bswap_constant_64((__force u64)(x)) - -#else - -#error "You must define __BYTE_ORDER to be __LITTLE_ENDIAN or __BIG_ENDIAN." - -#endif - -/* Unsigned from LE to CPU conversion. */ - -#define le16_to_cpu(x) (u16)__le16_to_cpu((le16)(x)) -#define le32_to_cpu(x) (u32)__le32_to_cpu((le32)(x)) -#define le64_to_cpu(x) (u64)__le64_to_cpu((le64)(x)) - -#define le16_to_cpup(x) (u16)__le16_to_cpu(*(const le16*)(x)) -#define le32_to_cpup(x) (u32)__le32_to_cpu(*(const le32*)(x)) -#define le64_to_cpup(x) (u64)__le64_to_cpu(*(const le64*)(x)) - -/* Signed from LE to CPU conversion. */ - -#define sle16_to_cpu(x) (s16)__le16_to_cpu((sle16)(x)) -#define sle32_to_cpu(x) (s32)__le32_to_cpu((sle32)(x)) -#define sle64_to_cpu(x) (s64)__le64_to_cpu((sle64)(x)) - -#define sle16_to_cpup(x) (s16)__le16_to_cpu(*(const sle16*)(x)) -#define sle32_to_cpup(x) (s32)__le32_to_cpu(*(const sle32*)(x)) -#define sle64_to_cpup(x) (s64)__le64_to_cpu(*(const sle64*)(x)) - -/* Unsigned from CPU to LE conversion. */ - -#define cpu_to_le16(x) (le16)__cpu_to_le16((u16)(x)) -#define cpu_to_le32(x) (le32)__cpu_to_le32((u32)(x)) -#define cpu_to_le64(x) (le64)__cpu_to_le64((u64)(x)) - -#define cpu_to_le16p(x) (le16)__cpu_to_le16(*(const u16*)(x)) -#define cpu_to_le32p(x) (le32)__cpu_to_le32(*(const u32*)(x)) -#define cpu_to_le64p(x) (le64)__cpu_to_le64(*(const u64*)(x)) - -/* Signed from CPU to LE conversion. */ - -#define cpu_to_sle16(x) (__force sle16)__cpu_to_le16((s16)(x)) -#define cpu_to_sle32(x) (__force sle32)__cpu_to_le32((s32)(x)) -#define cpu_to_sle64(x) (__force sle64)__cpu_to_le64((s64)(x)) - -#define cpu_to_sle16p(x) (__force sle16)__cpu_to_le16(*(const s16*)(x)) -#define cpu_to_sle32p(x) (__force sle32)__cpu_to_le32(*(const s32*)(x)) -#define cpu_to_sle64p(x) (__force sle64)__cpu_to_le64(*(const s64*)(x)) - -/* Constant endianness conversion defines. */ - -#define const_le16_to_cpu(x) (u16)__constant_le16_to_cpu((le16)(x)) -#define const_le32_to_cpu(x) (u32)__constant_le32_to_cpu((le32)(x)) -#define const_le64_to_cpu(x) (u64)__constant_le64_to_cpu((le64)(x)) - -#define const_cpu_to_le16(x) (le16)__constant_cpu_to_le16((u16)(x)) -#define const_cpu_to_le32(x) (le32)__constant_cpu_to_le32((u32)(x)) -#define const_cpu_to_le64(x) (le64)__constant_cpu_to_le64((u64)(x)) - -#ifdef __CHECKER__ -static void ntfs_endian_self_test(void) -{ - /* Should not generate warnings. */ - (le16)cpu_to_le16((u16)1); - (le32)cpu_to_le32((u32)1); - (le64)cpu_to_le64((u64)1); - (sle16)cpu_to_sle16((s16)1); - (sle32)cpu_to_sle32((s32)1); - (sle64)cpu_to_sle64((s64)1); - (u16)le16_to_cpu((__force le16)1); - (u32)le32_to_cpu((__force le32)1); - (u64)le64_to_cpu((__force le64)1); - (s16)sle16_to_cpu((__force sle16)1); - (s32)sle32_to_cpu((__force sle32)1); - (s64)sle64_to_cpu((__force sle64)1); - (le16)const_cpu_to_le16((u16)1); - (le32)const_cpu_to_le32((u32)1); - (le64)const_cpu_to_le64((u64)1); - (u16)const_le16_to_cpu((__force le16)1); - (u32)const_le32_to_cpu((__force le32)1); - (u64)const_le64_to_cpu((__force le64)1); - - /* - * TODO: Need some how to test that warnings are actually generated, - * but without flooding output with them and vice-versa print warning - * in case if some one warning is not triggered, but should. (Yura) - * - * I think it can only be done in a ./configure like script / shell - * script that will compile known good and known bad code and pipe the - * output from sparse to a file, then grep the file for the wanted - * warnings/lack thereof and then it would say "Tests: PASS " or - * "Tests: FAILED" or whatever. And you can then hook that into a - * "make test" make target or similar so it is only done when one - * wants to do it... (Anton) - * - * Also we can look on sparse self test script. (Yura) - */ -} -#endif - -#endif /* defined _NTFS_ENDIANS_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/index.h b/usr/src/lib/libntfs/common/include/ntfs/index.h deleted file mode 100644 index 75e23e2a4e..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/index.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * index.h - Defines for NTFS index handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * Copyright (c) 2004-2005 Richard Russon - * Copyright (c) 2005-2006 Yura Pakhuchiy - * Copyright (c) 2006 Szabolcs Szakacsits - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_INDEX_H -#define _NTFS_INDEX_H - -#include "attrib.h" -#include "types.h" -#include "layout.h" -#include "inode.h" -#include "mft.h" - -#define VCN_INDEX_ROOT_PARENT ((VCN)-2) - -#define MAX_PARENT_VCN 32 - -/** - * struct ntfs_index_context - - * @ni: inode containing the @entry described by this context - * @name: name of the index described by this context - * @name_len: length of the index name - * @entry: index entry (points into @ir or @ib) - * @data: index entry data (points into @entry) - * @data_len: length in bytes of @data - * @cr: - * @is_in_root: TRUE if @entry is in @ir or FALSE if it is in @ib - * @ir: index root if @is_in_root or NULL otherwise - * @actx: attribute search context if in root or NULL otherwise - * @ia_na: opened INDEX_ALLOCATION attribute - * @ib: index block if @is_in_root is FALSE or NULL otherwise - * @ib_vcn: VCN from which @ib where read from - * @ib_dirty: TRUE if index block was changed - * @parent_pos: parent entries' positions in the index block - * @parent_vcn: entry's parent nodes or VCN_INDEX_ROOT_PARENT for root - * @max_depth: number of the parent nodes - * @pindex: maximum it's the number of the parent nodes - * @block_size: index block size - * @vcn_size_bits: VCN size bits for this index block - * - * @ni is the inode this context belongs to. - * - * @entry is the index entry described by this context. @data and @data_len - * are the index entry data and its length in bytes, respectively. @data - * simply points into @entry. This is probably what the user is interested in. - * - * If @is_in_root is TRUE, @entry is in the index root attribute @ir described - * by the attribute search context @actx and inode @ni. @ib, @ib_vcn and - * @ib_dirty are undefined in this case. - * - * If @is_in_root is FALSE, @entry is in the index allocation attribute and @ib - * and @ib_vcn point to the index allocation block and VCN where it's placed, - * respectively. @ir and @actx are NULL in this case. @ia_na is opened - * INDEX_ALLOCATION attribute. @ib_dirty is TRUE if index block was changed and - * FALSE otherwise. - * - * To obtain a context call ntfs_index_ctx_get(). - * - * When finished with the @entry and its @data, call ntfs_index_ctx_put() to - * free the context and other associated resources. - * - * If the index entry was modified, call ntfs_index_entry_mark_dirty() before - * the call to ntfs_index_ctx_put() to ensure that the changes are written - * to disk. - */ -typedef struct { - ntfs_inode *ni; - ntfschar *name; - u32 name_len; - INDEX_ENTRY *entry; - void *data; - u16 data_len; - COLLATION_RULES cr; - BOOL is_in_root; - INDEX_ROOT *ir; - ntfs_attr_search_ctx *actx; - ntfs_attr *ia_na; - INDEX_BLOCK *ib; - VCN ib_vcn; - BOOL ib_dirty; - int parent_pos[MAX_PARENT_VCN]; - VCN parent_vcn[MAX_PARENT_VCN]; - int max_depth; - int pindex; - u32 block_size; - u8 vcn_size_bits; -} ntfs_index_context; - -extern ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, - ntfschar *name, u32 name_len); -extern void ntfs_index_ctx_put(ntfs_index_context *ictx); -extern void ntfs_index_ctx_reinit(ntfs_index_context *ictx); - -extern int ntfs_index_lookup(const void *key, const int key_len, - ntfs_index_context *ictx); - -extern int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, - MFT_REF mref); -extern int ntfs_index_rm(ntfs_index_context *ictx); - -extern INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr); - -extern VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie); - -extern char *ntfs_ie_filename_get(INDEX_ENTRY *ie); -extern void ntfs_ie_filename_dump(INDEX_ENTRY *ie); -extern void ntfs_ih_filename_dump(INDEX_HEADER *ih); - -extern void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx); - -#endif /* _NTFS_INDEX_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/inode.h b/usr/src/lib/libntfs/common/include/ntfs/inode.h deleted file mode 100644 index 90c2113116..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/inode.h +++ /dev/null @@ -1,215 +0,0 @@ -/* - * inode.h - Defines for NTFS inode handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2001,2002 Anton Altaparmakov - * Copyright (c) 2004-2007 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_INODE_H -#define _NTFS_INODE_H - -/* Forward declaration */ -typedef struct _ntfs_inode ntfs_inode; - -#include "list.h" -#include "types.h" -#include "layout.h" -#include "support.h" -#include "volume.h" - -/** - * enum ntfs_inode_state_bits - - * - * Defined bits for the state field in the ntfs_inode structure. - * (f) = files only, (d) = directories only - */ -typedef enum { - NI_Dirty, /* 1: Mft record needs to be written to disk. */ - - /* Below fields only make sense for base inodes. */ - NI_AttrList, /* 1: Mft record contains an attribute list. */ - NI_AttrListDirty, /* 1: Attribute list needs to be written to the - mft record and then to disk. */ - NI_FileNameDirty, /* 1: FILE_NAME attributes need to be updated - in the index. */ -} ntfs_inode_state_bits; - -#define test_nino_flag(ni, flag) test_bit(NI_##flag, (ni)->state) -#define set_nino_flag(ni, flag) set_bit(NI_##flag, (ni)->state) -#define clear_nino_flag(ni, flag) clear_bit(NI_##flag, (ni)->state) - -#define test_and_set_nino_flag(ni, flag) \ - test_and_set_bit(NI_##flag, (ni)->state) -#define test_and_clear_nino_flag(ni, flag) \ - test_and_clear_bit(NI_##flag, (ni)->state) - -#define NInoDirty(ni) test_nino_flag(ni, Dirty) -#define NInoSetDirty(ni) set_nino_flag(ni, Dirty) -#define NInoClearDirty(ni) clear_nino_flag(ni, Dirty) -#define NInoTestAndSetDirty(ni) test_and_set_nino_flag(ni, Dirty) -#define NInoTestAndClearDirty(ni) test_and_clear_nino_flag(ni, Dirty) - -#define NInoAttrList(ni) test_nino_flag(ni, AttrList) -#define NInoSetAttrList(ni) set_nino_flag(ni, AttrList) -#define NInoClearAttrList(ni) clear_nino_flag(ni, AttrList) - - -#define test_nino_al_flag(ni, flag) test_nino_flag(ni, AttrList##flag) -#define set_nino_al_flag(ni, flag) set_nino_flag(ni, AttrList##flag) -#define clear_nino_al_flag(ni, flag) clear_nino_flag(ni, AttrList##flag) - -#define test_and_set_nino_al_flag(ni, flag) \ - test_and_set_nino_flag(ni, AttrList##flag) -#define test_and_clear_nino_al_flag(ni, flag) \ - test_and_clear_nino_flag(ni, AttrList##flag) - -#define NInoAttrListDirty(ni) test_nino_al_flag(ni, Dirty) -#define NInoAttrListSetDirty(ni) set_nino_al_flag(ni, Dirty) -#define NInoAttrListClearDirty(ni) clear_nino_al_flag(ni, Dirty) -#define NInoAttrListTestAndSetDirty(ni) test_and_set_nino_al_flag(ni, Dirty) -#define NInoAttrListTestAndClearDirty(ni) test_and_clear_nino_al_flag(ni, Dirty) - -#define NInoFileNameDirty(ni) \ - test_nino_flag(ni, FileNameDirty) -#define NInoFileNameSetDirty(ni) \ - set_nino_flag(ni, FileNameDirty) -#define NInoFileNameClearDirty(ni) \ - clear_nino_flag(ni, FileNameDirty) -#define NInoFileNameTestAndSetDirty(ni) \ - test_and_set_nino_flag(ni, FileNameDirty) -#define NInoFileNameTestAndClearDirty(ni) \ - test_and_clear_nino_flag(ni, FileNameDirty) - -/** - * struct _ntfs_inode - The NTFS in-memory inode structure. - * - * It is just used as an extension to the fields already provided in the VFS - * inode. - */ -struct _ntfs_inode { - u64 mft_no; /* Inode / mft record number. */ - MFT_RECORD *mrec; /* The actual mft record of the inode. */ - ntfs_volume *vol; /* Pointer to the ntfs volume of this inode. */ - unsigned long state; /* NTFS specific flags describing this inode. - See ntfs_inode_state_bits above. */ - FILE_ATTR_FLAGS flags; /* Flags describing the file. - (Copy from STANDARD_INFORMATION) */ - /* - * Attribute list support (for use by the attribute lookup functions). - * Setup during ntfs_open_inode() for all inodes with attribute lists. - * Only valid if NI_AttrList is set in state. - */ - u32 attr_list_size; /* Length of attribute list value in bytes. */ - u8 *attr_list; /* Attribute list value itself. */ - /* Below fields are always valid. */ - s32 nr_extents; /* For a base mft record, the number of - attached extent inodes (0 if none), for - extent records this is -1. */ - union { /* This union is only used if nr_extents != 0. */ - ntfs_inode **extent_nis;/* For nr_extents > 0, array of the - ntfs inodes of the extent mft - records belonging to this base - inode which have been loaded. */ - ntfs_inode *base_ni; /* For nr_extents == -1, the ntfs - inode of the base mft record. */ - } u; - - /* Below fields are valid only for base inode. */ - - /* - * These two fields are used to sync filename index and guaranteed to be - * correct, however value in index itself maybe wrong (windows itself - * do not update them properly). - */ - s64 data_size; /* Data size of unnamed DATA attribute. */ - s64 allocated_size; /* Allocated size stored in the filename - index. (NOTE: Equal to allocated size of - the unnamed data attribute for normal or - encrypted files and to compressed size - of the unnamed data attribute for sparse or - compressed files.) */ - - /* - * These four fields are copy of relevant fields from - * STANDARD_INFORMATION attribute and used to sync it and FILE_NAME - * attribute in the index. - */ - time_t creation_time; - time_t last_data_change_time; - time_t last_mft_change_time; - time_t last_access_time; - - /* These 2 fields are used to keep track of opened inodes. */ - struct list_head list_entry; /* Keep pointers to the next/prev list - entry. */ - int nr_references; /* How many times this inode was - opened. We really close inode only - when this reaches zero. */ - - struct list_head attr_cache; /* List of opened attributes. */ -}; - -extern void __ntfs_inode_add_to_cache(ntfs_inode *ni); - -extern ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol); - -extern ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref); - -extern int ntfs_inode_close(ntfs_inode *ni); - -extern ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, - const leMFT_REF mref); - -extern int ntfs_inode_attach_all_extents(ntfs_inode *ni); - -/** - * ntfs_inode_mark_dirty - set the inode (and its base inode if it exists) dirty - * @ni: ntfs inode to set dirty - * - * Set the inode @ni dirty so it is written out later (at the latest at - * ntfs_inode_close() time). If @ni is an extent inode, set the base inode - * dirty, too. - * - * This function cannot fail. - */ -static __inline__ void ntfs_inode_mark_dirty(ntfs_inode *ni) -{ - NInoSetDirty(ni); - if (ni->nr_extents == -1) - NInoSetDirty(ni->u.base_ni); -} - -typedef enum { - NTFS_UPDATE_ATIME = 1 << 0, - NTFS_UPDATE_MTIME = 1 << 1, - NTFS_UPDATE_CTIME = 1 << 2, -} ntfs_time_update_flags; - -extern void ntfs_inode_update_times(ntfs_inode *ni, - ntfs_time_update_flags mask); - -extern int ntfs_inode_sync(ntfs_inode *ni); - -extern int ntfs_inode_add_attrlist(ntfs_inode *ni); - -extern int ntfs_inode_free_space(ntfs_inode *ni, int size); - -extern int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *a); - -#endif /* defined _NTFS_INODE_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/layout.h b/usr/src/lib/libntfs/common/include/ntfs/layout.h deleted file mode 100644 index 7ae239cccd..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/layout.h +++ /dev/null @@ -1,3063 +0,0 @@ -/* - * layout.h - Ntfs on-disk layout structures. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2005 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_LAYOUT_H -#define _NTFS_LAYOUT_H - -#include "types.h" -#include "endians.h" -#include "support.h" - -/* The NTFS oem_id "NTFS " */ -#define NTFS_SB_MAGIC const_cpu_to_le64(0x202020205346544eULL) - -/* - * Location of boot sector on partition: - * The standard NTFS_BOOT_SECTOR is on sector 0 of the partition. - * On NT4 and above there is one backup copy of the boot sector to - * be found on the last sector of the partition (not normally accessible - * from within Windows as the boot sector contained number of sectors - * value is one less than the actual value!). - * On versions of NT 3.51 and earlier, the backup copy was located at - * number of sectors/2 (integer divide), i.e. in the middle of the volume. - */ - -/** - * struct BIOS_PARAMETER_BLOCK - BIOS parameter block (BPB) structure. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le16 bytes_per_sector; /* Size of a sector in bytes. */ - u8 sectors_per_cluster; /* Size of a cluster in sectors. */ - le16 reserved_sectors; /* zero */ - u8 fats; /* zero */ - le16 root_entries; /* zero */ - le16 sectors; /* zero */ - u8 media_type; /* 0xf8 = hard disk */ - le16 sectors_per_fat; /* zero */ -/*0x0d*/le16 sectors_per_track; /* Required to boot Windows. */ -/*0x0f*/le16 heads; /* Required to boot Windows. */ -/*0x11*/le32 hidden_sectors; /* Offset to the start of the partition - relative to the disk in sectors. - Required to boot Windows. */ -/*0x15*/le32 large_sectors; /* zero */ -/* sizeof() = 25 (0x19) bytes */ -} __attribute__((__packed__)) BIOS_PARAMETER_BLOCK; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct NTFS_BOOT_SECTOR - NTFS boot sector structure. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u8 jump[3]; /* Irrelevant (jump to boot up code).*/ - le64 oem_id; /* Magic "NTFS ". */ -/*0x0b*/BIOS_PARAMETER_BLOCK bpb; /* See BIOS_PARAMETER_BLOCK. */ - u8 physical_drive; /* 0x00 floppy, 0x80 hard disk */ - u8 current_head; /* zero */ - u8 extended_boot_signature; /* 0x80 */ - u8 reserved2; /* zero */ -/*0x28*/sle64 number_of_sectors; /* Number of sectors in volume. Gives - maximum volume size of 2^63 sectors. - Assuming standard sector size of 512 - bytes, the maximum byte size is - approx. 4.7x10^21 bytes. (-; */ - sle64 mft_lcn; /* Cluster location of mft data. */ - sle64 mftmirr_lcn; /* Cluster location of copy of mft. */ - s8 clusters_per_mft_record; /* Mft record size in clusters. */ - u8 reserved0[3]; /* zero */ - s8 clusters_per_index_record; /* Index block size in clusters. */ - u8 reserved1[3]; /* zero */ - le64 volume_serial_number; /* Irrelevant (serial number). */ - le32 checksum; /* Boot sector checksum. */ -/*0x54*/u8 bootstrap[426]; /* Irrelevant (boot up code). */ - le16 end_of_sector_marker; /* End of boot sector magic. Always is - 0xaa55 in little endian. */ -/* sizeof() = 512 (0x200) bytes */ -} __attribute__((__packed__)) NTFS_BOOT_SECTOR; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum NTFS_RECORD_TYPES - - * - * Magic identifiers present at the beginning of all ntfs record containing - * records (like mft records for example). - */ -typedef enum { - /* Found in $MFT/$DATA. */ - magic_FILE = const_cpu_to_le32(0x454c4946), /* Mft entry. */ - magic_INDX = const_cpu_to_le32(0x58444e49), /* Index buffer. */ - magic_HOLE = const_cpu_to_le32(0x454c4f48), /* ? (NTFS 3.0+?) */ - - /* Found in $LogFile/$DATA. */ - magic_RSTR = const_cpu_to_le32(0x52545352), /* Restart page. */ - magic_RCRD = const_cpu_to_le32(0x44524352), /* Log record page. */ - - /* Found in $LogFile/$DATA. (May be found in $MFT/$DATA, also?) */ - magic_CHKD = const_cpu_to_le32(0x444b4843), /* Modified by chkdsk. */ - - /* Found in all ntfs record containing records. */ - magic_BAAD = const_cpu_to_le32(0x44414142), /* Failed multi sector - transfer was detected. */ - - /* - * Found in $LogFile/$DATA when a page is full or 0xff bytes and is - * thus not initialized. User has to initialize the page before using - * it. - */ - magic_empty = const_cpu_to_le32(0xffffffff),/* Record is empty and has - to be initialized before - it can be used. */ -} NTFS_RECORD_TYPES; - -/* - * Generic magic comparison macros. Finally found a use for the ## preprocessor - * operator! (-8 - */ - -static inline BOOL __ntfs_is_magic(le32 x, NTFS_RECORD_TYPES r) -{ - return (x == (__force le32)r); -} -#define ntfs_is_magic(x, m) __ntfs_is_magic(x, magic_##m) - -static inline BOOL __ntfs_is_magicp(le32 *p, NTFS_RECORD_TYPES r) -{ - return (*p == (__force le32)r); -} -#define ntfs_is_magicp(p, m) __ntfs_is_magicp(p, magic_##m) - -/* - * Specialised magic comparison macros for the NTFS_RECORD_TYPES defined above. - */ -#define ntfs_is_file_record(x) ( ntfs_is_magic (x, FILE) ) -#define ntfs_is_file_recordp(p) ( ntfs_is_magicp(p, FILE) ) -#define ntfs_is_mft_record(x) ( ntfs_is_file_record(x) ) -#define ntfs_is_mft_recordp(p) ( ntfs_is_file_recordp(p) ) -#define ntfs_is_indx_record(x) ( ntfs_is_magic (x, INDX) ) -#define ntfs_is_indx_recordp(p) ( ntfs_is_magicp(p, INDX) ) -#define ntfs_is_hole_record(x) ( ntfs_is_magic (x, HOLE) ) -#define ntfs_is_hole_recordp(p) ( ntfs_is_magicp(p, HOLE) ) - -#define ntfs_is_rstr_record(x) ( ntfs_is_magic (x, RSTR) ) -#define ntfs_is_rstr_recordp(p) ( ntfs_is_magicp(p, RSTR) ) -#define ntfs_is_rcrd_record(x) ( ntfs_is_magic (x, RCRD) ) -#define ntfs_is_rcrd_recordp(p) ( ntfs_is_magicp(p, RCRD) ) - -#define ntfs_is_chkd_record(x) ( ntfs_is_magic (x, CHKD) ) -#define ntfs_is_chkd_recordp(p) ( ntfs_is_magicp(p, CHKD) ) - -#define ntfs_is_baad_record(x) ( ntfs_is_magic (x, BAAD) ) -#define ntfs_is_baad_recordp(p) ( ntfs_is_magicp(p, BAAD) ) - -#define ntfs_is_empty_record(x) ( ntfs_is_magic (x, empty) ) -#define ntfs_is_empty_recordp(p) ( ntfs_is_magicp(p, empty) ) - - -#define NTFS_BLOCK_SIZE 512 -#define NTFS_BLOCK_SIZE_BITS 9 - -/** - * struct NTFS_RECORD - - * - * The Update Sequence Array (USA) is an array of the le16 values which belong - * to the end of each sector protected by the update sequence record in which - * this array is contained. Note that the first entry is the Update Sequence - * Number (USN), a cyclic counter of how many times the protected record has - * been written to disk. The values 0 and -1 (ie. 0xffff) are not used. All - * last le16's of each sector have to be equal to the USN (during reading) or - * are set to it (during writing). If they are not, an incomplete multi sector - * transfer has occurred when the data was written. - * The maximum size for the update sequence array is fixed to: - * maximum size = usa_ofs + (usa_count * 2) = 510 bytes - * The 510 bytes comes from the fact that the last le16 in the array has to - * (obviously) finish before the last le16 of the first 512-byte sector. - * This formula can be used as a consistency check in that usa_ofs + - * (usa_count * 2) has to be less than or equal to 510. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - NTFS_RECORD_TYPES magic;/* A four-byte magic identifying the - record type and/or status. */ - le16 usa_ofs; /* Offset to the Update Sequence Array (USA) - from the start of the ntfs record. */ - le16 usa_count; /* Number of u16 sized entries in the USA - including the Update Sequence Number (USN), - thus the number of fixups is the usa_count - minus 1. */ -} __attribute__((__packed__)) NTFS_RECORD; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum NTFS_SYSTEM_FILES - System files mft record numbers. - * - * All these files are always marked as used in the bitmap attribute of the - * mft; presumably in order to avoid accidental allocation for random other - * mft records. Also, the sequence number for each of the system files is - * always equal to their mft record number and it is never modified. - */ -typedef enum { - FILE_MFT = 0, /* Master file table (mft). Data attribute - contains the entries and bitmap attribute - records which ones are in use (bit==1). */ - FILE_MFTMirr = 1, /* Mft mirror: copy of first four mft records - in data attribute. If cluster size > 4kiB, - copy of first N mft records, with - N = cluster_size / mft_record_size. */ - FILE_LogFile = 2, /* Journalling log in data attribute. */ - FILE_Volume = 3, /* Volume name attribute and volume information - attribute (flags and ntfs version). Windows - refers to this file as volume DASD (Direct - Access Storage Device). */ - FILE_AttrDef = 4, /* Array of attribute definitions in data - attribute. */ - FILE_root = 5, /* Root directory. */ - FILE_Bitmap = 6, /* Allocation bitmap of all clusters (LCNs) in - data attribute. */ - FILE_Boot = 7, /* Boot sector (always at cluster 0) in data - attribute. */ - FILE_BadClus = 8, /* Contains all bad clusters in the non-resident - data attribute. */ - FILE_Secure = 9, /* Shared security descriptors in data attribute - and two indexes into the descriptors. - Appeared in Windows 2000. Before that, this - file was named $Quota but was unused. */ - FILE_UpCase = 10, /* Uppercase equivalents of all 65536 Unicode - characters in data attribute. */ - FILE_Extend = 11, /* Directory containing other system files (eg. - $ObjId, $Quota, $Reparse and $UsnJrnl). This - is new to NTFS 3.0. */ - FILE_reserved12 = 12, /* Reserved for future use (records 12-15). */ - FILE_reserved13 = 13, - FILE_reserved14 = 14, - FILE_reserved15 = 15, - FILE_first_user = 16, /* First user file, used as test limit for - whether to allow opening a file or not. */ -} NTFS_SYSTEM_FILES; - -/** - * enum MFT_RECORD_FLAGS - - * - * These are the so far known MFT_RECORD_* flags (16-bit) which contain - * information about the mft record in which they are present. - * - * MFT_RECORD_IS_4 exists on all $Extend sub-files. - * It seems that it marks it is a metadata file with MFT record >24, however, - * it is unknown if it is limited to metadata files only. - * - * MFT_RECORD_IS_VIEW_INDEX exists on every metafile with a non directory - * index, that means an INDEX_ROOT and an INDEX_ALLOCATION with a name other - * than "$I30". It is unknown if it is limited to metadata files only. - */ -#ifdef __sun -typedef uint16_t MFT_RECORD_FLAGS; -#define MFT_RECORD_IN_USE (const_cpu_to_le16(0x0001)) -#define MFT_RECORD_IS_DIRECTORY (const_cpu_to_le16(0x0002)) -#define MFT_RECORD_IS_4 (const_cpu_to_le16(0x0004)) -#define MFT_RECORD_IS_VIEW_INDEX (const_cpu_to_le16(0x0008)) -#else /* not __sun */ -typedef enum { - MFT_RECORD_IN_USE = const_cpu_to_le16(0x0001), - MFT_RECORD_IS_DIRECTORY = const_cpu_to_le16(0x0002), - MFT_RECORD_IS_4 = const_cpu_to_le16(0x0004), - MFT_RECORD_IS_VIEW_INDEX = const_cpu_to_le16(0x0008), - MFT_REC_SPACE_FILLER = const_cpu_to_le16(0xffff), - /* Just to make flags 16-bit. */ -} __attribute__((__packed__)) MFT_RECORD_FLAGS; -#endif /* __sun */ - -/* - * mft references (aka file references or file record segment references) are - * used whenever a structure needs to refer to a record in the mft. - * - * A reference consists of a 48-bit index into the mft and a 16-bit sequence - * number used to detect stale references. - * - * For error reporting purposes we treat the 48-bit index as a signed quantity. - * - * The sequence number is a circular counter (skipping 0) describing how many - * times the referenced mft record has been (re)used. This has to match the - * sequence number of the mft record being referenced, otherwise the reference - * is considered stale and removed (FIXME: only ntfsck or the driver itself?). - * - * If the sequence number is zero it is assumed that no sequence number - * consistency checking should be performed. - * - * FIXME: Since inodes are 32-bit as of now, the driver needs to always check - * for high_part being 0 and if not either BUG(), cause a panic() or handle - * the situation in some other way. This shouldn't be a problem as a volume has - * to become HUGE in order to need more than 32-bits worth of mft records. - * Assuming the standard mft record size of 1kb only the records (never mind - * the non-resident attributes, etc.) would require 4Tb of space on their own - * for the first 32 bits worth of records. This is only if some strange person - * doesn't decide to foul play and make the mft sparse which would be a really - * horrible thing to do as it would trash our current driver implementation. )-: - * Do I hear screams "we want 64-bit inodes!" ?!? (-; - * - * FIXME: The mft zone is defined as the first 12% of the volume. This space is - * reserved so that the mft can grow contiguously and hence doesn't become - * fragmented. Volume free space includes the empty part of the mft zone and - * when the volume's free 88% are used up, the mft zone is shrunk by a factor - * of 2, thus making more space available for more files/data. This process is - * repeated every time there is no more free space except for the mft zone until - * there really is no more free space. - */ - -/* - * Typedef the MFT_REF as a 64-bit value for easier handling. - * Also define two unpacking macros to get to the reference (MREF) and - * sequence number (MSEQNO) respectively. - * The _LE versions are to be applied on little endian MFT_REFs. - * Note: The _LE versions will return a CPU endian formatted value! - */ -#define MFT_REF_MASK_CPU 0x0000ffffffffffffULL -#define MFT_REF_MASK_LE const_cpu_to_le64(MFT_REF_MASK_CPU) - -typedef u64 MFT_REF; -typedef le64 leMFT_REF; - -#define MK_MREF(m, s) ((MFT_REF)(((MFT_REF)(s) << 48) | \ - ((MFT_REF)(m) & MFT_REF_MASK_CPU))) -#define MK_LE_MREF(m, s) const_cpu_to_le64(((MFT_REF)(((MFT_REF)(s) << 48) | \ - ((MFT_REF)(m) & MFT_REF_MASK_CPU)))) - -#define MREF(x) ((u64)((x) & MFT_REF_MASK_CPU)) -#define MSEQNO(x) ((u16)(((x) >> 48) & 0xffff)) -#define MREF_LE(x) ((u64)(const_le64_to_cpu(x) & MFT_REF_MASK_CPU)) -#define MSEQNO_LE(x) ((u16)((const_le64_to_cpu(x) >> 48) & 0xffff)) - -#define IS_ERR_MREF(x) (((x) & 0x0000800000000000ULL) ? 1 : 0) -#define ERR_MREF(x) ((u64)((s64)(x))) -#define MREF_ERR(x) ((int)((s64)(x))) - -/** - * struct MFT_RECORD - An MFT record layout (NTFS 3.1+) - * - * The mft record header present at the beginning of every record in the mft. - * This is followed by a sequence of variable length attribute records which - * is terminated by an attribute of type AT_END which is a truncated attribute - * in that it only consists of the attribute type code AT_END and none of the - * other members of the attribute structure are present. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ - NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */ - le16 usa_ofs; /* See NTFS_RECORD definition above. */ - le16 usa_count; /* See NTFS_RECORD definition above. */ - -/* 8*/ leLSN lsn; /* $LogFile sequence number for this record. - Changed every time the record is modified. */ -/* 16*/ le16 sequence_number; /* Number of times this mft record has been - reused. (See description for MFT_REF - above.) NOTE: The increment (skipping zero) - is done when the file is deleted. NOTE: If - this is zero it is left zero. */ -/* 18*/ le16 link_count; /* Number of hard links, i.e. the number of - directory entries referencing this record. - NOTE: Only used in mft base records. - NOTE: When deleting a directory entry we - check the link_count and if it is 1 we - delete the file. Otherwise we delete the - FILE_NAME_ATTR being referenced by the - directory entry from the mft record and - decrement the link_count. - FIXME: Careful with Win32 + DOS names! */ -/* 20*/ le16 attrs_offset; /* Byte offset to the first attribute in this - mft record from the start of the mft record. - NOTE: Must be aligned to 8-byte boundary. */ -/* 22*/ MFT_RECORD_FLAGS flags; /* Bit array of MFT_RECORD_FLAGS. When a file - is deleted, the MFT_RECORD_IN_USE flag is - set to zero. */ -/* 24*/ le32 bytes_in_use; /* Number of bytes used in this mft record. - NOTE: Must be aligned to 8-byte boundary. */ -/* 28*/ le32 bytes_allocated; /* Number of bytes allocated for this mft - record. This should be equal to the mft - record size. */ -/* 32*/ leMFT_REF base_mft_record;/* This is zero for base mft records. - When it is not zero it is a mft reference - pointing to the base mft record to which - this record belongs (this is then used to - locate the attribute list attribute present - in the base record which describes this - extension record and hence might need - modification when the extension record - itself is modified, also locating the - attribute list also means finding the other - potential extents, belonging to the non-base - mft record). */ -/* 40*/ le16 next_attr_instance; /* The instance number that will be - assigned to the next attribute added to this - mft record. NOTE: Incremented each time - after it is used. NOTE: Every time the mft - record is reused this number is set to zero. - NOTE: The first instance number is always 0. - */ -/* The below fields are specific to NTFS 3.1+ (Windows XP and above): */ -/* 42*/ le16 reserved; /* Reserved/alignment. */ -/* 44*/ le32 mft_record_number; /* Number of this mft record. */ -/* sizeof() = 48 bytes */ -/* - * When (re)using the mft record, we place the update sequence array at this - * offset, i.e. before we start with the attributes. This also makes sense, - * otherwise we could run into problems with the update sequence array - * containing in itself the last two bytes of a sector which would mean that - * multi sector transfer protection wouldn't work. As you can't protect data - * by overwriting it since you then can't get it back... - * When reading we obviously use the data from the ntfs record header. - */ -} __attribute__((__packed__)) MFT_RECORD; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct MFT_RECORD_OLD - An MFT record layout (NTFS <=3.0) - * - * This is the version without the NTFS 3.1+ specific fields. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ - NTFS_RECORD_TYPES magic;/* Usually the magic is "FILE". */ - le16 usa_ofs; /* See NTFS_RECORD definition above. */ - le16 usa_count; /* See NTFS_RECORD definition above. */ - -/* 8*/ leLSN lsn; /* $LogFile sequence number for this record. - Changed every time the record is modified. */ -/* 16*/ le16 sequence_number; /* Number of times this mft record has been - reused. (See description for MFT_REF - above.) NOTE: The increment (skipping zero) - is done when the file is deleted. NOTE: If - this is zero it is left zero. */ -/* 18*/ le16 link_count; /* Number of hard links, i.e. the number of - directory entries referencing this record. - NOTE: Only used in mft base records. - NOTE: When deleting a directory entry we - check the link_count and if it is 1 we - delete the file. Otherwise we delete the - FILE_NAME_ATTR being referenced by the - directory entry from the mft record and - decrement the link_count. - FIXME: Careful with Win32 + DOS names! */ -/* 20*/ le16 attrs_offset; /* Byte offset to the first attribute in this - mft record from the start of the mft record. - NOTE: Must be aligned to 8-byte boundary. */ -/* 22*/ MFT_RECORD_FLAGS flags; /* Bit array of MFT_RECORD_FLAGS. When a file - is deleted, the MFT_RECORD_IN_USE flag is - set to zero. */ -/* 24*/ le32 bytes_in_use; /* Number of bytes used in this mft record. - NOTE: Must be aligned to 8-byte boundary. */ -/* 28*/ le32 bytes_allocated; /* Number of bytes allocated for this mft - record. This should be equal to the mft - record size. */ -/* 32*/ MFT_REF base_mft_record; /* This is zero for base mft records. - When it is not zero it is a mft reference - pointing to the base mft record to which - this record belongs (this is then used to - locate the attribute list attribute present - in the base record which describes this - extension record and hence might need - modification when the extension record - itself is modified, also locating the - attribute list also means finding the other - potential extents, belonging to the non-base - mft record). */ -/* 40*/ le16 next_attr_instance; /* The instance number that will be - assigned to the next attribute added to this - mft record. NOTE: Incremented each time - after it is used. NOTE: Every time the mft - record is reused this number is set to zero. - NOTE: The first instance number is always 0. - */ -/* sizeof() = 42 bytes */ -/* - * When (re)using the mft record, we place the update sequence array at this - * offset, i.e. before we start with the attributes. This also makes sense, - * otherwise we could run into problems with the update sequence array - * containing in itself the last two bytes of a sector which would mean that - * multi sector transfer protection wouldn't work. As you can't protect data - * by overwriting it since you then can't get it back... - * When reading we obviously use the data from the ntfs record header. - */ -} __attribute__((__packed__)) MFT_RECORD_OLD; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum ATTR_TYPES - System defined attributes (32-bit). - * - * Each attribute type has a corresponding attribute name (Unicode string of - * maximum 64 character length) as described by the attribute definitions - * present in the data attribute of the $AttrDef system file. - * - * On NTFS 3.0 volumes the names are just as the types are named in the below - * enum exchanging AT_ for the dollar sign ($). If that isn't a revealing - * choice of symbol... (-; - */ -typedef enum { - AT_UNUSED = const_cpu_to_le32( 0), - AT_STANDARD_INFORMATION = const_cpu_to_le32( 0x10), - AT_ATTRIBUTE_LIST = const_cpu_to_le32( 0x20), - AT_FILE_NAME = const_cpu_to_le32( 0x30), - AT_OBJECT_ID = const_cpu_to_le32( 0x40), - AT_SECURITY_DESCRIPTOR = const_cpu_to_le32( 0x50), - AT_VOLUME_NAME = const_cpu_to_le32( 0x60), - AT_VOLUME_INFORMATION = const_cpu_to_le32( 0x70), - AT_DATA = const_cpu_to_le32( 0x80), - AT_INDEX_ROOT = const_cpu_to_le32( 0x90), - AT_INDEX_ALLOCATION = const_cpu_to_le32( 0xa0), - AT_BITMAP = const_cpu_to_le32( 0xb0), - AT_REPARSE_POINT = const_cpu_to_le32( 0xc0), - AT_EA_INFORMATION = const_cpu_to_le32( 0xd0), - AT_EA = const_cpu_to_le32( 0xe0), - AT_PROPERTY_SET = const_cpu_to_le32( 0xf0), - AT_LOGGED_UTILITY_STREAM = const_cpu_to_le32( 0x100), - AT_FIRST_USER_DEFINED_ATTRIBUTE = const_cpu_to_le32( 0x1000), - AT_END = const_cpu_to_le32(0xffffffff), -} ATTR_TYPES; - -/** - * enum COLLATION_RULES - The collation rules for sorting views/indexes/etc - * (32-bit). - * - * COLLATION_UNICODE_STRING - Collate Unicode strings by comparing their binary - * Unicode values, except that when a character can be uppercased, the - * upper case value collates before the lower case one. - * COLLATION_FILE_NAME - Collate file names as Unicode strings. The collation - * is done very much like COLLATION_UNICODE_STRING. In fact I have no idea - * what the difference is. Perhaps the difference is that file names - * would treat some special characters in an odd way (see - * unistr.c::ntfs_collate_names() and unistr.c::legal_ansi_char_array[] - * for what I mean but COLLATION_UNICODE_STRING would not give any special - * treatment to any characters at all, but this is speculation. - * COLLATION_NTOFS_ULONG - Sorting is done according to ascending le32 key - * values. E.g. used for $SII index in FILE_Secure, which sorts by - * security_id (le32). - * COLLATION_NTOFS_SID - Sorting is done according to ascending SID values. - * E.g. used for $O index in FILE_Extend/$Quota. - * COLLATION_NTOFS_SECURITY_HASH - Sorting is done first by ascending hash - * values and second by ascending security_id values. E.g. used for $SDH - * index in FILE_Secure. - * COLLATION_NTOFS_ULONGS - Sorting is done according to a sequence of ascending - * le32 key values. E.g. used for $O index in FILE_Extend/$ObjId, which - * sorts by object_id (16-byte), by splitting up the object_id in four - * le32 values and using them as individual keys. E.g. take the following - * two security_ids, stored as follows on disk: - * 1st: a1 61 65 b7 65 7b d4 11 9e 3d 00 e0 81 10 42 59 - * 2nd: 38 14 37 d2 d2 f3 d4 11 a5 21 c8 6b 79 b1 97 45 - * To compare them, they are split into four le32 values each, like so: - * 1st: 0xb76561a1 0x11d47b65 0xe0003d9e 0x59421081 - * 2nd: 0xd2371438 0x11d4f3d2 0x6bc821a5 0x4597b179 - * Now, it is apparent why the 2nd object_id collates after the 1st: the - * first le32 value of the 1st object_id is less than the first le32 of - * the 2nd object_id. If the first le32 values of both object_ids were - * equal then the second le32 values would be compared, etc. - */ -typedef enum { - COLLATION_BINARY = const_cpu_to_le32(0), /* Collate by binary - compare where the first byte is most - significant. */ - COLLATION_FILE_NAME = const_cpu_to_le32(1), /* Collate file names - as Unicode strings. */ - COLLATION_UNICODE_STRING = const_cpu_to_le32(2), /* Collate Unicode - strings by comparing their binary - Unicode values, except that when a - character can be uppercased, the upper - case value collates before the lower - case one. */ - COLLATION_NTOFS_ULONG = const_cpu_to_le32(16), - COLLATION_NTOFS_SID = const_cpu_to_le32(17), - COLLATION_NTOFS_SECURITY_HASH = const_cpu_to_le32(18), - COLLATION_NTOFS_ULONGS = const_cpu_to_le32(19), -} COLLATION_RULES; - -/** - * enum ATTR_DEF_FLAGS - - * - * The flags (32-bit) describing attribute properties in the attribute - * definition structure. FIXME: This information is based on Regis's - * information and, according to him, it is not certain and probably - * incomplete. The INDEXABLE flag is fairly certainly correct as only the file - * name attribute has this flag set and this is the only attribute indexed in - * NT4. - */ -typedef enum { - ATTR_DEF_INDEXABLE = const_cpu_to_le32(0x02), /* Attribute can be - indexed. */ - ATTR_DEF_MULTIPLE = const_cpu_to_le32(0x04), /* Attribute type - can be present multiple times in the - mft records of an inode. */ - ATTR_DEF_NOT_ZERO = const_cpu_to_le32(0x08), /* Attribute value - must contain at least one non-zero - byte. */ - ATTR_DEF_INDEXED_UNIQUE = const_cpu_to_le32(0x10), /* Attribute must be - indexed and the attribute value must be - unique for the attribute type in all of - the mft records of an inode. */ - ATTR_DEF_NAMED_UNIQUE = const_cpu_to_le32(0x20), /* Attribute must be - named and the name must be unique for - the attribute type in all of the mft - records of an inode. */ - ATTR_DEF_RESIDENT = const_cpu_to_le32(0x40), /* Attribute must be - resident. */ - ATTR_DEF_ALWAYS_LOG = const_cpu_to_le32(0x80), /* Always log - modifications to this attribute, - regardless of whether it is resident or - non-resident. Without this, only log - modifications if the attribute is - resident. */ -} ATTR_DEF_FLAGS; - -/** - * struct ATTR_DEF - - * - * The data attribute of FILE_AttrDef contains a sequence of attribute - * definitions for the NTFS volume. With this, it is supposed to be safe for an - * older NTFS driver to mount a volume containing a newer NTFS version without - * damaging it (that's the theory. In practice it's: not damaging it too much). - * Entries are sorted by attribute type. The flags describe whether the - * attribute can be resident/non-resident and possibly other things, but the - * actual bits are unknown. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*hex ofs*/ -/* 0*/ ntfschar name[0x40]; /* Unicode name of the attribute. Zero - terminated. */ -/* 80*/ ATTR_TYPES type; /* Type of the attribute. */ -/* 84*/ le32 display_rule; /* Default display rule. - FIXME: What does it mean? (AIA) */ -/* 88*/ COLLATION_RULES collation_rule; /* Default collation rule. */ -/* 8c*/ ATTR_DEF_FLAGS flags; /* Flags describing the attribute. */ -/* 90*/ sle64 min_size; /* Optional minimum attribute size. */ -/* 98*/ sle64 max_size; /* Maximum size of attribute. */ -/* sizeof() = 0xa0 or 160 bytes */ -} __attribute__((__packed__)) ATTR_DEF; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum ATTR_FLAGS - Attribute flags (16-bit). - */ -#ifdef __sun -typedef uint16_t ATTR_FLAGS; -#define ATTR_IS_COMPRESSED (const_cpu_to_le16(0x0001)) -#define ATTR_COMPRESSION_MASK (const_cpu_to_le16(0x00ff)) -#define ATTR_IS_ENCRYPTED (const_cpu_to_le16(0x4000)) -#define ATTR_IS_SPARSE (const_cpu_to_le16(0x8000)) -#else /* not __sun */ -typedef enum { - ATTR_IS_COMPRESSED = const_cpu_to_le16(0x0001), - ATTR_COMPRESSION_MASK = const_cpu_to_le16(0x00ff), /* Compression - method mask. Also, first - illegal value. */ - ATTR_IS_ENCRYPTED = const_cpu_to_le16(0x4000), - ATTR_IS_SPARSE = const_cpu_to_le16(0x8000), -} __attribute__((__packed__)) ATTR_FLAGS; -#endif /* __sun */ - -/* - * Attribute compression. - * - * Only the data attribute is ever compressed in the current ntfs driver in - * Windows. Further, compression is only applied when the data attribute is - * non-resident. Finally, to use compression, the maximum allowed cluster size - * on a volume is 4kib. - * - * The compression method is based on independently compressing blocks of X - * clusters, where X is determined from the compression_unit value found in the - * non-resident attribute record header (more precisely: X = 2^compression_unit - * clusters). On Windows NT/2k, X always is 16 clusters (compression_unit = 4). - * - * There are three different cases of how a compression block of X clusters - * can be stored: - * - * 1) The data in the block is all zero (a sparse block): - * This is stored as a sparse block in the runlist, i.e. the runlist - * entry has length = X and lcn = -1. The mapping pairs array actually - * uses a delta_lcn value length of 0, i.e. delta_lcn is not present at - * all, which is then interpreted by the driver as lcn = -1. - * NOTE: Even uncompressed files can be sparse on NTFS 3.0 volumes, then - * the same principles apply as above, except that the length is not - * restricted to being any particular value. - * - * 2) The data in the block is not compressed: - * This happens when compression doesn't reduce the size of the block - * in clusters. I.e. if compression has a small effect so that the - * compressed data still occupies X clusters, then the uncompressed data - * is stored in the block. - * This case is recognised by the fact that the runlist entry has - * length = X and lcn >= 0. The mapping pairs array stores this as - * normal with a run length of X and some specific delta_lcn, i.e. - * delta_lcn has to be present. - * - * 3) The data in the block is compressed: - * The common case. This case is recognised by the fact that the run - * list entry has length L < X and lcn >= 0. The mapping pairs array - * stores this as normal with a run length of X and some specific - * delta_lcn, i.e. delta_lcn has to be present. This runlist entry is - * immediately followed by a sparse entry with length = X - L and - * lcn = -1. The latter entry is to make up the vcn counting to the - * full compression block size X. - * - * In fact, life is more complicated because adjacent entries of the same type - * can be coalesced. This means that one has to keep track of the number of - * clusters handled and work on a basis of X clusters at a time being one - * block. An example: if length L > X this means that this particular runlist - * entry contains a block of length X and part of one or more blocks of length - * L - X. Another example: if length L < X, this does not necessarily mean that - * the block is compressed as it might be that the lcn changes inside the block - * and hence the following runlist entry describes the continuation of the - * potentially compressed block. The block would be compressed if the - * following runlist entry describes at least X - L sparse clusters, thus - * making up the compression block length as described in point 3 above. (Of - * course, there can be several runlist entries with small lengths so that the - * sparse entry does not follow the first data containing entry with - * length < X.) - * - * NOTE: At the end of the compressed attribute value, there most likely is not - * just the right amount of data to make up a compression block, thus this data - * is not even attempted to be compressed. It is just stored as is, unless - * the number of clusters it occupies is reduced when compressed in which case - * it is stored as a compressed compression block, complete with sparse - * clusters at the end. - */ - -/** - * enum RESIDENT_ATTR_FLAGS - Flags of resident attributes (8-bit). - */ -#ifdef __sun -typedef uint8_t RESIDENT_ATTR_FLAGS; -#define RESIDENT_ATTR_IS_INDEXED (0x01) -#else /* not __sun */ -typedef enum { - RESIDENT_ATTR_IS_INDEXED = 0x01, /* Attribute is referenced in an index - (has implications for deleting and - modifying the attribute). */ -} __attribute__((__packed__)) RESIDENT_ATTR_FLAGS; -#endif /* __sun */ - -/** - * struct ATTR_RECORD - Attribute record header. - * - * Always aligned to 8-byte boundary. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0*/ ATTR_TYPES type; /* The (32-bit) type of the attribute. */ -/* 4*/ le32 length; /* Byte size of the resident part of the - attribute (aligned to 8-byte boundary). - Used to get to the next attribute. */ -/* 8*/ u8 non_resident; /* If 0, attribute is resident. - If 1, attribute is non-resident. */ -/* 9*/ u8 name_length; /* Unicode character size of name of attribute. - 0 if unnamed. */ -/* 10*/ le16 name_offset; /* If name_length != 0, the byte offset to the - beginning of the name from the attribute - record. Note that the name is stored as a - Unicode string. When creating, place offset - just at the end of the record header. Then, - follow with attribute value or mapping pairs - array, resident and non-resident attributes - respectively, aligning to an 8-byte - boundary. */ -/* 12*/ ATTR_FLAGS flags; /* Flags describing the attribute. */ -/* 14*/ le16 instance; /* The instance of this attribute record. This - number is unique within this mft record (see - MFT_RECORD/next_attribute_instance notes - above for more details). */ -/* 16*/ union { - /* Resident attributes. */ - struct { -/* 16 */ le32 value_length; /* Byte size of attribute value. */ -/* 20 */ le16 value_offset; /* Byte offset of the attribute - value from the start of the - attribute record. When creating, - align to 8-byte boundary if we - have a name present as this might - not have a length of a multiple - of 8-bytes. */ -/* 22 */ RESIDENT_ATTR_FLAGS resident_flags; /* See above. */ -/* 23 */ s8 reservedR; /* Reserved/alignment to 8-byte - boundary. */ -/* 24 */ void *resident_end[]; /* Use offsetof(ATTR_RECORD, - resident_end) to get size of - a resident attribute. */ - } __attribute__((__packed__)) res; - - /* Non-resident attributes. */ - struct { -/* 16*/ leVCN lowest_vcn;/* Lowest valid virtual cluster number - for this portion of the attribute value or - 0 if this is the only extent (usually the - case). - Only when an attribute list is used - does lowest_vcn != 0 ever occur. */ -/* 24*/ leVCN highest_vcn;/* Highest valid vcn of this extent of - the attribute value. - Usually there is only one - portion, so this usually equals the attribute - value size in clusters minus 1. Can be -1 for - zero length files. Can be 0 for "single extent" - attributes. */ -/* 32*/ le16 mapping_pairs_offset; /* Byte offset from the - beginning of the structure to the mapping pairs - array which contains the mappings between the - VCNs and the logical cluster numbers (LCNs). - When creating, place this at the end of this - record header aligned to 8-byte boundary. */ -/* 34*/ u8 compression_unit; /* The compression unit expressed - as the log to the base 2 of the number of - clusters in a compression unit. 0 means not - compressed. (This effectively limits the - compression unit size to be a power of two - clusters.) WinNT4 only uses a value of 4. */ -/* 35*/ u8 reserved1[5]; /* Align to 8-byte boundary. */ -/* The sizes below are only used when lowest_vcn is zero, as otherwise it would - be difficult to keep them up-to-date.*/ -/* 40*/ sle64 allocated_size; /* Byte size of disk space - allocated to hold the attribute value. Always - is a multiple of the cluster size. When a file - is compressed, this field is a multiple of the - compression block size (2^compression_unit) and - it represents the logically allocated space - rather than the actual on disk usage. For this - use the compressed_size (see below). */ -/* 48*/ sle64 data_size; /* Byte size of the attribute - value. Can be larger than allocated_size if - attribute value is compressed or sparse. */ -/* 56*/ sle64 initialized_size; /* Byte size of initialized - portion of the attribute value. Usually equals - data_size. */ -#ifdef __sun -/* 64 */ -#define non_resident_end compressed_size -#else /* not __sun */ -/* 64 */ void *non_resident_end[0]; /* Use offsetof(ATTR_RECORD, - non_resident_end) to get - size of a non resident - attribute. */ -#endif /* __sun */ -/* sizeof(uncompressed attr) = 64*/ -/* 64*/ sle64 compressed_size; /* Byte size of the attribute - value after compression. Only present when - compressed. Always is a multiple of the - cluster size. Represents the actual amount of - disk space being used on the disk. */ -/* 72 */ void *compressed_end[]; - /* Use offsetof(ATTR_RECORD, compressed_end) to - get size of a compressed attribute. */ -/* sizeof(compressed attr) = 72*/ - } __attribute__((__packed__)) nonres; - } __attribute__((__packed__)) u; -} __attribute__((__packed__)) ATTR_RECORD; -#ifdef __sun -#pragma pack() -#endif - -typedef ATTR_RECORD ATTR_REC; - -/** - * enum FILE_ATTR_FLAGS - File attribute flags (32-bit). - */ -typedef enum { - /* - * These flags are only present in the STANDARD_INFORMATION attribute - * (in the field file_attributes). - */ - FILE_ATTR_READONLY = const_cpu_to_le32(0x00000001), - FILE_ATTR_HIDDEN = const_cpu_to_le32(0x00000002), - FILE_ATTR_SYSTEM = const_cpu_to_le32(0x00000004), - /* Old DOS valid. Unused in NT. = cpu_to_le32(0x00000008), */ - - FILE_ATTR_DIRECTORY = const_cpu_to_le32(0x00000010), - /* FILE_ATTR_DIRECTORY is not considered valid in NT. It is reserved - for the DOS SUBDIRECTORY flag. */ - FILE_ATTR_ARCHIVE = const_cpu_to_le32(0x00000020), - FILE_ATTR_DEVICE = const_cpu_to_le32(0x00000040), - FILE_ATTR_NORMAL = const_cpu_to_le32(0x00000080), - - FILE_ATTR_TEMPORARY = const_cpu_to_le32(0x00000100), - FILE_ATTR_SPARSE_FILE = const_cpu_to_le32(0x00000200), - FILE_ATTR_REPARSE_POINT = const_cpu_to_le32(0x00000400), - FILE_ATTR_COMPRESSED = const_cpu_to_le32(0x00000800), - - FILE_ATTR_OFFLINE = const_cpu_to_le32(0x00001000), - FILE_ATTR_NOT_CONTENT_INDEXED = const_cpu_to_le32(0x00002000), - FILE_ATTR_ENCRYPTED = const_cpu_to_le32(0x00004000), - - FILE_ATTR_VALID_FLAGS = const_cpu_to_le32(0x00007fb7), - /* FILE_ATTR_VALID_FLAGS masks out the old DOS VolId and the - FILE_ATTR_DEVICE and preserves everything else. This mask - is used to obtain all flags that are valid for reading. */ - FILE_ATTR_VALID_SET_FLAGS = const_cpu_to_le32(0x000031a7), - /* FILE_ATTR_VALID_SET_FLAGS masks out the old DOS VolId, the - FILE_ATTR_DEVICE, FILE_ATTR_DIRECTORY, FILE_ATTR_SPARSE_FILE, - FILE_ATTR_REPARSE_POINT, FILE_ATRE_COMPRESSED and FILE_ATTR_ENCRYPTED - and preserves the rest. This mask is used to to obtain all flags that - are valid for setting. */ - - /** - * FILE_ATTR_I30_INDEX_PRESENT - Is it a directory? - * - * This is a copy of the MFT_RECORD_IS_DIRECTORY bit from the mft - * record, telling us whether this is a directory or not, i.e. whether - * it has an index root attribute named "$I30" or not. - * - * This flag is only present in the FILE_NAME attribute (in the - * file_attributes field). - */ - FILE_ATTR_I30_INDEX_PRESENT = const_cpu_to_le32(0x10000000), - - /** - * FILE_ATTR_VIEW_INDEX_PRESENT - Does have a non-directory index? - * - * This is a copy of the MFT_RECORD_IS_VIEW_INDEX bit from the mft - * record, telling us whether this file has a view index present (eg. - * object id index, quota index, one of the security indexes and the - * reparse points index). - * - * This flag is only present in the $STANDARD_INFORMATION and - * $FILE_NAME attributes. - */ - FILE_ATTR_VIEW_INDEX_PRESENT = const_cpu_to_le32(0x20000000), -} __attribute__((__packed__)) FILE_ATTR_FLAGS; - -/* - * NOTE on times in NTFS: All times are in MS standard time format, i.e. they - * are the number of 100-nanosecond intervals since 1st January 1601, 00:00:00 - * universal coordinated time (UTC). (In Linux time starts 1st January 1970, - * 00:00:00 UTC and is stored as the number of 1-second intervals since then.) - */ - -/** - * struct STANDARD_INFORMATION - Attribute: Standard information (0x10). - * - * NOTE: Always resident. - * NOTE: Present in all base file records on a volume. - * NOTE: There is conflicting information about the meaning of each of the time - * fields but the meaning as defined below has been verified to be - * correct by practical experimentation on Windows NT4 SP6a and is hence - * assumed to be the one and only correct interpretation. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0*/ sle64 creation_time; /* Time file was created. Updated when - a filename is changed(?). */ -/* 8*/ sle64 last_data_change_time; /* Time the data attribute was last - modified. */ -/* 16*/ sle64 last_mft_change_time; /* Time this mft record was last - modified. */ -/* 24*/ sle64 last_access_time; /* Approximate time when the file was - last accessed (obviously this is not - updated on read-only volumes). In - Windows this is only updated when - accessed if some time delta has - passed since the last update. Also, - last access times updates can be - disabled altogether for speed. */ -/* 32*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ -/* 36*/ union { - /* NTFS 1.2 (and previous, presumably) */ - struct { - /* 36 */ u8 reserved12[12]; /* Reserved/alignment to 8-byte - boundary. */ - /* 48 */ void *v1_end[]; /* Marker for offsetof(). */ - } __attribute__((__packed__)) v12; -/* sizeof() = 48 bytes */ - /* NTFS 3.0 */ - struct { -/* - * If a volume has been upgraded from a previous NTFS version, then these - * fields are present only if the file has been accessed since the upgrade. - * Recognize the difference by comparing the length of the resident attribute - * value. If it is 48, then the following fields are missing. If it is 72 then - * the fields are present. Maybe just check like this: - * if (resident.ValueLength < sizeof(STANDARD_INFORMATION)) { - * Assume NTFS 1.2- format. - * If (volume version is 3.0+) - * Upgrade attribute to NTFS 3.0 format. - * else - * Use NTFS 1.2- format for access. - * } else - * Use NTFS 3.0 format for access. - * Only problem is that it might be legal to set the length of the value to - * arbitrarily large values thus spoiling this check. - But chkdsk probably - * views that as a corruption, assuming that it behaves like this for all - * attributes. - */ - /* 36*/ le32 maximum_versions; /* Maximum allowed versions for - file. Zero if version numbering is disabled. */ - /* 40*/ le32 version_number; /* This file's version (if any). - Set to zero if maximum_versions is zero. */ - /* 44*/ le32 class_id; /* Class id from bidirectional - class id index (?). */ - /* 48*/ le32 owner_id; /* Owner_id of the user owning - the file. Translate via $Q index in FILE_Extend - /$Quota to the quota control entry for the user - owning the file. Zero if quotas are disabled. */ - /* 52*/ le32 security_id; /* Security_id for the file. - Translate via $SII index and $SDS data stream - in FILE_Secure to the security descriptor. */ - /* 56*/ le64 quota_charged; /* Byte size of the charge to - the quota for all streams of the file. Note: Is - zero if quotas are disabled. */ - /* 64*/ le64 usn; /* Last update sequence number - of the file. This is a direct index into the - change (aka USN) journal file. It is zero if - the USN journal is disabled. - NOTE: To disable the journal need to delete - the journal file itself and to then walk the - whole mft and set all USN entries in all mft - records to zero! (This can take a while!) - The journal is FILE_Extend/$UsnJrnl. Win2k - will recreate the journal and initiate - logging if necessary when mounting the - partition. This, in contrast to disabling the - journal is a very fast process, so the user - won't even notice it. */ - /* 72*/ void *v3_end[]; /* Marker for offsetof(). */ - } __attribute__((__packed__)) v30; - } __attribute__((__packed__)) u; -/* sizeof() = 72 bytes (NTFS 3.0) */ -} __attribute__((__packed__)) STANDARD_INFORMATION; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct ATTR_LIST_ENTRY - Attribute: Attribute list (0x20). - * - * - Can be either resident or non-resident. - * - Value consists of a sequence of variable length, 8-byte aligned, - * ATTR_LIST_ENTRY records. - * - The attribute list attribute contains one entry for each attribute of - * the file in which the list is located, except for the list attribute - * itself. The list is sorted: first by attribute type, second by attribute - * name (if present), third by instance number. The extents of one - * non-resident attribute (if present) immediately follow after the initial - * extent. They are ordered by lowest_vcn and have their instance set to zero. - * It is not allowed to have two attributes with all sorting keys equal. - * - Further restrictions: - * - If not resident, the vcn to lcn mapping array has to fit inside the - * base mft record. - * - The attribute list attribute value has a maximum size of 256kb. This - * is imposed by the Windows cache manager. - * - Attribute lists are only used when the attributes of mft record do not - * fit inside the mft record despite all attributes (that can be made - * non-resident) having been made non-resident. This can happen e.g. when: - * - File has a large number of hard links (lots of file name - * attributes present). - * - The mapping pairs array of some non-resident attribute becomes so - * large due to fragmentation that it overflows the mft record. - * - The security descriptor is very complex (not applicable to - * NTFS 3.0 volumes). - * - There are many named streams. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0*/ ATTR_TYPES type; /* Type of referenced attribute. */ -/* 4*/ le16 length; /* Byte size of this entry. */ -/* 6*/ u8 name_length; /* Size in Unicode chars of the name of the - attribute or 0 if unnamed. */ -/* 7*/ u8 name_offset; /* Byte offset to beginning of attribute name - (always set this to where the name would - start even if unnamed). */ -/* 8*/ leVCN lowest_vcn; /* Lowest virtual cluster number of this portion - of the attribute value. This is usually 0. It - is non-zero for the case where one attribute - does not fit into one mft record and thus - several mft records are allocated to hold - this attribute. In the latter case, each mft - record holds one extent of the attribute and - there is one attribute list entry for each - extent. NOTE: This is DEFINITELY a signed - value! The windows driver uses cmp, followed - by jg when comparing this, thus it treats it - as signed. */ -/* 16*/ leMFT_REF mft_reference;/* The reference of the mft record holding - the ATTR_RECORD for this portion of the - attribute value. */ -/* 24*/ le16 instance; /* If lowest_vcn = 0, the instance of the - attribute being referenced; otherwise 0. */ -/* 26*/ ntfschar name[]; /* Use when creating only. When reading use - name_offset to determine the location of the - name. */ -/* sizeof() = 26 + (attribute_name_length * 2) bytes */ -} __attribute__((__packed__)) ATTR_LIST_ENTRY; -#ifdef __sun -#pragma pack() -#endif - -/* - * The maximum allowed length for a file name. - */ -#define NTFS_MAX_NAME_LEN 255 - -/** - * enum FILE_NAME_TYPE_FLAGS - Possible namespaces for filenames in ntfs. - * (8-bit). - */ -#ifdef __sun -typedef uint8_t FILE_NAME_TYPE_FLAGS; -#define FILE_NAME_POSIX (0x00) -#define FILE_NAME_WIN32 (0x01) -#define FILE_NAME_DOS (0x02) -#define FILE_NAME_WIN32_AND_DOS (0x03) -#else /* not __sun */ -typedef enum { - FILE_NAME_POSIX = 0x00, - /* This is the largest namespace. It is case sensitive and - allows all Unicode characters except for: '\0' and '/'. - Beware that in WinNT/2k files which eg have the same name - except for their case will not be distinguished by the - standard utilities and thus a "del filename" will delete - both "filename" and "fileName" without warning. */ - FILE_NAME_WIN32 = 0x01, - /* The standard WinNT/2k NTFS long filenames. Case insensitive. - All Unicode chars except: '\0', '"', '*', '/', ':', '<', - '>', '?', '\' and '|'. Further, names cannot end with a '.' - or a space. */ - FILE_NAME_DOS = 0x02, - /* The standard DOS filenames (8.3 format). Uppercase only. - All 8-bit characters greater space, except: '"', '*', '+', - ',', '/', ':', ';', '<', '=', '>', '?' and '\'. */ - FILE_NAME_WIN32_AND_DOS = 0x03, - /* 3 means that both the Win32 and the DOS filenames are - identical and hence have been saved in this single filename - record. */ -} __attribute__((__packed__)) FILE_NAME_TYPE_FLAGS; -#endif /* __sun */ - -/** - * struct FILE_NAME_ATTR - Attribute: Filename (0x30). - * - * NOTE: Always resident. - * NOTE: All fields, except the parent_directory, are only updated when the - * filename is changed. Until then, they just become out of sync with - * reality and the more up to date values are present in the standard - * information attribute. - * NOTE: There is conflicting information about the meaning of each of the time - * fields but the meaning as defined below has been verified to be - * correct by practical experimentation on Windows NT4 SP6a and is hence - * assumed to be the one and only correct interpretation. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*hex ofs*/ -/* 0*/ leMFT_REF parent_directory; /* Directory this filename is - referenced from. */ -/* 8*/ sle64 creation_time; /* Time file was created. */ -/* 10*/ sle64 last_data_change_time; /* Time the data attribute was last - modified. */ -/* 18*/ sle64 last_mft_change_time; /* Time this mft record was last - modified. */ -/* 20*/ sle64 last_access_time; /* Last time this mft record was - accessed. */ -/* 28*/ sle64 allocated_size; /* Byte size of on-disk allocated space - for the data attribute. So for - normal $DATA, this is the - allocated_size from the unnamed - $DATA attribute and for compressed - and/or sparse $DATA, this is the - compressed_size from the unnamed - $DATA attribute. NOTE: This is a - multiple of the cluster size. */ -/* 30*/ sle64 data_size; /* Byte size of actual data in data - attribute. */ -/* 38*/ FILE_ATTR_FLAGS file_attributes; /* Flags describing the file. */ -/* 3c*/ union { - /* 3c*/ struct { - /* 3c*/ le16 packed_ea_size; /* Size of the buffer needed to - pack the extended attributes - (EAs), if such are present.*/ - /* 3e*/ le16 reserved; /* Reserved for alignment. */ - } __attribute__((__packed__)) s; - /* 3c*/ le32 reparse_point_tag; /* Type of reparse point, - present only in reparse - points and only if there are - no EAs. */ - } __attribute__((__packed__)) u; -/* 40*/ u8 file_name_length; /* Length of file name in - (Unicode) characters. */ -/* 41*/ FILE_NAME_TYPE_FLAGS file_name_type; /* Namespace of the file name.*/ -/* 42*/ ntfschar file_name[]; /* File name in Unicode. */ -} __attribute__((__packed__)) FILE_NAME_ATTR; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct GUID - GUID structures store globally unique identifiers (GUID). - * - * A GUID is a 128-bit value consisting of one group of eight hexadecimal - * digits, followed by three groups of four hexadecimal digits each, followed - * by one group of twelve hexadecimal digits. GUIDs are Microsoft's - * implementation of the distributed computing environment (DCE) universally - * unique identifier (UUID). - * - * Example of a GUID in string format: - * 1F010768-5A73-BC91-0010-A52216A7227B - * And the same in binary: - * 1F0107685A73BC910010A52216A7227B - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef union { - struct { - le32 data1; /* The first eight hexadecimal digits of the - GUID. */ - le16 data2; /* The first group of four hexadecimal - digits. */ - le16 data3; /* The second group of four hexadecimal - digits. */ - u8 data4[8]; /* The first two bytes are the third group of - four hexadecimal digits. The remaining six - bytes are the final 12 hexadecimal digits. */ - } __attribute__((__packed__)) s; - u8 raw[16]; /* Raw binary for ease of access. */ -} __attribute__((__packed__)) GUID; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct OBJ_ID_INDEX_DATA - FILE_Extend/$ObjId contains an index named $O. - * - * This index contains all object_ids present on the volume as the index keys - * and the corresponding mft_record numbers as the index entry data parts. - * - * The data part (defined below) also contains three other object_ids: - * birth_volume_id - object_id of FILE_Volume on which the file was first - * created. Optional (i.e. can be zero). - * birth_object_id - object_id of file when it was first created. Usually - * equals the object_id. Optional (i.e. can be zero). - * domain_id - Reserved (always zero). - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - leMFT_REF mft_reference;/* Mft record containing the object_id in - the index entry key. */ - union { - struct { - GUID birth_volume_id; - GUID birth_object_id; - GUID domain_id; - } __attribute__((__packed__)) s; - u8 extended_info[48]; - } __attribute__((__packed__)) u; -} __attribute__((__packed__)) OBJ_ID_INDEX_DATA; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct OBJECT_ID_ATTR - Attribute: Object id (NTFS 3.0+) (0x40). - * - * NOTE: Always resident. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - GUID object_id; /* Unique id assigned to the - file.*/ - /* The following fields are optional. The attribute value size is 16 - bytes, i.e. sizeof(GUID), if these are not present at all. Note, - the entries can be present but one or more (or all) can be zero - meaning that that particular value(s) is(are) not defined. Note, - when the fields are missing here, it is well possible that they are - to be found within the $Extend/$ObjId system file indexed under the - above object_id. */ - union { - struct { - GUID birth_volume_id; /* Unique id of volume on which - the file was first created.*/ - GUID birth_object_id; /* Unique id of file when it was - first created. */ - GUID domain_id; /* Reserved, zero. */ - } __attribute__((__packed__)) s; - u8 extended_info[48]; - } __attribute__((__packed__)) u; -} __attribute__((__packed__)) OBJECT_ID_ATTR; -#ifdef __sun -#pragma pack() -#endif - -#if 0 -/** - * enum IDENTIFIER_AUTHORITIES - - * - * The pre-defined IDENTIFIER_AUTHORITIES used as SID_IDENTIFIER_AUTHORITY in - * the SID structure (see below). - */ -typedef enum { /* SID string prefix. */ - SECURITY_NULL_SID_AUTHORITY = {0, 0, 0, 0, 0, 0}, /* S-1-0 */ - SECURITY_WORLD_SID_AUTHORITY = {0, 0, 0, 0, 0, 1}, /* S-1-1 */ - SECURITY_LOCAL_SID_AUTHORITY = {0, 0, 0, 0, 0, 2}, /* S-1-2 */ - SECURITY_CREATOR_SID_AUTHORITY = {0, 0, 0, 0, 0, 3}, /* S-1-3 */ - SECURITY_NON_UNIQUE_AUTHORITY = {0, 0, 0, 0, 0, 4}, /* S-1-4 */ - SECURITY_NT_SID_AUTHORITY = {0, 0, 0, 0, 0, 5}, /* S-1-5 */ -} IDENTIFIER_AUTHORITIES; -#endif - -/** - * enum RELATIVE_IDENTIFIERS - - * - * These relative identifiers (RIDs) are used with the above identifier - * authorities to make up universal well-known SIDs. - * - * Note: The relative identifier (RID) refers to the portion of a SID, which - * identifies a user or group in relation to the authority that issued the SID. - * For example, the universal well-known SID Creator Owner ID (S-1-3-0) is - * made up of the identifier authority SECURITY_CREATOR_SID_AUTHORITY (3) and - * the relative identifier SECURITY_CREATOR_OWNER_RID (0). - */ -typedef enum { /* Identifier authority. */ - SECURITY_NULL_RID = 0, /* S-1-0 */ - SECURITY_WORLD_RID = 0, /* S-1-1 */ - SECURITY_LOCAL_RID = 0, /* S-1-2 */ - - SECURITY_CREATOR_OWNER_RID = 0, /* S-1-3 */ - SECURITY_CREATOR_GROUP_RID = 1, /* S-1-3 */ - - SECURITY_CREATOR_OWNER_SERVER_RID = 2, /* S-1-3 */ - SECURITY_CREATOR_GROUP_SERVER_RID = 3, /* S-1-3 */ - - SECURITY_DIALUP_RID = 1, - SECURITY_NETWORK_RID = 2, - SECURITY_BATCH_RID = 3, - SECURITY_INTERACTIVE_RID = 4, - SECURITY_SERVICE_RID = 6, - SECURITY_ANONYMOUS_LOGON_RID = 7, - SECURITY_PROXY_RID = 8, - SECURITY_ENTERPRISE_CONTROLLERS_RID=9, - SECURITY_SERVER_LOGON_RID = 9, - SECURITY_PRINCIPAL_SELF_RID = 0xa, - SECURITY_AUTHENTICATED_USER_RID = 0xb, - SECURITY_RESTRICTED_CODE_RID = 0xc, - SECURITY_TERMINAL_SERVER_RID = 0xd, - - SECURITY_LOGON_IDS_RID = 5, - SECURITY_LOGON_IDS_RID_COUNT = 3, - - SECURITY_LOCAL_SYSTEM_RID = 0x12, - - SECURITY_NT_NON_UNIQUE = 0x15, - - SECURITY_BUILTIN_DOMAIN_RID = 0x20, - - /* - * Well-known domain relative sub-authority values (RIDs). - */ - - /* Users. */ - DOMAIN_USER_RID_ADMIN = 0x1f4, - DOMAIN_USER_RID_GUEST = 0x1f5, - DOMAIN_USER_RID_KRBTGT = 0x1f6, - - /* Groups. */ - DOMAIN_GROUP_RID_ADMINS = 0x200, - DOMAIN_GROUP_RID_USERS = 0x201, - DOMAIN_GROUP_RID_GUESTS = 0x202, - DOMAIN_GROUP_RID_COMPUTERS = 0x203, - DOMAIN_GROUP_RID_CONTROLLERS = 0x204, - DOMAIN_GROUP_RID_CERT_ADMINS = 0x205, - DOMAIN_GROUP_RID_SCHEMA_ADMINS = 0x206, - DOMAIN_GROUP_RID_ENTERPRISE_ADMINS= 0x207, - DOMAIN_GROUP_RID_POLICY_ADMINS = 0x208, - - /* Aliases. */ - DOMAIN_ALIAS_RID_ADMINS = 0x220, - DOMAIN_ALIAS_RID_USERS = 0x221, - DOMAIN_ALIAS_RID_GUESTS = 0x222, - DOMAIN_ALIAS_RID_POWER_USERS = 0x223, - - DOMAIN_ALIAS_RID_ACCOUNT_OPS = 0x224, - DOMAIN_ALIAS_RID_SYSTEM_OPS = 0x225, - DOMAIN_ALIAS_RID_PRINT_OPS = 0x226, - DOMAIN_ALIAS_RID_BACKUP_OPS = 0x227, - - DOMAIN_ALIAS_RID_REPLICATOR = 0x228, - DOMAIN_ALIAS_RID_RAS_SERVERS = 0x229, - DOMAIN_ALIAS_RID_PREW2KCOMPACCESS = 0x22a, -} RELATIVE_IDENTIFIERS; - -/* - * The universal well-known SIDs: - * - * NULL_SID S-1-0-0 - * WORLD_SID S-1-1-0 - * LOCAL_SID S-1-2-0 - * CREATOR_OWNER_SID S-1-3-0 - * CREATOR_GROUP_SID S-1-3-1 - * CREATOR_OWNER_SERVER_SID S-1-3-2 - * CREATOR_GROUP_SERVER_SID S-1-3-3 - * - * (Non-unique IDs) S-1-4 - * - * NT well-known SIDs: - * - * NT_AUTHORITY_SID S-1-5 - * DIALUP_SID S-1-5-1 - * - * NETWORK_SID S-1-5-2 - * BATCH_SID S-1-5-3 - * INTERACTIVE_SID S-1-5-4 - * SERVICE_SID S-1-5-6 - * ANONYMOUS_LOGON_SID S-1-5-7 (aka null logon session) - * PROXY_SID S-1-5-8 - * SERVER_LOGON_SID S-1-5-9 (aka domain controller account) - * SELF_SID S-1-5-10 (self RID) - * AUTHENTICATED_USER_SID S-1-5-11 - * RESTRICTED_CODE_SID S-1-5-12 (running restricted code) - * TERMINAL_SERVER_SID S-1-5-13 (running on terminal server) - * - * (Logon IDs) S-1-5-5-X-Y - * - * (NT non-unique IDs) S-1-5-0x15-... - * - * (Built-in domain) S-1-5-0x20 - */ - -/** - * union SID_IDENTIFIER_AUTHORITY - A 48-bit value used in the SID structure - * - * NOTE: This is stored as a big endian number. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef union { - struct { - be16 high_part; /* High 16-bits. */ - be32 low_part; /* Low 32-bits. */ - } __attribute__((__packed__)) s; - u8 value[6]; /* Value as individual bytes. */ -} __attribute__((__packed__)) SID_IDENTIFIER_AUTHORITY; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SID - - * - * The SID structure is a variable-length structure used to uniquely identify - * users or groups. SID stands for security identifier. - * - * The standard textual representation of the SID is of the form: - * S-R-I-S-S... - * Where: - * - The first "S" is the literal character 'S' identifying the following - * digits as a SID. - * - R is the revision level of the SID expressed as a sequence of digits - * in decimal. - * - I is the 48-bit identifier_authority, expressed as digits in decimal, - * if I < 2^32, or hexadecimal prefixed by "0x", if I >= 2^32. - * - S... is one or more sub_authority values, expressed as digits in - * decimal. - * - * Example SID; the domain-relative SID of the local Administrators group on - * Windows NT/2k: - * S-1-5-32-544 - * This translates to a SID with: - * revision = 1, - * sub_authority_count = 2, - * identifier_authority = {0,0,0,0,0,5}, // SECURITY_NT_AUTHORITY - * sub_authority[0] = 32, // SECURITY_BUILTIN_DOMAIN_RID - * sub_authority[1] = 544 // DOMAIN_ALIAS_RID_ADMINS - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u8 revision; - u8 sub_authority_count; - SID_IDENTIFIER_AUTHORITY identifier_authority; - le32 sub_authority[1]; /* At least one sub_authority. */ -} __attribute__((__packed__)) SID; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum SID_CONSTANTS - Current constants for SIDs. - */ -typedef enum { - SID_REVISION = 1, /* Current revision level. */ - SID_MAX_SUB_AUTHORITIES = 15, /* Maximum number of those. */ - SID_RECOMMENDED_SUB_AUTHORITIES = 1, /* Will change to around 6 in - a future revision. */ -} SID_CONSTANTS; - -/** - * enum ACE_TYPES - The predefined ACE types (8-bit, see below). - */ -#ifdef __sun -typedef uint8_t ACE_TYPES; -#define ACCESS_ALLOWED_ACE_TYPE (0) -#define ACCESS_DENIED_ACE_TYPE (1) -#define SYSTEM_AUDIT_ACE_TYPE (2) -#else /* not __sun */ -typedef enum { - ACCESS_MIN_MS_ACE_TYPE = 0, - ACCESS_ALLOWED_ACE_TYPE = 0, - ACCESS_DENIED_ACE_TYPE = 1, - SYSTEM_AUDIT_ACE_TYPE = 2, - SYSTEM_ALARM_ACE_TYPE = 3, /* Not implemented as of Win2k. */ - ACCESS_MAX_MS_V2_ACE_TYPE = 3, - - ACCESS_ALLOWED_COMPOUND_ACE_TYPE= 4, - ACCESS_MAX_MS_V3_ACE_TYPE = 4, - - /* The following are Win2k only. */ - ACCESS_MIN_MS_OBJECT_ACE_TYPE = 5, - ACCESS_ALLOWED_OBJECT_ACE_TYPE = 5, - ACCESS_DENIED_OBJECT_ACE_TYPE = 6, - SYSTEM_AUDIT_OBJECT_ACE_TYPE = 7, - SYSTEM_ALARM_OBJECT_ACE_TYPE = 8, - ACCESS_MAX_MS_OBJECT_ACE_TYPE = 8, - - ACCESS_MAX_MS_V4_ACE_TYPE = 8, - - /* This one is for WinNT&2k. */ - ACCESS_MAX_MS_ACE_TYPE = 8, -} __attribute__((__packed__)) ACE_TYPES; -#endif /* __sun */ - -/** - * enum ACE_FLAGS - The ACE flags (8-bit) for audit and inheritance. - * - * SUCCESSFUL_ACCESS_ACE_FLAG is only used with system audit and alarm ACE - * types to indicate that a message is generated (in Windows!) for successful - * accesses. - * - * FAILED_ACCESS_ACE_FLAG is only used with system audit and alarm ACE types - * to indicate that a message is generated (in Windows!) for failed accesses. - */ -#ifdef __sun -typedef uint8_t ACE_FLAGS; -#define OBJECT_INHERIT_ACE (0x01) -#define CONTAINER_INHERIT_ACE (0x02) -#define INHERIT_ONLY_ACE (0x08) -#else /* not __sun */ -typedef enum { - /* The inheritance flags. */ - OBJECT_INHERIT_ACE = 0x01, - CONTAINER_INHERIT_ACE = 0x02, - NO_PROPAGATE_INHERIT_ACE = 0x04, - INHERIT_ONLY_ACE = 0x08, - INHERITED_ACE = 0x10, /* Win2k only. */ - VALID_INHERIT_FLAGS = 0x1f, - - /* The audit flags. */ - SUCCESSFUL_ACCESS_ACE_FLAG = 0x40, - FAILED_ACCESS_ACE_FLAG = 0x80, -} __attribute__((__packed__)) ACE_FLAGS; -#endif /* __sun */ - -/** - * struct ACE_HEADER - - * - * An ACE is an access-control entry in an access-control list (ACL). - * An ACE defines access to an object for a specific user or group or defines - * the types of access that generate system-administration messages or alarms - * for a specific user or group. The user or group is identified by a security - * identifier (SID). - * - * Each ACE starts with an ACE_HEADER structure (aligned on 4-byte boundary), - * which specifies the type and size of the ACE. The format of the subsequent - * data depends on the ACE type. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - ACE_TYPES type; /* Type of the ACE. */ - ACE_FLAGS flags; /* Flags describing the ACE. */ - le16 size; /* Size in bytes of the ACE. */ -} __attribute__((__packed__)) ACE_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum ACCESS_MASK - The access mask (32-bit). - * - * Defines the access rights. - */ -typedef enum { - /* - * The specific rights (bits 0 to 15). Depend on the type of the - * object being secured by the ACE. - */ - - /* Specific rights for files and directories are as follows: */ - - /* Right to read data from the file. (FILE) */ - FILE_READ_DATA = const_cpu_to_le32(0x00000001), - /* Right to list contents of a directory. (DIRECTORY) */ - FILE_LIST_DIRECTORY = const_cpu_to_le32(0x00000001), - - /* Right to write data to the file. (FILE) */ - FILE_WRITE_DATA = const_cpu_to_le32(0x00000002), - /* Right to create a file in the directory. (DIRECTORY) */ - FILE_ADD_FILE = const_cpu_to_le32(0x00000002), - - /* Right to append data to the file. (FILE) */ - FILE_APPEND_DATA = const_cpu_to_le32(0x00000004), - /* Right to create a subdirectory. (DIRECTORY) */ - FILE_ADD_SUBDIRECTORY = const_cpu_to_le32(0x00000004), - - /* Right to read extended attributes. (FILE/DIRECTORY) */ - FILE_READ_EA = const_cpu_to_le32(0x00000008), - - /* Right to write extended attributes. (FILE/DIRECTORY) */ - FILE_WRITE_EA = const_cpu_to_le32(0x00000010), - - /* Right to execute a file. (FILE) */ - FILE_EXECUTE = const_cpu_to_le32(0x00000020), - /* Right to traverse the directory. (DIRECTORY) */ - FILE_TRAVERSE = const_cpu_to_le32(0x00000020), - - /* - * Right to delete a directory and all the files it contains (its - * children), even if the files are read-only. (DIRECTORY) - */ - FILE_DELETE_CHILD = const_cpu_to_le32(0x00000040), - - /* Right to read file attributes. (FILE/DIRECTORY) */ - FILE_READ_ATTRIBUTES = const_cpu_to_le32(0x00000080), - - /* Right to change file attributes. (FILE/DIRECTORY) */ - FILE_WRITE_ATTRIBUTES = const_cpu_to_le32(0x00000100), - - /* - * The standard rights (bits 16 to 23). Are independent of the type of - * object being secured. - */ - - /* Right to delete the object. */ - DELETE = const_cpu_to_le32(0x00010000), - - /* - * Right to read the information in the object's security descriptor, - * not including the information in the SACL. I.e. right to read the - * security descriptor and owner. - */ - READ_CONTROL = const_cpu_to_le32(0x00020000), - - /* Right to modify the DACL in the object's security descriptor. */ - WRITE_DAC = const_cpu_to_le32(0x00040000), - - /* Right to change the owner in the object's security descriptor. */ - WRITE_OWNER = const_cpu_to_le32(0x00080000), - - /* - * Right to use the object for synchronization. Enables a process to - * wait until the object is in the signalled state. Some object types - * do not support this access right. - */ - SYNCHRONIZE = const_cpu_to_le32(0x00100000), - - /* - * The following STANDARD_RIGHTS_* are combinations of the above for - * convenience and are defined by the Win32 API. - */ - - /* These are currently defined to READ_CONTROL. */ - STANDARD_RIGHTS_READ = const_cpu_to_le32(0x00020000), - STANDARD_RIGHTS_WRITE = const_cpu_to_le32(0x00020000), - STANDARD_RIGHTS_EXECUTE = const_cpu_to_le32(0x00020000), - - /* Combines DELETE, READ_CONTROL, WRITE_DAC, and WRITE_OWNER access. */ - STANDARD_RIGHTS_REQUIRED = const_cpu_to_le32(0x000f0000), - - /* - * Combines DELETE, READ_CONTROL, WRITE_DAC, WRITE_OWNER, and - * SYNCHRONIZE access. - */ - STANDARD_RIGHTS_ALL = const_cpu_to_le32(0x001f0000), - - /* - * The access system ACL and maximum allowed access types (bits 24 to - * 25, bits 26 to 27 are reserved). - */ - ACCESS_SYSTEM_SECURITY = const_cpu_to_le32(0x01000000), - MAXIMUM_ALLOWED = const_cpu_to_le32(0x02000000), - - /* - * The generic rights (bits 28 to 31). These map onto the standard and - * specific rights. - */ - - /* Read, write, and execute access. */ - GENERIC_ALL = const_cpu_to_le32(0x10000000), - - /* Execute access. */ - GENERIC_EXECUTE = const_cpu_to_le32(0x20000000), - - /* - * Write access. For files, this maps onto: - * FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_DATA | - * FILE_WRITE_EA | STANDARD_RIGHTS_WRITE | SYNCHRONIZE - * For directories, the mapping has the same numerical value. See - * above for the descriptions of the rights granted. - */ - GENERIC_WRITE = const_cpu_to_le32(0x40000000), - - /* - * Read access. For files, this maps onto: - * FILE_READ_ATTRIBUTES | FILE_READ_DATA | FILE_READ_EA | - * STANDARD_RIGHTS_READ | SYNCHRONIZE - * For directories, the mapping has the same numerical value. See - * above for the descriptions of the rights granted. - */ - GENERIC_READ = const_cpu_to_le32(0x80000000), -} ACCESS_MASK; - -/** - * struct GENERIC_MAPPING - - * - * The generic mapping array. Used to denote the mapping of each generic - * access right to a specific access mask. - * - * FIXME: What exactly is this and what is it for? (AIA) - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - ACCESS_MASK generic_read; - ACCESS_MASK generic_write; - ACCESS_MASK generic_execute; - ACCESS_MASK generic_all; -} __attribute__((__packed__)) GENERIC_MAPPING; -#ifdef __sun -#pragma pack() -#endif - -/* - * The predefined ACE type structures are as defined below. - */ - -/** - * struct ACCESS_DENIED_ACE - - * - * ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ - ACE_TYPES type; /* Type of the ACE. */ - ACE_FLAGS flags; /* Flags describing the ACE. */ - le16 size; /* Size in bytes of the ACE. */ - -/* 4*/ ACCESS_MASK mask; /* Access mask associated with the ACE. */ -/* 8*/ SID sid; /* The SID associated with the ACE. */ -} __attribute__((__packed__)) ACCESS_ALLOWED_ACE, ACCESS_DENIED_ACE, - SYSTEM_AUDIT_ACE, SYSTEM_ALARM_ACE; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum OBJECT_ACE_FLAGS - The object ACE flags (32-bit). - */ -typedef enum { - ACE_OBJECT_TYPE_PRESENT = const_cpu_to_le32(1), - ACE_INHERITED_OBJECT_TYPE_PRESENT = const_cpu_to_le32(2), -} OBJECT_ACE_FLAGS; - -/** - * struct ACCESS_ALLOWED_OBJECT_ACE - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 ACE_HEADER; -- Unfolded here as gcc doesn't like unnamed structs. */ - ACE_TYPES type; /* Type of the ACE. */ - ACE_FLAGS flags; /* Flags describing the ACE. */ - le16 size; /* Size in bytes of the ACE. */ - -/* 4*/ ACCESS_MASK mask; /* Access mask associated with the ACE. */ -/* 8*/ OBJECT_ACE_FLAGS object_flags; /* Flags describing the object ACE. */ -/* 12*/ GUID object_type; -/* 28*/ GUID inherited_object_type; -/* 44*/ SID sid; /* The SID associated with the ACE. */ -} __attribute__((__packed__)) ACCESS_ALLOWED_OBJECT_ACE, - ACCESS_DENIED_OBJECT_ACE, - SYSTEM_AUDIT_OBJECT_ACE, - SYSTEM_ALARM_OBJECT_ACE; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct ACL - An ACL is an access-control list (ACL). - * - * An ACL starts with an ACL header structure, which specifies the size of - * the ACL and the number of ACEs it contains. The ACL header is followed by - * zero or more access control entries (ACEs). The ACL as well as each ACE - * are aligned on 4-byte boundaries. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u8 revision; /* Revision of this ACL. */ - u8 alignment1; - le16 size; /* Allocated space in bytes for ACL. Includes this - header, the ACEs and the remaining free space. */ - le16 ace_count; /* Number of ACEs in the ACL. */ - le16 alignment2; -/* sizeof() = 8 bytes */ -} __attribute__((__packed__)) ACL; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum ACL_CONSTANTS - Current constants for ACLs. - */ -typedef enum { - /* Current revision. */ - ACL_REVISION = 2, - ACL_REVISION_DS = 4, - - /* History of revisions. */ - ACL_REVISION1 = 1, - MIN_ACL_REVISION = 2, - ACL_REVISION2 = 2, - ACL_REVISION3 = 3, - ACL_REVISION4 = 4, - MAX_ACL_REVISION = 4, -} ACL_CONSTANTS; - -/** - * enum SECURITY_DESCRIPTOR_CONTROL - - * - * The security descriptor control flags (16-bit). - * - * SE_OWNER_DEFAULTED - This boolean flag, when set, indicates that the - * SID pointed to by the Owner field was provided by a - * defaulting mechanism rather than explicitly provided by the - * original provider of the security descriptor. This may - * affect the treatment of the SID with respect to inheritance - * of an owner. - * - * SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the - * SID in the Group field was provided by a defaulting mechanism - * rather than explicitly provided by the original provider of - * the security descriptor. This may affect the treatment of - * the SID with respect to inheritance of a primary group. - * - * SE_DACL_PRESENT - This boolean flag, when set, indicates that the - * security descriptor contains a discretionary ACL. If this - * flag is set and the Dacl field of the SECURITY_DESCRIPTOR is - * null, then a null ACL is explicitly being specified. - * - * SE_DACL_DEFAULTED - This boolean flag, when set, indicates that the - * ACL pointed to by the Dacl field was provided by a defaulting - * mechanism rather than explicitly provided by the original - * provider of the security descriptor. This may affect the - * treatment of the ACL with respect to inheritance of an ACL. - * This flag is ignored if the DaclPresent flag is not set. - * - * SE_SACL_PRESENT - This boolean flag, when set, indicates that the - * security descriptor contains a system ACL pointed to by the - * Sacl field. If this flag is set and the Sacl field of the - * SECURITY_DESCRIPTOR is null, then an empty (but present) - * ACL is being specified. - * - * SE_SACL_DEFAULTED - This boolean flag, when set, indicates that the - * ACL pointed to by the Sacl field was provided by a defaulting - * mechanism rather than explicitly provided by the original - * provider of the security descriptor. This may affect the - * treatment of the ACL with respect to inheritance of an ACL. - * This flag is ignored if the SaclPresent flag is not set. - * - * SE_SELF_RELATIVE - This boolean flag, when set, indicates that the - * security descriptor is in self-relative form. In this form, - * all fields of the security descriptor are contiguous in memory - * and all pointer fields are expressed as offsets from the - * beginning of the security descriptor. - */ -#ifdef __sun -typedef uint16_t SECURITY_DESCRIPTOR_CONTROL; -#define SE_DACL_PRESENT (const_cpu_to_le16(0x0004)) -#define SE_DACL_DEFAULTED (const_cpu_to_le16(0x0008)) -#define SE_SACL_PRESENT (const_cpu_to_le16(0x0010)) -#define SE_SACL_DEFAULTED (const_cpu_to_le16(0x0020)) -#define SE_SELF_RELATIVE (const_cpu_to_le16(0x8000)) -#else /* not __sun */ -typedef enum { - SE_OWNER_DEFAULTED = const_cpu_to_le16(0x0001), - SE_GROUP_DEFAULTED = const_cpu_to_le16(0x0002), - SE_DACL_PRESENT = const_cpu_to_le16(0x0004), - SE_DACL_DEFAULTED = const_cpu_to_le16(0x0008), - SE_SACL_PRESENT = const_cpu_to_le16(0x0010), - SE_SACL_DEFAULTED = const_cpu_to_le16(0x0020), - SE_DACL_AUTO_INHERIT_REQ = const_cpu_to_le16(0x0100), - SE_SACL_AUTO_INHERIT_REQ = const_cpu_to_le16(0x0200), - SE_DACL_AUTO_INHERITED = const_cpu_to_le16(0x0400), - SE_SACL_AUTO_INHERITED = const_cpu_to_le16(0x0800), - SE_DACL_PROTECTED = const_cpu_to_le16(0x1000), - SE_SACL_PROTECTED = const_cpu_to_le16(0x2000), - SE_RM_CONTROL_VALID = const_cpu_to_le16(0x4000), - SE_SELF_RELATIVE = const_cpu_to_le16(0x8000), -} __attribute__((__packed__)) SECURITY_DESCRIPTOR_CONTROL; -#endif /* __sun */ - -/** - * struct SECURITY_DESCRIPTOR_RELATIVE - - * - * Self-relative security descriptor. Contains the owner and group SIDs as well - * as the sacl and dacl ACLs inside the security descriptor itself. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u8 revision; /* Revision level of the security descriptor. */ - u8 alignment; - SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of - the descriptor as well as the following fields. */ - le32 owner; /* Byte offset to a SID representing an object's - owner. If this is NULL, no owner SID is present in - the descriptor. */ - le32 group; /* Byte offset to a SID representing an object's - primary group. If this is NULL, no primary group - SID is present in the descriptor. */ - le32 sacl; /* Byte offset to a system ACL. Only valid, if - SE_SACL_PRESENT is set in the control field. If - SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL - is specified. */ - le32 dacl; /* Byte offset to a discretionary ACL. Only valid, if - SE_DACL_PRESENT is set in the control field. If - SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL - (unconditionally granting access) is specified. */ -/* sizeof() = 0x14 bytes */ -} __attribute__((__packed__)) SECURITY_DESCRIPTOR_RELATIVE; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SECURITY_DESCRIPTOR - Absolute security descriptor. - * - * Does not contain the owner and group SIDs, nor the sacl and dacl ACLs inside - * the security descriptor. Instead, it contains pointers to these structures - * in memory. Obviously, absolute security descriptors are only useful for in - * memory representations of security descriptors. - * - * On disk, a self-relative security descriptor is used. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u8 revision; /* Revision level of the security descriptor. */ - u8 alignment; - SECURITY_DESCRIPTOR_CONTROL control; /* Flags qualifying the type of - the descriptor as well as the following fields. */ - SID *owner; /* Points to a SID representing an object's owner. If - this is NULL, no owner SID is present in the - descriptor. */ - SID *group; /* Points to a SID representing an object's primary - group. If this is NULL, no primary group SID is - present in the descriptor. */ - ACL *sacl; /* Points to a system ACL. Only valid, if - SE_SACL_PRESENT is set in the control field. If - SE_SACL_PRESENT is set but sacl is NULL, a NULL ACL - is specified. */ - ACL *dacl; /* Points to a discretionary ACL. Only valid, if - SE_DACL_PRESENT is set in the control field. If - SE_DACL_PRESENT is set but dacl is NULL, a NULL ACL - (unconditionally granting access) is specified. */ -} __attribute__((__packed__)) SECURITY_DESCRIPTOR; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum SECURITY_DESCRIPTOR_CONSTANTS - - * - * Current constants for security descriptors. - */ -typedef enum { - /* Current revision. */ - SECURITY_DESCRIPTOR_REVISION = 1, - SECURITY_DESCRIPTOR_REVISION1 = 1, - - /* The sizes of both the absolute and relative security descriptors is - the same as pointers, at least on ia32 architecture are 32-bit. */ - SECURITY_DESCRIPTOR_MIN_LENGTH = sizeof(SECURITY_DESCRIPTOR), -} SECURITY_DESCRIPTOR_CONSTANTS; - -/* - * Attribute: Security descriptor (0x50). - * - * A standard self-relative security descriptor. - * - * NOTE: Can be resident or non-resident. - * NOTE: Not used in NTFS 3.0+, as security descriptors are stored centrally - * in FILE_Secure and the correct descriptor is found using the security_id - * from the standard information attribute. - */ -typedef SECURITY_DESCRIPTOR_RELATIVE SECURITY_DESCRIPTOR_ATTR; - -/* - * On NTFS 3.0+, all security descriptors are stored in FILE_Secure. Only one - * referenced instance of each unique security descriptor is stored. - * - * FILE_Secure contains no unnamed data attribute, i.e. it has zero length. It - * does, however, contain two indexes ($SDH and $SII) as well as a named data - * stream ($SDS). - * - * Every unique security descriptor is assigned a unique security identifier - * (security_id, not to be confused with a SID). The security_id is unique for - * the NTFS volume and is used as an index into the $SII index, which maps - * security_ids to the security descriptor's storage location within the $SDS - * data attribute. The $SII index is sorted by ascending security_id. - * - * A simple hash is computed from each security descriptor. This hash is used - * as an index into the $SDH index, which maps security descriptor hashes to - * the security descriptor's storage location within the $SDS data attribute. - * The $SDH index is sorted by security descriptor hash and is stored in a B+ - * tree. When searching $SDH (with the intent of determining whether or not a - * new security descriptor is already present in the $SDS data stream), if a - * matching hash is found, but the security descriptors do not match, the - * search in the $SDH index is continued, searching for a next matching hash. - * - * When a precise match is found, the security_id corresponding to the security - * descriptor in the $SDS attribute is read from the found $SDH index entry and - * is stored in the $STANDARD_INFORMATION attribute of the file/directory to - * which the security descriptor is being applied. The $STANDARD_INFORMATION - * attribute is present in all base mft records (i.e. in all files and - * directories). - * - * If a match is not found, the security descriptor is assigned a new unique - * security_id and is added to the $SDS data attribute. Then, entries - * referencing the this security descriptor in the $SDS data attribute are - * added to the $SDH and $SII indexes. - * - * Note: Entries are never deleted from FILE_Secure, even if nothing - * references an entry any more. - */ - -/** - * struct SECURITY_DESCRIPTOR_HEADER - - * - * This header precedes each security descriptor in the $SDS data stream. - * This is also the index entry data part of both the $SII and $SDH indexes. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 hash; /* Hash of the security descriptor. */ - le32 security_id; /* The security_id assigned to the descriptor. */ - le64 offset; /* Byte offset of this entry in the $SDS stream. */ - le32 length; /* Size in bytes of this entry in $SDS stream. */ -} __attribute__((__packed__)) SECURITY_DESCRIPTOR_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SDH_INDEX_DATA - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 hash; /* Hash of the security descriptor. */ - le32 security_id; /* The security_id assigned to the descriptor. */ - le64 offset; /* Byte offset of this entry in the $SDS stream. */ - le32 length; /* Size in bytes of this entry in $SDS stream. */ - le32 reserved_II; /* Padding - always unicode "II" or zero. This field - isn't counted in INDEX_ENTRY's data_length. */ -} __attribute__((__packed__)) SDH_INDEX_DATA; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SII_INDEX_DATA - - */ -typedef SECURITY_DESCRIPTOR_HEADER SII_INDEX_DATA; - -/** - * struct SDS_ENTRY - - * - * The $SDS data stream contains the security descriptors, aligned on 16-byte - * boundaries, sorted by security_id in a B+ tree. Security descriptors cannot - * cross 256kib boundaries (this restriction is imposed by the Windows cache - * manager). Each security descriptor is contained in a SDS_ENTRY structure. - * Also, each security descriptor is stored twice in the $SDS stream with a - * fixed offset of 0x40000 bytes (256kib, the Windows cache manager's max size) - * between them; i.e. if a SDS_ENTRY specifies an offset of 0x51d0, then the - * the first copy of the security descriptor will be at offset 0x51d0 in the - * $SDS data stream and the second copy will be at offset 0x451d0. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 SECURITY_DESCRIPTOR_HEADER; -- Unfolded here as gcc doesn't like - unnamed structs. */ - le32 hash; /* Hash of the security descriptor. */ - le32 security_id; /* The security_id assigned to the descriptor. */ - le64 offset; /* Byte offset of this entry in the $SDS stream. */ - le32 length; /* Size in bytes of this entry in $SDS stream. */ -/* 20*/ SECURITY_DESCRIPTOR_RELATIVE sid; /* The self-relative security - descriptor. */ -} __attribute__((__packed__)) SDS_ENTRY; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SII_INDEX_KEY - The index entry key used in the $SII index. - * - * The collation type is COLLATION_NTOFS_ULONG. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 security_id; /* The security_id assigned to the descriptor. */ -} __attribute__((__packed__)) SII_INDEX_KEY; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct SDH_INDEX_KEY - The index entry key used in the $SDH index. - * - * The keys are sorted first by hash and then by security_id. - * The collation rule is COLLATION_NTOFS_SECURITY_HASH. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 hash; /* Hash of the security descriptor. */ - le32 security_id; /* The security_id assigned to the descriptor. */ -} __attribute__((__packed__)) SDH_INDEX_KEY; -#ifdef __sun -#pragma pack() -#endif - -#ifndef __sun -/** - * struct VOLUME_NAME - Attribute: Volume name (0x60). - * - * NOTE: Always resident. - * NOTE: Present only in FILE_Volume. - */ -typedef struct { - ntfschar name[]; /* The name of the volume in Unicode. */ -} __attribute__((__packed__)) VOLUME_NAME; -#endif - -/** - * enum VOLUME_FLAGS - Possible flags for the volume (16-bit). - * - * WARNING: Setting VOLUME_MOUNTED_ON_NT4 on a Volume causes Windows Vista to - * fail to boot (it hangs on a black screen). - */ -#ifdef __sun -typedef uint16_t VOLUME_FLAGS; -#define VOLUME_IS_DIRTY (const_cpu_to_le16(0x0001)) -#define VOLUME_RESIZE_LOG_FILE (const_cpu_to_le16(0x0002)) -#define VOLUME_UPGRADE_ON_MOUNT (const_cpu_to_le16(0x0004)) -#define VOLUME_MOUNTED_ON_NT4 (const_cpu_to_le16(0x0008)) -#define VOLUME_DELETE_USN_UNDERWAY (const_cpu_to_le16(0x0010)) -#define VOLUME_REPAIR_OBJECT_ID (const_cpu_to_le16(0x0020)) -#define VOLUME_CHKDSK_UNDERWAY (const_cpu_to_le16(0x4000)) -#define VOLUME_MODIFIED_BY_CHKDSK (const_cpu_to_le16(0x8000)) -#define VOLUME_FLAGS_MASK (const_cpu_to_le16(0xc03f)) -#else /* not __sun */ -typedef enum { - VOLUME_IS_DIRTY = const_cpu_to_le16(0x0001), - VOLUME_RESIZE_LOG_FILE = const_cpu_to_le16(0x0002), - VOLUME_UPGRADE_ON_MOUNT = const_cpu_to_le16(0x0004), - VOLUME_MOUNTED_ON_NT4 = const_cpu_to_le16(0x0008), - VOLUME_DELETE_USN_UNDERWAY = const_cpu_to_le16(0x0010), - VOLUME_REPAIR_OBJECT_ID = const_cpu_to_le16(0x0020), - VOLUME_CHKDSK_UNDERWAY = const_cpu_to_le16(0x4000), - VOLUME_MODIFIED_BY_CHKDSK = const_cpu_to_le16(0x8000), - VOLUME_FLAGS_MASK = const_cpu_to_le16(0xc03f), -} __attribute__((__packed__)) VOLUME_FLAGS; -#endif /* __sun */ - -/** - * struct VOLUME_INFORMATION - Attribute: Volume information (0x70). - * - * NOTE: Always resident. - * NOTE: Present only in FILE_Volume. - * NOTE: Windows 2000 uses NTFS 3.0 while Windows NT4 service pack 6a uses - * NTFS 1.2. I haven't personally seen other values yet. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le64 reserved; /* Not used (yet?). */ - u8 major_ver; /* Major version of the ntfs format. */ - u8 minor_ver; /* Minor version of the ntfs format. */ - VOLUME_FLAGS flags; /* Bit array of VOLUME_* flags. */ -} __attribute__((__packed__)) VOLUME_INFORMATION; -#ifdef __sun -#pragma pack() -#endif - -#ifndef __sun -/** - * struct DATA_ATTR - Attribute: Data attribute (0x80). - * - * NOTE: Can be resident or non-resident. - * - * Data contents of a file (i.e. the unnamed stream) or of a named stream. - */ -typedef struct { - u8 data[]; /* The file's data contents. */ -} __attribute__((__packed__)) DATA_ATTR; -#endif - -/** - * enum INDEX_HEADER_FLAGS - Index header flags (8-bit). - */ -#ifdef __sun -typedef uint8_t INDEX_HEADER_FLAGS; -#define SMALL_INDEX (0) -#define LARGE_INDEX (1) -#define LEAF_NODE (0) -#define INDEX_NODE (1) -#define NODE_MASK (1) -#else /* not __sun */ -typedef enum { - /* When index header is in an index root attribute: */ - SMALL_INDEX = 0, /* The index is small enough to fit inside the - index root attribute and there is no index - allocation attribute present. */ - LARGE_INDEX = 1, /* The index is too large to fit in the index - root attribute and/or an index allocation - attribute is present. */ - /* - * When index header is in an index block, i.e. is part of index - * allocation attribute: - */ - LEAF_NODE = 0, /* This is a leaf node, i.e. there are no more - nodes branching off it. */ - INDEX_NODE = 1, /* This node indexes other nodes, i.e. is not a - leaf node. */ - NODE_MASK = 1, /* Mask for accessing the *_NODE bits. */ -} __attribute__((__packed__)) INDEX_HEADER_FLAGS; -#endif /* __sun */ - -/** - * struct INDEX_HEADER - - * - * This is the header for indexes, describing the INDEX_ENTRY records, which - * follow the INDEX_HEADER. Together the index header and the index entries - * make up a complete index. - * - * IMPORTANT NOTE: The offset, length and size structure members are counted - * relative to the start of the index header structure and not relative to the - * start of the index root or index allocation structures themselves. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 entries_offset; /* Byte offset to first INDEX_ENTRY - aligned to 8-byte boundary. */ - le32 index_length; /* Data size of the index in bytes, - i.e. bytes used from allocated - size, aligned to 8-byte boundary. */ - le32 allocated_size; /* Byte size of this index (block), - multiple of 8 bytes. */ - /* NOTE: For the index root attribute, the above two numbers are always - equal, as the attribute is resident and it is resized as needed. In - the case of the index allocation attribute the attribute is not - resident and hence the allocated_size is a fixed value and must - equal the index_block_size specified by the INDEX_ROOT attribute - corresponding to the INDEX_ALLOCATION attribute this INDEX_BLOCK - belongs to. */ - INDEX_HEADER_FLAGS flags; /* Bit field of INDEX_HEADER_FLAGS. */ - u8 reserved[3]; /* Reserved/align to 8-byte boundary. */ -} __attribute__((__packed__)) INDEX_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct INDEX_ROOT - Attribute: Index root (0x90). - * - * NOTE: Always resident. - * - * This is followed by a sequence of index entries (INDEX_ENTRY structures) - * as described by the index header. - * - * When a directory is small enough to fit inside the index root then this - * is the only attribute describing the directory. When the directory is too - * large to fit in the index root, on the other hand, two additional attributes - * are present: an index allocation attribute, containing sub-nodes of the B+ - * directory tree (see below), and a bitmap attribute, describing which virtual - * cluster numbers (VCNs) in the index allocation attribute are in use by an - * index block. - * - * NOTE: The root directory (FILE_root) contains an entry for itself. Other - * directories do not contain entries for themselves, though. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - ATTR_TYPES type; /* Type of the indexed attribute. Is - $FILE_NAME for directories, zero - for view indexes. No other values - allowed. */ - COLLATION_RULES collation_rule; /* Collation rule used to sort the - index entries. If type is $FILE_NAME, - this must be COLLATION_FILE_NAME. */ - le32 index_block_size; /* Size of each index block in bytes (in - the index allocation attribute). */ - u8 clusters_per_index_block; /* Cluster size of each index block (in - the index allocation attribute), when - an index block is >= than a cluster, - otherwise sectors per index block. */ - u8 reserved[3]; /* Reserved/align to 8-byte boundary. */ - INDEX_HEADER index; /* Index header describing the - following index entries. */ -} __attribute__((__packed__)) INDEX_ROOT; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct INDEX_BLOCK - Attribute: Index allocation (0xa0). - * - * NOTE: Always non-resident (doesn't make sense to be resident anyway!). - * - * This is an array of index blocks. Each index block starts with an - * INDEX_BLOCK structure containing an index header, followed by a sequence of - * index entries (INDEX_ENTRY structures), as described by the INDEX_HEADER. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ - NTFS_RECORD_TYPES magic;/* Magic is "INDX". */ - le16 usa_ofs; /* See NTFS_RECORD definition. */ - le16 usa_count; /* See NTFS_RECORD definition. */ - -/* 8*/ leLSN lsn; /* $LogFile sequence number of the last - modification of this index block. */ -/* 16*/ leVCN index_block_vcn; /* Virtual cluster number of the index block. */ -/* 24*/ INDEX_HEADER index; /* Describes the following index entries. */ -/* sizeof()= 40 (0x28) bytes */ -/* - * When creating the index block, we place the update sequence array at this - * offset, i.e. before we start with the index entries. This also makes sense, - * otherwise we could run into problems with the update sequence array - * containing in itself the last two bytes of a sector which would mean that - * multi sector transfer protection wouldn't work. As you can't protect data - * by overwriting it since you then can't get it back... - * When reading use the data from the ntfs record header. - */ -} __attribute__((__packed__)) INDEX_BLOCK; -#ifdef __sun -#pragma pack() -#endif - -typedef INDEX_BLOCK INDEX_ALLOCATION; - -/** - * struct REPARSE_INDEX_KEY - - * - * The system file FILE_Extend/$Reparse contains an index named $R listing - * all reparse points on the volume. The index entry keys are as defined - * below. Note, that there is no index data associated with the index entries. - * - * The index entries are sorted by the index key file_id. The collation rule is - * COLLATION_NTOFS_ULONGS. FIXME: Verify whether the reparse_tag is not the - * primary key / is not a key at all. (AIA) - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 reparse_tag; /* Reparse point type (inc. flags). */ - leMFT_REF file_id; /* Mft record of the file containing the - reparse point attribute. */ -} __attribute__((__packed__)) REPARSE_INDEX_KEY; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum QUOTA_FLAGS - Quota flags (32-bit). - */ -typedef enum { - /* The user quota flags. Names explain meaning. */ - QUOTA_FLAG_DEFAULT_LIMITS = const_cpu_to_le32(0x00000001), - QUOTA_FLAG_LIMIT_REACHED = const_cpu_to_le32(0x00000002), - QUOTA_FLAG_ID_DELETED = const_cpu_to_le32(0x00000004), - - QUOTA_FLAG_USER_MASK = const_cpu_to_le32(0x00000007), - /* Bit mask for user quota flags. */ - - /* These flags are only present in the quota defaults index entry, - i.e. in the entry where owner_id = QUOTA_DEFAULTS_ID. */ - QUOTA_FLAG_TRACKING_ENABLED = const_cpu_to_le32(0x00000010), - QUOTA_FLAG_ENFORCEMENT_ENABLED = const_cpu_to_le32(0x00000020), - QUOTA_FLAG_TRACKING_REQUESTED = const_cpu_to_le32(0x00000040), - QUOTA_FLAG_LOG_THRESHOLD = const_cpu_to_le32(0x00000080), - QUOTA_FLAG_LOG_LIMIT = const_cpu_to_le32(0x00000100), - QUOTA_FLAG_OUT_OF_DATE = const_cpu_to_le32(0x00000200), - QUOTA_FLAG_CORRUPT = const_cpu_to_le32(0x00000400), - QUOTA_FLAG_PENDING_DELETES = const_cpu_to_le32(0x00000800), -} QUOTA_FLAGS; - -/** - * struct QUOTA_CONTROL_ENTRY - - * - * The system file FILE_Extend/$Quota contains two indexes $O and $Q. Quotas - * are on a per volume and per user basis. - * - * The $Q index contains one entry for each existing user_id on the volume. The - * index key is the user_id of the user/group owning this quota control entry, - * i.e. the key is the owner_id. The user_id of the owner of a file, i.e. the - * owner_id, is found in the standard information attribute. The collation rule - * for $Q is COLLATION_NTOFS_ULONG. - * - * The $O index contains one entry for each user/group who has been assigned - * a quota on that volume. The index key holds the SID of the user_id the - * entry belongs to, i.e. the owner_id. The collation rule for $O is - * COLLATION_NTOFS_SID. - * - * The $O index entry data is the user_id of the user corresponding to the SID. - * This user_id is used as an index into $Q to find the quota control entry - * associated with the SID. - * - * The $Q index entry data is the quota control entry and is defined below. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 version; /* Currently equals 2. */ - QUOTA_FLAGS flags; /* Flags describing this quota entry. */ - le64 bytes_used; /* How many bytes of the quota are in use. */ - sle64 change_time; /* Last time this quota entry was changed. */ - sle64 threshold; /* Soft quota (-1 if not limited). */ - sle64 limit; /* Hard quota (-1 if not limited). */ - sle64 exceeded_time; /* How long the soft quota has been exceeded. */ -/* The below field is NOT present for the quota defaults entry. */ - SID sid; /* The SID of the user/object associated with - this quota entry. If this field is missing - then the INDEX_ENTRY is padded with zeros - to multiply of 8 which are not counted in - the data_length field. If the SID is present - then this structure is padded with zeros to - multiply of 8 and the padding is counted in - the INDEX_ENTRY's data_length. */ -} __attribute__((__packed__)) QUOTA_CONTROL_ENTRY; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct QUOTA_O_INDEX_DATA - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 owner_id; - le32 unknown; /* Always 32. Seems to be padding and it's not - counted in the INDEX_ENTRY's data_length. - This field shouldn't be really here. */ -} __attribute__((__packed__)) QUOTA_O_INDEX_DATA; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum PREDEFINED_OWNER_IDS - Predefined owner_id values (32-bit). - */ -typedef enum { - QUOTA_INVALID_ID = const_cpu_to_le32(0x00000000), - QUOTA_DEFAULTS_ID = const_cpu_to_le32(0x00000001), - QUOTA_FIRST_USER_ID = const_cpu_to_le32(0x00000100), -} PREDEFINED_OWNER_IDS; - -/** - * enum INDEX_ENTRY_FLAGS - Index entry flags (16-bit). - */ -#ifdef __sun -typedef uint16_t INDEX_ENTRY_FLAGS; -#define INDEX_ENTRY_NODE (const_cpu_to_le16(1)) -#define INDEX_ENTRY_END (const_cpu_to_le16(2)) -#else /* not __sun */ -typedef enum { - INDEX_ENTRY_NODE = const_cpu_to_le16(1), /* This entry contains a - sub-node, i.e. a reference to an index - block in form of a virtual cluster - number (see below). */ - INDEX_ENTRY_END = const_cpu_to_le16(2), /* This signifies the last - entry in an index block. The index - entry does not represent a file but it - can point to a sub-node. */ - INDEX_ENTRY_SPACE_FILLER = const_cpu_to_le16(0xffff), - /* Just to force 16-bit width. */ -} __attribute__((__packed__)) INDEX_ENTRY_FLAGS; -#endif /* __sun */ - -/** - * struct INDEX_ENTRY_HEADER - This the index entry header (see below). - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0*/ union { /* Only valid when INDEX_ENTRY_END is not set. */ - leMFT_REF indexed_file; /* The mft reference of the file - described by this index - entry. Used for directory - indexes. */ - struct { /* Used for views/indexes to find the entry's data. */ - le16 data_offset; /* Data byte offset from this - INDEX_ENTRY. Follows the - index key. */ - le16 data_length; /* Data length in bytes. */ - le32 reservedV; /* Reserved (zero). */ - } __attribute__((__packed__)) s; - } __attribute__((__packed__)) u; -/* 8*/ le16 length; /* Byte size of this index entry, multiple of - 8-bytes. */ -/* 10*/ le16 key_length; /* Byte size of the key value, which is in the - index entry. It follows field reserved. Not - multiple of 8-bytes. */ -/* 12*/ INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */ -/* 14*/ le16 reserved; /* Reserved/align to 8-byte boundary. */ -/* sizeof() = 16 bytes */ -} __attribute__((__packed__)) INDEX_ENTRY_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct INDEX_ENTRY - This is an index entry. - * - * A sequence of such entries follows each INDEX_HEADER structure. Together - * they make up a complete index. The index follows either an index root - * attribute or an index allocation attribute. - * - * NOTE: Before NTFS 3.0 only filename attributes were indexed. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 INDEX_ENTRY_HEADER; -- Unfolded here as gcc dislikes unnamed structs. */ - union { /* Only valid when INDEX_ENTRY_END is not set. */ - leMFT_REF indexed_file; /* The mft reference of the file - described by this index - entry. Used for directory - indexes. */ - struct { /* Used for views/indexes to find the entry's data. */ - le16 data_offset; /* Data byte offset from this - INDEX_ENTRY. Follows the - index key. */ - le16 data_length; /* Data length in bytes. */ - le32 reservedV; /* Reserved (zero). */ - } __attribute__((__packed__)) s; - } __attribute__((__packed__)) u; - le16 length; /* Byte size of this index entry, multiple of - 8-bytes. */ - le16 key_length; /* Byte size of the key value, which is in the - index entry. It follows field reserved. Not - multiple of 8-bytes. */ - INDEX_ENTRY_FLAGS flags; /* Bit field of INDEX_ENTRY_* flags. */ - le16 reserved; /* Reserved/align to 8-byte boundary. */ - -/* 16*/ union { /* The key of the indexed attribute. NOTE: Only present - if INDEX_ENTRY_END bit in flags is not set. NOTE: On - NTFS versions before 3.0 the only valid key is the - FILE_NAME_ATTR. On NTFS 3.0+ the following - additional index keys are defined: */ - FILE_NAME_ATTR file_name;/* $I30 index in directories. */ - SII_INDEX_KEY sii; /* $SII index in $Secure. */ - SDH_INDEX_KEY sdh; /* $SDH index in $Secure. */ - GUID object_id; /* $O index in FILE_Extend/$ObjId: The - object_id of the mft record found in - the data part of the index. */ - REPARSE_INDEX_KEY reparse; /* $R index in - FILE_Extend/$Reparse. */ - SID sid; /* $O index in FILE_Extend/$Quota: - SID of the owner of the user_id. */ - le32 owner_id; /* $Q index in FILE_Extend/$Quota: - user_id of the owner of the quota - control entry in the data part of - the index. */ - } __attribute__((__packed__)) key; - /* The (optional) index data is inserted here when creating. */ - /* VCN vcn; */ /* If INDEX_ENTRY_NODE bit in flags is set, the last - eight bytes of this index entry contain the virtual - cluster number of the index block that holds the - entries immediately preceding the current entry (the - vcn references the corresponding cluster in the data - of the non-resident index allocation attribute). If - the key_length is zero, then the vcn immediately - follows the INDEX_ENTRY_HEADER. Regardless of - key_length, the address of the 8-byte boundary - aligned vcn of INDEX_ENTRY{_HEADER} *ie is given by - (char*)ie + le16_to_cpu(ie->length) - sizeof(VCN), - where sizeof(VCN) can be hardcoded as 8 if wanted. */ -} __attribute__((__packed__)) INDEX_ENTRY; -#ifdef __sun -#pragma pack() -#endif - -#ifndef __sun -/** - * struct BITMAP_ATTR - Attribute: Bitmap (0xb0). - * - * Contains an array of bits (aka a bitfield). - * - * When used in conjunction with the index allocation attribute, each bit - * corresponds to one index block within the index allocation attribute. Thus - * the number of bits in the bitmap * index block size / cluster size is the - * number of clusters in the index allocation attribute. - */ -typedef struct { - u8 bitmap[]; /* Array of bits. */ -} __attribute__((__packed__)) BITMAP_ATTR; -#endif - -/** - * enum PREDEFINED_REPARSE_TAGS - - * - * The reparse point tag defines the type of the reparse point. It also - * includes several flags, which further describe the reparse point. - * - * The reparse point tag is an unsigned 32-bit value divided in three parts: - * - * 1. The least significant 16 bits (i.e. bits 0 to 15) specify the type of - * the reparse point. - * 2. The 13 bits after this (i.e. bits 16 to 28) are reserved for future use. - * 3. The most significant three bits are flags describing the reparse point. - * They are defined as follows: - * bit 29: Name surrogate bit. If set, the filename is an alias for - * another object in the system. - * bit 30: High-latency bit. If set, accessing the first byte of data will - * be slow. (E.g. the data is stored on a tape drive.) - * bit 31: Microsoft bit. If set, the tag is owned by Microsoft. User - * defined tags have to use zero here. - */ -typedef enum { - IO_REPARSE_TAG_IS_ALIAS = const_cpu_to_le32(0x20000000), - IO_REPARSE_TAG_IS_HIGH_LATENCY = const_cpu_to_le32(0x40000000), - IO_REPARSE_TAG_IS_MICROSOFT = const_cpu_to_le32(0x80000000), - - IO_REPARSE_TAG_RESERVED_ZERO = const_cpu_to_le32(0x00000000), - IO_REPARSE_TAG_RESERVED_ONE = const_cpu_to_le32(0x00000001), - IO_REPARSE_TAG_RESERVED_RANGE = const_cpu_to_le32(0x00000001), - - IO_REPARSE_TAG_NSS = const_cpu_to_le32(0x68000005), - IO_REPARSE_TAG_NSS_RECOVER = const_cpu_to_le32(0x68000006), - IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x68000007), - IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x68000008), - - IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0x88000003), - - IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xa8000004), - - IO_REPARSE_TAG_SYMBOLIC_LINK = const_cpu_to_le32(0xe8000000), - - IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xe000ffff), -} PREDEFINED_REPARSE_TAGS; - -/** - * struct REPARSE_POINT - Attribute: Reparse point (0xc0). - * - * NOTE: Can be resident or non-resident. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 reparse_tag; /* Reparse point type (inc. flags). */ - le16 reparse_data_length; /* Byte size of reparse data. */ - le16 reserved; /* Align to 8-byte boundary. */ - u8 reparse_data[]; /* Meaning depends on reparse_tag. */ -} __attribute__((__packed__)) REPARSE_POINT; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct EA_INFORMATION - Attribute: Extended attribute information (0xd0). - * - * NOTE: Always resident. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le16 ea_length; /* Byte size of the packed extended - attributes. */ - le16 need_ea_count; /* The number of extended attributes which have - the NEED_EA bit set. */ - le32 ea_query_length; /* Byte size of the buffer required to query - the extended attributes when calling - ZwQueryEaFile() in Windows NT/2k. I.e. the - byte size of the unpacked extended - attributes. */ -} __attribute__((__packed__)) EA_INFORMATION; -#ifdef __sun -#pragma pack() -#endif - -#ifdef __sun -typedef uint8_t EA_FLAGS; -#define NEED_EA (0x80) -#else /* not __sun */ -/** - * enum EA_FLAGS - Extended attribute flags (8-bit). - */ -typedef enum { - NEED_EA = 0x80, /* Indicate that the file to which the EA - belongs cannot be interpreted without - understanding the associated extended - attributes. */ -} __attribute__((__packed__)) EA_FLAGS; -#endif /* __sun */ - -/** - * struct EA_ATTR - Attribute: Extended attribute (EA) (0xe0). - * - * Like the attribute list and the index buffer list, the EA attribute value is - * a sequence of EA_ATTR variable length records. - * - * FIXME: It appears weird that the EA name is not Unicode. Is it true? - * FIXME: It seems that name is always uppercased. Is it true? - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 next_entry_offset; /* Offset to the next EA_ATTR. */ - EA_FLAGS flags; /* Flags describing the EA. */ - u8 name_length; /* Length of the name of the extended - attribute in bytes. */ - le16 value_length; /* Byte size of the EA's value. */ - u8 name[]; /* Name of the EA. */ -#ifndef __sun - u8 value[]; /* The value of the EA. Immediately - follows the name. */ -#endif -} __attribute__((__packed__)) EA_ATTR; -#ifdef __sun -#pragma pack() -#endif - -#ifndef __sun -/** - * struct PROPERTY_SET - Attribute: Property set (0xf0). - * - * Intended to support Native Structure Storage (NSS) - a feature removed from - * NTFS 3.0 during beta testing. - */ -typedef struct { - /* Irrelevant as feature unused. */ -} __attribute__((__packed__)) PROPERTY_SET; -#endif - -#ifndef __sun -/** - * struct LOGGED_UTILITY_STREAM - Attribute: Logged utility stream (0x100). - * - * NOTE: Can be resident or non-resident. - * - * Operations on this attribute are logged to the journal ($LogFile) like - * normal metadata changes. - * - * Used by the Encrypting File System (EFS). All encrypted files have this - * attribute with the name $EFS. See below for the relevant structures. - */ -typedef struct { - /* Can be anything the creator chooses. */ -} __attribute__((__packed__)) LOGGED_UTILITY_STREAM; -#endif - -/* - * $EFS Data Structure: - * - * The following information is about the data structures that are contained - * inside a logged utility stream (0x100) with a name of "$EFS". - * - * The stream starts with an instance of EFS_ATTR_HEADER. - * - * Next, at offsets offset_to_ddf_array and offset_to_drf_array (unless any of - * them is 0) there is a EFS_DF_ARRAY_HEADER immediately followed by a sequence - * of multiple data decryption/recovery fields. - * - * Each data decryption/recovery field starts with a EFS_DF_HEADER and the next - * one (if it exists) can be found by adding EFS_DF_HEADER->df_length bytes to - * the offset of the beginning of the current EFS_DF_HEADER. - * - * The data decryption/recovery field contains an EFS_DF_CERTIFICATE_HEADER, a - * SID, an optional GUID, an optional container name, a non-optional user name, - * and the encrypted FEK. - * - * Note all the below are best guesses so may have mistakes/inaccuracies. - * Corrections/clarifications/additions are always welcome! - * - * Ntfs.sys takes an EFS value length of <= 0x54 or > 0x40000 to BSOD, i.e. it - * is invalid. - */ - -/** - * struct EFS_ATTR_HEADER - "$EFS" header. - * - * The header of the Logged utility stream (0x100) attribute named "$EFS". - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0*/ le32 length; /* Length of EFS attribute in bytes. */ - le32 state; /* Always 0? */ - le32 version; /* Efs version. Always 2? */ - le32 crypto_api_version; /* Always 0? */ -/* 16*/ u8 unknown4[16]; /* MD5 hash of decrypted FEK? This field is - created with a call to UuidCreate() so is - unlikely to be an MD5 hash and is more - likely to be GUID of this encrytped file - or something like that. */ -/* 32*/ u8 unknown5[16]; /* MD5 hash of DDFs? */ -/* 48*/ u8 unknown6[16]; /* MD5 hash of DRFs? */ -/* 64*/ le32 offset_to_ddf_array;/* Offset in bytes to the array of data - decryption fields (DDF), see below. Zero if - no DDFs are present. */ - le32 offset_to_drf_array;/* Offset in bytes to the array of data - recovery fields (DRF), see below. Zero if - no DRFs are present. */ - le32 reserved; /* Reserved. */ -} __attribute__((__packed__)) EFS_ATTR_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct EFS_DF_ARRAY_HEADER - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - le32 df_count; /* Number of data decryption/recovery fields in - the array. */ -} __attribute__((__packed__)) EFS_DF_ARRAY_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct EFS_DF_HEADER - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0*/ le32 df_length; /* Length of this data decryption/recovery - field in bytes. */ - le32 cred_header_offset;/* Offset in bytes to the credential header. */ - le32 fek_size; /* Size in bytes of the encrypted file - encryption key (FEK). */ - le32 fek_offset; /* Offset in bytes to the FEK from the start of - the data decryption/recovery field. */ -/* 16*/ le32 unknown1; /* always 0? Might be just padding. */ -} __attribute__((__packed__)) EFS_DF_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct EFS_DF_CREDENTIAL_HEADER - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0*/ le32 cred_length; /* Length of this credential in bytes. */ - le32 sid_offset; /* Offset in bytes to the user's sid from start - of this structure. Zero if no sid is - present. */ -/* 8*/ le32 type; /* Type of this credential: - 1 = CryptoAPI container. - 2 = Unexpected type. - 3 = Certificate thumbprint. - other = Unknown type. */ - union { - /* CryptoAPI container. */ - struct { -/* 12*/ le32 container_name_offset; /* Offset in bytes to - the name of the container from start of this - structure (may not be zero). */ -/* 16*/ le32 provider_name_offset; /* Offset in bytes to - the name of the provider from start of this - structure (may not be zero). */ - le32 public_key_blob_offset; /* Offset in bytes to - the public key blob from start of this - structure. */ -/* 24*/ le32 public_key_blob_size; /* Size in bytes of - public key blob. */ - } __attribute__((__packed__)) crypt; - /* Certificate thumbprint. */ - struct { -/* 12*/ le32 cert_thumbprint_header_size; /* Size in - bytes of the header of the certificate - thumbprint. */ -/* 16*/ le32 cert_thumbprint_header_offset; /* Offset in - bytes to the header of the certificate - thumbprint from start of this structure. */ - le32 unknown1; /* Always 0? Might be padding... */ - le32 unknown2; /* Always 0? Might be padding... */ - } __attribute__((__packed__)) cert; - } __attribute__((__packed__)) u; -} __attribute__((__packed__)) EFS_DF_CREDENTIAL_HEADER; -#ifdef __sun -#pragma pack() -#endif - -typedef EFS_DF_CREDENTIAL_HEADER EFS_DF_CRED_HEADER; - -/** - * struct EFS_DF_CERTIFICATE_THUMBPRINT_HEADER - - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0*/ le32 thumbprint_offset; /* Offset in bytes to the thumbprint. */ - le32 thumbprint_size; /* Size of thumbprint in bytes. */ -/* 8*/ le32 container_name_offset; /* Offset in bytes to the name of the - container from start of this - structure or 0 if no name present. */ - le32 provider_name_offset; /* Offset in bytes to the name of the - cryptographic provider from start of - this structure or 0 if no name - present. */ -/* 16*/ le32 user_name_offset; /* Offset in bytes to the user name - from start of this structure or 0 if - no user name present. (This is also - known as lpDisplayInformation.) */ -} __attribute__((__packed__)) EFS_DF_CERTIFICATE_THUMBPRINT_HEADER; -#ifdef __sun -#pragma pack() -#endif - -typedef EFS_DF_CERTIFICATE_THUMBPRINT_HEADER EFS_DF_CERT_THUMBPRINT_HEADER; - -#ifdef __sun -typedef uint64_t INTX_FILE_TYPES; -#define INTX_SYMBOLIC_LINK (const_cpu_to_le64(0x014B4E4C78746E49ULL)) -#define INTX_CHARACTER_DEVICE (const_cpu_to_le64(0x0052484378746E49ULL)) -#define INTX_BLOCK_DEVICE (const_cpu_to_le64(0x004B4C4278746E49ULL)) -#else /* not __sun */ -typedef enum { - INTX_SYMBOLIC_LINK = - const_cpu_to_le64(0x014B4E4C78746E49ULL), /* "IntxLNK\1" */ - INTX_CHARACTER_DEVICE = - const_cpu_to_le64(0x0052484378746E49ULL), /* "IntxCHR\0" */ - INTX_BLOCK_DEVICE = - const_cpu_to_le64(0x004B4C4278746E49ULL), /* "IntxBLK\0" */ -} INTX_FILE_TYPES; -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - INTX_FILE_TYPES magic; /* Intx file magic. */ - union { - /* For character and block devices. */ - struct { - le64 major; /* Major device number. */ - le64 minor; /* Minor device number. */ - char device_end; /* Marker for offsetof(). */ - } __attribute__((__packed__)) s; - /* For symbolic links. */ - ntfschar target[1]; - } __attribute__((__packed__)) u; -} __attribute__((__packed__)) INTX_FILE; -#ifdef __sun -#pragma pack() -#endif - -#endif /* defined _NTFS_LAYOUT_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h b/usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h deleted file mode 100644 index 07ab020d2d..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * lcnalloc.h - Exports for cluster (de)allocation. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2002 Anton Altaparmakov - * Copyright (c) 2004 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_LCNALLOC_H -#define _NTFS_LCNALLOC_H - -#include "types.h" -#include "runlist.h" -#include "volume.h" - -/** - * enum NTFS_CLUSTER_ALLOCATION_ZONES - - */ -typedef enum { - FIRST_ZONE = 0, /* For sanity checking. */ - MFT_ZONE = 0, /* Allocate from $MFT zone. */ - DATA_ZONE = 1, /* Allocate from $DATA zone. */ - LAST_ZONE = 1, /* For sanity checking. */ -} NTFS_CLUSTER_ALLOCATION_ZONES; - -extern runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, - LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone); - -extern int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl); - -extern int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, - s64 count); - -#endif /* defined _NTFS_LCNALLOC_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/list.h b/usr/src/lib/libntfs/common/include/ntfs/list.h deleted file mode 100644 index e3c774423d..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/list.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * list.h - Linked list implementation. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2002 Anton Altaparmakov and others - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_LIST_H -#define _NTFS_LIST_H - -/** - * struct list_head - Simple doubly linked list implementation. - * - * Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor - * modifications). - AIA - * - * 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 LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/** - * __list_add - Insert a new entry between two known consecutive entries. - * @new: - * @prev: - * @next: - * - * 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; -} - -/** - * list_add - add a new entry - * @new: 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. - */ -static __inline__ void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: 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. - */ -static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/** - * __list_del - - * @prev: - * @next: - * - * 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; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * - * Note: list_empty on entry does not return true after this, the entry is in - * an undefined state. - */ -static __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. - */ -static __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. - */ -static __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. - */ -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; - } -} - -/** - * 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)(&((type *)0)->member))) - -/** - * list_for_each - iterate over 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 a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#endif /* defined _NTFS_LIST_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/logfile.h b/usr/src/lib/libntfs/common/include/ntfs/logfile.h deleted file mode 100644 index 9c597ecb4d..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/logfile.h +++ /dev/null @@ -1,441 +0,0 @@ -/* - * logfile.h - Exports for $LogFile handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2005 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_LOGFILE_H -#define _NTFS_LOGFILE_H - -#include "types.h" -#include "endians.h" -#include "layout.h" - -/* - * Journal ($LogFile) organization: - * - * Two restart areas present in the first two pages (restart pages, one restart - * area in each page). When the volume is dismounted they should be identical, - * except for the update sequence array which usually has a different update - * sequence number. - * - * These are followed by log records organized in pages headed by a log record - * header going up to log file size. Not all pages contain log records when a - * volume is first formatted, but as the volume ages, all records will be used. - * When the log file fills up, the records at the beginning are purged (by - * modifying the oldest_lsn to a higher value presumably) and writing begins - * at the beginning of the file. Effectively, the log file is viewed as a - * circular entity. - * - * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept - * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We - * probably only want to support 1.1 as this seems to be the current version - * and we don't know how that differs from the older versions. The only - * exception is if the journal is clean as marked by the two restart pages - * then it doesn't matter whether we are on an earlier version. We can just - * reinitialize the logfile and start again with version 1.1. - */ - -/* Some $LogFile related constants. */ -#define MaxLogFileSize 0x100000000ULL -#define DefaultLogPageSize 4096 -#define MinLogRecordPages 48 - -/** - * struct RESTART_PAGE_HEADER - Log file restart page header. - * - * Begins the restart area. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ -/* 0*/ NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */ -/* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. - When creating, set this to be immediately - after this header structure (without any - alignment). */ -/* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */ - -/* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by - chkdsk. Only used when the magic is changed - to "CHKD". Otherwise this is zero. */ -/* 16*/ le32 system_page_size; /* Byte size of system pages when the log file - was created, has to be >= 512 and a power of - 2. Use this to calculate the required size - of the usa (usa_count) and add it to usa_ofs. - Then verify that the result is less than the - value of the restart_area_offset. */ -/* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >= - 512 and a power of 2. The default is 4096 - and is used when the system page size is - between 4096 and 8192. Otherwise this is - set to the system page size instead. */ -/* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to - the RESTART_AREA. Value has to be aligned - to 8-byte boundary. When creating, set this - to be after the usa. */ -/* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major - version is 1. */ -/* 28*/ sle16 major_ver; /* Log file major version. We only support - version 1.1. */ -/* sizeof() = 30 (0x1e) bytes */ -} __attribute__((__packed__)) RESTART_PAGE_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/* - * Constant for the log client indices meaning that there are no client records - * in this particular client array. Also inside the client records themselves, - * this means that there are no client records preceding or following this one. - */ -#define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff) -#define LOGFILE_NO_CLIENT_CPU 0xffff - -#ifdef __sun -#define RESTART_VOLUME_IS_CLEAN (const_cpu_to_le16(0x0002)) -#else /* not __sun */ -/* - * These are the so far known RESTART_AREA_* flags (16-bit) which contain - * information about the log file in which they are present. - */ -enum { - RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), - RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), - /* gcc: Force enum bit width to 16. */ -} __attribute__((__packed__)); -#endif /* __sun */ - -typedef le16 RESTART_AREA_FLAGS; - -/** - * struct RESTART_AREA - Log file restart area record. - * - * The offset of this record is found by adding the offset of the - * RESTART_PAGE_HEADER to the restart_area_offset value found in it. - * See notes at restart_area_offset above. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log - when the restart area was last written. - This happens often but what is the interval? - Is it just fixed time or is it every time a - check point is written or something else? - On create set to 0. */ -/* 8*/ le16 log_clients; /* Number of log client records in the array of - log client records which follows this - restart area. Must be 1. */ -/* 10*/ le16 client_free_list; /* The index of the first free log client record - in the array of log client records. - LOGFILE_NO_CLIENT means that there are no - free log client records in the array. - If != LOGFILE_NO_CLIENT, check that - log_clients > client_free_list. On Win2k - and presumably earlier, on a clean volume - this is != LOGFILE_NO_CLIENT, and it should - be 0, i.e. the first (and only) client - record is free and thus the logfile is - closed and hence clean. A dirty volume - would have left the logfile open and hence - this would be LOGFILE_NO_CLIENT. On WinXP - and presumably later, the logfile is always - open, even on clean shutdown so this should - always be LOGFILE_NO_CLIENT. */ -/* 12*/ le16 client_in_use_list;/* The index of the first in-use log client - record in the array of log client records. - LOGFILE_NO_CLIENT means that there are no - in-use log client records in the array. If - != LOGFILE_NO_CLIENT check that log_clients - > client_in_use_list. On Win2k and - presumably earlier, on a clean volume this - is LOGFILE_NO_CLIENT, i.e. there are no - client records in use and thus the logfile - is closed and hence clean. A dirty volume - would have left the logfile open and hence - this would be != LOGFILE_NO_CLIENT, and it - should be 0, i.e. the first (and only) - client record is in use. On WinXP and - presumably later, the logfile is always - open, even on clean shutdown so this should - always be 0. */ -/* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k - and presumably earlier this is always 0. On - WinXP and presumably later, if the logfile - was shutdown cleanly, the second bit, - RESTART_VOLUME_IS_CLEAN, is set. This bit - is cleared when the volume is mounted by - WinXP and set when the volume is dismounted, - thus if the logfile is dirty, this bit is - clear. Thus we don't need to check the - Windows version to determine if the logfile - is clean. Instead if the logfile is closed, - we know it must be clean. If it is open and - this bit is set, we also know it must be - clean. If on the other hand the logfile is - open and this bit is clear, we can be almost - certain that the logfile is dirty. */ -/* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence - number. This is calculated as 67 - the - number of bits required to store the logfile - size in bytes and this can be used in with - the specified file_size as a consistency - check. */ -/* 20*/ le16 restart_area_length;/* Length of the restart area including the - client array. Following checks required if - version matches. Otherwise, skip them. - restart_area_offset + restart_area_length - has to be <= system_page_size. Also, - restart_area_length has to be >= - client_array_offset + (log_clients * - sizeof(log client record)). */ -/* 22*/ le16 client_array_offset;/* Offset from the start of this record to - the first log client record if versions are - matched. When creating, set this to be - after this restart area structure, aligned - to 8-bytes boundary. If the versions do not - match, this is ignored and the offset is - assumed to be (sizeof(RESTART_AREA) + 7) & - ~7, i.e. rounded up to first 8-byte - boundary. Either way, client_array_offset - has to be aligned to an 8-byte boundary. - Also, restart_area_offset + - client_array_offset has to be <= 510. - Finally, client_array_offset + (log_clients - * sizeof(log client record)) has to be <= - system_page_size. On Win2k and presumably - earlier, this is 0x30, i.e. immediately - following this record. On WinXP and - presumably later, this is 0x40, i.e. there - are 16 extra bytes between this record and - the client array. This probably means that - the RESTART_AREA record is actually bigger - in WinXP and later. */ -/* 24*/ sle64 file_size; /* Usable byte size of the log file. If the - restart_area_offset + the offset of the - file_size are > 510 then corruption has - occurred. This is the very first check when - starting with the restart_area as if it - fails it means that some of the above values - will be corrupted by the multi sector - transfer protection. The file_size has to - be rounded down to be a multiple of the - log_page_size in the RESTART_PAGE_HEADER and - then it has to be at least big enough to - store the two restart pages and 48 (0x30) - log record pages. */ -/* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including - the log record header. On create set to - 0. */ -/* 36*/ le16 log_record_header_length;/* Byte size of the log record header. - If the version matches then check that the - value of log_record_header_length is a - multiple of 8, i.e. - (log_record_header_length + 7) & ~7 == - log_record_header_length. When creating set - it to sizeof(LOG_RECORD_HEADER), aligned to - 8 bytes. */ -/* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record - page. Must be a multiple of 8. On create - set it to immediately after the update - sequence array of the log record page. */ -/* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every - time the logfile is restarted which happens - at mount time when the logfile is opened. - When creating set to a random value. Win2k - sets it to the low 32 bits of the current - system time in NTFS format (see time.h). */ -/* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */ -/* sizeof() = 48 (0x30) bytes */ -} __attribute__((__packed__)) RESTART_AREA; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct LOG_CLIENT_RECORD - Log client record. - * - * The offset of this record is found by adding the offset of the - * RESTART_AREA to the client_array_offset value found in it. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/*Ofs*/ -/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create - set to 0. */ -/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart - the volume, i.e. the current position within - the log file. At present, if clean this - should = current_lsn in restart area but it - probably also = current_lsn when dirty most - of the time. At create set to 0. */ -/* 16*/ le16 prev_client; /* The offset to the previous log client record - in the array of log client records. - LOGFILE_NO_CLIENT means there is no previous - client record, i.e. this is the first one. - This is always LOGFILE_NO_CLIENT. */ -/* 18*/ le16 next_client; /* The offset to the next log client record in - the array of log client records. - LOGFILE_NO_CLIENT means there are no next - client records, i.e. this is the last one. - This is always LOGFILE_NO_CLIENT. */ -/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set - to zero every time the logfile is restarted - and it is incremented when the logfile is - closed at dismount time. Thus it is 0 when - dirty and 1 when clean. On WinXP and - presumably later, this is always 0. */ -/* 22*/ u8 reserved[6]; /* Reserved/alignment. */ -/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should - always be 8. */ -/* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should - always be "NTFS" with the remaining bytes - set to 0. */ -/* sizeof() = 160 (0xa0) bytes */ -} __attribute__((__packed__)) LOG_CLIENT_RECORD; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct RECORD_PAGE_HEADER - Log page record page header. - * - * Each log page begins with this header and is followed by several LOG_RECORD - * structures, starting at offset 0x40 (the size of this structure and the - * following update sequence array and then aligned to 8 byte boundary, but is - * this specified anywhere?). - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { -/* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ - NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */ - u16 usa_ofs; /* See NTFS_RECORD definition in layout.h. - When creating, set this to be immediately - after this header structure (without any - alignment). */ - u16 usa_count; /* See NTFS_RECORD definition in layout.h. */ - - union { - LSN last_lsn; - s64 file_offset; - } __attribute__((__packed__)) copy; - u32 flags; - u16 page_count; - u16 page_position; - union { - struct { - u16 next_record_offset; - u8 reserved[6]; - LSN last_end_lsn; - } __attribute__((__packed__)) packed; - } __attribute__((__packed__)) header; -} __attribute__((__packed__)) RECORD_PAGE_HEADER; -#ifdef __sun -#pragma pack() -#endif - -/** - * enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records. - * - * (Or is it log record pages?) - */ -#ifdef __sun -typedef const uint16_t LOG_RECORD_FLAGS; -#define LOG_RECORD_MULTI_PAGE (const_cpu_to_le16(0x0001)) -#else /* not __sun */ -typedef enum { - LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */ - LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff, - /* This has nothing to do with the log record. It is only so - gcc knows to make the flags 16-bit. */ -} __attribute__((__packed__)) LOG_RECORD_FLAGS; -#endif /* __sun */ - -/** - * struct LOG_CLIENT_ID - The log client id structure identifying a log client. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - u16 seq_number; - u16 client_index; -} __attribute__((__packed__)) LOG_CLIENT_ID; -#ifdef __sun -#pragma pack() -#endif - -/** - * struct LOG_RECORD - Log record header. - * - * Each log record seems to have a constant size of 0x70 bytes. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - LSN this_lsn; - LSN client_previous_lsn; - LSN client_undo_next_lsn; - u32 client_data_length; - LOG_CLIENT_ID client_id; - u32 record_type; - u32 transaction_id; - u16 flags; - u16 reserved_or_alignment[3]; -/* Now are at ofs 0x30 into struct. */ - u16 redo_operation; - u16 undo_operation; - u16 redo_offset; - u16 redo_length; - u16 undo_offset; - u16 undo_length; - u16 target_attribute; - u16 lcns_to_follow; /* Number of lcn_list entries - following this entry. */ -/* Now at ofs 0x40. */ - u16 record_offset; - u16 attribute_offset; - u32 alignment_or_reserved; - VCN target_vcn; -/* Now at ofs 0x50. */ - struct { /* Only present if lcns_to_follow - is not 0. */ - LCN lcn; - } __attribute__((__packed__)) lcn_list[]; -} __attribute__((__packed__)) LOG_RECORD; -#ifdef __sun -#pragma pack() -#endif - -extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp); -extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp); -extern int ntfs_empty_logfile(ntfs_attr *na); - -#endif /* defined _NTFS_LOGFILE_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/logging.h b/usr/src/lib/libntfs/common/include/ntfs/logging.h deleted file mode 100644 index 524643a149..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/logging.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * logging.h - Centralised logging. Part of the Linux-NTFS project. - * - * Copyright (c) 2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _LOGGING_H_ -#define _LOGGING_H_ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDARG_H -#include -#endif - -#include "types.h" - -/* Function prototype for the logging handlers */ -typedef int (ntfs_log_handler)(const char *function, const char *file, int line, - u32 level, void *data, const char *format, va_list args); - -/* Set the logging handler from one of the functions, below. */ -void ntfs_log_set_handler(ntfs_log_handler *handler); - -/* Logging handlers */ -ntfs_log_handler ntfs_log_handler_syslog __attribute__((format(printf, 6, 0))); -ntfs_log_handler ntfs_log_handler_fprintf __attribute__((format(printf, 6, 0))); -ntfs_log_handler ntfs_log_handler_null __attribute__((format(printf, 6, 0))); -ntfs_log_handler ntfs_log_handler_stdout __attribute__((format(printf, 6, 0))); -ntfs_log_handler ntfs_log_handler_outerr __attribute__((format(printf, 6, 0))); -ntfs_log_handler ntfs_log_handler_stderr __attribute__((format(printf, 6, 0))); - -/* Enable/disable certain log levels */ -u32 ntfs_log_set_levels(u32 levels); -u32 ntfs_log_clear_levels(u32 levels); -u32 ntfs_log_get_levels(void); - -/* Enable/disable certain log flags */ -u32 ntfs_log_set_flags(u32 flags); -u32 ntfs_log_clear_flags(u32 flags); -u32 ntfs_log_get_flags(void); - -/* Turn command-line options into logging flags */ -BOOL ntfs_log_parse_option(const char *option); - -int ntfs_log_redirect(const char *function, const char *file, int line, - u32 level, void *data, const char *format, ...) - __attribute__((format(printf, 6, 7))); - -/* Logging levels - Determine what gets logged */ -#define NTFS_LOG_LEVEL_DEBUG ((u32)1 << 0) /* x = 42 */ -#define NTFS_LOG_LEVEL_TRACE ((u32)1 << 1) /* Entering function x() */ -#define NTFS_LOG_LEVEL_QUIET ((u32)1 << 2) /* Quietable output */ -#define NTFS_LOG_LEVEL_INFO ((u32)1 << 3) /* Volume needs defragmenting */ -#define NTFS_LOG_LEVEL_VERBOSE ((u32)1 << 4) /* Forced to continue */ -#define NTFS_LOG_LEVEL_PROGRESS ((u32)1 << 5) /* 54% complete */ -#define NTFS_LOG_LEVEL_WARNING ((u32)1 << 6) /* You should backup before starting */ -#define NTFS_LOG_LEVEL_ERROR ((u32)1 << 7) /* Operation failed, no damage done */ -#define NTFS_LOG_LEVEL_PERROR ((u32)1 << 8) /* Message : standard error description */ -#define NTFS_LOG_LEVEL_CRITICAL ((u32)1 << 9) /* Operation failed,damage may have occurred */ - -/* Logging style flags - Manage the style of the output */ -#define NTFS_LOG_FLAG_PREFIX ((u32)1 << 0) /* Prefix messages with "ERROR: ", etc */ -#define NTFS_LOG_FLAG_FILENAME ((u32)1 << 1) /* Show the file origin of the message */ -#define NTFS_LOG_FLAG_LINE ((u32)1 << 2) /* Show the line number of the message */ -#define NTFS_LOG_FLAG_FUNCTION ((u32)1 << 3) /* Show the function name containing the message */ -#define NTFS_LOG_FLAG_ONLYNAME ((u32)1 << 4) /* Only display the filename, not the pathname */ -#define NTFS_LOG_FLAG_COLOUR ((u32)1 << 5) /* Colour highlight some messages */ - -/* Macros to simplify logging. One for each level defined above. - * Note, if DEBUG is not defined, then ntfs_log_debug/trace have no effect. - */ -#if defined(__GNUC__) - -#define ntfs_log_critical(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_CRITICAL,NULL,FORMAT,##ARGS) -#define ntfs_log_error(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_ERROR,NULL,FORMAT,##ARGS) -#define ntfs_log_info(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_INFO,NULL,FORMAT,##ARGS) -#define ntfs_log_perror(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_PERROR,NULL,FORMAT,##ARGS) -#define ntfs_log_progress(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_PROGRESS,NULL,FORMAT,##ARGS) -#define ntfs_log_quiet(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_QUIET,NULL,FORMAT,##ARGS) -#define ntfs_log_verbose(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_VERBOSE,NULL,FORMAT,##ARGS) -#define ntfs_log_warning(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_WARNING,NULL,FORMAT,##ARGS) - -#else /* not __GNUC__ */ - -#define PRINT(...) printf(__VA_ARGS__) - -#define ntfs_log_critical(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_CRITICAL,NULL,__VA_ARGS__) -#define ntfs_log_error(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_ERROR,NULL,__VA_ARGS__) -#define ntfs_log_info(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_INFO,NULL,__VA_ARGS__) -#define ntfs_log_perror(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_PERROR,NULL,__VA_ARGS__) -#define ntfs_log_progress(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_PROGRESS,NULL,__VA_ARGS__) -#define ntfs_log_quiet(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_QUIET,NULL,__VA_ARGS__) -#define ntfs_log_verbose(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_VERBOSE,NULL,__VA_ARGS__) -#define ntfs_log_warning(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_WARNING,NULL,__VA_ARGS__) - -#endif /* __GNUC__ */ - -/* - * By default debug and trace messages are compiled into the program, - * but not displayed. - */ -#if defined(__GNUC__) - -#ifndef DEBUG -#define ntfs_log_debug(FORMAT, ARGS...)do {} while (0) -#define ntfs_log_trace(FORMAT, ARGS...)do {} while (0) -#else /* !DEBUG */ -#define ntfs_log_debug(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_DEBUG,NULL,FORMAT,##ARGS) -#define ntfs_log_trace(FORMAT, ARGS...) ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__,NTFS_LOG_LEVEL_TRACE,NULL,FORMAT,##ARGS) -#endif /* DEBUG */ - -#else /* not __GNUC__ */ - -#ifndef DEBUG -#define ntfs_log_debug(...) do {} while (0) -#define ntfs_log_trace(...) do {} while (0) -#else /* !DEBUG */ -#define ntfs_log_debug(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_DEBUG,NULL,__VA_ARGS__) -#define ntfs_log_trace(...) ntfs_log_redirect("unknown",__FILE__,__LINE__,NTFS_LOG_LEVEL_TRACE,NULL,__VA_ARGS__) -#endif /* DEBUG */ - -#endif /* __GNUC__ */ - -#endif /* _LOGGING_H_ */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/mft.h b/usr/src/lib/libntfs/common/include/ntfs/mft.h deleted file mode 100644 index 180f61531d..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/mft.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * mft.h - Exports for MFT record handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2002 Anton Altaparmakov - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_MFT_H -#define _NTFS_MFT_H - -#include "volume.h" -#include "inode.h" -#include "layout.h" - -extern int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref, - const s64 count, MFT_RECORD *b); - -/** - * ntfs_mft_record_read - read a record from the mft - * @vol: volume to read from - * @mref: mft record number to read - * @b: output data buffer - * - * Read the mft record specified by @mref from volume @vol into buffer @b. - * Return 0 on success or -1 on error, with errno set to the error code. - * - * The read mft record is mst deprotected and is hence ready to use. The caller - * should check the record with is_baad_record() in case mst deprotection - * failed. - * - * NOTE: @b has to be at least of size vol->mft_record_size. - */ -static __inline__ int ntfs_mft_record_read(const ntfs_volume *vol, - const MFT_REF mref, MFT_RECORD *b) -{ - return ntfs_mft_records_read(vol, mref, 1, b); -} - -extern int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref, - MFT_RECORD **mrec, ATTR_RECORD **attr); - -extern int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref, - const s64 count, MFT_RECORD *b); - -/** - * ntfs_mft_record_write - write an mft record to disk - * @vol: volume to write to - * @mref: mft record number to write - * @b: data buffer containing the mft record to write - * - * Write the mft record specified by @mref from buffer @b to volume @vol. - * Return 0 on success or -1 on error, with errno set to the error code. - * - * Before the mft record is written, it is mst protected. After the write, it - * is deprotected again, thus resulting in an increase in the update sequence - * number inside the buffer @b. - * - * NOTE: @b has to be at least of size vol->mft_record_size. - */ -static __inline__ int ntfs_mft_record_write(const ntfs_volume *vol, - const MFT_REF mref, MFT_RECORD *b) -{ - return ntfs_mft_records_write(vol, mref, 1, b); -} - -/** - * ntfs_mft_record_get_data_size - return number of bytes used in mft record @b - * @m: mft record to get the data size of - * - * Takes the mft record @m and returns the number of bytes used in the record - * or 0 on error (i.e. @m is not a valid mft record). Zero is not a valid size - * for an mft record as it at least has to have the MFT_RECORD itself and a - * zero length attribute of type AT_END, thus making the minimum size 56 bytes. - * - * Aside: The size is independent of NTFS versions 1.x/3.x because the 8-byte - * alignment of the first attribute mask the difference in MFT_RECORD size - * between NTFS 1.x and 3.x. Also, you would expect every mft record to - * contain an update sequence array as well but that could in theory be - * non-existent (don't know if Windows' NTFS driver/chkdsk wouldn't view this - * as corruption in itself though). - */ -static __inline__ u32 ntfs_mft_record_get_data_size(const MFT_RECORD *m) -{ - if (!m || !ntfs_is_mft_record(m->magic)) - return 0; - /* Get the number of used bytes and return it. */ - return le32_to_cpu(m->bytes_in_use); -} - -extern int ntfs_mft_record_layout(const ntfs_volume *vol, const MFT_REF mref, - MFT_RECORD *mrec); - -extern int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref); - -extern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni); - -extern int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni); - -extern int ntfs_mft_usn_dec(MFT_RECORD *mrec); - -#endif /* defined _NTFS_MFT_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/mst.h b/usr/src/lib/libntfs/common/include/ntfs/mst.h deleted file mode 100644 index 0808b3c115..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/mst.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * mst.h - Exports for multi sector transfer fixup functions. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2000-2002 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_MST_H -#define _NTFS_MST_H - -#include "types.h" -#include "layout.h" - -extern int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size); -extern int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size); -extern void ntfs_mst_post_write_fixup(NTFS_RECORD *b); - -#endif /* defined _NTFS_MST_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/ntfstime.h b/usr/src/lib/libntfs/common/include/ntfs/ntfstime.h deleted file mode 100644 index 2fb85a5413..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/ntfstime.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * ntfstime.h - NTFS time related functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_NTFSTIME_H -#define _NTFS_NTFSTIME_H - -#ifdef HAVE_TIME_H -#include -#endif - -#include "types.h" - -#define NTFS_TIME_OFFSET ((s64)(369 * 365 + 89) * 24 * 3600 * 10000000) - -/** - * ntfs2utc - Convert an NTFS time to Unix time - * @ntfs_time: An NTFS time in 100ns units since 1601 - * - * NTFS stores times as the number of 100ns intervals since January 1st 1601 at - * 00:00 UTC. This system will not suffer from Y2K problems until ~57000AD. - * - * Return: n A Unix time (number of seconds since 1970) - */ -static __inline__ time_t ntfs2utc(sle64 ntfs_time) -{ - return (sle64_to_cpu(ntfs_time) - (NTFS_TIME_OFFSET)) / 10000000; -} - -/** - * utc2ntfs - Convert Linux time to NTFS time - * @utc_time: Linux time to convert to NTFS - * - * Convert the Linux time @utc_time to its corresponding NTFS time. - * - * Linux stores time in a long at present and measures it as the number of - * 1-second intervals since 1st January 1970, 00:00:00 UTC. - * - * NTFS uses Microsoft's standard time format which is stored in a s64 and is - * measured as the number of 100 nano-second intervals since 1st January 1601, - * 00:00:00 UTC. - * - * Return: n An NTFS time (100ns units since Jan 1601) - */ -static __inline__ sle64 utc2ntfs(time_t utc_time) -{ - /* Convert to 100ns intervals and then add the NTFS time offset. */ - return cpu_to_sle64((s64)utc_time * 10000000 + NTFS_TIME_OFFSET); -} - -#endif /* _NTFS_NTFSTIME_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/runlist.h b/usr/src/lib/libntfs/common/include/ntfs/runlist.h deleted file mode 100644 index f35202971f..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/runlist.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * runlist.h - Exports for runlist handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2002 Anton Altaparmakov - * Copyright (c) 2002 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_RUNLIST_H -#define _NTFS_RUNLIST_H - -#include "types.h" - -/* Forward declarations */ -typedef struct _runlist_element runlist_element; -typedef runlist_element runlist; - -#include "attrib.h" -#include "volume.h" - -/** - * struct _runlist_element - in memory vcn to lcn mapping array element. - * @vcn: starting vcn of the current array element - * @lcn: starting lcn of the current array element - * @length: length in clusters of the current array element - * - * The last vcn (in fact the last vcn + 1) is reached when length == 0. - * - * When lcn == -1 this means that the count vcns starting at vcn are not - * physically allocated (i.e. this is a hole / data is sparse). - */ -struct _runlist_element {/* In memory vcn to lcn mapping structure element. */ - VCN vcn; /* vcn = Starting virtual cluster number. */ - LCN lcn; /* lcn = Starting logical cluster number. */ - s64 length; /* Run length in clusters. */ -}; - -extern LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn); - -extern s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b); -extern s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b); - -extern int ntfs_rl_fill_zero(const ntfs_volume *vol, const runlist *rl, - s64 pos, const s64 count); - -extern runlist_element *ntfs_runlists_merge(runlist_element *drl, - runlist_element *srl); - -extern runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, - const ATTR_RECORD *attr, runlist_element *old_rl); - -extern int ntfs_get_nr_significant_bytes(const s64 n); - -extern int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, - const runlist_element *rl, const VCN start_vcn); - -extern int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, - const s64 n); - -extern int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, - const int dst_len, const runlist_element *rl, - const VCN start_vcn, VCN *const stop_vcn); - -extern int ntfs_rl_truncate(runlist **arl, const VCN start_vcn); - -extern int ntfs_rl_sparse(runlist *rl); -extern s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl); - -#ifdef NTFS_TEST -int test_rl_main(int argc, char *argv[]); -#endif - -#endif /* defined _NTFS_RUNLIST_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/security.h b/usr/src/lib/libntfs/common/include/ntfs/security.h deleted file mode 100644 index a61aabd754..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/security.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * security.h - Exports for handling security/ACLs in NTFS. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_SECURITY_H -#define _NTFS_SECURITY_H - -#include "types.h" -#include "layout.h" - -extern const GUID *const zero_guid; - -extern BOOL ntfs_guid_is_zero(const GUID *guid); -extern char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str); - -/** - * ntfs_sid_is_valid - determine if a SID is valid - * @sid: SID for which to determine if it is valid - * - * Determine if the SID pointed to by @sid is valid. - * - * Return TRUE if it is valid and FALSE otherwise. - */ -static __inline__ BOOL ntfs_sid_is_valid(const SID *sid) -{ - if (!sid || sid->revision != SID_REVISION || - sid->sub_authority_count > SID_MAX_SUB_AUTHORITIES) - return FALSE; - return TRUE; -} - -extern int ntfs_sid_to_mbs_size(const SID *sid); -extern char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, - size_t sid_str_size); -extern void ntfs_generate_guid(GUID *guid); - -#endif /* defined _NTFS_SECURITY_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/support.h b/usr/src/lib/libntfs/common/include/ntfs/support.h deleted file mode 100644 index 7c1eed632a..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/support.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * support.h - Various useful things. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2006 Szabolcs Szakacsits - * Copyright (c) 2006 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_SUPPORT_H -#define _NTFS_SUPPORT_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDDEF_H -#include -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#include "logging.h" - -/* - * Our mailing list. Use this define to prevent typos in email address. - */ -#define NTFS_DEV_LIST "linux-ntfs-dev@lists.sf.net" - -/* - * Generic macro to convert pointers to values for comparison purposes. - */ -#ifndef p2n -#define p2n(p) ((ptrdiff_t)((ptrdiff_t*)(p))) -#endif - -/* - * The classic min and max macros. - */ -#ifndef min -#define min(a,b) ((a) <= (b) ? (a) : (b)) -#endif - -#ifndef max -#define max(a,b) ((a) >= (b) ? (a) : (b)) -#endif - -/* - * Useful macro for determining the offset of a struct member. - */ -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -/* - * Round up and down @num to 2 in power of @order. - */ -#define ROUND_UP(num,order) (((num) + ((1 << (order)) - 1)) & \ - ~((1 << (order)) - 1)) -#define ROUND_DOWN(num,order) ((num) & ~((1 << (order)) - 1)) - -/* - * Simple bit operation macros. NOTE: These are NOT atomic. - */ -#define test_bit(bit, var) ((var) & (1 << (bit))) -#define set_bit(bit, var) (var) |= 1 << (bit) -#define clear_bit(bit, var) (var) &= ~(1 << (bit)) - -#ifdef __sun -#define test_and_set_bit(bit, var) _test_and_set_bit(bit, &var) -static __inline__ BOOL _test_and_set_bit(unsigned long bit, unsigned long *var) -{ - const BOOL old_state = test_bit(bit, *var); - set_bit(bit, *var); - return old_state; -} - -#define test_and_clear_bit(bit, var) _test_and_clear_bit(bit, &var) -static __inline__ BOOL _test_and_clear_bit(unsigned long bit, unsigned long *var) -{ - const BOOL old_state = test_bit(bit, *var); - clear_bit(bit, *var); - return old_state; -} -#else /* !__sun */ -#define test_and_set_bit(bit, var) \ -({ \ - const BOOL old_state = test_bit(bit, var); \ - set_bit(bit, var); \ - old_state; \ -}) - -#define test_and_clear_bit(bit, var) \ -({ \ - const BOOL old_state = test_bit(bit, var); \ - clear_bit(bit, var); \ - old_state; \ -}) -#endif /* __sun */ - -/* Memory allocation with logging. */ -extern void *ntfs_calloc(size_t size); -extern void *ntfs_malloc(size_t size); - -#endif /* defined _NTFS_SUPPORT_H */ diff --git a/usr/src/lib/libntfs/common/include/ntfs/types.h b/usr/src/lib/libntfs/common/include/ntfs/types.h deleted file mode 100644 index cd9a9a998d..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/types.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * types.h - Misc type definitions not related to on-disk structure. Part of - * the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2006 Szabolcs Szakacsits - * Copyright (c) 2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_TYPES_H -#define _NTFS_TYPES_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#if HAVE_STDINT_H || !HAVE_CONFIG_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif - -typedef uint8_t u8; /* Unsigned types of an exact size */ -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; - -typedef int8_t s8; /* Signed types of an exact size */ -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; - -#if defined(__CHECKER__) && !defined(NTFS_DO_NOT_CHECK_ENDIANS) - #undef __bitwise - #undef __force - #define __bitwise __attribute__((bitwise)) - #define __force __attribute__((force)) -#else - #undef __bitwise - #undef __force - #define __bitwise - #define __force -#endif - -typedef u16 __bitwise le16; -typedef u32 __bitwise le32; -typedef u64 __bitwise le64; - -/* - * Declare sle{16,32,64} to be unsigned because we do not want sign extension - * on BE architectures. - */ -typedef u16 __bitwise sle16; -typedef u32 __bitwise sle32; -typedef u64 __bitwise sle64; - -typedef u16 __bitwise be16; -typedef u32 __bitwise be32; -typedef u64 __bitwise be64; - -typedef le16 ntfschar; /* 2-byte Unicode character type. */ -#define UCHAR_T_SIZE_BITS 1 - -/* - * Clusters are signed 64-bit values on NTFS volumes. We define two types, LCN - * and VCN, to allow for type checking and better code readability. - */ -typedef s64 VCN; -typedef sle64 leVCN; -typedef s64 LCN; -typedef sle64 leLCN; - -/* - * The NTFS journal $LogFile uses log sequence numbers which are signed 64-bit - * values. We define our own type LSN, to allow for type checking and better - * code readability. - */ -typedef s64 LSN; -typedef sle64 leLSN; - -/* - * Cygwin has a collision between our BOOL and 's - * As long as this file will be included after we're fine. - */ -#ifndef _WINDEF_H -/** - * enum BOOL - These are just to make the code more readable... - */ -typedef enum { -#ifndef FALSE - FALSE = 0, -#endif -#ifndef NO - NO = 0, -#endif -#ifndef ZERO - ZERO = 0, -#endif -#ifndef TRUE - TRUE = 1, -#endif -#ifndef YES - YES = 1, -#endif -#ifndef ONE - ONE = 1, -#endif -} BOOL; -#endif /* defined _WINDEF_H */ - -/** - * enum IGNORE_CASE_BOOL - - */ -typedef enum { - CASE_SENSITIVE = 0, - IGNORE_CASE = 1, -} IGNORE_CASE_BOOL; - -#define STATUS_OK (0) -#define STATUS_ERROR (-1) -#define STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT (-2) -#define STATUS_KEEP_SEARCHING (-3) -#define STATUS_NOT_FOUND (-4) - -#endif /* defined _NTFS_TYPES_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/unistr.h b/usr/src/lib/libntfs/common/include/ntfs/unistr.h deleted file mode 100644 index 2c5fd5548c..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/unistr.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * unistr.h - Exports for Unicode string handling. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_UNISTR_H -#define _NTFS_UNISTR_H - -#include "types.h" -#include "layout.h" - -extern BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len, - const ntfschar *s2, size_t s2_len, const IGNORE_CASE_BOOL ic, - const ntfschar *upcase, const u32 upcase_size); - -extern int ntfs_names_collate(const ntfschar *name1, const u32 name1_len, - const ntfschar *name2, const u32 name2_len, - const int err_val, const IGNORE_CASE_BOOL ic, - const ntfschar *upcase, const u32 upcase_len); - -extern int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n); - -extern int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n, - const ntfschar *upcase, const u32 upcase_size); - -extern u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen); - -extern ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen); - -extern void ntfs_name_upcase(ntfschar *name, u32 name_len, - const ntfschar *upcase, const u32 upcase_len); - -extern void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr, - const ntfschar *upcase, const u32 upcase_len); - -extern int ntfs_file_values_compare(const FILE_NAME_ATTR *file_name_attr1, - const FILE_NAME_ATTR *file_name_attr2, - const int err_val, const IGNORE_CASE_BOOL ic, - const ntfschar *upcase, const u32 upcase_len); - -extern int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs, - int outs_len); -extern int ntfs_mbstoucs(const char *ins, ntfschar **outs, int outs_len); - -extern void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len); - -extern ntfschar *ntfs_str2ucs(const char *s, int *len); - -extern void ntfs_ucsfree(ntfschar *ucs); - -#endif /* defined _NTFS_UNISTR_H */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/version.h b/usr/src/lib/libntfs/common/include/ntfs/version.h deleted file mode 100644 index ec6dbdca32..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/version.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * version.h - Info about the NTFS library. Part of the Linux-NTFS project. - * - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_VERSION_H_ -#define _NTFS_VERSION_H_ - -extern const char *ntfs_libntfs_version(void); - -#endif /* _NTFS_VERSION_H_ */ - diff --git a/usr/src/lib/libntfs/common/include/ntfs/volume.h b/usr/src/lib/libntfs/common/include/ntfs/volume.h deleted file mode 100644 index 3183d69b13..0000000000 --- a/usr/src/lib/libntfs/common/include/ntfs/volume.h +++ /dev/null @@ -1,247 +0,0 @@ -/* - * volume.h - Exports for NTFS volume handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _NTFS_VOLUME_H -#define _NTFS_VOLUME_H - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_MNTENT_H -#include -#endif - -/* Forward declaration */ -typedef struct _ntfs_volume ntfs_volume; - -#include "list.h" -#include "types.h" -#include "support.h" -#include "device.h" -#include "inode.h" -#include "attrib.h" - -/** - * enum ntfs_mount_flags - - * - * Flags for the ntfs_mount() function. - */ -typedef enum { - NTFS_MNT_RDONLY = 1, - NTFS_MNT_FORENSIC = 2, - NTFS_MNT_CASE_SENSITIVE = 4, - NTFS_MNT_NOT_EXCLUSIVE = 8, - NTFS_MNT_FORCE = 16, - NTFS_MNT_INTERIX = 32, -} ntfs_mount_flags; - -/** - * enum ntfs_mounted_flags - - * - * Flags returned by the ntfs_check_if_mounted() function. - */ -typedef enum { - NTFS_MF_MOUNTED = 1, /* Device is mounted. */ - NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */ - NTFS_MF_READONLY = 4, /* Device is mounted read-only. */ -} ntfs_mounted_flags; - -extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags); - -/** - * enum ntfs_volume_state_bits - - * - * Defined bits for the state field in the ntfs_volume structure. - */ -typedef enum { - NV_ReadOnly, /* 1: Volume is read-only. */ - NV_CaseSensitive, /* 1: Volume is mounted case-sensitive. */ - NV_LogFileEmpty, /* 1: $logFile journal is empty. */ - NV_NoATime, /* 1: Do not update access time. */ - NV_WasDirty, /* 1: Volume was marked dirty before we mounted - it. */ - NV_ForensicMount, /* 1: Mount is forensic, i.e. no modifications - are to be done by mount/umount. */ - NV_Interix, /* 1: Make libntfs recognize Interix special - files. */ -} ntfs_volume_state_bits; - -#define test_nvol_flag(nv, flag) test_bit(NV_##flag, (nv)->state) -#define set_nvol_flag(nv, flag) set_bit(NV_##flag, (nv)->state) -#define clear_nvol_flag(nv, flag) clear_bit(NV_##flag, (nv)->state) - -#define NVolReadOnly(nv) test_nvol_flag(nv, ReadOnly) -#define NVolSetReadOnly(nv) set_nvol_flag(nv, ReadOnly) -#define NVolClearReadOnly(nv) clear_nvol_flag(nv, ReadOnly) - -#define NVolCaseSensitive(nv) test_nvol_flag(nv, CaseSensitive) -#define NVolSetCaseSensitive(nv) set_nvol_flag(nv, CaseSensitive) -#define NVolClearCaseSensitive(nv) clear_nvol_flag(nv, CaseSensitive) - -#define NVolLogFileEmpty(nv) test_nvol_flag(nv, LogFileEmpty) -#define NVolSetLogFileEmpty(nv) set_nvol_flag(nv, LogFileEmpty) -#define NVolClearLogFileEmpty(nv) clear_nvol_flag(nv, LogFileEmpty) - -#define NVolWasDirty(nv) test_nvol_flag(nv, WasDirty) -#define NVolSetWasDirty(nv) set_nvol_flag(nv, WasDirty) -#define NVolClearWasDirty(nv) clear_nvol_flag(nv, WasDirty) - -#define NVolForensicMount(nv) test_nvol_flag(nv, ForensicMount) -#define NVolSetForensicMount(nv) set_nvol_flag(nv, ForensicMount) -#define NVolClearForensicMount(nv) clear_nvol_flag(nv, ForensicMount) - -#define NVolInterix(nv) test_nvol_flag(nv, Interix) -#define NVolSetInterix(nv) set_nvol_flag(nv, Interix) -#define NVolClearInterix(nv) clear_nvol_flag(nv, Interix) - -/* - * NTFS version 1.1 and 1.2 are used by Windows NT4. - * NTFS version 2.x is used by Windows 2000 Beta - * NTFS version 3.0 is used by Windows 2000. - * NTFS version 3.1 is used by Windows XP, 2003 and Vista. - */ - -#define NTFS_V1_1(major, minor) ((major) == 1 && (minor) == 1) -#define NTFS_V1_2(major, minor) ((major) == 1 && (minor) == 2) -#define NTFS_V2_X(major, minor) ((major) == 2) -#define NTFS_V3_0(major, minor) ((major) == 3 && (minor) == 0) -#define NTFS_V3_1(major, minor) ((major) == 3 && (minor) == 1) - -#define NTFS_BUF_SIZE 8192 - -#define NTFS_INODE_CACHE_SIZE 512 /* WARNING: This should be power of 2. */ -#define NTFS_INODE_CACHE_SIZE_BITS (NTFS_INODE_CACHE_SIZE - 1) - -/** - * struct _ntfs_volume - structure describing an open volume in memory. - */ -struct _ntfs_volume { - union { - struct ntfs_device *dev; /* NTFS device associated with - the volume. */ - void *sb; /* For kernel porting compatibility. */ - } u; - char *vol_name; /* Name of the volume. */ - unsigned long state; /* NTFS specific flags describing this volume. - See ntfs_volume_state_bits above. */ - - ntfs_inode *vol_ni; /* ntfs_inode structure for FILE_Volume. */ - u8 major_ver; /* Ntfs major version of volume. */ - u8 minor_ver; /* Ntfs minor version of volume. */ - le16 flags; /* Bit array of VOLUME_* flags. */ - GUID guid; /* The volume guid if present (otherwise it is - a NULL guid). */ - - u16 sector_size; /* Byte size of a sector. */ - u8 sector_size_bits; /* Log(2) of the byte size of a sector. */ - u32 cluster_size; /* Byte size of a cluster. */ - u32 mft_record_size; /* Byte size of a mft record. */ - u32 indx_record_size; /* Byte size of a INDX record. */ - u8 cluster_size_bits; /* Log(2) of the byte size of a cluster. */ - u8 mft_record_size_bits;/* Log(2) of the byte size of a mft record. */ - u8 indx_record_size_bits;/* Log(2) of the byte size of a INDX record. */ - - /* Variables used by the cluster and mft allocators. */ - u8 mft_zone_multiplier; /* Initial mft zone multiplier. */ - s64 mft_data_pos; /* Mft record number at which to allocate the - next mft record. */ - LCN mft_zone_start; /* First cluster of the mft zone. */ - LCN mft_zone_end; /* First cluster beyond the mft zone. */ - LCN mft_zone_pos; /* Current position in the mft zone. */ - LCN data1_zone_pos; /* Current position in the first data zone. */ - LCN data2_zone_pos; /* Current position in the second data zone. */ - - s64 nr_clusters; /* Volume size in clusters, hence also the - number of bits in lcn_bitmap. */ - ntfs_inode *lcnbmp_ni; /* ntfs_inode structure for FILE_Bitmap. */ - ntfs_attr *lcnbmp_na; /* ntfs_attr structure for the data attribute - of FILE_Bitmap. Each bit represents a - cluster on the volume, bit 0 representing - lcn 0 and so on. A set bit means that the - cluster and vice versa. */ - - LCN mft_lcn; /* Logical cluster number of the data attribute - for FILE_MFT. */ - ntfs_inode *mft_ni; /* ntfs_inode structure for FILE_MFT. */ - ntfs_attr *mft_na; /* ntfs_attr structure for the data attribute - of FILE_MFT. */ - ntfs_attr *mftbmp_na; /* ntfs_attr structure for the bitmap attribute - of FILE_MFT. Each bit represents an mft - record in the $DATA attribute, bit 0 - representing mft record 0 and so on. A set - bit means that the mft record is in use and - vice versa. */ - - int mftmirr_size; /* Size of the FILE_MFTMirr in mft records. */ - LCN mftmirr_lcn; /* Logical cluster number of the data attribute - for FILE_MFTMirr. */ - ntfs_inode *mftmirr_ni; /* ntfs_inode structure for FILE_MFTMirr. */ - ntfs_attr *mftmirr_na; /* ntfs_attr structure for the data attribute - of FILE_MFTMirr. */ - - ntfschar *upcase; /* Upper case equivalents of all 65536 2-byte - Unicode characters. Obtained from - FILE_UpCase. */ - u32 upcase_len; /* Length in Unicode characters of the upcase - table. */ - - ATTR_DEF *attrdef; /* Attribute definitions. Obtained from - FILE_AttrDef. */ - s32 attrdef_len; /* Size of the attribute definition table in - bytes. */ - - long nr_free_clusters; /* This two are self explaining. */ - long nr_free_mft_records; - - struct list_head inode_cache[NTFS_INODE_CACHE_SIZE]; /* List of opened - inodes. */ -}; - -extern ntfs_volume *ntfs_volume_alloc(void); - -extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, - ntfs_mount_flags flags); - -extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, - ntfs_mount_flags flags); -extern int ntfs_device_umount(ntfs_volume *vol, const BOOL force); - -extern ntfs_volume *ntfs_mount(const char *name, ntfs_mount_flags flags); -extern int ntfs_umount(ntfs_volume *vol, const BOOL force); - -extern int ntfs_version_is_supported(ntfs_volume *vol); -extern int ntfs_logfile_reset(ntfs_volume *vol); - -extern int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags); - -#endif /* defined _NTFS_VOLUME_H */ diff --git a/usr/src/lib/libntfs/common/libntfs/attrib.c b/usr/src/lib/libntfs/common/libntfs/attrib.c deleted file mode 100644 index 3c239bdaa3..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/attrib.c +++ /dev/null @@ -1,5234 +0,0 @@ -/** - * attrib.c - Attribute handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2004-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "attrlist.h" -#include "device.h" -#include "mft.h" -#include "debug.h" -#include "mst.h" -#include "volume.h" -#include "types.h" -#include "layout.h" -#include "inode.h" -#include "runlist.h" -#include "lcnalloc.h" -#include "dir.h" -#include "compress.h" -#include "bitmap.h" -#include "logging.h" -#include "support.h" -#include "crypto.h" - -ntfschar AT_UNNAMED[] = { const_cpu_to_le16('\0') }; - -/** - * ntfs_get_attribute_value_length - Find the length of an attribute - * @a: - * - * Description... - * - * Returns: - */ -s64 ntfs_get_attribute_value_length(const ATTR_RECORD *a) -{ - if (!a) { - errno = EINVAL; - return 0; - } - errno = 0; - if (a->non_resident) - return sle64_to_cpu(a->u.nonres.data_size); - return (s64)le32_to_cpu(a->u.res.value_length); -} - -/** - * ntfs_get_attribute_value - Get a copy of an attribute - * @vol: - * @a: - * @b: - * - * Description... - * - * Returns: - */ -s64 ntfs_get_attribute_value(const ntfs_volume *vol, - const ATTR_RECORD *a, u8 *b) -{ - runlist *rl; - s64 total, r; - int i; - - /* Sanity checks. */ - if (!vol || !a || !b) { - errno = EINVAL; - return 0; - } - /* Complex attribute? */ - /* - * Ignore the flags in case they are not zero for an attribute list - * attribute. Windows does not complain about invalid flags and chkdsk - * does not detect or fix them so we need to cope with it, too. - */ - if (a->type != AT_ATTRIBUTE_LIST && a->flags) { - ntfs_log_error("Non-zero (%04x) attribute flags. Cannot handle " - "this yet.\n", le16_to_cpu(a->flags)); - errno = EOPNOTSUPP; - return 0; - } - if (!a->non_resident) { - /* Attribute is resident. */ - - /* Sanity check. */ - if (le32_to_cpu(a->u.res.value_length) + le16_to_cpu(a->u.res.value_offset) - > le32_to_cpu(a->length)) { - return 0; - } - - memcpy(b, (const char*)a + le16_to_cpu(a->u.res.value_offset), - le32_to_cpu(a->u.res.value_length)); - errno = 0; - return (s64)le32_to_cpu(a->u.res.value_length); - } - - /* Attribute is not resident. */ - - /* If no data, return 0. */ - if (!(a->u.nonres.data_size)) { - errno = 0; - return 0; - } - /* - * FIXME: What about attribute lists?!? (AIA) - */ - /* Decompress the mapping pairs array into a runlist. */ - rl = ntfs_mapping_pairs_decompress(vol, a, NULL); - if (!rl) { - errno = EINVAL; - return 0; - } - /* - * FIXED: We were overflowing here in a nasty fashion when we - * reach the last cluster in the runlist as the buffer will - * only be big enough to hold data_size bytes while we are - * reading in allocated_size bytes which is usually larger - * than data_size, since the actual data is unlikely to have a - * size equal to a multiple of the cluster size! - * FIXED2: We were also overflowing here in the same fashion - * when the data_size was more than one run smaller than the - * allocated size which happens with Windows XP sometimes. - */ - /* Now load all clusters in the runlist into b. */ - for (i = 0, total = 0; rl[i].length; i++) { - if (total + (rl[i].length << vol->cluster_size_bits) >= - sle64_to_cpu(a->u.nonres.data_size)) { - unsigned char *intbuf = NULL; - /* - * We have reached the last run so we were going to - * overflow when executing the ntfs_pread() which is - * BAAAAAAAD! - * Temporary fix: - * Allocate a new buffer with size: - * rl[i].length << vol->cluster_size_bits, do the - * read into our buffer, then memcpy the correct - * amount of data into the caller supplied buffer, - * free our buffer, and continue. - * We have reached the end of data size so we were - * going to overflow in the same fashion. - * Temporary fix: same as above. - */ - intbuf = ntfs_malloc(rl[i].length << - vol->cluster_size_bits); - if (!intbuf) { - int eo = errno; - free(rl); - errno = eo; - return 0; - } - /* - * FIXME: If compressed file: Only read if lcn != -1. - * Otherwise, we are dealing with a sparse run and we - * just memset the user buffer to 0 for the length of - * the run, which should be 16 (= compression unit - * size). - * FIXME: Really only when file is compressed, or can - * we have sparse runs in uncompressed files as well? - * - Yes we can, in sparse files! But not necessarily - * size of 16, just run length. - */ - r = ntfs_pread(vol->u.dev, rl[i].lcn << - vol->cluster_size_bits, rl[i].length << - vol->cluster_size_bits, intbuf); - if (r != rl[i].length << vol->cluster_size_bits) { -#define ESTR "Error reading attribute value" - if (r == -1) { - int eo = errno; - ntfs_log_perror(ESTR); - errno = eo; - } else if (r < rl[i].length << - vol->cluster_size_bits) { - ntfs_log_debug(ESTR": Ran out of " - "input data.\n"); - errno = EIO; - } else { - ntfs_log_debug(ESTR": unknown error\n"); - errno = EIO; - } -#undef ESTR - free(rl); - free(intbuf); - return 0; - } - memcpy(b + total, intbuf, sle64_to_cpu(a->u.nonres.data_size) - - total); - free(intbuf); - total = sle64_to_cpu(a->u.nonres.data_size); - break; - } - /* - * FIXME: If compressed file: Only read if lcn != -1. - * Otherwise, we are dealing with a sparse run and we just - * memset the user buffer to 0 for the length of the run, which - * should be 16 (= compression unit size). - * FIXME: Really only when file is compressed, or can - * we have sparse runs in uncompressed files as well? - * - Yes we can, in sparse files! But not necessarily size of - * 16, just run length. - */ - r = ntfs_pread(vol->u.dev, rl[i].lcn << vol->cluster_size_bits, - rl[i].length << vol->cluster_size_bits, - b + total); - if (r != rl[i].length << vol->cluster_size_bits) { -#define ESTR "Error reading attribute value" - if (r == -1) { - int eo = errno; - ntfs_log_perror(ESTR); - errno = eo; - } else if (r < rl[i].length << vol->cluster_size_bits) { - ntfs_log_debug(ESTR ": Ran out of " - "input data.\n"); - errno = EIO; - } else { - ntfs_log_debug(ESTR ": unknown error\n"); - errno = EIO; - } -#undef ESTR - free(rl); - return 0; - } - total += r; - } - free(rl); - return total; -} - -/* Already cleaned up code below, but still look for FIXME:... */ - -/** - * __ntfs_attr_init - primary initialization of an ntfs attribute structure - * @na: ntfs attribute to initialize - * @ni: ntfs inode with which to initialize the ntfs attribute - * @type: attribute type - * @name: attribute name in little endian Unicode or NULL - * @name_len: length of attribute @name in Unicode characters (if @name given) - * - * Initialize the ntfs attribute @na with @ni, @type, @name, and @name_len. - */ -static void __ntfs_attr_init(ntfs_attr *na, ntfs_inode *ni, - const ATTR_TYPES type, ntfschar *name, const u32 name_len) -{ - na->rl = NULL; - na->ni = ni; - na->type = type; - na->name = name; - if (name) - na->name_len = name_len; - else - na->name_len = 0; -} - -/** - * ntfs_attr_init - initialize an ntfs_attr with data sizes and status - * @na: - * @non_resident: - * @compressed: - * @encrypted: - * @sparse: - * @allocated_size: - * @data_size: - * @initialized_size: - * @compressed_size: - * @compression_unit: - * - * Final initialization for an ntfs attribute. - */ -void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident, - const BOOL compressed, const BOOL encrypted, const BOOL sparse, - const s64 allocated_size, const s64 data_size, - const s64 initialized_size, const s64 compressed_size, - const u8 compression_unit) -{ - if (!NAttrInitialized(na)) { - if (non_resident) - NAttrSetNonResident(na); - if (compressed) - NAttrSetCompressed(na); - if (encrypted) - NAttrSetEncrypted(na); - if (sparse) - NAttrSetSparse(na); - na->allocated_size = allocated_size; - na->data_size = data_size; - na->initialized_size = initialized_size; - if (compressed || sparse) { - ntfs_volume *vol = na->ni->vol; - - na->compressed_size = compressed_size; - na->compression_block_clusters = 1 << compression_unit; - na->compression_block_size = 1 << (compression_unit + - vol->cluster_size_bits); - na->compression_block_size_bits = ffs( - na->compression_block_size) - 1; - } - NAttrSetInitialized(na); - } -} - -/** - * ntfs_attr_open - open an ntfs attribute for access - * @ni: open ntfs inode in which the ntfs attribute resides - * @type: attribute type - * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL - * @name_len: length of attribute @name in Unicode characters (if @name given) - * - * Allocate a new ntfs attribute structure, initialize it with @ni, @type, - * @name, and @name_len, then return it. Return NULL on error with - * errno set to the error code. - * - * If @name is AT_UNNAMED look specifically for an unnamed attribute. If you - * do not care whether the attribute is named or not set @name to NULL. In - * both those cases @name_len is not used at all. - */ -ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len) -{ - ntfs_attr_search_ctx *ctx; - ntfs_attr *na; - ATTR_RECORD *a; - struct list_head *pos; - int err; - BOOL cs; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", - (unsigned long long)ni->mft_no, type); - if (!ni || !ni->vol || !ni->mrec) { - errno = EINVAL; - return NULL; - } - /* Check cache, maybe this attribute already opened? */ - list_for_each(pos, &ni->attr_cache) { - ntfs_attr *tmp_na; - - tmp_na = list_entry(pos, ntfs_attr, list_entry); - if (tmp_na->type == type && tmp_na->name_len == name_len && - !ntfs_ucsncmp(tmp_na->name, name, name_len)) { - ntfs_log_trace("Found this attribute in cache, " - "increment reference count and " - "return it.\n"); - tmp_na->nr_references++; - return tmp_na; - } - } - /* Search failed. Properly open attrbute. */ - na = calloc(sizeof(ntfs_attr), 1); - if (!na) - return NULL; - if (name && name != AT_UNNAMED && name != NTFS_INDEX_I30) { - name = ntfs_ucsndup(name, name_len); - if (!name) { - err = errno; - free(na); - errno = err; - return NULL; - } - } - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) { - err = errno; - goto err_out; - } - if (ntfs_attr_lookup(type, name, name_len, 0, 0, NULL, 0, ctx)) { - err = errno; - goto put_err_out; - } - - a = ctx->attr; - /* - * Wipe the flags in case they are not zero for an attribute list - * attribute. Windows does not complain about invalid flags and chkdsk - * does not detect or fix them so we need to cope with it, too. - */ - if (type == AT_ATTRIBUTE_LIST) - a->flags = 0; - cs = (a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ? 1 : 0; - if (!name) { - if (a->name_length) { - name = ntfs_ucsndup((ntfschar*)((u8*)a + le16_to_cpu( - a->name_offset)), a->name_length); - if (!name) { - err = errno; - goto put_err_out; - } - name_len = a->name_length; - } else { - name = AT_UNNAMED; - name_len = 0; - } - } - __ntfs_attr_init(na, ni, type, name, name_len); - if (a->non_resident) { - ntfs_attr_init(na, TRUE, (a->flags & ATTR_IS_COMPRESSED)? 1 : 0, - (a->flags & ATTR_IS_ENCRYPTED) ? 1 : 0, - (a->flags & ATTR_IS_SPARSE) ? 1 : 0, - sle64_to_cpu(a->u.nonres.allocated_size), - sle64_to_cpu(a->u.nonres.data_size), - sle64_to_cpu(a->u.nonres.initialized_size), - cs ? sle64_to_cpu(a->u.nonres.compressed_size) : 0, - cs ? a->u.nonres.compression_unit : 0); - } else { - s64 l = le32_to_cpu(a->u.res.value_length); - ntfs_attr_init(na, FALSE, (a->flags & ATTR_IS_COMPRESSED) ? 1:0, - (a->flags & ATTR_IS_ENCRYPTED) ? 1 : 0, - (a->flags & ATTR_IS_SPARSE) ? 1 : 0, - (l + 7) & ~7, l, l, cs ? (l + 7) & ~7 : 0, 0); - } - ntfs_attr_put_search_ctx(ctx); - if (NAttrEncrypted(na)) - ntfs_crypto_attr_open(na); - list_add_tail(&na->list_entry, &ni->attr_cache); - na->nr_references = 1; - return na; -put_err_out: - ntfs_attr_put_search_ctx(ctx); -err_out: - free(na); - errno = err; - return NULL; -} - -/** - * ntfs_attr_close - free an ntfs attribute structure - * @na: ntfs attribute structure to free - * - * Release all memory associated with the ntfs attribute @na and then release - * @na itself. - */ -void ntfs_attr_close(ntfs_attr *na) -{ - if (!na) - return; - na->nr_references--; - if (na->nr_references) { - ntfs_log_trace("There are %d more references left to " - "this attribute.\n", na->nr_references); - return; - } - ntfs_log_trace("There are no more references left to this attribute\n"); - list_del(&na->list_entry); - if (NAttrEncrypted(na)) - ntfs_crypto_attr_close(na); - if (NAttrNonResident(na) && na->rl) - free(na->rl); - /* Don't release if using an internal constant. */ - if (na->name != AT_UNNAMED && na->name != NTFS_INDEX_I30) - free(na->name); - free(na); -} - -/** - * ntfs_attr_map_runlist - map (a part of) a runlist of an ntfs attribute - * @na: ntfs attribute for which to map (part of) a runlist - * @vcn: map runlist part containing this vcn - * - * Map the part of a runlist containing the @vcn of the ntfs attribute @na. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn) -{ - LCN lcn; - ntfs_attr_search_ctx *ctx; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n", - (unsigned long long)na->ni->mft_no, na->type, (long long)vcn); - - lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn); - if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT) - return 0; - - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - return -1; - - /* Find the attribute in the mft record. */ - if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE, - vcn, NULL, 0, ctx)) { - runlist_element *rl; - - /* Decode the runlist. */ - rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr, - na->rl); - if (rl) { - na->rl = rl; - ntfs_attr_put_search_ctx(ctx); - return 0; - } - } - ntfs_attr_put_search_ctx(ctx); - return -1; -} - -/** - * ntfs_attr_map_runlist_range - map (a part of) a runlist of an ntfs attribute - * @na: ntfs attribute for which to map (part of) a runlist - * @from_vcn: map runlist part starting this vcn - * @to_vcn: map runlist part ending this vcn - * - * Map the part of a runlist from containing the @from_vcn to containing the - * @to_vcn of an ntfs attribute @na. It is OK for @to_vcn to be beyond last run. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn) -{ - ntfs_attr_search_ctx *ctx = NULL; - runlist *rl; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, " - "from_vcn 0x%llx, to_vcn 0x%llx.\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)from_vcn, (long long)to_vcn); - - /* Map extent with @from_vcn. */ - if (ntfs_attr_map_runlist(na, from_vcn)) - goto err_out; - - for (rl = na->rl; rl->vcn <= to_vcn;) { - /* Skip not interesting to us runs. */ - if (rl->lcn >= 0 || rl->lcn == LCN_HOLE || (rl->vcn + - rl->length < from_vcn && - rl->lcn == LCN_RL_NOT_MAPPED)) { - rl++; - continue; - } - - /* We reached the end of runlist, just exit. */ - if (rl->lcn == LCN_ENOENT) - break; - - /* Check for errors. */ - if (rl->lcn < 0 && rl->lcn != LCN_RL_NOT_MAPPED) { - errno = EIO; - goto err_out; - } - - /* Runlist is not mapped here. */ - if (!ctx) { - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - goto err_out; - } - /* Find the attribute in the mft record. */ - if (ntfs_attr_lookup(na->type, na->name, na->name_len, - CASE_SENSITIVE, rl->vcn, NULL, 0, - ctx)) - goto err_out; - - /* Decode the runlist. */ - rl = ntfs_mapping_pairs_decompress(na->ni->vol, ctx->attr, - na->rl); - if (!rl) - goto err_out; - na->rl = rl; - } - - ntfs_attr_put_search_ctx(ctx); - ntfs_log_trace("Done.\n"); - return 0; -err_out: - ntfs_attr_put_search_ctx(ctx); - ntfs_log_trace("Failed.\n"); - return -1; -} - -/** - * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute - * @na: ntfs attribute for which to map the runlist - * - * Map the whole runlist of the ntfs attribute @na. For an attribute made up - * of only one attribute extent this is the same as calling - * ntfs_attr_map_runlist(na, 0) but for an attribute with multiple extents this - * will map the runlist fragments from each of the extents thus giving access - * to the entirety of the disk allocation of an attribute. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attr_map_whole_runlist(ntfs_attr *na) -{ - VCN next_vcn, last_vcn, highest_vcn; - ntfs_attr_search_ctx *ctx; - ntfs_volume *vol = na->ni->vol; - ATTR_RECORD *a; - int err; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", - (unsigned long long)na->ni->mft_no, na->type); - - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - return -1; - - /* Map all attribute extents one by one. */ - next_vcn = last_vcn = highest_vcn = 0; - a = NULL; - while (1) { - runlist_element *rl; - - int not_mapped = 0; - if (ntfs_rl_vcn_to_lcn(na->rl, next_vcn) == LCN_RL_NOT_MAPPED) - not_mapped = 1; - - if (ntfs_attr_lookup(na->type, na->name, na->name_len, - CASE_SENSITIVE, next_vcn, NULL, 0, ctx)) - break; - - a = ctx->attr; - - if (not_mapped) { - /* Decode the runlist. */ - rl = ntfs_mapping_pairs_decompress(na->ni->vol, - a, na->rl); - if (!rl) - goto err_out; - na->rl = rl; - } - - /* Are we in the first extent? */ - if (!next_vcn) { - if (a->u.nonres.lowest_vcn) { - ntfs_log_trace("First extent of attribute has " - "non zero lowest_vcn. " - "Inode is corrupt.\n"); - errno = EIO; - goto err_out; - } - /* Get the last vcn in the attribute. */ - last_vcn = sle64_to_cpu(a->u.nonres.allocated_size) >> - vol->cluster_size_bits; - } - - /* Get the lowest vcn for the next extent. */ - highest_vcn = sle64_to_cpu(a->u.nonres.highest_vcn); - next_vcn = highest_vcn + 1; - - /* Only one extent or error, which we catch below. */ - if (next_vcn <= 0) { - errno = ENOENT; - break; - } - - /* Avoid endless loops due to corruption. */ - if (next_vcn < sle64_to_cpu(a->u.nonres.lowest_vcn)) { - ntfs_log_trace("Inode has corrupt attribute list " - "attribute.\n"); - errno = EIO; - goto err_out; - } - } - if (!a) { - if (errno == ENOENT) - ntfs_log_trace("Attribute not found. " - "Inode is corrupt.\n"); - else - ntfs_log_trace("Inode is corrupt.\n"); - goto err_out; - } - if (highest_vcn && highest_vcn != last_vcn - 1) { - ntfs_log_trace("Failed to load the complete run list for the " - "attribute. Bug or corrupt inode.\n"); - ntfs_log_trace("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n", - (long long)highest_vcn, - (long long)last_vcn - 1); - errno = EIO; - goto err_out; - } - err = errno; - ntfs_attr_put_search_ctx(ctx); - if (err == ENOENT) - return 0; -out_now: - errno = err; - return -1; -err_out: - err = errno; - ntfs_attr_put_search_ctx(ctx); - goto out_now; -} - -/** - * ntfs_attr_vcn_to_lcn - convert a vcn into a lcn given an ntfs attribute - * @na: ntfs attribute whose runlist to use for conversion - * @vcn: vcn to convert - * - * Convert the virtual cluster number @vcn of an attribute into a logical - * cluster number (lcn) of a device using the runlist @na->rl to map vcns to - * their corresponding lcns. - * - * If the @vcn is not mapped yet, attempt to map the attribute extent - * containing the @vcn and retry the vcn to lcn conversion. - * - * Since lcns must be >= 0, we use negative return values with special meaning: - * - * Return value Meaning / Description - * ========================================== - * -1 = LCN_HOLE Hole / not allocated on disk. - * -3 = LCN_ENOENT There is no such vcn in the attribute. - * -4 = LCN_EINVAL Input parameter error. - * -5 = LCN_EIO Corrupt fs, disk i/o error, or not enough memory. - */ -LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn) -{ - LCN lcn; - BOOL is_retry = FALSE; - - if (!na || !NAttrNonResident(na) || vcn < 0) - return (LCN)LCN_EINVAL; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long - long)na->ni->mft_no, na->type); -retry: - /* Convert vcn to lcn. If that fails map the runlist and retry once. */ - lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn); - if (lcn >= 0) - return lcn; - if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) { - is_retry = TRUE; - goto retry; - } - /* - * If the attempt to map the runlist failed, or we are getting - * LCN_RL_NOT_MAPPED despite having mapped the attribute extent - * successfully, something is really badly wrong... - */ - if (!is_retry || lcn == (LCN)LCN_RL_NOT_MAPPED) - return (LCN)LCN_EIO; - /* lcn contains the appropriate error code. */ - return lcn; -} - -/** - * ntfs_attr_find_vcn - find a vcn in the runlist of an ntfs attribute - * @na: ntfs attribute whose runlist to search - * @vcn: vcn to find - * - * Find the virtual cluster number @vcn in the runlist of the ntfs attribute - * @na and return the the address of the runlist element containing the @vcn. - * - * Note you need to distinguish between the lcn of the returned runlist - * element being >= 0 and LCN_HOLE. In the later case you have to return zeroes - * on read and allocate clusters on write. You need to update the runlist, the - * attribute itself as well as write the modified mft record to disk. - * - * If there is an error return NULL with errno set to the error code. The - * following error codes are defined: - * EINVAL Input parameter error. - * ENOENT There is no such vcn in the runlist. - * ENOMEM Not enough memory. - * EIO I/O error or corrupt metadata. - */ -runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn) -{ - runlist_element *rl; - BOOL is_retry = FALSE; - - if (!na || !NAttrNonResident(na) || vcn < 0) { - errno = EINVAL; - return NULL; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn %llx\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)vcn); -retry: - rl = na->rl; - if (!rl) - goto map_rl; - if (vcn < rl[0].vcn) - goto map_rl; - while (rl->length) { - if (vcn < rl[1].vcn) { - if (rl->lcn >= (LCN)LCN_HOLE) - return rl; - break; - } - rl++; - } - switch (rl->lcn) { - case (LCN)LCN_RL_NOT_MAPPED: - goto map_rl; - case (LCN)LCN_ENOENT: - errno = ENOENT; - break; - case (LCN)LCN_EINVAL: - errno = EINVAL; - break; - default: - errno = EIO; - break; - } - return NULL; -map_rl: - /* The @vcn is in an unmapped region, map the runlist and retry. */ - if (!is_retry && !ntfs_attr_map_runlist(na, vcn)) { - is_retry = TRUE; - goto retry; - } - /* - * If we already retried or the mapping attempt failed something has - * gone badly wrong. EINVAL and ENOENT coming from a failed mapping - * attempt are equivalent to errors for us as they should not happen - * in our code paths. - */ - if (is_retry || errno == EINVAL || errno == ENOENT) - errno = EIO; - return NULL; -} - -/** - * ntfs_attr_pread - read from an attribute specified by an ntfs_attr structure - * @na: ntfs attribute to read from - * @pos: byte position in the attribute to begin reading from - * @count: number of bytes to read - * @b: output data buffer - * - * This function will read @count bytes starting at offset @pos from the ntfs - * attribute @na into the data buffer @b. - * - * On success, return the number of successfully read bytes. If this number is - * lower than @count this means that the read reached end of file or that an - * error was encountered during the read so that the read is partial. 0 means - * end of file or nothing was read (also return 0 when @count is 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of ntfs_pread(), or to EINVAL in case of invalid - * arguments. - */ -s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b) -{ - s64 br, to_read, ofs, total, total2; - ntfs_volume *vol; - runlist_element *rl; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, " - "count 0x%llx.\n", (unsigned long long)na->ni->mft_no, - na->type, (long long)pos, (long long)count); - if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - /* - * If this is a compressed attribute it needs special treatment, but - * only if it is non-resident. - */ - if (NAttrCompressed(na) && NAttrNonResident(na)) - return ntfs_compressed_attr_pread(na, pos, count, b); - /* - * Encrypted non-resident attributes are not supported. We return - * access denied, which is what Windows NT4 does, too. - */ - if (NAttrEncrypted(na) && NAttrNonResident(na)) - return ntfs_crypto_attr_pread(na, pos, count, b); - - vol = na->ni->vol; - if (!count) - return 0; - /* Truncate reads beyond end of attribute. */ - if (pos + count > na->data_size) { - if (pos >= na->data_size) - return 0; - count = na->data_size - pos; - } - /* If it is a resident attribute, get the value from the mft record. */ - if (!NAttrNonResident(na)) { - ntfs_attr_search_ctx *ctx; - char *val; - - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - return -1; - if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, - 0, NULL, 0, ctx)) { - int eo; -res_err_out: - eo = errno; - ntfs_attr_put_search_ctx(ctx); - errno = eo; - return -1; - } - val = (char*)ctx->attr + le16_to_cpu(ctx->attr->u.res.value_offset); - if (val < (char*)ctx->attr || val + - le32_to_cpu(ctx->attr->u.res.value_length) > - (char*)ctx->mrec + vol->mft_record_size) { - errno = EIO; - goto res_err_out; - } - memcpy(b, val + pos, count); - ntfs_attr_put_search_ctx(ctx); - return count; - } - total = total2 = 0; - /* Zero out reads beyond initialized size. */ - if (pos + count > na->initialized_size) { - if (pos >= na->initialized_size) { - memset(b, 0, count); - return count; - } - total2 = pos + count - na->initialized_size; - count -= total2; - memset((u8*)b + count, 0, total2); - } - /* Find the runlist element containing the vcn. */ - rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits); - if (!rl) { - /* - * If the vcn is not present it is an out of bounds read. - * However, we already truncated the read to the data_size, - * so getting this here is an error. - */ - if (errno == ENOENT) - errno = EIO; - return -1; - } - /* - * Gather the requested data into the linear destination buffer. Note, - * a partial final vcn is taken care of by the @count capping of read - * length. - */ - ofs = pos - (rl->vcn << vol->cluster_size_bits); - for (; count; rl++, ofs = 0) { - if (rl->lcn == LCN_RL_NOT_MAPPED) { - rl = ntfs_attr_find_vcn(na, rl->vcn); - if (!rl) { - if (errno == ENOENT) - errno = EIO; - goto rl_err_out; - } - /* Needed for case when runs merged. */ - ofs = pos + total - (rl->vcn << vol->cluster_size_bits); - } - if (!rl->length) - goto rl_err_out; - if (rl->lcn < (LCN)0) { - if (rl->lcn != (LCN)LCN_HOLE) - goto rl_err_out; - /* It is a hole, just zero the matching @b range. */ - to_read = min(count, (rl->length << - vol->cluster_size_bits) - ofs); - memset(b, 0, to_read); - /* Update progress counters. */ - total += to_read; - count -= to_read; - b = (u8*)b + to_read; - continue; - } - /* It is a real lcn, read it into @dst. */ - to_read = min(count, (rl->length << vol->cluster_size_bits) - - ofs); -retry: - ntfs_log_trace("Reading 0x%llx bytes from vcn 0x%llx, " - "lcn 0x%llx, ofs 0x%llx.\n", to_read, rl->vcn, - rl->lcn, ofs); - br = ntfs_pread(vol->u.dev, (rl->lcn << vol->cluster_size_bits) + - ofs, to_read, b); - /* If everything ok, update progress counters and continue. */ - if (br > 0) { - total += br; - count -= br; - b = (u8*)b + br; - continue; - } - /* If the syscall was interrupted, try again. */ - if (br == (s64)-1 && errno == EINTR) - goto retry; - if (total) - return total; - if (!br) - errno = EIO; - return -1; - } - /* Finally, return the number of bytes read. */ - return total + total2; -rl_err_out: - if (total) - return total; - errno = EIO; - return -1; -} - -/** - * ntfs_attr_pwrite - positioned write to an ntfs attribute - * @na: ntfs attribute to write to - * @pos: position in the attribute to write to - * @count: number of bytes to write - * @b: data buffer to write to disk - * - * This function will write @count bytes from data buffer @b to ntfs attribute - * @na at position @pos. - * - * On success, return the number of successfully written bytes. If this number - * is lower than @count this means that an error was encountered during the - * write so that the write is partial. 0 means nothing was written (also return - * 0 when @count is 0). - * - * On error and nothing has been written, return -1 with errno set - * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of - * invalid arguments. - */ -s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) -{ - s64 written, to_write, ofs, total, old_initialized_size, old_data_size; - VCN update_from = -1; - ntfs_volume *vol; - ntfs_attr_search_ctx *ctx = NULL; - runlist_element *rl; - int eo; - struct { - unsigned int undo_initialized_size : 1; - unsigned int undo_data_size : 1; - unsigned int update_mapping_pairs : 1; - } need_to = { 0, 0, 0 }; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, " - "count 0x%llx.\n", na->ni->mft_no, na->type, - (long long)pos, (long long)count); - if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - vol = na->ni->vol; - /* - * Encrypted non-resident attributes are not supported. We return - * access denied, which is what Windows NT4 does, too. - */ - if (NAttrEncrypted(na) && NAttrNonResident(na)) { - errno = EACCES; - return -1; - } - /* If this is a compressed attribute it needs special treatment. */ - if (NAttrCompressed(na)) { - // TODO: Implement writing compressed attributes! (AIA) - // return ntfs_attr_pwrite_compressed(ntfs_attr *na, - // const s64 pos, s64 count, void *b); - errno = EOPNOTSUPP; - return -1; - } - if (!count) - return 0; - /* If the write reaches beyond the end, extend the attribute. */ - old_data_size = na->data_size; - if (pos + count > na->data_size) { - if (__ntfs_attr_truncate(na, pos + count, FALSE)) { - eo = errno; - ntfs_log_trace("Attribute extend failed.\n"); - errno = eo; - return -1; - } - need_to.undo_data_size = 1; - } - old_initialized_size = na->initialized_size; - /* If it is a resident attribute, write the data to the mft record. */ - if (!NAttrNonResident(na)) { - char *val; - - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - goto err_out; - if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, - 0, NULL, 0, ctx)) - goto err_out; - val = (char*)ctx->attr + le16_to_cpu(ctx->attr->u.res.value_offset); - if (val < (char*)ctx->attr || val + - le32_to_cpu(ctx->attr->u.res.value_length) > - (char*)ctx->mrec + vol->mft_record_size) { - errno = EIO; - goto err_out; - } - memcpy(val + pos, b, count); - if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no, - ctx->mrec)) { - /* - * NOTE: We are in a bad state at this moment. We have - * dirtied the mft record but we failed to commit it to - * disk. Since we have read the mft record ok before, - * it is unlikely to fail writing it, so is ok to just - * return error here... (AIA) - */ - goto err_out; - } - ntfs_attr_put_search_ctx(ctx); - return count; - } - total = 0; - /* Handle writes beyond initialized_size. */ - if (pos + count > na->initialized_size) { - /* - * Map runlist between initialized size and place we start - * writing at. - */ - if (ntfs_attr_map_runlist_range(na, na->initialized_size >> - vol->cluster_size_bits, - pos >> vol->cluster_size_bits)) - goto err_out; - /* Set initialized_size to @pos + @count. */ - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - goto err_out; - if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, - 0, NULL, 0, ctx)) - goto err_out; - /* If write starts beyond initialized_size, zero the gap. */ - if (pos > na->initialized_size && ntfs_rl_fill_zero(vol, - na->rl, na->initialized_size, - pos - na->initialized_size)) - goto err_out; - - ctx->attr->u.nonres.initialized_size = cpu_to_sle64(pos + count); - if (ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no, - ctx->mrec)) { - /* - * Undo the change in the in-memory copy and send it - * back for writing. - */ - ctx->attr->u.nonres.initialized_size = - cpu_to_sle64(old_initialized_size); - ntfs_mft_record_write(vol, ctx->ntfs_ino->mft_no, - ctx->mrec); - goto err_out; - } - na->initialized_size = pos + count; - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - /* - * NOTE: At this point the initialized_size in the mft record - * has been updated BUT there is random data on disk thus if - * we decide to abort, we MUST change the initialized_size - * again. - */ - need_to.undo_initialized_size = 1; - } - /* Find the runlist element containing the vcn. */ - rl = ntfs_attr_find_vcn(na, pos >> vol->cluster_size_bits); - if (!rl) { - /* - * If the vcn is not present it is an out of bounds write. - * However, we already extended the size of the attribute, - * so getting this here must be an error of some kind. - */ - if (errno == ENOENT) - errno = EIO; - goto err_out; - } - /* - * Scatter the data from the linear data buffer to the volume. Note, a - * partial final vcn is taken care of by the @count capping of write - * length. - */ - ofs = pos - (rl->vcn << vol->cluster_size_bits); - for (; count; rl++, ofs = 0) { - if (rl->lcn == LCN_RL_NOT_MAPPED) { - rl = ntfs_attr_find_vcn(na, rl->vcn); - if (!rl) { - if (errno == ENOENT) - errno = EIO; - goto rl_err_out; - } - /* Needed for case when runs merged. */ - ofs = pos + total - (rl->vcn << vol->cluster_size_bits); - } - if (!rl->length) { - errno = EIO; - goto rl_err_out; - } - if (rl->lcn < (LCN)0) { - LCN lcn_seek_from = -1; - runlist *rlc; - VCN cur_vcn, from_vcn; - - if (rl->lcn != (LCN)LCN_HOLE) { - errno = EIO; - goto rl_err_out; - } - - to_write = min(count, (rl->length << - vol->cluster_size_bits) - ofs); - - /* Instantiate the hole. */ - cur_vcn = rl->vcn; - from_vcn = rl->vcn + (ofs >> vol->cluster_size_bits); - ntfs_log_trace("Instantiate hole with vcn 0x%llx.\n", - cur_vcn); - /* - * Map whole runlist to be able update mapping pairs - * later. - */ - if (ntfs_attr_map_whole_runlist(na)) - goto err_out; - /* - * Restore @rl, it probably get lost during runlist - * mapping. - */ - rl = ntfs_attr_find_vcn(na, cur_vcn); - if (!rl) { - ntfs_log_error("BUG! Failed to find run after " - "mapping whole runlist. Please " - "report to the %s.\n", - NTFS_DEV_LIST); - errno = EIO; - goto err_out; - } - /* - * Search backwards to find the best lcn to start - * seek from. - */ - rlc = rl; - while (rlc->vcn) { - rlc--; - if (rlc->lcn >= 0) { - lcn_seek_from = rlc->lcn + - (from_vcn - rlc->vcn); - break; - } - } - if (lcn_seek_from == -1) { - /* Backwards search failed, search forwards. */ - rlc = rl; - while (rlc->length) { - rlc++; - if (rlc->lcn >= 0) { - lcn_seek_from = rlc->lcn - - (rlc->vcn - from_vcn); - if (lcn_seek_from < -1) - lcn_seek_from = -1; - break; - } - } - } - /* Allocate clusters to instantiate the hole. */ - rlc = ntfs_cluster_alloc(vol, from_vcn, - ((ofs + to_write - 1) >> - vol->cluster_size_bits) + 1 + - rl->vcn - from_vcn, - lcn_seek_from, DATA_ZONE); - if (!rlc) { - eo = errno; - ntfs_log_trace("Failed to allocate clusters " - "for hole instantiating.\n"); - errno = eo; - goto err_out; - } - /* Merge runlists. */ - rl = ntfs_runlists_merge(na->rl, rlc); - if (!rl) { - eo = errno; - ntfs_log_trace("Failed to merge runlists.\n"); - if (ntfs_cluster_free_from_rl(vol, rlc)) { - ntfs_log_trace("Failed to free just " - "allocated clusters. Leaving " - "inconsistent metadata. " - "Run chkdsk\n"); - } - errno = eo; - goto err_out; - } - na->rl = rl; - need_to.update_mapping_pairs = 1; - if (update_from == -1) - update_from = from_vcn; - rl = ntfs_attr_find_vcn(na, cur_vcn); - if (!rl) { - /* - * It's definitely a BUG, if we failed to find - * @cur_vcn, because we missed it during - * instantiating of the hole. - */ - ntfs_log_error("BUG! Failed to find run after " - "instantiating. Please report " - "to the %s.\n", NTFS_DEV_LIST); - errno = EIO; - goto err_out; - } - /* If leaved part of the hole go to the next run. */ - if (rl->lcn < 0) - rl++; - /* Now LCN shoudn't be less than 0. */ - if (rl->lcn < 0) { - ntfs_log_error("BUG! LCN is lesser than 0. " - "Please report to the %s.\n", - NTFS_DEV_LIST); - errno = EIO; - goto err_out; - } - if (rl->vcn < cur_vcn) { - /* - * Clusters that replaced hole are merged with - * previous run, so we need to update offset. - */ - ofs += (cur_vcn - rl->vcn) << - vol->cluster_size_bits; - } - if (rl->vcn > cur_vcn) { - /* - * We left part of the hole, so update we need - * to update offset - */ - ofs -= (rl->vcn - cur_vcn) << - vol->cluster_size_bits; - } - /* - * Clear region between start of @rl->vcn cluster and - * @ofs if necessary. - */ - if (ofs && ntfs_rl_fill_zero(vol, na->rl, rl->vcn << - vol->cluster_size_bits, ofs)) - goto err_out; - } - /* It is a real lcn, write it to the volume. */ - to_write = min(count, (rl->length << vol->cluster_size_bits) - - ofs); -retry: - ntfs_log_trace("Writing 0x%llx bytes to vcn 0x%llx, lcn 0x%llx," - " ofs 0x%llx.\n", to_write, rl->vcn, rl->lcn, - ofs); - if (!NVolReadOnly(vol)) { - s64 pos = (rl->lcn << vol->cluster_size_bits) + ofs; - int bsize = 4096; /* FIXME: Test whether we need - PAGE_SIZE here. Eg., on IA64. */ - /* - * Write 4096 size blocks if it's possible. This will - * cause the kernel not to seek and read disk blocks for - * filling the end of the buffer which increases write - * speed. - */ - if (vol->cluster_size >= bsize && !(ofs % bsize) && - (to_write % bsize) && ofs + to_write == - na->initialized_size) { - char *cb; - s64 rounded = (to_write + bsize - 1) & - ~(bsize - 1); - - cb = ntfs_malloc(rounded); - if (!cb) - goto err_out; - memcpy(cb, b, to_write); - memset(cb + to_write, 0, rounded - to_write); - written = ntfs_pwrite(vol->u.dev, pos, rounded, - cb); - if (written > to_write) - written = to_write; - free(cb); - } else - written = ntfs_pwrite(vol->u.dev, pos, to_write, - b); - } else - written = to_write; - /* If everything ok, update progress counters and continue. */ - if (written > 0) { - total += written; - count -= written; - b = (const u8*)b + written; - continue; - } - /* If the syscall was interrupted, try again. */ - if (written == (s64)-1 && errno == EINTR) - goto retry; - if (!written) - errno = EIO; - goto rl_err_out; - } -done: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - /* Update mapping pairs if needed. */ - if (need_to.update_mapping_pairs) { - if (ntfs_attr_update_mapping_pairs(na, update_from)) { - /* FIXME: We want rollback here. */ - ntfs_log_perror("%s(): Failed to update mapping pairs. " - "Leaving inconsistent metadata. " - "Run chkdsk!", "ntfs_attr_pwrite"); - errno = EIO; - return -1; - } - } - /* Finally, return the number of bytes written. */ - return total; -rl_err_out: - eo = errno; - if (total) { - if (need_to.undo_initialized_size) { - if (pos + total > na->initialized_size) - goto done; - /* - * TODO: Need to try to change initialized_size. If it - * succeeds goto done, otherwise goto err_out. (AIA) - */ - errno = EOPNOTSUPP; - goto err_out; - } - goto done; - } - errno = eo; -err_out: - eo = errno; - if (need_to.undo_initialized_size) { - int err; - - err = 0; - if (!ctx) { - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - err = 1; - } else - ntfs_attr_reinit_search_ctx(ctx); - if (ctx) { - err = ntfs_attr_lookup(na->type, na->name, - na->name_len, 0, 0, NULL, 0, ctx); - if (!err) { - na->initialized_size = old_initialized_size; - ctx->attr->u.nonres.initialized_size = cpu_to_sle64( - old_initialized_size); - err = ntfs_mft_record_write(vol, - ctx->ntfs_ino->mft_no, - ctx->mrec); - } - } - if (err) { - /* - * FIXME: At this stage could try to recover by filling - * old_initialized_size -> new_initialized_size with - * data or at least zeroes. (AIA) - */ - ntfs_log_error("Eeek! Failed to recover from error. " - "Leaving metadata in inconsistent " - "state! Run chkdsk!\n"); - } - } - if (ctx) - ntfs_attr_put_search_ctx(ctx); - /* Update mapping pairs if needed. */ - if (need_to.update_mapping_pairs) - ntfs_attr_update_mapping_pairs(na, update_from); - /* Restore original data_size if needed. */ - if (need_to.undo_data_size && ntfs_attr_truncate(na, old_data_size)) - ntfs_log_trace("Failed to restore data_size.\n"); - errno = eo; - return -1; -} - -/** - * ntfs_attr_mst_pread - multi sector transfer protected ntfs attribute read - * @na: multi sector transfer protected ntfs attribute to read from - * @pos: byte position in the attribute to begin reading from - * @bk_cnt: number of mst protected blocks to read - * @bk_size: size of each mst protected block in bytes - * @dst: output data buffer - * - * This function will read @bk_cnt blocks of size @bk_size bytes each starting - * at offset @pos from the ntfs attribute @na into the data buffer @b. - * - * On success, the multi sector transfer fixups are applied and the number of - * read blocks is returned. If this number is lower than @bk_cnt this means - * that the read has either reached end of attribute or that an error was - * encountered during the read so that the read is partial. 0 means end of - * attribute or nothing to read (also return 0 when @bk_cnt or @bk_size are 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of ntfs_attr_pread() or to EINVAL in case of invalid - * arguments. - * - * NOTE: If an incomplete multi sector transfer is detected the magic is - * changed to BAAD but no error is returned, i.e. it is possible that any of - * the returned blocks have multi sector transfer errors. This should be - * detected by the caller by checking each block with is_baad_recordp(&block). - * The reasoning is that we want to fixup as many blocks as possible and we - * want to return even bad ones to the caller so, e.g. in case of ntfsck, the - * errors can be repaired. - */ -s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt, - const u32 bk_size, void *dst) -{ - s64 br; - u8 *end; - - ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, " - "pos 0x%llx.\n", (unsigned long long)na->ni->mft_no, - na->type, (long long)pos); - if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) { - errno = EINVAL; - return -1; - } - br = ntfs_attr_pread(na, pos, bk_cnt * bk_size, dst); - if (br <= 0) - return br; - br /= bk_size; - for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst + - bk_size) - ntfs_mst_post_read_fixup((NTFS_RECORD*)dst, bk_size); - /* Finally, return the number of blocks read. */ - return br; -} - -/** - * ntfs_attr_mst_pwrite - multi sector transfer protected ntfs attribute write - * @na: multi sector transfer protected ntfs attribute to write to - * @pos: position in the attribute to write to - * @bk_cnt: number of mst protected blocks to write - * @bk_size: size of each mst protected block in bytes - * @src: data buffer to write to disk - * - * This function will write @bk_cnt blocks of size @bk_size bytes each from - * data buffer @b to multi sector transfer (mst) protected ntfs attribute @na - * at position @pos. - * - * On success, return the number of successfully written blocks. If this number - * is lower than @bk_cnt this means that an error was encountered during the - * write so that the write is partial. 0 means nothing was written (also - * return 0 when @bk_cnt or @bk_size are 0). - * - * On error and nothing has been written, return -1 with errno set - * appropriately to the return code of ntfs_attr_pwrite(), or to EINVAL in case - * of invalid arguments. - * - * NOTE: We mst protect the data, write it, then mst deprotect it using a quick - * deprotect algorithm (no checking). This saves us from making a copy before - * the write and at the same time causes the usn to be incremented in the - * buffer. This conceptually fits in better with the idea that cached data is - * always deprotected and protection is performed when the data is actually - * going to hit the disk and the cache is immediately deprotected again - * simulating an mst read on the written data. This way cache coherency is - * achieved. - */ -s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, s64 bk_cnt, - const u32 bk_size, void *src) -{ - s64 written, i; - - ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, " - "pos 0x%llx.\n", (unsigned long long)na->ni->mft_no, - na->type, (long long)pos); - if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) { - errno = EINVAL; - return -1; - } - if (!bk_cnt) - return 0; - /* Prepare data for writing. */ - for (i = 0; i < bk_cnt; ++i) { - int err; - - err = ntfs_mst_pre_write_fixup((NTFS_RECORD*) - ((u8*)src + i * bk_size), bk_size); - if (err < 0) { - /* Abort write at this position. */ - if (!i) - return err; - bk_cnt = i; - break; - } - } - /* Write the prepared data. */ - written = ntfs_attr_pwrite(na, pos, bk_cnt * bk_size, src); - /* Quickly deprotect the data again. */ - for (i = 0; i < bk_cnt; ++i) - ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)src + i * - bk_size)); - if (written <= 0) - return written; - /* Finally, return the number of complete blocks written. */ - return written / bk_size; -} - -/** - * ntfs_attr_find - find (next) attribute in mft record - * @type: attribute type to find - * @name: attribute name to find (optional, i.e. NULL means don't care) - * @name_len: attribute name length (only needed if @name present) - * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) - * @val: attribute value to find (optional, resident attributes only) - * @val_len: attribute value length - * @ctx: search context with mft record and attribute to search from - * - * You shouldn't need to call this function directly. Use lookup_attr() instead. - * - * ntfs_attr_find() takes a search context @ctx as parameter and searches the - * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an - * attribute of @type, optionally @name and @val. If found, ntfs_attr_find() - * returns 0 and @ctx->attr will point to the found attribute. - * - * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and - * @ctx->attr will point to the attribute before which the attribute being - * searched for would need to be inserted if such an action were to be desired. - * - * On actual error, ntfs_attr_find() returns -1 with errno set to the error - * code but not to ENOENT. In this case @ctx->attr is undefined and in - * particular do not rely on it not changing. - * - * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it - * is FALSE, the search begins after @ctx->attr. - * - * If @type is AT_UNUSED, return the first found attribute, i.e. one can - * enumerate all attributes by setting @type to AT_UNUSED and then calling - * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to - * indicate that there are no more entries. During the enumeration, each - * successful call of ntfs_attr_find() will return the next attribute in the - * mft record @ctx->mrec. - * - * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT. - * AT_END is not a valid attribute, its length is zero for example, thus it is - * safer to return error instead of success in this case. This also allows us - * to interoperate cleanly with ntfs_external_attr_find(). - * - * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present - * but not AT_UNNAMED search for a named attribute matching @name. Otherwise, - * match both named and unnamed attributes. - * - * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and - * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record - * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at - * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case - * sensitive. When @name is present, @name_len is the @name length in Unicode - * characters. - * - * If @name is not present (NULL), we assume that the unnamed attribute is - * being searched for. - * - * Finally, the resident attribute value @val is looked for, if present. - * If @val is not present (NULL), @val_len is ignored. - * - * ntfs_attr_find() only searches the specified mft record and it ignores the - * presence of an attribute list attribute (unless it is the one being searched - * for, obviously). If you need to take attribute lists into consideration, use - * ntfs_attr_lookup() instead (see below). This also means that you cannot use - * ntfs_attr_find() to search for extent records of non-resident attributes, as - * extents with lowest_vcn != 0 are usually described by the attribute list - * attribute only. - Note that it is possible that the first extent is only in - * the attribute list while the last extent is in the base mft record, so don't - * rely on being able to find the first extent in the base mft record. - * - * Warning: Never use @val when looking for attribute types which can be - * non-resident as this most likely will result in a crash! - */ -static int ntfs_attr_find(const ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx) -{ - ATTR_RECORD *a; - ntfs_volume *vol; - ntfschar *upcase; - u32 upcase_len; - - ntfs_log_trace("Entering for attribute type 0x%x.\n", type); - - if (ctx->ntfs_ino) { - vol = ctx->ntfs_ino->vol; - upcase = vol->upcase; - upcase_len = vol->upcase_len; - } else { - if (name && name != AT_UNNAMED) { - errno = EINVAL; - return -1; - } - vol = NULL; - upcase = NULL; - upcase_len = 0; - } - /* - * Iterate over attributes in mft record starting at @ctx->attr, or the - * attribute following that, if @ctx->is_first is TRUE. - */ - if (ctx->is_first) { - a = ctx->attr; - ctx->is_first = FALSE; - } else - a = (ATTR_RECORD*)((char*)ctx->attr + - le32_to_cpu(ctx->attr->length)); - for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) { - if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec + - le32_to_cpu(ctx->mrec->bytes_allocated)) - break; - ctx->attr = a; - if (((type != AT_UNUSED) && (le32_to_cpu(a->type) > - le32_to_cpu(type))) || - (a->type == AT_END)) { - errno = ENOENT; - return -1; - } - if (!a->length) - break; - /* If this is an enumeration return this attribute. */ - if (type == AT_UNUSED) - return 0; - if (a->type != type) - continue; - /* - * If @name is AT_UNNAMED we want an unnamed attribute. - * If @name is present, compare the two names. - * Otherwise, match any attribute. - */ - if (name == AT_UNNAMED) { - /* The search failed if the found attribute is named. */ - if (a->name_length) { - errno = ENOENT; - return -1; - } - } else if (name && !ntfs_names_are_equal(name, name_len, - (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)), - a->name_length, ic, upcase, upcase_len)) { - register int rc; - - rc = ntfs_names_collate(name, name_len, - (ntfschar*)((char*)a + - le16_to_cpu(a->name_offset)), - a->name_length, 1, IGNORE_CASE, - upcase, upcase_len); - /* - * If @name collates before a->name, there is no - * matching attribute. - */ - if (rc == -1) { - errno = ENOENT; - return -1; - } - /* If the strings are not equal, continue search. */ - if (rc) - continue; - rc = ntfs_names_collate(name, name_len, - (ntfschar*)((char*)a + - le16_to_cpu(a->name_offset)), - a->name_length, 1, CASE_SENSITIVE, - upcase, upcase_len); - if (rc == -1) { - errno = ENOENT; - return -1; - } - if (rc) - continue; - } - /* - * The names match or @name not present and attribute is - * unnamed. If no @val specified, we have found the attribute - * and are done. - */ - if (!val) - return 0; - /* @val is present; compare values. */ - else { - register int rc; - - rc = memcmp(val, (char*)a +le16_to_cpu(a->u.res.value_offset), - min(val_len, - le32_to_cpu(a->u.res.value_length))); - /* - * If @val collates before the current attribute's - * value, there is no matching attribute. - */ - if (!rc) { - register u32 avl; - avl = le32_to_cpu(a->u.res.value_length); - if (val_len == avl) - return 0; - if (val_len < avl) { - errno = ENOENT; - return -1; - } - } else if (rc < 0) { - errno = ENOENT; - return -1; - } - } - } - ntfs_log_debug("ntfs_attr_find(): File is corrupt. Run chkdsk.\n"); - errno = EIO; - return -1; -} - -/** - * ntfs_external_attr_find - find an attribute in the attribute list of an inode - * @type: attribute type to find - * @name: attribute name to find (optional, i.e. NULL means don't care) - * @name_len: attribute name length (only needed if @name present) - * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) - * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only) - * @val: attribute value to find (optional, resident attributes only) - * @val_len: attribute value length - * @ctx: search context with mft record and attribute to search from - * - * You shouldn't need to call this function directly. Use ntfs_attr_lookup() - * instead. - * - * Find an attribute by searching the attribute list for the corresponding - * attribute list entry. Having found the entry, map the mft record for read - * if the attribute is in a different mft record/inode, find the attribute in - * there and return it. - * - * If @type is AT_UNUSED, return the first found attribute, i.e. one can - * enumerate all attributes by setting @type to AT_UNUSED and then calling - * ntfs_external_attr_find() repeatedly until it returns -1 with errno set to - * ENOENT to indicate that there are no more entries. During the enumeration, - * each successful call of ntfs_external_attr_find() will return the next - * attribute described by the attribute list of the base mft record described - * by the search context @ctx. - * - * If @type is AT_END, seek to the end of the base mft record ignoring the - * attribute list completely and return -1 with errno set to ENOENT. AT_END is - * not a valid attribute, its length is zero for example, thus it is safer to - * return error instead of success in this case. - * - * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present - * but not AT_UNNAMED search for a named attribute matching @name. Otherwise, - * match both named and unnamed attributes. - * - * On first search @ctx->ntfs_ino must be the inode of the base mft record and - * @ctx must have been obtained from a call to ntfs_attr_get_search_ctx(). - * On subsequent calls, @ctx->ntfs_ino can be any extent inode, too - * (@ctx->base_ntfs_ino is then the base inode). - * - * After finishing with the attribute/mft record you need to call - * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any - * mapped extent inodes, etc). - * - * Return 0 if the search was successful and -1 if not, with errno set to the - * error code. - * - * On success, @ctx->attr is the found attribute, it is in mft record - * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this - * attribute with @ctx->base_* being the base mft record to which @ctx->attr - * belongs. - * - * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the - * attribute which collates just after the attribute being searched for in the - * base ntfs inode, i.e. if one wants to add the attribute to the mft record - * this is the correct place to insert it into, and if there is not enough - * space, the attribute should be placed in an extent mft record. - * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list - * at which the new attribute's attribute list entry should be inserted. The - * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL. - * The only exception to this is when @type is AT_END, in which case - * @ctx->al_entry is set to NULL also (see above). - * - * The following error codes are defined: - * ENOENT Attribute not found, not an error as such. - * EINVAL Invalid arguments. - * EIO I/O error or corrupt data structures found. - * ENOMEM Not enough memory to allocate necessary buffers. - */ -static int ntfs_external_attr_find(ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const VCN lowest_vcn, const u8 *val, const u32 val_len, - ntfs_attr_search_ctx *ctx) -{ - ntfs_inode *base_ni, *ni; - ntfs_volume *vol; - ATTR_LIST_ENTRY *al_entry, *next_al_entry; - u8 *al_start, *al_end; - ATTR_RECORD *a; - ntfschar *al_name; - u32 al_name_len; - BOOL is_first_search = FALSE; - - ni = ctx->ntfs_ino; - base_ni = ctx->base_ntfs_ino; - ntfs_log_trace("Entering for inode 0x%llx, attribute type 0x%x.\n", - (unsigned long long)ni->mft_no, type); - if (!base_ni) { - /* First call happens with the base mft record. */ - base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino; - ctx->base_mrec = ctx->mrec; - } - if (ni == base_ni) - ctx->base_attr = ctx->attr; - if (type == AT_END) - goto not_found; - vol = base_ni->vol; - al_start = base_ni->attr_list; - al_end = al_start + base_ni->attr_list_size; - if (!ctx->al_entry) { - ctx->al_entry = (ATTR_LIST_ENTRY*)al_start; - is_first_search = TRUE; - } - /* - * Iterate over entries in attribute list starting at @ctx->al_entry, - * or the entry following that, if @ctx->is_first is TRUE. - */ - if (ctx->is_first) { - al_entry = ctx->al_entry; - ctx->is_first = FALSE; - /* - * If an enumeration and the first attribute is higher than - * the attribute list itself, need to return the attribute list - * attribute. - */ - if ((type == AT_UNUSED) && is_first_search && - le32_to_cpu(al_entry->type) > - le32_to_cpu(AT_ATTRIBUTE_LIST)) - goto find_attr_list_attr; - } else { - al_entry = (ATTR_LIST_ENTRY*)((char*)ctx->al_entry + - le16_to_cpu(ctx->al_entry->length)); - /* - * If this is an enumeration and the attribute list attribute - * is the next one in the enumeration sequence, just return the - * attribute list attribute from the base mft record as it is - * not listed in the attribute list itself. - */ - if ((type == AT_UNUSED) && le32_to_cpu(ctx->al_entry->type) < - le32_to_cpu(AT_ATTRIBUTE_LIST) && - le32_to_cpu(al_entry->type) > - le32_to_cpu(AT_ATTRIBUTE_LIST)) { - int rc; -find_attr_list_attr: - - /* Check for bogus calls. */ - if (name || name_len || val || val_len || lowest_vcn) { - errno = EINVAL; - return -1; - } - - /* We want the base record. */ - ctx->ntfs_ino = base_ni; - ctx->mrec = ctx->base_mrec; - ctx->is_first = TRUE; - /* Sanity checks are performed elsewhere. */ - ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + - le16_to_cpu(ctx->mrec->attrs_offset)); - - /* Find the attribute list attribute. */ - rc = ntfs_attr_find(AT_ATTRIBUTE_LIST, NULL, 0, - IGNORE_CASE, NULL, 0, ctx); - - /* - * Setup the search context so the correct - * attribute is returned next time round. - */ - ctx->al_entry = al_entry; - ctx->is_first = TRUE; - - /* Got it. Done. */ - if (!rc) - return 0; - - /* Error! If other than not found return it. */ - if (errno != ENOENT) - return rc; - - /* Not found?!? Absurd! Must be a bug... )-: */ - ntfs_log_trace("BUG! Attribute list attribute not " - "found but it exists! " - "Returning error (EINVAL).\n"); - errno = EINVAL; - return -1; - } - } - for (;; al_entry = next_al_entry) { - /* Out of bounds check. */ - if ((u8*)al_entry < base_ni->attr_list || - (u8*)al_entry > al_end) - break; /* Inode is corrupt. */ - ctx->al_entry = al_entry; - /* Catch the end of the attribute list. */ - if ((u8*)al_entry == al_end) - goto not_found; - if (!al_entry->length) - break; - if ((u8*)al_entry + 6 > al_end || (u8*)al_entry + - le16_to_cpu(al_entry->length) > al_end) - break; - next_al_entry = (ATTR_LIST_ENTRY*)((u8*)al_entry + - le16_to_cpu(al_entry->length)); - if (type != AT_UNUSED) { - if (le32_to_cpu(al_entry->type) > le32_to_cpu(type)) - goto not_found; - if (type != al_entry->type) - continue; - } - al_name_len = al_entry->name_length; - al_name = (ntfschar*)((u8*)al_entry + al_entry->name_offset); - /* - * If !@type we want the attribute represented by this - * attribute list entry. - */ - if (type == AT_UNUSED) - goto is_enumeration; - /* - * If @name is AT_UNNAMED we want an unnamed attribute. - * If @name is present, compare the two names. - * Otherwise, match any attribute. - */ - if (name == AT_UNNAMED) { - if (al_name_len) - goto not_found; - } else if (name && !ntfs_names_are_equal(al_name, al_name_len, - name, name_len, ic, vol->upcase, - vol->upcase_len)) { - register int rc; - - rc = ntfs_names_collate(name, name_len, al_name, - al_name_len, 1, IGNORE_CASE, - vol->upcase, vol->upcase_len); - /* - * If @name collates before al_name, there is no - * matching attribute. - */ - if (rc == -1) - goto not_found; - /* If the strings are not equal, continue search. */ - if (rc) - continue; - /* - * FIXME: Reverse engineering showed 0, IGNORE_CASE but - * that is inconsistent with ntfs_attr_find(). The - * subsequent rc checks were also different. Perhaps I - * made a mistake in one of the two. Need to recheck - * which is correct or at least see what is going - * on... (AIA) - */ - rc = ntfs_names_collate(name, name_len, al_name, - al_name_len, 1, CASE_SENSITIVE, - vol->upcase, vol->upcase_len); - if (rc == -1) - goto not_found; - if (rc) - continue; - } - /* - * The names match or @name not present and attribute is - * unnamed. Now check @lowest_vcn. Continue search if the - * next attribute list entry still fits @lowest_vcn. Otherwise - * we have reached the right one or the search has failed. - */ - if (lowest_vcn && (u8*)next_al_entry >= al_start && - (u8*)next_al_entry + 6 < al_end && - (u8*)next_al_entry + le16_to_cpu( - next_al_entry->length) <= al_end && - sle64_to_cpu(next_al_entry->lowest_vcn) <= - lowest_vcn && - next_al_entry->type == al_entry->type && - next_al_entry->name_length == al_name_len && - ntfs_names_are_equal((ntfschar*)((char*) - next_al_entry + - next_al_entry->name_offset), - next_al_entry->name_length, - al_name, al_name_len, CASE_SENSITIVE, - vol->upcase, vol->upcase_len)) - continue; -is_enumeration: - if (MREF_LE(al_entry->mft_reference) == ni->mft_no) { - if (MSEQNO_LE(al_entry->mft_reference) != - le16_to_cpu( - ni->mrec->sequence_number)) { - ntfs_log_debug("Found stale mft reference in " - "attribute list!\n"); - break; - } - } else { /* Mft references do not match. */ - /* Do we want the base record back? */ - if (MREF_LE(al_entry->mft_reference) == - base_ni->mft_no) { - ni = ctx->ntfs_ino = base_ni; - ctx->mrec = ctx->base_mrec; - } else { - /* We want an extent record. */ - ni = ntfs_extent_inode_open(base_ni, - al_entry->mft_reference); - if (!ni) { - ntfs_log_perror("Failed to map extent " - "inode"); - break; - } - ctx->ntfs_ino = ni; - ctx->mrec = ni->mrec; - } - } - a = ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec + - le16_to_cpu(ctx->mrec->attrs_offset)); - /* - * ctx->ntfs_ino, ctx->mrec, and ctx->attr now point to the - * mft record containing the attribute represented by the - * current al_entry. - * - * We could call into ntfs_attr_find() to find the right - * attribute in this mft record but this would be less - * efficient and not quite accurate as ntfs_attr_find() ignores - * the attribute instance numbers for example which become - * important when one plays with attribute lists. Also, because - * a proper match has been found in the attribute list entry - * above, the comparison can now be optimized. So it is worth - * re-implementing a simplified ntfs_attr_find() here. - * - * Use a manual loop so we can still use break and continue - * with the same meanings as above. - */ -do_next_attr_loop: - if ((char*)a < (char*)ctx->mrec || (char*)a > (char*)ctx->mrec + - le32_to_cpu(ctx->mrec->bytes_allocated)) - break; - if (a->type == AT_END) - continue; - if (!a->length) - break; - if (al_entry->instance != a->instance) - goto do_next_attr; - /* - * If the type and/or the name are/is mismatched between the - * attribute list entry and the attribute record, there is - * corruption so we break and return error EIO. - */ - if (al_entry->type != a->type) - break; - if (!ntfs_names_are_equal((ntfschar*)((char*)a + - le16_to_cpu(a->name_offset)), - a->name_length, al_name, - al_name_len, CASE_SENSITIVE, - vol->upcase, vol->upcase_len)) - break; - ctx->attr = a; - /* - * If no @val specified or @val specified and it matches, we - * have found it! Also, if !@type, it is an enumeration, so we - * want the current attribute. - */ - if ((type == AT_UNUSED) || !val || (!a->non_resident && - le32_to_cpu(a->u.res.value_length) == val_len && - !memcmp((char*)a + le16_to_cpu(a->u.res.value_offset), - val, val_len))) { - return 0; - } -do_next_attr: - /* Proceed to the next attribute in the current mft record. */ - a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length)); - goto do_next_attr_loop; - } - if (ni != base_ni) { - ctx->ntfs_ino = base_ni; - ctx->mrec = ctx->base_mrec; - ctx->attr = ctx->base_attr; - } - ntfs_log_debug("Inode is corrupt.\n"); - errno = EIO; - return -1; -not_found: - /* - * If we were looking for AT_END or we were enumerating and reached the - * end, we reset the search context @ctx and use ntfs_attr_find() to - * seek to the end of the base mft record. - */ - if (type == AT_UNUSED || type == AT_END) { - ntfs_attr_reinit_search_ctx(ctx); - return ntfs_attr_find(AT_END, name, name_len, ic, val, val_len, - ctx); - } - /* - * The attribute wasn't found. Before we return, we want to ensure - * @ctx->mrec and @ctx->attr indicate the position at which the - * attribute should be inserted in the base mft record. Since we also - * want to preserve @ctx->al_entry we cannot reinitialize the search - * context using ntfs_attr_reinit_search_ctx() as this would set - * @ctx->al_entry to NULL. Thus we do the necessary bits manually (see - * ntfs_attr_init_search_ctx() below). Note, we _only_ preserve - * @ctx->al_entry as the remaining fields (base_*) are identical to - * their non base_ counterparts and we cannot set @ctx->base_attr - * correctly yet as we do not know what @ctx->attr will be set to by - * the call to ntfs_attr_find() below. - */ - ctx->mrec = ctx->base_mrec; - ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + - le16_to_cpu(ctx->mrec->attrs_offset)); - ctx->is_first = TRUE; - ctx->ntfs_ino = ctx->base_ntfs_ino; - ctx->base_ntfs_ino = NULL; - ctx->base_mrec = NULL; - ctx->base_attr = NULL; - /* - * In case there are multiple matches in the base mft record, need to - * keep enumerating until we get an attribute not found response (or - * another error), otherwise we would keep returning the same attribute - * over and over again and all programs using us for enumeration would - * lock up in a tight loop. - */ - { - int ret; - - do { - ret = ntfs_attr_find(type, name, name_len, ic, val, - val_len, ctx); - } while (!ret); - return ret; - } -} - -/** - * ntfs_attr_lookup - find an attribute in an ntfs inode - * @type: attribute type to find - * @name: attribute name to find (optional, i.e. NULL means don't care) - * @name_len: attribute name length (only needed if @name present) - * @ic: IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present) - * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only) - * @val: attribute value to find (optional, resident attributes only) - * @val_len: attribute value length - * @ctx: search context with mft record and attribute to search from - * - * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must - * be the base mft record and @ctx must have been obtained from a call to - * ntfs_attr_get_search_ctx(). - * - * This function transparently handles attribute lists and @ctx is used to - * continue searches where they were left off at. - * - * If @type is AT_UNUSED, return the first found attribute, i.e. one can - * enumerate all attributes by setting @type to AT_UNUSED and then calling - * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT - * to indicate that there are no more entries. During the enumeration, each - * successful call of ntfs_attr_lookup() will return the next attribute, with - * the current attribute being described by the search context @ctx. - * - * If @type is AT_END, seek to the end of the base mft record ignoring the - * attribute list completely and return -1 with errno set to ENOENT. AT_END is - * not a valid attribute, its length is zero for example, thus it is safer to - * return error instead of success in this case. It should never be needed to - * do this, but we implement the functionality because it allows for simpler - * code inside ntfs_external_attr_find(). - * - * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present - * but not AT_UNNAMED search for a named attribute matching @name. Otherwise, - * match both named and unnamed attributes. - * - * After finishing with the attribute/mft record you need to call - * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any - * mapped extent inodes, etc). - * - * Return 0 if the search was successful and -1 if not, with errno set to the - * error code. - * - * On success, @ctx->attr is the found attribute, it is in mft record - * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this - * attribute with @ctx->base_* being the base mft record to which @ctx->attr - * belongs. If no attribute list attribute is present @ctx->al_entry and - * @ctx->base_* are NULL. - * - * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the - * attribute which collates just after the attribute being searched for in the - * base ntfs inode, i.e. if one wants to add the attribute to the mft record - * this is the correct place to insert it into, and if there is not enough - * space, the attribute should be placed in an extent mft record. - * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list - * at which the new attribute's attribute list entry should be inserted. The - * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL. - * The only exception to this is when @type is AT_END, in which case - * @ctx->al_entry is set to NULL also (see above). - * - * - * The following error codes are defined: - * ENOENT Attribute not found, not an error as such. - * EINVAL Invalid arguments. - * EIO I/O error or corrupt data structures found. - * ENOMEM Not enough memory to allocate necessary buffers. - */ -int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name, - const u32 name_len, const IGNORE_CASE_BOOL ic, - const VCN lowest_vcn, const u8 *val, const u32 val_len, - ntfs_attr_search_ctx *ctx) -{ - ntfs_volume *vol; - ntfs_inode *base_ni; - - if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED && - (!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) || - !vol->upcase || !vol->upcase_len))) { - errno = EINVAL; - return -1; - } - if (ctx->base_ntfs_ino) - base_ni = ctx->base_ntfs_ino; - else - base_ni = ctx->ntfs_ino; - if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST) - return ntfs_attr_find(type, name, name_len, ic, val, val_len, - ctx); - return ntfs_external_attr_find(type, name, name_len, ic, lowest_vcn, - val, val_len, ctx); -} - -/** - * ntfs_attr_init_search_ctx - initialize an attribute search context - * @ctx: attribute search context to initialize - * @ni: ntfs inode with which to initialize the search context - * @mrec: mft record with which to initialize the search context - * - * Initialize the attribute search context @ctx with @ni and @mrec. - */ -static void ntfs_attr_init_search_ctx(ntfs_attr_search_ctx *ctx, - ntfs_inode *ni, MFT_RECORD *mrec) -{ - if (!mrec) - mrec = ni->mrec; - ctx->mrec = mrec; - /* Sanity checks are performed elsewhere. */ - ctx->attr = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset)); - ctx->is_first = TRUE; - ctx->ntfs_ino = ni; - ctx->al_entry = NULL; - ctx->base_ntfs_ino = NULL; - ctx->base_mrec = NULL; - ctx->base_attr = NULL; -} - -/** - * ntfs_attr_reinit_search_ctx - reinitialize an attribute search context - * @ctx: attribute search context to reinitialize - * - * Reinitialize the attribute search context @ctx. - * - * This is used when a search for a new attribute is being started to reset - * the search context to the beginning. - */ -void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx) -{ - if (!ctx->base_ntfs_ino) { - /* No attribute list. */ - ctx->is_first = TRUE; - /* Sanity checks are performed elsewhere. */ - ctx->attr = (ATTR_RECORD*)((u8*)ctx->mrec + - le16_to_cpu(ctx->mrec->attrs_offset)); - /* - * This needs resetting due to ntfs_external_attr_find() which - * can leave it set despite having zeroed ctx->base_ntfs_ino. - */ - ctx->al_entry = NULL; - return; - } /* Attribute list. */ - ntfs_attr_init_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec); - return; -} - -/** - * ntfs_attr_get_search_ctx - allocate/initialize a new attribute search context - * @ni: ntfs inode with which to initialize the search context - * @mrec: mft record with which to initialize the search context - * - * Allocate a new attribute search context, initialize it with @ni and @mrec, - * and return it. Return NULL on error with errno set to ENOMEM. - * - * @mrec can be NULL, in which case the mft record is taken from @ni. - * - * Note: For low level utilities which know what they are doing we allow @ni to - * be NULL and @mrec to be set. Do NOT do this unless you understand the - * implications!!! For example it is no longer safe to call ntfs_attr_lookup() - * if you - */ -ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec) -{ - ntfs_attr_search_ctx *ctx; - - if (!ni && !mrec) { - errno = EINVAL; - return NULL; - } - ctx = ntfs_malloc(sizeof(ntfs_attr_search_ctx)); - if (ctx) - ntfs_attr_init_search_ctx(ctx, ni, mrec); - return ctx; -} - -/** - * ntfs_attr_put_search_ctx - release an attribute search context - * @ctx: attribute search context to free - * - * Release the attribute search context @ctx. This function does not change - * errno and doing nothing if NULL passed to it. - */ -void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx) -{ - free(ctx); -} - -/** - * ntfs_attr_find_in_attrdef - find an attribute in the $AttrDef system file - * @vol: ntfs volume to which the attribute belongs - * @type: attribute type which to find - * - * Search for the attribute definition record corresponding to the attribute - * @type in the $AttrDef system file. - * - * Return the attribute type definition record if found and NULL if not found - * or an error occurred. On error the error code is stored in errno. The - * following error codes are defined: - * ENOENT - The attribute @type is not specified in $AttrDef. - * EINVAL - Invalid parameters (e.g. @vol is not valid). - */ -ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol, - const ATTR_TYPES type) -{ - ATTR_DEF *ad; - - if (!vol || !vol->attrdef || !type) { - errno = EINVAL; - return NULL; - } - for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef < - vol->attrdef_len && ad->type; ++ad) { - /* We haven't found it yet, carry on searching. */ - if (le32_to_cpu(ad->type) < le32_to_cpu(type)) - continue; - /* We found the attribute; return it. */ - if (ad->type == type) - return ad; - /* We have gone too far already. No point in continuing. */ - break; - } - /* Attribute not found?!? */ - errno = ENOENT; - return NULL; -} - -/** - * ntfs_attr_size_bounds_check - check a size of an attribute type for validity - * @vol: ntfs volume to which the attribute belongs - * @type: attribute type which to check - * @size: size which to check - * - * Check whether the @size in bytes is valid for an attribute of @type on the - * ntfs volume @vol. This information is obtained from $AttrDef system file. - * - * Return 0 if valid and -1 if not valid or an error occurred. On error the - * error code is stored in errno. The following error codes are defined: - * ERANGE - @size is not valid for the attribute @type. - * ENOENT - The attribute @type is not specified in $AttrDef. - * EINVAL - Invalid parameters (e.g. @size is < 0 or @vol is not valid). - */ -int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type, - const s64 size) -{ - ATTR_DEF *ad; - - if (size < 0) { - errno = EINVAL; - return -1; - } - - /* - * $ATTRIBUTE_LIST should be not greater than 0x40000, but this is not - * listed in the AttrDef. - */ - if (type == AT_ATTRIBUTE_LIST && size > 0x40000) { - errno = ERANGE; - return -1; - } - - ad = ntfs_attr_find_in_attrdef(vol, type); - if (!ad) - return -1; - /* We found the attribute. - Do the bounds check. */ - if ((sle64_to_cpu(ad->min_size) && size < - sle64_to_cpu(ad->min_size)) || - ((sle64_to_cpu(ad->max_size) > 0) && size > - sle64_to_cpu(ad->max_size))) { - /* @size is out of range! */ - errno = ERANGE; - return -1; - } - return 0; -} - -/** - * ntfs_attr_can_be_non_resident - check if an attribute can be non-resident - * @vol: ntfs volume to which the attribute belongs - * @type: attribute type which to check - * - * Check whether the attribute of @type on the ntfs volume @vol is allowed to - * be non-resident. This information is obtained from $AttrDef system file. - * - * Return 0 if the attribute is allowed to be non-resident and -1 if not or an - * error occurred. On error the error code is stored in errno. The following - * error codes are defined: - * EPERM - The attribute is not allowed to be non-resident. - * ENOENT - The attribute @type is not specified in $AttrDef. - * EINVAL - Invalid parameters (e.g. @vol is not valid). - */ -int ntfs_attr_can_be_non_resident(const ntfs_volume *vol, const ATTR_TYPES type) -{ - ATTR_DEF *ad; - - /* Find the attribute definition record in $AttrDef. */ - ad = ntfs_attr_find_in_attrdef(vol, type); - if (!ad) - return -1; - /* Check the flags and return the result. */ - if (ad->flags & ATTR_DEF_RESIDENT) { - ntfs_log_trace("Attribute can't be non-resident\n"); - errno = EPERM; - return -1; - } - return 0; -} - -/** - * ntfs_attr_can_be_resident - check if an attribute can be resident - * @vol: ntfs volume to which the attribute belongs - * @type: attribute type which to check - * - * Check whether the attribute of @type on the ntfs volume @vol is allowed to - * be resident. This information is derived from our ntfs knowledge and may - * not be completely accurate, especially when user defined attributes are - * present. Basically we allow everything to be resident except for index - * allocation and extended attribute attributes. - * - * Return 0 if the attribute is allowed to be resident and -1 if not or an - * error occurred. On error the error code is stored in errno. The following - * error codes are defined: - * EPERM - The attribute is not allowed to be resident. - * EINVAL - Invalid parameters (e.g. @vol is not valid). - * - * Warning: In the system file $MFT the attribute $Bitmap must be non-resident - * otherwise windows will not boot (blue screen of death)! We cannot - * check for this here as we don't know which inode's $Bitmap is being - * asked about so the caller needs to special case this. - */ -int ntfs_attr_can_be_resident(const ntfs_volume *vol, const ATTR_TYPES type) -{ - if (!vol || !vol->attrdef || !type) { - errno = EINVAL; - return -1; - } - if (type != AT_INDEX_ALLOCATION) - return 0; - - ntfs_log_trace("Attribute can't be resident\n"); - errno = EPERM; - return -1; -} - -/** - * ntfs_make_room_for_attr - make room for an attribute inside an mft record - * @m: mft record - * @pos: position at which to make space - * @size: byte size to make available at this position - * - * @pos points to the attribute in front of which we want to make space. - * - * Return 0 on success or -1 on error. On error the error code is stored in - * errno. Possible error codes are: - * ENOSPC - There is not enough space available to complete operation. The - * caller has to make space before calling this. - * EINVAL - Input parameters were faulty. - */ -int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size) -{ - u32 biu; - - ntfs_log_trace("Entering for pos 0x%d, size %u.\n", - (int)(pos - (u8*)m), (unsigned) size); - - /* Make size 8-byte alignment. */ - size = (size + 7) & ~7; - - /* Rigorous consistency checks. */ - if (!m || !pos || pos < (u8*)m || pos + size > - (u8*)m + le32_to_cpu(m->bytes_allocated)) { - errno = EINVAL; - return -1; - } - /* The -8 is for the attribute terminator. */ - if (pos - (u8*)m > (int)le32_to_cpu(m->bytes_in_use) - 8) { - errno = EINVAL; - return -1; - } - /* Nothing to do. */ - if (!size) - return 0; - - biu = le32_to_cpu(m->bytes_in_use); - /* Do we have enough space? */ - if (biu + size > le32_to_cpu(m->bytes_allocated)) { - ntfs_log_trace("Not enough space in the MFT record\n"); - errno = ENOSPC; - return -1; - } - /* Move everything after pos to pos + size. */ - memmove(pos + size, pos, biu - (pos - (u8*)m)); - /* Update mft record. */ - m->bytes_in_use = cpu_to_le32(biu + size); - return 0; -} - -/** - * ntfs_resident_attr_record_add - add resident attribute to inode - * @ni: opened ntfs inode to which MFT record add attribute - * @type: type of the new attribute - * @name: name of the new attribute - * @name_len: name length of the new attribute - * @val: value of the new attribute - * @size: size of new attribute (length of @val, if @val != NULL) - * @flags: flags of the new attribute - * - * Return offset to attribute from the beginning of the mft record on success - * and -1 on error. On error the error code is stored in errno. - * Possible error codes are: - * EINVAL - Invalid arguments passed to function. - * EEXIST - Attribute of such type and with same name already exists. - * EIO - I/O error occurred or damaged filesystem. - */ -int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, u32 size, - ATTR_FLAGS flags) -{ - ntfs_attr_search_ctx *ctx; - u32 length; - ATTR_RECORD *a; - MFT_RECORD *m; - int err, offset; - ntfs_inode *base_ni; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n", - (long long) ni->mft_no, le32_to_cpu(type), le16_to_cpu(flags)); - - if (!ni || (!name && name_len)) { - errno = EINVAL; - return -1; - } - - if (ntfs_attr_can_be_resident(ni->vol, type)) { - if (errno == EPERM) - ntfs_log_trace("Attribute can't be resident.\n"); - else - ntfs_log_trace("ntfs_attr_can_be_resident failed.\n"); - return -1; - } - - /* Locate place where record should be. */ - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return -1; - /* - * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for - * attribute in @ni->mrec, not any extent inode in case if @ni is base - * file record. - */ - if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, val, size, - ctx)) { - err = EEXIST; - ntfs_log_trace("Attribute already present.\n"); - goto put_err_out; - } - if (errno != ENOENT) { - err = EIO; - goto put_err_out; - } - a = ctx->attr; - m = ctx->mrec; - - /* Make room for attribute. */ - length = offsetof(ATTR_RECORD, u.res.resident_end) + - ((name_len * sizeof(ntfschar) + 7) & ~7) + - ((size + 7) & ~7); - if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) { - err = errno; - ntfs_log_trace("Failed to make room for attribute.\n"); - goto put_err_out; - } - - /* Setup record fields. */ - offset = ((u8*)a - (u8*)m); - a->type = type; - a->length = cpu_to_le32(length); - a->non_resident = 0; - a->name_length = name_len; - a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, u.res.resident_end)); - a->flags = flags; - a->instance = m->next_attr_instance; - a->u.res.value_length = cpu_to_le32(size); - a->u.res.value_offset = cpu_to_le16(length - ((size + 7) & ~7)); - if (val) - memcpy((u8*)a + le16_to_cpu(a->u.res.value_offset), val, size); - else - memset((u8*)a + le16_to_cpu(a->u.res.value_offset), 0, size); - if (type == AT_FILE_NAME) - a->u.res.resident_flags = RESIDENT_ATTR_IS_INDEXED; - else - a->u.res.resident_flags = 0; - if (name_len) - memcpy((u8*)a + le16_to_cpu(a->name_offset), - name, sizeof(ntfschar) * name_len); - m->next_attr_instance = - cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff); - if (ni->nr_extents == -1) - base_ni = ni->u.base_ni; - else - base_ni = ni; - if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) { - if (ntfs_attrlist_entry_add(ni, a)) { - err = errno; - ntfs_attr_record_resize(m, a, 0); - ntfs_log_trace("Failed add attribute entry to " - "ATTRIBUTE_LIST.\n"); - goto put_err_out; - } - } - ntfs_inode_mark_dirty(ni); - ntfs_attr_put_search_ctx(ctx); - return offset; -put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_non_resident_attr_record_add - add extent of non-resident attribute - * @ni: opened ntfs inode to which MFT record add attribute - * @type: type of the new attribute extent - * @name: name of the new attribute extent - * @name_len: name length of the new attribute extent - * @lowest_vcn: lowest vcn of the new attribute extent - * @dataruns_size: dataruns size of the new attribute extent - * @flags: flags of the new attribute extent - * - * Return offset to attribute from the beginning of the mft record on success - * and -1 on error. On error the error code is stored in errno. - * Possible error codes are: - * EINVAL - Invalid arguments passed to function. - * EEXIST - Attribute of such type, with same lowest vcn and with same - * name already exists. - * EIO - I/O error occurred or damaged filesystem. - */ -int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, - ATTR_FLAGS flags) -{ - ntfs_attr_search_ctx *ctx; - u32 length; - ATTR_RECORD *a; - MFT_RECORD *m; - ntfs_inode *base_ni; - int err, offset; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld, " - "dataruns_size %d, flags 0x%x.\n", - (long long) ni->mft_no, le32_to_cpu(type), - (long long) lowest_vcn, dataruns_size, - le16_to_cpu(flags)); - - if (!ni || dataruns_size <= 0 || (!name && name_len)) { - errno = EINVAL; - return -1; - } - - if (ntfs_attr_can_be_non_resident(ni->vol, type)) { - if (errno == EPERM) - ntfs_log_trace("Attribute can't be non resident.\n"); - else - ntfs_log_trace("ntfs_attr_can_be_non_resident() " - "failed.\n"); - return -1; - } - - /* Locate place where record should be. */ - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return -1; - /* - * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for - * attribute in @ni->mrec, not any extent inode in case if @ni is base - * file record. - */ - if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, NULL, 0, - ctx)) { - err = EEXIST; - ntfs_log_trace("Attribute already present.\n"); - goto put_err_out; - } - if (errno != ENOENT) { - err = EIO; - goto put_err_out; - } - a = ctx->attr; - m = ctx->mrec; - - /* Make room for attribute. */ - dataruns_size = (dataruns_size + 7) & ~7; - length = offsetof(ATTR_RECORD, u.nonres.compressed_size) + ((sizeof(ntfschar) * - name_len + 7) & ~7) + dataruns_size + - ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ? - sizeof(a->u.nonres.compressed_size) : 0); - if (ntfs_make_room_for_attr(ctx->mrec, (u8*) ctx->attr, length)) { - err = errno; - ntfs_log_trace("Failed to make room for attribute.\n"); - goto put_err_out; - } - - /* Setup record fields. */ - a->type = type; - a->length = cpu_to_le32(length); - a->non_resident = 1; - a->name_length = name_len; - a->name_offset = cpu_to_le16(offsetof(ATTR_RECORD, u.nonres.compressed_size) + - ((flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) ? - sizeof(a->u.nonres.compressed_size) : 0)); - a->flags = flags; - a->instance = m->next_attr_instance; - a->u.nonres.lowest_vcn = cpu_to_sle64(lowest_vcn); - a->u.nonres.mapping_pairs_offset = cpu_to_le16(length - dataruns_size); - a->u.nonres.compression_unit = (flags & ATTR_IS_COMPRESSED) ? 4 : 0; - /* If @lowest_vcn == 0, than setup empty attribute. */ - if (!lowest_vcn) { - a->u.nonres.highest_vcn = cpu_to_sle64(-1); - a->u.nonres.allocated_size = 0; - a->u.nonres.data_size = 0; - a->u.nonres.initialized_size = 0; - /* Set empty mapping pairs. */ - *((u8*)a + le16_to_cpu(a->u.nonres.mapping_pairs_offset)) = 0; - } - if (name_len) - memcpy((u8*)a + le16_to_cpu(a->name_offset), - name, sizeof(ntfschar) * name_len); - m->next_attr_instance = - cpu_to_le16((le16_to_cpu(m->next_attr_instance) + 1) & 0xffff); - if (ni->nr_extents == -1) - base_ni = ni->u.base_ni; - else - base_ni = ni; - if (type != AT_ATTRIBUTE_LIST && NInoAttrList(base_ni)) { - if (ntfs_attrlist_entry_add(ni, a)) { - err = errno; - ntfs_attr_record_resize(m, a, 0); - ntfs_log_trace("Failed add attribute entry to " - "ATTRIBUTE_LIST.\n"); - goto put_err_out; - } - } - ntfs_inode_mark_dirty(ni); - /* - * Locate offset from start of the MFT record where new attribute is - * placed. We need relookup it, because record maybe moved during - * update of attribute list. - */ - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, - lowest_vcn, NULL, 0, ctx)) { - err = errno; - ntfs_log_trace("Attribute lookup failed. Probably leaving " - "inconsistent metadata.\n"); - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; - } - offset = (u8*)ctx->attr - (u8*)ctx->mrec; - ntfs_attr_put_search_ctx(ctx); - return offset; -put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_attr_record_rm - remove attribute extent - * @ctx: search context describing the attribute which should be removed - * - * If this function succeed, user should reinit search context if he/she wants - * use it anymore. - * - * Return 0 on success and -1 on error. On error the error code is stored in - * errno. Possible error codes are: - * EINVAL - Invalid arguments passed to function. - * EIO - I/O error occurred or damaged filesystem. - */ -int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx) -{ - ntfs_inode *base_ni, *ni; - ATTR_TYPES type; - int err; - - if (!ctx || !ctx->ntfs_ino || !ctx->mrec || !ctx->attr) { - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", - (long long) ctx->ntfs_ino->mft_no, - (unsigned) le32_to_cpu(ctx->attr->type)); - type = ctx->attr->type; - ni = ctx->ntfs_ino; - if (ctx->base_ntfs_ino) - base_ni = ctx->base_ntfs_ino; - else - base_ni = ctx->ntfs_ino; - - /* Remove attribute itself. */ - if (ntfs_attr_record_resize(ctx->mrec, ctx->attr, 0)) { - ntfs_log_trace("Couldn't remove attribute record. " - "Bug or damaged MFT record.\n"); - if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) - if (ntfs_attrlist_entry_add(ni, ctx->attr)) - ntfs_log_trace("Rollback failed. Leaving " - "inconsistent metadata.\n"); - err = EIO; - return -1; - } - ntfs_inode_mark_dirty(ni); - - /* - * Remove record from $ATTRIBUTE_LIST if present and we don't want - * delete $ATTRIBUTE_LIST itself. - */ - if (NInoAttrList(base_ni) && type != AT_ATTRIBUTE_LIST) { - if (ntfs_attrlist_entry_rm(ctx)) { - ntfs_log_trace("Couldn't delete record from " - "$ATTRIBUTE_LIST.\n"); - return -1; - } - } - - /* Post $ATTRIBUTE_LIST delete setup. */ - if (type == AT_ATTRIBUTE_LIST) { - if (NInoAttrList(base_ni) && base_ni->attr_list) - free(base_ni->attr_list); - base_ni->attr_list = NULL; - NInoClearAttrList(base_ni); - NInoAttrListClearDirty(base_ni); - } - - /* Free MFT record, if it isn't contain attributes. */ - if (le32_to_cpu(ctx->mrec->bytes_in_use) - - le16_to_cpu(ctx->mrec->attrs_offset) == 8) { - if (ntfs_mft_record_free(ni->vol, ni)) { - // FIXME: We need rollback here. - ntfs_log_trace("Couldn't free MFT record.\n"); - errno = EIO; - return -1; - } - /* Remove done if we freed base inode. */ - if (ni == base_ni) - return 0; - } - - if (type == AT_ATTRIBUTE_LIST || !NInoAttrList(base_ni)) - return 0; - - /* Remove attribute list if we don't need it any more. */ - if (!ntfs_attrlist_need(base_ni)) { - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - /* - * FIXME: Should we succeed here? Definitely something - * goes wrong because NInoAttrList(base_ni) returned - * that we have got attribute list. - */ - ntfs_log_trace("Couldn't find attribute list. Succeed " - "anyway.\n"); - return 0; - } - /* Deallocate clusters. */ - if (ctx->attr->non_resident) { - runlist *al_rl; - - al_rl = ntfs_mapping_pairs_decompress(base_ni->vol, - ctx->attr, NULL); - if (!al_rl) { - ntfs_log_trace("Couldn't decompress attribute " - "list runlist. Succeed " - "anyway.\n"); - return 0; - } - if (ntfs_cluster_free_from_rl(base_ni->vol, al_rl)) { - ntfs_log_trace("Leaking clusters! Run chkdsk. " - "Couldn't free clusters from " - "attribute list runlist.\n"); - } - free(al_rl); - } - /* Remove attribute record itself. */ - if (ntfs_attr_record_rm(ctx)) { - /* - * FIXME: Should we succeed here? BTW, chkdsk doesn't - * complain if it find MFT record with attribute list, - * but without extents. - */ - ntfs_log_trace("Couldn't remove attribute list. " - "Succeed anyway.\n"); - return 0; - } - } - return 0; -} - -/** - * ntfs_attr_add - add attribute to inode - * @ni: opened ntfs inode to which add attribute - * @type: type of the new attribute - * @name: name in unicode of the new attribute - * @name_len: name length in unicode characters of the new attribute - * @val: value of new attribute - * @size: size of the new attribute / length of @val (if specified) - * - * @val should always be specified for always resident attributes (eg. FILE_NAME - * attribute), for attributes that can become non-resident @val can be NULL - * (eg. DATA attribute). @size can be specified even if @val is NULL, in this - * case data size will be equal to @size and initialized size will be equal - * to 0. - * - * If inode haven't got enough space to add attribute, add attribute to one of - * it extents, if no extents present or no one of them have enough space, than - * allocate new extent and add attribute to it. - * - * If on one of this steps attribute list is needed but not present, than it is - * added transparently to caller. So, this function should not be called with - * @type == AT_ATTRIBUTE_LIST, if you really need to add attribute list call - * ntfs_inode_add_attrlist instead. - * - * On success return 0. On error return -1 with errno set to the error code. - */ -int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, s64 size) -{ - u32 attr_rec_size; - int err, i, offset; - BOOL is_resident = TRUE; - BOOL always_non_resident = FALSE, always_resident = FALSE; - ntfs_inode *attr_ni; - ntfs_attr *na; - - if (!ni || size < 0 || type == AT_ATTRIBUTE_LIST) { - ntfs_log_trace("Invalid arguments passed.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr %x, size %lld.\n", - (long long) ni->mft_no, type, size); - - if (ni->nr_extents == -1) - ni = ni->u.base_ni; - - /* Check the attribute type and the size. */ - if (ntfs_attr_size_bounds_check(ni->vol, type, size)) { - if (errno == ERANGE) { - ntfs_log_trace("Size bounds check failed.\n"); - } else if (errno == ENOENT) { - ntfs_log_trace("Invalid attribute type. Aborting...\n"); - errno = EIO; - } - return -1; - } - - /* Sanity checks for always resident attributes. */ - if (ntfs_attr_can_be_non_resident(ni->vol, type)) { - if (errno != EPERM) { - err = errno; - ntfs_log_trace("ntfs_attr_can_be_non_resident() " - "failed.\n"); - goto err_out; - } - /* @val is mandatory. */ - if (!val) { - ntfs_log_trace("@val is mandatory for always resident " - "attributes.\n"); - errno = EINVAL; - return -1; - } - if (size > ni->vol->mft_record_size) { - ntfs_log_trace("Attribute is too big.\n"); - errno = ERANGE; - return -1; - } - always_resident = TRUE; - } - - /* Check whether attribute can be resident. */ - if (ntfs_attr_can_be_resident(ni->vol, type)) { - if (errno != EPERM) { - err = errno; - ntfs_log_trace("ntfs_attr_can_be_resident() failed.\n"); - goto err_out; - } - is_resident = FALSE; - always_non_resident = TRUE; - } - -retry: - /* Calculate attribute record size. */ - if (is_resident) - attr_rec_size = offsetof(ATTR_RECORD, u.res.resident_end) + - ROUND_UP(name_len * sizeof(ntfschar), 3) + - ROUND_UP(size, 3); - else /* We add 8 for space for mapping pairs. */ - attr_rec_size = offsetof(ATTR_RECORD, u.nonres.non_resident_end) + - ROUND_UP(name_len * sizeof(ntfschar), 3) + 8; - - /* - * If we have enough free space for the new attribute in the base MFT - * record, then add attribute to it. - */ - if (le32_to_cpu(ni->mrec->bytes_allocated) - - le32_to_cpu(ni->mrec->bytes_in_use) >= attr_rec_size) { - attr_ni = ni; - goto add_attr_record; - } - - /* Try to add to extent inodes. */ - if (ntfs_inode_attach_all_extents(ni)) { - err = errno; - ntfs_log_trace("Failed to attach all extents to inode.\n"); - goto err_out; - } - for (i = 0; i < ni->nr_extents; i++) { - attr_ni = ni->u.extent_nis[i]; - if (le32_to_cpu(attr_ni->mrec->bytes_allocated) - - le32_to_cpu(attr_ni->mrec->bytes_in_use) >= - attr_rec_size) - goto add_attr_record; - } - - /* - * If failed to find space for resident attribute, then try to find - * space for non resident one. - */ - if (is_resident && !always_resident) { - is_resident = FALSE; - goto retry; - } - - /* - * FIXME: Try to make other attributes non-resident here. Factor out - * code from ntfs_resident_attr_resize. - */ - - /* There is no extent that contain enough space for new attribute. */ - if (!NInoAttrList(ni)) { - /* Add attribute list not present, add it and retry. */ - if (ntfs_inode_add_attrlist(ni)) { - err = errno; - ntfs_log_trace("Failed to add attribute list.\n"); - goto err_out; - } - return ntfs_attr_add(ni, type, name, name_len, val, size); - } - /* Allocate new extent for attribute. */ - attr_ni = ntfs_mft_record_alloc(ni->vol, ni); - if (!attr_ni) { - err = errno; - ntfs_log_trace("Failed to allocate extent record.\n"); - goto err_out; - } - - /* - * Determine resident or not will be attribute using heuristics and - * calculate attribute record size. FIXME: small code duplication here. - */ - if (always_resident || (!always_non_resident && size < 256)) { - is_resident = TRUE; - attr_rec_size = offsetof(ATTR_RECORD, u.res.resident_end) + - ROUND_UP(name_len * sizeof(ntfschar), 3) + - ROUND_UP(size, 3); - } else { /* We add 8 for space for mapping pairs. */ - is_resident = FALSE; - attr_rec_size = offsetof(ATTR_RECORD, u.nonres.non_resident_end) + - ROUND_UP(name_len * sizeof(ntfschar), 3) + 8; - } - -add_attr_record: - if (is_resident) { - /* Add resident attribute. */ - offset = ntfs_resident_attr_record_add(attr_ni, type, name, - name_len, val, size, 0); - if (offset < 0) { - err = errno; - ntfs_log_trace("Failed to add resident attribute.\n"); - goto free_err_out; - } - return 0; - } - - /* Add non resident attribute. */ - offset = ntfs_non_resident_attr_record_add(attr_ni, type, name, - name_len, 0, 8, 0); - if (offset < 0) { - err = errno; - ntfs_log_trace("Failed to add non resident attribute.\n"); - goto free_err_out; - } - - /* If @size == 0, we are done. */ - if (!size) - return 0; - - /* Open new attribute and resize it. */ - na = ntfs_attr_open(ni, type, name, name_len); - if (!na) { - err = errno; - ntfs_log_trace("Failed to open just added attribute.\n"); - goto rm_attr_err_out; - } - /* Resize and set attribute value. */ - if (ntfs_attr_truncate(na, size) || - (val && (ntfs_attr_pwrite(na, 0, size, val) != size))) { - err = errno; - ntfs_log_trace("Failed to initialize just added attribute.\n"); - if (ntfs_attr_rm(na)) - ntfs_log_trace("Failed to remove just added attribute. " - "Probably leaving inconsistent " - "metadata.\n"); - goto err_out; - } - ntfs_attr_close(na); - /* Done !*/ - return 0; - -rm_attr_err_out: - /* Remove just added attribute. */ - if (ntfs_attr_record_resize(attr_ni->mrec, - (ATTR_RECORD*)((u8*)attr_ni->mrec + offset), 0)) { - ntfs_log_trace("Failed to remove just added attribute.\n"); - } -free_err_out: - /* Free MFT record, if it isn't contain attributes. */ - if (le32_to_cpu(attr_ni->mrec->bytes_in_use) - - le16_to_cpu(attr_ni->mrec->attrs_offset) == 8) { - if (ntfs_mft_record_free(attr_ni->vol, attr_ni)) { - ntfs_log_trace("Failed to free MFT record. Leaving " - "inconsistent metadata.\n"); - } - } -err_out: - errno = err; - return -1; -} - -/** - * ntfs_attr_rm - remove attribute from ntfs inode - * @na: opened ntfs attribute to delete - * - * Remove attribute and all it's extents from ntfs inode. If attribute was non - * resident also free all clusters allocated by attribute. This function always - * closes @na upon exit (both on success and failure). - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_attr_rm(ntfs_attr *na) -{ - ntfs_attr_search_ctx *ctx; - int ret = 0; - - if (!na) { - ntfs_log_trace("Invalid arguments passed.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", - (long long) na->ni->mft_no, na->type); - - /* Free cluster allocation. */ - if (NAttrNonResident(na)) { - if (ntfs_attr_map_whole_runlist(na)) { - ntfs_attr_close(na); - return -1; - } - if (ntfs_cluster_free(na->ni->vol, na, 0, -1) < 0) { - ntfs_log_trace("Failed to free cluster allocation. " - "Leaving inconsistent metadata.\n"); - ret = -1; - } - } - - /* Search for attribute extents and remove them all. */ - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) { - ntfs_attr_close(na); - return -1; - } - while (!ntfs_attr_lookup(na->type, na->name, na->name_len, - CASE_SENSITIVE, 0, NULL, 0, ctx)) { - if (ntfs_attr_record_rm(ctx)) { - ntfs_log_trace("Failed to remove attribute extent. " - "Leaving inconsistent metadata.\n"); - ret = -1; - } - ntfs_attr_reinit_search_ctx(ctx); - } - if (errno != ENOENT) { - ntfs_log_trace("Attribute lookup failed. " - "Probably leaving inconsistent metadata.\n"); - ret = -1; - } - - /* Throw away now non-exist attribute. */ - ntfs_attr_close(na); - /* Done. */ - return ret; -} - -/** - * ntfs_attr_record_resize - resize an attribute record - * @m: mft record containing attribute record - * @a: attribute record to resize - * @new_size: new size in bytes to which to resize the attribute record @a - * - * Resize the attribute record @a, i.e. the resident part of the attribute, in - * the mft record @m to @new_size bytes. - * - * Return 0 on success and -1 on error with errno set to the error code. - * The following error codes are defined: - * ENOSPC - Not enough space in the mft record @m to perform the resize. - * Note that on error no modifications have been performed whatsoever. - * - * Warning: If you make a record smaller without having copied all the data you - * are interested in the data may be overwritten! - */ -int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size) -{ - ntfs_log_trace("Entering for new_size %u.\n", (unsigned) new_size); - /* Align to 8 bytes, just in case the caller hasn't. */ - new_size = (new_size + 7) & ~7; - /* If the actual attribute length has changed, move things around. */ - if (new_size != le32_to_cpu(a->length)) { - u32 new_muse = le32_to_cpu(m->bytes_in_use) - - le32_to_cpu(a->length) + new_size; - /* Not enough space in this mft record. */ - if (new_muse > le32_to_cpu(m->bytes_allocated)) { - errno = ENOSPC; - return -1; - } - /* Move attributes following @a to their new location. */ - memmove((u8*)a + new_size, (u8*)a + le32_to_cpu(a->length), - le32_to_cpu(m->bytes_in_use) - ((u8*)a - - (u8*)m) - le32_to_cpu(a->length)); - /* Adjust @m to reflect the change in used space. */ - m->bytes_in_use = cpu_to_le32(new_muse); - /* Adjust @a to reflect the new size. */ - if (new_size >= offsetof(ATTR_REC, length) + sizeof(a->length)) - a->length = cpu_to_le32(new_size); - } - return 0; -} - -/** - * ntfs_resident_attr_value_resize - resize the value of a resident attribute - * @m: mft record containing attribute record - * @a: attribute record whose value to resize - * @new_size: new size in bytes to which to resize the attribute value of @a - * - * Resize the value of the attribute @a in the mft record @m to @new_size bytes. - * If the value is made bigger, the newly "allocated" space is cleared. - * - * Return 0 on success and -1 on error with errno set to the error code. - * The following error codes are defined: - * ENOSPC - Not enough space in the mft record @m to perform the resize. - * Note that on error no modifications have been performed whatsoever. - */ -int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a, - const u32 new_size) -{ - ntfs_log_trace("Entering for new size %u.\n", (unsigned)new_size); - - /* - * Check that the attribute name hasn't been placed after the - * attribute value. Chkdsk treat this as corruption. - */ - if (a->name_length && le16_to_cpu(a->name_offset) >= - le16_to_cpu(a->u.res.value_offset)) { - ntfs_log_trace("Name is placed after the attribute value. " - "Corrupted inode. Run chkdsk. Aborting...\n"); - errno = EIO; - return -1; - } - /* Resize the resident part of the attribute record. */ - if (ntfs_attr_record_resize(m, a, (le16_to_cpu(a->u.res.value_offset) + - new_size + 7) & ~7) < 0) { - if (errno != ENOSPC) { - int eo = errno; - ntfs_log_trace("Attribute record resize failed. " - "Aborting...\n"); - errno = eo; - } - return -1; - } - /* - * If we made the attribute value bigger, clear the area between the - * old size and @new_size. - */ - if (new_size > le32_to_cpu(a->u.res.value_length)) - memset((u8*)a + le16_to_cpu(a->u.res.value_offset) + - le32_to_cpu(a->u.res.value_length), 0, new_size - - le32_to_cpu(a->u.res.value_length)); - /* Finally update the length of the attribute value. */ - a->u.res.value_length = cpu_to_le32(new_size); - return 0; -} - -/** - * ntfs_attr_record_move_to - move attribute record to target inode - * @ctx: attribute search context describing the attribute record - * @ni: opened ntfs inode to which move attribute record - * - * If this function succeed, user should reinit search context if he/she wants - * use it anymore. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni) -{ - ntfs_attr_search_ctx *nctx; - ATTR_RECORD *a; - int err; - - if (!ctx || !ctx->attr || !ctx->ntfs_ino || !ni) { - ntfs_log_trace("Invalid arguments passed.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for ctx->attr->type 0x%x, " - "ctx->ntfs_ino->mft_no 0x%llx, ni->mft_no 0x%llx.\n", - (unsigned) le32_to_cpu(ctx->attr->type), - (long long) ctx->ntfs_ino->mft_no, - (long long) ni->mft_no); - - if (ctx->ntfs_ino == ni) - return 0; - - if (!ctx->al_entry) { - ntfs_log_trace("Inode should contain attribute list to use " - "this function.\n"); - errno = EINVAL; - return -1; - } - - /* Find place in MFT record where attribute will be moved. */ - a = ctx->attr; - nctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!nctx) { - ntfs_log_trace("Couldn't obtain search context.\n"); - return -1; - } - /* - * Use ntfs_attr_find instead of ntfs_attr_lookup to find place for - * attribute in @ni->mrec, not any extent inode in case if @ni is base - * file record. - */ - if (!ntfs_attr_find(a->type, (ntfschar*)((u8*)a + le16_to_cpu( - a->name_offset)), a->name_length, CASE_SENSITIVE, NULL, - 0, nctx)) { - ntfs_log_trace("Attribute of such type, with same name already " - "present in this MFT record.\n"); - err = EEXIST; - goto put_err_out; - } - if (errno != ENOENT) { - err = errno; - ntfs_log_debug("Attribute lookup failed.\n"); - goto put_err_out; - } - - /* Make space and move attribute. */ - if (ntfs_make_room_for_attr(ni->mrec, (u8*) nctx->attr, - le32_to_cpu(a->length))) { - err = errno; - ntfs_log_trace("Couldn't make space for attribute.\n"); - goto put_err_out; - } - memcpy(nctx->attr, a, le32_to_cpu(a->length)); - nctx->attr->instance = nctx->mrec->next_attr_instance; - nctx->mrec->next_attr_instance = cpu_to_le16( - (le16_to_cpu(nctx->mrec->next_attr_instance) + 1) & 0xffff); - ntfs_attr_record_resize(ctx->mrec, a, 0); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_inode_mark_dirty(ni); - - /* Update attribute list. */ - ctx->al_entry->mft_reference = - MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); - ctx->al_entry->instance = nctx->attr->instance; - ntfs_attrlist_mark_dirty(ni); - - ntfs_attr_put_search_ctx(nctx); - return 0; -put_err_out: - ntfs_attr_put_search_ctx(nctx); - errno = err; - return -1; -} - -/** - * ntfs_attr_record_move_away - move away attribute record from it's mft record - * @ctx: attribute search context describing the attribute record - * @extra: minimum amount of free space in the new holder of record - * - * New attribute record holder must have free @extra bytes after moving - * attribute record to it. - * - * If this function succeed, user should reinit search context if he/she wants - * use it anymore. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra) -{ - ntfs_inode *base_ni, *ni; - MFT_RECORD *m; - int i; - - if (!ctx || !ctx->attr || !ctx->ntfs_ino || extra < 0) { - ntfs_log_trace("Invalid arguments passed.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for attr 0x%x, inode 0x%llx.\n", - (unsigned) le32_to_cpu(ctx->attr->type), - (long long) ctx->ntfs_ino->mft_no); - - if (ctx->ntfs_ino->nr_extents == -1) - base_ni = ctx->base_ntfs_ino; - else - base_ni = ctx->ntfs_ino; - - if (!NInoAttrList(base_ni)) { - ntfs_log_trace("Inode should contain attribute list to use " - "this function.\n"); - errno = EINVAL; - return -1; - } - - if (ntfs_inode_attach_all_extents(ctx->ntfs_ino)) { - ntfs_log_trace("Couldn't attach extent inode.\n"); - return -1; - } - - /* Walk through all extents and try to move attribute to them. */ - for (i = 0; i < base_ni->nr_extents; i++) { - ni = base_ni->u.extent_nis[i]; - m = ni->mrec; - - if (ctx->ntfs_ino->mft_no == ni->mft_no) - continue; - - if (le32_to_cpu(m->bytes_allocated) - - le32_to_cpu(m->bytes_in_use) < - le32_to_cpu(ctx->attr->length) + extra) - continue; - - /* - * ntfs_attr_record_move_to can fail if extent with other lowest - * VCN already present in inode we trying move record to. So, - * do not return error. - */ - if (!ntfs_attr_record_move_to(ctx, ni)) - return 0; - } - - /* - * Failed to move attribute to one of the current extents, so allocate - * new extent and move attribute to it. - */ - ni = ntfs_mft_record_alloc(base_ni->vol, base_ni); - if (!ni) { - ntfs_log_trace("Couldn't allocate new MFT record.\n"); - return -1; - } - if (ntfs_attr_record_move_to(ctx, ni)) { - ntfs_log_trace("Couldn't move attribute to new MFT record.\n"); - return -1; - } - return 0; -} - -/** - * ntfs_attr_make_non_resident - convert a resident to a non-resident attribute - * @na: open ntfs attribute to make non-resident - * @ctx: ntfs search context describing the attribute - * - * Convert a resident ntfs attribute to a non-resident one. - * - * Return 0 on success and -1 on error with errno set to the error code. The - * following error codes are defined: - * EPERM - The attribute is not allowed to be non-resident. - * TODO: others... - * - * NOTE to self: No changes in the attribute list are required to move from - * a resident to a non-resident attribute. - * - * Warning: We do not set the inode dirty and we do not write out anything! - * We expect the caller to do this as this is a fairly low level - * function and it is likely there will be further changes made. - */ -static int ntfs_attr_make_non_resident(ntfs_attr *na, - ntfs_attr_search_ctx *ctx) -{ - s64 new_allocated_size, bw; - ntfs_volume *vol = na->ni->vol; - ATTR_REC *a = ctx->attr; - runlist *rl; - int mp_size, mp_ofs, name_ofs, arec_size; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long - long)na->ni->mft_no, na->type); - - /* Some preliminary sanity checking. */ - if (NAttrNonResident(na)) { - ntfs_log_trace("Eeek! Trying to make non-resident attribute " - "non-resident. Aborting...\n"); - errno = EINVAL; - return -1; - } - - /* Check that the attribute is allowed to be non-resident. */ - if (ntfs_attr_can_be_non_resident(vol, na->type)) - return -1; - - /* - * Check that the attribute name hasn't been placed after the - * attribute value. Chkdsk treat this as corruption. - */ - if (a->name_length && le16_to_cpu(a->name_offset) >= - le16_to_cpu(a->u.res.value_offset)) { - ntfs_log_trace("Name is placed after the attribute value. " - "Corrupted inode. Run chkdsk. Aborting...\n"); - errno = EIO; - return -1; - } - - new_allocated_size = (le32_to_cpu(a->u.res.value_length) + vol->cluster_size - - 1) & ~(vol->cluster_size - 1); - - if (new_allocated_size > 0) { - /* Start by allocating clusters to hold the attribute value. */ - rl = ntfs_cluster_alloc(vol, 0, new_allocated_size >> - vol->cluster_size_bits, -1, DATA_ZONE); - if (!rl) { - if (errno != ENOSPC) { - ntfs_log_trace("Eeek! Failed to allocate " - "cluster(s). Aborting...\n"); - } - return -1; - } - } else - rl = NULL; - /* - * Setup the in-memory attribute structure to be non-resident so that - * we can use ntfs_attr_pwrite(). - */ - NAttrSetNonResident(na); - na->rl = rl; - na->allocated_size = new_allocated_size; - na->data_size = na->initialized_size = le32_to_cpu(a->u.res.value_length); - /* - * FIXME: For now just clear all of these as we don't support them when - * writing. - */ - NAttrClearCompressed(na); - NAttrClearSparse(na); - NAttrClearEncrypted(na); - - if (rl) { - /* Now copy the attribute value to the allocated cluster(s). */ - bw = ntfs_attr_pwrite(na, 0, le32_to_cpu(a->u.res.value_length), - (u8*)a + le16_to_cpu(a->u.res.value_offset)); - if (bw != le32_to_cpu(a->u.res.value_length)) { - ntfs_log_debug("Failed to write out attribute value " - "(bw = %lli, errno = %i). " - "Aborting...\n", (long long)bw, errno); - if (bw >= 0) - errno = EIO; - goto cluster_free_err_out; - } - } - /* Determine the size of the mapping pairs array. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0); - if (mp_size < 0) { - ntfs_log_debug("Failed to get size for mapping pairs array. " - "Aborting...\n"); - goto cluster_free_err_out; - } - /* Calculate new offsets for the name and the mapping pairs array. */ - name_ofs = (sizeof(ATTR_REC) - sizeof(a->u.nonres.compressed_size) + 7) & ~7; - mp_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; - /* - * Determine the size of the resident part of the non-resident - * attribute record. (Not compressed thus no compressed_size element - * present.) - */ - arec_size = (mp_ofs + mp_size + 7) & ~7; - - /* Resize the resident part of the attribute record. */ - if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) { - if (errno != ENOSPC) { - ntfs_log_trace("Failed to resize attribute record. " - "Aborting...\n"); - } - goto cluster_free_err_out; - } - - /* - * Convert the resident part of the attribute record to describe a - * non-resident attribute. - */ - a->non_resident = 1; - - /* Move the attribute name if it exists and update the offset. */ - if (a->name_length) - memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), - a->name_length * sizeof(ntfschar)); - a->name_offset = cpu_to_le16(name_ofs); - - /* Update the flags to match the in-memory ones. */ - a->flags &= ~(ATTR_IS_SPARSE | ATTR_IS_ENCRYPTED | - ATTR_COMPRESSION_MASK); - - /* Setup the fields specific to non-resident attributes. */ - a->u.nonres.lowest_vcn = cpu_to_sle64(0); - a->u.nonres.highest_vcn = cpu_to_sle64((new_allocated_size - 1) >> - vol->cluster_size_bits); - - a->u.nonres.mapping_pairs_offset = cpu_to_le16(mp_ofs); - - a->u.nonres.compression_unit = 0; - - memset(&a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1)); - - a->u.nonres.allocated_size = cpu_to_sle64(new_allocated_size); - a->u.nonres.data_size = a->u.nonres.initialized_size = cpu_to_sle64(na->data_size); - - /* Generate the mapping pairs array in the attribute record. */ - if (ntfs_mapping_pairs_build(vol, (u8*)a + mp_ofs, arec_size - mp_ofs, - rl, 0, NULL) < 0) { - // FIXME: Eeek! We need rollback! (AIA) - ntfs_log_trace("Eeek! Failed to build mapping pairs. Leaving " - "corrupt attribute record on disk. In memory " - "runlist is still intact! Error code is %i. " - "FIXME: Need to rollback instead!\n", errno); - return -1; - } - - /* Done! */ - return 0; - -cluster_free_err_out: - if (rl && ntfs_cluster_free(vol, na, 0, -1) < 0) - ntfs_log_trace("Failed to release allocated clusters in error " - "code path. Leaving inconsistent metadata...\n"); - NAttrClearNonResident(na); - na->allocated_size = na->data_size; - na->rl = NULL; - free(rl); - return -1; -} - -/** - * ntfs_resident_attr_resize - resize a resident, open ntfs attribute - * @na: resident ntfs attribute to resize - * @newsize: new size (in bytes) to which to resize the attribute - * - * Change the size of a resident, open ntfs attribute @na to @newsize bytes. - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * ENOMEM - Not enough memory to complete operation. - * ERANGE - @newsize is not valid for the attribute type of @na. - * ENOSPC - There is no enough space on the volume to allocate - * new clusters or in base mft to resize $ATTRIBUTE_LIST. - * EOVERFLOW - Resident attribute can not become non resident and - * already filled whole MFT record, but had not reached - * @newsize bytes length. - */ -static int ntfs_resident_attr_resize(ntfs_attr *na, const s64 newsize) -{ - ntfs_attr_search_ctx *ctx; - ntfs_volume *vol; - ntfs_inode *ni; - int err; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, new size %lld.\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)newsize); - - /* Get the attribute record that needs modification. */ - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) - return -1; - if (ntfs_attr_lookup(na->type, na->name, na->name_len, 0, 0, NULL, 0, - ctx)) { - err = errno; - goto put_err_out; - } - vol = na->ni->vol; - /* - * Check the attribute type and the corresponding minimum and maximum - * sizes against @newsize and fail if @newsize is out of bounds. - */ - if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) { - err = errno; - if (err == ERANGE) { - ntfs_log_trace("Size bounds check failed. " - "Aborting...\n"); - } else if (err == ENOENT) - err = EIO; - goto put_err_out; - } - /* - * If @newsize is bigger than the MFT record we need to make the - * attribute non-resident if the attribute type supports it. If it is - * smaller we can go ahead and attempt the resize. - */ - if (newsize < vol->mft_record_size) { - /* Perform the resize of the attribute record. */ - if (!ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, - newsize)) { - /* Update attribute size everywhere. */ - na->data_size = na->initialized_size = newsize; - na->allocated_size = ROUND_UP(newsize, 3); - if (NAttrCompressed(na) || NAttrSparse(na)) - na->compressed_size = na->allocated_size; - if (na->type == AT_DATA && na->name == AT_UNNAMED) { - na->ni->data_size = na->data_size; - na->ni->allocated_size = na->allocated_size; - NInoFileNameSetDirty(na->ni); - } - goto resize_done; - } - /* Error! If not enough space, just continue. */ - if (errno != ENOSPC) { - err = errno; - ntfs_log_trace("Failed to resize resident part " - "of attribute. Aborting...\n"); - goto put_err_out; - } - } - /* There is not enough space in the MFT record to perform the resize. */ - - /* Make the attribute non-resident if possible. */ - if (!ntfs_attr_make_non_resident(na, ctx)) { - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - /* Resize non-resident attribute */ - return ntfs_attr_truncate(na, newsize); - } else if (errno != ENOSPC && errno != EPERM) { - err = errno; - ntfs_log_trace("Failed to make attribute non-resident. " - "Aborting...\n"); - goto put_err_out; - } - - /* Try to make other attributes non-resident and retry each time. */ - ntfs_attr_init_search_ctx(ctx, NULL, na->ni->mrec); - while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { - ntfs_attr *tna; - ATTR_RECORD *a; - - a = ctx->attr; - if (a->non_resident) - continue; - - /* - * Check out whether convert is reasonable. Assume that mapping - * pairs will take 8 bytes. - */ - if (le32_to_cpu(a->length) <= offsetof(ATTR_RECORD, - u.nonres.compressed_size) + ROUND_UP(a->name_length * - sizeof(ntfschar), 3) + 8) - continue; - - tna = ntfs_attr_open(na->ni, a->type, (ntfschar*)((u8*)a + - le16_to_cpu(a->name_offset)), a->name_length); - if (!tna) { - err = errno; - ntfs_log_trace("Couldn't open attribute.\n"); - goto put_err_out; - } - if (ntfs_attr_make_non_resident(tna, ctx)) { - ntfs_attr_close(tna); - continue; - } - ntfs_inode_mark_dirty(tna->ni); - ntfs_attr_close(tna); - ntfs_attr_put_search_ctx(ctx); - return ntfs_resident_attr_resize(na, newsize); - } - /* Check whether error occurred. */ - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto put_err_out; - } - - /* We can't move out attribute list, thus move out others. */ - if (na->type == AT_ATTRIBUTE_LIST) { - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD, - u.nonres.non_resident_end) + 8)) { - ntfs_log_trace("Couldn't free space in the MFT record " - "to make attribute list non " - "resident.\n"); - return -1; - } - return ntfs_resident_attr_resize(na, newsize); - } - - /* - * Move the attribute to a new MFT record, creating an attribute list - * attribute or modifying it if it is already present. - */ - - /* Point search context back to attribute which we need resize. */ - ntfs_attr_init_search_ctx(ctx, na->ni, NULL); - if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - ntfs_log_trace("Attribute lookup failed.\n"); - err = errno; - goto put_err_out; - } - - /* - * Force index allocation creation instead of moving out index root - * from the base MFT record. - */ - if (na->type == AT_INDEX_ROOT && na->data_size > sizeof(INDEX_ROOT) + - sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)) { - INDEX_ROOT *ir; - - ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - if (!(ir->index.flags & LARGE_INDEX)) { - err = EOVERFLOW; - goto put_err_out; - } - } - - /* - * Check whether attribute is already single in the this MFT record. - * 8 added for the attribute terminator. - */ - if (le32_to_cpu(ctx->mrec->bytes_in_use) == - le16_to_cpu(ctx->mrec->attrs_offset) + - le32_to_cpu(ctx->attr->length) + 8) { - err = EOVERFLOW; - goto put_err_out; - } - - /* Add attribute list if not present. */ - if (na->ni->nr_extents == -1) - ni = na->ni->u.base_ni; - else - ni = na->ni; - if (!NInoAttrList(ni)) { - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_add_attrlist(ni)) - return -1; - return ntfs_resident_attr_resize(na, newsize); - } - /* Allocate new MFT record. */ - ni = ntfs_mft_record_alloc(vol, ni); - if (!ni) { - err = errno; - ntfs_log_trace("Couldn't allocate new MFT record.\n"); - goto put_err_out; - } - /* Move attribute to it. */ - if (ntfs_attr_record_move_to(ctx, ni)) { - err = errno; - ntfs_log_trace("Couldn't move attribute to new MFT record.\n"); - goto put_err_out; - } - /* Update ntfs attribute. */ - if (na->ni->nr_extents == -1) - na->ni = ni; - - ntfs_attr_put_search_ctx(ctx); - /* Try to perform resize once again. */ - return ntfs_resident_attr_resize(na, newsize); - -resize_done: - /* - * Set the inode (and its base inode if it exists) dirty so it is - * written out later. - */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - /* Done! */ - ntfs_attr_put_search_ctx(ctx); - return 0; -put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_attr_make_resident - convert a non-resident to a resident attribute - * @na: open ntfs attribute to make resident - * @ctx: ntfs search context describing the attribute - * - * Convert a non-resident ntfs attribute to a resident one. - * - * Return 0 on success and -1 on error with errno set to the error code. The - * following error codes are defined: - * EINVAL - Invalid arguments passed. - * EPERM - The attribute is not allowed to be resident. - * EIO - I/O error, damaged inode or bug. - * ENOSPC - There is no enough space to perform conversion. - * EOPNOTSUPP - Requested conversion is not supported yet. - * - * Warning: We do not set the inode dirty and we do not write out anything! - * We expect the caller to do this as this is a fairly low level - * function and it is likely there will be further changes made. - */ -static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx) -{ - ntfs_volume *vol = na->ni->vol; - ATTR_REC *a = ctx->attr; - int name_ofs, val_ofs; - s64 arec_size, bytes_read; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long - long)na->ni->mft_no, na->type); - - /* Should be called for the first extent of the attribute. */ - if (sle64_to_cpu(a->u.nonres.lowest_vcn)) { - ntfs_log_trace("Should be called for the first extent of the " - "attribute. Aborting...\n"); - errno = EINVAL; - return -1; - } - - /* Some preliminary sanity checking. */ - if (!NAttrNonResident(na)) { - ntfs_log_trace("Trying to make resident attribute resident. " - "Aborting...\n"); - errno = EINVAL; - return -1; - } - - /* Make sure this is not $MFT/$BITMAP or Windows will not boot! */ - if (na->type == AT_BITMAP && na->ni->mft_no == FILE_MFT) { - errno = EPERM; - return -1; - } - - /* Check that the attribute is allowed to be resident. */ - if (ntfs_attr_can_be_resident(vol, na->type)) - return -1; - - /* - * Check that the attribute name hasn't been placed after the - * mapping pairs array. Chkdsk treat this as corruption. - */ - if (a->name_length && le16_to_cpu(a->name_offset) >= - le16_to_cpu(a->u.nonres.mapping_pairs_offset)) { - ntfs_log_trace("Damaged attribute. Name is placed after the " - "mapping pairs array. Run chkdsk. Aborting.\n"); - errno = EIO; - return -1; - } - - if (NAttrCompressed(na) || NAttrEncrypted(na)) { - ntfs_log_trace("Making compressed or encrypted files resident " - "is not implemented yet.\n"); - errno = EOPNOTSUPP; - return -1; - } - - /* Work out offsets into and size of the resident attribute. */ - name_ofs = 24; /* = sizeof(resident_ATTR_REC); */ - val_ofs = (name_ofs + a->name_length * sizeof(ntfschar) + 7) & ~7; - arec_size = (val_ofs + na->data_size + 7) & ~7; - - /* Sanity check the size before we start modifying the attribute. */ - if (le32_to_cpu(ctx->mrec->bytes_in_use) - le32_to_cpu(a->length) + - arec_size > le32_to_cpu(ctx->mrec->bytes_allocated)) { - ntfs_log_trace("Not enough space to make attribute resident\n"); - errno = ENOSPC; - return -1; - } - - /* Read and cache the whole runlist if not already done. */ - if (ntfs_attr_map_whole_runlist(na)) - return -1; - - /* Move the attribute name if it exists and update the offset. */ - if (a->name_length) { - memmove((u8*)a + name_ofs, (u8*)a + le16_to_cpu(a->name_offset), - a->name_length * sizeof(ntfschar)); - } - a->name_offset = cpu_to_le16(name_ofs); - - /* Resize the resident part of the attribute record. */ - if (ntfs_attr_record_resize(ctx->mrec, a, arec_size) < 0) { - /* - * Bug, because ntfs_attr_record_resize should not fail (we - * already checked that attribute fits MFT record). - */ - ntfs_log_error("BUG! Failed to resize attribute record. " - "Please report to the %s. Aborting...\n", - NTFS_DEV_LIST); - errno = EIO; - return -1; - } - - /* Convert the attribute record to describe a resident attribute. */ - a->non_resident = 0; - a->flags = 0; - a->u.res.value_length = cpu_to_le32(na->data_size); - a->u.res.value_offset = cpu_to_le16(val_ofs); - /* - * File names cannot be non-resident so we would never see this here - * but at least it serves as a reminder that there may be attributes - * for which we do need to set this flag. (AIA) - */ - if (a->type == AT_FILE_NAME) - a->u.res.resident_flags = RESIDENT_ATTR_IS_INDEXED; - else - a->u.res.resident_flags = 0; - a->u.res.reservedR = 0; - - /* Sanity fixup... Shouldn't really happen. (AIA) */ - if (na->initialized_size > na->data_size) - na->initialized_size = na->data_size; - - /* Copy data from run list to resident attribute value. */ - bytes_read = ntfs_rl_pread(vol, na->rl, 0, na->initialized_size, - (u8*)a + val_ofs); - if (bytes_read != na->initialized_size) { - if (bytes_read >= 0) - errno = EIO; - ntfs_log_trace("Eeek! Failed to read attribute data. Leaving " - "inconsistent metadata. Run chkdsk. " - "Aborting...\n"); - return -1; - } - - /* Clear memory in gap between initialized_size and data_size. */ - if (na->initialized_size < na->data_size) - memset((u8*)a + val_ofs + na->initialized_size, 0, - na->data_size - na->initialized_size); - - /* - * Deallocate clusters from the runlist. - * - * NOTE: We can use ntfs_cluster_free() because we have already mapped - * the whole run list and thus it doesn't matter that the attribute - * record is in a transiently corrupted state at this moment in time. - */ - if (ntfs_cluster_free(vol, na, 0, -1) < 0) { - ntfs_log_perror("Eeek! Failed to release allocated clusters"); - ntfs_log_trace("Ignoring error and leaving behind wasted " - "clusters.\n"); - } - - /* Throw away the now unused runlist. */ - free(na->rl); - na->rl = NULL; - - /* Update in-memory struct ntfs_attr. */ - NAttrClearNonResident(na); - NAttrClearCompressed(na); - NAttrClearSparse(na); - NAttrClearEncrypted(na); - na->initialized_size = na->data_size; - na->allocated_size = na->compressed_size = (na->data_size + 7) & ~7; - na->compression_block_size = 0; - na->compression_block_size_bits = na->compression_block_clusters = 0; - return 0; -} - -#define NTFS_VCN_DELETE_MARK -2 -/** - * ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute - * @na: non-resident ntfs open attribute for which we need update - * @from_vcn: update runlist starting this VCN - * - * Build mapping pairs from @na->rl and write them to the disk. Also, this - * function updates sparse bit, allocated and compressed size (allocates/frees - * space for this field if required). - * - * @na->allocated_size should be set to correct value for the new runlist before - * call to this function. Vice-versa @na->compressed_size will be calculated and - * set to correct value during this function. - * - * New runlist should be fully formed starting @from_vcn. Runs before @from_vcn - * can be mapped or not, but on-disk structures should not be modified before - * call to this function so they can be mapped if necessary. - * - * FIXME: Make it O(1) for sparse files too, not only for normal. - * - * FIXME: Rewrite without using NTFS_VCN_DELETE_MARK define. - * - * NOTE: Be careful in the future with updating bits on compressed files (at - * present assumed that on-disk flag is already set/cleared before call to - * this function). - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * EINVAL - Invalid arguments passed. - * ENOMEM - Not enough memory to complete operation. - * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST - * or there is no free MFT records left to allocate. - */ -int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn) -{ - ntfs_attr_search_ctx *ctx; - ntfs_inode *ni, *base_ni; - MFT_RECORD *m; - ATTR_RECORD *a; - VCN stop_vcn; - int err, mp_size, cur_max_mp_size, exp_max_mp_size; - BOOL finished_build; - -retry: - if (!na || !na->rl) { - ntfs_log_trace("Invalid parameters passed.\n"); - errno = EINVAL; - return -1; - } - - if (!NAttrNonResident(na)) { - ntfs_log_trace("Attribute should be non resident.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, from vcn 0x%lld." - "\n", (unsigned long long)na->ni->mft_no, na->type, - from_vcn); - - if (na->ni->nr_extents == -1) - base_ni = na->ni->u.base_ni; - else - base_ni = na->ni; - - ctx = ntfs_attr_get_search_ctx(base_ni, NULL); - if (!ctx) { - ntfs_log_trace("Couldn't get search context.\n"); - return -1; - } - - /* Fill attribute records with new mapping pairs. */ - stop_vcn = 0; - finished_build = FALSE; - while (!ntfs_attr_lookup(na->type, na->name, na->name_len, - CASE_SENSITIVE, ctx->is_first ? 0 : from_vcn, - NULL, 0, ctx)) { - a = ctx->attr; - m = ctx->mrec; - /* - * If runlist is updating not from the beginning, then set - * @stop_vcn properly, i.e. to the lowest vcn of record that - * contain @from_vcn. Also we do not need @from_vcn anymore, - * set it to 0 to make ntfs_attr_lookup enumerate attributes. - */ - if (from_vcn && a->u.nonres.lowest_vcn) { - LCN first_lcn; - - stop_vcn = sle64_to_cpu(a->u.nonres.lowest_vcn); - from_vcn = 0; - /* - * Check whether the first run we need to update is - * the last run in runlist, if so, then deallocate - * all attribute extents starting this one. - */ - first_lcn = ntfs_rl_vcn_to_lcn(na->rl, stop_vcn); - if (first_lcn == LCN_EINVAL) { - ntfs_log_trace("BUG! Incorrect runlist.\n"); - err = EIO; - goto put_err_out; - } - if (first_lcn == LCN_ENOENT || - first_lcn == LCN_RL_NOT_MAPPED) - finished_build = TRUE; - } - - /* - * Check whether we finished mapping pairs build, if so mark - * extent as need to delete (by setting highest vcn to - * NTFS_VCN_DELETE_MARK (-2), we shall check it later and - * delete extent) and continue search. - */ - if (finished_build) { - ntfs_log_trace("Mark attr 0x%x for delete in inode " - "0x%llx.\n", (unsigned)le32_to_cpu( - a->type), ctx->ntfs_ino->mft_no); - a->u.nonres.highest_vcn = cpu_to_sle64(NTFS_VCN_DELETE_MARK); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - continue; - } - - /* - * Check that the attribute name hasn't been placed after the - * mapping pairs array. Windows treat this as a corruption. - */ - if (a->name_length) { - if (le16_to_cpu(a->name_offset) >= - le16_to_cpu(a->u.nonres.mapping_pairs_offset)) { - ntfs_log_error("Damaged attribute. Name is " - "placed after the mapping " - "pairs array. Run chkdsk.\n"); - err = EIO; - goto put_err_out; - } - } - /* - * If we in the first extent, then set/clean sparse bit, - * update allocated and compressed size. - */ - if (!a->u.nonres.lowest_vcn) { - int sparse; - - /* Update allocated size. */ - a->u.nonres.allocated_size = cpu_to_sle64(na->allocated_size); - /* - * Check whether part of runlist we are updating is - * sparse. - */ - sparse = ntfs_rl_sparse(na->rl); - if (sparse == -1) { - ntfs_log_trace("Bad runlist.\n"); - err = errno; - goto put_err_out; - } - /* - * If new part or on-disk attribute is not sparse, then - * we should fully map runlist to make final decision. - */ - if (sparse || (a->flags & ATTR_IS_SPARSE)) { - if (from_vcn && ntfs_attr_map_runlist_range(na, - 0, from_vcn - 1)) { - ntfs_log_trace("Failed to map runlist " - "before @from_vcn.\n"); - err = errno; - goto put_err_out; - } - /* - * Reconsider whether whole runlist is sparse - * if new part is not. - */ - if (!sparse) { - sparse = ntfs_rl_sparse(na->rl); - if (sparse == -1) { - ntfs_log_trace("Bad " - "runlist.\n"); - err = errno; - goto put_err_out; - } - } - } - /* Attribute becomes sparse/compressed. */ - if (sparse && !(a->flags & (ATTR_IS_SPARSE | - ATTR_IS_COMPRESSED))) { - /* - * We need to move attribute to another mft - * record, if attribute is to small to add - * compressed_size field to it and we have no - * free space in the current mft record. - */ - if ((le32_to_cpu(a->length) - le16_to_cpu( - a->u.nonres.mapping_pairs_offset) - == 8) && !(le32_to_cpu( - m->bytes_allocated) - - le32_to_cpu(m->bytes_in_use))) { - if (!NInoAttrList(na->ni)) { - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_add_attrlist( - na->ni)) - return -1; - goto retry; - } - if (ntfs_attr_record_move_away(ctx, - 8)) { - ntfs_log_trace("Failed to move " - "attribute to another " - "extent. Aborting..\n"); - err = errno; - goto put_err_out; - } - ntfs_attr_put_search_ctx(ctx); - goto retry; - } - if (!(le32_to_cpu(a->length) - le16_to_cpu( - a->u.nonres.mapping_pairs_offset))) { - ntfs_log_trace("Size of the space " - "allocated for mapping " - "pairs should not be 0." - " Aborting ...\n"); - err = EIO; - goto put_err_out; - } - NAttrSetSparse(na); - a->flags |= ATTR_IS_SPARSE; - a->u.nonres.compression_unit = 4; /* Windows set it so, - even if attribute - is not actually - compressed. */ - memmove((u8*)a + le16_to_cpu(a->name_offset) + - 8, (u8*)a + le16_to_cpu(a->name_offset), - a->name_length * sizeof(ntfschar)); - a->name_offset = cpu_to_le16(le16_to_cpu( - a->name_offset) + 8); - a->u.nonres.mapping_pairs_offset = - cpu_to_le16(le16_to_cpu( - a->u.nonres.mapping_pairs_offset) + 8); - /* - * We should update all mapping pairs, because - * we shifted their starting position. - */ - from_vcn = 0; - } - /* Attribute becomes normal. */ - if (!sparse && (a->flags & ATTR_IS_SPARSE) && - !(a->flags & ATTR_IS_COMPRESSED)) { - NAttrClearSparse(na); - a->flags &= ~ATTR_IS_SPARSE; - a->u.nonres.compression_unit = 0; - memmove((u8*)a + le16_to_cpu(a->name_offset) - - 8, (u8*)a + le16_to_cpu(a->name_offset), - a->name_length * sizeof(ntfschar)); - /* - * Windows defragmentation tool do not update - * name offset correctly for unnamed - * attributes, but chkdsk do not like when it - * negative, so do not change it at all if it - * would become negative. - */ - if (le16_to_cpu(a->name_offset) >= 8) - a->name_offset = cpu_to_le16( - le16_to_cpu( - a->name_offset) - 8); - a->u.nonres.mapping_pairs_offset = - cpu_to_le16(le16_to_cpu( - a->u.nonres.mapping_pairs_offset) - 8); - /* - * We should update all mapping pairs, because - * we shifted their starting position. - */ - from_vcn = 0; - } - /* Update compressed size if required. */ - if (sparse || (a->flags & ATTR_IS_COMPRESSED)) { - s64 new_compr_size; - - new_compr_size = ntfs_rl_get_compressed_size( - na->ni->vol, na->rl); - if (new_compr_size == -1) { - err = errno; - ntfs_log_trace("BUG! Leaving " - "inconsistent " - "metadata.\n"); - goto put_err_out; - } - na->compressed_size = new_compr_size; - a->u.nonres.compressed_size = cpu_to_sle64( - new_compr_size); - } - /* - * Set FILE_NAME dirty flag, to update sparse bit and - * allocated size in the index. - */ - if (na->type == AT_DATA && na->name == AT_UNNAMED) { - if (sparse) - na->ni->allocated_size = - na->compressed_size; - else - na->ni->allocated_size = - na->allocated_size; - NInoFileNameSetDirty(na->ni); - } - - /* - * We do want to do anything for the first extent in - * case we are updating mapping pairs not from the - * begging. - */ - if (!a->u.nonres.highest_vcn || from_vcn <= - sle64_to_cpu(a->u.nonres.highest_vcn) + 1) - from_vcn = 0; - else { - if (from_vcn) - continue; - } - } - - /* Get the size for the rest of mapping pairs array. */ - mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, na->rl, - stop_vcn); - if (mp_size <= 0) { - err = errno; - ntfs_log_trace("Get size for mapping pairs failed.\n"); - goto put_err_out; - } - /* - * Determine maximum possible length of mapping pairs, - * if we shall *not* expand space for mapping pairs. - */ - cur_max_mp_size = le32_to_cpu(a->length) - - le16_to_cpu(a->u.nonres.mapping_pairs_offset); - /* - * Determine maximum possible length of mapping pairs in the - * current mft record, if we shall expand space for mapping - * pairs. - */ - exp_max_mp_size = le32_to_cpu(m->bytes_allocated) - - le32_to_cpu(m->bytes_in_use) + cur_max_mp_size; - /* Test mapping pairs for fitting in the current mft record. */ - if (mp_size > exp_max_mp_size) { - /* - * Mapping pairs of $ATTRIBUTE_LIST attribute must fit - * in the base mft record. Try to move out other - * attributes and try again. - */ - if (na->type == AT_ATTRIBUTE_LIST) { - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_free_space(na->ni, mp_size - - cur_max_mp_size)) { - if (errno != ENOSPC) - return -1; - ntfs_log_error("Attribute list mapping " - "pairs size to big, " - "can't fit them in the " - "base MFT record. " - "Defragment volume and " - "try once again.\n"); - errno = ENOSPC; - return -1; - } - goto retry; - } - - /* Add attribute list if it isn't present, and retry. */ - if (!NInoAttrList(base_ni)) { - ntfs_attr_put_search_ctx(ctx); - if (ntfs_inode_add_attrlist(base_ni)) { - ntfs_log_trace("Couldn't add attribute " - "list.\n"); - return -1; - } - goto retry; - } - - /* - * Set mapping pairs size to maximum possible for this - * mft record. We shall write the rest of mapping pairs - * to another MFT records. - */ - mp_size = exp_max_mp_size; - } - - /* Change space for mapping pairs if we need it. */ - if (((mp_size + 7) & ~7) != cur_max_mp_size) { - if (ntfs_attr_record_resize(m, a, - le16_to_cpu(a->u.nonres.mapping_pairs_offset) + - mp_size)) { - ntfs_log_error("BUG! Ran out of space in mft " - "record. Please run chkdsk and " - "if that doesn't find any " - "errors please report you saw " - "this message to %s.\n", - NTFS_DEV_LIST); - err = EIO; - goto put_err_out; - } - } - - /* Update lowest vcn. */ - a->u.nonres.lowest_vcn = cpu_to_sle64(stop_vcn); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - if ((ctx->ntfs_ino->nr_extents == -1 || - NInoAttrList(ctx->ntfs_ino)) && - ctx->attr->type != AT_ATTRIBUTE_LIST) { - ctx->al_entry->lowest_vcn = cpu_to_sle64(stop_vcn); - ntfs_attrlist_mark_dirty(ctx->ntfs_ino); - } - - /* - * Generate the new mapping pairs array directly into the - * correct destination, i.e. the attribute record itself. - */ - if (!ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + le16_to_cpu( - a->u.nonres.mapping_pairs_offset), mp_size, na->rl, - stop_vcn, &stop_vcn)) - finished_build = TRUE; - if (!finished_build && errno != ENOSPC) { - err = errno; - ntfs_log_error("BUG! Mapping pairs build failed. " - "Please run chkdsk and if that doesn't " - "find any errors please report you saw " - "this message to %s.\n", NTFS_DEV_LIST); - goto put_err_out; - } - a->u.nonres.highest_vcn = cpu_to_sle64(stop_vcn - 1); - } - /* Check whether error occurred. */ - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto put_err_out; - } - /* Sanity check. */ - if (from_vcn) { - err = ENOMSG; - ntfs_log_error("Library BUG! @from_vcn is nonzero, please " - "report to %s.\n", NTFS_DEV_LIST); - goto put_err_out; - } - - /* Deallocate not used attribute extents and return with success. */ - if (finished_build) { - ntfs_attr_reinit_search_ctx(ctx); - ntfs_log_trace("Deallocate marked extents.\n"); - while (!ntfs_attr_lookup(na->type, na->name, na->name_len, - CASE_SENSITIVE, 0, NULL, 0, ctx)) { - if (sle64_to_cpu(ctx->attr->u.nonres.highest_vcn) != - NTFS_VCN_DELETE_MARK) - continue; - /* Remove unused attribute record. */ - if (ntfs_attr_record_rm(ctx)) { - err = errno; - ntfs_log_trace("Couldn't remove unused " - "attribute record.\n"); - goto put_err_out; - } - ntfs_attr_reinit_search_ctx(ctx); - } - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto put_err_out; - } - ntfs_log_trace("Deallocate done.\n"); - ntfs_attr_put_search_ctx(ctx); - ntfs_log_trace("Done!"); - return 0; - } - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - - /* Allocate new MFT records for the rest of mapping pairs. */ - while (1) { - /* Calculate size of rest mapping pairs. */ - mp_size = ntfs_get_size_for_mapping_pairs(na->ni->vol, - na->rl, stop_vcn); - if (mp_size <= 0) { - err = errno; - ntfs_log_trace("Get size for mapping pairs failed.\n"); - goto put_err_out; - } - /* Allocate new mft record. */ - ni = ntfs_mft_record_alloc(na->ni->vol, base_ni); - if (!ni) { - err = errno; - ntfs_log_trace("Couldn't allocate new MFT record.\n"); - goto put_err_out; - } - m = ni->mrec; - /* - * If mapping size exceed available space, set them to - * possible maximum. - */ - cur_max_mp_size = le32_to_cpu(m->bytes_allocated) - - le32_to_cpu(m->bytes_in_use) - - (offsetof(ATTR_RECORD, u.nonres.compressed_size) + - ((NAttrCompressed(na) || NAttrSparse(na)) ? - sizeof(a->u.nonres.compressed_size) : 0)) - - ((sizeof(ntfschar) * na->name_len + 7) & ~7); - if (mp_size > cur_max_mp_size) - mp_size = cur_max_mp_size; - /* Add attribute extent to new record. */ - err = ntfs_non_resident_attr_record_add(ni, na->type, - na->name, na->name_len, stop_vcn, mp_size, 0); - if (err == -1) { - err = errno; - ntfs_log_trace("Couldn't add attribute extent into the " - "MFT record.\n"); - if (ntfs_mft_record_free(na->ni->vol, ni)) { - ntfs_log_trace("Couldn't free MFT record.\n"); - } - goto put_err_out; - } - a = (ATTR_RECORD*)((u8*)m + err); - - err = ntfs_mapping_pairs_build(na->ni->vol, (u8*)a + - le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp_size, na->rl, - stop_vcn, &stop_vcn); - if (err < 0 && errno != ENOSPC) { - err = errno; - ntfs_log_error("BUG! Mapping pairs build failed. " - "Please run chkdsk and if that doesn't " - "find any errors please report you saw " - "this message to %s.\n", NTFS_DEV_LIST); - if (ntfs_mft_record_free(na->ni->vol, ni)) - ntfs_log_trace("Couldn't free MFT record.\n"); - goto put_err_out; - } - a->u.nonres.highest_vcn = cpu_to_sle64(stop_vcn - 1); - ntfs_inode_mark_dirty(ni); - /* All mapping pairs has been written. */ - if (!err) - break; - } - ntfs_log_trace("Done!\n"); - return 0; -put_err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} -#undef NTFS_VCN_DELETE_MARK - -/** - * ntfs_non_resident_attr_shrink - shrink a non-resident, open ntfs attribute - * @na: non-resident ntfs attribute to shrink - * @newsize: new size (in bytes) to which to shrink the attribute - * - * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes. - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * ENOMEM - Not enough memory to complete operation. - * ERANGE - @newsize is not valid for the attribute type of @na. - */ -static int ntfs_non_resident_attr_shrink(ntfs_attr *na, const s64 newsize) -{ - ntfs_volume *vol; - ntfs_attr_search_ctx *ctx; - VCN first_free_vcn; - s64 nr_freed_clusters; - int err; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, newsize %lld.\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)newsize); - - vol = na->ni->vol; - - /* - * Check the attribute type and the corresponding minimum size - * against @newsize and fail if @newsize is too small. - */ - if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) { - if (errno == ERANGE) { - ntfs_log_trace("Eeek! Size bounds check failed. " - "Aborting...\n"); - } else if (errno == ENOENT) - errno = EIO; - return -1; - } - - /* The first cluster outside the new allocation. */ - first_free_vcn = (newsize + vol->cluster_size - 1) >> - vol->cluster_size_bits; - /* - * Compare the new allocation with the old one and only deallocate - * clusters if there is a change. - */ - if ((na->allocated_size >> vol->cluster_size_bits) != first_free_vcn) { - if (ntfs_attr_map_whole_runlist(na)) { - ntfs_log_trace("Eeek! ntfs_attr_map_whole_runlist " - "failed.\n"); - return -1; - } - /* Deallocate all clusters starting with the first free one. */ - nr_freed_clusters = ntfs_cluster_free(vol, na, first_free_vcn, - -1); - if (nr_freed_clusters < 0) { - ntfs_log_trace("Eeek! Freeing of clusters failed. " - "Aborting...\n"); - return -1; - } - - /* Truncate the runlist itself. */ - if (ntfs_rl_truncate(&na->rl, first_free_vcn)) { - err = errno; - /* - * Failed to truncate the runlist, so just throw it - * away, it will be mapped afresh on next use. - */ - free(na->rl); - na->rl = NULL; - ntfs_log_trace("Eeek! Run list truncation failed.\n"); - errno = err; - return -1; - } - - /* Prepare to mapping pairs update. */ - na->allocated_size = first_free_vcn << vol->cluster_size_bits; - /* Write mapping pairs for new runlist. */ - if (ntfs_attr_update_mapping_pairs(na, first_free_vcn)) { - ntfs_log_trace("Eeek! Mapping pairs update failed. " - "Leaving inconsistent metadata. " - "Run chkdsk.\n"); - return -1; - } - } - - /* Get the first attribute record. */ - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) { - ntfs_log_trace("Couldn't get attribute search context.\n"); - return -1; - } - if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - err = errno; - if (err == ENOENT) - err = EIO; - ntfs_log_trace("Eeek! Lookup of first attribute extent failed. " - "Leaving inconsistent metadata.\n"); - goto put_err_out; - } - - /* Update data and initialized size. */ - na->data_size = newsize; - ctx->attr->u.nonres.data_size = cpu_to_sle64(newsize); - if (newsize < na->initialized_size) { - na->initialized_size = newsize; - ctx->attr->u.nonres.initialized_size = cpu_to_sle64(newsize); - } - /* Update data size in the index. */ - if (na->type == AT_DATA && na->name == AT_UNNAMED) { - na->ni->data_size = na->data_size; - NInoFileNameSetDirty(na->ni); - } - - /* If the attribute now has zero size, make it resident. */ - if (!newsize) { - if (ntfs_attr_make_resident(na, ctx)) { - /* If couldn't make resident, just continue. */ - if (errno != EPERM) - ntfs_log_error("Failed to make attribute " - "resident. Leaving as is...\n"); - } - } - - /* Set the inode dirty so it is written out later. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - /* Done! */ - ntfs_attr_put_search_ctx(ctx); - return 0; -put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_non_resident_attr_expand - expand a non-resident, open ntfs attribute - * @na: non-resident ntfs attribute to expand - * @newsize: new size (in bytes) to which to expand the attribute - * @sparse: if TRUE then will create hole if possible - * - * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes, - * by allocating new clusters. - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * ENOMEM - Not enough memory to complete operation. - * ERANGE - @newsize is not valid for the attribute type of @na. - * ENOSPC - There is no enough space in base mft to resize $ATTRIBUTE_LIST. - */ -static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize, - BOOL sparse) -{ - VCN first_free_vcn; - ntfs_volume *vol; - ntfs_attr_search_ctx *ctx; - runlist *rl, *rln; - s64 org_alloc_size; - int err; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, new size %lld, " - "current size %lld.\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)newsize, (long long)na->data_size); - - vol = na->ni->vol; - - /* - * Check the attribute type and the corresponding maximum size - * against @newsize and fail if @newsize is too big. - */ - if (ntfs_attr_size_bounds_check(vol, na->type, newsize) < 0) { - if (errno == ERANGE) { - ntfs_log_trace("Eeek! Size bounds check failed. " - "Aborting...\n"); - } else if (errno == ENOENT) - errno = EIO; - return -1; - } - - /* Save for future use. */ - org_alloc_size = na->allocated_size; - /* The first cluster outside the new allocation. */ - first_free_vcn = (newsize + vol->cluster_size - 1) >> - vol->cluster_size_bits; - /* - * Compare the new allocation with the old one and only allocate - * clusters if there is a change. - */ - if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) { - /* Map required part of runlist. */ - if (ntfs_attr_map_runlist(na, na->allocated_size >> - vol->cluster_size_bits)) { - ntfs_log_error("Failed to map runlist.\n"); - return -1; - } - - /* - * If we extend $DATA attribute on NTFS 3+ volume, we can add - * sparse runs instead of real allocation of clusters. - */ - if (na->type == AT_DATA && vol->major_ver >= 3 && sparse) { - rl = ntfs_malloc(0x1000); - if (!rl) - return -1; - - rl[0].vcn = (na->allocated_size >> - vol->cluster_size_bits); - rl[0].lcn = LCN_HOLE; - rl[0].length = first_free_vcn - - (na->allocated_size >> vol->cluster_size_bits); - rl[1].vcn = first_free_vcn; - rl[1].lcn = LCN_ENOENT; - rl[1].length = 0; - } else { - /* - * Determine first after last LCN of attribute. - * We will start seek clusters from this LCN to avoid - * fragmentation. If there are no valid LCNs in the - * attribute let the cluster allocator choose the - * starting LCN. - */ - LCN lcn_seek_from; - - lcn_seek_from = -1; - if (na->rl->length) { - /* Seek to the last run list element. */ - for (rl = na->rl; (rl + 1)->length; rl++) - ; - /* - * If the last LCN is a hole or similar seek - * back to last valid LCN. - */ - while (rl->lcn < 0 && rl != na->rl) - rl--; - /* - * Only set lcn_seek_from it the LCN is valid. - */ - if (rl->lcn >= 0) - lcn_seek_from = rl->lcn + rl->length; - } - - rl = ntfs_cluster_alloc(vol, na->allocated_size >> - vol->cluster_size_bits, first_free_vcn - - (na->allocated_size >> - vol->cluster_size_bits), lcn_seek_from, - DATA_ZONE); - if (!rl) { - ntfs_log_trace("Cluster allocation failed.\n"); - return -1; - } - } - - /* Append new clusters to attribute runlist. */ - rln = ntfs_runlists_merge(na->rl, rl); - if (!rln) { - /* Failed, free just allocated clusters. */ - err = errno; - ntfs_log_trace("Run list merge failed.\n"); - ntfs_cluster_free_from_rl(vol, rl); - free(rl); - errno = err; - return -1; - } - na->rl = rln; - - /* Prepare to mapping pairs update. */ - na->allocated_size = first_free_vcn << vol->cluster_size_bits; - /* Write mapping pairs for new runlist. */ - if (ntfs_attr_update_mapping_pairs(na, org_alloc_size >> - vol->cluster_size_bits)) { - err = errno; - ntfs_log_trace("Mapping pairs update failed.\n"); - goto rollback; - } - } - - ctx = ntfs_attr_get_search_ctx(na->ni, NULL); - if (!ctx) { - ntfs_log_trace("Failed to get search context.\n"); - if (na->allocated_size == org_alloc_size) { - return -1; - } - err = errno; - goto rollback; - } - - if (ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - err = errno; - ntfs_log_trace("Lookup of first attribute extent failed.\n"); - if (err == ENOENT) - err = EIO; - if (na->allocated_size != org_alloc_size) { - ntfs_attr_put_search_ctx(ctx); - goto rollback; - } else - goto put_err_out; - } - - /* Update data size. */ - na->data_size = newsize; - ctx->attr->u.nonres.data_size = cpu_to_sle64(newsize); - /* Update data size in the index. */ - if (na->type == AT_DATA && na->name == AT_UNNAMED) { - na->ni->data_size = na->data_size; - NInoFileNameSetDirty(na->ni); - } - /* Set the inode dirty so it is written out later. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - /* Done! */ - ntfs_attr_put_search_ctx(ctx); - return 0; -rollback: - /* Free allocated clusters. */ - if (ntfs_cluster_free(vol, na, org_alloc_size >> - vol->cluster_size_bits, -1) < 0) { - ntfs_log_trace("Eeek! Leaking clusters. Run chkdsk!\n"); - err = EIO; - } - /* Now, truncate the runlist itself. */ - if (ntfs_rl_truncate(&na->rl, org_alloc_size >> - vol->cluster_size_bits)) { - /* - * Failed to truncate the runlist, so just throw it away, it - * will be mapped afresh on next use. - */ - free(na->rl); - na->rl = NULL; - ntfs_log_trace("Couldn't truncate runlist. Rollback failed.\n"); - } else { - /* Prepare to mapping pairs update. */ - na->allocated_size = org_alloc_size; - /* Restore mapping pairs. */ - if (ntfs_attr_update_mapping_pairs(na, na->allocated_size >> - vol->cluster_size_bits)) { - ntfs_log_trace("Failed to restore old mapping pairs. " - "Rollback failed.\n"); - } - } - errno = err; - return -1; -put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - - -/** - * __ntfs_attr_truncate - resize an ntfs attribute - * @na: open ntfs attribute to resize - * @newsize: new size (in bytes) to which to resize the attribute - * @sparse: if TRUE then will create hole if possible - * - * Change the size of an open ntfs attribute @na to @newsize bytes. If the - * attribute is made bigger and the attribute is resident the newly - * "allocated" space is cleared and if the attribute is non-resident the - * newly allocated space is marked as not initialised and no real allocation - * on disk is performed. - * - * On success return 0 and on error return -1 with errno set to the error code. - * The following error codes are defined: - * EINVAL - Invalid arguments were passed to the function. - * EACCES - Attribute is encrypted. - * ERANGE - @newsize is not valid for the attribute type of @na. - * ENOSPC - There is no enough space on the volume to allocate - * new clusters or in base mft to resize $ATTRIBUTE_LIST. - * EOVERFLOW - Resident attribute can not become non resident and - * already filled whole MFT record, but had not reached - * @newsize bytes length. - * EOPNOTSUPP - The desired resize is not implemented yet. - */ -int __ntfs_attr_truncate(ntfs_attr *na, const s64 newsize, BOOL sparse) -{ - int ret; - - if (!na || newsize < 0 || - (na->ni->mft_no == FILE_MFT && na->type == AT_DATA)) { - ntfs_log_trace("Invalid arguments passed.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long - long)na->ni->mft_no, na->type); - - if (na->data_size == newsize) - return 0; - /* - * Encrypted attributes are not supported. We return access denied, - * which is what Windows NT4 does, too. - */ - if (NAttrEncrypted(na)) { - errno = EACCES; - ntfs_log_trace("Failed (encrypted).\n"); - return -1; - } - /* - * TODO: Implement making handling of compressed attributes. - */ - if (NAttrCompressed(na)) { - errno = EOPNOTSUPP; - ntfs_log_trace("Failed (compressed).\n"); - return -1; - } - if (NAttrNonResident(na)) { - if (newsize > na->data_size) - ret = ntfs_non_resident_attr_expand(na, newsize, - sparse); - else - ret = ntfs_non_resident_attr_shrink(na, newsize); - } else - ret = ntfs_resident_attr_resize(na, newsize); - if (!ret) - ntfs_log_trace("Done!\n"); - else - ntfs_log_trace("Failed.\n"); - return ret; -} - - -/** - * Wrapper around __ntfs_attr_truncate that always tries to creates hole - */ -int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) -{ - return __ntfs_attr_truncate(na, newsize, TRUE); -} - - -/** - * ntfs_attr_readall - read the entire data from an ntfs attribute - * @ni: open ntfs inode in which the ntfs attribute resides - * @type: attribute type - * @name: attribute name in little endian Unicode or AT_UNNAMED or NULL - * @name_len: length of attribute @name in Unicode characters (if @name given) - * @data_size: if non-NULL then store here the data size - * - * This function will read the entire content of an ntfs attribute. - * If @name is AT_UNNAMED then look specifically for an unnamed attribute. - * If @name is NULL then the attribute could be either named or not. - * In both those cases @name_len is not used at all. - * - * On success a buffer is allocated with the content of the attribute - * and which needs to be freed when it's not needed anymore. If the - * @data_size parameter is non-NULL then the data size is set there. - * - * On error NULL is returned with errno set to the error code. - */ -void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len, s64 *data_size) -{ - ntfs_attr *na; - void *data, *ret = NULL; - s64 size; - - na = ntfs_attr_open(ni, type, name, name_len); - if (!na) { - ntfs_log_perror("ntfs_attr_open failed"); - return NULL; - } - data = ntfs_malloc(na->data_size); - if (!data) - goto out; - - size = ntfs_attr_pread(na, 0, na->data_size, data); - if (size != na->data_size) { - ntfs_log_perror("ntfs_attr_pread failed"); - free(data); - goto out; - } - ret = data; - if (data_size) - *data_size = size; -out: - ntfs_attr_close(na); - return ret; -} - -/** - * ntfs_attr_exist - FIXME: description - */ -int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, - u32 name_len) -{ - ntfs_attr_search_ctx *ctx; - int ret; - - ntfs_log_trace("Entering.\n"); - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return 0; - - ret = ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0, - ctx); - - ntfs_attr_put_search_ctx(ctx); - return !ret; -} diff --git a/usr/src/lib/libntfs/common/libntfs/attrlist.c b/usr/src/lib/libntfs/common/libntfs/attrlist.c deleted file mode 100644 index 3bbc6a3ca8..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/attrlist.c +++ /dev/null @@ -1,320 +0,0 @@ -/** - * attrlist.c - Attribute list attribute handling code. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2004-2005 Anton Altaparmakov - * Copyright (c) 2004-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "layout.h" -#include "attrib.h" -#include "attrlist.h" -#include "debug.h" -#include "unistr.h" -#include "logging.h" - -/** - * ntfs_attrlist_need - check whether inode need attribute list - * @ni: opened ntfs inode for which perform check - * - * Check whether all are attributes belong to one MFT record, in that case - * attribute list is not needed. - * - * Return 1 if inode need attribute list, 0 if not, -1 on error with errno set - * to the error code. If function succeed errno set to 0. The following error - * codes are defined: - * EINVAL - Invalid arguments passed to function or attribute haven't got - * attribute list. - */ -int ntfs_attrlist_need(ntfs_inode *ni) -{ - ATTR_LIST_ENTRY *ale; - - if (!ni) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - if (!NInoAttrList(ni)) { - ntfs_log_trace("Inode haven't got attribute list.\n"); - errno = EINVAL; - return -1; - } - - if (!ni->attr_list) { - ntfs_log_trace("Corrupt in-memory struct.\n"); - errno = EINVAL; - return -1; - } - - errno = 0; - ale = (ATTR_LIST_ENTRY *)ni->attr_list; - while ((u8*)ale < ni->attr_list + ni->attr_list_size) { - if (MREF_LE(ale->mft_reference) != ni->mft_no) - return 1; - ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length)); - } - return 0; -} - -/** - * ntfs_attrlist_entry_add - add an attribute list attribute entry - * @ni: opened ntfs inode, which contains that attribute - * @attr: attribute record to add to attribute list - * - * Return 0 on success and -1 on error with errno set to the error code. The - * following error codes are defined: - * EINVAL - Invalid arguments passed to function. - * ENOMEM - Not enough memory to allocate necessary buffers. - * EIO - I/O error occurred or damaged filesystem. - * EEXIST - Such attribute already present in attribute list. - */ -int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr) -{ - ATTR_LIST_ENTRY *ale; - leMFT_REF mref; - ntfs_attr *na = NULL; - ntfs_attr_search_ctx *ctx; - u8 *new_al; - int entry_len, entry_offset, err; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", - (long long) ni->mft_no, - (unsigned) le32_to_cpu(attr->type)); - - if (!ni || !attr) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number)); - - if (ni->nr_extents == -1) - ni = ni->u.base_ni; - - if (!NInoAttrList(ni)) { - ntfs_log_trace("Attribute list isn't present.\n"); - errno = ENOENT; - return -1; - } - - /* Determine size and allocate memory for new attribute list. */ - entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * - attr->name_length + 7) & ~7; - new_al = malloc(ni->attr_list_size + entry_len); - if (!new_al) { - ntfs_log_trace("Not enough memory.\n"); - err = ENOMEM; - return -1; - } - - /* Find place for the new entry. */ - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) { - err = errno; - ntfs_log_trace("Failed to obtain attribute search context.\n"); - goto err_out; - } - if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*) - ((u8*)attr + le16_to_cpu(attr->name_offset)) : - AT_UNNAMED, attr->name_length, CASE_SENSITIVE, - (attr->non_resident) ? sle64_to_cpu(attr->u.nonres.lowest_vcn) : - 0, (attr->non_resident) ? NULL : ((u8*)attr + - le16_to_cpu(attr->u.res.value_offset)), (attr->non_resident) ? - 0 : le32_to_cpu(attr->u.res.value_length), ctx)) { - /* Found some extent, check it to be before new extent. */ - if (ctx->al_entry->lowest_vcn == attr->u.nonres.lowest_vcn) { - err = EEXIST; - ntfs_log_trace("Such attribute already present in the " - "attribute list.\n"); - ntfs_attr_put_search_ctx(ctx); - goto err_out; - } - /* Add new entry after this extent. */ - ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry + - le16_to_cpu(ctx->al_entry->length)); - } else { - /* Check for real errors. */ - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - ntfs_attr_put_search_ctx(ctx); - goto err_out; - } - /* No previous extents found. */ - ale = ctx->al_entry; - } - /* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */ - ntfs_attr_put_search_ctx(ctx); - - /* Determine new entry offset. */ - entry_offset = ((u8 *)ale - ni->attr_list); - /* Set pointer to new entry. */ - ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset); - /* Form new entry. */ - ale->type = attr->type; - ale->length = cpu_to_le16(entry_len); - ale->name_length = attr->name_length; - ale->name_offset = offsetof(ATTR_LIST_ENTRY, name); - if (attr->non_resident) - ale->lowest_vcn = attr->u.nonres.lowest_vcn; - else - ale->lowest_vcn = 0; - ale->mft_reference = mref; - ale->instance = attr->instance; - NTFS_ON_DEBUG(memset(ale->name, 0, ((u8*)((u8*)ale + entry_len)) - - ((u8*)ale->name))); /* Shut up, valgrind. */ - memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset), - attr->name_length * sizeof(ntfschar)); - - /* Resize $ATTRIBUTE_LIST to new length. */ - na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); - if (!na) { - err = errno; - ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); - goto err_out; - } - if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) { - err = errno; - ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); - goto err_out; - } - - /* Copy entries from old attribute list to new. */ - memcpy(new_al, ni->attr_list, entry_offset); - memcpy(new_al + entry_offset + entry_len, ni->attr_list + - entry_offset, ni->attr_list_size - entry_offset); - - /* Set new runlist. */ - free(ni->attr_list); - ni->attr_list = new_al; - ni->attr_list_size = ni->attr_list_size + entry_len; - NInoAttrListSetDirty(ni); - /* Done! */ - ntfs_attr_close(na); - return 0; -err_out: - if (na) - ntfs_attr_close(na); - free(new_al); - errno = err; - return -1; -} - -/** - * ntfs_attrlist_entry_rm - remove an attribute list attribute entry - * @ctx: attribute search context describing the attribute list entry - * - * Remove the attribute list entry @ctx->al_entry from the attribute list. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx) -{ - u8 *new_al; - int new_al_len; - ntfs_inode *base_ni; - ntfs_attr *na; - ATTR_LIST_ENTRY *ale; - int err; - - if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - if (ctx->base_ntfs_ino) - base_ni = ctx->base_ntfs_ino; - else - base_ni = ctx->ntfs_ino; - ale = ctx->al_entry; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld." - "\n", (long long) ctx->ntfs_ino->mft_no, - (unsigned) le32_to_cpu(ctx->al_entry->type), - (long long) sle64_to_cpu(ctx->al_entry->lowest_vcn)); - - if (!NInoAttrList(base_ni)) { - ntfs_log_trace("Attribute list isn't present.\n"); - errno = ENOENT; - return -1; - } - - /* Allocate memory for new attribute list. */ - new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length); - new_al = malloc(new_al_len); - if (!new_al) { - ntfs_log_trace("Not enough memory.\n"); - errno = ENOMEM; - return -1; - } - - /* Reisze $ATTRIBUTE_LIST to new length. */ - na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); - if (!na) { - err = errno; - ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n"); - goto err_out; - } - if (ntfs_attr_truncate(na, new_al_len)) { - err = errno; - ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n"); - goto err_out; - } - - /* Copy entries from old attribute list to new. */ - memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list); - memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu( - ale->length), new_al_len - ((u8*)ale - base_ni->attr_list)); - - /* Set new runlist. */ - free(base_ni->attr_list); - base_ni->attr_list = new_al; - base_ni->attr_list_size = new_al_len; - NInoAttrListSetDirty(base_ni); - /* Done! */ - ntfs_attr_close(na); - return 0; -err_out: - if (na) - ntfs_attr_close(na); - free(new_al); - errno = err; - return -1; -} diff --git a/usr/src/lib/libntfs/common/libntfs/bitmap.c b/usr/src/lib/libntfs/common/libntfs/bitmap.c deleted file mode 100644 index 2f7d6bb84a..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/bitmap.c +++ /dev/null @@ -1,249 +0,0 @@ -/** - * bitmap.c - Bitmap handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2006 Anton Altaparmakov - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "bitmap.h" -#include "debug.h" -#include "logging.h" - -/** - * ntfs_bitmap_set_bits_in_run - set a run of bits in a bitmap to a value - * @na: attribute containing the bitmap - * @start_bit: first bit to set - * @count: number of bits to set - * @value: value to set the bits to (i.e. 0 or 1) - * - * Set @count bits starting at bit @start_bit in the bitmap described by the - * attribute @na to @value, where @value is either 0 or 1. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -static int ntfs_bitmap_set_bits_in_run(ntfs_attr *na, s64 start_bit, - s64 count, int value) -{ - ntfs_volume *vol = na->ni->vol; - s64 bufsize, br, left = count; - u8 *buf, *lastbyte_buf; - int bit, firstbyte, lastbyte, lastbyte_pos, tmp, err; - - if (!na || start_bit < 0 || count < 0) { - errno = EINVAL; - return -1; - } - - bit = start_bit & 7; - if (bit) - firstbyte = 1; - else - firstbyte = 0; - - /* Calculate the required buffer size in bytes, capping it at 8kiB. */ - bufsize = ((count - (bit ? 8 - bit : 0) + 7) >> 3) + firstbyte; - if (bufsize > 8192) - bufsize = 8192; - - buf = (u8*)ntfs_malloc(bufsize); - if (!buf) - return -1; - - /* Depending on @value, zero or set all bits in the allocated buffer. */ - memset(buf, value ? 0xff : 0, bufsize); - - /* If there is a first partial byte... */ - if (bit) { - /* read it in... */ - br = ntfs_attr_pread(na, start_bit >> 3, 1, buf); - if (br != 1) { - free(buf); - errno = EIO; - return -1; - } - /* and set or clear the appropriate bits in it. */ - while ((bit & 7) && left--) { - if (value) - *buf |= 1 << bit++; - else - *buf &= ~(1 << bit++); - } - /* Update @start_bit to the new position. */ - start_bit = (start_bit + 7) & ~7; - } - - /* Loop until @left reaches zero. */ - lastbyte = 0; - lastbyte_buf = NULL; - bit = left & 7; - do { - /* If there is a last partial byte... */ - if (left > 0 && bit) { - lastbyte_pos = ((left + 7) >> 3) + firstbyte; - if (!lastbyte_pos) { - // FIXME: Eeek! BUG! - ntfs_log_trace("lastbyte is zero. Leaving " - "inconsistent metadata.\n"); - err = EIO; - goto free_err_out; - } - /* and it is in the currently loaded bitmap window... */ - if (lastbyte_pos <= bufsize) { - lastbyte_buf = buf + lastbyte_pos - 1; - - /* read the byte in... */ - br = ntfs_attr_pread(na, (start_bit + left) >> - 3, 1, lastbyte_buf); - if (br != 1) { - // FIXME: Eeek! We need rollback! (AIA) - ntfs_log_trace("Read of last byte " - "failed. Leaving " - "inconsistent " - "metadata.\n"); - err = EIO; - goto free_err_out; - } - /* and set/clear the appropriate bits in it. */ - while (bit && left--) { - if (value) - *lastbyte_buf |= 1 << --bit; - else - *lastbyte_buf &= ~(1 << --bit); - } - /* We don't want to come back here... */ - bit = 0; - /* We have a last byte that we have handled. */ - lastbyte = 1; - } - } - - /* Write the prepared buffer to disk. */ - tmp = (start_bit >> 3) - firstbyte; - br = ntfs_attr_pwrite(na, tmp, bufsize, buf); - if (br != bufsize) { - // FIXME: Eeek! We need rollback! (AIA) - ntfs_log_trace("Failed to write buffer to bitmap. " - "Leaving inconsistent metadata.\n"); - err = EIO; - goto free_err_out; - } - - /* Update counters. */ - tmp = (bufsize - firstbyte - lastbyte) << 3; - if (firstbyte) { - firstbyte = 0; - /* - * Re-set the partial first byte so a subsequent write - * of the buffer does not have stale, incorrect bits. - */ - *buf = value ? 0xff : 0; - } - start_bit += tmp; - left -= tmp; - if (bufsize > (tmp = (left + 7) >> 3)) - bufsize = tmp; - - if (lastbyte && left != 0) { - // FIXME: Eeek! BUG! - ntfs_log_trace("Last buffer but count is not zero (= " - "%lli). Leaving inconsistent metadata." - "\n", (long long)left); - err = EIO; - goto free_err_out; - } - } while (left > 0); - - /* Update free clusters and MFT records. */ - if (na == vol->mftbmp_na) { - if (value) - vol->nr_free_mft_records -= count; - else - vol->nr_free_mft_records += count; - } - if (na == vol->lcnbmp_na) { - if (value) - vol->nr_free_clusters -= count; - else - vol->nr_free_clusters += count; - } - - /* Done! */ - free(buf); - return 0; - -free_err_out: - free(buf); - errno = err; - return -1; -} - -/** - * ntfs_bitmap_set_run - set a run of bits in a bitmap - * @na: attribute containing the bitmap - * @start_bit: first bit to set - * @count: number of bits to set - * - * Set @count bits starting at bit @start_bit in the bitmap described by the - * attribute @na. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_bitmap_set_run(ntfs_attr *na, s64 start_bit, s64 count) -{ - return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 1); -} - -/** - * ntfs_bitmap_clear_run - clear a run of bits in a bitmap - * @na: attribute containing the bitmap - * @start_bit: first bit to clear - * @count: number of bits to clear - * - * Clear @count bits starting at bit @start_bit in the bitmap described by the - * attribute @na. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count) -{ - ntfs_log_trace("Dealloc from bit 0x%llx, count 0x%llx.\n", - (long long)start_bit, (long long)count); - - return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0); -} - diff --git a/usr/src/lib/libntfs/common/libntfs/bootsect.c b/usr/src/lib/libntfs/common/libntfs/bootsect.c deleted file mode 100644 index 3c4e9ca9b2..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/bootsect.c +++ /dev/null @@ -1,273 +0,0 @@ -/** - * bootsect.c - Boot sector handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * Copyright (c) 2005 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "bootsect.h" -#include "debug.h" -#include "logging.h" - -/** - * ntfs_boot_sector_is_ntfs - check if buffer contains a valid ntfs boot sector - * @b: buffer containing putative boot sector to analyze - * @silent: if zero, output progress messages to stderr - * - * Check if the buffer @b contains a valid ntfs boot sector. The buffer @b - * must be at least 512 bytes in size. - * - * If @silent is zero, output progress messages to stderr. Otherwise, do not - * output any messages (except when configured with --enable-debug in which - * case warning/debug messages may be displayed). - * - * Return TRUE if @b contains a valid ntfs boot sector and FALSE if not. - */ -BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b, - const BOOL silent __attribute__((unused))) -{ - u32 i; - - ntfs_log_debug("\nBeginning bootsector check...\n"); - - /* - * Check that checksum == sum of u32 values from b to the checksum - * field. If checksum is zero, no checking is done. We will work when - * the checksum test fails, since some utilities update the boot sector - * ignoring the checksum which leaves the checksum out-of-date. We - * report a warning if this is the case. - */ - if ((void*)b < (void*)&b->checksum && b->checksum) { - u32 *u = (u32 *)b; - u32 *bi = (u32 *)(&b->checksum); - - ntfs_log_debug("Calculating bootsector checksum... "); - for (i = 0; u < bi; ++u) - i += le32_to_cpup(u); - if (le32_to_cpu(b->checksum) && le32_to_cpu(b->checksum) != i) { - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("The NTFS bootsector contains an " - "incorrect checksum."); - } else - ntfs_log_debug("OK\n"); - } - - /* Check OEMidentifier is "NTFS " */ - ntfs_log_debug("Checking OEMid... "); - if (b->oem_id != NTFS_SB_MAGIC) /* "NTFS " */ - goto not_ntfs; - ntfs_log_debug("OK\n"); - - /* Check bytes per sector value is between 256 and 4096. */ - ntfs_log_debug("Checking bytes per sector... "); - if (le16_to_cpu(b->bpb.bytes_per_sector) < 0x100 || - le16_to_cpu(b->bpb.bytes_per_sector) > 0x1000) - goto not_ntfs; - ntfs_log_debug("OK\n"); - - /* Check sectors per cluster value is valid. */ - ntfs_log_debug("Checking sectors per cluster... "); - switch (b->bpb.sectors_per_cluster) { - case 1: case 2: case 4: case 8: case 16: case 32: case 64: case 128: - break; - default: - goto not_ntfs; - } - ntfs_log_debug("OK\n"); - - /* Check the cluster size is not above 65536 bytes. */ - ntfs_log_debug("Checking cluster size... "); - if ((u32)le16_to_cpu(b->bpb.bytes_per_sector) * - b->bpb.sectors_per_cluster > 0x10000) - goto not_ntfs; - ntfs_log_debug("OK\n"); - - /* Check reserved/unused fields are really zero. */ - ntfs_log_debug("Checking reserved fields are zero... "); - if (le16_to_cpu(b->bpb.reserved_sectors) || - le16_to_cpu(b->bpb.root_entries) || - le16_to_cpu(b->bpb.sectors) || - le16_to_cpu(b->bpb.sectors_per_fat) || - le32_to_cpu(b->bpb.large_sectors) || - b->bpb.fats) - goto not_ntfs; - ntfs_log_debug("OK\n"); - - /* Check clusters per file mft record value is valid. */ - ntfs_log_debug("Checking clusters per mft record... "); - if ((u8)b->clusters_per_mft_record < 0xe1 || - (u8)b->clusters_per_mft_record > 0xf7) { - switch (b->clusters_per_mft_record) { - case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: - break; - default: - goto not_ntfs; - } - } - ntfs_log_debug("OK\n"); - - /* Check clusters per index block value is valid. */ - ntfs_log_debug("Checking clusters per index block... "); - if ((u8)b->clusters_per_index_record < 0xe1 || - (u8)b->clusters_per_index_record > 0xf7) { - switch (b->clusters_per_index_record) { - case 1: case 2: case 4: case 8: case 0x10: case 0x20: case 0x40: - break; - default: - goto not_ntfs; - } - } - ntfs_log_debug("OK\n"); - - if (b->end_of_sector_marker != cpu_to_le16(0xaa55)) - ntfs_log_debug("Warning: Bootsector has invalid end of sector " - "marker.\n"); - - ntfs_log_debug("Bootsector check completed successfully.\n"); - return TRUE; -not_ntfs: - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("Bootsector check failed. Aborting...\n"); - return FALSE; -} - -/** - * ntfs_boot_sector_parse - setup an ntfs volume from an ntfs boot sector - * @vol: ntfs_volume to setup - * @bs: buffer containing ntfs boot sector to parse - * - * Parse the ntfs bootsector @bs and setup the ntfs volume @vol with the - * obtained values. - * - * Return 0 on success or -1 on error with errno set to the error code EINVAL. - */ -int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) -{ - u8 sectors_per_cluster; - s8 c; - - /* We return -1 with errno = EINVAL on error. */ - errno = EINVAL; - - vol->sector_size = le16_to_cpu(bs->bpb.bytes_per_sector); - vol->sector_size_bits = ffs(vol->sector_size) - 1; - ntfs_log_debug("SectorSize = 0x%x\n", vol->sector_size); - ntfs_log_debug("SectorSizeBits = %u\n", vol->sector_size_bits); - /* - * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being - * below or equal the number_of_clusters) really belong in the - * ntfs_boot_sector_is_ntfs but in this way we can just do this once. - */ - sectors_per_cluster = bs->bpb.sectors_per_cluster; - ntfs_log_debug("NumberOfSectors = %lli\n", - sle64_to_cpu(bs->number_of_sectors)); - ntfs_log_debug("SectorsPerCluster = 0x%x\n", sectors_per_cluster); - if (sectors_per_cluster & (sectors_per_cluster - 1)) { - ntfs_log_debug("Error: %s is not a valid NTFS partition! " - "sectors_per_cluster is not a power of 2.\n", - vol->u.dev->d_name); - return -1; - } - vol->nr_clusters = sle64_to_cpu(bs->number_of_sectors) >> - (ffs(sectors_per_cluster) - 1); - - vol->mft_lcn = sle64_to_cpu(bs->mft_lcn); - vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn); - ntfs_log_debug("MFT LCN = 0x%llx\n", vol->mft_lcn); - ntfs_log_debug("MFTMirr LCN = 0x%llx\n", vol->mftmirr_lcn); - if (vol->mft_lcn > vol->nr_clusters || - vol->mftmirr_lcn > vol->nr_clusters) { - ntfs_log_debug("Error: %s is not a valid NTFS partition!\n", - vol->u.dev->d_name); - ntfs_log_debug("($Mft LCN or $MftMirr LCN is greater than the " - "number of clusters!)\n"); - return -1; - } - vol->cluster_size = sectors_per_cluster * vol->sector_size; - if (vol->cluster_size & (vol->cluster_size - 1)) { - ntfs_log_debug("Error: %s is not a valid NTFS partition! " - "cluster_size is not a power of 2.\n", - vol->u.dev->d_name); - return -1; - } - vol->cluster_size_bits = ffs(vol->cluster_size) - 1; - /* - * Need to get the clusters per mft record and handle it if it is - * negative. Then calculate the mft_record_size. A value of 0x80 is - * illegal, thus signed char is actually ok! - */ - c = bs->clusters_per_mft_record; - ntfs_log_debug("ClusterSize = 0x%x\n", (unsigned)vol->cluster_size); - ntfs_log_debug("ClusterSizeBits = %u\n", vol->cluster_size_bits); - ntfs_log_debug("ClustersPerMftRecord = 0x%x\n", c); - /* - * When clusters_per_mft_record is negative, it means that it is to - * be taken to be the negative base 2 logarithm of the mft_record_size - * min bytes. Then: - * mft_record_size = 2^(-clusters_per_mft_record) bytes. - */ - if (c < 0) - vol->mft_record_size = 1 << -c; - else - vol->mft_record_size = c << vol->cluster_size_bits; - if (vol->mft_record_size & (vol->mft_record_size - 1)) { - ntfs_log_debug("Error: %s is not a valid NTFS partition! " - "mft_record_size is not a power of 2.\n", - vol->u.dev->d_name); - return -1; - } - vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; - ntfs_log_debug("MftRecordSize = 0x%x\n", - (unsigned)vol->mft_record_size); - ntfs_log_debug("MftRecordSizeBits = %u\n", vol->mft_record_size_bits); - /* Same as above for INDX record. */ - c = bs->clusters_per_index_record; - ntfs_log_debug("ClustersPerINDXRecord = 0x%x\n", c); - if (c < 0) - vol->indx_record_size = 1 << -c; - else - vol->indx_record_size = c << vol->cluster_size_bits; - vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1; - ntfs_log_debug("INDXRecordSize = 0x%x\n", - (unsigned)vol->indx_record_size); - ntfs_log_debug("INDXRecordSizeBits = %u\n", vol->indx_record_size_bits); - /* - * Windows cares only about first 4 records in $MFTMirr and inores - * everything beyend them. - */ - vol->mftmirr_size = 4; - return 0; -} diff --git a/usr/src/lib/libntfs/common/libntfs/collate.c b/usr/src/lib/libntfs/common/libntfs/collate.c deleted file mode 100644 index 566ceef475..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/collate.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * collate.c - NTFS collation handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * Copyright (c) 2005 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STRING_H -#include -#endif - -#include "compat.h" -#include "collate.h" -#include "debug.h" -#include "unistr.h" -#include "logging.h" - -/** - * ntfs_collate_binary - Which of two binary objects should be listed first - * @vol: unused - * @data1: - * @data1_len: - * @data2: - * @data2_len: - * - * Description... - * - * Returns: - */ -static int ntfs_collate_binary(ntfs_volume *vol __attribute__((unused)), - const void *data1, size_t data1_len, - const void *data2, size_t data2_len) -{ - int rc; - - ntfs_log_trace("Entering.\n"); - rc = memcmp(data1, data2, min(data1_len, data2_len)); - if (!rc && (data1_len != data2_len)) { - if (data1_len < data2_len) - rc = -1; - else - rc = 1; - } - ntfs_log_trace("Done, returning %i.\n", rc); - return rc; -} - -/** - * ntfs_collate_ntofs_ulong - Which of two long ints should be listed first - * @vol: unused - * @data1: - * @data1_len: - * @data2: - * @data2_len: - * - * Description... - * - * Returns: - */ -static int ntfs_collate_ntofs_ulong(ntfs_volume *vol __attribute__((unused)), - const void *data1, size_t data1_len, - const void *data2, size_t data2_len) -{ - int rc; - u32 d1, d2; - - ntfs_log_trace("Entering.\n"); - if (data1_len != data2_len || data1_len != 4) { - ntfs_log_error("data1_len or/and data2_len not equal to 4.\n"); - return NTFS_COLLATION_ERROR; - } - d1 = le32_to_cpup(data1); - d2 = le32_to_cpup(data2); - if (d1 < d2) - rc = -1; - else { - if (d1 == d2) - rc = 0; - else - rc = 1; - } - ntfs_log_trace("Done, returning %i.\n", rc); - return rc; -} - -/** - * ntfs_collate_file_name - Which of two filenames should be listed first - * @vol: - * @data1: - * @data1_len: unused - * @data2: - * @data2_len: unused - * - * Description... - * - * Returns: - */ -static int ntfs_collate_file_name(ntfs_volume *vol, - const void *data1, size_t data1_len __attribute__((unused)), - const void *data2, size_t data2_len __attribute__((unused))) -{ - int rc; - - ntfs_log_trace("Entering.\n"); - rc = ntfs_file_values_compare(data1, data2, NTFS_COLLATION_ERROR, - IGNORE_CASE, vol->upcase, vol->upcase_len); - if (!rc) - rc = ntfs_file_values_compare(data1, data2, - NTFS_COLLATION_ERROR, CASE_SENSITIVE, - vol->upcase, vol->upcase_len); - ntfs_log_trace("Done, returning %i.\n", rc); - return rc; -} - -typedef int (*ntfs_collate_func_t)(ntfs_volume *, const void *, size_t, - const void *, size_t); - -static ntfs_collate_func_t ntfs_do_collate0x0[3] = { - ntfs_collate_binary, - ntfs_collate_file_name, - NULL/*ntfs_collate_unicode_string*/, -}; - -static ntfs_collate_func_t ntfs_do_collate0x1[4] = { - ntfs_collate_ntofs_ulong, - NULL/*ntfs_collate_ntofs_sid*/, - NULL/*ntfs_collate_ntofs_security_hash*/, - NULL/*ntfs_collate_ntofs_ulongs*/, -}; - -/** - * ntfs_is_collation_rule_supported - Check if a collation rule is implemented. - * @cr: The to-be-checked collation rule - * - * Use this function to know if @cr is supported by libntfs. - * - * 7 collation rules are known to be supported by NTFS as defined - * in layout.h. However, libntfs only support 3 of them ATM. - * - * Return TRUE if @cr is supported. FALSE otherwise. - */ -BOOL ntfs_is_collation_rule_supported(COLLATION_RULES cr) -{ - return (cr == COLLATION_BINARY || cr == COLLATION_NTOFS_ULONG || - cr == COLLATION_FILE_NAME); - /* - * FIXME: At the moment we only support COLLATION_BINARY, - * COLLATION_NTOFS_ULONG and COLLATION_FILE_NAME. - * The correct future implementation of this function should be: - * - * u32 i = le32_to_cpu(cr); - * return ((i <= 0x02) || ((i >= 0x10) && (i <= 0x13))); - */ -} - -/** - * ntfs_collate - collate two data items using a specified collation rule - * @vol: ntfs volume to which the data items belong - * @cr: collation rule to use when comparing the items - * @data1: first data item to collate - * @data1_len: length in bytes of @data1 - * @data2: second data item to collate - * @data2_len: length in bytes of @data2 - * - * Collate the two data items @data1 and @data2 using the collation rule @cr - * and return -1, 0, or 1 if @data1 is found, respectively, to collate before, - * to match, or to collate after @data2. - * - * For speed we use the collation rule @cr as an index into two tables of - * function pointers to call the appropriate collation function. - * - * Return NTFS_COLLATION_ERROR if error occurred. - */ -int ntfs_collate(ntfs_volume *vol, COLLATION_RULES cr, - const void *data1, size_t data1_len, - const void *data2, size_t data2_len) -{ - u32 i; - - ntfs_log_trace("Entering.\n"); - if (!vol || !data1 || !data2) { - ntfs_log_error("Invalid arguments passed.\n"); - return NTFS_COLLATION_ERROR; - } - - if (!ntfs_is_collation_rule_supported(cr)) - goto err; - i = le32_to_cpu(cr); - if (i <= 0x02) - return ntfs_do_collate0x0[i](vol, data1, data1_len, - data2, data2_len); - if (i < 0x10) - goto err; - i -= 0x10; - if (i <= 3) - return ntfs_do_collate0x1[i](vol, data1, data1_len, - data2, data2_len); -err: - ntfs_log_debug("Unknown collation rule.\n"); - return NTFS_COLLATION_ERROR; -} diff --git a/usr/src/lib/libntfs/common/libntfs/compat.c b/usr/src/lib/libntfs/common/libntfs/compat.c deleted file mode 100644 index acdf4db7ce..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/compat.c +++ /dev/null @@ -1,73 +0,0 @@ -/** - * compat.c - Tweaks for Windows compatibility - * - * Copyright (c) 2002 Richard Russon - * Copyright (c) 2002-2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef WINDOWS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "compat.h" - -/* TODO: Add check for FFS in the configure script... (AIA) */ - -#ifndef HAVE_FFS -/** - * ffs - Find the first set bit in an int - * @x: - * - * Description... - * - * Returns: - */ -int ffs(int x) -{ - int r = 1; - - if (!x) - return 0; - if (!(x & 0xffff)) { - x >>= 16; - r += 16; - } - if (!(x & 0xff)) { - x >>= 8; - r += 8; - } - if (!(x & 0xf)) { - x >>= 4; - r += 4; - } - if (!(x & 3)) { - x >>= 2; - r += 2; - } - if (!(x & 1)) { - x >>= 1; - r += 1; - } - return r; -} -#endif /* HAVE_FFS */ - -#endif /* WINDOWS */ - diff --git a/usr/src/lib/libntfs/common/libntfs/compress.c b/usr/src/lib/libntfs/common/libntfs/compress.c deleted file mode 100644 index def04e46eb..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/compress.c +++ /dev/null @@ -1,553 +0,0 @@ -/** - * compress.c - Compressed attribute handling code. Part of the Linux-NTFS - * project. - * - * Copyright (c) 2004-2005 Anton Altaparmakov - * Copyright (c) 2005 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "debug.h" -#include "volume.h" -#include "types.h" -#include "layout.h" -#include "runlist.h" -#include "compress.h" -#include "logging.h" - -/** - * enum ntfs_compression_constants - constants used in the compression code - */ -typedef enum { - /* Token types and access mask. */ - NTFS_SYMBOL_TOKEN = 0, - NTFS_PHRASE_TOKEN = 1, - NTFS_TOKEN_MASK = 1, - - /* Compression sub-block constants. */ - NTFS_SB_SIZE_MASK = 0x0fff, - NTFS_SB_SIZE = 0x1000, - NTFS_SB_IS_COMPRESSED = 0x8000, -} ntfs_compression_constants; - -/** - * ntfs_decompress - decompress a compression block into an array of pages - * @dest: buffer to which to write the decompressed data - * @dest_size: size of buffer @dest in bytes - * @cb_start: compression block to decompress - * @cb_size: size of compression block @cb_start in bytes - * - * This decompresses the compression block @cb_start into the destination - * buffer @dest. - * - * @cb_start is a pointer to the compression block which needs decompressing - * and @cb_size is the size of @cb_start in bytes (8-64kiB). - * - * Return 0 if success or -EOVERFLOW on error in the compressed stream. - */ -static int ntfs_decompress(u8 *dest, const u32 dest_size, - u8 *const cb_start, const u32 cb_size) -{ - /* - * Pointers into the compressed data, i.e. the compression block (cb), - * and the therein contained sub-blocks (sb). - */ - u8 *cb_end = cb_start + cb_size; /* End of cb. */ - u8 *cb = cb_start; /* Current position in cb. */ - u8 *cb_sb_start = cb; /* Beginning of the current sb in the cb. */ - u8 *cb_sb_end; /* End of current sb / beginning of next sb. */ - /* Variables for uncompressed data / destination. */ - u8 *dest_end = dest + dest_size; /* End of dest buffer. */ - u8 *dest_sb_start; /* Start of current sub-block in dest. */ - u8 *dest_sb_end; /* End of current sb in dest. */ - /* Variables for tag and token parsing. */ - u8 tag; /* Current tag. */ - int token; /* Loop counter for the eight tokens in tag. */ - - ntfs_log_trace("Entering, cb_size = 0x%x.\n", (unsigned)cb_size); -do_next_sb: - ntfs_log_debug("Beginning sub-block at offset = 0x%x in the cb.\n", - cb - cb_start); - /* - * Have we reached the end of the compression block or the end of the - * decompressed data? The latter can happen for example if the current - * position in the compression block is one byte before its end so the - * first two checks do not detect it. - */ - if (cb == cb_end || !le16_to_cpup((u16*)cb) || dest == dest_end) { - ntfs_log_debug("Completed. Returning success (0).\n"); - return 0; - } - /* Setup offset for the current sub-block destination. */ - dest_sb_start = dest; - dest_sb_end = dest + NTFS_SB_SIZE; - /* Check that we are still within allowed boundaries. */ - if (dest_sb_end > dest_end) - goto return_overflow; - /* Does the minimum size of a compressed sb overflow valid range? */ - if (cb + 6 > cb_end) - goto return_overflow; - /* Setup the current sub-block source pointers and validate range. */ - cb_sb_start = cb; - cb_sb_end = cb_sb_start + (le16_to_cpup((u16*)cb) & NTFS_SB_SIZE_MASK) - + 3; - if (cb_sb_end > cb_end) - goto return_overflow; - /* Now, we are ready to process the current sub-block (sb). */ - if (!(le16_to_cpup((u16*)cb) & NTFS_SB_IS_COMPRESSED)) { - ntfs_log_debug("Found uncompressed sub-block.\n"); - /* This sb is not compressed, just copy it into destination. */ - /* Advance source position to first data byte. */ - cb += 2; - /* An uncompressed sb must be full size. */ - if (cb_sb_end - cb != NTFS_SB_SIZE) - goto return_overflow; - /* Copy the block and advance the source position. */ - memcpy(dest, cb, NTFS_SB_SIZE); - cb += NTFS_SB_SIZE; - /* Advance destination position to next sub-block. */ - dest += NTFS_SB_SIZE; - goto do_next_sb; - } - ntfs_log_debug("Found compressed sub-block.\n"); - /* This sb is compressed, decompress it into destination. */ - /* Forward to the first tag in the sub-block. */ - cb += 2; -do_next_tag: - if (cb == cb_sb_end) { - /* Check if the decompressed sub-block was not full-length. */ - if (dest < dest_sb_end) { - int nr_bytes = dest_sb_end - dest; - - ntfs_log_debug("Filling incomplete sub-block with zeroes.\n"); - /* Zero remainder and update destination position. */ - memset(dest, 0, nr_bytes); - dest += nr_bytes; - } - /* We have finished the current sub-block. */ - goto do_next_sb; - } - /* Check we are still in range. */ - if (cb > cb_sb_end || dest > dest_sb_end) - goto return_overflow; - /* Get the next tag and advance to first token. */ - tag = *cb++; - /* Parse the eight tokens described by the tag. */ - for (token = 0; token < 8; token++, tag >>= 1) { - u16 lg, pt, length, max_non_overlap; - register u16 i; - u8 *dest_back_addr; - - /* Check if we are done / still in range. */ - if (cb >= cb_sb_end || dest > dest_sb_end) - break; - /* Determine token type and parse appropriately.*/ - if ((tag & NTFS_TOKEN_MASK) == NTFS_SYMBOL_TOKEN) { - /* - * We have a symbol token, copy the symbol across, and - * advance the source and destination positions. - */ - *dest++ = *cb++; - /* Continue with the next token. */ - continue; - } - /* - * We have a phrase token. Make sure it is not the first tag in - * the sb as this is illegal and would confuse the code below. - */ - if (dest == dest_sb_start) - goto return_overflow; - /* - * Determine the number of bytes to go back (p) and the number - * of bytes to copy (l). We use an optimized algorithm in which - * we first calculate log2(current destination position in sb), - * which allows determination of l and p in O(1) rather than - * O(n). We just need an arch-optimized log2() function now. - */ - lg = 0; - for (i = dest - dest_sb_start - 1; i >= 0x10; i >>= 1) - lg++; - /* Get the phrase token into i. */ - pt = le16_to_cpup((u16*)cb); - /* - * Calculate starting position of the byte sequence in - * the destination using the fact that p = (pt >> (12 - lg)) + 1 - * and make sure we don't go too far back. - */ - dest_back_addr = dest - (pt >> (12 - lg)) - 1; - if (dest_back_addr < dest_sb_start) - goto return_overflow; - /* Now calculate the length of the byte sequence. */ - length = (pt & (0xfff >> lg)) + 3; - /* Verify destination is in range. */ - if (dest + length > dest_sb_end) - goto return_overflow; - /* The number of non-overlapping bytes. */ - max_non_overlap = dest - dest_back_addr; - if (length <= max_non_overlap) { - /* The byte sequence doesn't overlap, just copy it. */ - memcpy(dest, dest_back_addr, length); - /* Advance destination pointer. */ - dest += length; - } else { - /* - * The byte sequence does overlap, copy non-overlapping - * part and then do a slow byte by byte copy for the - * overlapping part. Also, advance the destination - * pointer. - */ - memcpy(dest, dest_back_addr, max_non_overlap); - dest += max_non_overlap; - dest_back_addr += max_non_overlap; - length -= max_non_overlap; - while (length--) - *dest++ = *dest_back_addr++; - } - /* Advance source position and continue with the next token. */ - cb += 2; - } - /* No tokens left in the current tag. Continue with the next tag. */ - goto do_next_tag; -return_overflow: - ntfs_log_debug("Failed. Returning -EOVERFLOW.\n"); - errno = EOVERFLOW; - return -1; -} - -/** - * ntfs_is_cb_compressed - internal function, do not use - * - * This is a very specialised function determining if a cb is compressed or - * uncompressed. It is assumed that checking for a sparse cb has already been - * performed and that the cb is not sparse. It makes all sorts of other - * assumptions as well and hence it is not useful anywhere other than where it - * is used at the moment. Please, do not make this function available for use - * outside of compress.c as it is bound to confuse people and not do what they - * want. - * - * Return TRUE on errors so that the error will be detected later on in the - * code. Might be a bit confusing to debug but there really should never be - * errors coming from here. - */ -static BOOL ntfs_is_cb_compressed(ntfs_attr *na, - runlist_element *rl, VCN cb_start_vcn, int cb_clusters) -{ - /* - * The simplest case: the run starting at @cb_start_vcn contains - * @cb_clusters clusters which are all not sparse, thus the cb is not - * compressed. - */ -restart: - cb_clusters -= rl->length - (cb_start_vcn - rl->vcn); - while (cb_clusters > 0) { - /* Go to the next run. */ - rl++; - /* Map the next runlist fragment if it is not mapped. */ - if (rl->lcn < LCN_HOLE || !rl->length) { - cb_start_vcn = rl->vcn; - rl = ntfs_attr_find_vcn(na, rl->vcn); - if (!rl || rl->lcn < LCN_HOLE || !rl->length) - return TRUE; - /* - * If the runs were merged need to deal with the - * resulting partial run so simply restart. - */ - if (rl->vcn < cb_start_vcn) - goto restart; - } - /* If the current run is sparse, the cb is compressed. */ - if (rl->lcn == LCN_HOLE) - return TRUE; - /* If the whole cb is not sparse, it is not compressed. */ - if (rl->length >= cb_clusters) - return FALSE; - cb_clusters -= rl->length; - }; - /* All cb_clusters were not sparse thus the cb is not compressed. */ - return FALSE; -} - -/** - * ntfs_compressed_attr_pread - read from a compressed attribute - * @na: ntfs attribute to read from - * @pos: byte position in the attribute to begin reading from - * @count: number of bytes to read - * @b: output data buffer - * - * NOTE: You probably want to be using attrib.c::ntfs_attr_pread() instead. - * - * This function will read @count bytes starting at offset @pos from the - * compressed ntfs attribute @na into the data buffer @b. - * - * On success, return the number of successfully read bytes. If this number - * is lower than @count this means that the read reached end of file or that - * an error was encountered during the read so that the read is partial. - * 0 means end of file or nothing was read (also return 0 when @count is 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of ntfs_pread(), or to EINVAL in case of invalid - * arguments. - */ -s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b) -{ - s64 br, to_read, ofs, total, total2; - u64 cb_size_mask; - VCN start_vcn, vcn, end_vcn; - ntfs_volume *vol; - runlist_element *rl; - u8 *dest, *cb, *cb_pos, *cb_end; - u32 cb_size; - int err; - unsigned int nr_cbs, cb_clusters; - - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count 0x%llx.\n", - (unsigned long long)na->ni->mft_no, na->type, - (long long)pos, (long long)count); - if (!na || !NAttrCompressed(na) || !na->ni || !na->ni->vol || !b || - pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - /* - * Encrypted attributes are not supported. We return access denied, - * which is what Windows NT4 does, too. - */ - if (NAttrEncrypted(na)) { - errno = EACCES; - return -1; - } - if (!count) - return 0; - /* Truncate reads beyond end of attribute. */ - if (pos + count > na->data_size) { - if (pos >= na->data_size) { - return 0; - } - count = na->data_size - pos; - } - /* If it is a resident attribute, simply use ntfs_attr_pread(). */ - if (!NAttrNonResident(na)) - return ntfs_attr_pread(na, pos, count, b); - total = total2 = 0; - /* Zero out reads beyond initialized size. */ - if (pos + count > na->initialized_size) { - if (pos >= na->initialized_size) { - memset(b, 0, count); - return count; - } - total2 = pos + count - na->initialized_size; - count -= total2; - memset((u8*)b + count, 0, total2); - } - vol = na->ni->vol; - cb_size = na->compression_block_size; - cb_size_mask = cb_size - 1UL; - cb_clusters = na->compression_block_clusters; - - /* Need a temporary buffer for each loaded compression block. */ - cb = ntfs_malloc(cb_size); - if (!cb) - return -1; - - /* Need a temporary buffer for each uncompressed block. */ - dest = ntfs_malloc(cb_size); - if (!dest) { - err = errno; - free(cb); - errno = err; - return -1; - } - /* - * The first vcn in the first compression block (cb) which we need to - * decompress. - */ - start_vcn = (pos & ~cb_size_mask) >> vol->cluster_size_bits; - /* Offset in the uncompressed cb at which to start reading data. */ - ofs = pos & cb_size_mask; - /* - * The first vcn in the cb after the last cb which we need to - * decompress. - */ - end_vcn = ((pos + count + cb_size - 1) & ~cb_size_mask) >> - vol->cluster_size_bits; - /* Number of compression blocks (cbs) in the wanted vcn range. */ - nr_cbs = (end_vcn - start_vcn) << vol->cluster_size_bits >> - na->compression_block_size_bits; - cb_end = cb + cb_size; -do_next_cb: - nr_cbs--; - cb_pos = cb; - vcn = start_vcn; - start_vcn += cb_clusters; - - /* Check whether the compression block is sparse. */ - rl = ntfs_attr_find_vcn(na, vcn); - if (!rl || rl->lcn < LCN_HOLE) { - free(cb); - free(dest); - if (total) - return total; - /* FIXME: Do we want EIO or the error code? (AIA) */ - errno = EIO; - return -1; - } - if (rl->lcn == LCN_HOLE) { - /* Sparse cb, zero out destination range overlapping the cb. */ - ntfs_log_debug("Found sparse compression block.\n"); - to_read = min(count, cb_size - ofs); - memset(b, 0, to_read); - ofs = 0; - total += to_read; - count -= to_read; - b = (u8*)b + to_read; - } else if (!ntfs_is_cb_compressed(na, rl, vcn, cb_clusters)) { - s64 tdata_size, tinitialized_size; - /* - * Uncompressed cb, read it straight into the destination range - * overlapping the cb. - */ - ntfs_log_debug("Found uncompressed compression block.\n"); - /* - * Read the uncompressed data into the destination buffer. - * NOTE: We cheat a little bit here by marking the attribute as - * not compressed in the ntfs_attr structure so that we can - * read the data by simply using ntfs_attr_pread(). (-8 - * NOTE: we have to modify data_size and initialized_size - * temporarily as well... - */ - to_read = min(count, cb_size - ofs); - ofs += vcn << vol->cluster_size_bits; - NAttrClearCompressed(na); - tdata_size = na->data_size; - tinitialized_size = na->initialized_size; - na->data_size = na->initialized_size = na->allocated_size; - do { - br = ntfs_attr_pread(na, ofs, to_read, b); - if (br < 0) { - err = errno; - na->data_size = tdata_size; - na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); - free(cb); - free(dest); - if (total) - return total; - errno = err; - return br; - } - total += br; - count -= br; - b = (u8*)b + br; - to_read -= br; - ofs += br; - } while (to_read > 0); - na->data_size = tdata_size; - na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); - ofs = 0; - } else { - s64 tdata_size, tinitialized_size; - - /* - * Compressed cb, decompress it into the temporary buffer, then - * copy the data to the destination range overlapping the cb. - */ - ntfs_log_debug("Found compressed compression block.\n"); - /* - * Read the compressed data into the temporary buffer. - * NOTE: We cheat a little bit here by marking the attribute as - * not compressed in the ntfs_attr structure so that we can - * read the raw, compressed data by simply using - * ntfs_attr_pread(). (-8 - * NOTE: We have to modify data_size and initialized_size - * temporarily as well... - */ - to_read = cb_size; - NAttrClearCompressed(na); - tdata_size = na->data_size; - tinitialized_size = na->initialized_size; - na->data_size = na->initialized_size = na->allocated_size; - do { - br = ntfs_attr_pread(na, - (vcn << vol->cluster_size_bits) + - (cb_pos - cb), to_read, cb_pos); - if (br < 0) { - err = errno; - na->data_size = tdata_size; - na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); - free(cb); - free(dest); - if (total) - return total; - errno = err; - return br; - } - cb_pos += br; - to_read -= br; - } while (to_read > 0); - na->data_size = tdata_size; - na->initialized_size = tinitialized_size; - NAttrSetCompressed(na); - /* Just a precaution. */ - if (cb_pos + 2 <= cb_end) - *(u16*)cb_pos = 0; - ntfs_log_debug("Successfully read the compression block.\n"); - if (ntfs_decompress(dest, cb_size, cb, cb_size) < 0) { - err = errno; - free(cb); - free(dest); - if (total) - return total; - errno = err; - return -1; - } - to_read = min(count, cb_size - ofs); - memcpy(b, dest + ofs, to_read); - total += to_read; - count -= to_read; - b = (u8*)b + to_read; - ofs = 0; - } - /* Do we have more work to do? */ - if (nr_cbs) - goto do_next_cb; - /* We no longer need the buffers. */ - free(cb); - free(dest); - /* Return number of bytes read. */ - return total + total2; -} diff --git a/usr/src/lib/libntfs/common/libntfs/crypto.c b/usr/src/lib/libntfs/common/libntfs/crypto.c deleted file mode 100644 index 850e0705c6..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/crypto.c +++ /dev/null @@ -1,1519 +0,0 @@ -/** - * crypto.c - Routines for dealing with encrypted files. Part of the - * Linux-NTFS project. - * - * Copyright (c) 2005 Yuval Fledel - * Copyright (c) 2005-2007 Anton Altaparmakov - * Copyright (c) 2007 Yura Pakhuchiy - * - * 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: Cleanup this file. Write nice descriptions for non-exported functions - * and maybe clean up namespace (not necessary for all functions to belong to - * ntfs_crypto, we can have ntfs_fek, ntfs_rsa, etc.., but there should be - * maximum 2-3 namespaces, not every function begins with it own namespace - * like now). - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "types.h" -#include "volume.h" -#include "debug.h" -#include "dir.h" -#include "layout.h" -#include "crypto.h" - -#ifdef ENABLE_CRYPTO - -#include -#include -#include - -#include - -#define NTFS_CONFIG_PATH_SYSTEM "/etc/libntfs/config" -#define NTFS_CONFIG_PATH_USER ".libntfs/config" - -#define NTFS_SHA1_THUMBPRINT_SIZE 0x14 - -#define NTFS_CRED_TYPE_CERT_THUMBPRINT const_cpu_to_le32(3) - -#define NTFS_EFS_CERT_PURPOSE_OID_DDF "1.3.6.1.4.1.311.10.3.4" -#define NTFS_EFS_CERT_PURPOSE_OID_DRF "1.3.6.1.4.1.311.10.3.4.1" - -#define NTFS_EFS_SECTOR_SIZE 512 - -typedef enum { - DF_TYPE_UNKNOWN, - DF_TYPE_DDF, - DF_TYPE_DRF, -} NTFS_DF_TYPES; - -/** - * enum NTFS_CRYPTO_ALGORITHMS - List of crypto algorithms used by EFS (32 bit) - * - * To choose which one is used in Windows, create or set the REG_DWORD registry - * key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\EFS\ - * AlgorithmID to the value of your chosen crypto algorithm, e.g. to use DesX, - * set AlgorithmID to 0x6604. - * - * Note that the Windows versions I have tried so far (all are high crypto - * enabled) ignore the AlgorithmID value if it is not one of CALG_3DES, - * CALG_DESX, or CALG_AES_256, i.e. you cannot select CALG_DES at all using - * this registry key. It would be interesting to check out encryption on one - * of the "crippled" crypto Windows versions... - */ -typedef enum { - CALG_DES = const_cpu_to_le32(0x6601), - /* If not one of the below three, fall back to standard Des. */ - CALG_3DES = const_cpu_to_le32(0x6603), - CALG_DESX = const_cpu_to_le32(0x6604), - CALG_AES_256 = const_cpu_to_le32(0x6610), -} NTFS_CRYPTO_ALGORITHMS; - -/** - * struct ntfs_fek - Decrypted, in-memory file encryption key. - */ -struct _ntfs_fek { - gcry_cipher_hd_t gcry_cipher_hd; - le32 alg_id; - u8 *key_data; - gcry_cipher_hd_t *des_gcry_cipher_hd_ptr; -}; - -typedef struct _ntfs_fek ntfs_fek; - -struct _ntfs_crypto_attr { - ntfs_fek *fek; -}; - -typedef struct { - u64 in_whitening, out_whitening; - gcry_cipher_hd_t gcry_cipher_hd; -} ntfs_desx_ctx; - -ntfschar NTFS_EFS[5] = { - const_cpu_to_le16('$'), const_cpu_to_le16('E'), const_cpu_to_le16('F'), - const_cpu_to_le16('S'), const_cpu_to_le16(0) -}; - -typedef struct { - gcry_sexp_t key; - NTFS_DF_TYPES df_type; - char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE]; -} ntfs_rsa_private_key_t; - -/* - * Yes, global variables sucks, but we need to keep whether we performed - * gcrypt/gnutls global initialization and keep user's RSA keys. - */ -typedef struct { - int initialized; - int desx_alg_id; - gcry_module_t desx_module; - ntfs_rsa_private_key_t **rsa_key; - int nr_rsa_keys; -} ntfs_crypto_ctx_t; - -static ntfs_crypto_ctx_t ntfs_crypto_ctx = { - .desx_alg_id = -1, - .desx_module = NULL, -}; - -/** - * ntfs_pkcs12_load_pfxfile - */ -static int ntfs_pkcs12_load_pfxfile(const char *keyfile, u8 **pfx, - unsigned *pfx_size) -{ - int f, to_read, total, attempts, br; - struct stat key_stat; - - if (!keyfile || !pfx || !pfx_size) { - ntfs_log_error("You have to specify the key file, a pointer " - "to hold the key file contents, and a pointer " - "to hold the size of the key file contents.\n"); - return -1; - } - f = open(keyfile, O_RDONLY); - if (f == -1) { - ntfs_log_perror("Failed to open key file"); - return -1; - } - if (fstat(f, &key_stat) == -1) { - ntfs_log_perror("Failed to stat key file"); - goto file_out; - } - if (!S_ISREG(key_stat.st_mode)) { - ntfs_log_error("Key file is not a regular file, cannot read " - "it.\n"); - goto file_out; - } - if (!key_stat.st_size) { - ntfs_log_error("Key file has zero size.\n"); - goto file_out; - } - *pfx = malloc(key_stat.st_size + 1); - if (!*pfx) { - ntfs_log_perror("Failed to allocate buffer for key file " - "contents"); - goto file_out; - } - to_read = key_stat.st_size; - total = attempts = 0; - do { - br = read(f, *pfx + total, to_read); - if (br == -1) { - ntfs_log_perror("Failed to read from key file"); - goto free_out; - } - if (!br) - attempts++; - to_read -= br; - total += br; - } while (to_read > 0 && attempts < 3); - close(f); - /* Make sure it is zero terminated. */ - (*pfx)[key_stat.st_size] = 0; - *pfx_size = key_stat.st_size; - return 0; -free_out: - free(*pfx); -file_out: - close(f); - return -1; -} - -/** - * ntfs_rsa_private_key_import_from_gnutls - */ -static gcry_sexp_t ntfs_rsa_private_key_import_from_gnutls( - gnutls_x509_privkey_t priv_key) -{ - int i, j; - size_t tmp_size; - gnutls_datum_t rd[6]; - gcry_mpi_t rm[6]; - gcry_sexp_t rsa_key; - - /* Extract the RSA parameters from the GNU TLS private key. */ - if (gnutls_x509_privkey_export_rsa_raw(priv_key, &rd[0], &rd[1], - &rd[2], &rd[3], &rd[4], &rd[5])) { - ntfs_log_error("Failed to export rsa parameters. (Is the " - "key an RSA private key?)\n"); - return NULL; - } - /* Convert each RSA parameter to MPI format. */ - for (i = 0; i < 6; i++) { - if (gcry_mpi_scan(&rm[i], GCRYMPI_FMT_USG, rd[i].data, - rd[i].size, &tmp_size) != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to convert RSA parameter %i " - "to mpi format (size %d)\n", i, - rd[i].size); - rsa_key = NULL; - break; - } - } - /* Release the no longer needed datum values. */ - for (j = 0; j < 6; j++) { - if (rd[j].data && rd[j].size) - gnutls_free(rd[j].data); - } - /* - * Build the gcrypt private key, note libgcrypt uses p and q inversed - * to what gnutls uses. - */ - if (i == 6 && gcry_sexp_build(&rsa_key, NULL, - "(private-key(rsa(n%m)(e%m)(d%m)(p%m)(q%m)(u%m)))", - rm[0], rm[1], rm[2], rm[4], rm[3], rm[5]) != - GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to build RSA private key s-exp.\n"); - rsa_key = NULL; - } - /* Release the no longer needed MPI values. */ - for (j = 0; j < i; j++) - gcry_mpi_release(rm[j]); - return rsa_key; -} - -/** - * ntfs_rsa_private_key_release - */ -static void ntfs_rsa_private_key_release(ntfs_rsa_private_key_t *rsa_key) -{ - if (rsa_key) { - if (rsa_key->key) - gcry_sexp_release(rsa_key->key); - free(rsa_key); - } -} - -/** - * ntfs_pkcs12_extract_rsa_key - */ -static ntfs_rsa_private_key_t *ntfs_pkcs12_extract_rsa_key(u8 *pfx, - int pfx_size, const char *password) -{ - int err, bag_index, flags; - gnutls_datum_t dpfx, dkey; - gnutls_pkcs12_t pkcs12 = NULL; - gnutls_pkcs12_bag_t bag = NULL; - gnutls_x509_privkey_t pkey = NULL; - gnutls_x509_crt_t crt = NULL; - ntfs_rsa_private_key_t *rsa_key = NULL; - char purpose_oid[100]; - size_t purpose_oid_size = sizeof(purpose_oid); - size_t tp_size; - BOOL have_thumbprint = FALSE; - - rsa_key = malloc(sizeof(ntfs_rsa_private_key_t)); - if (!rsa_key) { - ntfs_log_perror("%s", "ntfs_pkcs12_extract_rsa_key"); - return NULL; - } - rsa_key->df_type = DF_TYPE_UNKNOWN; - rsa_key->key = NULL; - tp_size = sizeof(rsa_key->thumbprint); - /* Create a pkcs12 structure. */ - err = gnutls_pkcs12_init(&pkcs12); - if (err) { - ntfs_log_error("Failed to initialize PKCS#12 structure: %s\n", - gnutls_strerror(err)); - goto err; - } - /* Convert the PFX file (DER format) to native pkcs12 format. */ - dpfx.data = pfx; - dpfx.size = pfx_size; - err = gnutls_pkcs12_import(pkcs12, &dpfx, GNUTLS_X509_FMT_DER, 0); - if (err) { - ntfs_log_error("Failed to convert the PFX file from DER to " - "native PKCS#12 format: %s\n", - gnutls_strerror(err)); - goto err; - } - /* - * Verify that the password is correct and that the key file has not - * been tampered with. Note if the password has zero length and the - * verification fails, retry with password set to NULL. This is needed - * to get password less .pfx files generated with Windows XP SP1 (and - * probably earlier versions of Windows) to work. - */ -retry_verify: - err = gnutls_pkcs12_verify_mac(pkcs12, password); - if (err) { - if (err == GNUTLS_E_MAC_VERIFY_FAILED && - password && !strlen(password)) { - password = NULL; - goto retry_verify; - } - ntfs_log_error("You are probably misspelled password to PFX " - "file.\n"); - goto err; - } - for (bag_index = 0; ; bag_index++) { - err = gnutls_pkcs12_bag_init(&bag); - if (err) { - ntfs_log_error("Failed to initialize PKCS#12 Bag " - "structure: %s\n", - gnutls_strerror(err)); - goto err; - } - err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag); - if (err) { - if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { - err = 0; - break; - } - ntfs_log_error("Failed to obtain Bag from PKCS#12 " - "structure: %s\n", - gnutls_strerror(err)); - goto err; - } -check_again: - err = gnutls_pkcs12_bag_get_count(bag); - if (err < 0) { - ntfs_log_error("Failed to obtain Bag count: %s\n", - gnutls_strerror(err)); - goto err; - } - err = gnutls_pkcs12_bag_get_type(bag, 0); - if (err < 0) { - ntfs_log_error("Failed to determine Bag type: %s\n", - gnutls_strerror(err)); - goto err; - } - flags = 0; - switch (err) { - case GNUTLS_BAG_PKCS8_KEY: - flags = GNUTLS_PKCS_PLAIN; - case GNUTLS_BAG_PKCS8_ENCRYPTED_KEY: - err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); - if (err < 0) { - ntfs_log_error("Failed to obtain Bag data: " - "%s\n", gnutls_strerror(err)); - goto err; - } - err = gnutls_x509_privkey_init(&pkey); - if (err) { - ntfs_log_error("Failed to initialized " - "private key structure: %s\n", - gnutls_strerror(err)); - goto err; - } - /* Decrypt the private key into GNU TLS format. */ - err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey, - GNUTLS_X509_FMT_DER, password, flags); - if (err) { - ntfs_log_error("Failed to convert private " - "key from DER to GNU TLS " - "format: %s\n", - gnutls_strerror(err)); - goto err; - } -#if 0 - /* - * Export the key again, but unencrypted, and output it - * to stderr. Note the output has an RSA header so to - * compare to openssl pkcs12 -nodes -in myfile.pfx - * output need to ignore the part of the key between - * the first "MII..." up to the second "MII...". The - * actual RSA private key begins at the second "MII..." - * and in my testing at least was identical to openssl - * output and was also identical both on big and little - * endian so gnutls should be endianness safe. - */ - char *buf = malloc(8192); - size_t bufsize = 8192; - err = gnutls_x509_privkey_export_pkcs8(pkey, - GNUTLS_X509_FMT_PEM, "", GNUTLS_PKCS_PLAIN, buf, - &bufsize); - if (err) { - ntfs_log_error("eek1\n"); - exit(1); - } - ntfs_log_error("%s\n", buf); - free(buf); -#endif - /* Convert the private key to our internal format. */ - rsa_key->key = - ntfs_rsa_private_key_import_from_gnutls(pkey); - if (!rsa_key->key) - goto err; - break; - case GNUTLS_BAG_ENCRYPTED: - err = gnutls_pkcs12_bag_decrypt(bag, password); - if (err) { - ntfs_log_error("Failed to decrypt Bag: %s\n", - gnutls_strerror(err)); - goto err; - } - goto check_again; - case GNUTLS_BAG_CERTIFICATE: - err = gnutls_pkcs12_bag_get_data(bag, 0, &dkey); - if (err < 0) { - ntfs_log_error("Failed to obtain Bag data: " - "%s\n", gnutls_strerror(err)); - goto err; - } - err = gnutls_x509_crt_init(&crt); - if (err) { - ntfs_log_error("Failed to initialize " - "certificate structure: %s\n", - gnutls_strerror(err)); - goto err; - } - err = gnutls_x509_crt_import(crt, &dkey, - GNUTLS_X509_FMT_DER); - if (err) { - ntfs_log_error("Failed to convert certificate " - "from DER to GNU TLS format: " - "%s\n", gnutls_strerror(err)); - goto err; - } - err = gnutls_x509_crt_get_key_purpose_oid(crt, 0, - purpose_oid, &purpose_oid_size, NULL); - if (err) { - ntfs_log_error("Failed to get key purpose " - "OID: %s\n", - gnutls_strerror(err)); - goto err; - } - purpose_oid[purpose_oid_size - 1] = 0; - if (!strcmp(purpose_oid, - NTFS_EFS_CERT_PURPOSE_OID_DRF)) - rsa_key->df_type = DF_TYPE_DRF; - else if (!strcmp(purpose_oid, - NTFS_EFS_CERT_PURPOSE_OID_DDF)) - rsa_key->df_type = DF_TYPE_DDF; - else { - ntfs_log_error("Certificate has unknown " - "purpose OID %s.\n", - purpose_oid); - err = EINVAL; - goto err; - } - /* Return the thumbprint to the caller. */ - err = gnutls_x509_crt_get_fingerprint(crt, - GNUTLS_DIG_SHA1, rsa_key->thumbprint, - &tp_size); - if (err) { - ntfs_log_error("Failed to get thumbprint: " - "%s\n", gnutls_strerror(err)); - goto err; - } - if (tp_size != NTFS_SHA1_THUMBPRINT_SIZE) { - ntfs_log_error("Invalid thumbprint size %zd. " - "Should be %d.\n", tp_size, - sizeof(rsa_key->thumbprint)); - err = EINVAL; - goto err; - } - have_thumbprint = TRUE; - gnutls_x509_crt_deinit(crt); - crt = NULL; - break; - default: - /* We do not care about other types. */ - break; - } - gnutls_pkcs12_bag_deinit(bag); - } -err: - if (err || !rsa_key->key || rsa_key->df_type == DF_TYPE_UNKNOWN || - !have_thumbprint) { - if (!err) - ntfs_log_error("Key type or thumbprint not found, " - "aborting.\n"); - ntfs_rsa_private_key_release(rsa_key); - rsa_key = NULL; - } - if (crt) - gnutls_x509_crt_deinit(crt); - if (pkey) - gnutls_x509_privkey_deinit(pkey); - if (bag) - gnutls_pkcs12_bag_deinit(bag); - if (pkcs12) - gnutls_pkcs12_deinit(pkcs12); - return rsa_key; -} - -/** - * ntfs_buffer_reverse - - * - * This is a utility function for reversing the order of a buffer in place. - * Users of this function should be very careful not to sweep byte order - * problems under the rug. - */ -static inline void ntfs_buffer_reverse(u8 *buf, unsigned buf_size) -{ - unsigned i; - u8 t; - - for (i = 0; i < buf_size / 2; i++) { - t = buf[i]; - buf[i] = buf[buf_size - i - 1]; - buf[buf_size - i - 1] = t; - } -} - -#ifndef HAVE_STRNLEN -/** - * strnlen - strnlen is a gnu extension so emulate it if not present - */ -static size_t strnlen(const char *s, size_t maxlen) -{ - const char *p, *end; - - /* Look for a '\0' character. */ - for (p = s, end = s + maxlen; p < end && *p; p++) - ; - return p - s; -} -#endif /* ! HAVE_STRNLEN */ - -/** - * ntfs_raw_fek_decrypt - - * - * Note: decrypting into the input buffer. - */ -static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size, - ntfs_rsa_private_key_t *rsa_key) -{ - gcry_mpi_t fek_mpi; - gcry_sexp_t fek_sexp, fek_sexp2; - gcry_error_t err; - size_t size, padding; - - /* Reverse the raw FEK. */ - ntfs_buffer_reverse(fek, fek_size); - /* Convert the FEK to internal MPI format. */ - err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to convert file encryption key to " - "internal MPI format: %s\n", - gcry_strerror(err)); - return 0; - } - /* Create an internal S-expression from the FEK. */ - err = gcry_sexp_build(&fek_sexp, NULL, - "(enc-val (flags) (rsa (a %m)))", fek_mpi); - gcry_mpi_release(fek_mpi); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to create internal S-expression of " - "the file encryption key: %s\n", - gcry_strerror(err)); - return 0; - } - /* Decrypt the FEK. */ - err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, rsa_key->key); - gcry_sexp_release(fek_sexp); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to decrypt the file encryption key: " - "%s\n", gcry_strerror(err)); - return 0; - } - /* Extract the actual FEK from the decrypted raw S-expression. */ - fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0); - gcry_sexp_release(fek_sexp2); - if (!fek_sexp) { - ntfs_log_error("Failed to find the decrypted file encryption " - "key in the internal S-expression.\n"); - return 0; - } - /* Convert the decrypted FEK S-expression into MPI format. */ - fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG); - gcry_sexp_release(fek_sexp); - if (!fek_mpi) { - ntfs_log_error("Failed to convert the decrypted file " - "encryption key S-expression to internal MPI " - "format.\n"); - return 0; - } - /* Convert the decrypted FEK from MPI format to binary data. */ - err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi); - gcry_mpi_release(fek_mpi); - if (err != GPG_ERR_NO_ERROR || !size) { - ntfs_log_error("Failed to convert decrypted file encryption " - "key from internal MPI format to binary data: " - "%s\n", gcry_strerror(err)); - return 0; - } - /* - * Finally, remove the PKCS#1 padding and return the size of the - * decrypted FEK. - */ - padding = strnlen((char *)fek, size) + 1; - if (padding > size) { - ntfs_log_error("Failed to remove PKCS#1 padding from " - "decrypted file encryption key.\n"); - return 0; - } - size -= padding; - memmove(fek, fek + padding, size); - return size; -} - -/** - * ntfs_desx_key_expand - expand a 128-bit desx key to the needed 192-bit key - * @src: source buffer containing 128-bit key - * - * Expands the on-disk 128-bit desx key to the needed des key, the in-, and the - * out-whitening keys required to perform desx {de,en}cryption. - */ -static gcry_error_t ntfs_desx_key_expand(const u8 *src, u32 *des_key, - u64 *out_whitening, u64 *in_whitening) -{ - static const u8 *salt1 = (const u8*)"Dan Simon "; - static const u8 *salt2 = (const u8*)"Scott Field"; - static const int salt_len = 12; - gcry_md_hd_t hd1, hd2; - u32 *md; - gcry_error_t err; - - err = gcry_md_open(&hd1, GCRY_MD_MD5, 0); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to open MD5 digest.\n"); - return err; - } - /* Hash the on-disk key. */ - gcry_md_write(hd1, src, 128 / 8); - /* Copy the current hash for efficiency. */ - err = gcry_md_copy(&hd2, hd1); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to copy MD5 digest object.\n"); - goto out; - } - /* Hash with the first salt and store the result. */ - gcry_md_write(hd1, salt1, salt_len); - md = (u32*)gcry_md_read(hd1, 0); - des_key[0] = md[0] ^ md[1]; - des_key[1] = md[2] ^ md[3]; - /* Hash with the second salt and store the result. */ - gcry_md_write(hd2, salt2, salt_len); - md = (u32*)gcry_md_read(hd2, 0); - *out_whitening = *(u64*)md; - *in_whitening = *(u64*)(md + 2); - gcry_md_close(hd2); -out: - gcry_md_close(hd1); - return err; -} - -/** - * ntfs_desx_setkey - libgcrypt set_key implementation for DES-X-MS128 - * @context: pointer to a variable of type ntfs_desx_ctx - * @key: the 128 bit DES-X-MS128 key, concated with the DES handle - * @keylen: must always be 16 - * - * This is the libgcrypt set_key implementation for DES-X-MS128. - */ -static gcry_err_code_t ntfs_desx_setkey(void *context, const u8 *key, - unsigned keylen) -{ - ntfs_desx_ctx *ctx = context; - gcry_error_t err; - u8 des_key[8]; - - if (keylen != 16) { - ntfs_log_error("Key length for desx must be 16.\n"); - return GPG_ERR_INV_KEYLEN; - } - err = gcry_cipher_open(&ctx->gcry_cipher_hd, GCRY_CIPHER_DES, - GCRY_CIPHER_MODE_ECB, 0); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to open des cipher (error 0x%x).\n", - err); - return err; - } - err = ntfs_desx_key_expand(key, (u32*)des_key, &ctx->out_whitening, - &ctx->in_whitening); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to expand desx key (error 0x%x).\n", - err); - gcry_cipher_close(ctx->gcry_cipher_hd); - return err; - } - err = gcry_cipher_setkey(ctx->gcry_cipher_hd, des_key, sizeof(des_key)); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to set des key (error 0x%x).\n", err); - gcry_cipher_close(ctx->gcry_cipher_hd); - return err; - } - /* - * Take a note of the ctx->gcry_cipher_hd since we need to close it at - * ntfs_decrypt_data_key_close() time. - */ - **(gcry_cipher_hd_t***)(key + ((keylen + 7) & ~7)) = - &ctx->gcry_cipher_hd; - return GPG_ERR_NO_ERROR; -} - -/** - * ntfs_desx_decrypt - */ -static void ntfs_desx_decrypt(void *context, u8 *outbuf, const u8 *inbuf) -{ - ntfs_desx_ctx *ctx = context; - gcry_error_t err; - - err = gcry_cipher_reset(ctx->gcry_cipher_hd); - if (err != GPG_ERR_NO_ERROR) - ntfs_log_error("Failed to reset des cipher (error 0x%x).\n", - err); - *(u64*)outbuf = *(const u64*)inbuf ^ ctx->out_whitening; - err = gcry_cipher_encrypt(ctx->gcry_cipher_hd, outbuf, 8, NULL, 0); - if (err != GPG_ERR_NO_ERROR) - ntfs_log_error("Des decryption failed (error 0x%x).\n", err); - *(u64*)outbuf ^= ctx->in_whitening; -} - -static gcry_cipher_spec_t ntfs_desx_cipher = { - .name = "DES-X-MS128", - .blocksize = 8, - .keylen = 128, - .contextsize = sizeof(ntfs_desx_ctx), - .setkey = ntfs_desx_setkey, - .decrypt = ntfs_desx_decrypt, -}; - -#ifdef NTFS_TEST -/* - * Do not remove this test code from this file! (AIA) - * It would be nice to move all tests (these and runlist) out of the library - * (at least, into the separate file{,s}), so they would not annoy eyes. (Yura) - */ - -/** - * ntfs_desx_key_expand_test - */ -static BOOL ntfs_desx_key_expand_test(void) -{ - const u8 known_desx_on_disk_key[16] = { - 0xa1, 0xf9, 0xe0, 0xb2, 0x53, 0x23, 0x9e, 0x8f, - 0x0f, 0x91, 0x45, 0xd9, 0x8e, 0x20, 0xec, 0x30 - }; - const u8 known_des_key[8] = { - 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f, - }; - const u8 known_out_whitening[8] = { - 0xed, 0xda, 0x4c, 0x47, 0x60, 0x49, 0xdb, 0x8d, - }; - const u8 known_in_whitening[8] = { - 0x75, 0xf6, 0xa0, 0x1a, 0xc0, 0xca, 0x28, 0x1e - }; - u64 test_out_whitening, test_in_whitening; - union { - u64 u64; - u32 u32[2]; - } test_des_key; - gcry_error_t err; - BOOL res; - - err = ntfs_desx_key_expand(known_desx_on_disk_key, test_des_key.u32, - &test_out_whitening, &test_in_whitening); - if (err != GPG_ERR_NO_ERROR) - res = FALSE; - else - res = test_des_key.u64 == *(u64*)known_des_key && - test_out_whitening == - *(u64*)known_out_whitening && - test_in_whitening == - *(u64*)known_in_whitening; - ntfs_log_error("Testing whether ntfs_desx_key_expand() works: %s\n", - res ? "SUCCESS" : "FAILED"); - return res; -} - -/** - * ntfs_des_test - */ -static BOOL ntfs_des_test(void) -{ - const u8 known_des_key[8] = { - 0x27, 0xd1, 0x93, 0x09, 0xcb, 0x78, 0x93, 0x1f - }; - const u8 known_des_encrypted_data[8] = { - 0xdc, 0xf7, 0x68, 0x2a, 0xaf, 0x48, 0x53, 0x0f - }; - const u8 known_decrypted_data[8] = { - 0xd8, 0xd9, 0x15, 0x23, 0x5b, 0x88, 0x0e, 0x09 - }; - u8 test_decrypted_data[8]; - int res; - gcry_error_t err; - gcry_cipher_hd_t gcry_cipher_hd; - - err = gcry_cipher_open(&gcry_cipher_hd, GCRY_CIPHER_DES, - GCRY_CIPHER_MODE_ECB, 0); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to open des cipher (error 0x%x).\n", - err); - return FALSE; - } - err = gcry_cipher_setkey(gcry_cipher_hd, known_des_key, - sizeof(known_des_key)); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to set des key (error 0x%x.\n", err); - gcry_cipher_close(gcry_cipher_hd); - return FALSE; - } - /* - * Apply DES decryption (ntfs actually uses encryption when decrypting). - */ - err = gcry_cipher_encrypt(gcry_cipher_hd, test_decrypted_data, - sizeof(test_decrypted_data), known_des_encrypted_data, - sizeof(known_des_encrypted_data)); - gcry_cipher_close(gcry_cipher_hd); - if (err) { - ntfs_log_error("Failed to des decrypt test data (error " - "0x%x).\n", err); - return FALSE; - } - res = !memcmp(test_decrypted_data, known_decrypted_data, - sizeof(known_decrypted_data)); - ntfs_log_error("Testing whether des decryption works: %s\n", - res ? "SUCCESS" : "FAILED"); - return res; -} - -#else /* !defined(NTFS_TEST) */ - -/** - * ntfs_desx_key_expand_test - */ -static inline BOOL ntfs_desx_key_expand_test(void) -{ - return TRUE; -} - -/** - * ntfs_des_test - */ -static inline BOOL ntfs_des_test(void) -{ - return TRUE; -} - -#endif /* !defined(NTFS_TEST) */ - -/** - * ntfs_fek_import_from_raw - */ -static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf, - unsigned fek_size) -{ - ntfs_fek *fek; - u32 key_size, wanted_key_size, gcry_algo; - gcry_error_t err; - - key_size = le32_to_cpup(fek_buf); - ntfs_log_debug("key_size 0x%x\n", key_size); - if (key_size + 16 > fek_size) { - ntfs_log_debug("Invalid FEK. It was probably decrypted with " - "the incorrect RSA key."); - errno = EINVAL; - return NULL; - } - fek = malloc(((((sizeof(*fek) + 7) & ~7) + key_size + 7) & ~7) + - sizeof(gcry_cipher_hd_t)); - if (!fek) { - errno = ENOMEM; - return NULL; - } - fek->alg_id = *(le32*)(fek_buf + 8); - ntfs_log_debug("algorithm_id 0x%x\n", le32_to_cpu(fek->alg_id)); - fek->key_data = (u8*)fek + ((sizeof(*fek) + 7) & ~7); - memcpy(fek->key_data, fek_buf + 16, key_size); - fek->des_gcry_cipher_hd_ptr = NULL; - *(gcry_cipher_hd_t***)(fek->key_data + ((key_size + 7) & ~7)) = - &fek->des_gcry_cipher_hd_ptr; - switch (fek->alg_id) { - case CALG_DESX: - if (!ntfs_crypto_ctx.desx_module) { - if (!ntfs_desx_key_expand_test() || !ntfs_des_test()) { - err = EINVAL; - goto out; - } - err = gcry_cipher_register(&ntfs_desx_cipher, - &ntfs_crypto_ctx.desx_alg_id, - &ntfs_crypto_ctx.desx_module); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to register desx " - "cipher: %s\n", - gcry_strerror(err)); - err = EINVAL; - goto out; - } - } - wanted_key_size = 16; - gcry_algo = ntfs_crypto_ctx.desx_alg_id; - break; - case CALG_3DES: - wanted_key_size = 24; - gcry_algo = GCRY_CIPHER_3DES; - break; - case CALG_AES_256: - wanted_key_size = 32; - gcry_algo = GCRY_CIPHER_AES256; - break; - default: - wanted_key_size = 8; - gcry_algo = GCRY_CIPHER_DES; - if (fek->alg_id == CALG_DES) - ntfs_log_error("DES is not supported at present\n"); - else - ntfs_log_error("Unknown crypto algorithm 0x%x\n", - le32_to_cpu(fek->alg_id)); - ntfs_log_error(". Please email %s and say that you saw this " - "message. We will then try to implement " - "support for this algorithm.\n", NTFS_DEV_LIST); - err = EOPNOTSUPP; - goto out; - } - if (key_size != wanted_key_size) { - ntfs_log_error("%s key of %u bytes but needed size is %u " - "bytes, assuming corrupt or incorrect key. " - "Aborting.\n", - gcry_cipher_algo_name(gcry_algo), - (unsigned)key_size, (unsigned)wanted_key_size); - err = EIO; - goto out; - } - err = gcry_cipher_open(&fek->gcry_cipher_hd, gcry_algo, - GCRY_CIPHER_MODE_CBC, 0); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("gcry_cipher_open() failed: %s\n", - gcry_strerror(err)); - err = EINVAL; - goto out; - } - err = gcry_cipher_setkey(fek->gcry_cipher_hd, fek->key_data, key_size); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("gcry_cipher_setkey() failed: %s\n", - gcry_strerror(err)); - gcry_cipher_close(fek->gcry_cipher_hd); - err = EINVAL; - goto out; - } - return fek; -out: - free(fek); - errno = err; - return NULL; -} - -/** - * ntfs_fek_release - */ -static void ntfs_fek_release(ntfs_fek *fek) -{ - if (fek->des_gcry_cipher_hd_ptr) - gcry_cipher_close(*fek->des_gcry_cipher_hd_ptr); - gcry_cipher_close(fek->gcry_cipher_hd); - free(fek); -} - -/** - * ntfs_df_array_fek_get - */ -static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array, - ntfs_rsa_private_key_t *rsa_key) -{ - EFS_DF_HEADER *df_header; - EFS_DF_CREDENTIAL_HEADER *df_cred; - EFS_DF_CERT_THUMBPRINT_HEADER *df_cert; - u8 *fek_buf; - ntfs_fek *fek; - u32 df_count, fek_size; - unsigned i, thumbprint_size = sizeof(rsa_key->thumbprint); - - df_count = le32_to_cpu(df_array->df_count); - if (!df_count) - ntfs_log_error("There are no elements in the DF array.\n"); - df_header = (EFS_DF_HEADER*)(df_array + 1); - for (i = 0; i < df_count; i++, df_header = (EFS_DF_HEADER*)( - (u8*)df_header + le32_to_cpu(df_header->df_length))) { - df_cred = (EFS_DF_CREDENTIAL_HEADER*)((u8*)df_header + - le32_to_cpu(df_header->cred_header_offset)); - if (df_cred->type != NTFS_CRED_TYPE_CERT_THUMBPRINT) { - ntfs_log_debug("Credential type is not certificate " - "thumbprint, skipping DF entry.\n"); - continue; - } - df_cert = (EFS_DF_CERT_THUMBPRINT_HEADER*)((u8*)df_cred + - le32_to_cpu( - df_cred->cert_thumbprint_header_offset)); - if (le32_to_cpu(df_cert->thumbprint_size) != thumbprint_size) { - ntfs_log_error("Thumbprint size %d is not valid " - "(should be %d), skipping this DF " - "entry.\n", - le32_to_cpu(df_cert->thumbprint_size), - thumbprint_size); - continue; - } - if (memcmp((u8*)df_cert + - le32_to_cpu(df_cert->thumbprint_offset), - rsa_key->thumbprint, thumbprint_size)) { - ntfs_log_debug("Thumbprints do not match, skipping " - "this DF entry.\n"); - continue; - } - /* - * The thumbprints match so this is probably the DF entry - * matching the RSA key. Try to decrypt the FEK with it. - */ - fek_size = le32_to_cpu(df_header->fek_size); - fek_buf = (u8*)df_header + le32_to_cpu(df_header->fek_offset); - /* Decrypt the FEK. Note: This is done in place. */ - fek_size = ntfs_raw_fek_decrypt(fek_buf, fek_size, rsa_key); - if (fek_size) { - /* Convert the FEK to our internal format. */ - fek = ntfs_fek_import_from_raw(fek_buf, fek_size); - if (fek) - return fek; - ntfs_log_error("Failed to convert the decrypted file " - "encryption key to internal format.\n"); - } else - ntfs_log_error("Failed to decrypt the file " - "encryption key.\n"); - } - return NULL; -} - -/** - * ntfs_inode_fek_get - - */ -static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode, - ntfs_rsa_private_key_t *rsa_key) -{ - EFS_ATTR_HEADER *efs; - EFS_DF_ARRAY_HEADER *df_array = NULL; - ntfs_fek *fek = NULL; - - /* Obtain the $EFS contents. */ - efs = ntfs_attr_readall(inode, AT_LOGGED_UTILITY_STREAM, NTFS_EFS, 4, - NULL); - if (!efs) { - ntfs_log_perror("Failed to read $EFS attribute"); - return NULL; - } - /* - * Depending on whether the key is a normal key or a data recovery key, - * iterate through the DDF or DRF array, respectively. - */ - if (rsa_key->df_type == DF_TYPE_DDF) { - if (efs->offset_to_ddf_array) - df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs + - le32_to_cpu(efs->offset_to_ddf_array)); - else - ntfs_log_error("There are no entries in the DDF " - "array.\n"); - } else if (rsa_key->df_type == DF_TYPE_DRF) { - if (efs->offset_to_drf_array) - df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs + - le32_to_cpu(efs->offset_to_drf_array)); - else - ntfs_log_error("There are no entries in the DRF " - "array.\n"); - } else - ntfs_log_error("Invalid DF type.\n"); - if (df_array) - fek = ntfs_df_array_fek_get(df_array, rsa_key); - free(efs); - return fek; -} - -/** - * ntfs_fek_decrypt_sector - */ -static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset) -{ - gcry_error_t err; - - err = gcry_cipher_reset(fek->gcry_cipher_hd); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to reset cipher: %s\n", - gcry_strerror(err)); - return -1; - } - /* - * Note: You may wonder why we are not calling gcry_cipher_setiv() here - * instead of doing it by hand after the decryption. The answer is - * that gcry_cipher_setiv() wants an iv of length 8 bytes but we give - * it a length of 16 for AES256 so it does not like it. - */ - err = gcry_cipher_decrypt(fek->gcry_cipher_hd, data, 512, NULL, 0); - if (err != GPG_ERR_NO_ERROR) { - ntfs_log_error("Decryption failed: %s\n", gcry_strerror(err)); - return -1; - } - /* Apply the IV. */ - if (fek->alg_id == CALG_AES_256) { - ((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset); - ((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset); - } else { - /* All other algorithms (Des, 3Des, DesX) use the same IV. */ - ((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset); - } - return 512; -} - -/** - * ntfs_crypto_deinit - perform library-wide crypto deinitialization - */ -static void ntfs_crypto_deinit(void) -{ - int i; - - if (!ntfs_crypto_ctx.initialized) - return; - - for (i = 0; i < ntfs_crypto_ctx.nr_rsa_keys; i++) - ntfs_rsa_private_key_release(ntfs_crypto_ctx.rsa_key[i]); - free(ntfs_crypto_ctx.rsa_key); - ntfs_crypto_ctx.rsa_key = NULL; - ntfs_crypto_ctx.nr_rsa_keys = 0; - gnutls_global_deinit(); - if (ntfs_crypto_ctx.desx_module) { - gcry_cipher_unregister(ntfs_crypto_ctx.desx_module); - ntfs_crypto_ctx.desx_module = NULL; - ntfs_crypto_ctx.desx_alg_id = -1; - } - ntfs_crypto_ctx.initialized = 0; -} - - -static void ntfs_crypto_parse_config(struct config_t *cfg) -{ - ntfs_crypto_ctx_t *ctx = &ntfs_crypto_ctx; - config_setting_t *cfg_keys, *cfg_key; - const char *pfx_file, *pfx_pwd; - ntfs_rsa_private_key_t *key; - u8 *pfx_buf; - unsigned pfx_size; - int i; - - /* Search for crypto.keys list. */ - cfg_keys = config_lookup(cfg, "crypto.keys"); - if (!cfg_keys) { - ntfs_log_error("Unable to find crypto.keys in config file.\n"); - return; - } - /* Iterate trough list of records about keys. */ - for (i = 0; (cfg_key = config_setting_get_elem(cfg_keys, i)); i++) { - /* Get path and password to key. */ - pfx_file = config_setting_get_string_elem(cfg_key, 0); - pfx_pwd = config_setting_get_string_elem(cfg_key, 1); - if (!pfx_file) { - ntfs_log_error("Entry number %d in section crypto.keys " - "of configuration file formed " - "incorrectly.\n", i + 1); - continue; - } - if (!pfx_pwd) - pfx_pwd = ""; - /* Load the PKCS#12 file containing the user's private key. */ - if (ntfs_pkcs12_load_pfxfile(pfx_file, &pfx_buf, &pfx_size)) { - ntfs_log_error("Failed to load key file %s.\n", - pfx_file); - continue; - } - /* - * Check whether we need to allocate memory for new key pointer. - * If yes, allocate memory for it and for 3 more pointers. - */ - if (!(ctx->nr_rsa_keys % 4)) { - ntfs_rsa_private_key_t **new; - - new = realloc(ctx->rsa_key, - sizeof(ntfs_rsa_private_key_t *) * - (ctx->nr_rsa_keys + 4)); - if (!new) { - ntfs_log_perror("Unable to store all keys"); - break; - } - ctx->rsa_key = new; - } - /* Obtain the user's private RSA key from the key file. */ - key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, pfx_pwd); - if (key) - ctx->rsa_key[ctx->nr_rsa_keys++] = key; - else - ntfs_log_error("Failed to obtain RSA key from %s\n", - pfx_file); - /* No longer need the pfx file contents. */ - free(pfx_buf); - } -} - - -static void ntfs_crypto_read_configs(void) -{ - struct config_t cfg; - char *home; - int fd = -1; - - config_init(&cfg); - /* Load system configuration file. */ - if (config_read_file(&cfg, NTFS_CONFIG_PATH_SYSTEM)) - ntfs_crypto_parse_config(&cfg); - else - if (config_error_line(&cfg)) /* Do not cry if file absent. */ - ntfs_log_error("Failed to read system configuration " - "file: %s (line %d).\n", - config_error_text(&cfg), - config_error_line(&cfg)); - /* Load user configuration file. */ - fd = open(".", O_RDONLY); /* Save current working directory. */ - if (fd == -1) { - ntfs_log_error("Failed to open working directory.\n"); - goto out; - } - home = getenv("HOME"); - if (!home) { - ntfs_log_error("Environment variable HOME is not set.\n"); - goto out; - } - if (chdir(home) == -1) { - ntfs_log_perror("chdir() to home directory failed"); - goto out; - } - if (config_read_file(&cfg, NTFS_CONFIG_PATH_USER)) - ntfs_crypto_parse_config(&cfg); - else - if (config_error_line(&cfg)) /* Do not cry if file absent. */ - ntfs_log_error("Failed to read user configuration " - "file: %s (line %d).\n", - config_error_text(&cfg), - config_error_line(&cfg)); - if (fchdir(fd) == -1) - ntfs_log_error("Failed to restore original working " - "directory.\n"); -out: - if (fd != -1) - close(fd); - config_destroy(&cfg); -} - -/** - * ntfs_crypto_init - perform library-wide crypto initializations - * - * This function is called during first call of ntfs_crypto_attr_open and - * performs gcrypt and GNU TLS initializations, then read list of PFX files - * from configuration files and load RSA keys from them. - */ -static int ntfs_crypto_init(void) -{ - int err; - - if (ntfs_crypto_ctx.initialized) - return 0; - - /* Initialize gcrypt library. Note: Must come before GNU TLS init. */ - if (gcry_control(GCRYCTL_DISABLE_SECMEM, 0) != GPG_ERR_NO_ERROR) { - ntfs_log_error("Failed to initialize the gcrypt library.\n"); - return -1; - } - /* Initialize GNU TLS library. Note: Must come after libgcrypt init. */ - err = gnutls_global_init(); - if (err < 0) { - ntfs_log_error("Failed to initialize GNU TLS library: %s\n", - gnutls_strerror(err)); - return -1; - } - /* Read crypto related sections of libntfs configuration files. */ - ntfs_crypto_read_configs(); - - ntfs_crypto_ctx.initialized = 1; - atexit(ntfs_crypto_deinit); - return 0; -} - - -/** - * ntfs_crypto_attr_open - perform crypto related initialization for attribute - * @na: ntfs attribute to perform initialization for - * - * This function is called from ntfs_attr_open for encrypted attributes and - * tries to decrypt FEK enumerating all user submitted RSA keys. If we - * successfully obtained FEK, then @na->crypto is allocated and FEK stored - * inside. In the other case @na->crypto is set to NULL. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_crypto_attr_open(ntfs_attr *na) -{ - ntfs_fek *fek; - int i; - - na->crypto = NULL; - if (!na || !NAttrEncrypted(na)) { - errno = EINVAL; - return -1; - } - if (ntfs_crypto_init()) { - errno = EACCES; - return -1; - } - - for (i = 0; i < ntfs_crypto_ctx.nr_rsa_keys; i++) { - fek = ntfs_inode_fek_get(na->ni, ntfs_crypto_ctx.rsa_key[i]); - if (fek) { - na->crypto = ntfs_malloc(sizeof(ntfs_crypto_attr)); - if (!na->crypto) - return -1; - na->crypto->fek = fek; - return 0; - } - } - - errno = EACCES; - return -1; -} - - -/** - * ntfs_crypto_attr_close - perform crypto related deinit for attribute - * @na: ntfs attribute to perform deinitialization for - * - * This function is called from ntfs_attr_close for encrypted attributes and - * frees memory that were allocated for it handling. - */ -void ntfs_crypto_attr_close(ntfs_attr *na) -{ - if (!na || !NAttrEncrypted(na)) - return; - - if (na->crypto) { - ntfs_fek_release(na->crypto->fek); - free(na->crypto); - } -} - - -/** - * ntfs_crypto_attr_pread - read from an encrypted attribute - * @na: ntfs attribute to read from - * @pos: byte position in the attribute to begin reading from - * @count: number of bytes to read - * @b: output data buffer - * - * This function is called from ntfs_attr_pread for encrypted attributes and - * should behave as described in ntfs_attr_pread description. - */ -s64 ntfs_crypto_attr_pread(ntfs_attr *na, const s64 pos, s64 count, void *b) -{ - unsigned char *buffer; - s64 bytes_read, offset, total, length; - int i; - - if (!na || pos < 0 || count < 0 || !b || !NAttrEncrypted(na)) { - errno = EINVAL; - return -1; - } - if (!count) - return 0; - - if (!na->crypto) { - errno = EACCES; - return -1; - } - - buffer = malloc(NTFS_EFS_SECTOR_SIZE); - if (!buffer) - return -1; - - ntfs_attr_map_runlist_range(na, pos >> na->ni->vol->cluster_size_bits, - (pos + count - 1) >> na->ni->vol->cluster_size_bits); - - total = 0; - offset = ROUND_DOWN(pos, 9); - while (total < count && offset < na->data_size) { - /* Calculate number of bytes we actually want. */ - length = NTFS_EFS_SECTOR_SIZE; - if (offset + length > pos + count) - length = pos + count - offset; - if (offset + length > na->data_size) - length = na->data_size - offset; - - if (length < 0) { - total = -1; - errno = EIO; - ntfs_log_error("LIBRARY BUG!!! Please report that you " - "saw this message to %s. Thanks!", - NTFS_DEV_LIST); - break; - } - - /* Just write zeros if @offset fully beyond initialized size. */ - if (offset >= na->initialized_size) { - memset(b + total, 0, length); - total += length; - continue; - } - - bytes_read = ntfs_rl_pread(na->ni->vol, na->rl, offset, - NTFS_EFS_SECTOR_SIZE, buffer); - if (!bytes_read) - break; - if (bytes_read != NTFS_EFS_SECTOR_SIZE) { - ntfs_log_perror("%s(): ntfs_rl_pread returned %lld " - "bytes", "ntfs_crypto_attr_pread", bytes_read); - break; - } - if ((i = ntfs_fek_decrypt_sector(na->crypto->fek, buffer, - offset)) < bytes_read) { - ntfs_log_error("%s(): Couldn't decrypt all data " - "(%u/%lld/%lld/%lld)!", "ntfs_crypto_attr_pread", - i, (long long)bytes_read, - (long long)offset, (long long)total); - break; - } - - /* Handle partially in initialized size situation. */ - if (offset + length > na->initialized_size) - memset(buffer + (na->initialized_size - offset), 0, - offset + length - na->initialized_size); - - if (offset >= pos) - memcpy(b + total, buffer, length); - else { - length -= (pos - offset); - memcpy(b + total, buffer + (pos - offset), length); - } - total += length; - offset += bytes_read; - } - - free(buffer); - return total; -} - -#else /* !ENABLE_CRYPTO */ - -/* Stubs for crypto-disabled version of libntfs. */ - -int ntfs_crypto_attr_open(ntfs_attr *na) -{ - na->crypto = NULL; - errno = EACCES; - return -1; -} - -void ntfs_crypto_attr_close(ntfs_attr *na) -{ -} - -s64 ntfs_crypto_attr_pread(ntfs_attr *na, const s64 pos, s64 count, - void *b) -{ - errno = EACCES; - return -1; -} - -#endif /* !ENABLE_CRYPTO */ - diff --git a/usr/src/lib/libntfs/common/libntfs/debug.c b/usr/src/lib/libntfs/common/libntfs/debug.c deleted file mode 100644 index 8962051006..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/debug.c +++ /dev/null @@ -1,73 +0,0 @@ -/** - * debug.c - Debugging output functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "runlist.h" -#include "debug.h" -#include "logging.h" - -#ifdef DEBUG -/** - * ntfs_debug_runlist_dump - Dump a runlist. - * @rl: - * - * Description... - * - * Returns: - */ -void ntfs_debug_runlist_dump(const runlist_element *rl) -{ - int i = 0; - const char *lcn_str[5] = { "LCN_HOLE ", "LCN_RL_NOT_MAPPED", - "LCN_ENOENT ", "LCN_EINVAL ", - "LCN_unknown " }; - - ntfs_log_debug("NTFS-fs DEBUG: Dumping runlist (values in hex):\n"); - if (!rl) { - ntfs_log_debug("Run list not present.\n"); - return; - } - ntfs_log_debug("VCN LCN Run length\n"); - do { - LCN lcn = (rl + i)->lcn; - - if (lcn < (LCN)0) { - int idx = -lcn - 1; - - if (idx > -LCN_EINVAL - 1) - idx = 4; - ntfs_log_debug("%-16llx %s %-16llx%s\n", rl[i].vcn, lcn_str[idx], rl[i].length, rl[i].length ? "" : " (runlist end)"); - } else - ntfs_log_debug("%-16llx %-16llx %-16llx%s\n", rl[i].vcn, rl[i].lcn, rl[i].length, rl[i].length ? "" : " (runlist end)"); - } while (rl[i++].length); -} - -#endif - diff --git a/usr/src/lib/libntfs/common/libntfs/device.c b/usr/src/lib/libntfs/common/libntfs/device.c deleted file mode 100644 index 89c2b1b2dc..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/device.c +++ /dev/null @@ -1,796 +0,0 @@ -/** - * device.c - Low level device io functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2004-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_SYS_PARAM_H -#include -#endif -#ifdef HAVE_SYS_MOUNT_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif -#ifdef HAVE_LINUX_HDREG_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "mst.h" -#include "debug.h" -#include "device.h" -#include "logging.h" - -#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE) -#define BLKGETSIZE _IO(0x12,96) /* Get device size in 512-byte blocks. */ -#endif -#if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64) -#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* Get device size in bytes. */ -#endif -#if defined(linux) && !defined(HDIO_GETGEO) -#define HDIO_GETGEO 0x0301 /* Get device geometry. */ -#endif -#if defined(linux) && defined(_IO) && !defined(BLKSSZGET) -# define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytes. */ -#endif -#if defined(linux) && defined(_IO) && !defined(BLKBSZSET) -# define BLKBSZSET _IOW(0x12,113,size_t) /* Set device block size in bytes. */ -#endif - -/** - * ntfs_device_alloc - allocate an ntfs device structure and pre-initialize it - * @name: name of the device (must be present) - * @state: initial device state (usually zero) - * @dops: ntfs device operations to use with the device (must be present) - * @priv_data: pointer to private data (optional) - * - * Allocate an ntfs device structure and pre-initialize it with the user- - * specified device operations @dops, device state @state, device name @name, - * and optional private data @priv_data. - * - * Note, @name is copied and can hence be freed after this functions returns. - * - * On success return a pointer to the allocated ntfs device structure and on - * error return NULL with errno set to the error code returned by malloc(). - */ -struct ntfs_device *ntfs_device_alloc(const char *name, const long state, - struct ntfs_device_operations *dops, void *priv_data) -{ - struct ntfs_device *dev; - - if (!name) { - errno = EINVAL; - return NULL; - } - - dev = (struct ntfs_device *)ntfs_malloc(sizeof(struct ntfs_device)); - if (dev) { - if (!(dev->d_name = strdup(name))) { - int eo = errno; - free(dev); - errno = eo; - return NULL; - } - dev->d_ops = dops; - dev->d_state = state; - dev->d_private = priv_data; - } - return dev; -} - -/** - * ntfs_device_free - free an ntfs device structure - * @dev: ntfs device structure to free - * - * Free the ntfs device structure @dev. - * - * Return 0 on success or -1 on error with errno set to the error code. The - * following error codes are defined: - * EINVAL Invalid pointer @dev. - * EBUSY Device is still open. Close it before freeing it! - */ -int ntfs_device_free(struct ntfs_device *dev) -{ - if (!dev) { - errno = EINVAL; - return -1; - } - if (NDevOpen(dev)) { - errno = EBUSY; - return -1; - } - free(dev->d_name); - free(dev); - return 0; -} - -/** - * fake_pread - read operation disguised as pread - * @dev: device to read from - * @b: output data buffer - * @count: number of bytes to read - * @pos: position in device to read from - * - * Auxiliary function, used when we emulate pread by seek() + a sequence of - * read()s. - */ -static s64 fake_pread(struct ntfs_device *dev, void *b, s64 count, - s64 pos __attribute__((unused))) -{ - return dev->d_ops->read(dev, b, count); -} - -/** - * ntfs_pread - positioned read from disk - * @dev: device to read from - * @pos: position in device to read from - * @count: number of bytes to read - * @b: output data buffer - * - * This function will read @count bytes from device @dev at position @pos into - * the data buffer @b. - * - * On success, return the number of successfully read bytes. If this number is - * lower than @count this means that we have either reached end of file or - * encountered an error during the read so that the read is partial. 0 means - * end of file or nothing to read (@count is 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of either seek, read, or set to EINVAL in case of - * invalid arguments. - */ -s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, void *b) -{ - s64 br, total; - struct ntfs_device_operations *dops; - s64 (*_pread)(struct ntfs_device *, void *, s64, s64); - - ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count); - if (!b || count < 0 || pos < 0) { - errno = EINVAL; - return -1; - } - if (!count) - return 0; - dops = dev->d_ops; - _pread = dops->pread; - if (!_pread) - _pread = fake_pread; -seek: - /* Locate to position if pread is to be emulated by seek() + read(). */ - if (_pread == fake_pread && - dops->seek(dev, pos, SEEK_SET) == (off_t)-1) { - ntfs_log_perror("ntfs_pread: device seek to 0x%llx returned " - "error", pos); - return -1; - } - /* Read the data. */ - for (total = 0; count; count -= br, total += br) { - br = _pread(dev, (char*)b + total, count, pos + total); - /* If everything ok, continue. */ - if (br > 0) - continue; - /* If EOF or error return number of bytes read. */ - if (!br || total) - return total; - /* - * If pread is not supported by the OS, fall back to emulating - * it by seek() + read() and set the device pread() pointer to - * NULL so we automatically use seek() + read() from now on. - */ - if (errno == ENOSYS && _pread != fake_pread) { - _pread = fake_pread; - dops->pread = NULL; - goto seek; - } - /* Nothing read and error, return error status. */ - return br; - } - /* Finally, return the number of bytes read. */ - return total; -} - -/** - * fake_pwrite - write operation disguised as pwrite - * @dev: device to write to - * @b: input data buffer - * @count: number of bytes to write - * @pos: position in device to write to - * - * Auxiliary function, used when we emulate pwrite by seek() + a sequence of - * write()s. - */ -static s64 fake_pwrite(struct ntfs_device *dev, const void *b, s64 count, - s64 pos __attribute__((unused))) -{ - return dev->d_ops->write(dev, b, count); -} - -/** - * ntfs_pwrite - positioned write to disk - * @dev: device to write to - * @pos: position in file descriptor to write to - * @count: number of bytes to write - * @b: data buffer to write to disk - * - * This function will write @count bytes from data buffer @b to the device @dev - * at position @pos. - * - * On success, return the number of successfully written bytes. If this number - * is lower than @count this means that the write has been interrupted in - * flight or that an error was encountered during the write so that the write - * is partial. 0 means nothing was written (also return 0 when @count is 0). - * - * On error and nothing has been written, return -1 with errno set - * appropriately to the return code of either seek, write, or set - * to EINVAL in case of invalid arguments. - */ -s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, - const void *b) -{ - s64 written, total; - struct ntfs_device_operations *dops; - s64 (*_pwrite)(struct ntfs_device *, const void *, s64, s64); - - ntfs_log_trace("Entering for pos 0x%llx, count 0x%llx.\n", pos, count); - if (!b || count < 0 || pos < 0) { - errno = EINVAL; - return -1; - } - if (!count) - return 0; - if (NDevReadOnly(dev)) { - errno = EROFS; - return -1; - } - dops = dev->d_ops; - _pwrite = dops->pwrite; - if (!_pwrite) - _pwrite = fake_pwrite; -seek: - /* - * Locate to position if pwrite is to be emulated by seek() + write(). - */ - if (_pwrite == fake_pwrite && - dops->seek(dev, pos, SEEK_SET) == (off_t)-1) { - ntfs_log_perror("ntfs_pwrite: seek to 0x%llx returned error", - pos); - return -1; - } - NDevSetDirty(dev); - /* Write the data. */ - for (total = 0; count; count -= written, total += written) { - written = _pwrite(dev, (const char*)b + total, count, - pos + total); - /* If everything ok, continue. */ - if (written > 0) - continue; - /* - * If nothing written or error return number of bytes written. - */ - if (!written || total) - break; - /* - * If pwrite is not supported by the OS, fall back to emulating - * it by seek() + write() and set the device pwrite() pointer - * to NULL so we automatically use seek() + write() from now - * on. - */ - if (errno == ENOSYS && _pwrite != fake_pwrite) { - _pwrite = fake_pwrite; - dops->pwrite = NULL; - goto seek; - } - /* Nothing written and error, return error status. */ - return written; - } - /* Finally, return the number of bytes written. */ - return total; -} - -/** - * ntfs_mst_pread - multi sector transfer (mst) positioned read - * @dev: device to read from - * @pos: position in file descriptor to read from - * @count: number of blocks to read - * @bksize: size of each block that needs mst deprotecting - * @b: output data buffer - * - * Multi sector transfer (mst) positioned read. This function will read @count - * blocks of size @bksize bytes each from device @dev at position @pos into the - * the data buffer @b. - * - * On success, return the number of successfully read blocks. If this number is - * lower than @count this means that we have reached end of file, that the read - * was interrupted, or that an error was encountered during the read so that - * the read is partial. 0 means end of file or nothing was read (also return 0 - * when @count or @bksize are 0). - * - * On error and nothing was read, return -1 with errno set appropriately to the - * return code of either seek, read, or set to EINVAL in case of invalid - * arguments. - * - * NOTE: If an incomplete multi sector transfer has been detected the magic - * will have been changed to magic_BAAD but no error will be returned. Thus it - * is possible that we return count blocks as being read but that any number - * (between zero and count!) of these blocks is actually subject to a multi - * sector transfer error. This should be detected by the caller by checking for - * the magic being "BAAD". - */ -s64 ntfs_mst_pread(struct ntfs_device *dev, const s64 pos, s64 count, - const u32 bksize, void *b) -{ - s64 br, i; - - if (bksize & (bksize - 1) || bksize % NTFS_BLOCK_SIZE) { - errno = EINVAL; - return -1; - } - /* Do the read. */ - br = ntfs_pread(dev, pos, count * bksize, b); - if (br < 0) - return br; - /* - * Apply fixups to successfully read data, disregarding any errors - * returned from the MST fixup function. This is because we want to - * fixup everything possible and we rely on the fact that the "BAAD" - * magic will be detected later on. - */ - count = br / bksize; - for (i = 0; i < count; ++i) - ntfs_mst_post_read_fixup((NTFS_RECORD*) - ((u8*)b + i * bksize), bksize); - /* Finally, return the number of complete blocks read. */ - return count; -} - -/** - * ntfs_mst_pwrite - multi sector transfer (mst) positioned write - * @dev: device to write to - * @pos: position in file descriptor to write to - * @count: number of blocks to write - * @bksize: size of each block that needs mst protecting - * @b: data buffer to write to disk - * - * Multi sector transfer (mst) positioned write. This function will write - * @count blocks of size @bksize bytes each from data buffer @b to the device - * @dev at position @pos. - * - * On success, return the number of successfully written blocks. If this number - * is lower than @count this means that the write has been interrupted or that - * an error was encountered during the write so that the write is partial. 0 - * means nothing was written (also return 0 when @count or @bksize are 0). - * - * On error and nothing has been written, return -1 with errno set - * appropriately to the return code of either seek, write, or set - * to EINVAL in case of invalid arguments. - * - * NOTE: We mst protect the data, write it, then mst deprotect it using a quick - * deprotect algorithm (no checking). This saves us from making a copy before - * the write and at the same time causes the usn to be incremented in the - * buffer. This conceptually fits in better with the idea that cached data is - * always deprotected and protection is performed when the data is actually - * going to hit the disk and the cache is immediately deprotected again - * simulating an mst read on the written data. This way cache coherency is - * achieved. - */ -s64 ntfs_mst_pwrite(struct ntfs_device *dev, const s64 pos, s64 count, - const u32 bksize, void *b) -{ - s64 written, i; - - if (count < 0 || bksize % NTFS_BLOCK_SIZE) { - errno = EINVAL; - return -1; - } - if (!count) - return 0; - /* Prepare data for writing. */ - for (i = 0; i < count; ++i) { - int err; - - err = ntfs_mst_pre_write_fixup((NTFS_RECORD*) - ((u8*)b + i * bksize), bksize); - if (err < 0) { - /* Abort write at this position. */ - if (!i) - return err; - count = i; - break; - } - } - /* Write the prepared data. */ - written = ntfs_pwrite(dev, pos, count * bksize, b); - /* Quickly deprotect the data again. */ - for (i = 0; i < count; ++i) - ntfs_mst_post_write_fixup((NTFS_RECORD*)((u8*)b + i * bksize)); - if (written <= 0) - return written; - /* Finally, return the number of complete blocks written. */ - return written / bksize; -} - -/** - * ntfs_cluster_read - read ntfs clusters - * @vol: volume to read from - * @lcn: starting logical cluster number - * @count: number of clusters to read - * @b: output data buffer - * - * Read @count ntfs clusters starting at logical cluster number @lcn from - * volume @vol into buffer @b. Return number of clusters read or -1 on error, - * with errno set to the error code. - */ -s64 ntfs_cluster_read(const ntfs_volume *vol, const s64 lcn, const s64 count, - void *b) -{ - s64 br; - - if (!vol || lcn < 0 || count < 0) { - errno = EINVAL; - return -1; - } - if (vol->nr_clusters < lcn + count) { - errno = ESPIPE; - return -1; - } - br = ntfs_pread(vol->u.dev, lcn << vol->cluster_size_bits, - count << vol->cluster_size_bits, b); - if (br < 0) { - ntfs_log_perror("Error reading cluster(s)"); - return br; - } - return br >> vol->cluster_size_bits; -} - -/** - * ntfs_cluster_write - write ntfs clusters - * @vol: volume to write to - * @lcn: starting logical cluster number - * @count: number of clusters to write - * @b: data buffer to write to disk - * - * Write @count ntfs clusters starting at logical cluster number @lcn from - * buffer @b to volume @vol. Return the number of clusters written or -1 on - * error, with errno set to the error code. - */ -s64 ntfs_cluster_write(const ntfs_volume *vol, const s64 lcn, - const s64 count, const void *b) -{ - s64 bw; - - if (!vol || lcn < 0 || count < 0) { - errno = EINVAL; - return -1; - } - if (vol->nr_clusters < lcn + count) { - errno = ESPIPE; - return -1; - } - if (!NVolReadOnly(vol)) - bw = ntfs_pwrite(vol->u.dev, lcn << vol->cluster_size_bits, - count << vol->cluster_size_bits, b); - else - bw = count << vol->cluster_size_bits; - if (bw < 0) { - ntfs_log_perror("Error writing cluster(s)"); - return bw; - } - return bw >> vol->cluster_size_bits; -} - -/** - * ntfs_device_offset_valid - test if a device offset is valid - * @dev: open device - * @ofs: offset to test for validity - * - * Test if the offset @ofs is an existing location on the device described - * by the open device structure @dev. - * - * Return 0 if it is valid and -1 if it is not valid. - */ -static int ntfs_device_offset_valid(struct ntfs_device *dev, s64 ofs) -{ - char ch; - - if (dev->d_ops->seek(dev, ofs, SEEK_SET) >= 0 && - dev->d_ops->read(dev, &ch, 1) == 1) - return 0; - return -1; -} - -/** - * ntfs_device_size_get - return the size of a device in blocks - * @dev: open device - * @block_size: block size in bytes in which to return the result - * - * Return the number of @block_size sized blocks in the device described by the - * open device @dev. - * - * Adapted from e2fsutils-1.19, Copyright (C) 1995 Theodore Ts'o. - * - * On error return -1 with errno set to the error code. - */ -s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size) -{ - s64 high, low; - - if (!dev || block_size <= 0 || (block_size - 1) & block_size) { - errno = EINVAL; - return -1; - } -#ifdef BLKGETSIZE64 - { u64 size; - - if (dev->d_ops->ioctl(dev, BLKGETSIZE64, &size) >= 0) { - ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu (0x%llx)\n", - (unsigned long long)size, - (unsigned long long)size); - return (s64)size / block_size; - } - } -#endif -#ifdef BLKGETSIZE - { unsigned long size; - - if (dev->d_ops->ioctl(dev, BLKGETSIZE, &size) >= 0) { - ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu (0x%lx)\n", - size, size); - return (s64)size * 512 / block_size; - } - } -#endif -#ifdef FDGETPRM - { struct floppy_struct this_floppy; - - if (dev->d_ops->ioctl(dev, FDGETPRM, &this_floppy) >= 0) { - ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu (0x%lx)\n", - (unsigned long)this_floppy.size, - (unsigned long)this_floppy.size); - return (s64)this_floppy.size * 512 / block_size; - } - } -#endif - /* - * We couldn't figure it out by using a specialized ioctl, - * so do binary search to find the size of the device. - */ - low = 0LL; - for (high = 1024LL; !ntfs_device_offset_valid(dev, high); high <<= 1) - low = high; - while (low < high - 1LL) { - const s64 mid = (low + high) / 2; - - if (!ntfs_device_offset_valid(dev, mid)) - low = mid; - else - high = mid; - } - dev->d_ops->seek(dev, 0LL, SEEK_SET); - return (low + 1LL) / block_size; -} - -/** - * ntfs_device_partition_start_sector_get - get starting sector of a partition - * @dev: open device - * - * On success, return the starting sector of the partition @dev in the parent - * block device of @dev. On error return -1 with errno set to the error code. - * - * The following error codes are defined: - * EINVAL Input parameter error - * EOPNOTSUPP System does not support HDIO_GETGEO ioctl - * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO - */ -s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev) -{ - if (!dev) { - errno = EINVAL; - return -1; - } -#ifdef HDIO_GETGEO - { struct hd_geometry geo; - - if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) { - ntfs_log_debug("HDIO_GETGEO start_sect = %lu (0x%lx)\n", - geo.start, geo.start); - return geo.start; - } - } -#else - errno = EOPNOTSUPP; -#endif - return -1; -} - -/** - * ntfs_device_heads_get - get number of heads of device - * @dev: open device - * - * On success, return the number of heads on the device @dev. On error return - * -1 with errno set to the error code. - * - * The following error codes are defined: - * EINVAL Input parameter error - * EOPNOTSUPP System does not support HDIO_GETGEO ioctl - * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO - */ -int ntfs_device_heads_get(struct ntfs_device *dev) -{ - if (!dev) { - errno = EINVAL; - return -1; - } -#ifdef HDIO_GETGEO - { struct hd_geometry geo; - - if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) { - ntfs_log_debug("HDIO_GETGEO heads = %u (0x%x)\n", - (unsigned)geo.heads, - (unsigned)geo.heads); - return geo.heads; - } - } -#else - errno = EOPNOTSUPP; -#endif - return -1; -} - -/** - * ntfs_device_sectors_per_track_get - get number of sectors per track of device - * @dev: open device - * - * On success, return the number of sectors per track on the device @dev. On - * error return -1 with errno set to the error code. - * - * The following error codes are defined: - * EINVAL Input parameter error - * EOPNOTSUPP System does not support HDIO_GETGEO ioctl - * ENOTTY @dev is a file or a device not supporting HDIO_GETGEO - */ -int ntfs_device_sectors_per_track_get(struct ntfs_device *dev) -{ - if (!dev) { - errno = EINVAL; - return -1; - } -#ifdef HDIO_GETGEO - { struct hd_geometry geo; - - if (!dev->d_ops->ioctl(dev, HDIO_GETGEO, &geo)) { - ntfs_log_debug("HDIO_GETGEO sectors_per_track = %u (0x%x)\n", - (unsigned)geo.sectors, - (unsigned)geo.sectors); - return geo.sectors; - } - } -#else - errno = EOPNOTSUPP; -#endif - return -1; -} - -/** - * ntfs_device_sector_size_get - get sector size of a device - * @dev: open device - * - * On success, return the sector size in bytes of the device @dev. - * On error return -1 with errno set to the error code. - * - * The following error codes are defined: - * EINVAL Input parameter error - * EOPNOTSUPP System does not support BLKSSZGET ioctl - * ENOTTY @dev is a file or a device not supporting BLKSSZGET - */ -int ntfs_device_sector_size_get(struct ntfs_device *dev) -{ - if (!dev) { - errno = EINVAL; - return -1; - } -#ifdef BLKSSZGET - { - int sect_size = 0; - - if (!dev->d_ops->ioctl(dev, BLKSSZGET, §_size)) { - ntfs_log_debug("BLKSSZGET sector size = %d bytes\n", - sect_size); - return sect_size; - } - } -#else - errno = EOPNOTSUPP; -#endif - return -1; -} - -/** - * ntfs_device_block_size_set - set block size of a device - * @dev: open device - * @block_size: block size to set @dev to - * - * On success, return 0. - * On error return -1 with errno set to the error code. - * - * The following error codes are defined: - * EINVAL Input parameter error - * EOPNOTSUPP System does not support BLKBSZSET ioctl - * ENOTTY @dev is a file or a device not supporting BLKBSZSET - */ -int ntfs_device_block_size_set(struct ntfs_device *dev, - int block_size __attribute__((unused))) -{ - if (!dev) { - errno = EINVAL; - return -1; - } -#ifdef BLKBSZSET - { - size_t s_block_size = block_size; - if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) { - ntfs_log_debug("Used BLKBSZSET to set block size to " - "%d bytes.\n", block_size); - return 0; - } - /* If not a block device, pretend it was successful. */ - if (!NDevBlock(dev)) - return 0; - } -#else - /* If not a block device, pretend it was successful. */ - if (!NDevBlock(dev)) - return 0; - errno = EOPNOTSUPP; -#endif - return -1; -} diff --git a/usr/src/lib/libntfs/common/libntfs/device_io.c b/usr/src/lib/libntfs/common/libntfs/device_io.c deleted file mode 100644 index 706e935f34..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/device_io.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * device_io.c - Default device io operations. Part of the Linux-NTFS project. - * - * Copyright (c) 2003-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "config.h" - -#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS - -#if defined(__CYGWIN32__) - -/* On Cygwin; use Win32 low level device operations. */ -#include "win32_io.c" - -#elif defined(__FreeBSD__) - -/* On FreeBSD; need to use sector aligned i/o. */ -#include "freebsd_io.c" - -#else - -/* - * Not on Cygwin or FreeBSD; use standard Unix style low level device - * operations. - */ -#include "unix_io.c" - -#endif - -#endif /* NO_NTFS_DEVICE_DEFAULT_IO_OPS */ diff --git a/usr/src/lib/libntfs/common/libntfs/dir.c b/usr/src/lib/libntfs/common/libntfs/dir.c deleted file mode 100644 index b112c73205..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/dir.c +++ /dev/null @@ -1,1773 +0,0 @@ -/** - * dir.c - Directory handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif - -#ifdef HAVE_SYS_SYSMACROS_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "debug.h" -#include "attrib.h" -#include "inode.h" -#include "dir.h" -#include "volume.h" -#include "mft.h" -#include "index.h" -#include "ntfstime.h" -#include "lcnalloc.h" -#include "logging.h" - -/* - * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O" - * and "$Q" as global constants. - */ -ntfschar NTFS_INDEX_I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), - const_cpu_to_le16('3'), const_cpu_to_le16('0'), - const_cpu_to_le16('\0') }; -ntfschar NTFS_INDEX_SII[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'), - const_cpu_to_le16('I'), const_cpu_to_le16('I'), - const_cpu_to_le16('\0') }; -ntfschar NTFS_INDEX_SDH[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'), - const_cpu_to_le16('D'), const_cpu_to_le16('H'), - const_cpu_to_le16('\0') }; -ntfschar NTFS_INDEX_O[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('O'), - const_cpu_to_le16('\0') }; -ntfschar NTFS_INDEX_Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'), - const_cpu_to_le16('\0') }; -ntfschar NTFS_INDEX_R[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('R'), - const_cpu_to_le16('\0') }; - -/** - * ntfs_inode_lookup_by_name - find an inode in a directory given its name - * @dir_ni: ntfs inode of the directory in which to search for the name - * @uname: Unicode name for which to search in the directory - * @uname_len: length of the name @uname in Unicode characters - * - * Look for an inode with name @uname in the directory with inode @dir_ni. - * ntfs_inode_lookup_by_name() walks the contents of the directory looking for - * the Unicode name. If the name is found in the directory, the corresponding - * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it - * is a 64-bit number containing the sequence number. - * - * On error, return -1 with errno set to the error code. If the inode is is not - * found errno is ENOENT. - * - * Note, @uname_len does not include the (optional) terminating NULL character. - * - * Note, we look for a case sensitive match first but we also look for a case - * insensitive match at the same time. If we find a case insensitive match, we - * save that for the case that we don't find an exact match, where we return - * the mft reference of the case insensitive match. - * - * If the volume is mounted with the case sensitive flag set, then we only - * allow exact matches. - */ -u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname, - const int uname_len) -{ - VCN vcn; - u64 mref = 0; - s64 br; - ntfs_volume *vol = dir_ni->vol; - ntfs_attr_search_ctx *ctx; - INDEX_ROOT *ir; - INDEX_ENTRY *ie; - INDEX_ALLOCATION *ia; - u8 *index_end; - ntfs_attr *ia_na; - int eo, rc; - u32 index_block_size, index_vcn_size; - u8 index_vcn_size_bits; - - if (!dir_ni || !dir_ni->mrec || !uname || uname_len <= 0) { - errno = EINVAL; - return -1; - } - - ctx = ntfs_attr_get_search_ctx(dir_ni, NULL); - if (!ctx) - return -1; - - /* Find the index root attribute in the mft record. */ - if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - ntfs_log_perror("Index root attribute missing in directory " - "inode 0x%llx", (unsigned long long)dir_ni-> - mft_no); - goto put_err_out; - } - /* Get to the index root value. */ - ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - index_block_size = le32_to_cpu(ir->index_block_size); - if (index_block_size < NTFS_BLOCK_SIZE || - index_block_size & (index_block_size - 1)) { - ntfs_log_debug("Index block size %u is invalid.\n", - (unsigned)index_block_size); - goto put_err_out; - } - index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); - /* The first index entry. */ - ie = (INDEX_ENTRY*)((u8*)&ir->index + - le32_to_cpu(ir->index.entries_offset)); - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry. - */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { - /* Bounds checks. */ - if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + - sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->key_length) > - index_end) - goto put_err_out; - /* - * The last entry cannot contain a name. It can however contain - * a pointer to a child node in the B+tree so we just break out. - */ - if (ie->flags & INDEX_ENTRY_END) - break; - /* - * We perform a case sensitive comparison and if that matches - * we are done and return the mft reference of the inode (i.e. - * the inode number together with the sequence number for - * consistency checking). We convert it to cpu format before - * returning. - */ - if (ntfs_names_are_equal(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, - CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { -found_it: - /* - * We have a perfect match, so we don't need to care - * about having matched imperfectly before. - */ - mref = le64_to_cpu(ie->u.indexed_file); - ntfs_attr_put_search_ctx(ctx); - return mref; - } - /* - * For a case insensitive mount, we also perform a case - * insensitive comparison. If the comparison matches, we cache - * the mft reference in mref. Use first case insensitive match - * in case if no name matches case sensitive, but several names - * matches case insensitive. - */ - if (!mref && !NVolCaseSensitive(vol) && - ntfs_names_are_equal(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, - IGNORE_CASE, vol->upcase, vol->upcase_len)) - mref = le64_to_cpu(ie->u.indexed_file); - /* - * Not a perfect match, need to do full blown collation so we - * know which way in the B+tree we have to go. - */ - rc = ntfs_names_collate(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, 1, - IGNORE_CASE, vol->upcase, vol->upcase_len); - /* - * If uname collates before the name of the current entry, there - * is definitely no such name in this index but we might need to - * descend into the B+tree so we just break out of the loop. - */ - if (rc == -1) - break; - /* The names are not equal, continue the search. */ - if (rc) - continue; - /* - * Names match with case insensitive comparison, now try the - * case sensitive comparison, which is required for proper - * collation. - */ - rc = ntfs_names_collate(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, 1, - CASE_SENSITIVE, vol->upcase, vol->upcase_len); - if (rc == -1) - break; - if (rc) - continue; - /* - * Perfect match, this will never happen as the - * ntfs_are_names_equal() call will have gotten a match but we - * still treat it correctly. - */ - goto found_it; - } - /* - * We have finished with this index without success. Check for the - * presence of a child node and if not present return error code - * ENOENT, unless we have got the mft reference of a matching name - * cached in mref in which case return mref. - */ - if (!(ie->flags & INDEX_ENTRY_NODE)) { - ntfs_attr_put_search_ctx(ctx); - if (mref) - return mref; - ntfs_log_debug("Entry not found.\n"); - errno = ENOENT; - return -1; - } /* Child node present, descend into it. */ - - /* Open the index allocation attribute. */ - ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); - if (!ia_na) { - ntfs_log_perror("Failed to open index allocation attribute. " - "Directory inode 0x%llx is corrupt or driver " - "bug", (unsigned long long)dir_ni->mft_no); - goto put_err_out; - } - - /* Allocate a buffer for the current index block. */ - ia = (INDEX_ALLOCATION*)malloc(index_block_size); - if (!ia) { - ntfs_log_perror("Failed to allocate buffer for index block"); - ntfs_attr_close(ia_na); - goto put_err_out; - } - - /* Determine the size of a vcn in the directory index. */ - if (vol->cluster_size <= index_block_size) { - index_vcn_size = vol->cluster_size; - index_vcn_size_bits = vol->cluster_size_bits; - } else { - index_vcn_size = vol->sector_size; - index_vcn_size_bits = vol->sector_size_bits; - } - - /* Get the starting vcn of the index_block holding the child node. */ - vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); - -descend_into_child_node: - - /* Read the index block starting at vcn. */ - br = ntfs_attr_mst_pread(ia_na, vcn << index_vcn_size_bits, 1, - index_block_size, ia); - if (br != 1) { - if (br != -1) - errno = EIO; - ntfs_log_perror("Failed to read vcn 0x%llx", - (unsigned long long)vcn); - goto close_err_out; - } - - if (sle64_to_cpu(ia->index_block_vcn) != vcn) { - ntfs_log_debug("Actual VCN (0x%llx) of index buffer is " - "different from expected VCN (0x%llx).\n", - (long long)sle64_to_cpu(ia->index_block_vcn), - (long long)vcn); - errno = EIO; - goto close_err_out; - } - if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) { - ntfs_log_debug("Index buffer (VCN 0x%llx) of directory inode " - "0x%llx has a size (%u) differing from the " - "directory specified size (%u).\n", - (long long)vcn, (unsigned long long)dir_ni-> - mft_no, (unsigned)le32_to_cpu(ia->index. - allocated_size) + 0x18, (unsigned) - index_block_size); - errno = EIO; - goto close_err_out; - } - index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); - if (index_end > (u8*)ia + index_block_size) { - ntfs_log_debug("Size of index buffer (VCN 0x%llx) of directory " - "inode 0x%llx exceeds maximum size.\n", - (long long)vcn, (unsigned long long)dir_ni-> - mft_no); - errno = EIO; - goto close_err_out; - } - - /* The first index entry. */ - ie = (INDEX_ENTRY*)((u8*)&ia->index + - le32_to_cpu(ia->index.entries_offset)); - /* - * Iterate similar to above big loop but applied to index buffer, thus - * loop until we exceed valid memory (corruption case) or until we - * reach the last entry. - */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { - /* Bounds check. */ - if ((u8*)ie < (u8*)ia || (u8*)ie + - sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->key_length) > - index_end) { - ntfs_log_debug("Index entry out of bounds in directory " - "inode 0x%llx.\n", - (unsigned long long)dir_ni->mft_no); - errno = EIO; - goto close_err_out; - } - /* - * The last entry cannot contain a name. It can however contain - * a pointer to a child node in the B+tree so we just break out. - */ - if (ie->flags & INDEX_ENTRY_END) - break; - /* - * We perform a case sensitive comparison and if that matches - * we are done and return the mft reference of the inode (i.e. - * the inode number together with the sequence number for - * consistency checking). We convert it to cpu format before - * returning. - */ - if (ntfs_names_are_equal(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, - CASE_SENSITIVE, vol->upcase, vol->upcase_len)) { -found_it2: - /* - * We have a perfect match, so we don't need to care - * about having matched imperfectly before. - */ - mref = le64_to_cpu(ie->u.indexed_file); - free(ia); - ntfs_attr_close(ia_na); - ntfs_attr_put_search_ctx(ctx); - return mref; - } - /* - * For a case insensitive mount, we also perform a case - * insensitive comparison. If the comparison matches, we cache - * the mft reference in mref. Use first case insensitive match - * in case if no name matches case sensitive, but several names - * matches case insensitive. - */ - if (!mref && !NVolCaseSensitive(vol) && - ntfs_names_are_equal(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, - IGNORE_CASE, vol->upcase, vol->upcase_len)) - mref = le64_to_cpu(ie->u.indexed_file); - /* - * Not a perfect match, need to do full blown collation so we - * know which way in the B+tree we have to go. - */ - rc = ntfs_names_collate(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, 1, - IGNORE_CASE, vol->upcase, vol->upcase_len); - /* - * If uname collates before the name of the current entry, there - * is definitely no such name in this index but we might need to - * descend into the B+tree so we just break out of the loop. - */ - if (rc == -1) - break; - /* The names are not equal, continue the search. */ - if (rc) - continue; - /* - * Names match with case insensitive comparison, now try the - * case sensitive comparison, which is required for proper - * collation. - */ - rc = ntfs_names_collate(uname, uname_len, - (ntfschar*)&ie->key.file_name.file_name, - ie->key.file_name.file_name_length, 1, - CASE_SENSITIVE, vol->upcase, vol->upcase_len); - if (rc == -1) - break; - if (rc) - continue; - /* - * Perfect match, this will never happen as the - * ntfs_are_names_equal() call will have gotten a match but we - * still treat it correctly. - */ - goto found_it2; - } - /* - * We have finished with this index buffer without success. Check for - * the presence of a child node. - */ - if (ie->flags & INDEX_ENTRY_NODE) { - if ((ia->index.flags & NODE_MASK) == LEAF_NODE) { - ntfs_log_debug("Index entry with child node found in a " - "leaf node in directory inode " - "0x%llx.\n", - (unsigned long long)dir_ni->mft_no); - errno = EIO; - goto close_err_out; - } - /* Child node present, descend into it. */ - vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); - if (vcn >= 0) - goto descend_into_child_node; - ntfs_log_debug("Negative child node vcn in directory inode " - "0x%llx.\n", (unsigned long long)dir_ni-> - mft_no); - errno = EIO; - goto close_err_out; - } - free(ia); - ntfs_attr_close(ia_na); - ntfs_attr_put_search_ctx(ctx); - /* - * No child node present, return error code ENOENT, unless we have got - * the mft reference of a matching name cached in mref in which case - * return mref. - */ - if (mref) - return mref; - ntfs_log_debug("Entry not found.\n"); - errno = ENOENT; - return -1; -put_err_out: - eo = EIO; - ntfs_log_debug("Corrupt directory. Aborting lookup.\n"); -eo_put_err_out: - ntfs_attr_put_search_ctx(ctx); - errno = eo; - return -1; -close_err_out: - eo = errno; - free(ia); - ntfs_attr_close(ia_na); - goto eo_put_err_out; -} - -/** - * ntfs_pathname_to_inode_num - find the inode number which represents the - * given pathname - * @vol: An ntfs volume obtained from ntfs_mount - * @parent: A directory inode to begin the search (may be NULL) - * @pathname: Pathname to be located - * - * Take an ASCII pathname and find the inode that represents it. The function - * splits the path and then descends the directory tree. If @parent is NULL, - * then the root directory '.' will be used as the base for the search. - * - * Return: -1 Error, the pathname was invalid, or some other error occurred - * else Success, the pathname was valid - */ -u64 ntfs_pathname_to_inode_num(ntfs_volume *vol, ntfs_inode *parent, - const char *pathname) -{ - u64 inum, result; - int len, err = 0; - char *p, *q; - ntfs_inode *ni = NULL; - ntfschar *unicode = NULL; - char *ascii = NULL; - - inum = result = (u64)-1; - if (!vol || !pathname) { - err = EINVAL; - goto close; - } - ntfs_log_trace("Path: '%s'\n", pathname); - if (parent) { - ni = parent; - } else - inum = FILE_root; - unicode = calloc(1, MAX_PATH); - ascii = strdup(pathname); - if (!unicode || !ascii) { - ntfs_log_error("Out of memory.\n"); - err = ENOMEM; - goto close; - } - p = ascii; - /* Remove leading /'s. */ - while (p && *p == PATH_SEP) - p++; - while (p && *p) { - if (!ni) { - ni = ntfs_inode_open(vol, inum); - if (!ni) { - ntfs_log_debug("Cannot open inode %llu.\n", - (unsigned long long)inum); - err = EIO; - goto close; - } - } - /* Find the end of the first token. */ - q = strchr(p, PATH_SEP); - if (q != NULL) { - *q = 0; - q++; - } - len = ntfs_mbstoucs(p, &unicode, MAX_PATH); - if (len < 0) { - ntfs_log_debug("Couldn't convert name to Unicode: " - "%s.\n", p); - err = EILSEQ; - goto close; - } - inum = ntfs_inode_lookup_by_name(ni, unicode, len); - if (inum == (u64)-1) { - ntfs_log_debug("Couldn't find name '%s' in pathname " - "'%s'.\n", p, pathname); - err = ENOENT; - goto close; - } - inum = MREF(inum); - if (ni != parent) - ntfs_inode_close(ni); - ni = NULL; - p = q; - while (p && *p == PATH_SEP) - p++; - } - result = inum; -close: - if (ni && (ni != parent)) - ntfs_inode_close(ni); - free(ascii); - free(unicode); - if (err) - errno = err; - return result; -} - -/** - * ntfs_pathname_to_inode - Find the inode which represents the given pathname - * @vol: An ntfs volume obtained from ntfs_mount - * @parent: A directory inode to begin the search (may be NULL) - * @pathname: Pathname to be located - * - * Take an ASCII pathname and find the inode that represents it. The function - * splits the path and then descends the directory tree. If @parent is NULL, - * then the root directory '.' will be used as the base for the search. - * - * Return: inode Success, the pathname was valid - * NULL Error, the pathname was invalid, or some other error occurred - */ -ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, - const char *pathname) -{ - u64 inum; - - inum = ntfs_pathname_to_inode_num(vol, parent, pathname); - if (inum == (u64)-1) - return NULL; - return ntfs_inode_open(vol, inum); -} - -/* - * The little endian Unicode string ".." for ntfs_readdir(). - */ -static const ntfschar dotdot[3] = { const_cpu_to_le16('.'), - const_cpu_to_le16('.'), - const_cpu_to_le16('\0') }; - -/** - * ntfs_filldir - ntfs specific filldir method - * @vol: ntfs volume with wjich we are working - * @pos: current position in directory - * @ie: current index entry - * @dirent: context for filldir callback supplied by the caller - * @filldir: filldir callback supplied by the caller - * - * Pass information specifying the current directory entry @ie to the @filldir - * callback. - */ -static int ntfs_filldir(ntfs_volume *vol, s64 *pos, INDEX_ENTRY *ie, - void *dirent, ntfs_filldir_t filldir) -{ - FILE_NAME_ATTR *fn = &ie->key.file_name; - unsigned dt_type; - - ntfs_log_trace("Entering.\n"); - - /* Skip root directory self reference entry. */ - if (MREF_LE(ie->u.indexed_file) == FILE_root) - return 0; - if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT) - dt_type = NTFS_DT_DIR; - else { - if (NVolInterix(vol) && fn->file_attributes & FILE_ATTR_SYSTEM) - dt_type = NTFS_DT_UNKNOWN; - else - dt_type = NTFS_DT_REG; - } - return filldir(dirent, fn->file_name, fn->file_name_length, - fn->file_name_type, *pos, - le64_to_cpu(ie->u.indexed_file), dt_type); -} - -/** - * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode - * @ni: ntfs inode whose parent directory to find - * - * Find the parent directory of the ntfs inode @ni. To do this, find the first - * file name attribute in the mft record of @ni and return the parent mft - * reference from that. - * - * Note this only makes sense for directories, since files can be hard linked - * from multiple directories and there is no way for us to tell which one is - * being looked for. - * - * Technically directories can have hard links, too, but we consider that as - * illegal as Linux/UNIX do not support directory hard links. - * - * Return the mft reference of the parent directory on success or -1 on error - * with errno set to the error code. - */ -static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) -{ - MFT_REF mref; - ntfs_attr_search_ctx *ctx; - FILE_NAME_ATTR *fn; - int eo; - - ntfs_log_trace("Entering.\n"); - - if (!ni) { - errno = EINVAL; - return ERR_MREF(-1); - } - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return ERR_MREF(-1); - if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { - ntfs_log_debug("No file name found in inode 0x%llx. Corrupt " - "inode.\n", (unsigned long long)ni->mft_no); - goto err_out; - } - if (ctx->attr->non_resident) { - ntfs_log_debug("File name attribute must be resident. " - "Corrupt inode 0x%llx.\n", - (unsigned long long)ni->mft_no); - goto io_err_out; - } - fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - if ((u8*)fn + le32_to_cpu(ctx->attr->u.res.value_length) > - (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) { - ntfs_log_debug("Corrupt file name attribute in inode 0x%llx.\n", - (unsigned long long)ni->mft_no); - goto io_err_out; - } - mref = le64_to_cpu(fn->parent_directory); - ntfs_attr_put_search_ctx(ctx); - return mref; -io_err_out: - errno = EIO; -err_out: - eo = errno; - ntfs_attr_put_search_ctx(ctx); - errno = eo; - return ERR_MREF(-1); -} - -/** - * ntfs_readdir - read the contents of an ntfs directory - * @dir_ni: ntfs inode of current directory - * @pos: current position in directory - * @dirent: context for filldir callback supplied by the caller - * @filldir: filldir callback supplied by the caller - * - * Parse the index root and the index blocks that are marked in use in the - * index bitmap and hand each found directory entry to the @filldir callback - * supplied by the caller. - * - * Return 0 on success or -1 on error with errno set to the error code. - * - * Note: Index blocks are parsed in ascending vcn order, from which follows - * that the directory entries are not returned sorted. - */ -int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, - void *dirent, ntfs_filldir_t filldir) -{ - s64 i_size, br, ia_pos, bmp_pos, ia_start; - ntfs_volume *vol; - ntfs_attr *ia_na, *bmp_na = NULL; - ntfs_attr_search_ctx *ctx = NULL; - u8 *index_end, *bmp = NULL; - INDEX_ROOT *ir; - INDEX_ENTRY *ie; - INDEX_ALLOCATION *ia = NULL; - int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo; - u32 index_block_size, index_vcn_size; - u8 index_block_size_bits, index_vcn_size_bits; - - ntfs_log_trace("Entering.\n"); - - if (!dir_ni || !pos || !filldir) { - errno = EINVAL; - return -1; - } - - if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { - errno = ENOTDIR; - return -1; - } - - vol = dir_ni->vol; - - ntfs_log_trace("Entering for inode 0x%llx, *pos 0x%llx.\n", - (unsigned long long)dir_ni->mft_no, (long long)*pos); - - /* Open the index allocation attribute. */ - ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); - if (!ia_na) { - if (errno != ENOENT) { - ntfs_log_perror("Failed to open index allocation " - "attribute. Directory inode 0x%llx is " - "corrupt or bug", (unsigned long long) - dir_ni->mft_no); - return -1; - } - i_size = 0; - } else - i_size = ia_na->data_size; - - rc = 0; - - /* Are we at end of dir yet? */ - if (*pos >= i_size + vol->mft_record_size) - goto done; - - /* Emulate . and .. for all directories. */ - if (!*pos) { - rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos, - MK_MREF(dir_ni->mft_no, - le16_to_cpu(dir_ni->mrec->sequence_number)), - NTFS_DT_DIR); - if (rc) - goto err_out; - ++*pos; - } - if (*pos == 1) { - MFT_REF parent_mref; - - parent_mref = ntfs_mft_get_parent_ref(dir_ni); - if (parent_mref == ERR_MREF(-1)) { - ntfs_log_perror("Parent directory not found"); - goto dir_err_out; - } - - rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos, - parent_mref, NTFS_DT_DIR); - if (rc) - goto err_out; - ++*pos; - } - - ctx = ntfs_attr_get_search_ctx(dir_ni, NULL); - if (!ctx) - goto err_out; - - /* Get the offset into the index root attribute. */ - ir_pos = (int)*pos; - /* Find the index root attribute in the mft record. */ - if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - ntfs_log_debug("Index root attribute missing in directory " - "inode 0x%llx.\n", (unsigned long long)dir_ni-> - mft_no); - goto dir_err_out; - } - /* Get to the index root value. */ - ir = (INDEX_ROOT*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - - /* Determine the size of a vcn in the directory index. */ - index_block_size = le32_to_cpu(ir->index_block_size); - if (index_block_size < NTFS_BLOCK_SIZE || - index_block_size & (index_block_size - 1)) { - ntfs_log_debug("Index block size %u is invalid.\n", - (unsigned)index_block_size); - goto dir_err_out; - } - index_block_size_bits = ffs(index_block_size) - 1; - if (vol->cluster_size <= index_block_size) { - index_vcn_size = vol->cluster_size; - index_vcn_size_bits = vol->cluster_size_bits; - } else { - index_vcn_size = vol->sector_size; - index_vcn_size_bits = vol->sector_size_bits; - } - - /* Are we jumping straight into the index allocation attribute? */ - if (*pos >= vol->mft_record_size) { - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - goto skip_index_root; - } - - index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); - /* The first index entry. */ - ie = (INDEX_ENTRY*)((u8*)&ir->index + - le32_to_cpu(ir->index.entries_offset)); - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry or until filldir tells us it has had enough - * or signals an error (both covered by the rc test). - */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { - ntfs_log_debug("In index root, offset 0x%x.\n", - (u8*)ie - (u8*)ir); - /* Bounds checks. */ - if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + - sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->key_length) > - index_end) - goto dir_err_out; - /* The last entry cannot contain a name. */ - if (ie->flags & INDEX_ENTRY_END) - break; - /* Skip index root entry if continuing previous readdir. */ - if (ir_pos > (u8*)ie - (u8*)ir) - continue; - /* Advance the position even if going to skip the entry. */ - *pos = (u8*)ie - (u8*)ir; - /* - * Submit the directory entry to ntfs_filldir(), which will - * invoke the filldir() callback as appropriate. - */ - rc = ntfs_filldir(vol, pos, ie, dirent, filldir); - if (rc) - goto err_out; - } - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - - /* If there is no index allocation attribute we are finished. */ - if (!ia_na) - goto EOD; - - /* Advance *pos to the beginning of the index allocation. */ - *pos = vol->mft_record_size; - -skip_index_root: - - if (!ia_na) - goto done; - - /* Allocate a buffer for the current index block. */ - ia = (INDEX_ALLOCATION*)malloc(index_block_size); - if (!ia) { - ntfs_log_perror("Failed to allocate buffer for index block"); - goto err_out; - } - - bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4); - if (!bmp_na) { - ntfs_log_perror("Failed to open index bitmap attribute"); - goto dir_err_out; - } - - /* Get the offset into the index allocation attribute. */ - ia_pos = *pos - vol->mft_record_size; - - bmp_pos = ia_pos >> index_block_size_bits; - if (bmp_pos >> 3 >= bmp_na->data_size) { - ntfs_log_debug("Current index position exceeds index bitmap " - "size.\n"); - goto dir_err_out; - } - - bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096); - bmp = (u8*)malloc(bmp_buf_size); - if (!bmp) { - ntfs_log_perror("Failed to allocate bitmap buffer"); - goto err_out; - } - - br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); - if (br != bmp_buf_size) { - if (br != -1) - errno = EIO; - ntfs_log_perror("Failed to read from index bitmap attribute"); - goto err_out; - } - - bmp_buf_pos = 0; - /* If the index block is not in use find the next one that is. */ - while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) { -find_next_index_buffer: - bmp_pos++; - bmp_buf_pos++; - /* If we have reached the end of the bitmap, we are done. */ - if (bmp_pos >> 3 >= bmp_na->data_size) - goto EOD; - ia_pos = bmp_pos << index_block_size_bits; - if (bmp_buf_pos >> 3 < bmp_buf_size) - continue; - /* Read next chunk from the index bitmap. */ - if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size) - bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3); - br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); - if (br != bmp_buf_size) { - if (br != -1) - errno = EIO; - ntfs_log_perror("Failed to read from index bitmap " - "attribute"); - goto err_out; - } - } - - ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos); - - /* Read the index block starting at bmp_pos. */ - br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1, - index_block_size, ia); - if (br != 1) { - if (br != -1) - errno = EIO; - ntfs_log_perror("Failed to read index block"); - goto err_out; - } - - ia_start = ia_pos & ~(s64)(index_block_size - 1); - if (sle64_to_cpu(ia->index_block_vcn) != ia_start >> - index_vcn_size_bits) { - ntfs_log_debug("Actual VCN (0x%llx) of index buffer is " - "different from expected VCN (0x%llx) in " - "inode 0x%llx.\n", - (long long)sle64_to_cpu(ia->index_block_vcn), - (long long)ia_start >> index_vcn_size_bits, - (unsigned long long)dir_ni->mft_no); - goto dir_err_out; - } - if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) { - ntfs_log_debug("Index buffer (VCN 0x%llx) of directory inode " - "0x%llx has a size (%u) differing from the " - "directory specified size (%u).\n", - (long long)ia_start >> index_vcn_size_bits, - (unsigned long long)dir_ni->mft_no, - (unsigned) le32_to_cpu(ia->index.allocated_size) - + 0x18, (unsigned)index_block_size); - goto dir_err_out; - } - index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); - if (index_end > (u8*)ia + index_block_size) { - ntfs_log_debug("Size of index buffer (VCN 0x%llx) of directory " - "inode 0x%llx exceeds maximum size.\n", - (long long)ia_start >> index_vcn_size_bits, - (unsigned long long)dir_ni->mft_no); - goto dir_err_out; - } - /* The first index entry. */ - ie = (INDEX_ENTRY*)((u8*)&ia->index + - le32_to_cpu(ia->index.entries_offset)); - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry or until ntfs_filldir tells us it has had - * enough or signals an error (both covered by the rc test). - */ - for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { - ntfs_log_debug("In index allocation, offset 0x%llx.\n", - (long long)ia_start + ((u8*)ie - (u8*)ia)); - /* Bounds checks. */ - if ((u8*)ie < (u8*)ia || (u8*)ie + - sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8*)ie + le16_to_cpu(ie->key_length) > - index_end) { - ntfs_log_debug("Index entry out of bounds in directory " - "inode 0x%llx.\n", (unsigned long long) - dir_ni->mft_no); - goto dir_err_out; - } - /* The last entry cannot contain a name. */ - if (ie->flags & INDEX_ENTRY_END) - break; - /* Skip index entry if continuing previous readdir. */ - if (ia_pos - ia_start > (u8*)ie - (u8*)ia) - continue; - /* Advance the position even if going to skip the entry. */ - *pos = (u8*)ie - (u8*)ia + (sle64_to_cpu( - ia->index_block_vcn) << index_vcn_size_bits) + - dir_ni->vol->mft_record_size; - /* - * Submit the directory entry to ntfs_filldir(), which will - * invoke the filldir() callback as appropriate. - */ - rc = ntfs_filldir(vol, pos, ie, dirent, filldir); - if (rc) - goto err_out; - } - goto find_next_index_buffer; -EOD: - /* We are finished, set *pos to EOD. */ - *pos = i_size + vol->mft_record_size; -done: - free(ia); - free(bmp); - if (bmp_na) - ntfs_attr_close(bmp_na); - if (ia_na) - ntfs_attr_close(ia_na); - ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos); - return 0; -dir_err_out: - errno = EIO; -err_out: - eo = errno; - if (rc) - ntfs_log_trace("filldir returned %i, *pos 0x%llx.", rc, - (long long)*pos); - ntfs_log_trace("Failed.\n"); - if (ctx) - ntfs_attr_put_search_ctx(ctx); - free(ia); - free(bmp); - if (bmp_na) - ntfs_attr_close(bmp_na); - if (ia_na) - ntfs_attr_close(ia_na); - errno = eo; - return -1; -} - -/** - * __ntfs_create - create object on ntfs volume - * @dir_ni: ntfs inode for directory in which create new object - * @name: unicode name of new object - * @name_len: length of the name in unicode characters - * @type: type of the object to create - * @dev: major and minor device numbers (obtained from makedev()) - * @target: target in unicode (only for symlinks) - * @target_len: length of target in unicode characters - * - * Internal, use ntfs_create{,_device,_symlink} wrappers instead. - * - * @type can be: - * S_IFREG to create regular file - * S_IFDIR to create directory - * S_IFBLK to create block device - * S_IFCHR to create character device - * S_IFLNK to create symbolic link - * S_IFIFO to create FIFO - * S_IFSOCK to create socket - * other values are invalid. - * - * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value - * ignored. - * - * @target and @target_len are used only if @type is S_IFLNK, in other cases - * their value ignored. - * - * Return opened ntfs inode that describes created object on success or NULL - * on error with errno set to the error code. - */ -static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, - ntfschar *name, u8 name_len, dev_t type, dev_t dev, - ntfschar *target, u8 target_len) -{ - ntfs_inode *ni; - int rollback_data = 0, rollback_sd = 0; - FILE_NAME_ATTR *fn = NULL; - STANDARD_INFORMATION *si = NULL; - SECURITY_DESCRIPTOR_ATTR *sd = NULL; - ACL *acl; - ACCESS_ALLOWED_ACE *ace; - SID *sid; - int err, fn_len, si_len, sd_len; - - ntfs_log_trace("Entering.\n"); - - /* Sanity checks. */ - if (!dir_ni || !name || !name_len) { - ntfs_log_error("Invalid arguments.\n"); - errno = EINVAL; - return NULL; - } - /* FIXME: Reparse points requires special handling. */ - if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) { - errno = EOPNOTSUPP; - return NULL; - } - /* Allocate MFT record for new file. */ - ni = ntfs_mft_record_alloc(dir_ni->vol, NULL); - if (!ni) { - ntfs_log_error("Failed to allocate new MFT record: %s.\n", - strerror(errno)); - return NULL; - } - /* - * Create STANDARD_INFORMATION attribute. Write STANDARD_INFORMATION - * version 1.2, windows will upgrade it to version 3 if needed. - */ - si_len = offsetof(STANDARD_INFORMATION, u.v12.v1_end); - si = calloc(1, si_len); - if (!si) { - err = errno; - ntfs_log_error("Not enough memory.\n"); - goto err_out; - } - si->creation_time = utc2ntfs(ni->creation_time); - si->last_data_change_time = utc2ntfs(ni->last_data_change_time); - si->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - si->last_access_time = utc2ntfs(ni->last_access_time); - if (!S_ISREG(type) && !S_ISDIR(type)) { - si->file_attributes = FILE_ATTR_SYSTEM; - ni->flags = FILE_ATTR_SYSTEM; - } - /* Add STANDARD_INFORMATION to inode. */ - if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, - (u8*)si, si_len)) { - err = errno; - ntfs_log_error("Failed to add STANDARD_INFORMATION " - "attribute.\n"); - goto err_out; - } - /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ - /* - * Calculate security descriptor length. We have 2 sub-authorities in - * owner and group SIDs, but structure SID contain only one, so add - * 4 bytes to every SID. - */ - sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + - sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); - sd = calloc(1, sd_len); - if (!sd) { - err = errno; - ntfs_log_error("Not enough memory.\n"); - goto err_out; - } - sd->revision = 1; - sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; - sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); - sd->owner = cpu_to_le32((u8*)sid - (u8*)sd); - sid->revision = 1; - sid->sub_authority_count = 2; - sid->sub_authority[0] = cpu_to_le32(32); - sid->sub_authority[1] = cpu_to_le32(544); - sid->identifier_authority.value[5] = 5; - sid = (SID*)((u8*)sid + sizeof(SID) + 4); - sd->group = cpu_to_le32((u8*)sid - (u8*)sd); - sid->revision = 1; - sid->sub_authority_count = 2; - sid->sub_authority[0] = cpu_to_le32(32); - sid->sub_authority[1] = cpu_to_le32(544); - sid->identifier_authority.value[5] = 5; - acl = (ACL*)((u8*)sid + sizeof(SID) + 4); - sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd); - acl->revision = 2; - acl->size = cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); - acl->ace_count = cpu_to_le16(1); - ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); - ace->type = ACCESS_ALLOWED_ACE_TYPE; - ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; - ace->size = cpu_to_le16(sizeof(ACCESS_ALLOWED_ACE)); - ace->mask = cpu_to_le32(0x1f01ff); /* FIXME */ - ace->sid.revision = 1; - ace->sid.sub_authority_count = 1; - ace->sid.sub_authority[0] = 0; - ace->sid.identifier_authority.value[5] = 1; - /* Add SECURITY_DESCRIPTOR attribute to inode. */ - if (ntfs_attr_add(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0, - (u8*)sd, sd_len)) { - err = errno; - ntfs_log_error("Failed to add SECURITY_DESCRIPTOR " - "attribute.\n"); - goto err_out; - } - rollback_sd = 1; - /* Add DATA/INDEX_ROOT attribute. */ - if (S_ISDIR(type)) { - INDEX_ROOT *ir = NULL; - INDEX_ENTRY *ie; - int ir_len, index_len; - - /* Create INDEX_ROOT attribute. */ - index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER); - ir_len = offsetof(INDEX_ROOT, index) + index_len; - ir = calloc(1, ir_len); - if (!ir) { - err = errno; - ntfs_log_error("Not enough memory.\n"); - goto err_out; - } - ir->type = AT_FILE_NAME; - ir->collation_rule = COLLATION_FILE_NAME; - ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size); - if (ni->vol->cluster_size <= ni->vol->indx_record_size) - ir->clusters_per_index_block = - ni->vol->indx_record_size >> - ni->vol->cluster_size_bits; - else - ir->clusters_per_index_block = - ni->vol->indx_record_size >> - ni->vol->sector_size_bits; - ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER)); - ir->index.index_length = cpu_to_le32(index_len); - ir->index.allocated_size = cpu_to_le32(index_len); - ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT)); - ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER)); - ie->key_length = 0; - ie->flags = INDEX_ENTRY_END; - /* Add INDEX_ROOT attribute to inode. */ - if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4, - (u8*)ir, ir_len)) { - err = errno; - free(ir); - ntfs_log_error("Failed to add INDEX_ROOT attribute.\n"); - goto err_out; - } - free(ir); - } else { - INTX_FILE *data; - int data_len; - - switch (type) { - case S_IFBLK: - case S_IFCHR: - data_len = offsetof(INTX_FILE, u.s.device_end); - data = ntfs_malloc(data_len); - if (!data) { - err = errno; - goto err_out; - } - data->u.s.major = cpu_to_le64(major(dev)); - data->u.s.minor = cpu_to_le64(minor(dev)); - if (type == S_IFBLK) - data->magic = INTX_BLOCK_DEVICE; - if (type == S_IFCHR) - data->magic = INTX_CHARACTER_DEVICE; - break; - case S_IFLNK: - data_len = sizeof(INTX_FILE_TYPES) + - target_len * sizeof(ntfschar); - data = ntfs_malloc(data_len); - if (!data) { - err = errno; - goto err_out; - } - data->magic = INTX_SYMBOLIC_LINK; - memcpy(data->u.target, target, - target_len * sizeof(ntfschar)); - break; - case S_IFSOCK: - data = NULL; - data_len = 1; - break; - default: /* FIFO or regular file. */ - data = NULL; - data_len = 0; - break; - } - /* Add DATA attribute to inode. */ - if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data, - data_len)) { - err = errno; - free(data); - ntfs_log_error("Failed to add DATA attribute.\n"); - goto err_out; - } - rollback_data = 1; - free(data); - } - /* Create FILE_NAME attribute. */ - fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); - fn = ntfs_calloc(fn_len); - if (!fn) { - err = errno; - goto err_out; - } - fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, - le16_to_cpu(dir_ni->mrec->sequence_number)); - fn->file_name_length = name_len; - fn->file_name_type = FILE_NAME_POSIX; - if (S_ISDIR(type)) - fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT; - if (!S_ISREG(type) && !S_ISDIR(type)) - fn->file_attributes = FILE_ATTR_SYSTEM; - fn->creation_time = utc2ntfs(ni->creation_time); - fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); - fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - fn->last_access_time = utc2ntfs(ni->last_access_time); - memcpy(fn->file_name, name, name_len * sizeof(ntfschar)); - /* Add FILE_NAME attribute to inode. */ - if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) { - err = errno; - ntfs_log_error("Failed to add FILE_NAME attribute.\n"); - goto err_out; - } - /* Add FILE_NAME attribute to index. */ - if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no, - le16_to_cpu(ni->mrec->sequence_number)))) { - err = errno; - ntfs_log_perror("Failed to add entry to the index"); - goto err_out; - } - /* Set hard links count and directory flag. */ - ni->mrec->link_count = cpu_to_le16(1); - if (S_ISDIR(type)) - ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY; - ntfs_inode_mark_dirty(ni); - /* Done! */ - free(fn); - free(si); - free(sd); - ntfs_log_trace("Done.\n"); - return ni; -err_out: - ntfs_log_trace("Failed.\n"); - if (rollback_sd) { - ntfs_attr *na; - - na = ntfs_attr_open(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); - if (!na) - ntfs_log_perror("Failed to open SD (0x50) attribute of " - " inode 0x%llx. Run chkdsk.\n", - (unsigned long long)ni->mft_no); - else if (ntfs_attr_rm(na)) - ntfs_log_perror("Failed to remove SD (0x50) attribute " - "of inode 0x%llx. Run chkdsk.\n", - (unsigned long long)ni->mft_no); - } - if (rollback_data) { - ntfs_attr *na; - - na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); - if (!na) - ntfs_log_perror("Failed to open data attribute of " - " inode 0x%llx. Run chkdsk.\n", - (unsigned long long)ni->mft_no); - else if (ntfs_attr_rm(na)) - ntfs_log_perror("Failed to remove data attribute of " - "inode 0x%llx. Run chkdsk.\n", - (unsigned long long)ni->mft_no); - } - /* - * Free extent MFT records (should not exist any with current - * ntfs_create implementation, but for any case if something will be - * changed in the future). - */ - while (ni->nr_extents) - if (ntfs_mft_record_free(ni->vol, *(ni->u.extent_nis))) { - err = errno; - ntfs_log_error("Failed to free extent MFT record. " - "Leaving inconsistent metadata.\n"); - } - if (ntfs_mft_record_free(ni->vol, ni)) - ntfs_log_error("Failed to free MFT record. " - "Leaving inconsistent metadata. Run chkdsk.\n"); - free(fn); - free(si); - free(sd); - errno = err; - return NULL; -} - -/** - * Some wrappers around __ntfs_create() ... - */ - -ntfs_inode *ntfs_create(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type) -{ - if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO && - type != S_IFSOCK) { - ntfs_log_error("Invalid arguments.\n"); - return NULL; - } - return __ntfs_create(dir_ni, name, name_len, type, 0, NULL, 0); -} - -ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - dev_t type, dev_t dev) -{ - if (type != S_IFCHR && type != S_IFBLK) { - ntfs_log_error("Invalid arguments.\n"); - return NULL; - } - return __ntfs_create(dir_ni, name, name_len, type, dev, NULL, 0); -} - -ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, ntfschar *name, u8 name_len, - ntfschar *target, u8 target_len) -{ - if (!target || !target_len) { - ntfs_log_error("Invalid arguments.\n"); - return NULL; - } - return __ntfs_create(dir_ni, name, name_len, S_IFLNK, 0, - target, target_len); -} - -/** - * ntfs_delete - delete file or directory from ntfs volume - * @pni: ntfs inode for object to delete - * @dir_ni: ntfs inode for directory in which delete object - * @name: unicode name of the object to delete - * @name_len: length of the name in unicode characters - * - * @pni is pointer to pointer to ntfs_inode structure. Upon successful - * completion and if inode is really deleted (there are no more links left to - * it) this function will close @*pni and set it to NULL, in the other cases - * @*pni will stay opened. - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_delete(ntfs_inode **pni, ntfs_inode *dir_ni, ntfschar *name, - u8 name_len) -{ - ntfs_attr_search_ctx *actx = NULL; - ntfs_index_context *ictx = NULL; - ntfs_inode *ni; - FILE_NAME_ATTR *fn = NULL; - BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE; - BOOL case_sensitive_match = TRUE; - int err = 0; - - ntfs_log_trace("Entering.\n"); - - if (!pni || !(ni = *pni) || !dir_ni || !name || !name_len || - ni->nr_extents == -1 || dir_ni->nr_extents == -1) { - ntfs_log_error("Invalid arguments.\n"); - errno = EINVAL; - goto err_out; - } - if (ni->nr_references > 1 && le16_to_cpu(ni->mrec->link_count) == 1) { - ntfs_log_error("Trying to deleting inode with left " - "references.\n"); - errno = EINVAL; - goto err_out; - } - /* - * Search for FILE_NAME attribute with such name. If it's in POSIX or - * WIN32_AND_DOS namespace, then simply remove it from index and inode. - * If filename in DOS or in WIN32 namespace, then remove DOS name first, - * only then remove WIN32 name. Mark WIN32 name as POSIX name to prevent - * chkdsk to complain about DOS name absence in case if DOS name had - * been successfully deleted, but WIN32 name remove failed. - */ - actx = ntfs_attr_get_search_ctx(ni, NULL); - if (!actx) - goto err_out; -search: - while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, - 0, NULL, 0, actx)) { - errno = 0; - fn = (FILE_NAME_ATTR*)((u8*)actx->attr + - le16_to_cpu(actx->attr->u.res.value_offset)); - ntfs_log_trace("Found filename with instance number %d.\n", - le16_to_cpu(actx->attr->instance)); - if (looking_for_dos_name) { - if (fn->file_name_type == FILE_NAME_DOS) - break; - else - continue; - } - if (looking_for_win32_name) { - if (fn->file_name_type == FILE_NAME_WIN32) - break; - else - continue; - } - if (dir_ni->mft_no == MREF_LE(fn->parent_directory) && - ntfs_names_are_equal(fn->file_name, - fn->file_name_length, name, - name_len, case_sensitive_match ? - CASE_SENSITIVE : IGNORE_CASE, ni->vol->upcase, - ni->vol->upcase_len)) { - if (fn->file_name_type == FILE_NAME_WIN32) { - looking_for_dos_name = TRUE; - ntfs_attr_reinit_search_ctx(actx); - ntfs_log_trace("Restart search. " - "Looking for DOS name.\n"); - continue; - } - if (fn->file_name_type == FILE_NAME_DOS) - looking_for_dos_name = TRUE; - break; - } - } - if (errno) { - /* - * If case sensitive search failed and volume mounted case - * insensitive, then try once again ignoring case. - */ - if (errno == ENOENT && !NVolCaseSensitive(ni->vol) && - case_sensitive_match) { - case_sensitive_match = FALSE; - ntfs_attr_reinit_search_ctx(actx); - ntfs_log_trace("Restart search. Ignore case."); - goto search; - } - ntfs_log_error("Failed to find requested filename in FILE_NAME " - "attributes that belong to this inode.\n"); - goto err_out; - } - /* If deleting directory check it to be empty. */ - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { - ntfs_attr *na; - - na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4); - if (!na) { - ntfs_log_error("Corrupt directory or library bug.\n"); - errno = EIO; - goto err_out; - } - /* - * Do not allow non-empty directory deletion if hard links count - * is 1 (always) or 2 (in case if filename in DOS namespace, - * because we delete it first in file which have both WIN32 and - * DOS names). - */ - if ((na->data_size != sizeof(INDEX_ROOT) + sizeof( - INDEX_ENTRY_HEADER)) && (le16_to_cpu( - ni->mrec->link_count) == 1 || - (le16_to_cpu(ni->mrec->link_count) == 2 && - fn->file_name_type == FILE_NAME_DOS))) { - ntfs_attr_close(na); - ntfs_log_error("Directory is not empty.\n"); - errno = ENOTEMPTY; - goto err_out; - } - ntfs_attr_close(na); - } - /* One more sanity check. */ - if (ni->nr_references > 1 && looking_for_dos_name && - le16_to_cpu(ni->mrec->link_count) == 2) { - ntfs_log_error("Trying to deleting inode with left " - "references.\n"); - errno = EINVAL; - goto err_out; - } - ntfs_log_trace("Found!\n"); - /* Search for such FILE_NAME in index. */ - ictx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); - if (!ictx) - goto err_out; - if (ntfs_index_lookup(fn, le32_to_cpu(actx->attr->u.res.value_length), ictx)) - goto err_out; - /* Set namespace to POSIX for WIN32 name. */ - if (fn->file_name_type == FILE_NAME_WIN32) { - fn->file_name_type = FILE_NAME_POSIX; - ntfs_inode_mark_dirty(actx->ntfs_ino); - ((FILE_NAME_ATTR*)ictx->data)->file_name_type = FILE_NAME_POSIX; - ntfs_index_entry_mark_dirty(ictx); - } - /* Do not support reparse point deletion yet. */ - if (((FILE_NAME_ATTR*)ictx->data)->file_attributes & - FILE_ATTR_REPARSE_POINT) { - errno = EOPNOTSUPP; - goto err_out; - } - /* Remove FILE_NAME from index. */ - if (ntfs_index_rm(ictx)) - goto err_out; - - /* Remove FILE_NAME from inode. */ - if (ntfs_attr_record_rm(actx)) - goto err_out; - /* Decrement hard link count. */ - ni->mrec->link_count = cpu_to_le16(le16_to_cpu( - ni->mrec->link_count) - 1); - ntfs_inode_mark_dirty(ni); - if (looking_for_dos_name) { - looking_for_dos_name = FALSE; - looking_for_win32_name = TRUE; - ntfs_attr_reinit_search_ctx(actx); - ntfs_log_trace("DOS name deleted. " - "Now search for WIN32 name.\n"); - goto search; - } else - ntfs_log_trace("Deleted.\n"); - /* TODO: Update object id, quota and security indexes if required. */ - /* - * If hard link count is not equal to zero then we are done. In other - * case there are no reference to this inode left, so we should free all - * non-resident attributes and mark all MFT record as not in use. - */ - if (ni->mrec->link_count) - goto out; - ntfs_attr_reinit_search_ctx(actx); - while (!ntfs_attrs_walk(actx)) { - if (actx->attr->non_resident) { - runlist *rl; - - rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr, - NULL); - if (!rl) { - err = errno; - ntfs_log_error("Failed to decompress runlist. " - "Leaving inconsistent " - "metadata.\n"); - continue; - } - if (ntfs_cluster_free_from_rl(ni->vol, rl)) { - err = errno; - ntfs_log_error("Failed to free clusters. " - "Leaving inconsistent " - "metadata.\n"); - continue; - } - free(rl); - } - } - if (errno != ENOENT) { - err = errno; - ntfs_log_error("Attribute enumeration failed. " - "Probably leaving inconsistent metadata.\n"); - } - /* All extents should be attached after attribute walk. */ - while (ni->nr_extents) - if (ntfs_mft_record_free(ni->vol, *(ni->u.extent_nis))) { - err = errno; - ntfs_log_error("Failed to free extent MFT record. " - "Leaving inconsistent metadata.\n"); - } - if (ntfs_mft_record_free(ni->vol, ni)) { - err = errno; - ntfs_log_error("Failed to free base MFT record. " - "Leaving inconsistent metadata.\n"); - } - *pni = NULL; -out: - if (actx) - ntfs_attr_put_search_ctx(actx); - if (ictx) - ntfs_index_ctx_put(ictx); - if (err) { - ntfs_log_error("%s(): Failed.\n", "ntfs_delete"); - errno = err; - return -1; - } - ntfs_log_trace("Done.\n"); - return 0; -err_out: - err = errno; - goto out; -} - -/** - * ntfs_link - create hard link for file or directory - * @ni: ntfs inode for object to create hard link - * @dir_ni: ntfs inode for directory in which new link should be placed - * @name: unicode name of the new link - * @name_len: length of the name in unicode characters - * - * NOTE: At present we allow creating hard links to directories, we use them - * in a temporary state during rename. But it's definitely bad idea to have - * hard links to directories as a result of operation. - * FIXME: Create internal __ntfs_link that allows hard links to a directories - * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link. - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) -{ - FILE_NAME_ATTR *fn = NULL; - int fn_len, err; - - ntfs_log_trace("Entering.\n"); - - if (!ni || !dir_ni || !name || !name_len || - ni->mft_no == dir_ni->mft_no) { - err = EINVAL; - ntfs_log_error("Invalid arguments."); - goto err_out; - } - /* FIXME: Reparse points requires special handling. */ - if (ni->flags & FILE_ATTR_REPARSE_POINT) { - err = EOPNOTSUPP; - goto err_out; - } - /* Create FILE_NAME attribute. */ - fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); - fn = ntfs_calloc(fn_len); - if (!fn) { - err = errno; - goto err_out; - } - fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, - le16_to_cpu(dir_ni->mrec->sequence_number)); - fn->file_name_length = name_len; - fn->file_name_type = FILE_NAME_POSIX; - fn->file_attributes = ni->flags; - if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) - fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT; - fn->allocated_size = cpu_to_sle64(ni->allocated_size); - fn->data_size = cpu_to_sle64(ni->data_size); - fn->creation_time = utc2ntfs(ni->creation_time); - fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); - fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - fn->last_access_time = utc2ntfs(ni->last_access_time); - memcpy(fn->file_name, name, name_len * sizeof(ntfschar)); - /* Add FILE_NAME attribute to index. */ - if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no, - le16_to_cpu(ni->mrec->sequence_number)))) { - err = errno; - ntfs_log_error("Failed to add entry to the index.\n"); - goto err_out; - } - /* Add FILE_NAME attribute to inode. */ - if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) { - ntfs_index_context *ictx; - - err = errno; - ntfs_log_error("Failed to add FILE_NAME attribute.\n"); - /* Try to remove just added attribute from index. */ - ictx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); - if (!ictx) - goto rollback_failed; - if (ntfs_index_lookup(fn, fn_len, ictx)) { - ntfs_index_ctx_put(ictx); - goto rollback_failed; - } - if (ntfs_index_rm(ictx)) { - ntfs_index_ctx_put(ictx); - goto rollback_failed; - } - goto err_out; - } - /* Increment hard links count. */ - ni->mrec->link_count = cpu_to_le16(le16_to_cpu( - ni->mrec->link_count) + 1); - /* Done! */ - ntfs_inode_mark_dirty(ni); - free(fn); - ntfs_log_trace("Done.\n"); - return 0; -rollback_failed: - ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n"); -err_out: - ntfs_log_error("%s(): Failed.\n", "ntfs_link"); - free(fn); - errno = err; - return -1; -} - diff --git a/usr/src/lib/libntfs/common/libntfs/index.c b/usr/src/lib/libntfs/common/libntfs/index.c deleted file mode 100644 index efa4ae5913..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/index.c +++ /dev/null @@ -1,1862 +0,0 @@ -/** - * index.c - NTFS index handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2004-2005 Anton Altaparmakov - * Copyright (c) 2004-2005 Richard Russon - * Copyright (c) 2005-2007 Yura Pakhuchiy - * Copyright (c) 2005-2006 Szabolcs Szakacsits - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "collate.h" -#include "debug.h" -#include "index.h" -#include "mst.h" -#include "dir.h" -#include "logging.h" -#include "bitmap.h" -#include "support.h" - -/** - * ntfs_index_entry_mark_dirty - mark an index entry dirty - * @ictx: ntfs index context describing the index entry - * - * Mark the index entry described by the index entry context @ictx dirty. - * - * If the index entry is in the index root attribute, simply mark the inode - * containing the index root attribute dirty. This ensures the mftrecord, and - * hence the index root attribute, will be written out to disk later. - * - * If the index entry is in an index block belonging to the index allocation - * attribute, set ib_dirty to TRUE, thus index block will be updated during - * ntfs_index_ctx_put. - */ -void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx) -{ - if (ictx->is_in_root) - ntfs_inode_mark_dirty(ictx->actx->ntfs_ino); - else - ictx->ib_dirty = TRUE; -} - -static s64 ntfs_ib_vcn_to_pos(ntfs_index_context *icx, VCN vcn) -{ - return vcn << icx->vcn_size_bits; -} - -static VCN ntfs_ib_pos_to_vcn(ntfs_index_context *icx, s64 pos) -{ - return pos >> icx->vcn_size_bits; -} - -static int ntfs_ib_write(ntfs_index_context *icx, VCN vcn, void *buf) -{ - s64 ret; - - ntfs_log_trace("vcn: %lld\n", vcn); - - ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn), - 1, icx->block_size, buf); - if (ret != 1) { - ntfs_log_perror("Failed to write index block %lld of inode " - "%llu", (long long)vcn, - (unsigned long long)icx->ni->mft_no); - return STATUS_ERROR; - } - return STATUS_OK; -} - -static int ntfs_icx_ib_write(ntfs_index_context *icx) -{ - if (ntfs_ib_write(icx, icx->ib_vcn, icx->ib)) - return STATUS_ERROR; - - icx->ib_dirty = FALSE; - - return STATUS_OK; -} - -/** - * ntfs_index_ctx_get - allocate and initialize a new index context - * @ni: ntfs inode with which to initialize the context - * @name: name of the which context describes - * @name_len: length of the index name - * - * Allocate a new index context, initialize it with @ni and return it. - * Return NULL if allocation failed. - */ -ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, - ntfschar *name, u32 name_len) -{ - ntfs_index_context *icx; - - ntfs_log_trace("Entering.\n"); - - if (!ni) { - errno = EINVAL; - return NULL; - } - if (ni->nr_extents == -1) - ni = ni->u.base_ni; - icx = ntfs_calloc(sizeof(ntfs_index_context)); - if (icx) - *icx = (ntfs_index_context) { - .ni = ni, - .name = name, - .name_len = name_len, - }; - return icx; -} - -static void ntfs_index_ctx_free(ntfs_index_context *icx) -{ - ntfs_log_trace("Entering.\n"); - - if (!icx->entry) - return; - - if (icx->actx) - ntfs_attr_put_search_ctx(icx->actx); - - if (icx->is_in_root) { - if (icx->ia_na) - ntfs_attr_close(icx->ia_na); - return; - } - - if (icx->ib_dirty) { - /* FIXME: Error handling!!! */ - ntfs_ib_write(icx, icx->ib_vcn, icx->ib); - } - - free(icx->ib); - ntfs_attr_close(icx->ia_na); -} - -/** - * ntfs_index_ctx_put - release an index context - * @icx: index context to free - * - * Release the index context @icx, releasing all associated resources. - */ -void ntfs_index_ctx_put(ntfs_index_context *icx) -{ - ntfs_index_ctx_free(icx); - free(icx); -} - -/** - * ntfs_index_ctx_reinit - reinitialize an index context - * @icx: index context to reinitialize - * - * Reinitialize the index context @icx so it can be used for ntfs_index_lookup. - */ -void ntfs_index_ctx_reinit(ntfs_index_context *icx) -{ - ntfs_log_trace("Entering.\n"); - - ntfs_index_ctx_free(icx); - - *icx = (ntfs_index_context) { - .ni = icx->ni, - .name = icx->name, - .name_len = icx->name_len, - }; -} - -static leVCN *ntfs_ie_get_vcn_addr(INDEX_ENTRY *ie) -{ - return (leVCN *)((u8 *)ie + le16_to_cpu(ie->length) - sizeof(VCN)); -} - -/** - * Get the subnode vcn to which the index entry refers. - */ -VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie) -{ - return sle64_to_cpup(ntfs_ie_get_vcn_addr(ie)); -} - -static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih) -{ - return (INDEX_ENTRY *)((u8 *)ih + le32_to_cpu(ih->entries_offset)); -} - -static INDEX_ENTRY *ntfs_ie_get_next(INDEX_ENTRY *ie) -{ - return (INDEX_ENTRY *)((char *)ie + le16_to_cpu(ie->length)); -} - -static u8 *ntfs_ie_get_end(INDEX_HEADER *ih) -{ - /* FIXME: check if it isn't overflowing the index block size */ - return (u8 *)ih + le32_to_cpu(ih->index_length); -} - -static int ntfs_ie_end(INDEX_ENTRY *ie) -{ - return (ie->flags & INDEX_ENTRY_END) ? 1 : 0; -} - -/** - * Find the last entry in the index block - */ -static INDEX_ENTRY *ntfs_ie_get_last(INDEX_ENTRY *ie, char *ies_end) -{ - ntfs_log_trace("Entering.\n"); - - while ((char *)ie < ies_end && !ntfs_ie_end(ie)) - ie = ntfs_ie_get_next(ie); - return ie; -} - -static INDEX_ENTRY *ntfs_ie_get_by_pos(INDEX_HEADER *ih, int pos) -{ - INDEX_ENTRY *ie; - - ntfs_log_trace("pos: %d\n", pos); - - ie = ntfs_ie_get_first(ih); - - while (pos-- > 0) - ie = ntfs_ie_get_next(ie); - return ie; -} - -static INDEX_ENTRY *ntfs_ie_prev(INDEX_HEADER *ih, INDEX_ENTRY *ie) -{ - INDEX_ENTRY *ie_prev, *tmp; - - ntfs_log_trace("Entering.\n"); - - ie_prev = NULL; - tmp = ntfs_ie_get_first(ih); - - while (tmp != ie) { - ie_prev = tmp; - tmp = ntfs_ie_get_next(tmp); - } - return ie_prev; -} - -char *ntfs_ie_filename_get(INDEX_ENTRY *ie) -{ - FILE_NAME_ATTR *fn; - char *name = NULL; - int name_len; - - fn = (FILE_NAME_ATTR *)&ie->key; - name_len = ntfs_ucstombs(fn->file_name, fn->file_name_length, &name, 0); - if (name_len < 0) { - ntfs_log_perror("ntfs_ucstombs"); - return NULL; - } else if (name_len > 0) - return name; - free(name); - return NULL; -} - -void ntfs_ie_filename_dump(INDEX_ENTRY *ie) -{ - char *s; - - s = ntfs_ie_filename_get(ie); - ntfs_log_debug("'%s' ", s); - free(s); -} - -void ntfs_ih_filename_dump(INDEX_HEADER *ih) -{ - INDEX_ENTRY *ie; - - ntfs_log_trace("Entering.\n"); - - ie = ntfs_ie_get_first(ih); - while (!ntfs_ie_end(ie)) { - ntfs_ie_filename_dump(ie); - ie = ntfs_ie_get_next(ie); - } -} - -static int ntfs_ih_numof_entries(INDEX_HEADER *ih) -{ - int n; - INDEX_ENTRY *ie; - - ntfs_log_trace("Entering.\n"); - - ie = ntfs_ie_get_first(ih); - for (n = 0; !ntfs_ie_end(ie); n++) - ie = ntfs_ie_get_next(ie); - return n; -} - -static int ntfs_ih_one_entry(INDEX_HEADER *ih) -{ - return (ntfs_ih_numof_entries(ih) == 1); -} - -static int ntfs_ih_zero_entry(INDEX_HEADER *ih) -{ - return (ntfs_ih_numof_entries(ih) == 0); -} - -static void ntfs_ie_delete(INDEX_HEADER *ih, INDEX_ENTRY *ie) -{ - u32 new_size; - - ntfs_log_trace("Entering.\n"); - - new_size = le32_to_cpu(ih->index_length) - le16_to_cpu(ie->length); - ih->index_length = cpu_to_le32(new_size); - memmove(ie, (u8 *)ie + le16_to_cpu(ie->length), - new_size - ((u8 *)ie - (u8 *)ih)); -} - -static void ntfs_ie_set_vcn(INDEX_ENTRY *ie, VCN vcn) -{ - *ntfs_ie_get_vcn_addr(ie) = cpu_to_sle64(vcn); -} - -/** - * Insert @ie index entry at @pos entry. Used @ih values should be ok already. - */ -static void ntfs_ie_insert(INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_ENTRY *pos) -{ - int ie_size = le16_to_cpu(ie->length); - - ntfs_log_trace("Entering.\n"); - - ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) + ie_size); - memmove((u8 *)pos + ie_size, pos, - le32_to_cpu(ih->index_length) - ((u8 *)pos - (u8 *)ih) - - ie_size); - memcpy(pos, ie, ie_size); -} - -static INDEX_ENTRY *ntfs_ie_dup(INDEX_ENTRY *ie) -{ - INDEX_ENTRY *dup; - - ntfs_log_trace("Entering.\n"); - - dup = ntfs_malloc(le16_to_cpu(ie->length)); - if (dup) - memcpy(dup, ie, le16_to_cpu(ie->length)); - return dup; -} - -static INDEX_ENTRY *ntfs_ie_dup_novcn(INDEX_ENTRY *ie) -{ - INDEX_ENTRY *dup; - int size = le16_to_cpu(ie->length); - - ntfs_log_trace("Entering.\n"); - - if (ie->flags & INDEX_ENTRY_NODE) - size -= sizeof(VCN); - - dup = ntfs_malloc(size); - if (dup) { - memcpy(dup, ie, size); - dup->flags &= ~INDEX_ENTRY_NODE; - dup->length = cpu_to_le16(size); - } - return dup; -} - -static int ntfs_ia_check(ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn) -{ - u32 ib_size = (unsigned)le32_to_cpu(ib->index.allocated_size) + 0x18; - - ntfs_log_trace("Entering.\n"); - - if (!ntfs_is_indx_record(ib->magic)) { - - ntfs_log_error("Corrupt index block signature: vcn %lld inode " - "%llu\n", (long long)vcn, - (unsigned long long)icx->ni->mft_no); - return -1; - } - - if (sle64_to_cpu(ib->index_block_vcn) != vcn) { - - ntfs_log_error("Corrupt index block: VCN (%lld) is different " - "from expected VCN (%lld) in inode %llu\n", - (long long)sle64_to_cpu(ib->index_block_vcn), - (long long)vcn, - (unsigned long long)icx->ni->mft_no); - return -1; - } - - if (ib_size != icx->block_size) { - - ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu " - "has a size (%u) differing from the index " - "specified size (%u)\n", (long long)vcn, - icx->ni->mft_no, (unsigned)ib_size, - (unsigned)icx->block_size); - return -1; - } - return 0; -} - -static INDEX_ROOT *ntfs_ir_lookup(ntfs_inode *ni, ntfschar *name, - u32 name_len, ntfs_attr_search_ctx **ctx) -{ - ATTR_RECORD *a; - INDEX_ROOT *ir = NULL; - - ntfs_log_trace("Entering.\n"); - - *ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!*ctx) { - ntfs_log_perror("Failed to get $INDEX_ROOT search context"); - return NULL; - } - - if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, - 0, NULL, 0, *ctx)) { - ntfs_log_perror("Failed to lookup $INDEX_ROOT"); - goto err_out; - } - - a = (*ctx)->attr; - if (a->non_resident) { - errno = EINVAL; - ntfs_log_perror("Non-resident $INDEX_ROOT detected"); - goto err_out; - } - - ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->u.res.value_offset)); -err_out: - if (!ir) - ntfs_attr_put_search_ctx(*ctx); - return ir; -} - -/** - * Find a key in the index block. - * - * Return values: - * STATUS_OK with errno set to ESUCCESS if we know for sure that the - * entry exists and @ie_out points to this entry. - * STATUS_NOT_FOUND with errno set to ENOENT if we know for sure the - * entry doesn't exist and @ie_out is the insertion point. - * STATUS_KEEP_SEARCHING if we can't answer the above question and - * @vcn will contain the node index block. - * STATUS_ERROR with errno set if on unexpected error during lookup. - */ -static int ntfs_ie_lookup(const void *key, const int key_len, - ntfs_index_context *icx, INDEX_HEADER *ih, - VCN *vcn, INDEX_ENTRY **ie_out) -{ - INDEX_ENTRY *ie; - u8 *index_end; - int rc, item = 0; - - ntfs_log_trace("Entering.\n"); - - index_end = ntfs_ie_get_end(ih); - - /* - * Loop until we exceed valid memory (corruption case) or until we - * reach the last entry. - */ - for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) { - /* Bounds checks. */ - if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || - (u8 *)ie + le16_to_cpu(ie->length) > index_end) { - errno = ERANGE; - ntfs_log_error("Index entry out of bounds in inode " - "%llu.\n", - (unsigned long long)icx->ni->mft_no); - return STATUS_ERROR; - } - /* - * The last entry cannot contain a key. It can however contain - * a pointer to a child node in the B+tree so we just break out. - */ - if (ntfs_ie_end(ie)) - break; - /* - * Not a perfect match, need to do full blown collation so we - * know which way in the B+tree we have to go. - */ - rc = ntfs_collate(icx->ni->vol, icx->cr, key, key_len, &ie->key, - le16_to_cpu(ie->key_length)); - if (rc == NTFS_COLLATION_ERROR) { - ntfs_log_error("Collation error. Perhaps a filename " - "contains invalid characters?\n"); - errno = ERANGE; - return STATUS_ERROR; - } - /* - * If @key collates before the key of the current entry, there - * is definitely no such key in this index but we might need to - * descend into the B+tree so we just break out of the loop. - */ - if (rc == -1) - break; - - if (!rc) { - *ie_out = ie; - errno = 0; - icx->parent_pos[icx->pindex] = item; - return STATUS_OK; - } - - item++; - } - /* - * We have finished with this index block without success. Check for the - * presence of a child node and if not present return with errno ENOENT, - * otherwise we will keep searching in another index block. - */ - if (!(ie->flags & INDEX_ENTRY_NODE)) { - ntfs_log_debug("Index entry wasn't found.\n"); - *ie_out = ie; - errno = ENOENT; - return STATUS_NOT_FOUND; - } - - /* Get the starting vcn of the index_block holding the child node. */ - *vcn = ntfs_ie_get_vcn(ie); - if (*vcn < 0) { - errno = EINVAL; - ntfs_log_perror("Negative vcn in inode %llu\n", - icx->ni->mft_no); - return STATUS_ERROR; - } - - ntfs_log_trace("Parent entry number %d\n", item); - icx->parent_pos[icx->pindex] = item; - return STATUS_KEEP_SEARCHING; -} - -static ntfs_attr *ntfs_ia_open(ntfs_index_context *icx, ntfs_inode *ni) -{ - ntfs_attr *na; - - na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len); - if (!na) { - ntfs_log_perror("Failed to open index allocation of inode " - "%llu", (unsigned long long)ni->mft_no); - return NULL; - } - return na; -} - -static int ntfs_ib_read(ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst) -{ - s64 pos, ret; - - ntfs_log_trace("vcn: %lld\n", vcn); - - pos = ntfs_ib_vcn_to_pos(icx, vcn); - - ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, - (u8 *)dst); - if (ret != 1) { - if (ret == -1) - ntfs_log_perror("Failed to read index block"); - else - ntfs_log_error("Failed to read full index block at " - "%lld\n", (long long)pos); - return -1; - } - - if (ntfs_ia_check(icx, dst, vcn)) - return -1; - return 0; -} - -static int ntfs_icx_parent_inc(ntfs_index_context *icx) -{ - icx->pindex++; - if (icx->pindex >= MAX_PARENT_VCN) { - errno = EOPNOTSUPP; - ntfs_log_perror("Index is over %d level deep", MAX_PARENT_VCN); - return STATUS_ERROR; - } - return STATUS_OK; -} - -static int ntfs_icx_parent_dec(ntfs_index_context *icx) -{ - icx->pindex--; - if (icx->pindex < 0) { - errno = EINVAL; - ntfs_log_perror("Corrupt index pointer (%d)", icx->pindex); - return STATUS_ERROR; - } - return STATUS_OK; -} - -/** - * ntfs_index_lookup - find a key in an index and return its index entry - * @key: [IN] key for which to search in the index - * @key_len: [IN] length of @key in bytes - * @icx: [IN/OUT] context describing the index and the returned entry - * - * Before calling ntfs_index_lookup(), @icx must have been obtained from a - * call to ntfs_index_ctx_get(). - * - * Look for the @key in the index specified by the index lookup context @icx. - * ntfs_index_lookup() walks the contents of the index looking for the @key. - * - * If the @key is found in the index, 0 is returned and @icx is setup to - * describe the index entry containing the matching @key. @icx->entry is the - * index entry and @icx->data and @icx->data_len are the index entry data and - * its length in bytes, respectively. - * - * If the @key is not found in the index, -1 is returned, errno = ENOENT and - * @icx is setup to describe the index entry whose key collates immediately - * after the search @key, i.e. this is the position in the index at which - * an index entry with a key of @key would need to be inserted. - * - * If an error occurs return -1, set errno to error code and @icx is left - * untouched. - * - * When finished with the entry and its data, call ntfs_index_ctx_put() to free - * the context and other associated resources. - * - * If the index entry was modified, call ntfs_index_entry_mark_dirty() before - * the call to ntfs_index_ctx_put() to ensure that the changes are written - * to disk. - */ -int ntfs_index_lookup(const void *key, const int key_len, - ntfs_index_context *icx) -{ - VCN old_vcn, vcn; - ntfs_inode *ni = icx->ni; - INDEX_ROOT *ir; - INDEX_ENTRY *ie; - INDEX_BLOCK *ib = NULL; - ntfs_attr_search_ctx *actx; - int ret, err = 0; - - ntfs_log_trace("Entering.\n"); - - if (!key || key_len <= 0) { - errno = EINVAL; - ntfs_log_perror("key: %p key_len: %d", key, key_len); - return -1; - } - - ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &actx); - if (!ir) { - if (errno == ENOENT) - errno = EIO; - return -1; - } - - icx->block_size = le32_to_cpu(ir->index_block_size); - if (icx->block_size < NTFS_BLOCK_SIZE) { - errno = EINVAL; - ntfs_log_perror("Index block size (%u) is smaller than the " - "sector size (%d)", (unsigned)icx->block_size, - NTFS_BLOCK_SIZE); - return -1; - } - - if (ni->vol->cluster_size <= icx->block_size) - icx->vcn_size_bits = ni->vol->cluster_size_bits; - else - icx->vcn_size_bits = ni->vol->sector_size_bits; - - icx->cr = ir->collation_rule; - if (!ntfs_is_collation_rule_supported(icx->cr)) { - err = errno = EOPNOTSUPP; - ntfs_log_perror("Unknown collation rule 0x%x", - (unsigned)le32_to_cpu(icx->cr)); - goto err_out; - } - - old_vcn = VCN_INDEX_ROOT_PARENT; - /* - * FIXME: check for both ir and ib that the first index entry is - * within the index block. - */ - ret = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie); - if (ret == STATUS_ERROR) { - err = errno; - goto err_out; - } - - icx->actx = actx; - icx->ir = ir; - - if (ret != STATUS_KEEP_SEARCHING) { - /* STATUS_OK or STATUS_NOT_FOUND */ - err = errno; - icx->is_in_root = TRUE; - icx->parent_vcn[icx->pindex] = old_vcn; - goto done; - } - - /* Child node present, descend into it. */ - icx->ia_na = ntfs_ia_open(icx, ni); - if (!icx->ia_na) - goto err_out; - - ib = ntfs_malloc(icx->block_size); - if (!ib) { - err = errno; - goto err_out; - } - -descend_into_child_node: - icx->parent_vcn[icx->pindex] = old_vcn; - if (ntfs_icx_parent_inc(icx)) { - err = errno; - goto err_out; - } - old_vcn = vcn; - - ntfs_log_debug("Descend into node with VCN %lld.\n", vcn); - - if (ntfs_ib_read(icx, vcn, ib)) - goto err_out; - - ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie); - if (ret != STATUS_KEEP_SEARCHING) { - err = errno; - if (ret == STATUS_ERROR) - goto err_out; - - /* STATUS_OK or STATUS_NOT_FOUND */ - icx->is_in_root = FALSE; - icx->ib = ib; - icx->parent_vcn[icx->pindex] = icx->ib_vcn = vcn; - goto done; - } - - if ((ib->index.flags & NODE_MASK) == LEAF_NODE) { - ntfs_log_error("Index entry with child node found in a leaf " - "node in inode 0x%llx.\n", - (unsigned long long)ni->mft_no); - goto err_out; - } - - goto descend_into_child_node; -err_out: - if (icx->ia_na) { - ntfs_attr_close(icx->ia_na); - icx->ia_na = NULL; - } - free(ib); - if (!err) - err = EIO; - if (actx) - ntfs_attr_put_search_ctx(actx); - errno = err; - return -1; -done: - icx->entry = ie; - icx->data = (u8 *)ie + offsetof(INDEX_ENTRY, key); - icx->data_len = le16_to_cpu(ie->key_length); - icx->max_depth = icx->pindex; - ntfs_log_trace("Done.\n"); - if (err) { - errno = err; - return -1; - } - return 0; -} - -static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, - INDEX_HEADER_FLAGS node_type) -{ - INDEX_BLOCK *ib; - int ih_size = sizeof(INDEX_HEADER); - - ntfs_log_trace("Entering ib_vcn = %lld ib_size = %u\n", ib_vcn, - ib_size); - - ib = ntfs_calloc(ib_size); - if (!ib) - return NULL; - - ib->magic = magic_INDX; - ib->usa_ofs = cpu_to_le16(sizeof(INDEX_BLOCK)); - ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1); - /* Set USN to 1 */ - *(le16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = cpu_to_le16(1); - ib->lsn = 0; - - ib->index_block_vcn = cpu_to_sle64(ib_vcn); - - ib->index.entries_offset = cpu_to_le32((ih_size + - le16_to_cpu(ib->usa_count) * 2 + 7) & ~7); - ib->index.index_length = 0; - ib->index.allocated_size = cpu_to_le32(ib_size - - (sizeof(INDEX_BLOCK) - ih_size)); - ib->index.flags = node_type; - return ib; -} - -/** - * Find the median by going through all the entries - */ -static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih) -{ - INDEX_ENTRY *ie, *ie_start; - u8 *ie_end; - int i = 0, median; - - ntfs_log_trace("Entering.\n"); - - ie = ie_start = ntfs_ie_get_first(ih); - ie_end = (u8 *)ntfs_ie_get_end(ih); - - while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) { - ie = ntfs_ie_get_next(ie); - i++; - } - /* - * NOTE: this could be also the entry at the half of the index block. - */ - median = i / 2 - 1; - - ntfs_log_trace("Entries: %d median: %d\n", i, median); - - for (i = 0, ie = ie_start; i <= median; i++) - ie = ntfs_ie_get_next(ie); - - return ie; -} - -static s64 ntfs_ibm_vcn_to_pos(ntfs_index_context *icx, VCN vcn) -{ - return ntfs_ib_vcn_to_pos(icx, vcn) / icx->block_size; -} - -static s64 ntfs_ibm_pos_to_vcn(ntfs_index_context *icx, s64 pos) -{ - return ntfs_ib_pos_to_vcn(icx, pos * icx->block_size); -} - -static int ntfs_ibm_add(ntfs_index_context *icx) -{ - u8 bmp[8]; - - ntfs_log_trace("Entering.\n"); - - if (ntfs_attr_exist(icx->ni, AT_BITMAP, icx->name, icx->name_len)) - return STATUS_OK; - /* - * AT_BITMAP must be at least 8 bytes. - */ - memset(bmp, 0, sizeof(bmp)); - if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len, - bmp, sizeof(bmp))) { - ntfs_log_perror("Failed to add AT_BITMAP"); - return STATUS_ERROR; - } - return STATUS_OK; -} - -static int ntfs_ibm_modify(ntfs_index_context *icx, VCN vcn, int set) -{ - u8 byte; - s64 pos = ntfs_ibm_vcn_to_pos(icx, vcn); - u32 bpos = pos / 8; - u32 bit = 1 << (pos % 8); - ntfs_attr *na; - int ret = STATUS_ERROR; - - ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", vcn); - - na = ntfs_attr_open(icx->ni, AT_BITMAP, icx->name, icx->name_len); - if (!na) { - ntfs_log_perror("Failed to open $BITMAP attribute"); - return -1; - } - - if (set) { - if (na->data_size < bpos + 1) { - if (ntfs_attr_truncate(na, (na->data_size + 8) & ~7)) { - ntfs_log_perror("Failed to truncate AT_BITMAP"); - goto err_na; - } - } - } - - if (ntfs_attr_pread(na, bpos, 1, &byte) != 1) { - ntfs_log_perror("Failed to read $BITMAP"); - goto err_na; - } - - if (set) - byte |= bit; - else - byte &= ~bit; - - if (ntfs_attr_pwrite(na, bpos, 1, &byte) != 1) { - ntfs_log_perror("Failed to write $Bitmap"); - goto err_na; - } - - ret = STATUS_OK; -err_na: - ntfs_attr_close(na); - return ret; -} - - -static int ntfs_ibm_set(ntfs_index_context *icx, VCN vcn) -{ - return ntfs_ibm_modify(icx, vcn, 1); -} - -static int ntfs_ibm_clear(ntfs_index_context *icx, VCN vcn) -{ - return ntfs_ibm_modify(icx, vcn, 0); -} - -static VCN ntfs_ibm_get_free(ntfs_index_context *icx) -{ - u8 *bm; - int bit; - s64 vcn, byte, size; - - ntfs_log_trace("Entering.\n"); - - bm = ntfs_attr_readall(icx->ni, AT_BITMAP, icx->name, icx->name_len, - &size); - if (!bm) - return (VCN)-1; - - for (byte = 0; byte < size; byte++) { - - if (bm[byte] == 255) - continue; - - for (bit = 0; bit < 8; bit++) { - if (!(bm[byte] & (1 << bit))) { - vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); - goto out; - } - } - } - - vcn = ntfs_ibm_pos_to_vcn(icx, size * 8); -out: - ntfs_log_trace("allocated vcn: %lld\n", vcn); - - if (ntfs_ibm_set(icx, vcn)) - vcn = (VCN)-1; - - free(bm); - return vcn; -} - -static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn) -{ - INDEX_BLOCK *ib; - INDEX_ENTRY *ie_last; - char *ies_start, *ies_end; - int i; - - ntfs_log_trace("Entering.\n"); - - if (!(ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), - LEAF_NODE))) - return NULL; - - ies_start = (char *)ntfs_ie_get_first(&ir->index); - ies_end = (char *)ntfs_ie_get_end(&ir->index); - - ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); - /* - * Copy all entries, including the termination entry - * as well, which can never have any data. - */ - i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length); - memcpy(ntfs_ie_get_first(&ib->index), ies_start, i); - - ib->index.flags = ir->index.flags; - ib->index.index_length = cpu_to_le32(i + - le32_to_cpu(ib->index.entries_offset)); - return ib; -} - -static void ntfs_ir_nill(INDEX_ROOT *ir) -{ - INDEX_ENTRY *ie_last; - char *ies_start, *ies_end; - - ntfs_log_trace("Entering\n"); - /* TODO: This function could be much simpler. */ - ies_start = (char *)ntfs_ie_get_first(&ir->index); - ies_end = (char *)ntfs_ie_get_end(&ir->index); - ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); - /* Move the index root termination entry forward. */ - if ((char *)ie_last > ies_start) { - memmove(ies_start, (char *)ie_last, le16_to_cpu( - ie_last->length)); - ie_last = (INDEX_ENTRY *)ies_start; - } -} - -static int ntfs_ib_copy_tail(ntfs_index_context *icx, INDEX_BLOCK *src, - INDEX_ENTRY *median, VCN new_vcn) -{ - u8 *ies_end; - INDEX_ENTRY *ie_head; /* first entry after the median */ - int tail_size, ret; - INDEX_BLOCK *dst; - - ntfs_log_trace("Entering.\n"); - - dst = ntfs_ib_alloc(new_vcn, icx->block_size, - src->index.flags & NODE_MASK); - if (!dst) - return STATUS_ERROR; - - ie_head = ntfs_ie_get_next(median); - - ies_end = (u8 *)ntfs_ie_get_end(&src->index); - tail_size = ies_end - (u8 *)ie_head; - memcpy(ntfs_ie_get_first(&dst->index), ie_head, tail_size); - - dst->index.index_length = cpu_to_le32(tail_size + - le32_to_cpu(dst->index.entries_offset)); - - ret = ntfs_ib_write(icx, new_vcn, dst); - - free(dst); - return ret; -} - -static int ntfs_ib_cut_tail(ntfs_index_context *icx, INDEX_BLOCK *src, - INDEX_ENTRY *ie) -{ - char *ies_start, *ies_end; - INDEX_ENTRY *ie_last; - - ntfs_log_trace("Entering.\n"); - - ies_start = (char *)ntfs_ie_get_first(&src->index); - ies_end = (char *)ntfs_ie_get_end(&src->index); - - ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); - if (ie_last->flags & INDEX_ENTRY_NODE) - ntfs_ie_set_vcn(ie_last, ntfs_ie_get_vcn(ie)); - - memcpy(ie, ie_last, le16_to_cpu(ie_last->length)); - - src->index.index_length = cpu_to_le32(((char *)ie - ies_start) + - le16_to_cpu(ie->length) + - le32_to_cpu(src->index.entries_offset)); - - if (ntfs_ib_write(icx, icx->parent_vcn[icx->pindex + 1], src)) - return STATUS_ERROR; - - return STATUS_OK; -} - -static int ntfs_ia_add(ntfs_index_context *icx) -{ - ntfs_log_trace("Entering.\n"); - - if (ntfs_ibm_add(icx)) - return -1; - - if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, - icx->name_len)) { - if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name, - icx->name_len, NULL, 0)) { - ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION"); - return -1; - } - } - - icx->ia_na = ntfs_ia_open(icx, icx->ni); - if (!icx->ia_na) - return -1; - return 0; -} - -static INDEX_ROOT *ntfs_ir_lookup2(ntfs_inode *ni, ntfschar *name, u32 len) -{ - ntfs_attr_search_ctx *ctx; - INDEX_ROOT *ir; - - ir = ntfs_ir_lookup(ni, name, len, &ctx); - if (ir) - ntfs_attr_put_search_ctx(ctx); - return ir; -} - -static int ntfs_ir_reparent(ntfs_index_context *icx) -{ - ntfs_attr_search_ctx *ctx; - INDEX_ROOT *ir; - INDEX_ENTRY *ie; - INDEX_BLOCK *ib = NULL; - VCN new_ib_vcn; - int ret = STATUS_ERROR; - - ntfs_log_trace("Entering.\n"); - - if (!(icx->ia_na)) - if (ntfs_ia_add(icx)) - return -1; - - ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, &ctx); - if (!ir) - return -1; - - new_ib_vcn = ntfs_ibm_get_free(icx); - if (new_ib_vcn == -1) - goto err_out; - - ib = ntfs_ir_to_ib(ir, new_ib_vcn); - if (ib == NULL) { - ntfs_log_perror("Failed to move index root to index block"); - goto clear_bmp; - } - - if (ntfs_ib_write(icx, new_ib_vcn, ib)) - goto clear_bmp; - - ntfs_ir_nill(ir); - - ie = ntfs_ie_get_first(&ir->index); - ie->flags |= INDEX_ENTRY_NODE; - ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)); - ntfs_ie_set_vcn(ie, new_ib_vcn); - - ir->index.flags = LARGE_INDEX; - ir->index.index_length = cpu_to_le32(le32_to_cpu( - ir->index.entries_offset) + le16_to_cpu(ie->length)); - ir->index.allocated_size = ir->index.index_length; - - if (ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, - sizeof(INDEX_ROOT) - sizeof(INDEX_HEADER) + - le32_to_cpu(ir->index.allocated_size))) - /* FIXME: revert bitmap, index root */ - goto err_out; - ntfs_inode_mark_dirty(ctx->ntfs_ino); - - ret = STATUS_OK; -err_out: - ntfs_attr_put_search_ctx(ctx); - free(ib); - return ret; -clear_bmp: - ntfs_ibm_clear(icx, new_ib_vcn); - goto err_out; -} - -/** - * ntfs_ir_truncate - Truncate index root attribute - * - * Returns STATUS_OK, STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT or STATUS_ERROR. - */ -static int ntfs_ir_truncate(ntfs_index_context *icx, int data_size) -{ - ntfs_attr *na; - int ret; - - ntfs_log_trace("Entering.\n"); - - na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len); - if (!na) { - ntfs_log_perror("Failed to open INDEX_ROOT"); - return STATUS_ERROR; - } - /* - * INDEX_ROOT must be resident and its entries can be moved to - * INDEX_BLOCK, so ENOSPC isn't a real error. - */ - ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index)); - if (ret == STATUS_OK) { - icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); - if (!icx->ir) - return STATUS_ERROR; - - icx->ir->index.allocated_size = cpu_to_le32(data_size); - } else { - if (errno != ENOSPC && errno != EOVERFLOW) - ntfs_log_trace("Failed to truncate INDEX_ROOT"); - if (errno == EOVERFLOW) - ret = STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT; - } - - ntfs_attr_close(na); - return ret; -} - -/** - * ntfs_ir_make_space - Make more space for the index root attribute - * - * On success return STATUS_OK or STATUS_KEEP_SEARCHING. - * On error return STATUS_ERROR. - */ -static int ntfs_ir_make_space(ntfs_index_context *icx, int data_size) -{ - int ret; - - ntfs_log_trace("Entering.\n"); - - ret = ntfs_ir_truncate(icx, data_size); - if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) { - ret = ntfs_ir_reparent(icx); - if (ret == STATUS_OK) - ret = STATUS_KEEP_SEARCHING; - else - ntfs_log_perror("Failed to nodify INDEX_ROOT"); - } - return ret; -} - -/* - * NOTE: 'ie' must be a copy of a real index entry. - */ -static int ntfs_ie_add_vcn(INDEX_ENTRY **ie) -{ - INDEX_ENTRY *p, *old = *ie; - - old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN)); - p = realloc(old, le16_to_cpu(old->length)); - if (!p) - return STATUS_ERROR; - - p->flags |= INDEX_ENTRY_NODE; - *ie = p; - return STATUS_OK; -} - -static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, - int pos) -{ - INDEX_ENTRY *ie_node, *ie; - int ret = STATUS_ERROR; - VCN old_vcn; - - ntfs_log_trace("Entering.\n"); - - ie = ntfs_ie_dup(orig_ie); - if (!ie) - return STATUS_ERROR; - - if (!(ie->flags & INDEX_ENTRY_NODE)) - if (ntfs_ie_add_vcn(&ie)) - goto out; - - ie_node = ntfs_ie_get_by_pos(ih, pos); - old_vcn = ntfs_ie_get_vcn(ie_node); - ntfs_ie_set_vcn(ie_node, new_vcn); - - ntfs_ie_insert(ih, ie, ie_node); - ntfs_ie_set_vcn(ie_node, old_vcn); - ret = STATUS_OK; -out: - free(ie); - return ret; -} - -static VCN ntfs_icx_parent_vcn(ntfs_index_context *icx) -{ - return icx->parent_vcn[icx->pindex]; -} - -static VCN ntfs_icx_parent_pos(ntfs_index_context *icx) -{ - return icx->parent_pos[icx->pindex]; -} - -static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median, - VCN new_vcn) -{ - u32 new_size; - int ret; - - ntfs_log_trace("Entering.\n"); - - icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); - if (!icx->ir) - return STATUS_ERROR; - - new_size = le32_to_cpu(icx->ir->index.index_length) + - le16_to_cpu(median->length); - if (!(median->flags & INDEX_ENTRY_NODE)) - new_size += sizeof(VCN); - - ret = ntfs_ir_make_space(icx, new_size); - if (ret != STATUS_OK) - return ret; - - icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); - if (!icx->ir) - return STATUS_ERROR; - - return ntfs_ih_insert(&icx->ir->index, median, new_vcn, - ntfs_icx_parent_pos(icx)); -} - -static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib); - -/** - * ntfs_ib_insert - insert an index block to an index context. - * - * On success return STATUS_OK or STATUS_KEEP_SEARCHING. - * On error return STATUS_ERROR. - */ -static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn) -{ - INDEX_BLOCK *ib; - u32 idx_size, allocated_size; - int err = STATUS_ERROR; - VCN old_vcn; - - ntfs_log_trace("Entering.\n"); - - ib = ntfs_malloc(icx->block_size); - if (!ib) - return -1; - - old_vcn = ntfs_icx_parent_vcn(icx); - - if (ntfs_ib_read(icx, old_vcn, ib)) - goto err_out; - - idx_size = le32_to_cpu(ib->index.index_length); - allocated_size = le32_to_cpu(ib->index.allocated_size); - /* FIXME: sizeof(VCN) should be included only if ie has no VCN */ - if (idx_size + le16_to_cpu(ie->length) + sizeof(VCN) > allocated_size) { - err = ntfs_ib_split(icx, ib); - if (err == STATUS_OK) - err = STATUS_KEEP_SEARCHING; - goto err_out; - } - - if (ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx))) - goto err_out; - - if (ntfs_ib_write(icx, old_vcn, ib)) - goto err_out; - - err = STATUS_OK; -err_out: - free(ib); - return err; -} - -/** - * ntfs_ib_split - Split index allocation attribute - * - * On success return STATUS_OK or STATUS_KEEP_SEARCHING. - * On error return is STATUS_ERROR. - */ -static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib) -{ - INDEX_ENTRY *median; - VCN new_vcn; - int ret; - - ntfs_log_trace("Entering.\n"); - - if (ntfs_icx_parent_dec(icx)) - return STATUS_ERROR; - - median = ntfs_ie_get_median(&ib->index); - new_vcn = ntfs_ibm_get_free(icx); - if (new_vcn == -1) - return STATUS_ERROR; - - if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) { - ntfs_ibm_clear(icx, new_vcn); - return STATUS_ERROR; - } - - if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) - ret = ntfs_ir_insert_median(icx, median, new_vcn); - else - ret = ntfs_ib_insert(icx, median, new_vcn); - - ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - - if (ret != STATUS_OK) { - ntfs_ibm_clear(icx, new_vcn); - return ret; - } - - ret = ntfs_ib_cut_tail(icx, ib, median); - return ret; -} - -static int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) -{ - INDEX_HEADER *ih; - int allocated_size, new_size; - int ret = STATUS_ERROR; - -#ifdef DEBUG - char *fn; - fn = ntfs_ie_filename_get(ie); - ntfs_log_trace("file: '%s'\n", fn); - free(fn); -#endif - - while (1) { - if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), - icx)) { - errno = EEXIST; - ntfs_log_error("Index already have such entry.\n"); - goto err_out; - } - if (errno != ENOENT) { - ntfs_log_perror("Failed to find place for new entry"); - goto err_out; - } - - if (icx->is_in_root) - ih = &icx->ir->index; - else - ih = &icx->ib->index; - - allocated_size = le32_to_cpu(ih->allocated_size); - new_size = le32_to_cpu(ih->index_length) + - le16_to_cpu(ie->length); - - if (new_size <= allocated_size) - break; - - ntfs_log_trace("index block sizes: allocated: %d needed: %d\n", - allocated_size, new_size); - - if (icx->is_in_root) { - if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR) - goto err_out; - } else { - if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR) - goto err_out; - } - ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - ntfs_index_ctx_reinit(icx); - } - - ntfs_ie_insert(ih, ie, icx->entry); - ntfs_index_entry_mark_dirty(icx); - - ret = STATUS_OK; -err_out: - ntfs_log_trace("%s\n", ret ? "Failed" : "Done"); - return ret; -} - -/** - * ntfs_index_add_filename - add filename to directory index - * @ni: ntfs inode describing directory to which index add filename - * @fn: FILE_NAME attribute to add - * @mref: reference of the inode which @fn describes - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref) -{ - INDEX_ENTRY *ie; - ntfs_index_context *icx; - int fn_size, ie_size, ret = -1, err; - - ntfs_log_trace("Entering.\n"); - - if (!ni || !fn) { - ntfs_log_error("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - fn_size = (fn->file_name_length * sizeof(ntfschar)) + - sizeof(FILE_NAME_ATTR); - ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7; - - ie = ntfs_calloc(ie_size); - if (!ie) - return -1; - - ie->u.indexed_file = cpu_to_le64(mref); - ie->length = cpu_to_le16(ie_size); - ie->key_length = cpu_to_le16(fn_size); - memcpy(&ie->key, fn, fn_size); - - icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4); - if (!icx) - goto out; - - err = errno; - ret = ntfs_ie_add(icx, ie); - errno = err; - - ntfs_index_ctx_put(icx); -out: - free(ie); - return ret; -} - -static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, - INDEX_ENTRY *ie, INDEX_BLOCK *ib) -{ - INDEX_ENTRY *ie_roam; - int ret = STATUS_ERROR; - - ntfs_log_trace("Entering.\n"); - - ie_roam = ntfs_ie_dup_novcn(ie); - if (!ie_roam) - return STATUS_ERROR; - - ntfs_ie_delete(ih, ie); - - if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) - ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - else - if (ntfs_ib_write(icx, ntfs_icx_parent_vcn(icx), ib)) - goto out; - - ntfs_index_ctx_reinit(icx); - - ret = ntfs_ie_add(icx, ie_roam); -out: - free(ie_roam); - return ret; -} - -/** - * ntfs_ir_leafify - - * - * Used if an empty index block to be deleted has END entry as the parent - * in the INDEX_ROOT which is the only one there. - */ -static void ntfs_ir_leafify(ntfs_index_context *icx, INDEX_HEADER *ih) -{ - INDEX_ENTRY *ie; - - ntfs_log_trace("Entering.\n"); - - ie = ntfs_ie_get_first(ih); - ie->flags &= ~INDEX_ENTRY_NODE; - ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(VCN)); - - ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - - sizeof(VCN)); - ih->flags &= ~LARGE_INDEX; - - /* Not fatal error */ - ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); - - ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - ntfs_index_ctx_reinit(icx); -} - -/** - * ntfs_ih_reparent_end - - * - * Used if an empty index block to be deleted has END entry as the parent - * in the INDEX_ROOT which is not the only one there. - */ -static int ntfs_ih_reparent_end(ntfs_index_context *icx, INDEX_HEADER *ih, - INDEX_BLOCK *ib) -{ - INDEX_ENTRY *ie, *ie_prev; - - ntfs_log_trace("Entering.\n"); - - ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx)); - ie_prev = ntfs_ie_prev(ih, ie); - - ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev)); - return ntfs_ih_takeout(icx, ih, ie_prev, ib); -} - -static int ntfs_index_rm_leaf(ntfs_index_context *icx) -{ - INDEX_BLOCK *ib = NULL; - INDEX_HEADER *parent_ih; - INDEX_ENTRY *ie; - int ret = STATUS_ERROR; - - ntfs_log_trace("pindex: %d\n", icx->pindex); - - if (ntfs_icx_parent_dec(icx)) - return STATUS_ERROR; - - if (ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1])) - return STATUS_ERROR; - - if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) - parent_ih = &icx->ir->index; - else { - ib = ntfs_malloc(icx->block_size); - if (!ib) - return STATUS_ERROR; - - if (ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib)) - goto out; - - parent_ih = &ib->index; - } - - ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx)); - if (!ntfs_ie_end(ie)) { - ret = ntfs_ih_takeout(icx, parent_ih, ie, ib); - goto out; - } - - if (ntfs_ih_zero_entry(parent_ih)) { - - if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { - ntfs_ir_leafify(icx, parent_ih); - goto ok; - } - - ret = ntfs_index_rm_leaf(icx); - goto out; - } - - if (ntfs_ih_reparent_end(icx, parent_ih, ib)) - goto out; -ok: - ret = STATUS_OK; -out: - free(ib); - return ret; -} - -static int ntfs_index_rm_node(ntfs_index_context *icx) -{ - int entry_pos; - VCN vcn; - INDEX_BLOCK *ib = NULL; - INDEX_ENTRY *ie_succ, *ie, *entry = icx->entry; - INDEX_HEADER *ih; - u32 new_size; - int delta, ret = STATUS_ERROR; - - ntfs_log_trace("Entering.\n"); - - if (!icx->ia_na) { - icx->ia_na = ntfs_ia_open(icx, icx->ni); - if (!icx->ia_na) - return STATUS_ERROR; - } - - ib = ntfs_malloc(icx->block_size); - if (!ib) - return STATUS_ERROR; - - ie_succ = ntfs_ie_get_next(icx->entry); - entry_pos = icx->parent_pos[icx->pindex]++; -descend: - vcn = ntfs_ie_get_vcn(ie_succ); - if (ntfs_ib_read(icx, vcn, ib)) - goto out; - - ie_succ = ntfs_ie_get_first(&ib->index); - - if (ntfs_icx_parent_inc(icx)) - goto out; - - icx->parent_vcn[icx->pindex] = vcn; - icx->parent_pos[icx->pindex] = 0; - - if ((ib->index.flags & NODE_MASK) == INDEX_NODE) - goto descend; - - if (ntfs_ih_zero_entry(&ib->index)) { - errno = EOPNOTSUPP; - ntfs_log_perror("Failed to find any entry in an index block. " - "Please run chkdsk."); - goto out; - } - - ie = ntfs_ie_dup(ie_succ); - if (!ie) - goto out; - - if (ntfs_ie_add_vcn(&ie)) - goto out2; - - ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(icx->entry)); - - if (icx->is_in_root) - ih = &icx->ir->index; - else - ih = &icx->ib->index; - - delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length); - new_size = le32_to_cpu(ih->index_length) + delta; - if (delta > 0) { - if (icx->is_in_root) { - if (ntfs_ir_truncate(icx, new_size)) { - errno = EOPNOTSUPP; - ntfs_log_perror("Denied to truncate INDEX_ROOT" - " during entry removal"); - goto out2; - } - ih = &icx->ir->index; - entry = ntfs_ie_get_by_pos(ih, entry_pos); - } else if (new_size > le32_to_cpu(ih->allocated_size)) { - errno = EOPNOTSUPP; - ntfs_log_perror("Denied to split INDEX_BLOCK during " - "entry removal"); - goto out2; - } - } - - ntfs_ie_delete(ih, entry); - ntfs_ie_insert(ih, ie, entry); - - if (icx->is_in_root) { - if (ntfs_ir_truncate(icx, new_size)) - goto out2; - ntfs_inode_mark_dirty(icx->actx->ntfs_ino); - } else - if (ntfs_icx_ib_write(icx)) - goto out2; - - ntfs_ie_delete(&ib->index, ie_succ); - - if (ntfs_ih_zero_entry(&ib->index)) { - if (ntfs_index_rm_leaf(icx)) - goto out2; - } else - if (ntfs_ib_write(icx, vcn, ib)) - goto out2; - - ret = STATUS_OK; -out2: - free(ie); -out: - free(ib); - return ret; -} - -/** - * ntfs_index_rm - remove entry from the index - * @icx: index context describing entry to delete - * - * Delete entry described by @icx from the index. Index context is always - * reinitialized after use of this function, so it can be used for index - * lookup once again. - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_index_rm(ntfs_index_context *icx) -{ - INDEX_HEADER *ih; - int err; - - ntfs_log_trace("Entering.\n"); - - if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) { - ntfs_log_error("Invalid arguments.\n"); - errno = EINVAL; - goto err_out; - } - if (icx->is_in_root) - ih = &icx->ir->index; - else - ih = &icx->ib->index; - - if (icx->entry->flags & INDEX_ENTRY_NODE) { - - if (ntfs_index_rm_node(icx)) - goto err_out; - - } else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) { - - ntfs_ie_delete(ih, icx->entry); - - if (icx->is_in_root) { - err = ntfs_ir_truncate(icx, - le32_to_cpu(ih->index_length)); - if (err != STATUS_OK) - goto err_out; - } else - if (ntfs_icx_ib_write(icx)) - goto err_out; - } else { - if (ntfs_index_rm_leaf(icx)) - goto err_out; - } - - ntfs_index_ctx_reinit(icx); - ntfs_log_trace("Done.\n"); - return 0; -err_out: - err = errno; - ntfs_index_ctx_reinit(icx); - errno = err; - ntfs_log_trace("Failed.\n"); - return -1; -} - -/** - * ntfs_index_root_get - read the index root of an attribute - * @ni: open ntfs inode in which the ntfs attribute resides - * @attr: attribute for which we want its index root - * - * This function will read the related index root an ntfs attribute. - * - * On success a buffer is allocated with the content of the index root - * and which needs to be freed when it's not needed anymore. - * - * On error NULL is returned with errno set to the error code. - */ -INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr) -{ - ntfs_attr_search_ctx *ctx; - ntfschar *name; - INDEX_ROOT *root = NULL; - - name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)); - - if (!ntfs_ir_lookup(ni, name, attr->name_length, &ctx)) - return NULL; - - root = ntfs_malloc(sizeof(INDEX_ROOT)); - if (!root) - goto out; - - *root = *((INDEX_ROOT *)((u8 *)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset))); -out: - ntfs_attr_put_search_ctx(ctx); - return root; -} - diff --git a/usr/src/lib/libntfs/common/libntfs/inode.c b/usr/src/lib/libntfs/common/libntfs/inode.c deleted file mode 100644 index 9ea1d34524..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/inode.c +++ /dev/null @@ -1,1200 +0,0 @@ -/** - * inode.c - Inode handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2004-2007 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "inode.h" -#include "debug.h" -#include "mft.h" -#include "attrlist.h" -#include "runlist.h" -#include "lcnalloc.h" -#include "index.h" -#include "dir.h" -#include "ntfstime.h" -#include "logging.h" - -/** - * __ntfs_inode_allocate - Create and initialise an NTFS inode object - * @vol: - * - * Description... - * - * Returns: - */ -static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol) -{ - ntfs_inode *ni; - - ni = (ntfs_inode*)calloc(1, sizeof(ntfs_inode)); - if (ni) { - ni->vol = vol; - INIT_LIST_HEAD(&ni->attr_cache); - } - return ni; -} - -/** - * ntfs_inode_allocate - Create an NTFS inode object - * @vol: - * - * Description... - * - * Returns: - */ -ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol) -{ - return __ntfs_inode_allocate(vol); -} - -/** - * __ntfs_inode_release - Destroy an NTFS inode object - * @ni: - * - * Description... - * - * Returns: - */ -static int __ntfs_inode_release(ntfs_inode *ni) -{ - if (NInoDirty(ni)) - ntfs_log_debug("Eeek. Discarding dirty inode!\n"); - if (NInoAttrList(ni) && ni->attr_list) - free(ni->attr_list); - free(ni->mrec); - free(ni); - return 0; -} - -/** - * __ntfs_inode_add_to_cache - do not use me! Only for internal library use. - */ -void __ntfs_inode_add_to_cache(ntfs_inode *ni) -{ - list_add_tail(&ni->list_entry, &ni->vol->inode_cache[ - ni->mft_no & NTFS_INODE_CACHE_SIZE_BITS]); - ni->nr_references = 1; -} - -/** - * ntfs_inode_open - open an inode ready for access - * @vol: volume to get the inode from - * @mref: inode number / mft record number to open - * - * Allocate an ntfs_inode structure and initialize it for the given inode - * specified by @mref. @mref specifies the inode number / mft record to read, - * including the sequence number, which can be 0 if no sequence number checking - * is to be performed. - * - * Then, allocate a buffer for the mft record, read the mft record from the - * volume @vol, and attach it to the ntfs_inode structure (->mrec). The - * mft record is mst deprotected and sanity checked for validity and we abort - * if deprotection or checks fail. - * - * Finally, search for an attribute list attribute in the mft record and if one - * is found, load the attribute list attribute value and attach it to the - * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate - * this. - * - * Return a pointer to the ntfs_inode structure on success or NULL on error, - * with errno set to the error code. - */ -ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) -{ - s64 l; - ntfs_inode *ni; - ntfs_attr_search_ctx *ctx; - int err = 0; - STANDARD_INFORMATION *std_info; - struct list_head *pos; - - ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); - if (!vol) { - errno = EINVAL; - return NULL; - } - /* Check cache, maybe this inode already opened? */ - list_for_each(pos, &vol->inode_cache[MREF(mref) & - NTFS_INODE_CACHE_SIZE_BITS]) { - ntfs_inode *tmp_ni; - - tmp_ni = list_entry(pos, ntfs_inode, list_entry); - if (tmp_ni->mft_no == MREF(mref)) { - ntfs_log_trace("Found this inode in cache, increment " - "reference count and return it.\n"); - tmp_ni->nr_references++; - return tmp_ni; - } - } - /* Search failed. Properly open inode. */ - ni = __ntfs_inode_allocate(vol); - if (!ni) - return NULL; - if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL)) - goto err_out; - if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) { - err = ENOENT; - goto err_out; - } - ni->mft_no = MREF(mref); - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - goto err_out; - /* Receive some basic information about inode. */ - if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, - 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { - err = errno; - ntfs_log_trace("Failed to receive STANDARD_INFORMATION " - "attribute.\n"); - goto put_err_out; - } - std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - ni->flags = std_info->file_attributes; - ni->creation_time = ntfs2utc(std_info->creation_time); - ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time); - ni->last_mft_change_time = ntfs2utc(std_info->last_mft_change_time); - ni->last_access_time = ntfs2utc(std_info->last_access_time); - /* Set attribute list information. */ - if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, - ctx)) { - if (errno != ENOENT) - goto put_err_out; - /* Attribute list attribute does not present. */ - goto get_size; - } - NInoSetAttrList(ni); - l = ntfs_get_attribute_value_length(ctx->attr); - if (!l) - goto put_err_out; - if (l > 0x40000) { - err = EIO; - goto put_err_out; - } - ni->attr_list_size = l; - ni->attr_list = ntfs_malloc(ni->attr_list_size); - if (!ni->attr_list) - goto put_err_out; - l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list); - if (!l) - goto put_err_out; - if (l != ni->attr_list_size) { - err = EIO; - goto put_err_out; - } -get_size: - if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { - if (errno != ENOENT) - goto put_err_out; - /* Directory or special file. */ - ni->data_size = ni->allocated_size = 0; - } else { - if (ctx->attr->non_resident) { - ni->data_size = sle64_to_cpu(ctx->attr->u.nonres.data_size); - if (ctx->attr->flags & - (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) - ni->allocated_size = sle64_to_cpu( - ctx->attr->u.nonres.compressed_size); - else - ni->allocated_size = sle64_to_cpu( - ctx->attr->u.nonres.allocated_size); - } else { - ni->data_size = le32_to_cpu(ctx->attr->u.res.value_length); - ni->allocated_size = (ni->data_size + 7) & ~7; - } - } - ntfs_attr_put_search_ctx(ctx); - __ntfs_inode_add_to_cache(ni); - return ni; -put_err_out: - if (!err) - err = errno; - ntfs_attr_put_search_ctx(ctx); -err_out: - if (!err) - err = errno; - __ntfs_inode_release(ni); - errno = err; - return NULL; -} - -/** - * ntfs_inode_close - close an ntfs inode and free all associated memory - * @ni: ntfs inode to close - * - * Make sure the ntfs inode @ni is clean. - * - * If the ntfs inode @ni is a base inode, close all associated extent inodes, - * then deallocate all memory attached to it, and finally free the ntfs inode - * structure itself. - * - * If it is an extent inode, we disconnect it from its base inode before we - * destroy it. - * - * It is OK to pass NULL to this function, it is just noop in this case. - * - * Return 0 on success or -1 on error with errno set to the error code. On - * error, @ni has not been freed. The user should attempt to handle the error - * and call ntfs_inode_close() again. The following error codes are defined: - * - * EBUSY @ni and/or its attribute list runlist is/are dirty and the - * attempt to write it/them to disk failed. - * EINVAL @ni is invalid (probably it is an extent inode). - * EIO I/O error while trying to write inode to disk. - */ -int ntfs_inode_close(ntfs_inode *ni) -{ - if (!ni) - return 0; - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - /* Decrement number of users. If there are left then just return. */ - if (ni->nr_extents != -1) { - ni->nr_references--; - if (ni->nr_references) { - ntfs_log_trace("There are %d more references left to " - "this inode.\n", - ni->nr_references); - return 0; - } else - ntfs_log_trace("There are no more references left to " - "this inode.\n"); - } - /* Check whether all attributes of this inode are closed. */ - if (!list_empty(&ni->attr_cache)) - ntfs_log_error("%s(): Not all attributes are closed. " - "We definitely have memory leak. " - "Continue anyway.\n", "ntfs_inode_close"); - /* If we have dirty metadata, write it out. */ - if (NInoDirty(ni) || NInoAttrListDirty(ni)) { - if (ntfs_inode_sync(ni)) { - if (errno != EIO) - errno = EBUSY; - return -1; - } - } - /* Is this a base inode with mapped extent inodes? */ - if (ni->nr_extents > 0) { - while (ni->nr_extents > 0) { - if (ntfs_inode_close(ni->u.extent_nis[0])) { - if (errno != EIO) - errno = EBUSY; - return -1; - } - } - } else if (ni->nr_extents == -1) { - ntfs_inode **tmp_nis; - ntfs_inode *base_ni; - s32 i; - - /* - * If the inode is an extent inode, disconnect it from the - * base inode before destroying it. - */ - base_ni = ni->u.base_ni; - for (i = 0; i < base_ni->nr_extents; ++i) { - tmp_nis = base_ni->u.extent_nis; - if (tmp_nis[i] != ni) - continue; - /* Found it. Disconnect. */ - memmove(tmp_nis + i, tmp_nis + i + 1, - (base_ni->nr_extents - i - 1) * - sizeof(ntfs_inode *)); - /* Buffer should be for multiple of four extents. */ - if ((--base_ni->nr_extents) & 3) { - i = -1; - break; - } - /* - * ElectricFence is unhappy with realloc(x,0) as free(x) - * thus we explicitly separate these two cases. - */ - if (base_ni->nr_extents) { - /* Resize the memory buffer. */ - tmp_nis = realloc(tmp_nis, base_ni->nr_extents * - sizeof(ntfs_inode *)); - /* Ignore errors, they don't really matter. */ - if (tmp_nis) - base_ni->u.extent_nis = tmp_nis; - } else if (tmp_nis) - free(tmp_nis); - /* Allow for error checking. */ - i = -1; - break; - } - if (i != -1) - ntfs_log_debug("Extent inode was not attached to base " - "inode! Continuing regardless.\n"); - } - /* Remove inode from the list of opened inodes. */ - if (ni->nr_extents != -1) - list_del(&ni->list_entry); - return __ntfs_inode_release(ni); -} - -/** - * ntfs_extent_inode_open - load an extent inode and attach it to its base - * @base_ni: base ntfs inode - * @mref: mft reference of the extent inode to load (in little endian) - * - * First check if the extent inode @mref is already attached to the base ntfs - * inode @base_ni, and if so, return a pointer to the attached extent inode. - * - * If the extent inode is not already attached to the base inode, allocate an - * ntfs_inode structure and initialize it for the given inode @mref. @mref - * specifies the inode number / mft record to read, including the sequence - * number, which can be 0 if no sequence number checking is to be performed. - * - * Then, allocate a buffer for the mft record, read the mft record from the - * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec). - * The mft record is mst deprotected and sanity checked for validity and we - * abort if deprotection or checks fail. - * - * Finally attach the ntfs inode to its base inode @base_ni and return a - * pointer to the ntfs_inode structure on success or NULL on error, with errno - * set to the error code. - * - * Note, extent inodes are never closed directly. They are automatically - * disposed off by the closing of the base inode. - */ -ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const leMFT_REF mref) -{ - u64 mft_no = MREF_LE(mref); - ntfs_inode *ni; - ntfs_inode **extent_nis; - int i; - - if (!base_ni) { - errno = EINVAL; - return NULL; - } - ntfs_log_trace("Opening extent inode 0x%llx " - "(base MFT record 0x%llx).\n", - (unsigned long long)mft_no, - (unsigned long long)base_ni->mft_no); - /* Is the extent inode already open and attached to the base inode? */ - if (base_ni->nr_extents > 0) { - extent_nis = base_ni->u.extent_nis; - for (i = 0; i < base_ni->nr_extents; i++) { - u16 seq_no; - - ni = extent_nis[i]; - if (mft_no != ni->mft_no) - continue; - /* Verify the sequence number if given. */ - seq_no = MSEQNO_LE(mref); - if (seq_no && seq_no != le16_to_cpu( - ni->mrec->sequence_number)) { - ntfs_log_debug("Found stale extent mft " - "reference! Corrupt file " - "system. Run chkdsk.\n"); - errno = EIO; - return NULL; - } - /* We are done, return the extent inode. */ - return ni; - } - } - /* Wasn't there, we need to load the extent inode. */ - ni = __ntfs_inode_allocate(base_ni->vol); - if (!ni) - return NULL; - if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec, - NULL)) - goto err_out; - ni->mft_no = mft_no; - ni->nr_extents = -1; - ni->u.base_ni = base_ni; - /* Attach extent inode to base inode, reallocating memory if needed. */ - if (!(base_ni->nr_extents & 3)) { - i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); - - extent_nis = (ntfs_inode**)ntfs_malloc(i); - if (!extent_nis) - goto err_out; - if (base_ni->nr_extents) { - memcpy(extent_nis, base_ni->u.extent_nis, - i - 4 * sizeof(ntfs_inode *)); - free(base_ni->u.extent_nis); - } - base_ni->u.extent_nis = extent_nis; - } - base_ni->u.extent_nis[base_ni->nr_extents++] = ni; - return ni; -err_out: - i = errno; - __ntfs_inode_release(ni); - errno = i; - ntfs_log_perror("Failed to open extent inode"); - return NULL; -} - -/** - * ntfs_inode_attach_all_extents - attach all extents for target inode - * @ni: opened ntfs inode for which perform attach - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_inode_attach_all_extents(ntfs_inode *ni) -{ - ATTR_LIST_ENTRY *ale; - u64 prev_attached = 0; - - if (!ni) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - if (ni->nr_extents == -1) - ni = ni->u.base_ni; - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - /* Inode haven't got attribute list, thus nothing to attach. */ - if (!NInoAttrList(ni)) - return 0; - - if (!ni->attr_list) { - ntfs_log_trace("Corrupted in-memory structure.\n"); - errno = EINVAL; - return -1; - } - - /* Walk through attribute list and attach all extents. */ - errno = 0; - ale = (ATTR_LIST_ENTRY *)ni->attr_list; - while ((u8*)ale < ni->attr_list + ni->attr_list_size) { - if (ni->mft_no != MREF_LE(ale->mft_reference) && - prev_attached != MREF_LE(ale->mft_reference)) { - if (!ntfs_extent_inode_open(ni, ale->mft_reference)) { - ntfs_log_trace("Couldn't attach extent " - "inode (attr type 0x%x " - "references to it).\n", - le32_to_cpu(ale->type)); - return -1; - } - prev_attached = MREF_LE(ale->mft_reference); - } - ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length)); - } - return 0; -} - -/** - * ntfs_inode_sync_standard_information - update standard information attribute - * @ni: ntfs inode to update standard information - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -static int ntfs_inode_sync_standard_information(ntfs_inode *ni) -{ - ntfs_attr_search_ctx *ctx; - STANDARD_INFORMATION *std_info; - int err; - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return -1; - if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, - 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { - err = errno; - ntfs_log_trace("Failed to receive STANDARD_INFORMATION " - "attribute.\n"); - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; - } - std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - std_info->file_attributes = ni->flags; - std_info->creation_time = utc2ntfs(ni->creation_time); - std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time); - std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - std_info->last_access_time = utc2ntfs(ni->last_access_time); - ntfs_attr_put_search_ctx(ctx); - return 0; -} - -/** - * ntfs_inode_sync_file_name - update FILE_NAME attributes - * @ni: ntfs inode to update FILE_NAME attributes - * - * Update all FILE_NAME attributes for inode @ni in the index. - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -static int ntfs_inode_sync_file_name(ntfs_inode *ni) -{ - ntfs_attr_search_ctx *ctx = NULL; - ntfs_index_context *ictx; - ntfs_inode *index_ni; - FILE_NAME_ATTR *fn; - int err = 0; - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) { - err = errno; - ntfs_log_trace("Failed to get attribute search context.\n"); - goto err_out; - } - /* Walk through all FILE_NAME attributes and update them. */ - while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) { - fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr + - le16_to_cpu(ctx->attr->u.res.value_offset)); - if (MREF_LE(fn->parent_directory) == ni->mft_no) { - /* - * WARNING: We cheater here and obtain 2 attribute - * search contexts for one inode (first we obtained - * above, second will be obtained inside - * ntfs_index_lookup), it's acceptable for library, - * but will lock kernel. - */ - index_ni = ni; - } else - index_ni = ntfs_inode_open(ni->vol, - le64_to_cpu(fn->parent_directory)); - if (!index_ni) { - if (!err) - err = errno; - ntfs_log_trace("Failed to open inode with index.\n"); - continue; - } - ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4); - if (!ictx) { - if (!err) - err = errno; - ntfs_log_trace("Failed to get index context.\n"); - ntfs_inode_close(index_ni); - continue; - } - if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) { - if (!err) { - if (errno == ENOENT) - err = EIO; - else - err = errno; - } - ntfs_log_trace("Index lookup failed.\n"); - ntfs_index_ctx_put(ictx); - ntfs_inode_close(index_ni); - continue; - } - /* Update flags and file size. */ - fn = (FILE_NAME_ATTR *)ictx->data; - fn->file_attributes = - (fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) | - (ni->flags & FILE_ATTR_VALID_FLAGS); - fn->allocated_size = cpu_to_sle64(ni->allocated_size); - fn->data_size = cpu_to_sle64(ni->data_size); - fn->creation_time = utc2ntfs(ni->creation_time); - fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); - fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); - fn->last_access_time = utc2ntfs(ni->last_access_time); - ntfs_index_entry_mark_dirty(ictx); - ntfs_index_ctx_put(ictx); - if (ni != index_ni) - ntfs_inode_close(index_ni); - } - /* Check for real error occurred. */ - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto err_out; - } - ntfs_attr_put_search_ctx(ctx); - if (err) { - errno = err; - return -1; - } - return 0; -err_out: - if (ctx) - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_inode_sync - write the inode (and its dirty extents) to disk - * @ni: ntfs inode to write - * - * Write the inode @ni to disk as well as its dirty extent inodes if such - * exist and @ni is a base inode. If @ni is an extent inode, only @ni is - * written completely disregarding its base inode and any other extent inodes. - * - * For a base inode with dirty extent inodes if any writes fail for whatever - * reason, the failing inode is skipped and the sync process is continued. At - * the end the error condition that brought about the failure is returned. Thus - * the smallest amount of data loss possible occurs. - * - * Return 0 on success or -1 on error with errno set to the error code. - * The following error codes are defined: - * EINVAL - Invalid arguments were passed to the function. - * EBUSY - Inode and/or one of its extents is busy, try again later. - * EIO - I/O error while writing the inode (or one of its extents). - */ -int ntfs_inode_sync(ntfs_inode *ni) -{ - int err = 0; - - if (!ni) { - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - /* Update FILE_NAME's in the index. */ - if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && - NInoFileNameTestAndClearDirty(ni) && - ntfs_inode_sync_file_name(ni)) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - } - ntfs_log_trace("Failed to sync FILE_NAME attributes.\n"); - NInoFileNameSetDirty(ni); - } - - /* Write out attribute list from cache to disk. */ - if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && - NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) { - ntfs_attr *na; - - na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); - if (!na) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - ntfs_log_trace("Attribute list sync failed " - "(open failed).\n"); - } - NInoAttrListSetDirty(ni); - } else { - if (na->data_size == ni->attr_list_size) { - if (ntfs_attr_pwrite(na, 0, ni->attr_list_size, - ni->attr_list) != - ni->attr_list_size) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - ntfs_log_trace("Attribute list " - "sync failed " - "(write).\n"); - } - NInoAttrListSetDirty(ni); - } - } else { - err = EIO; - ntfs_log_trace("Attribute list sync failed " - "(invalid size).\n"); - NInoAttrListSetDirty(ni); - } - ntfs_attr_close(na); - } - } - - /* Write this inode out to the $MFT (and $MFTMirr if applicable). */ - if (NInoTestAndClearDirty(ni)) { - /* Update STANDARD_INFORMATION. */ - if ((ni->mrec->flags & MFT_RECORD_IN_USE) && - ni->nr_extents != -1 && - ntfs_inode_sync_standard_information(ni)) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - } - ntfs_log_trace("Failed to sync standard " - "information.\n"); - } - /* Write MFT record. */ - if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - } - NInoSetDirty(ni); - ntfs_log_trace("Base MFT record sync failed.\n"); - } - } - - /* If this is a base inode with extents write all dirty extents, too. */ - if (ni->nr_extents > 0) { - s32 i; - - for (i = 0; i < ni->nr_extents; ++i) { - ntfs_inode *eni; - - eni = ni->u.extent_nis[i]; - if (NInoTestAndClearDirty(eni)) { - if (ntfs_mft_record_write(eni->vol, eni->mft_no, - eni->mrec)) { - if (!err || errno == EIO) { - err = errno; - if (err != EIO) - err = EBUSY; - } - NInoSetDirty(eni); - ntfs_log_trace("Extent MFT record sync " - "failed.\n"); - } - } - } - } - - if (!err) - return 0; - errno = err; - return -1; -} - -/** - * ntfs_inode_add_attrlist - add attribute list to inode and fill it - * @ni: opened ntfs inode to which add attribute list - * - * Return 0 on success or -1 on error with errno set to the error code. - * The following error codes are defined: - * EINVAL - Invalid arguments were passed to the function. - * EEXIST - Attribute list already exist. - * EIO - Input/Ouput error occurred. - * ENOMEM - Not enough memory to perform add. - */ -int ntfs_inode_add_attrlist(ntfs_inode *ni) -{ - int err; - ntfs_attr_search_ctx *ctx; - u8 *al, *aln; - int al_len, al_allocated; - ATTR_LIST_ENTRY *ale; - ntfs_attr *na; - - if (!ni) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - if (NInoAttrList(ni) || ni->nr_extents) { - ntfs_log_trace("Inode already has got attribute list.\n"); - errno = EEXIST; - return -1; - } - - al_allocated = 0x40; - al_len = 0; - al = malloc(al_allocated); - NTFS_ON_DEBUG(memset(al, 0, 0x40)); /* Valgrind. */ - ale = (ATTR_LIST_ENTRY *) al; - if (!al) { - ntfs_log_trace("Not enough memory.\n"); - errno = ENOMEM; - return -1; - } - - /* Form attribute list. */ - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) { - err = errno; - ntfs_log_trace("Couldn't get search context.\n"); - goto err_out; - } - /* Walk through all attributes. */ - while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { - if (ctx->attr->type == AT_ATTRIBUTE_LIST) { - err = EIO; - ntfs_log_trace("Attribute list already present.\n"); - goto put_err_out; - } - /* Calculate new length of attribute list. */ - al_len += (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * - ctx->attr->name_length + 7) & ~7; - /* Allocate more memory if needed. */ - while (al_len > al_allocated) { - al_allocated += 0x40; - aln = realloc(al, al_allocated); - NTFS_ON_DEBUG(memset(aln + al_allocated - 0x40, 0, - 0x40)); /* Valgrind. */ - if (!aln) { - ntfs_log_trace("Not enough memory.\n"); - err = ENOMEM; - goto put_err_out; - } - ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al)); - al = aln; - } - /* Add attribute to attribute list. */ - ale->type = ctx->attr->type; - ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) + - sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7); - ale->name_length = ctx->attr->name_length; - ale->name_offset = (u8 *)ale->name - (u8 *)ale; - if (ctx->attr->non_resident) - ale->lowest_vcn = ctx->attr->u.nonres.lowest_vcn; - else - ale->lowest_vcn = 0; - ale->mft_reference = MK_LE_MREF(ni->mft_no, - le16_to_cpu(ni->mrec->sequence_number)); - ale->instance = ctx->attr->instance; - memcpy(ale->name, (u8 *)ctx->attr + - le16_to_cpu(ctx->attr->name_offset), - ctx->attr->name_length * sizeof(ntfschar)); - ale = (ATTR_LIST_ENTRY *)(al + al_len); - } - /* Check for real error occurred. */ - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto put_err_out; - } - /* Deallocate trailing memory. */ - aln = realloc(al, al_len); - if (!aln) { - err = errno; - ntfs_log_trace("realloc() failed.\n"); - goto put_err_out; - } - al = aln; - - /* Set in-memory attribute list. */ - ni->attr_list = al; - ni->attr_list_size = al_len; - NInoSetAttrList(ni); - NInoAttrListSetDirty(ni); - - /* Free space if there is not enough it for $ATTRIBUTE_LIST. */ - if (le32_to_cpu(ni->mrec->bytes_allocated) - - le32_to_cpu(ni->mrec->bytes_in_use) < - offsetof(ATTR_RECORD, u.res.resident_end)) { - if (ntfs_inode_free_space(ni, - offsetof(ATTR_RECORD, u.res.resident_end))) { - /* Failed to free space. */ - err = errno; - ntfs_log_trace("Failed to free space for " - "$ATTRIBUTE_LIST.\n"); - goto rollback; - } - } - - /* Add $ATTRIBUTE_LIST to mft record. */ - if (ntfs_resident_attr_record_add(ni, - AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) { - err = errno; - ntfs_log_trace("Couldn't add $ATTRIBUTE_LIST to MFT record.\n"); - goto rollback; - } - - /* Resize it. */ - na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); - if (!na) { - err = errno; - ntfs_log_trace("Failed to open just added $ATTRIBUTE_LIST.\n"); - goto remove_attrlist_record; - } - if (ntfs_attr_truncate(na, al_len)) { - err = errno; - ntfs_log_trace("Failed to resize just added $ATTRIBUTE_LIST.\n"); - ntfs_attr_close(na); - goto remove_attrlist_record;; - } - /* Done! */ - ntfs_attr_put_search_ctx(ctx); - ntfs_attr_close(na); - return 0; -remove_attrlist_record: - /* Prevent ntfs_attr_recorm_rm from freeing attribute list. */ - ni->attr_list = NULL; - NInoClearAttrList(ni); - /* Remove $ATTRIBUTE_LIST record. */ - ntfs_attr_reinit_search_ctx(ctx); - if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, - CASE_SENSITIVE, 0, NULL, 0, ctx)) { - if (ntfs_attr_record_rm(ctx)) - ntfs_log_trace("Rollback failed. Failed to remove attribute " - "list record.\n"); - } else - ntfs_log_trace("Rollback failed. Couldn't find attribute list " - "record.\n"); - /* Setup back in-memory runlist. */ - ni->attr_list = al; - ni->attr_list_size = al_len; - NInoSetAttrList(ni); -rollback: - /* - * Scan attribute list for attributes that placed not in the base MFT - * record and move them to it. - */ - ntfs_attr_reinit_search_ctx(ctx); - ale = (ATTR_LIST_ENTRY*)al; - while ((u8*)ale < al + al_len) { - if (MREF_LE(ale->mft_reference) != ni->mft_no) { - if (!ntfs_attr_lookup(ale->type, ale->name, - ale->name_length, - CASE_SENSITIVE, - sle64_to_cpu(ale->lowest_vcn), - NULL, 0, ctx)) { - if (ntfs_attr_record_move_to(ctx, ni)) - ntfs_log_trace("Rollback failed. Couldn't " - "back attribute to base MFT record.\n"); - } else - ntfs_log_trace("Rollback failed. ntfs_attr_lookup " - "failed.\n"); - ntfs_attr_reinit_search_ctx(ctx); - } - ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length)); - } - /* Remove in-memory attribute list. */ - ni->attr_list = NULL; - ni->attr_list_size = 0; - NInoClearAttrList(ni); - NInoAttrListClearDirty(ni); -put_err_out: - ntfs_attr_put_search_ctx(ctx); -err_out: - free(al); - errno = err; - return -1; -} - -/** - * ntfs_inode_free_space - free space in the MFT record of inode - * @ni: ntfs inode in which MFT record free space - * @size: amount of space needed to free - * - * Return 0 on success or -1 on error with errno set to the error code. - */ -int ntfs_inode_free_space(ntfs_inode *ni, int size) -{ - ntfs_attr_search_ctx *ctx; - int freed, err; - - if (!ni || size < 0) { - ntfs_log_trace("Invalid arguments.\n"); - errno = EINVAL; - return -1; - } - - ntfs_log_trace("Entering for inode 0x%llx, size %d.\n", - (long long) ni->mft_no, size); - - freed = (le32_to_cpu(ni->mrec->bytes_allocated) - - le32_to_cpu(ni->mrec->bytes_in_use)); - - if (size <= freed) - return 0; - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) { - ntfs_log_trace("Failed to get attribute search context.\n"); - return -1; - } - - /* - * Chkdsk complain if $STANDARD_INFORMATION is not in the base MFT - * record. FIXME: I'm not sure in this, need to recheck. For now simply - * do not move $STANDARD_INFORMATION at all. - * - * Also we can't move $ATTRIBUTE_LIST from base MFT_RECORD, so position - * search context on first attribute after $STANDARD_INFORMATION and - * $ATTRIBUTE_LIST. - * - * Why we reposition instead of simply skip this attributes during - * enumeration? Because in case we have got only in-memory attribute - * list ntfs_attr_lookup will fail when it will try to find - * $ATTRIBUTE_LIST. - */ - if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL, - 0, ctx)) { - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - goto put_err_out; - } - if (ctx->attr->type == AT_END) { - err = ENOSPC; - goto put_err_out; - } - } - - while (1) { - int record_size; - - /* - * Check whether attribute is from different MFT record. If so, - * find next, because we don't need such. - */ - while (ctx->ntfs_ino->mft_no != ni->mft_no) { - if (ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, - 0, NULL, 0, ctx)) { - err = errno; - if (errno != ENOENT) { - ntfs_log_trace("Attribute lookup failed.\n"); - } else - err = ENOSPC; - goto put_err_out; - } - } - - record_size = le32_to_cpu(ctx->attr->length); - - /* Move away attribute. */ - if (ntfs_attr_record_move_away(ctx, 0)) { - err = errno; - ntfs_log_trace("Failed to move out attribute.\n"); - break; - } - freed += record_size; - - /* Check whether we done. */ - if (size <= freed) { - ntfs_attr_put_search_ctx(ctx); - return 0; - } - - /* - * Reposition to first attribute after $STANDARD_INFORMATION and - * $ATTRIBUTE_LIST (see comments upwards). - */ - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, - NULL, 0, ctx)) { - if (errno != ENOENT) { - err = errno; - ntfs_log_trace("Attribute lookup failed.\n"); - break; - } - if (ctx->attr->type == AT_END) { - err = ENOSPC; - break; - } - } - } -put_err_out: - ntfs_attr_put_search_ctx(ctx); - if (err == ENOSPC) - ntfs_log_trace("No attributes left that can be moved out.\n"); - errno = err; - return -1; -} - -/** - * ntfs_inode_update_times - update selected time fields for ntfs inode - * @ni: ntfs inode for which update time fields - * @mask: select which time fields should be updated - * - * This function updates time fields to current time. Fields to update are - * selected using @mask (see enum @ntfs_time_update_flags for posssible values). - */ -void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask) -{ - time_t now; - - if (!ni) { - ntfs_log_error("%s(): Invalid arguments.\n", "ntfs_inode_update_times"); - return; - } - if ((ni->mft_no < FILE_first_user && ni->mft_no != FILE_root) || - NVolReadOnly(ni->vol) || !mask) - return; - - now = time(NULL); - if (mask & NTFS_UPDATE_ATIME) - ni->last_access_time = now; - if (mask & NTFS_UPDATE_MTIME) - ni->last_data_change_time = now; - if (mask & NTFS_UPDATE_CTIME) - ni->last_mft_change_time = now; - NInoFileNameSetDirty(ni); - NInoSetDirty(ni); -} - -/** - * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute - * @mft_no: mft record number where @attr is present - * @attr: attribute record used to check for the $Bad attribute - * - * Check if the mft record given by @mft_no and @attr contains the bad sector - * list. Please note that mft record numbers describing $Badclus extent inodes - * will not match the current $Badclus:$Bad check. - * - * On success return 1 if the file is $Badclus:$Bad, otherwise return 0. - * On error return -1 with errno set to the error code. - */ -int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr) -{ - int len, ret = 0; - ntfschar *ustr; - - if (!attr) { - ntfs_log_error("Invalid argument.\n"); - errno = EINVAL; - return -1; - } - - if (mft_no != FILE_BadClus) - return 0; - - if (attr->type != AT_DATA) - return 0; - - if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) { - ntfs_log_perror("Couldn't convert '$Bad' to Unicode"); - return -1; - } - - if (ustr && ntfs_names_are_equal(ustr, len, - (ntfschar *)((u8 *)attr + le16_to_cpu( - attr->name_offset)), attr->name_length, 0, NULL, 0)) - ret = 1; - - ntfs_ucsfree(ustr); - - return ret; -} diff --git a/usr/src/lib/libntfs/common/libntfs/lcnalloc.c b/usr/src/lib/libntfs/common/libntfs/lcnalloc.c deleted file mode 100644 index 7f42f8a564..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/lcnalloc.c +++ /dev/null @@ -1,858 +0,0 @@ -/** - * lcnalloc.c - Cluster (de)allocation code. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2004 Anton Altaparmakov - * Copyright (c) 2004 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "attrib.h" -#include "bitmap.h" -#include "debug.h" -#include "runlist.h" -#include "volume.h" -#include "lcnalloc.h" -#include "logging.h" - -/** - * ntfs_cluster_alloc - allocate clusters on an ntfs volume - * @vol: mounted ntfs volume on which to allocate the clusters - * @start_vcn: vcn to use for the first allocated cluster - * @count: number of clusters to allocate - * @start_lcn: starting lcn at which to allocate the clusters (or -1 if none) - * @zone: zone from which to allocate the clusters - * - * Allocate @count clusters preferably starting at cluster @start_lcn or at the - * current allocator position if @start_lcn is -1, on the mounted ntfs volume - * @vol. @zone is either DATA_ZONE for allocation of normal clusters and - * MFT_ZONE for allocation of clusters for the master file table, i.e. the - * $MFT/$DATA attribute. - * - * On success return a runlist describing the allocated cluster(s). - * - * On error return NULL with errno set to the error code. - * - * Notes on the allocation algorithm - * ================================= - * - * There are two data zones. First is the area between the end of the mft zone - * and the end of the volume, and second is the area between the start of the - * volume and the start of the mft zone. On unmodified/standard NTFS 1.x - * volumes, the second data zone doesn't exist due to the mft zone being - * expanded to cover the start of the volume in order to reserve space for the - * mft bitmap attribute. - * - * This is not the prettiest function but the complexity stems from the need of - * implementing the mft vs data zoned approach and from the fact that we have - * access to the lcn bitmap in portions of up to 8192 bytes at a time, so we - * need to cope with crossing over boundaries of two buffers. Further, the fact - * that the allocator allows for caller supplied hints as to the location of - * where allocation should begin and the fact that the allocator keeps track of - * where in the data zones the next natural allocation should occur, contribute - * to the complexity of the function. But it should all be worthwhile, because - * this allocator should: 1) be a full implementation of the MFT zone approach - * used by Windows, 2) cause reduction in fragmentation as much as possible, - * and 3) be speedy in allocations (the code is not optimized for speed, but - * the algorithm is, so further speed improvements are probably possible). - * - * FIXME: We should be monitoring cluster allocation and increment the MFT zone - * size dynamically but this is something for the future. We will just cause - * heavier fragmentation by not doing it and I am not even sure Windows would - * grow the MFT zone dynamically, so it might even be correct not to do this. - * The overhead in doing dynamic MFT zone expansion would be very large and - * unlikely worth the effort. (AIA) - * - * TODO: I have added in double the required zone position pointer wrap around - * logic which can be optimized to having only one of the two logic sets. - * However, having the double logic will work fine, but if we have only one of - * the sets and we get it wrong somewhere, then we get into trouble, so - * removing the duplicate logic requires _very_ careful consideration of _all_ - * possible code paths. So at least for now, I am leaving the double logic - - * better safe than sorry... (AIA) - */ -runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, - LCN start_lcn, const NTFS_CLUSTER_ALLOCATION_ZONES zone) -{ - LCN zone_start, zone_end, bmp_pos, bmp_initial_pos, last_read_pos, lcn; - LCN prev_lcn = 0, prev_run_len = 0, mft_zone_size; - s64 clusters, br; - runlist *rl = NULL, *trl; - u8 *buf, *byte; - int err = 0, rlpos, rlsize, buf_size; - u8 pass, done_zones, search_zone, need_writeback, bit; - - ntfs_log_trace("Entering with count = 0x%llx, start_lcn = 0x%llx, zone = " - "%s_ZONE.\n", (long long)count, (long long)start_lcn, - zone == MFT_ZONE ? "MFT" : "DATA"); - if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na || - (s8)zone < FIRST_ZONE || zone > LAST_ZONE) { - ntfs_log_trace("Invalid arguments!\n"); - errno = EINVAL; - return NULL; - } - - /* Return empty runlist if @count == 0 */ - if (!count) { - rl = ntfs_malloc(0x1000); - if (!rl) - return NULL; - rl[0].vcn = start_vcn; - rl[0].lcn = LCN_RL_NOT_MAPPED; - rl[0].length = 0; - return rl; - } - - /* Allocate memory. */ - buf = (u8*)ntfs_malloc(8192); - if (!buf) - return NULL; - /* - * If no specific @start_lcn was requested, use the current data zone - * position, otherwise use the requested @start_lcn but make sure it - * lies outside the mft zone. Also set done_zones to 0 (no zones done) - * and pass depending on whether we are starting inside a zone (1) or - * at the beginning of a zone (2). If requesting from the MFT_ZONE, - * we either start at the current position within the mft zone or at - * the specified position. If the latter is out of bounds then we start - * at the beginning of the MFT_ZONE. - */ - done_zones = 0; - pass = 1; - /* - * zone_start and zone_end are the current search range. search_zone - * is 1 for mft zone, 2 for data zone 1 (end of mft zone till end of - * volume) and 4 for data zone 2 (start of volume till start of mft - * zone). - */ - zone_start = start_lcn; - if (zone_start < 0) { - if (zone == DATA_ZONE) - zone_start = vol->data1_zone_pos; - else - zone_start = vol->mft_zone_pos; - if (!zone_start) { - /* - * Zone starts at beginning of volume which means a - * single pass is sufficient. - */ - pass = 2; - } - } else if (zone == DATA_ZONE && zone_start >= vol->mft_zone_start && - zone_start < vol->mft_zone_end) { - zone_start = vol->mft_zone_end; - /* - * Starting at beginning of data1_zone which means a single - * pass in this zone is sufficient. - */ - pass = 2; - } else if (zone == MFT_ZONE && (zone_start < vol->mft_zone_start || - zone_start >= vol->mft_zone_end)) { - zone_start = vol->mft_lcn; - if (!vol->mft_zone_end) - zone_start = 0; - /* - * Starting at beginning of volume which means a single pass - * is sufficient. - */ - pass = 2; - } - if (zone == MFT_ZONE) { - zone_end = vol->mft_zone_end; - search_zone = 1; - } else /* if (zone == DATA_ZONE) */ { - /* Skip searching the mft zone. */ - done_zones |= 1; - if (zone_start >= vol->mft_zone_end) { - zone_end = vol->nr_clusters; - search_zone = 2; - } else { - zone_end = vol->mft_zone_start; - search_zone = 4; - } - } - /* - * bmp_pos is the current bit position inside the bitmap. We use - * bmp_initial_pos to determine whether or not to do a zone switch. - */ - bmp_pos = bmp_initial_pos = zone_start; - - /* Loop until all clusters are allocated, i.e. clusters == 0. */ - clusters = count; - rlpos = rlsize = 0; - while (1) { - ntfs_log_trace("Start of outer while loop: done_zones = 0x%x, " - "search_zone = %i, pass = %i, zone_start = " - "0x%llx, zone_end = 0x%llx, bmp_initial_pos = " - "0x%llx, bmp_pos = 0x%llx, rlpos = %i, rlsize = " - "%i.\n", done_zones, search_zone, pass, - (long long)zone_start, (long long)zone_end, - (long long)bmp_initial_pos, (long long)bmp_pos, - rlpos, rlsize); - /* Loop until we run out of free clusters. */ - last_read_pos = bmp_pos >> 3; - ntfs_log_trace("last_read_pos = 0x%llx.\n", (long long)last_read_pos); - br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, 8192, buf); - if (br <= 0) { - if (!br) { - /* Reached end of attribute. */ - ntfs_log_trace("End of attribute reached. Skipping " - "to zone_pass_done.\n"); - goto zone_pass_done; - } - err = errno; - ntfs_log_trace("ntfs_attr_pread() failed. Aborting.\n"); - goto err_ret; - } - /* - * We might have read less than 8192 bytes if we are close to - * the end of the attribute. - */ - buf_size = (int)br << 3; - lcn = bmp_pos & 7; - bmp_pos &= ~7; - need_writeback = 0; - ntfs_log_trace("Before inner while loop: buf_size = %i, lcn = " - "0x%llx, bmp_pos = 0x%llx, need_writeback = %i.\n", - buf_size, (long long)lcn, (long long)bmp_pos, - need_writeback); - while (lcn < buf_size && lcn + bmp_pos < zone_end) { - byte = buf + (lcn >> 3); - ntfs_log_trace("In inner while loop: buf_size = %i, lcn = " - "0x%llx, bmp_pos = 0x%llx, " - "need_writeback = %i, byte ofs = 0x%x, " - "*byte = 0x%x.\n", buf_size, - (long long)lcn, (long long)bmp_pos, - need_writeback, (unsigned int)(lcn >> 3), - (unsigned int)*byte); - /* Skip full bytes. */ - if (*byte == 0xff) { - lcn = (lcn + 8) & ~7; - ntfs_log_trace("continuing while loop 1.\n"); - continue; - } - bit = 1 << (lcn & 7); - ntfs_log_trace("bit = %i.\n", bit); - /* If the bit is already set, go onto the next one. */ - if (*byte & bit) { - lcn++; - ntfs_log_trace("continuing while loop 2.\n"); - continue; - } - /* Reallocate memory if necessary. */ - if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) { - ntfs_log_trace("Reallocating space.\n"); - if (!rl) - ntfs_log_trace("First free bit is at LCN = " - "0x%llx.\n", (long long)(lcn + bmp_pos)); - rlsize += 4096; - trl = (runlist*)realloc(rl, rlsize); - if (!trl) { - err = ENOMEM; - ntfs_log_trace("Failed to allocate memory, " - "going to wb_err_ret.\n"); - goto wb_err_ret; - } - rl = trl; - ntfs_log_trace("Reallocated memory, rlsize = " - "0x%x.\n", rlsize); - } - /* Allocate the bitmap bit. */ - *byte |= bit; - vol->nr_free_clusters--; - /* We need to write this bitmap buffer back to disk! */ - need_writeback = 1; - ntfs_log_trace("*byte = 0x%x, need_writeback is set.\n", - (unsigned int)*byte); - /* - * Coalesce with previous run if adjacent LCNs. - * Otherwise, append a new run. - */ - ntfs_log_trace("Adding run (lcn 0x%llx, len 0x%llx), " - "prev_lcn = 0x%llx, lcn = 0x%llx, " - "bmp_pos = 0x%llx, prev_run_len = " - "0x%llx, rlpos = %i.\n", - (long long)(lcn + bmp_pos), 1LL, - (long long)prev_lcn, (long long)lcn, - (long long)bmp_pos, - (long long)prev_run_len, rlpos); - if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) { - ntfs_log_trace("Coalescing to run (lcn 0x%llx, len " - "0x%llx).\n", - (long long)rl[rlpos - 1].lcn, - (long long) rl[rlpos - 1].length); - rl[rlpos - 1].length = ++prev_run_len; - ntfs_log_trace("Run now (lcn 0x%llx, len 0x%llx), " - "prev_run_len = 0x%llx.\n", - (long long)rl[rlpos - 1].lcn, - (long long)rl[rlpos - 1].length, - (long long)prev_run_len); - } else { - if (rlpos) { - ntfs_log_trace("Adding new run, (previous " - "run lcn 0x%llx, len 0x%llx).\n", - (long long) rl[rlpos - 1].lcn, - (long long) rl[rlpos - 1].length); - rl[rlpos].vcn = rl[rlpos - 1].vcn + - prev_run_len; - } else { - ntfs_log_trace("Adding new run, is first run.\n"); - rl[rlpos].vcn = start_vcn; - } - rl[rlpos].lcn = prev_lcn = lcn + bmp_pos; - rl[rlpos].length = prev_run_len = 1; - rlpos++; - } - /* Done? */ - if (!--clusters) { - LCN tc; - /* - * Update the current zone position. Positions - * of already scanned zones have been updated - * during the respective zone switches. - */ - tc = lcn + bmp_pos + 1; - ntfs_log_trace("Done. Updating current zone " - "position, tc = 0x%llx, search_zone = %i.\n", - (long long)tc, search_zone); - switch (search_zone) { - case 1: - ntfs_log_trace("Before checks, vol->mft_zone_pos = 0x%llx.\n", - (long long) vol->mft_zone_pos); - if (tc >= vol->mft_zone_end) { - vol->mft_zone_pos = - vol->mft_lcn; - if (!vol->mft_zone_end) - vol->mft_zone_pos = 0; - } else if ((bmp_initial_pos >= - vol->mft_zone_pos || - tc > vol->mft_zone_pos) - && tc >= vol->mft_lcn) - vol->mft_zone_pos = tc; - ntfs_log_trace("After checks, vol->mft_zone_pos = 0x%llx.\n", - (long long) vol->mft_zone_pos); - break; - case 2: - ntfs_log_trace("Before checks, vol->data1_zone_pos = 0x%llx.\n", - (long long) vol->data1_zone_pos); - if (tc >= vol->nr_clusters) - vol->data1_zone_pos = - vol->mft_zone_end; - else if ((bmp_initial_pos >= - vol->data1_zone_pos || - tc > vol->data1_zone_pos) - && tc >= vol->mft_zone_end) - vol->data1_zone_pos = tc; - ntfs_log_trace("After checks, vol->data1_zone_pos = 0x%llx.\n", - (long long) vol->data1_zone_pos); - break; - case 4: - ntfs_log_trace("Before checks, vol->data2_zone_pos = 0x%llx.\n", - (long long) vol->data2_zone_pos); - if (tc >= vol->mft_zone_start) - vol->data2_zone_pos = 0; - else if (bmp_initial_pos >= - vol->data2_zone_pos || - tc > vol->data2_zone_pos) - vol->data2_zone_pos = tc; - ntfs_log_trace("After checks, vol->data2_zone_pos = 0x%llx.\n", - (long long) vol->data2_zone_pos); - break; - default: - free(rl); - free(buf); - NTFS_BUG("switch (search_zone) 1"); - return NULL; - } - ntfs_log_trace("Going to done_ret.\n"); - goto done_ret; - } - lcn++; - } - bmp_pos += buf_size; - ntfs_log_trace("After inner while loop: buf_size = 0x%x, lcn = " - "0x%llx, bmp_pos = 0x%llx, need_writeback = %i.\n", - buf_size, (long long)lcn, - (long long)bmp_pos, need_writeback); - if (need_writeback) { - s64 bw; - ntfs_log_trace("Writing back.\n"); - need_writeback = 0; - bw = ntfs_attr_pwrite(vol->lcnbmp_na, last_read_pos, - br, buf); - if (bw != br) { - if (bw == -1) - err = errno; - else - err = EIO; - ntfs_log_trace("Bitmap writeback failed in read next " - "buffer code path with error code %i.\n", err); - goto err_ret; - } - } - if (bmp_pos < zone_end) { - ntfs_log_trace("Continuing outer while loop, bmp_pos = " - "0x%llx, zone_end = 0x%llx.\n", - (long long)bmp_pos, - (long long)zone_end); - continue; - } -zone_pass_done: /* Finished with the current zone pass. */ - ntfs_log_trace("At zone_pass_done, pass = %i.\n", pass); - if (pass == 1) { - /* - * Now do pass 2, scanning the first part of the zone - * we omitted in pass 1. - */ - pass = 2; - zone_end = zone_start; - switch (search_zone) { - case 1: /* mft_zone */ - zone_start = vol->mft_zone_start; - break; - case 2: /* data1_zone */ - zone_start = vol->mft_zone_end; - break; - case 4: /* data2_zone */ - zone_start = 0; - break; - default: - NTFS_BUG("switch (search_zone) 2"); - } - /* Sanity check. */ - if (zone_end < zone_start) - zone_end = zone_start; - bmp_pos = zone_start; - ntfs_log_trace("Continuing outer while loop, pass = 2, " - "zone_start = 0x%llx, zone_end = " - "0x%llx, bmp_pos = 0x%llx.\n", - zone_start, zone_end, bmp_pos); - continue; - } /* pass == 2 */ -done_zones_check: - ntfs_log_trace("At done_zones_check, search_zone = %i, done_zones " - "before = 0x%x, done_zones after = 0x%x.\n", - search_zone, done_zones, done_zones | search_zone); - done_zones |= search_zone; - if (done_zones < 7) { - ntfs_log_trace("Switching zone.\n"); - /* Now switch to the next zone we haven't done yet. */ - pass = 1; - switch (search_zone) { - case 1: - ntfs_log_trace("Switching from mft zone to data1 " - "zone.\n"); - /* Update mft zone position. */ - if (rlpos) { - LCN tc; - ntfs_log_trace("Before checks, vol->mft_zone_pos = 0x%llx.\n", - (long long) vol->mft_zone_pos); - tc = rl[rlpos - 1].lcn + - rl[rlpos - 1].length; - if (tc >= vol->mft_zone_end) { - vol->mft_zone_pos = - vol->mft_lcn; - if (!vol->mft_zone_end) - vol->mft_zone_pos = 0; - } else if ((bmp_initial_pos >= - vol->mft_zone_pos || - tc > vol->mft_zone_pos) - && tc >= vol->mft_lcn) - vol->mft_zone_pos = tc; - ntfs_log_trace("After checks, vol->mft_zone_pos = 0x%llx.\n", - (long long) vol->mft_zone_pos); - } - /* Switch from mft zone to data1 zone. */ -switch_to_data1_zone: search_zone = 2; - zone_start = bmp_initial_pos = - vol->data1_zone_pos; - zone_end = vol->nr_clusters; - if (zone_start == vol->mft_zone_end) - pass = 2; - if (zone_start >= zone_end) { - vol->data1_zone_pos = zone_start = - vol->mft_zone_end; - pass = 2; - } - break; - case 2: - ntfs_log_trace("Switching from data1 zone to data2 " - "zone.\n"); - /* Update data1 zone position. */ - if (rlpos) { - LCN tc; - ntfs_log_trace("Before checks, vol->data1_zone_pos = 0x%llx.\n", - (long long) vol->data1_zone_pos); - tc = rl[rlpos - 1].lcn + - rl[rlpos - 1].length; - if (tc >= vol->nr_clusters) - vol->data1_zone_pos = - vol->mft_zone_end; - else if ((bmp_initial_pos >= - vol->data1_zone_pos || - tc > vol->data1_zone_pos) - && tc >= vol->mft_zone_end) - vol->data1_zone_pos = tc; - ntfs_log_trace("After checks, vol->data1_zone_pos = 0x%llx.\n", - (long long) vol->data1_zone_pos); - } - /* Switch from data1 zone to data2 zone. */ - search_zone = 4; - zone_start = bmp_initial_pos = - vol->data2_zone_pos; - zone_end = vol->mft_zone_start; - if (!zone_start) - pass = 2; - if (zone_start >= zone_end) { - vol->data2_zone_pos = zone_start = - bmp_initial_pos = 0; - pass = 2; - } - break; - case 4: - ntfs_log_debug("Switching from data2 zone to data1 " - "zone.\n"); - /* Update data2 zone position. */ - if (rlpos) { - LCN tc; - ntfs_log_trace("Before checks, vol->data2_zone_pos = 0x%llx.\n", - (long long) vol->data2_zone_pos); - tc = rl[rlpos - 1].lcn + - rl[rlpos - 1].length; - if (tc >= vol->mft_zone_start) - vol->data2_zone_pos = 0; - else if (bmp_initial_pos >= - vol->data2_zone_pos || - tc > vol->data2_zone_pos) - vol->data2_zone_pos = tc; - ntfs_log_trace("After checks, vol->data2_zone_pos = 0x%llx.\n", - (long long) vol->data2_zone_pos); - } - /* Switch from data2 zone to data1 zone. */ - goto switch_to_data1_zone; /* See above. */ - default: - NTFS_BUG("switch (search_zone) 3"); - } - ntfs_log_trace("After zone switch, search_zone = %i, pass = " - "%i, bmp_initial_pos = 0x%llx, " - "zone_start = 0x%llx, zone_end = " - "0x%llx.\n", search_zone, pass, - (long long)bmp_initial_pos, - (long long)zone_start, - (long long)zone_end); - bmp_pos = zone_start; - if (zone_start == zone_end) { - ntfs_log_trace("Empty zone, going to " - "done_zones_check.\n"); - /* Empty zone. Don't bother searching it. */ - goto done_zones_check; - } - ntfs_log_trace("Continuing outer while loop.\n"); - continue; - } /* done_zones == 7 */ - ntfs_log_trace("All zones are finished.\n"); - /* - * All zones are finished! If DATA_ZONE, shrink mft zone. If - * MFT_ZONE, we have really run out of space. - */ - mft_zone_size = vol->mft_zone_end - vol->mft_zone_start; - ntfs_log_trace("vol->mft_zone_start = 0x%llx, vol->mft_zone_end = " - "0x%llx, mft_zone_size = 0x%llx.\n", - (long long)vol->mft_zone_start, - (long long)vol->mft_zone_end, - (long long)mft_zone_size); - if (zone == MFT_ZONE || mft_zone_size <= 0) { - ntfs_log_trace("No free clusters left, going to err_ret.\n"); - /* Really no more space left on device. */ - err = ENOSPC; - goto err_ret; - } /* zone == DATA_ZONE && mft_zone_size > 0 */ - ntfs_log_trace("Shrinking mft zone.\n"); - zone_end = vol->mft_zone_end; - mft_zone_size >>= 1; - if (mft_zone_size > 0) - vol->mft_zone_end = vol->mft_zone_start + mft_zone_size; - else /* mft zone and data2 zone no longer exist. */ - vol->data2_zone_pos = vol->mft_zone_start = - vol->mft_zone_end = 0; - if (vol->mft_zone_pos >= vol->mft_zone_end) { - vol->mft_zone_pos = vol->mft_lcn; - if (!vol->mft_zone_end) - vol->mft_zone_pos = 0; - } - bmp_pos = zone_start = bmp_initial_pos = - vol->data1_zone_pos = vol->mft_zone_end; - search_zone = 2; - pass = 2; - done_zones &= ~2; - ntfs_log_trace("After shrinking mft zone, mft_zone_size = 0x%llx, " - "vol->mft_zone_start = 0x%llx, " - "vol->mft_zone_end = 0x%llx, vol->mft_zone_pos " - "= 0x%llx, search_zone = 2, pass = 2, " - "dones_zones = 0x%x, zone_start = 0x%llx, " - "zone_end = 0x%llx, vol->data1_zone_pos = " - "0x%llx, continuing outer while loop.\n", - (long long)mft_zone_size, - (long long)vol->mft_zone_start, - (long long)vol->mft_zone_end, - (long long)vol->mft_zone_pos, - done_zones, - (long long)zone_start, - (long long)zone_end, - (long long)vol->data1_zone_pos); - } - ntfs_log_debug("After outer while loop.\n"); -done_ret: - ntfs_log_debug("At done_ret.\n"); - /* Add runlist terminator element. */ - rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; - rl[rlpos].lcn = LCN_RL_NOT_MAPPED; - rl[rlpos].length = 0; - if (need_writeback) { - s64 bw; - ntfs_log_trace("Writing back.\n"); - need_writeback = 0; - bw = ntfs_attr_pwrite(vol->lcnbmp_na, last_read_pos, br, buf); - if (bw != br) { - if (bw < 0) - err = errno; - else - err = EIO; - ntfs_log_trace("Bitmap writeback failed in done code path " - "with error code %i.\n", err); - goto err_ret; - } - } -done_err_ret: - ntfs_log_debug("At done_err_ret (follows done_ret).\n"); - free(buf); - /* Done! */ - if (!err) - return rl; - ntfs_log_trace("Failed to allocate clusters. Returning with error code " - "%i.\n", err); - errno = err; - return NULL; -wb_err_ret: - ntfs_log_trace("At wb_err_ret.\n"); - if (need_writeback) { - s64 bw; - ntfs_log_trace("Writing back.\n"); - need_writeback = 0; - bw = ntfs_attr_pwrite(vol->lcnbmp_na, last_read_pos, br, buf); - if (bw != br) { - if (bw < 0) - err = errno; - else - err = EIO; - ntfs_log_trace("Bitmap writeback failed in error code path " - "with error code %i.\n", err); - } - } -err_ret: - ntfs_log_trace("At err_ret.\n"); - if (rl) { - if (err == ENOSPC) { - ntfs_log_trace("err = ENOSPC, first free lcn = 0x%llx, could " - "allocate up to = 0x%llx clusters.\n", - (long long)rl[0].lcn, - (long long)count - clusters); - } - /* Add runlist terminator element. */ - rl[rlpos].vcn = rl[rlpos - 1].vcn + rl[rlpos - 1].length; - rl[rlpos].lcn = LCN_RL_NOT_MAPPED; - rl[rlpos].length = 0; - /* Deallocate all allocated clusters. */ - ntfs_log_trace("Deallocating allocated clusters.\n"); - ntfs_cluster_free_from_rl(vol, rl); - /* Free the runlist. */ - free(rl); - rl = NULL; - } else { - if (err == ENOSPC) { - ntfs_log_trace("No space left at all, err = ENOSPC, first " - "free lcn = 0x%llx.\n", - (long long)vol->data1_zone_pos); - } - } - ntfs_log_trace("rl = NULL, going to done_err_ret.\n"); - goto done_err_ret; -} - -/** - * ntfs_cluster_free_from_rl - free clusters from runlist - * @vol: mounted ntfs volume on which to free the clusters - * @rl: runlist from which deallocate clusters - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl) -{ - ntfs_log_trace("Entering.\n"); - - for (; rl->length; rl++) { - - ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", - (long long)rl->lcn, (long long)rl->length); - - if (rl->lcn >= 0 && ntfs_bitmap_clear_run(vol->lcnbmp_na, - rl->lcn, rl->length)) { - int eo = errno; - ntfs_log_trace("Eeek! Deallocation of clusters failed.\n"); - errno = eo; - return -1; - } - } - return 0; -} - -/** - * ntfs_cluster_free - free clusters on an ntfs volume - * @vol: mounted ntfs volume on which to free the clusters - * @na: attribute whose runlist describes the clusters to free - * @start_vcn: vcn in @rl at which to start freeing clusters - * @count: number of clusters to free or -1 for all clusters - * - * Free @count clusters starting at the cluster @start_vcn in the runlist - * described by the attribute @na from the mounted ntfs volume @vol. - * - * If @count is -1, all clusters from @start_vcn to the end of the runlist - * are deallocated. - * - * On success return the number of deallocated clusters (not counting sparse - * clusters) and on error return -1 with errno set to the error code. - */ -int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count) -{ - runlist *rl; - s64 nr_freed, delta, to_free; - - if (!vol || !vol->lcnbmp_na || !na || start_vcn < 0 || - (count < 0 && count != -1)) { - ntfs_log_trace("Invalid arguments!\n"); - errno = EINVAL; - return -1; - } - ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, " - "vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no, - na->type, (long long)count, (long long)start_vcn); - - rl = ntfs_attr_find_vcn(na, start_vcn); - if (!rl) { - if (errno == ENOENT) - return 0; - else - return -1; - } - - if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { - errno = EIO; - return -1; - } - - /* Find the starting cluster inside the run that needs freeing. */ - delta = start_vcn - rl->vcn; - - /* The number of clusters in this run that need freeing. */ - to_free = rl->length - delta; - if (count >= 0 && to_free > count) - to_free = count; - - if (rl->lcn != LCN_HOLE) { - /* Do the actual freeing of the clusters in this run. */ - if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn + delta, - to_free)) - return -1; - /* We have freed @to_free real clusters. */ - nr_freed = to_free; - } else { - /* No real clusters were freed. */ - nr_freed = 0; - } - - /* Go to the next run and adjust the number of clusters left to free. */ - ++rl; - if (count >= 0) - count -= to_free; - - /* - * Loop over the remaining runs, using @count as a capping value, and - * free them. - */ - for (; rl->length && count != 0; ++rl) { - // FIXME: Need to try ntfs_attr_map_runlist() for attribute - // list support! (AIA) - if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { - // FIXME: Eeek! We need rollback! (AIA) - ntfs_log_trace("Eeek! invalid lcn (= %lli). Should attempt " - "to map runlist! Leaving inconsistent " - "metadata!\n", (long long)rl->lcn); - errno = EIO; - return -1; - } - - /* The number of clusters in this run that need freeing. */ - to_free = rl->length; - if (count >= 0 && to_free > count) - to_free = count; - - if (rl->lcn != LCN_HOLE) { - /* Do the actual freeing of the clusters in the run. */ - if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, - to_free)) { - int eo = errno; - - // FIXME: Eeek! We need rollback! (AIA) - ntfs_log_trace("Eeek! bitmap clear run failed. " - "Leaving inconsistent metadata!\n"); - errno = eo; - return -1; - } - /* We have freed @to_free real clusters. */ - nr_freed += to_free; - } - - if (count >= 0) - count -= to_free; - } - - if (count != -1 && count != 0) { - // FIXME: Eeek! BUG() - ntfs_log_trace("Eeek! count still not zero (= %lli). Leaving " - "inconsistent metadata!\n", (long long)count); - errno = EIO; - return -1; - } - - /* Done. Return the number of actual clusters that were freed. */ - return nr_freed; -} diff --git a/usr/src/lib/libntfs/common/libntfs/logfile.c b/usr/src/lib/libntfs/common/libntfs/logfile.c deleted file mode 100644 index 054bd2f088..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/logfile.c +++ /dev/null @@ -1,769 +0,0 @@ -/** - * logfile.c - NTFS journal handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2005 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "debug.h" -#include "logfile.h" -#include "volume.h" -#include "mst.h" -#include "logging.h" - -/** - * ntfs_check_restart_page_header - check the page header for consistency - * @rp: restart page header to check - * @pos: position in logfile at which the restart page header resides - * - * Check the restart page header @rp for consistency and return TRUE if it is - * consistent and FALSE otherwise. - * - * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not - * require the full restart page. - */ -static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos) -{ - u32 logfile_system_page_size, logfile_log_page_size; - u16 ra_ofs, usa_count, usa_ofs, usa_end = 0; - BOOL have_usa = TRUE; - - ntfs_log_trace("Entering.\n"); - /* - * If the system or log page sizes are smaller than the ntfs block size - * or either is not a power of 2 we cannot handle this log file. - */ - logfile_system_page_size = le32_to_cpu(rp->system_page_size); - logfile_log_page_size = le32_to_cpu(rp->log_page_size); - if (logfile_system_page_size < NTFS_BLOCK_SIZE || - logfile_log_page_size < NTFS_BLOCK_SIZE || - logfile_system_page_size & - (logfile_system_page_size - 1) || - logfile_log_page_size & (logfile_log_page_size - 1)) { - ntfs_log_error("$LogFile uses unsupported page size.\n"); - return FALSE; - } - /* - * We must be either at !pos (1st restart page) or at pos = system page - * size (2nd restart page). - */ - if (pos && pos != logfile_system_page_size) { - ntfs_log_error("Found restart area in incorrect " - "position in $LogFile.\n"); - return FALSE; - } - /* We only know how to handle version 1.1. */ - if (sle16_to_cpu(rp->major_ver) != 1 || - sle16_to_cpu(rp->minor_ver) != 1) { - ntfs_log_error("$LogFile version %i.%i is not " - "supported. (This driver supports version " - "1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver), - (int)sle16_to_cpu(rp->minor_ver)); - return FALSE; - } - /* - * If chkdsk has been run the restart page may not be protected by an - * update sequence array. - */ - if (ntfs_is_chkd_record(rp->magic) && !le16_to_cpu(rp->usa_count)) { - have_usa = FALSE; - goto skip_usa_checks; - } - /* Verify the size of the update sequence array. */ - usa_count = 1 + (logfile_system_page_size >> NTFS_BLOCK_SIZE_BITS); - if (usa_count != le16_to_cpu(rp->usa_count)) { - ntfs_log_error("$LogFile restart page specifies " - "inconsistent update sequence array count.\n"); - return FALSE; - } - /* Verify the position of the update sequence array. */ - usa_ofs = le16_to_cpu(rp->usa_ofs); - usa_end = usa_ofs + usa_count * sizeof(u16); - if (usa_ofs < sizeof(RESTART_PAGE_HEADER) || - usa_end > NTFS_BLOCK_SIZE - sizeof(u16)) { - ntfs_log_error("$LogFile restart page specifies " - "inconsistent update sequence array offset.\n"); - return FALSE; - } -skip_usa_checks: - /* - * Verify the position of the restart area. It must be: - * - aligned to 8-byte boundary, - * - after the update sequence array, and - * - within the system page size. - */ - ra_ofs = le16_to_cpu(rp->restart_area_offset); - if (ra_ofs & 7 || (have_usa ? ra_ofs < usa_end : - ra_ofs < sizeof(RESTART_PAGE_HEADER)) || - ra_ofs > logfile_system_page_size) { - ntfs_log_error("$LogFile restart page specifies " - "inconsistent restart area offset.\n"); - return FALSE; - } - /* - * Only restart pages modified by chkdsk are allowed to have chkdsk_lsn - * set. - */ - if (!ntfs_is_chkd_record(rp->magic) && sle64_to_cpu(rp->chkdsk_lsn)) { - ntfs_log_error("$LogFile restart page is not modified " - "by chkdsk but a chkdsk LSN is specified.\n"); - return FALSE; - } - ntfs_log_trace("Done.\n"); - return TRUE; -} - -/** - * ntfs_check_restart_area - check the restart area for consistency - * @rp: restart page whose restart area to check - * - * Check the restart area of the restart page @rp for consistency and return - * TRUE if it is consistent and FALSE otherwise. - * - * This function assumes that the restart page header has already been - * consistency checked. - * - * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not - * require the full restart page. - */ -static BOOL ntfs_check_restart_area(RESTART_PAGE_HEADER *rp) -{ - u64 file_size; - RESTART_AREA *ra; - u16 ra_ofs, ra_len, ca_ofs; - u8 fs_bits; - - ntfs_log_trace("Entering.\n"); - ra_ofs = le16_to_cpu(rp->restart_area_offset); - ra = (RESTART_AREA*)((u8*)rp + ra_ofs); - /* - * Everything before ra->file_size must be before the first word - * protected by an update sequence number. This ensures that it is - * safe to access ra->client_array_offset. - */ - if (ra_ofs + offsetof(RESTART_AREA, file_size) > - NTFS_BLOCK_SIZE - sizeof(u16)) { - ntfs_log_error("$LogFile restart area specifies " - "inconsistent file offset.\n"); - return FALSE; - } - /* - * Now that we can access ra->client_array_offset, make sure everything - * up to the log client array is before the first word protected by an - * update sequence number. This ensures we can access all of the - * restart area elements safely. Also, the client array offset must be - * aligned to an 8-byte boundary. - */ - ca_ofs = le16_to_cpu(ra->client_array_offset); - if (((ca_ofs + 7) & ~7) != ca_ofs || - ra_ofs + ca_ofs > (u16)(NTFS_BLOCK_SIZE - - sizeof(u16))) { - ntfs_log_error("$LogFile restart area specifies " - "inconsistent client array offset.\n"); - return FALSE; - } - /* - * The restart area must end within the system page size both when - * calculated manually and as specified by ra->restart_area_length. - * Also, the calculated length must not exceed the specified length. - */ - ra_len = ca_ofs + le16_to_cpu(ra->log_clients) * - sizeof(LOG_CLIENT_RECORD); - if ((u32)(ra_ofs + ra_len) > le32_to_cpu(rp->system_page_size) || - (u32)(ra_ofs + le16_to_cpu(ra->restart_area_length)) > - le32_to_cpu(rp->system_page_size) || - ra_len > le16_to_cpu(ra->restart_area_length)) { - ntfs_log_error("$LogFile restart area is out of bounds " - "of the system page size specified by the " - "restart page header and/or the specified " - "restart area length is inconsistent.\n"); - return FALSE; - } - /* - * The ra->client_free_list and ra->client_in_use_list must be either - * LOGFILE_NO_CLIENT or less than ra->log_clients or they are - * overflowing the client array. - */ - if ((ra->client_free_list != LOGFILE_NO_CLIENT && - le16_to_cpu(ra->client_free_list) >= - le16_to_cpu(ra->log_clients)) || - (ra->client_in_use_list != LOGFILE_NO_CLIENT && - le16_to_cpu(ra->client_in_use_list) >= - le16_to_cpu(ra->log_clients))) { - ntfs_log_error("$LogFile restart area specifies " - "overflowing client free and/or in use lists.\n"); - return FALSE; - } - /* - * Check ra->seq_number_bits against ra->file_size for consistency. - * We cannot just use ffs() because the file size is not a power of 2. - */ - file_size = (u64)sle64_to_cpu(ra->file_size); - fs_bits = 0; - while (file_size) { - file_size >>= 1; - fs_bits++; - } - if (le32_to_cpu(ra->seq_number_bits) != (u32)(67 - fs_bits)) { - ntfs_log_error("$LogFile restart area specifies " - "inconsistent sequence number bits.\n"); - return FALSE; - } - /* The log record header length must be a multiple of 8. */ - if (((le16_to_cpu(ra->log_record_header_length) + 7) & ~7) != - le16_to_cpu(ra->log_record_header_length)) { - ntfs_log_error("$LogFile restart area specifies " - "inconsistent log record header length.\n"); - return FALSE; - } - /* Ditto for the log page data offset. */ - if (((le16_to_cpu(ra->log_page_data_offset) + 7) & ~7) != - le16_to_cpu(ra->log_page_data_offset)) { - ntfs_log_error("$LogFile restart area specifies " - "inconsistent log page data offset.\n"); - return FALSE; - } - ntfs_log_trace("Done.\n"); - return TRUE; -} - -/** - * ntfs_check_log_client_array - check the log client array for consistency - * @rp: restart page whose log client array to check - * - * Check the log client array of the restart page @rp for consistency and - * return TRUE if it is consistent and FALSE otherwise. - * - * This function assumes that the restart page header and the restart area have - * already been consistency checked. - * - * Unlike ntfs_check_restart_page_header() and ntfs_check_restart_area(), this - * function needs @rp->system_page_size bytes in @rp, i.e. it requires the full - * restart page and the page must be multi sector transfer deprotected. - */ -static BOOL ntfs_check_log_client_array(RESTART_PAGE_HEADER *rp) -{ - RESTART_AREA *ra; - LOG_CLIENT_RECORD *ca, *cr; - u16 nr_clients, idx; - BOOL in_free_list, idx_is_first; - - ntfs_log_trace("Entering.\n"); - ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); - ca = (LOG_CLIENT_RECORD*)((u8*)ra + - le16_to_cpu(ra->client_array_offset)); - /* - * Check the ra->client_free_list first and then check the - * ra->client_in_use_list. Check each of the log client records in - * each of the lists and check that the array does not overflow the - * ra->log_clients value. Also keep track of the number of records - * visited as there cannot be more than ra->log_clients records and - * that way we detect eventual loops in within a list. - */ - nr_clients = le16_to_cpu(ra->log_clients); - idx = le16_to_cpu(ra->client_free_list); - in_free_list = TRUE; -check_list: - for (idx_is_first = TRUE; idx != LOGFILE_NO_CLIENT_CPU; nr_clients--, - idx = le16_to_cpu(cr->next_client)) { - if (!nr_clients || idx >= le16_to_cpu(ra->log_clients)) - goto err_out; - /* Set @cr to the current log client record. */ - cr = ca + idx; - /* The first log client record must not have a prev_client. */ - if (idx_is_first) { - if (cr->prev_client != LOGFILE_NO_CLIENT) - goto err_out; - idx_is_first = FALSE; - } - } - /* Switch to and check the in use list if we just did the free list. */ - if (in_free_list) { - in_free_list = FALSE; - idx = le16_to_cpu(ra->client_in_use_list); - goto check_list; - } - ntfs_log_trace("Done.\n"); - return TRUE; -err_out: - ntfs_log_error("$LogFile log client array is corrupt.\n"); - return FALSE; -} - -/** - * ntfs_check_and_load_restart_page - check the restart page for consistency - * @log_na: opened ntfs attribute for journal $LogFile - * @rp: restart page to check - * @pos: position in @log_na at which the restart page resides - * @wrp: [OUT] copy of the multi sector transfer deprotected restart page - * @lsn: [OUT] set to the current logfile lsn on success - * - * Check the restart page @rp for consistency and return 0 if it is consistent - * and errno otherwise. The restart page may have been modified by chkdsk in - * which case its magic is CHKD instead of RSTR. - * - * This function only needs NTFS_BLOCK_SIZE bytes in @rp, i.e. it does not - * require the full restart page. - * - * If @wrp is not NULL, on success, *@wrp will point to a buffer containing a - * copy of the complete multi sector transfer deprotected page. On failure, - * *@wrp is undefined. - * - * Similarly, if @lsn is not NULL, on success *@lsn will be set to the current - * logfile lsn according to this restart page. On failure, *@lsn is undefined. - * - * The following error codes are defined: - * EINVAL - The restart page is inconsistent. - * ENOMEM - Not enough memory to load the restart page. - * EIO - Failed to reading from $LogFile. - */ -static int ntfs_check_and_load_restart_page(ntfs_attr *log_na, - RESTART_PAGE_HEADER *rp, s64 pos, RESTART_PAGE_HEADER **wrp, - LSN *lsn) -{ - RESTART_AREA *ra; - RESTART_PAGE_HEADER *trp; - int err; - - ntfs_log_trace("Entering.\n"); - /* Check the restart page header for consistency. */ - if (!ntfs_check_restart_page_header(rp, pos)) { - /* Error output already done inside the function. */ - return EINVAL; - } - /* Check the restart area for consistency. */ - if (!ntfs_check_restart_area(rp)) { - /* Error output already done inside the function. */ - return EINVAL; - } - ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); - /* - * Allocate a buffer to store the whole restart page so we can multi - * sector transfer deprotect it. - */ - trp = ntfs_malloc(le32_to_cpu(rp->system_page_size)); - if (!trp) - return ENOMEM; - /* - * Read the whole of the restart page into the buffer. If it fits - * completely inside @rp, just copy it from there. Otherwise read it - * from disk. - */ - if (le32_to_cpu(rp->system_page_size) <= NTFS_BLOCK_SIZE) - memcpy(trp, rp, le32_to_cpu(rp->system_page_size)); - else if (ntfs_attr_pread(log_na, pos, - le32_to_cpu(rp->system_page_size), trp) != - le32_to_cpu(rp->system_page_size)) { - err = errno; - ntfs_log_error("Failed to read whole restart page into the " - "buffer.\n"); - if (err != ENOMEM) - err = EIO; - goto err_out; - } - /* - * Perform the multi sector transfer deprotection on the buffer if the - * restart page is protected. - */ - if ((!ntfs_is_chkd_record(trp->magic) || le16_to_cpu(trp->usa_count)) - && ntfs_mst_post_read_fixup((NTFS_RECORD*)trp, - le32_to_cpu(rp->system_page_size))) { - /* - * A multi sector tranfer error was detected. We only need to - * abort if the restart page contents exceed the multi sector - * transfer fixup of the first sector. - */ - if (le16_to_cpu(rp->restart_area_offset) + - le16_to_cpu(ra->restart_area_length) > - NTFS_BLOCK_SIZE - (int)sizeof(u16)) { - ntfs_log_error("Multi sector transfer error " - "detected in $LogFile restart page.\n"); - err = EINVAL; - goto err_out; - } - } - /* - * If the restart page is modified by chkdsk or there are no active - * logfile clients, the logfile is consistent. Otherwise, need to - * check the log client records for consistency, too. - */ - err = 0; - if (ntfs_is_rstr_record(rp->magic) && - ra->client_in_use_list != LOGFILE_NO_CLIENT) { - if (!ntfs_check_log_client_array(trp)) { - err = EINVAL; - goto err_out; - } - } - if (lsn) { - if (ntfs_is_rstr_record(rp->magic)) - *lsn = sle64_to_cpu(ra->current_lsn); - else /* if (ntfs_is_chkd_record(rp->magic)) */ - *lsn = sle64_to_cpu(rp->chkdsk_lsn); - } - ntfs_log_trace("Done.\n"); - if (wrp) - *wrp = trp; - else { -err_out: - free(trp); - } - return err; -} - -/** - * ntfs_check_logfile - check in the journal if the volume is consistent - * @log_na: ntfs attribute of loaded journal $LogFile to check - * @rp: [OUT] on success this is a copy of the current restart page - * - * Check the $LogFile journal for consistency and return TRUE if it is - * consistent and FALSE if not. On success, the current restart page is - * returned in *@rp. Caller must call ntfs_free(*@rp) when finished with it. - * - * At present we only check the two restart pages and ignore the log record - * pages. - * - * Note that the MstProtected flag is not set on the $LogFile inode and hence - * when reading pages they are not deprotected. This is because we do not know - * if the $LogFile was created on a system with a different page size to ours - * yet and mst deprotection would fail if our page size is smaller. - */ -BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp) -{ - s64 size, pos; - LSN rstr1_lsn, rstr2_lsn; - ntfs_volume *vol = log_na->ni->vol; - u8 *kaddr = NULL; - RESTART_PAGE_HEADER *rstr1_ph = NULL; - RESTART_PAGE_HEADER *rstr2_ph = NULL; - int log_page_size, log_page_mask, err; - BOOL logfile_is_empty = TRUE; - u8 log_page_bits; - - ntfs_log_trace("Entering.\n"); - /* An empty $LogFile must have been clean before it got emptied. */ - if (NVolLogFileEmpty(vol)) - goto is_empty; - size = log_na->data_size; - /* Make sure the file doesn't exceed the maximum allowed size. */ - if (size > (s64)MaxLogFileSize) - size = MaxLogFileSize; - log_page_size = DefaultLogPageSize; - log_page_mask = log_page_size - 1; - /* - * Use generic_ffs() instead of ffs() to enable the compiler to - * optimize log_page_size and log_page_bits into constants. - */ - log_page_bits = ffs(log_page_size) - 1; - size &= ~(log_page_size - 1); - - /* - * Ensure the log file is big enough to store at least the two restart - * pages and the minimum number of log record pages. - */ - if (size < log_page_size * 2 || (size - log_page_size * 2) >> - log_page_bits < MinLogRecordPages) { - ntfs_log_error("$LogFile is too small.\n"); - return FALSE; - } - /* Allocate memory for restart page. */ - kaddr = ntfs_malloc(NTFS_BLOCK_SIZE); - if (!kaddr) - return FALSE; - /* - * Read through the file looking for a restart page. Since the restart - * page header is at the beginning of a page we only need to search at - * what could be the beginning of a page (for each page size) rather - * than scanning the whole file byte by byte. If all potential places - * contain empty and uninitialized records, the log file can be assumed - * to be empty. - */ - for (pos = 0; pos < size; pos <<= 1) { - /* - * Read first NTFS_BLOCK_SIZE bytes of potential restart page. - */ - if (ntfs_attr_pread(log_na, pos, NTFS_BLOCK_SIZE, kaddr) != - NTFS_BLOCK_SIZE) { - ntfs_log_error("Failed to read first NTFS_BLOCK_SIZE " - "bytes of potential restart page.\n"); - goto err_out; - } - - /* - * A non-empty block means the logfile is not empty while an - * empty block after a non-empty block has been encountered - * means we are done. - */ - if (!ntfs_is_empty_recordp((le32*)kaddr)) - logfile_is_empty = FALSE; - else if (!logfile_is_empty) - break; - /* - * A log record page means there cannot be a restart page after - * this so no need to continue searching. - */ - if (ntfs_is_rcrd_recordp((le32*)kaddr)) - break; - /* If not a (modified by chkdsk) restart page, continue. */ - if (!ntfs_is_rstr_recordp((le32*)kaddr) && - !ntfs_is_chkd_recordp((le32*)kaddr)) { - if (!pos) - pos = NTFS_BLOCK_SIZE >> 1; - continue; - } - /* - * Check the (modified by chkdsk) restart page for consistency - * and get a copy of the complete multi sector transfer - * deprotected restart page. - */ - err = ntfs_check_and_load_restart_page(log_na, - (RESTART_PAGE_HEADER*)kaddr, pos, - !rstr1_ph ? &rstr1_ph : &rstr2_ph, - !rstr1_ph ? &rstr1_lsn : &rstr2_lsn); - if (!err) { - /* - * If we have now found the first (modified by chkdsk) - * restart page, continue looking for the second one. - */ - if (!pos) { - pos = NTFS_BLOCK_SIZE >> 1; - continue; - } - /* - * We have now found the second (modified by chkdsk) - * restart page, so we can stop looking. - */ - break; - } - /* - * Error output already done inside the function. Note, we do - * not abort if the restart page was invalid as we might still - * find a valid one further in the file. - */ - if (err != EINVAL) - goto err_out; - /* Continue looking. */ - if (!pos) - pos = NTFS_BLOCK_SIZE >> 1; - } - if (kaddr) { - free(kaddr); - kaddr = NULL; - } - if (logfile_is_empty) { - NVolSetLogFileEmpty(vol); -is_empty: - ntfs_log_trace("Done. ($LogFile is empty.)\n"); - return TRUE; - } - if (!rstr1_ph) { - if (rstr2_ph) - ntfs_log_error("BUG: rstr2_ph isn't NULL!\n"); - ntfs_log_error("Did not find any restart pages in " - "$LogFile and it was not empty.\n"); - return FALSE; - } - /* If both restart pages were found, use the more recent one. */ - if (rstr2_ph) { - /* - * If the second restart area is more recent, switch to it. - * Otherwise just throw it away. - */ - if (rstr2_lsn > rstr1_lsn) { - ntfs_log_debug("Using second restart page as it is more " - "recent.\n"); - free(rstr1_ph); - rstr1_ph = rstr2_ph; - /* rstr1_lsn = rstr2_lsn; */ - } else { - ntfs_log_debug("Using first restart page as it is more " - "recent.\n"); - free(rstr2_ph); - } - rstr2_ph = NULL; - } - /* All consistency checks passed. */ - if (rp) - *rp = rstr1_ph; - else - free(rstr1_ph); - ntfs_log_trace("Done.\n"); - return TRUE; -err_out: - free(kaddr); - free(rstr1_ph); - free(rstr2_ph); - return FALSE; -} - -/** - * ntfs_is_logfile_clean - check in the journal if the volume is clean - * @log_na: ntfs attribute of loaded journal $LogFile to check - * @rp: copy of the current restart page - * - * Analyze the $LogFile journal and return TRUE if it indicates the volume was - * shutdown cleanly and FALSE if not. - * - * At present we only look at the two restart pages and ignore the log record - * pages. This is a little bit crude in that there will be a very small number - * of cases where we think that a volume is dirty when in fact it is clean. - * This should only affect volumes that have not been shutdown cleanly but did - * not have any pending, non-check-pointed i/o, i.e. they were completely idle - * at least for the five seconds preceding the unclean shutdown. - * - * This function assumes that the $LogFile journal has already been consistency - * checked by a call to ntfs_check_logfile() and in particular if the $LogFile - * is empty this function requires that NVolLogFileEmpty() is true otherwise an - * empty volume will be reported as dirty. - */ -BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp) -{ - RESTART_AREA *ra; - - ntfs_log_trace("Entering.\n"); - /* An empty $LogFile must have been clean before it got emptied. */ - if (NVolLogFileEmpty(log_na->ni->vol)) { - ntfs_log_trace("Done. ($LogFile is empty.)\n"); - return TRUE; - } - if (!rp) { - ntfs_log_error("Restart page header is NULL.\n"); - return FALSE; - } - if (!ntfs_is_rstr_record(rp->magic) && - !ntfs_is_chkd_record(rp->magic)) { - ntfs_log_error("Restart page buffer is invalid. This is " - "probably a bug in that the $LogFile should " - "have been consistency checked before calling " - "this function.\n"); - return FALSE; - } - - ra = (RESTART_AREA*)((u8*)rp + le16_to_cpu(rp->restart_area_offset)); - /* - * If the $LogFile has active clients, i.e. it is open, and we do not - * have the RESTART_VOLUME_IS_CLEAN bit set in the restart area flags, - * we assume there was an unclean shutdown. - */ - if (ra->client_in_use_list != LOGFILE_NO_CLIENT && - !(ra->flags & RESTART_VOLUME_IS_CLEAN)) { - ntfs_log_debug("Done. $LogFile indicates a dirty shutdown.\n"); - return FALSE; - } - /* $LogFile indicates a clean shutdown. */ - ntfs_log_trace("Done. $LogFile indicates a clean shutdown.\n"); - return TRUE; -} - -/** - * ntfs_empty_logfile - empty the contents of the $LogFile journal - * @na: ntfs attribute of journal $LogFile to empty - * - * Empty the contents of the $LogFile journal @na and return 0 on success and - * -1 on error. - * - * This function assumes that the $LogFile journal has already been consistency - * checked by a call to ntfs_check_logfile() and that ntfs_is_logfile_clean() - * has been used to ensure that the $LogFile is clean. - */ -int ntfs_empty_logfile(ntfs_attr *na) -{ - s64 len, pos, count; - char buf[NTFS_BUF_SIZE]; - int err; - - ntfs_log_trace("Entering.\n"); - if (NVolLogFileEmpty(na->ni->vol)) - goto done; - - /* The $DATA attribute of the $LogFile has to be non-resident. */ - if (!NAttrNonResident(na)) { - err = EIO; - ntfs_log_debug("$LogFile $DATA attribute is resident!?!\n"); - goto io_error_exit; - } - - /* Get length of $LogFile contents. */ - len = na->data_size; - if (!len) { - ntfs_log_debug("$LogFile has zero length, no disk write " - "needed.\n"); - return 0; - } - - /* Read $LogFile until its end. We do this as a check for correct - length thus making sure we are decompressing the mapping pairs - array correctly and hence writing below is safe as well. */ - pos = 0; - while ((count = ntfs_attr_pread(na, pos, NTFS_BUF_SIZE, buf)) > 0) - pos += count; - - if (count == -1 || pos != len) { - err = errno; - ntfs_log_debug("Amount of $LogFile data read does not " - "correspond to expected length!\n"); - if (count != -1) - err = EIO; - goto io_error_exit; - } - - /* Fill the buffer with 0xff's. */ - memset(buf, -1, NTFS_BUF_SIZE); - - /* Set the $DATA attribute. */ - pos = 0; - while ((count = len - pos) > 0) { - if (count > NTFS_BUF_SIZE) - count = NTFS_BUF_SIZE; - - if ((count = ntfs_attr_pwrite(na, pos, count, buf)) <= 0) { - err = errno; - ntfs_log_debug("Failed to set the $LogFile attribute " - "value.\n"); - if (count != -1) - err = EIO; - goto io_error_exit; - } - pos += count; - } - - /* Set the flag so we do not have to do it again on remount. */ - NVolSetLogFileEmpty(na->ni->vol); -done: - ntfs_log_trace("Done.\n"); - return 0; -io_error_exit: - errno = err; - return -1; -} diff --git a/usr/src/lib/libntfs/common/libntfs/logging.c b/usr/src/lib/libntfs/common/libntfs/logging.c deleted file mode 100644 index eb447e493f..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/logging.c +++ /dev/null @@ -1,644 +0,0 @@ -/** - * logging.c - Centralised logging. Part of the Linux-NTFS project. - * - * Copyright (c) 2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STDARG_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_SYSLOG_H -#include -#endif - -#include "compat.h" -#include "logging.h" - -#ifndef PATH_SEP -#define PATH_SEP '/' -#endif - -/* Colour prefixes and a suffix */ -#ifdef __sun -static const char *col_green = "\033[32m"; -static const char *col_cyan = "\033[36m"; -static const char *col_yellow = "\033[01;33m"; -static const char *col_red = "\033[01;31m"; -static const char *col_redinv = "\033[01;07;31m"; -static const char *col_end = "\033[0m"; -#else /* ! __sun */ -static const char *col_green = "\e[32m"; -static const char *col_cyan = "\e[36m"; -static const char *col_yellow = "\e[01;33m"; -static const char *col_red = "\e[01;31m"; -static const char *col_redinv = "\e[01;07;31m"; -static const char *col_end = "\e[0m"; -#endif /* __sun */ - -/** - * struct ntfs_logging - Control info for the logging system - * @levels: Bitfield of logging levels - * @flags: Flags which affect the output style - * @handler: Function to perform the actual logging - */ -struct ntfs_logging { - u32 levels; - u32 flags; - ntfs_log_handler *handler; -}; - -/** - * ntfs_log - This struct controls all the logging in the library and tools. - */ -static struct ntfs_logging ntfs_log = { - .levels = NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_QUIET | - NTFS_LOG_LEVEL_WARNING | NTFS_LOG_LEVEL_ERROR | - NTFS_LOG_LEVEL_PERROR | NTFS_LOG_LEVEL_CRITICAL | - NTFS_LOG_LEVEL_PROGRESS | - 0, - .flags = NTFS_LOG_FLAG_ONLYNAME, - .handler = ntfs_log_handler_null, -}; - - -/** - * ntfs_log_get_levels - Get a list of the current logging levels - * - * Find out which logging levels are enabled. - * - * Returns: Log levels in a 32-bit field - */ -u32 ntfs_log_get_levels(void) -{ - return ntfs_log.levels; -} - -/** - * ntfs_log_set_levels - Enable extra logging levels - * @levels: 32-bit field of log levels to set - * - * Enable one or more logging levels. - * The logging levels are named: NTFS_LOG_LEVEL_*. - * - * Returns: Log levels that were enabled before the call - */ -u32 ntfs_log_set_levels(u32 levels) -{ - u32 old; - old = ntfs_log.levels; - ntfs_log.levels |= levels; - return old; -} - -/** - * ntfs_log_clear_levels - Disable some logging levels - * @levels: 32-bit field of log levels to clear - * - * Disable one or more logging levels. - * The logging levels are named: NTFS_LOG_LEVEL_*. - * - * Returns: Log levels that were enabled before the call - */ -u32 ntfs_log_clear_levels(u32 levels) -{ - u32 old; - old = ntfs_log.levels; - ntfs_log.levels &= (~levels); - return old; -} - - -/** - * ntfs_log_get_flags - Get a list of logging style flags - * - * Find out which logging flags are enabled. - * - * Returns: Logging flags in a 32-bit field - */ -u32 ntfs_log_get_flags(void) -{ - return ntfs_log.flags; -} - -/** - * ntfs_log_set_flags - Enable extra logging style flags - * @flags: 32-bit field of logging flags to set - * - * Enable one or more logging flags. - * The log flags are named: NTFS_LOG_LEVEL_*. - * - * Returns: Logging flags that were enabled before the call - */ -u32 ntfs_log_set_flags(u32 flags) -{ - u32 old; - old = ntfs_log.flags; - ntfs_log.flags |= flags; - return old; -} - -/** - * ntfs_log_clear_flags - Disable some logging styles - * @flags: 32-bit field of logging flags to clear - * - * Disable one or more logging flags. - * The log flags are named: NTFS_LOG_LEVEL_*. - * - * Returns: Logging flags that were enabled before the call - */ -u32 ntfs_log_clear_flags(u32 flags) -{ - u32 old; - old = ntfs_log.flags; - ntfs_log.flags &= (~flags); - return old; -} - - -/** - * ntfs_log_get_stream - Default output streams for logging levels - * @level: Log level - * - * By default, urgent messages are sent to "stderr". - * Other messages are sent to "stdout". - * - * Returns: "string" Prefix to be used - */ -static FILE * ntfs_log_get_stream(u32 level) -{ - FILE *stream; - - switch (level) { - case NTFS_LOG_LEVEL_INFO: - case NTFS_LOG_LEVEL_QUIET: - case NTFS_LOG_LEVEL_PROGRESS: - case NTFS_LOG_LEVEL_VERBOSE: - stream = stdout; - break; - - case NTFS_LOG_LEVEL_DEBUG: - case NTFS_LOG_LEVEL_TRACE: - case NTFS_LOG_LEVEL_WARNING: - case NTFS_LOG_LEVEL_ERROR: - case NTFS_LOG_LEVEL_CRITICAL: - case NTFS_LOG_LEVEL_PERROR: - default: - stream = stderr; - break; - } - - return stream; -} - -/** - * ntfs_log_get_prefix - Default prefixes for logging levels - * @level: Log level to be prefixed - * - * Prefixing the logging output can make it easier to parse. - * - * Returns: "string" Prefix to be used - */ -static const char * ntfs_log_get_prefix(u32 level) -{ - const char *prefix; - - switch (level) { - case NTFS_LOG_LEVEL_DEBUG: - prefix = "DEBUG: "; - break; - case NTFS_LOG_LEVEL_TRACE: - prefix = "TRACE: "; - break; - case NTFS_LOG_LEVEL_QUIET: - prefix = "QUIET: "; - break; - case NTFS_LOG_LEVEL_INFO: - prefix = "INFO: "; - break; - case NTFS_LOG_LEVEL_VERBOSE: - prefix = "VERBOSE: "; - break; - case NTFS_LOG_LEVEL_PROGRESS: - prefix = "PROGRESS: "; - break; - case NTFS_LOG_LEVEL_WARNING: - prefix = "WARNING: "; - break; - case NTFS_LOG_LEVEL_ERROR: - prefix = "ERROR: "; - break; - case NTFS_LOG_LEVEL_PERROR: - prefix = "ERROR: "; - break; - case NTFS_LOG_LEVEL_CRITICAL: - prefix = "CRITICAL: "; - break; - default: - prefix = ""; - break; - } - - return prefix; -} - - -/** - * ntfs_log_set_handler - Provide an alternate logging handler - * @handler: function to perform the logging - * - * This alternate handler will be called for all future logging requests. - * If no @handler is specified, logging will revert to the default handler. - */ -void ntfs_log_set_handler(ntfs_log_handler *handler) -{ - if (handler) { - ntfs_log.handler = handler; -#ifdef HAVE_SYSLOG_H - if (handler == ntfs_log_handler_syslog) - openlog("libntfs", LOG_PID, LOG_USER); -#endif - } else - ntfs_log.handler = ntfs_log_handler_null; -} - -/** - * ntfs_log_redirect - Pass on the request to the real handler - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @...: Arguments to be formatted - * - * This is just a redirector function. The arguments are simply passed to the - * main logging handler (as defined in the global logging struct @ntfs_log). - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_redirect(const char *function, const char *file, - int line, u32 level, void *data, const char *format, ...) -{ - int olderr = errno; - int ret; - va_list args; - - if (!(ntfs_log.levels & level)) /* Don't log this message */ - return 0; - - va_start(args, format); - errno = olderr; - ret = ntfs_log.handler(function, file, line, level, data, format, args); - va_end(args); - - errno = olderr; - return ret; -} - - -#ifdef HAVE_SYSLOG_H -/** - * ntfs_log_handler_syslog - syslog logging handler - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * A syslog logging handler. Ignores colors and truncates output after 512 - * bytes. - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_handler_syslog(const char *function, const char *file, int line, - u32 level, void *data __attribute__((unused)), - const char *format, va_list args) -{ - char buffer[512]; - int ret = 0, olderr = errno; - - if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) && - (strchr(file, PATH_SEP))) /* Abbreviate the filename */ - file = strrchr(file, PATH_SEP) + 1; - - /* Prefix the output */ - if (ret < sizeof(buffer) && ntfs_log.flags & NTFS_LOG_FLAG_PREFIX) - ret += snprintf(buffer + ret, sizeof(buffer) - ret, "%s", - ntfs_log_get_prefix(level)); - - /* Source filename */ - if (ret < sizeof(buffer) && ntfs_log.flags & NTFS_LOG_FLAG_FILENAME) - ret += snprintf(buffer + ret, sizeof(buffer) - ret, "%s ", - file); - - /* Source line number */ - if (ret < sizeof(buffer) && ntfs_log.flags & NTFS_LOG_FLAG_LINE) - ret += snprintf(buffer + ret, sizeof(buffer) - ret, "(%d) ", - line); - - /* Source function */ - if (ret < sizeof(buffer) && ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) - || (level & NTFS_LOG_LEVEL_TRACE))) - ret += snprintf(buffer + ret, sizeof(buffer) - ret, "%s(): ", - function); - - /* Message itself */ - if (ret < sizeof(buffer)) - ret += vsnprintf(buffer + ret, sizeof(buffer) - ret, format, - args); - - /* Append errno */ - if (ret < sizeof(buffer) && level & NTFS_LOG_LEVEL_PERROR) - ret += snprintf(buffer + ret, sizeof(buffer) - ret, ": %s.\n", - strerror(olderr)); - - syslog(LOG_NOTICE, "%s", buffer); - - errno = olderr; - return ret; -} -#endif - -/** - * ntfs_log_handler_fprintf - Basic logging handler - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * A simple logging handler. This is where the log line is finally displayed. - * It is more likely that you will want to set the handler to either - * ntfs_log_handler_outerr or ntfs_log_handler_stderr. - * - * Note: For this handler, @data is a pointer to a FILE output stream. - * If @data is NULL, nothing will be displayed. - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_handler_fprintf(const char *function, const char *file, - int line, u32 level, void *data, const char *format, va_list args) -{ - int ret = 0; - int olderr = errno; - FILE *stream; - const char *col_prefix = NULL; - const char *col_suffix = NULL; - - if (!data) /* Interpret data as a FILE stream. */ - return 0; /* If it's NULL, we can't do anything. */ - stream = (FILE*)data; - - if (ntfs_log.flags & NTFS_LOG_FLAG_COLOUR) { - /* Pick a colour determined by the log level */ - switch (level) { - case NTFS_LOG_LEVEL_DEBUG: - col_prefix = col_green; - col_suffix = col_end; - break; - case NTFS_LOG_LEVEL_TRACE: - col_prefix = col_cyan; - col_suffix = col_end; - break; - case NTFS_LOG_LEVEL_WARNING: - col_prefix = col_yellow; - col_suffix = col_end; - break; - case NTFS_LOG_LEVEL_ERROR: - case NTFS_LOG_LEVEL_PERROR: - col_prefix = col_red; - col_suffix = col_end; - break; - case NTFS_LOG_LEVEL_CRITICAL: - col_prefix = col_redinv; - col_suffix = col_end; - break; - } - } - - if (col_prefix) - ret += fprintf(stream, col_prefix); - - if ((ntfs_log.flags & NTFS_LOG_FLAG_ONLYNAME) && - (strchr(file, PATH_SEP))) /* Abbreviate the filename */ - file = strrchr(file, PATH_SEP) + 1; - - if (ntfs_log.flags & NTFS_LOG_FLAG_PREFIX) /* Prefix the output */ - ret += fprintf(stream, "%s", ntfs_log_get_prefix(level)); - - if (ntfs_log.flags & NTFS_LOG_FLAG_FILENAME) /* Source filename */ - ret += fprintf(stream, "%s ", file); - - if (ntfs_log.flags & NTFS_LOG_FLAG_LINE) /* Source line number */ - ret += fprintf(stream, "(%d) ", line); - - if ((ntfs_log.flags & NTFS_LOG_FLAG_FUNCTION) || /* Source function */ - (level & NTFS_LOG_LEVEL_TRACE)) - ret += fprintf(stream, "%s(): ", function); - - ret += vfprintf(stream, format, args); - - if (level & NTFS_LOG_LEVEL_PERROR) - ret += fprintf(stream, ": %s.\n", strerror(olderr)); - - if (col_suffix) - ret += fprintf(stream, col_suffix); - - - fflush(stream); - errno = olderr; - return ret; -} - -/** - * ntfs_log_handler_null - Null logging handler (no output) - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * This handler produces no output. It provides a way to temporarily disable - * logging, without having to change the levels and flags. - * - * Returns: 0 Message wasn't logged - */ -int ntfs_log_handler_null(const char *function __attribute__((unused)), const char *file __attribute__((unused)), - int line __attribute__((unused)), u32 level __attribute__((unused)), void *data __attribute__((unused)), - const char *format __attribute__((unused)), va_list args __attribute__((unused))) -{ - return 0; -} - -/** - * ntfs_log_handler_stdout - All logs go to stdout - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * Display a log message to stdout. - * - * Note: For this handler, @data is a pointer to a FILE output stream. - * If @data is NULL, then stdout will be used. - * - * Note: This function calls ntfs_log_handler_fprintf to do the main work. - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_handler_stdout(const char *function, const char *file, - int line, u32 level, void *data, const char *format, va_list args) -{ - if (!data) - data = stdout; - - return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); -} - -/** - * ntfs_log_handler_outerr - Logs go to stdout/stderr depending on level - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * Display a log message. The output stream will be determined by the log - * level. - * - * Note: For this handler, @data is a pointer to a FILE output stream. - * If @data is NULL, the function ntfs_log_get_stream will be called - * - * Note: This function calls ntfs_log_handler_fprintf to do the main work. - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_handler_outerr(const char *function, const char *file, - int line, u32 level, void *data, const char *format, va_list args) -{ - if (!data) - data = ntfs_log_get_stream(level); - - return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); -} - -/** - * ntfs_log_handler_stderr - All logs go to stderr - * @function: Function in which the log line occurred - * @file: File in which the log line occurred - * @line: Line number on which the log line occurred - * @level: Level at which the line is logged - * @data: User specified data, possibly specific to a handler - * @format: printf-style formatting string - * @args: Arguments to be formatted - * - * Display a log message to stderr. - * - * Note: For this handler, @data is a pointer to a FILE output stream. - * If @data is NULL, then stdout will be used. - * - * Note: This function calls ntfs_log_handler_fprintf to do the main work. - * - * Returns: -1 Error occurred - * 0 Message wasn't logged - * num Number of output characters - */ -int ntfs_log_handler_stderr(const char *function, const char *file, - int line, u32 level, void *data, const char *format, va_list args) -{ - if (!data) - data = stderr; - - return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); -} - - -/** - * ntfs_log_parse_option - Act upon command line options - * @option: Option flag - * - * Delegate some of the work of parsing the command line. All the options begin - * with "--log-". Options cause log levels to be enabled in @ntfs_log (the - * global logging structure). - * - * Note: The "colour" option changes the logging handler. - * - * Returns: TRUE Option understood - * FALSE Invalid log option - */ -BOOL ntfs_log_parse_option(const char *option) -{ - if (strcmp(option, "--log-debug") == 0) { - ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG); - return TRUE; - } else if (strcmp(option, "--log-verbose") == 0) { - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - return TRUE; - } else if (strcmp(option, "--log-quiet") == 0) { - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - return TRUE; - } else if (strcmp(option, "--log-trace") == 0) { - ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE); - return TRUE; - } else if ((strcmp(option, "--log-colour") == 0) || - (strcmp(option, "--log-color") == 0)) { - ntfs_log_set_flags(NTFS_LOG_FLAG_COLOUR); - return TRUE; - } - - ntfs_log_debug("Unknown logging option '%s'\n", option); - return FALSE; -} - diff --git a/usr/src/lib/libntfs/common/libntfs/mft.c b/usr/src/lib/libntfs/common/libntfs/mft.c deleted file mode 100644 index 49034707ba..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/mft.c +++ /dev/null @@ -1,1583 +0,0 @@ -/** - * mft.c - Mft record handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * Copyright (c) 2004-2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#include - -#include "compat.h" -#include "types.h" -#include "device.h" -#include "debug.h" -#include "bitmap.h" -#include "attrib.h" -#include "inode.h" -#include "volume.h" -#include "layout.h" -#include "lcnalloc.h" -#include "mft.h" -#include "logging.h" - -/** - * ntfs_mft_records_read - read records from the mft from disk - * @vol: volume to read from - * @mref: starting mft record number to read - * @count: number of mft records to read - * @b: output data buffer - * - * Read @count mft records starting at @mref from volume @vol into buffer - * @b. Return 0 on success or -1 on error, with errno set to the error - * code. - * - * If any of the records exceed the initialized size of the $MFT/$DATA - * attribute, i.e. they cannot possibly be allocated mft records, assume this - * is a bug and return error code ESPIPE. - * - * The read mft records are mst deprotected and are hence ready to use. The - * caller should check each record with is_baad_record() in case mst - * deprotection failed. - * - * NOTE: @b has to be at least of size @count * vol->mft_record_size. - */ -int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref, - const s64 count, MFT_RECORD *b) -{ - s64 br; - VCN m; - - ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); - if (!vol || !vol->mft_na || !b || count < 0) { - errno = EINVAL; - return -1; - } - m = MREF(mref); - /* Refuse to read non-allocated mft records. */ - if (m + count > vol->mft_na->initialized_size >> - vol->mft_record_size_bits) { - errno = ESPIPE; - return -1; - } - br = ntfs_attr_mst_pread(vol->mft_na, m << vol->mft_record_size_bits, - count, vol->mft_record_size, b); - if (br != count) { - if (br != -1) - errno = EIO; - if (br >= 0) - ntfs_log_debug("Error: partition is smaller than it should " - "be!\n"); - else - ntfs_log_perror("Error reading $Mft record(s)"); - return -1; - } - return 0; -} - -/** - * ntfs_mft_records_write - write mft records to disk - * @vol: volume to write to - * @mref: starting mft record number to write - * @count: number of mft records to write - * @b: data buffer containing the mft records to write - * - * Write @count mft records starting at @mref from data buffer @b to volume - * @vol. Return 0 on success or -1 on error, with errno set to the error code. - * - * If any of the records exceed the initialized size of the $MFT/$DATA - * attribute, i.e. they cannot possibly be allocated mft records, assume this - * is a bug and return error code ESPIPE. - * - * Before the mft records are written, they are mst protected. After the write, - * they are deprotected again, thus resulting in an increase in the update - * sequence number inside the data buffer @b. - * - * If any mft records are written which are also represented in the mft mirror - * $MFTMirr, we make a copy of the relevant parts of the data buffer @b into a - * temporary buffer before we do the actual write. Then if at least one mft - * record was successfully written, we write the appropriate mft records from - * the copied buffer to the mft mirror, too. - */ -int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref, - const s64 count, MFT_RECORD *b) -{ - s64 bw; - VCN m; - void *bmirr = NULL; - int cnt = 0, res = 0; - - ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); - if (!vol || !vol->mft_na || vol->mftmirr_size <= 0 || !b || count < 0) { - errno = EINVAL; - return -1; - } - m = MREF(mref); - /* Refuse to write non-allocated mft records. */ - if (m + count > vol->mft_na->initialized_size >> - vol->mft_record_size_bits) { - errno = ESPIPE; - return -1; - } - if (m < vol->mftmirr_size) { - if (!vol->mftmirr_na) { - errno = EINVAL; - return -1; - } - cnt = vol->mftmirr_size - m; - if (cnt > count) - cnt = count; - bmirr = ntfs_malloc(cnt * vol->mft_record_size); - if (!bmirr) - return -1; - memcpy(bmirr, b, cnt * vol->mft_record_size); - } - bw = ntfs_attr_mst_pwrite(vol->mft_na, m << vol->mft_record_size_bits, - count, vol->mft_record_size, b); - if (bw != count) { - if (bw != -1) - errno = EIO; - if (bw >= 0) - ntfs_log_error("Partial write while writing $Mft " - "record(s)!\n"); - else - ntfs_log_perror("Error writing $Mft record(s)"); - res = errno; - } - if (bmirr && bw > 0) { - if (bw < cnt) - cnt = bw; - bw = ntfs_attr_mst_pwrite(vol->mftmirr_na, - m << vol->mft_record_size_bits, cnt, - vol->mft_record_size, bmirr); - if (bw != cnt) { - if (bw != -1) - errno = EIO; - ntfs_log_debug("Error: failed to sync $MFTMirr! Run " - "chkdsk.\n"); - res = errno; - } - } - free(bmirr); - if (!res) - return res; - errno = res; - return -1; -} - -/** - * ntfs_file_record_read - read a FILE record from the mft from disk - * @vol: volume to read from - * @mref: mft reference specifying mft record to read - * @mrec: address of pointer in which to return the mft record - * @attr: address of pointer in which to return the first attribute - * - * Read a FILE record from the mft of @vol from the storage medium. @mref - * specifies the mft record to read, including the sequence number, which can - * be 0 if no sequence number checking is to be performed. - * - * The function allocates a buffer large enough to hold the mft record and - * reads the record into the buffer (mst deprotecting it in the process). - * *@mrec is then set to point to the buffer. - * - * If @attr is not NULL, *@attr is set to point to the first attribute in the - * mft record, i.e. *@attr is a pointer into *@mrec. - * - * Return 0 on success, or -1 on error, with errno set to the error code. - * - * The read mft record is checked for having the magic FILE, - * and for having a matching sequence number (if MSEQNO(*@mref) != 0). - * If either of these fails, -1 is returned and errno is set to EIO. If you get - * this, but you still want to read the mft record (e.g. in order to correct - * it), use ntfs_mft_record_read() directly. - * - * Note: Caller has to free *@mrec when finished. - * - * Note: We do not check if the mft record is flagged in use. The caller can - * check if desired. - */ -int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref, - MFT_RECORD **mrec, ATTR_RECORD **attr) -{ - MFT_RECORD *m; - ATTR_RECORD *a; - int err; - - if (!vol || !mrec) { - errno = EINVAL; - return -1; - } - m = *mrec; - if (!m) { - m = (MFT_RECORD*)ntfs_malloc(vol->mft_record_size); - if (!m) - return -1; - } - if (ntfs_mft_record_read(vol, mref, m)) { - err = errno; - goto read_failed; - } - if (!ntfs_is_file_record(m->magic)) - goto file_corrupt; - if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) - goto file_corrupt; - a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset)); - if (p2n(a) < p2n(m) || (char*)a > (char*)m + vol->mft_record_size) - goto file_corrupt; - *mrec = m; - if (attr) - *attr = a; - return 0; -file_corrupt: - ntfs_log_debug("ntfs_file_record_read(): file is corrupt.\n"); - err = EIO; -read_failed: - if (m != *mrec) - free(m); - errno = err; - return -1; -} - -/** - * ntfs_mft_record_layout - layout an mft record into a memory buffer - * @vol: volume to which the mft record will belong - * @mref: mft reference specifying the mft record number - * @mrec: destination buffer of size >= @vol->mft_record_size bytes - * - * Layout an empty, unused mft record with the mft reference @mref into the - * buffer @m. The volume @vol is needed because the mft record structure was - * modified in NTFS 3.1 so we need to know which volume version this mft record - * will be used on. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_mft_record_layout(const ntfs_volume *vol, const MFT_REF mref, - MFT_RECORD *mrec) -{ - ATTR_RECORD *a; - - if (!vol || !mrec) { - errno = EINVAL; - return -1; - } - /* Aligned to 2-byte boundary. */ - if (vol->major_ver < 3 || (vol->major_ver == 3 && !vol->minor_ver)) - mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD_OLD) + 1) & ~1); - else { - /* Abort if mref is > 32 bits. */ - if (MREF(mref) & 0x0000ffff00000000ull) { - ntfs_log_debug("Mft reference exceeds 32 bits!\n"); - errno = ERANGE; - return -1; - } - mrec->usa_ofs = cpu_to_le16((sizeof(MFT_RECORD) + 1) & ~1); - /* - * Set the NTFS 3.1+ specific fields while we know that the - * volume version is 3.1+. - */ - mrec->reserved = cpu_to_le16(0); - mrec->mft_record_number = cpu_to_le32(MREF(mref)); - } - mrec->magic = magic_FILE; - if (vol->mft_record_size >= NTFS_BLOCK_SIZE) - mrec->usa_count = cpu_to_le16(vol->mft_record_size / - NTFS_BLOCK_SIZE + 1); - else { - mrec->usa_count = cpu_to_le16(1); - ntfs_log_error("Sector size is bigger than MFT record size. " - "Setting usa_count to 1. If Windows chkdsk " - "reports this as corruption, please email %s " - "stating that you saw this message and that " - "the file system created was corrupt. " - "Thank you.\n", NTFS_DEV_LIST); - } - /* Set the update sequence number to 1. */ - *(le16*)((u8*)mrec + le16_to_cpu(mrec->usa_ofs)) = cpu_to_le16(1); - mrec->lsn = 0; - mrec->sequence_number = cpu_to_le16(1); - mrec->link_count = cpu_to_le16(0); - /* Aligned to 8-byte boundary. */ - mrec->attrs_offset = cpu_to_le16((le16_to_cpu(mrec->usa_ofs) + - (le16_to_cpu(mrec->usa_count) << 1) + 7) & ~7); - mrec->flags = cpu_to_le16(0); - /* - * Using attrs_offset plus eight bytes (for the termination attribute), - * aligned to 8-byte boundary. - */ - mrec->bytes_in_use = cpu_to_le32((le16_to_cpu(mrec->attrs_offset) + 8 + - 7) & ~7); - mrec->bytes_allocated = cpu_to_le32(vol->mft_record_size); - mrec->base_mft_record = cpu_to_le64((MFT_REF)0); - mrec->next_attr_instance = cpu_to_le16(0); - a = (ATTR_RECORD*)((u8*)mrec + le16_to_cpu(mrec->attrs_offset)); - a->type = AT_END; - a->length = cpu_to_le32(0); - /* Finally, clear the unused part of the mft record. */ - memset((u8*)a + 8, 0, vol->mft_record_size - ((u8*)a + 8 - (u8*)mrec)); - return 0; -} - -/** - * ntfs_mft_record_format - format an mft record on an ntfs volume - * @vol: volume on which to format the mft record - * @mref: mft reference specifying mft record to format - * - * Format the mft record with the mft reference @mref in $MFT/$DATA, i.e. lay - * out an empty, unused mft record in memory and write it to the volume @vol. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref) -{ - MFT_RECORD *m; - int err; - - if (!vol || !vol->mft_na) { - errno = EINVAL; - return -1; - } - m = ntfs_calloc(vol->mft_record_size); - if (!m) - return -1; - if (ntfs_mft_record_layout(vol, mref, m)) { - err = errno; - free(m); - errno = err; - return -1; - } - if (ntfs_mft_record_write(vol, mref, m)) { - err = errno; - free(m); - errno = err; - return -1; - } - free(m); - return 0; -} - -static const char *es = " Leaving inconsistent metadata. Run chkdsk."; - -/** - * ntfs_ffz - Find the first unset (zero) bit in a word - * @word: - * - * Description... - * - * Returns: - */ -static inline unsigned int ntfs_ffz(unsigned int word) -{ - return ffs(~word) - 1; -} - -#ifndef PAGE_SIZE -#define PAGE_SIZE 4096 -#endif - -/** - * ntfs_mft_bitmap_find_free_rec - find a free mft record in the mft bitmap - * @vol: volume on which to search for a free mft record - * @base_ni: open base inode if allocating an extent mft record or NULL - * - * Search for a free mft record in the mft bitmap attribute on the ntfs volume - * @vol. - * - * If @base_ni is NULL start the search at the default allocator position. - * - * If @base_ni is not NULL start the search at the mft record after the base - * mft record @base_ni. - * - * Return the free mft record on success and -1 on error with errno set to the - * error code. An error code of ENOSPC means that there are no free mft - * records in the currently initialized mft bitmap. - */ -static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni) -{ - s64 pass_end, ll, data_pos, pass_start, ofs, bit; - ntfs_attr *mftbmp_na; - u8 *buf, *byte; - unsigned int size; - u8 pass, b; - - mftbmp_na = vol->mftbmp_na; - /* - * Set the end of the pass making sure we do not overflow the mft - * bitmap. - */ - size = PAGE_SIZE; - pass_end = vol->mft_na->allocated_size >> vol->mft_record_size_bits; - ll = mftbmp_na->initialized_size << 3; - if (pass_end > ll) - pass_end = ll; - pass = 1; - if (!base_ni) - data_pos = vol->mft_data_pos; - else - data_pos = base_ni->mft_no + 1; - if (data_pos < 24) - data_pos = 24; - if (data_pos >= pass_end) { - data_pos = 24; - pass = 2; - /* This happens on a freshly formatted volume. */ - if (data_pos >= pass_end) { - errno = ENOSPC; - return -1; - } - } - pass_start = data_pos; - buf = (u8*)ntfs_malloc(PAGE_SIZE); - if (!buf) - return -1; - - ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, " - "pass_end 0x%llx, data_pos 0x%llx.\n", pass, - (long long)pass_start, (long long)pass_end, - (long long)data_pos); -#ifdef DEBUG - byte = NULL; - b = 0; -#endif - /* Loop until a free mft record is found. */ - for (; pass <= 2; size = PAGE_SIZE) { - /* Cap size to pass_end. */ - ofs = data_pos >> 3; - ll = ((pass_end + 7) >> 3) - ofs; - if (size > ll) - size = ll; - ll = ntfs_attr_pread(mftbmp_na, ofs, size, buf); - if (ll < 0) { - ntfs_log_error("Failed to read mft bitmap " - "attribute, aborting.\n"); - free(buf); - return -1; - } - ntfs_log_debug("Read 0x%llx bytes.\n", (long long)ll); - /* If we read at least one byte, search @buf for a zero bit. */ - if (ll) { - size = ll << 3; - bit = data_pos & 7; - data_pos &= ~7ull; - ntfs_log_debug("Before inner for loop: size 0x%x, " - "data_pos 0x%llx, bit 0x%llx, " - "*byte 0x%hhx, b %u.\n", size, - (long long)data_pos, (long long)bit, - byte ? *byte : -1, b); - for (; bit < size && data_pos + bit < pass_end; - bit &= ~7ull, bit += 8) { - byte = buf + (bit >> 3); - if (*byte == 0xff) - continue; - /* Note: ffz() result must be zero based. */ - b = ntfs_ffz((unsigned long)*byte); - if (b < 8 && b >= (bit & 7)) { - free(buf); - return data_pos + (bit & ~7ull) + b; - } - } - ntfs_log_debug("After inner for loop: size 0x%x, " - "data_pos 0x%llx, bit 0x%llx, " - "*byte 0x%hhx, b %u.\n", size, - (long long)data_pos, (long long)bit, - byte ? *byte : -1, b); - data_pos += size; - /* - * If the end of the pass has not been reached yet, - * continue searching the mft bitmap for a zero bit. - */ - if (data_pos < pass_end) - continue; - } - /* Do the next pass. */ - pass++; - if (pass == 2) { - /* - * Starting the second pass, in which we scan the first - * part of the zone which we omitted earlier. - */ - pass_end = pass_start; - data_pos = pass_start = 24; - ntfs_log_debug("pass %i, pass_start 0x%llx, pass_end " - "0x%llx.\n", pass, (long long)pass_start, - (long long)pass_end); - if (data_pos >= pass_end) - break; - } - } - /* No free mft records in currently initialized mft bitmap. */ - free(buf); - errno = ENOSPC; - return -1; -} - -/** - * ntfs_mft_bitmap_extend_allocation - extend mft bitmap attribute by a cluster - * @vol: volume on which to extend the mft bitmap attribute - * - * Extend the mft bitmap attribute on the ntfs volume @vol by one cluster. - * - * Note: Only changes allocated_size, i.e. does not touch initialized_size or - * data_size. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol) -{ - LCN lcn; - s64 ll = 0; /* silence compiler warning */ - ntfs_attr *mftbmp_na, *lcnbmp_na; - runlist_element *rl, *rl2 = NULL; /* silence compiler warning */ - ntfs_attr_search_ctx *ctx; - MFT_RECORD *m = NULL; /* silence compiler warning */ - ATTR_RECORD *a = NULL; /* silence compiler warning */ - int ret, mp_size; - u32 old_alen = 0; /* silence compiler warning */ - u8 b, tb; - struct { - u8 added_cluster:1; - u8 added_run:1; - u8 mp_rebuilt:1; - } status = { 0, 0, 0 }; - - mftbmp_na = vol->mftbmp_na; - lcnbmp_na = vol->lcnbmp_na; - /* - * Determine the last lcn of the mft bitmap. The allocated size of the - * mft bitmap cannot be zero so we are ok to do this. - */ - rl = ntfs_attr_find_vcn(mftbmp_na, (mftbmp_na->allocated_size - 1) >> - vol->cluster_size_bits); - if (!rl || !rl->length || rl->lcn < 0) { - ntfs_log_error("Failed to determine last allocated " - "cluster of mft bitmap attribute.\n"); - if (rl) - errno = EIO; - return -1; - } - lcn = rl->lcn + rl->length; - /* - * Attempt to get the cluster following the last allocated cluster by - * hand as it may be in the MFT zone so the allocator would not give it - * to us. - */ - ret = (int)ntfs_attr_pread(lcnbmp_na, lcn >> 3, 1, &b); - if (ret < 0) { - ntfs_log_error("Failed to read from lcn bitmap.\n"); - return -1; - } - ntfs_log_debug("Read %i byte%s.\n", ret, ret == 1 ? "" : "s"); - tb = 1 << (lcn & 7ull); - if (ret == 1 && b != 0xff && !(b & tb)) { - /* Next cluster is free, allocate it. */ - b |= tb; - ret = (int)ntfs_attr_pwrite(lcnbmp_na, lcn >> 3, 1, &b); - if (ret < 1) { - ntfs_log_error("Failed to write to lcn " - "bitmap.\n"); - if (!ret) - errno = EIO; - return -1; - } - vol->nr_free_clusters--; - /* Update the mft bitmap runlist. */ - rl->length++; - rl[1].vcn++; - status.added_cluster = 1; - ntfs_log_debug("Appending one cluster to mft bitmap.\n"); - } else { - /* Allocate a cluster from the DATA_ZONE. */ - rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE); - if (!rl2) { - ntfs_log_error("Failed to allocate a cluster for " - "the mft bitmap.\n"); - return -1; - } - rl = ntfs_runlists_merge(mftbmp_na->rl, rl2); - if (!rl) { - ret = errno; - ntfs_log_error("Failed to merge runlists for mft " - "bitmap.\n"); - if (ntfs_cluster_free_from_rl(vol, rl2)) - ntfs_log_error("Failed to deallocate " - "cluster.%s\n", es); - free(rl2); - errno = ret; - return -1; - } - mftbmp_na->rl = rl; - status.added_run = 1; - ntfs_log_debug("Adding one run to mft bitmap.\n"); - /* Find the last run in the new runlist. */ - for (; rl[1].length; rl++) - ; - } - /* - * Update the attribute record as well. Note: @rl is the last - * (non-terminator) runlist element of mft bitmap. - */ - ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); - if (!ctx) { - ntfs_log_error("Failed to get search context.\n"); - goto undo_alloc; - } - if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, - mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) { - ntfs_log_error("Failed to find last attribute extent of " - "mft bitmap attribute.\n"); - goto undo_alloc; - } - m = ctx->mrec; - a = ctx->attr; - ll = sle64_to_cpu(a->u.nonres.lowest_vcn); - rl2 = ntfs_attr_find_vcn(mftbmp_na, ll); - if (!rl2 || !rl2->length) { - ntfs_log_error("Failed to determine previous last " - "allocated cluster of mft bitmap attribute.\n"); - if (rl2) - errno = EIO; - goto undo_alloc; - } - /* Get the size for the new mapping pairs array for this extent. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); - if (mp_size <= 0) { - ntfs_log_error("Get size for mapping pairs failed for " - "mft bitmap attribute extent.\n"); - goto undo_alloc; - } - /* Expand the attribute record if necessary. */ - old_alen = le32_to_cpu(a->length); - if (ntfs_attr_record_resize(m, a, mp_size + - le16_to_cpu(a->u.nonres.mapping_pairs_offset))) { - if (errno != ENOSPC) { - ntfs_log_error("Failed to resize attribute " - "record for mft bitmap attribute.\n"); - goto undo_alloc; - } - // TODO: Deal with this by moving this extent to a new mft - // record or by starting a new extent in a new mft record. - ntfs_log_error("Not enough space in this mft record to " - "accommodate extended mft bitmap attribute " - "extent. Cannot handle this yet.\n"); - errno = EOPNOTSUPP; - goto undo_alloc; - } - status.mp_rebuilt = 1; - /* Generate the mapping pairs array directly into the attr record. */ - if (ntfs_mapping_pairs_build(vol, (u8*)a + - le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp_size, rl2, ll, - NULL)) { - ntfs_log_error("Failed to build mapping pairs array for " - "mft bitmap attribute.\n"); - errno = EIO; - goto undo_alloc; - } - /* Update the highest_vcn. */ - a->u.nonres.highest_vcn = cpu_to_sle64(rl[1].vcn - 1); - /* - * We now have extended the mft bitmap allocated_size by one cluster. - * Reflect this in the ntfs_attr structure and the attribute record. - */ - if (a->u.nonres.lowest_vcn) { - /* - * We are not in the first attribute extent, switch to it, but - * first ensure the changes will make it to disk later. - */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, - mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("Failed to find first attribute " - "extent of mft bitmap attribute.\n"); - goto restore_undo_alloc; - } - a = ctx->attr; - } - mftbmp_na->allocated_size += vol->cluster_size; - a->u.nonres.allocated_size = cpu_to_sle64(mftbmp_na->allocated_size); - /* Ensure the changes make it to disk. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - return 0; -restore_undo_alloc: - ret = errno; - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, - mftbmp_na->name_len, 0, rl[1].vcn, NULL, 0, ctx)) { - ntfs_log_error("Failed to find last attribute extent of " - "mft bitmap attribute.%s\n", es); - ntfs_attr_put_search_ctx(ctx); - mftbmp_na->allocated_size += vol->cluster_size; - /* - * The only thing that is now wrong is ->allocated_size of the - * base attribute extent which chkdsk should be able to fix. - */ - errno = ret; - return -1; - } - m = ctx->mrec; - a = ctx->attr; - a->u.nonres.highest_vcn = cpu_to_sle64(rl[1].vcn - 2); - errno = ret; -undo_alloc: - ret = errno; - if (status.added_cluster) { - /* Truncate the last run in the runlist by one cluster. */ - rl->length--; - rl[1].vcn--; - } else if (status.added_run) { - lcn = rl->lcn; - /* Remove the last run from the runlist. */ - rl->lcn = rl[1].lcn; - rl->length = 0; - } - /* Deallocate the cluster. */ - if (ntfs_bitmap_clear_bit(lcnbmp_na, lcn)) - ntfs_log_error("Failed to free cluster.%s\n", es); - if (status.mp_rebuilt) { - if (ntfs_mapping_pairs_build(vol, (u8*)a + - le16_to_cpu(a->u.nonres.mapping_pairs_offset), - old_alen - le16_to_cpu(a->u.nonres.mapping_pairs_offset), - rl2, ll, NULL)) - ntfs_log_error("Failed to restore mapping " - "pairs array.%s\n", es); - if (ntfs_attr_record_resize(m, a, old_alen)) - ntfs_log_error("Failed to restore attribute " - "record.%s\n", es); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - } - if (ctx) - ntfs_attr_put_search_ctx(ctx); - errno = ret; - return -1; -} - -/** - * ntfs_mft_bitmap_extend_initialized - extend mft bitmap initialized data - * @vol: volume on which to extend the mft bitmap attribute - * - * Extend the initialized portion of the mft bitmap attribute on the ntfs - * volume @vol by 8 bytes. - * - * Note: Only changes initialized_size and data_size, i.e. requires that - * allocated_size is big enough to fit the new initialized_size. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol) -{ - s64 old_data_size, old_initialized_size, ll; - ntfs_attr *mftbmp_na; - ntfs_attr_search_ctx *ctx; - ATTR_RECORD *a; - int err; - - mftbmp_na = vol->mftbmp_na; - ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); - if (!ctx) { - ntfs_log_error("Failed to get search context.\n"); - return -1; - } - if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, - mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("Failed to find first attribute extent of " - "mft bitmap attribute.\n"); - err = errno; - goto put_err_out; - } - a = ctx->attr; - old_data_size = mftbmp_na->data_size; - old_initialized_size = mftbmp_na->initialized_size; - mftbmp_na->initialized_size += 8; - a->u.nonres.initialized_size = cpu_to_sle64(mftbmp_na->initialized_size); - if (mftbmp_na->initialized_size > mftbmp_na->data_size) { - mftbmp_na->data_size = mftbmp_na->initialized_size; - a->u.nonres.data_size = cpu_to_sle64(mftbmp_na->data_size); - } - /* Ensure the changes make it to disk. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - /* Initialize the mft bitmap attribute value with zeroes. */ - ll = 0; - ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll); - if (ll == 8) { - ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n"); - return 0; - } - vol->nr_free_mft_records += 64; /* 8 bytes x 8 bits each. */ - ntfs_log_error("Failed to write to mft bitmap.\n"); - err = errno; - if (ll >= 0) - err = EIO; - /* Try to recover from the error. */ - ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); - if (!ctx) { - ntfs_log_error("Failed to get search context.%s\n", es); - goto err_out; - } - if (ntfs_attr_lookup(mftbmp_na->type, mftbmp_na->name, - mftbmp_na->name_len, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("Failed to find first attribute extent of " - "mft bitmap attribute.%s\n", es); -put_err_out: - ntfs_attr_put_search_ctx(ctx); - goto err_out; - } - a = ctx->attr; - mftbmp_na->initialized_size = old_initialized_size; - a->u.nonres.initialized_size = cpu_to_sle64(old_initialized_size); - if (mftbmp_na->data_size != old_data_size) { - mftbmp_na->data_size = old_data_size; - a->u.nonres.data_size = cpu_to_sle64(old_data_size); - } - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - ntfs_log_debug("Restored status of mftbmp: allocated_size 0x%llx, " - "data_size 0x%llx, initialized_size 0x%llx.\n", - (long long)mftbmp_na->allocated_size, - (long long)mftbmp_na->data_size, - (long long)mftbmp_na->initialized_size); -err_out: - errno = err; - return -1; -} - -/** - * ntfs_mft_data_extend_allocation - extend mft data attribute - * @vol: volume on which to extend the mft data attribute - * - * Extend the mft data attribute on the ntfs volume @vol by 16 mft records - * worth of clusters or if not enough space for this by one mft record worth - * of clusters. - * - * Note: Only changes allocated_size, i.e. does not touch initialized_size or - * data_size. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) -{ - LCN lcn; - VCN old_last_vcn; - s64 min_nr, nr, ll = 0; /* silence compiler warning */ - ntfs_attr *mft_na; - runlist_element *rl, *rl2; - ntfs_attr_search_ctx *ctx; - MFT_RECORD *m = NULL; /* silence compiler warning */ - ATTR_RECORD *a = NULL; /* silence compiler warning */ - int err, mp_size; - u32 old_alen = 0; /* silence compiler warning */ - BOOL mp_rebuilt = FALSE; - - ntfs_log_debug("Extending mft data allocation.\n"); - mft_na = vol->mft_na; - /* - * Determine the preferred allocation location, i.e. the last lcn of - * the mft data attribute. The allocated size of the mft data - * attribute cannot be zero so we are ok to do this. - */ - rl = ntfs_attr_find_vcn(mft_na, - (mft_na->allocated_size - 1) >> vol->cluster_size_bits); - if (!rl || !rl->length || rl->lcn < 0) { - ntfs_log_error("Failed to determine last allocated " - "cluster of mft data attribute.\n"); - if (rl) - errno = EIO; - return -1; - } - lcn = rl->lcn + rl->length; - ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn); - /* Minimum allocation is one mft record worth of clusters. */ - min_nr = vol->mft_record_size >> vol->cluster_size_bits; - if (!min_nr) - min_nr = 1; - /* Want to allocate 16 mft records worth of clusters. */ - nr = vol->mft_record_size << 4 >> vol->cluster_size_bits; - if (!nr) - nr = min_nr; - ntfs_log_debug("Trying mft data allocation with default cluster count " - "%lli.\n", (long long)nr); - old_last_vcn = rl[1].vcn; - do { - rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE); - if (rl2) - break; - if (errno != ENOSPC || nr == min_nr) { - ntfs_log_error("Failed to allocate the minimal " - "number of clusters (%lli) for the " - "mft data attribute.\n", (long long)nr); - return -1; - } - /* - * There is not enough space to do the allocation, but there - * might be enough space to do a minimal allocation so try that - * before failing. - */ - nr = min_nr; - ntfs_log_debug("Retrying mft data allocation with minimal cluster " - "count %lli.\n", (long long)nr); - } while (1); - rl = ntfs_runlists_merge(mft_na->rl, rl2); - if (!rl) { - err = errno; - ntfs_log_error("Failed to merge runlists for mft data " - "attribute.\n"); - if (ntfs_cluster_free_from_rl(vol, rl2)) - ntfs_log_error("Failed to deallocate clusters " - "from the mft data attribute.%s\n", es); - free(rl2); - errno = err; - return -1; - } - mft_na->rl = rl; - ntfs_log_debug("Allocated %lli clusters.\n", nr); - /* Find the last run in the new runlist. */ - for (; rl[1].length; rl++) - ; - /* Update the attribute record as well. */ - ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); - if (!ctx) { - ntfs_log_error("Failed to get search context.\n"); - goto undo_alloc; - } - if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, - rl[1].vcn, NULL, 0, ctx)) { - ntfs_log_error("Failed to find last attribute extent of " - "mft data attribute.\n"); - goto undo_alloc; - } - m = ctx->mrec; - a = ctx->attr; - ll = sle64_to_cpu(a->u.nonres.lowest_vcn); - rl2 = ntfs_attr_find_vcn(mft_na, ll); - if (!rl2 || !rl2->length) { - ntfs_log_error("Failed to determine previous last " - "allocated cluster of mft data attribute.\n"); - if (rl2) - errno = EIO; - goto undo_alloc; - } - /* Get the size for the new mapping pairs array for this extent. */ - mp_size = ntfs_get_size_for_mapping_pairs(vol, rl2, ll); - if (mp_size <= 0) { - ntfs_log_error("Get size for mapping pairs failed for " - "mft data attribute extent.\n"); - goto undo_alloc; - } - /* Expand the attribute record if necessary. */ - old_alen = le32_to_cpu(a->length); - if (ntfs_attr_record_resize(m, a, - mp_size + le16_to_cpu(a->u.nonres.mapping_pairs_offset))) { - if (errno != ENOSPC) { - ntfs_log_error("Failed to resize attribute " - "record for mft data attribute.\n"); - goto undo_alloc; - } - // TODO: Deal with this by moving this extent to a new mft - // record or by starting a new extent in a new mft record. - // Note: Use the special reserved mft records and ensure that - // this extent is not required to find the mft record in - // question. - ntfs_log_error("Not enough space in this mft record to " - "accommodate extended mft data attribute " - "extent. Cannot handle this yet.\n"); - errno = EOPNOTSUPP; - goto undo_alloc; - } - mp_rebuilt = TRUE; - /* - * Generate the mapping pairs array directly into the attribute record. - */ - if (ntfs_mapping_pairs_build(vol, - (u8*)a + le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp_size, - rl2, ll, NULL)) { - ntfs_log_error("Failed to build mapping pairs array of " - "mft data attribute.\n"); - errno = EIO; - goto undo_alloc; - } - /* Update the highest_vcn. */ - a->u.nonres.highest_vcn = cpu_to_sle64(rl[1].vcn - 1); - /* - * We now have extended the mft data allocated_size by nr clusters. - * Reflect this in the ntfs_attr structure and the attribute record. - * @rl is the last (non-terminator) runlist element of mft data - * attribute. - */ - if (a->u.nonres.lowest_vcn) { - /* - * We are not in the first attribute extent, switch to it, but - * first ensure the changes will make it to disk later. - */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mft_na->type, mft_na->name, - mft_na->name_len, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("Failed to find first attribute " - "extent of mft data attribute.\n"); - goto restore_undo_alloc; - } - a = ctx->attr; - } - mft_na->allocated_size += nr << vol->cluster_size_bits; - a->u.nonres.allocated_size = cpu_to_sle64(mft_na->allocated_size); - /* Ensure the changes make it to disk. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - return 0; -restore_undo_alloc: - err = errno; - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, - rl[1].vcn, NULL, 0, ctx)) { - ntfs_log_error("Failed to find last attribute extent of " - "mft data attribute.%s\n", es); - ntfs_attr_put_search_ctx(ctx); - mft_na->allocated_size += nr << vol->cluster_size_bits; - /* - * The only thing that is now wrong is ->allocated_size of the - * base attribute extent which chkdsk should be able to fix. - */ - errno = err; - return -1; - } - m = ctx->mrec; - a = ctx->attr; - a->u.nonres.highest_vcn = cpu_to_sle64(old_last_vcn - 1); - errno = err; -undo_alloc: - err = errno; - if (ntfs_cluster_free(vol, mft_na, old_last_vcn, -1) < 0) - ntfs_log_error("Failed to free clusters from mft data " - "attribute.%s\n", es); - if (ntfs_rl_truncate(&mft_na->rl, old_last_vcn)) - ntfs_log_error("Failed to truncate mft data attribute " - "runlist.%s\n", es); - if (mp_rebuilt) { - if (ntfs_mapping_pairs_build(vol, (u8*)a + - le16_to_cpu(a->u.nonres.mapping_pairs_offset), - old_alen - le16_to_cpu(a->u.nonres.mapping_pairs_offset), - rl2, ll, NULL)) - ntfs_log_error("Failed to restore mapping pairs " - "array.%s\n", es); - if (ntfs_attr_record_resize(m, a, old_alen)) - ntfs_log_error("Failed to restore attribute " - "record.%s\n", es); - ntfs_inode_mark_dirty(ctx->ntfs_ino); - } - if (ctx) - ntfs_attr_put_search_ctx(ctx); - errno = err; - return -1; -} - -/** - * ntfs_mft_record_alloc - allocate an mft record on an ntfs volume - * @vol: volume on which to allocate the mft record - * @base_ni: open base inode if allocating an extent mft record or NULL - * - * Allocate an mft record in $MFT/$DATA of an open ntfs volume @vol. - * - * If @base_ni is NULL make the mft record a base mft record and allocate it at - * the default allocator position. - * - * If @base_ni is not NULL make the allocated mft record an extent record, - * allocate it starting at the mft record after the base mft record and attach - * the allocated and opened ntfs inode to the base inode @base_ni. - * - * On success return the now opened ntfs (extent) inode of the mft record. - * - * On error return NULL with errno set to the error code. - * - * To find a free mft record, we scan the mft bitmap for a zero bit. To - * optimize this we start scanning at the place specified by @base_ni or if - * @base_ni is NULL we start where we last stopped and we perform wrap around - * when we reach the end. Note, we do not try to allocate mft records below - * number 24 because numbers 0 to 15 are the defined system files anyway and 16 - * to 24 are special in that they are used for storing extension mft records - * for the $DATA attribute of $MFT. This is required to avoid the possibility - * of creating a run list with a circular dependence which once written to disk - * can never be read in again. Windows will only use records 16 to 24 for - * normal files if the volume is completely out of space. We never use them - * which means that when the volume is really out of space we cannot create any - * more files while Windows can still create up to 8 small files. We can start - * doing this at some later time, it does not matter much for now. - * - * When scanning the mft bitmap, we only search up to the last allocated mft - * record. If there are no free records left in the range 24 to number of - * allocated mft records, then we extend the $MFT/$DATA attribute in order to - * create free mft records. We extend the allocated size of $MFT/$DATA by 16 - * records at a time or one cluster, if cluster size is above 16kiB. If there - * is not sufficient space to do this, we try to extend by a single mft record - * or one cluster, if cluster size is above the mft record size, but we only do - * this if there is enough free space, which we know from the values returned - * by the failed cluster allocation function when we tried to do the first - * allocation. - * - * No matter how many mft records we allocate, we initialize only the first - * allocated mft record, incrementing mft data size and initialized size - * accordingly, open an ntfs_inode for it and return it to the caller, unless - * there are less than 24 mft records, in which case we allocate and initialize - * mft records until we reach record 24 which we consider as the first free mft - * record for use by normal files. - * - * If during any stage we overflow the initialized data in the mft bitmap, we - * extend the initialized size (and data size) by 8 bytes, allocating another - * cluster if required. The bitmap data size has to be at least equal to the - * number of mft records in the mft, but it can be bigger, in which case the - * superfluous bits are padded with zeroes. - * - * Thus, when we return successfully (return value non-zero), we will have: - * - initialized / extended the mft bitmap if necessary, - * - initialized / extended the mft data if necessary, - * - set the bit corresponding to the mft record being allocated in the - * mft bitmap, - * - open an ntfs_inode for the allocated mft record, and we will - * - return the ntfs_inode. - * - * On error (return value zero), nothing will have changed. If we had changed - * anything before the error occurred, we will have reverted back to the - * starting state before returning to the caller. Thus, except for bugs, we - * should always leave the volume in a consistent state when returning from - * this function. - * - * Note, this function cannot make use of most of the normal functions, like - * for example for attribute resizing, etc, because when the run list overflows - * the base mft record and an attribute list is used, it is very important that - * the extension mft records used to store the $DATA attribute of $MFT can be - * reached without having to read the information contained inside them, as - * this would make it impossible to find them in the first place after the - * volume is dismounted. $MFT/$BITMAP probably does not need to follow this - * rule because the bitmap is not essential for finding the mft records, but on - * the other hand, handling the bitmap in this special way would make life - * easier because otherwise there might be circular invocations of functions - * when reading the bitmap but if we are careful, we should be able to avoid - * all problems. - */ -ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni) -{ - s64 ll, bit, old_data_initialized, old_data_size; - ntfs_attr *mft_na, *mftbmp_na; - ntfs_attr_search_ctx *ctx; - MFT_RECORD *m; - ATTR_RECORD *a; - ntfs_inode *ni; - int err; - le16 seq_no, usn; - - if (base_ni) - ntfs_log_trace("Entering (allocating an extent mft record for " - "base mft record 0x%llx).\n", - (long long)base_ni->mft_no); - else - ntfs_log_trace("Entering (allocating a base mft record).\n"); - if (!vol || !vol->mft_na || !vol->mftbmp_na) { - errno = EINVAL; - return NULL; - } - mft_na = vol->mft_na; - mftbmp_na = vol->mftbmp_na; - bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni); - if (bit >= 0) { - ntfs_log_debug("Found free record (#1), bit 0x%llx.\n", - (long long)bit); - goto found_free_rec; - } - if (errno != ENOSPC) - return NULL; - /* - * No free mft records left. If the mft bitmap already covers more - * than the currently used mft records, the next records are all free, - * so we can simply allocate the first unused mft record. - * Note: We also have to make sure that the mft bitmap at least covers - * the first 24 mft records as they are special and whilst they may not - * be in use, we do not allocate from them. - */ - ll = mft_na->initialized_size >> vol->mft_record_size_bits; - if (mftbmp_na->initialized_size << 3 > ll && - mftbmp_na->initialized_size > 3) { - bit = ll; - if (bit < 24) - bit = 24; - ntfs_log_debug("Found free record (#2), bit 0x%llx.\n", - (long long)bit); - goto found_free_rec; - } - /* - * The mft bitmap needs to be expanded until it covers the first unused - * mft record that we can allocate. - * Note: The smallest mft record we allocate is mft record 24. - */ - ntfs_log_debug("Status of mftbmp before extension: allocated_size 0x%llx, " - "data_size 0x%llx, initialized_size 0x%llx.\n", - (long long)mftbmp_na->allocated_size, - (long long)mftbmp_na->data_size, - (long long)mftbmp_na->initialized_size); - if (mftbmp_na->initialized_size + 8 > mftbmp_na->allocated_size) { - /* Need to extend bitmap by one more cluster. */ - ntfs_log_debug("mftbmp: initialized_size + 8 > allocated_size.\n"); - if (ntfs_mft_bitmap_extend_allocation(vol)) - goto err_out; - ntfs_log_debug("Status of mftbmp after allocation extension: " - "allocated_size 0x%llx, data_size 0x%llx, " - "initialized_size 0x%llx.\n", - (long long)mftbmp_na->allocated_size, - (long long)mftbmp_na->data_size, - (long long)mftbmp_na->initialized_size); - } - /* - * We now have sufficient allocated space, extend the initialized_size - * as well as the data_size if necessary and fill the new space with - * zeroes. - */ - bit = mftbmp_na->initialized_size << 3; - if (ntfs_mft_bitmap_extend_initialized(vol)) - goto err_out; - ntfs_log_debug("Status of mftbmp after initialized extension: " - "allocated_size 0x%llx, data_size 0x%llx, " - "initialized_size 0x%llx.\n", - (long long)mftbmp_na->allocated_size, - (long long)mftbmp_na->data_size, - (long long)mftbmp_na->initialized_size); - ntfs_log_debug("Found free record (#3), bit 0x%llx.\n", (long long)bit); -found_free_rec: - /* @bit is the found free mft record, allocate it in the mft bitmap. */ - ntfs_log_debug("At found_free_rec.\n"); - if (ntfs_bitmap_set_bit(mftbmp_na, bit)) { - ntfs_log_error("Failed to allocate bit in mft bitmap.\n"); - goto err_out; - } - ntfs_log_debug("Set bit 0x%llx in mft bitmap.\n", (long long)bit); - /* The mft bitmap is now uptodate. Deal with mft data attribute now. */ - ll = (bit + 1) << vol->mft_record_size_bits; - if (ll <= mft_na->initialized_size) { - ntfs_log_debug("Allocated mft record already initialized.\n"); - goto mft_rec_already_initialized; - } - ntfs_log_debug("Initializing allocated mft record.\n"); - /* - * The mft record is outside the initialized data. Extend the mft data - * attribute until it covers the allocated record. The loop is only - * actually traversed more than once when a freshly formatted volume is - * first written to so it optimizes away nicely in the common case. - */ - ntfs_log_debug("Status of mft data before extension: " - "allocated_size 0x%llx, data_size 0x%llx, " - "initialized_size 0x%llx.\n", - (long long)mft_na->allocated_size, - (long long)mft_na->data_size, - (long long)mft_na->initialized_size); - while (ll > mft_na->allocated_size) { - if (ntfs_mft_data_extend_allocation(vol)) - goto undo_mftbmp_alloc; - ntfs_log_debug("Status of mft data after allocation extension: " - "allocated_size 0x%llx, data_size 0x%llx, " - "initialized_size 0x%llx.\n", - (long long)mft_na->allocated_size, - (long long)mft_na->data_size, - (long long)mft_na->initialized_size); - } - old_data_initialized = mft_na->initialized_size; - old_data_size = mft_na->data_size; - /* - * Extend mft data initialized size (and data size of course) to reach - * the allocated mft record, formatting the mft records along the way. - * Note: We only modify the ntfs_attr structure as that is all that is - * needed by ntfs_mft_record_format(). We will update the attribute - * record itself in one fell swoop later on. - */ - while (ll > mft_na->initialized_size) { - s64 ll2 = mft_na->initialized_size >> vol->mft_record_size_bits; - mft_na->initialized_size += vol->mft_record_size; - if (mft_na->initialized_size > mft_na->data_size) - mft_na->data_size = mft_na->initialized_size; - ntfs_log_debug("Initializing mft record 0x%llx.\n", (long long)ll2); - err = ntfs_mft_record_format(vol, ll2); - if (err) { - ntfs_log_error("Failed to format mft record.\n"); - goto undo_data_init; - } - } - /* Update the mft data attribute record to reflect the new sizes. */ - ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); - if (!ctx) { - ntfs_log_error("Failed to get search context.\n"); - goto undo_data_init; - } - if (ntfs_attr_lookup(mft_na->type, mft_na->name, mft_na->name_len, 0, - 0, NULL, 0, ctx)) { - ntfs_log_error("Failed to find first attribute extent of " - "mft data attribute.\n"); - ntfs_attr_put_search_ctx(ctx); - goto undo_data_init; - } - a = ctx->attr; - a->u.nonres.initialized_size = cpu_to_sle64(mft_na->initialized_size); - a->u.nonres.data_size = cpu_to_sle64(mft_na->data_size); - /* Ensure the changes make it to disk. */ - ntfs_inode_mark_dirty(ctx->ntfs_ino); - ntfs_attr_put_search_ctx(ctx); - ntfs_log_debug("Status of mft data after mft record initialization: " - "allocated_size 0x%llx, data_size 0x%llx, " - "initialized_size 0x%llx.\n", - (long long)mft_na->allocated_size, - (long long)mft_na->data_size, - (long long)mft_na->initialized_size); - /* Sanity checks. */ - if (mft_na->data_size > mft_na->allocated_size || - mft_na->initialized_size > mft_na->data_size) - NTFS_BUG("mft_na sanity checks failed"); - /* Sync MFT to disk now in order to minimize data-loss. */ - if (ntfs_inode_sync(mft_na->ni)) { - ntfs_log_debug("mft sync after extension failed. rolling back."); - goto undo_data_init; - } -mft_rec_already_initialized: - /* - * We now have allocated and initialized the mft record. Need to read - * it from disk and re-format it, preserving the sequence number if it - * is not zero as well as the update sequence number if it is not zero - * or -1 (0xffff). - */ - m = (MFT_RECORD*)ntfs_malloc(vol->mft_record_size); - if (!m) - goto undo_mftbmp_alloc; - - if (ntfs_mft_record_read(vol, bit, m)) { - err = errno; - ntfs_log_error("Failed to read mft record.\n"); - free(m); - errno = err; - goto undo_mftbmp_alloc; - } - /* Sanity check that the mft record is really not in use. */ - if (ntfs_is_file_record(m->magic) && (m->flags & MFT_RECORD_IN_USE)) { - ntfs_log_error("Mft record 0x%llx was marked unused in " - "mft bitmap but is marked used itself. " - "Corrupt filesystem or library bug! " - "Run chkdsk immediately!\n", (long long)bit); - free(m); - errno = EIO; - goto undo_mftbmp_alloc; - } - seq_no = m->sequence_number; - usn = *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)); - if (ntfs_mft_record_layout(vol, bit, m)) { - err = errno; - ntfs_log_error("Failed to re-format mft record.\n"); - free(m); - errno = err; - goto undo_mftbmp_alloc; - } - if (seq_no) - m->sequence_number = seq_no; - if (usn && le16_to_cpu(usn) != 0xffff) - *(le16*)((u8*)m + le16_to_cpu(m->usa_ofs)) = usn; - /* Set the mft record itself in use. */ - m->flags |= MFT_RECORD_IN_USE; - /* Now need to open an ntfs inode for the mft record. */ - ni = ntfs_inode_allocate(vol); - if (!ni) { - err = errno; - ntfs_log_error("Failed to allocate buffer for inode.\n"); - free(m); - errno = err; - goto undo_mftbmp_alloc; - } - ni->mft_no = bit; - ni->mrec = m; - /* - * If we are allocating an extent mft record, make the opened inode an - * extent inode and attach it to the base inode. Also, set the base - * mft record reference in the extent inode. - */ - if (base_ni) { - ni->nr_extents = -1; - ni->u.base_ni = base_ni; - m->base_mft_record = MK_LE_MREF(base_ni->mft_no, - le16_to_cpu(base_ni->mrec->sequence_number)); - /* - * Attach the extent inode to the base inode, reallocating - * memory if needed. - */ - if (!(base_ni->nr_extents & 3)) { - ntfs_inode **extent_nis; - int i; - - i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); - extent_nis = (ntfs_inode**)ntfs_malloc(i); - if (!extent_nis) { - err = errno; - free(m); - free(ni); - errno = err; - goto undo_mftbmp_alloc; - } - if (base_ni->u.extent_nis) { - memcpy(extent_nis, base_ni->u.extent_nis, - i - 4 * sizeof(ntfs_inode *)); - free(base_ni->u.extent_nis); - } - base_ni->u.extent_nis = extent_nis; - } - base_ni->u.extent_nis[base_ni->nr_extents++] = ni; - } - /* Make sure the allocated inode is written out to disk later. */ - ntfs_inode_mark_dirty(ni); - /* Initialize time, allocated and data size in ntfs_inode struct. */ - ni->data_size = ni->allocated_size = 0; - ni->flags = 0; - ni->creation_time = ni->last_data_change_time = - ni->last_mft_change_time = - ni->last_access_time = time(NULL); - if (!base_ni) { - /* Update the default mft allocation position if it was used. */ - vol->mft_data_pos = bit + 1; - /* Add inode to cache. */ - __ntfs_inode_add_to_cache(ni); - } - /* Return the opened, allocated inode of the allocated mft record. */ - ntfs_log_debug("Returning opened, allocated %sinode 0x%llx.\n", - base_ni ? "extent " : "", (long long)bit); - return ni; -undo_data_init: - mft_na->initialized_size = old_data_initialized; - mft_na->data_size = old_data_size; -undo_mftbmp_alloc: - err = errno; - if (ntfs_bitmap_clear_bit(mftbmp_na, bit)) - ntfs_log_error("Failed to clear bit in mft bitmap.%s\n", es); - errno = err; -err_out: - if (!errno) - errno = EIO; - return NULL; -} - -/** - * ntfs_mft_record_free - free an mft record on an ntfs volume - * @vol: volume on which to free the mft record - * @ni: open ntfs inode of the mft record to free - * - * Free the mft record of the open inode @ni on the mounted ntfs volume @vol. - * Note that this function calls ntfs_inode_close() internally and hence you - * cannot use the pointer @ni any more after this function returns success. - * - * On success return 0 and on error return -1 with errno set to the error code. - */ -int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni) -{ - u64 mft_no; - int err; - u16 seq_no; - le16 old_seq_no; - - ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); - - if (!vol || !vol->mftbmp_na || !ni) { - errno = EINVAL; - return -1; - } - - /* Cache the mft reference for later. */ - mft_no = ni->mft_no; - - /* Mark the mft record as not in use. */ - ni->mrec->flags &= ~MFT_RECORD_IN_USE; - - /* Increment the sequence number, skipping zero, if it is not zero. */ - old_seq_no = ni->mrec->sequence_number; - seq_no = le16_to_cpu(old_seq_no); - if (seq_no == 0xffff) - seq_no = 1; - else if (seq_no) - seq_no++; - ni->mrec->sequence_number = cpu_to_le16(seq_no); - - /* Set the inode dirty and write it out. */ - ntfs_inode_mark_dirty(ni); - if (ntfs_inode_sync(ni)) { - err = errno; - goto sync_rollback; - } - - /* Clear the bit in the $MFT/$BITMAP corresponding to this record. */ - if (ntfs_bitmap_clear_bit(vol->mftbmp_na, mft_no)) { - err = errno; - // FIXME: If ntfs_bitmap_clear_run() guarantees rollback on - // error, this could be changed to goto sync_rollback; - goto bitmap_rollback; - } - - /* Throw away the now freed inode. */ - if (!ntfs_inode_close(ni)) - return 0; - err = errno; - - /* Rollback what we did... */ -bitmap_rollback: - if (ntfs_bitmap_set_bit(vol->mftbmp_na, mft_no)) - ntfs_log_debug("Eeek! Rollback failed in ntfs_mft_record_free(). " - "Leaving inconsistent metadata!\n"); -sync_rollback: - ni->mrec->flags |= MFT_RECORD_IN_USE; - ni->mrec->sequence_number = old_seq_no; - ntfs_inode_mark_dirty(ni); - errno = err; - return -1; -} - -/** - * ntfs_mft_usn_dec - Decrement USN by one - * @mrec: pointer to an mft record - * - * On success return 0 and on error return -1 with errno set. - */ -int ntfs_mft_usn_dec(MFT_RECORD *mrec) -{ - u16 usn; - le16 *usnp; - - if (!mrec) { - errno = EINVAL; - return -1; - } - usnp = (le16 *)((char *)mrec + le16_to_cpu(mrec->usa_ofs)); - usn = le16_to_cpup(usnp); - if (usn-- <= 1) - usn = 0xfffe; - *usnp = cpu_to_le16(usn); - - return 0; -} - diff --git a/usr/src/lib/libntfs/common/libntfs/misc.c b/usr/src/lib/libntfs/common/libntfs/misc.c deleted file mode 100644 index 26a51c13c9..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/misc.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * misc.c - Miscellaneous functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2006 Szabolcs Szakacsits - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif - -#include "compat.h" -#include "support.h" -#include "logging.h" - -/** - * ntfs_calloc - A logging supported calloc(3) - * - * Return a pointer to the allocated memory or NULL if the request fails. - * Memory is initialized with zeros. - */ -void *ntfs_calloc(size_t size) -{ - void *p; - - p = calloc(1, size); - if (!p) - ntfs_log_perror("Failed to calloc %lld bytes", (long long)size); - return p; -} - -/** - * ntfs_malloc - A logging supported malloc(3) - * - * Return a pointer to the allocated memory or NULL if the request fails. - * Memory is uninitialized. - */ -void *ntfs_malloc(size_t size) -{ - void *p; - - p = malloc(size); - if (!p) - ntfs_log_perror("Failed to malloc %lld bytes", (long long)size); - return p; -} diff --git a/usr/src/lib/libntfs/common/libntfs/mst.c b/usr/src/lib/libntfs/common/libntfs/mst.c deleted file mode 100644 index 2b48e992c0..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/mst.c +++ /dev/null @@ -1,216 +0,0 @@ -/** - * mst.c - Multi sector fixup handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2004 Anton Altaparmakov - * Copyright (c) 2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "mst.h" - -/** - * ntfs_mst_post_read_fixup - deprotect multi sector transfer protected data - * @b: pointer to the data to deprotect - * @size: size in bytes of @b - * - * Perform the necessary post read multi sector transfer fixups and detect the - * presence of incomplete multi sector transfers. - In that case, overwrite the - * magic of the ntfs record header being processed with "BAAD" (in memory only!) - * and abort processing. - * - * Return 0 on success and -1 on error, with errno set to the error code. The - * following error codes are defined: - * EINVAL Invalid arguments or invalid NTFS record in buffer @b. - * EIO Multi sector transfer error was detected. Magic of the NTFS - * record in @b will have been set to "BAAD". - */ -int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size) -{ - u16 usa_ofs, usa_count, usn; - u16 *usa_pos, *data_pos; - - /* Setup the variables. */ - usa_ofs = le16_to_cpu(b->usa_ofs); - /* Decrement usa_count to get number of fixups. */ - usa_count = le16_to_cpu(b->usa_count) - 1; - /* Size and alignment checks. */ - if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 || - (u32)(usa_ofs + (usa_count * 2)) > size || - (size >> NTFS_BLOCK_SIZE_BITS) != usa_count) { - errno = EINVAL; - return -1; - } - /* Position of usn in update sequence array. */ - usa_pos = (u16*)b + usa_ofs/sizeof(u16); - /* - * The update sequence number which has to be equal to each of the - * u16 values before they are fixed up. Note no need to care for - * endianness since we are comparing and moving data for on disk - * structures which means the data is consistent. - If it is - * consistency the wrong endianness it doesn't make any difference. - */ - usn = *usa_pos; - /* - * Position in protected data of first u16 that needs fixing up. - */ - data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; - /* - * Check for incomplete multi sector transfer(s). - */ - while (usa_count--) { - if (*data_pos != usn) { - /* - * Incomplete multi sector transfer detected! )-: - * Set the magic to "BAAD" and return failure. - * Note that magic_BAAD is already converted to le32. - */ - b->magic = magic_BAAD; - errno = EIO; - return -1; - } - data_pos += NTFS_BLOCK_SIZE/sizeof(u16); - } - /* Re-setup the variables. */ - usa_count = le16_to_cpu(b->usa_count) - 1; - data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; - /* Fixup all sectors. */ - while (usa_count--) { - /* - * Increment position in usa and restore original data from - * the usa into the data buffer. - */ - *data_pos = *(++usa_pos); - /* Increment position in data as well. */ - data_pos += NTFS_BLOCK_SIZE/sizeof(u16); - } - return 0; -} - -/** - * ntfs_mst_pre_write_fixup - apply multi sector transfer protection - * @b: pointer to the data to protect - * @size: size in bytes of @b - * - * Perform the necessary pre write multi sector transfer fixup on the data - * pointer to by @b of @size. - * - * Return 0 if fixups applied successfully or -1 if no fixups were performed - * due to errors. In that case errno i set to the error code (EINVAL). - * - * NOTE: We consider the absence / invalidity of an update sequence array to - * mean error. This means that you have to create a valid update sequence - * array header in the ntfs record before calling this function, otherwise it - * will fail (the header needs to contain the position of the update sequence - * array together with the number of elements in the array). You also need to - * initialise the update sequence number before calling this function - * otherwise a random word will be used (whatever was in the record at that - * position at that time). - */ -int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size) -{ - u16 usa_ofs, usa_count, usn; - le16 *usa_pos, *data_pos, usnle; - - /* Sanity check + only fixup if it makes sense. */ - if (!b || ntfs_is_baad_record(b->magic) || - ntfs_is_hole_record(b->magic)) { - errno = EINVAL; - return -1; - } - /* Setup the variables. */ - usa_ofs = le16_to_cpu(b->usa_ofs); - /* Decrement usa_count to get number of fixups. */ - usa_count = le16_to_cpu(b->usa_count) - 1; - /* Size and alignment checks. */ - if (size & (NTFS_BLOCK_SIZE - 1) || usa_ofs & 1 || - (u32)(usa_ofs + (usa_count * 2)) > size || - (size >> NTFS_BLOCK_SIZE_BITS) != usa_count) { - errno = EINVAL; - return -1; - } - /* Position of usn in update sequence array. */ - usa_pos = (le16*)((u8*)b + usa_ofs); - /* - * Cyclically increment the update sequence number - * (skipping 0 and -1, i.e. 0xffff). - */ - usn = le16_to_cpup(usa_pos) + 1; - if (usn == 0xffff || !usn) - usn = 1; - usnle = cpu_to_le16(usn); - *usa_pos = usnle; - /* Position in data of first u16 that needs fixing up. */ - data_pos = (le16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; - /* Fixup all sectors. */ - while (usa_count--) { - /* - * Increment the position in the usa and save the - * original data from the data buffer into the usa. - */ - *(++usa_pos) = *data_pos; - /* Apply fixup to data. */ - *data_pos = usnle; - /* Increment position in data as well. */ - data_pos += NTFS_BLOCK_SIZE/sizeof(u16); - } - return 0; -} - -/** - * ntfs_mst_post_write_fixup - deprotect multi sector transfer protected data - * @b: pointer to the data to deprotect - * - * Perform the necessary post write multi sector transfer fixup, not checking - * for any errors, because we assume we have just used - * ntfs_mst_pre_write_fixup(), thus the data will be fine or we would never - * have gotten here. - */ -void ntfs_mst_post_write_fixup(NTFS_RECORD *b) -{ - u16 *usa_pos, *data_pos; - - u16 usa_ofs = le16_to_cpu(b->usa_ofs); - u16 usa_count = le16_to_cpu(b->usa_count) - 1; - - /* Position of usn in update sequence array. */ - usa_pos = (u16*)b + usa_ofs/sizeof(u16); - - /* Position in protected data of first u16 that needs fixing up. */ - data_pos = (u16*)b + NTFS_BLOCK_SIZE/sizeof(u16) - 1; - - /* Fixup all sectors. */ - while (usa_count--) { - /* - * Increment position in usa and restore original data from - * the usa into the data buffer. - */ - *data_pos = *(++usa_pos); - - /* Increment position in data as well. */ - data_pos += NTFS_BLOCK_SIZE/sizeof(u16); - } -} - diff --git a/usr/src/lib/libntfs/common/libntfs/runlist.c b/usr/src/lib/libntfs/common/libntfs/runlist.c deleted file mode 100644 index d70b643a88..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/runlist.c +++ /dev/null @@ -1,2154 +0,0 @@ -/** - * runlist.c - Run list handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2002-2005 Anton Altaparmakov - * Copyright (c) 2002-2005 Richard Russon - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2004-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "volume.h" -#include "layout.h" -#include "debug.h" -#include "device.h" -#include "logging.h" - -/** - * ntfs_rl_mm - runlist memmove - * @base: - * @dst: - * @src: - * @size: - * - * Description... - * - * Returns: - */ -static __inline__ void ntfs_rl_mm(runlist_element *base, int dst, int src, - int size) -{ - if ((dst != src) && (size > 0)) - memmove(base + dst, base + src, size * sizeof(*base)); -} - -/** - * ntfs_rl_mc - runlist memory copy - * @dstbase: - * @dst: - * @srcbase: - * @src: - * @size: - * - * Description... - * - * Returns: - */ -static __inline__ void ntfs_rl_mc(runlist_element *dstbase, int dst, - runlist_element *srcbase, int src, int size) -{ - if (size > 0) - memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase)); -} - -/** - * ntfs_rl_realloc - Reallocate memory for runlists - * @rl: original runlist - * @old_size: number of runlist elements in the original runlist @rl - * @new_size: number of runlist elements we need space for - * - * As the runlists grow, more memory will be required. To prevent large - * numbers of small reallocations of memory, this function returns a 4kiB block - * of memory. - * - * N.B. If the new allocation doesn't require a different number of 4kiB - * blocks in memory, the function will return the original pointer. - * - * On success, return a pointer to the newly allocated, or recycled, memory. - * On error, return NULL with errno set to the error code. - */ -static runlist_element *ntfs_rl_realloc(runlist_element *rl, - int old_size, int new_size) -{ - old_size = (old_size * sizeof(runlist_element) + 0xfff) & ~0xfff; - new_size = (new_size * sizeof(runlist_element) + 0xfff) & ~0xfff; - if (old_size == new_size) - return rl; - return realloc(rl, new_size); -} - -/** - * ntfs_rl_are_mergeable - test if two runlists can be joined together - * @dst: original runlist - * @src: new runlist to test for mergeability with @dst - * - * Test if two runlists can be joined together. For this, their VCNs and LCNs - * must be adjacent. - * - * Return: TRUE Success, the runlists can be merged. - * FALSE Failure, the runlists cannot be merged. - */ -static BOOL ntfs_rl_are_mergeable(runlist_element *dst, - runlist_element *src) -{ - if (!dst || !src) { - ntfs_log_debug("Eeek. ntfs_rl_are_mergeable() invoked with NULL " - "pointer!\n"); - return FALSE; - } - - /* We can merge unmapped regions even if they are misaligned. */ - if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED)) - return TRUE; - /* If the runs are misaligned, we cannot merge them. */ - if ((dst->vcn + dst->length) != src->vcn) - return FALSE; - /* If both runs are non-sparse and contiguous, we can merge them. */ - if ((dst->lcn >= 0) && (src->lcn >= 0) && - ((dst->lcn + dst->length) == src->lcn)) - return TRUE; - /* If we are merging two holes, we can merge them. */ - if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE)) - return TRUE; - /* Cannot merge. */ - return FALSE; -} - -/** - * __ntfs_rl_merge - merge two runlists without testing if they can be merged - * @dst: original, destination runlist - * @src: new runlist to merge with @dst - * - * Merge the two runlists, writing into the destination runlist @dst. The - * caller must make sure the runlists can be merged or this will corrupt the - * destination runlist. - */ -static __inline__ void __ntfs_rl_merge(runlist_element *dst, - runlist_element *src) -{ - dst->length += src->length; -} - -/** - * ntfs_rl_append - append a runlist after a given element - * @dst: original runlist to be worked on - * @dsize: number of elements in @dst (including end marker) - * @src: runlist to be inserted into @dst - * @ssize: number of elements in @src (excluding end marker) - * @loc: append the new runlist @src after this element in @dst - * - * Append the runlist @src after element @loc in @dst. Merge the right end of - * the new runlist, if necessary. Adjust the size of the hole before the - * appended runlist. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @dst and @src are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. - */ -static runlist_element *ntfs_rl_append(runlist_element *dst, - int dsize, runlist_element *src, int ssize, int loc) -{ - BOOL right = FALSE; /* Right end of @src needs merging */ - int marker; /* End of the inserted runs */ - - if (!dst || !src) { - ntfs_log_debug("Eeek. ntfs_rl_append() invoked with NULL " - "pointer!\n"); - errno = EINVAL; - return NULL; - } - - /* First, check if the right hand end needs merging. */ - if ((loc + 1) < dsize) - right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); - - /* Space required: @dst size + @src size, less one if we merged. */ - dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right); - if (!dst) - return NULL; - /* - * We are guaranteed to succeed from here so can start modifying the - * original runlists. - */ - - /* First, merge the right hand end, if necessary. */ - if (right) - __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); - - /* marker - First run after the @src runs that have been inserted */ - marker = loc + ssize + 1; - - /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - loc - 1 - right); - ntfs_rl_mc(dst, loc + 1, src, 0, ssize); - - /* Adjust the size of the preceding hole. */ - dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; - - /* We may have changed the length of the file, so fix the end marker */ - if (dst[marker].lcn == LCN_ENOENT) - dst[marker].vcn = dst[marker-1].vcn + dst[marker-1].length; - - return dst; -} - -/** - * ntfs_rl_insert - insert a runlist into another - * @dst: original runlist to be worked on - * @dsize: number of elements in @dst (including end marker) - * @src: new runlist to be inserted - * @ssize: number of elements in @src (excluding end marker) - * @loc: insert the new runlist @src before this element in @dst - * - * Insert the runlist @src before element @loc in the runlist @dst. Merge the - * left end of the new runlist, if necessary. Adjust the size of the hole - * after the inserted runlist. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @dst and @src are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. - */ -static runlist_element *ntfs_rl_insert(runlist_element *dst, - int dsize, runlist_element *src, int ssize, int loc) -{ - BOOL left = FALSE; /* Left end of @src needs merging */ - BOOL disc = FALSE; /* Discontinuity between @dst and @src */ - int marker; /* End of the inserted runs */ - - if (!dst || !src) { - ntfs_log_debug("Eeek. ntfs_rl_insert() invoked with NULL " - "pointer!\n"); - errno = EINVAL; - return NULL; - } - - /* disc => Discontinuity between the end of @dst and the start of @src. - * This means we might need to insert a "notmapped" run. - */ - if (loc == 0) - disc = (src[0].vcn > 0); - else { - s64 merged_length; - - left = ntfs_rl_are_mergeable(dst + loc - 1, src); - - merged_length = dst[loc - 1].length; - if (left) - merged_length += src->length; - - disc = (src[0].vcn > dst[loc - 1].vcn + merged_length); - } - - /* Space required: @dst size + @src size, less one if we merged, plus - * one if there was a discontinuity. - */ - dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc); - if (!dst) - return NULL; - /* - * We are guaranteed to succeed from here so can start modifying the - * original runlist. - */ - - if (left) - __ntfs_rl_merge(dst + loc - 1, src); - - /* - * marker - First run after the @src runs that have been inserted - * Nominally: marker = @loc + @ssize (location + number of runs in @src) - * If "left", then the first run in @src has been merged with one in @dst. - * If "disc", then @dst and @src don't meet and we need an extra run to fill the gap. - */ - marker = loc + ssize - left + disc; - - /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, marker, loc, dsize - loc); - ntfs_rl_mc(dst, loc + disc, src, left, ssize - left); - - /* Adjust the VCN of the first run after the insertion ... */ - dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; - /* ... and the length. */ - if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED) - dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn; - - /* Writing beyond the end of the file and there's a discontinuity. */ - if (disc) { - if (loc > 0) { - dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length; - dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn; - } else { - dst[loc].vcn = 0; - dst[loc].length = dst[loc + 1].vcn; - } - dst[loc].lcn = LCN_RL_NOT_MAPPED; - } - return dst; -} - -/** - * ntfs_rl_replace - overwrite a runlist element with another runlist - * @dst: original runlist to be worked on - * @dsize: number of elements in @dst (including end marker) - * @src: new runlist to be inserted - * @ssize: number of elements in @src (excluding end marker) - * @loc: index in runlist @dst to overwrite with @src - * - * Replace the runlist element @dst at @loc with @src. Merge the left and - * right ends of the inserted runlist, if necessary. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @dst and @src are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. - */ -static runlist_element *ntfs_rl_replace(runlist_element *dst, - int dsize, runlist_element *src, int ssize, int loc) -{ - signed delta; - BOOL left = FALSE; /* Left end of @src needs merging */ - BOOL right = FALSE; /* Right end of @src needs merging */ - int tail; /* Start of tail of @dst */ - int marker; /* End of the inserted runs */ - - if (!dst || !src) { - ntfs_log_debug("Eeek. ntfs_rl_replace() invoked with NULL " - "pointer!\n"); - errno = EINVAL; - return NULL; - } - - /* First, see if the left and right ends need merging. */ - if ((loc + 1) < dsize) - right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1); - if (loc > 0) - left = ntfs_rl_are_mergeable(dst + loc - 1, src); - - /* Allocate some space. We'll need less if the left, right, or both - * ends get merged. The -1 accounts for the run being replaced. - */ - delta = ssize - 1 - left - right; - if (delta > 0) { - dst = ntfs_rl_realloc(dst, dsize, dsize + delta); - if (!dst) - return NULL; - } - /* - * We are guaranteed to succeed from here so can start modifying the - * original runlists. - */ - - /* First, merge the left and right ends, if necessary. */ - if (right) - __ntfs_rl_merge(src + ssize - 1, dst + loc + 1); - if (left) - __ntfs_rl_merge(dst + loc - 1, src); - - /* - * tail - Offset of the tail of @dst - * Nominally: @tail = @loc + 1 (location, skipping the replaced run) - * If "right", then one of @dst's runs is already merged into @src. - */ - tail = loc + right + 1; - - /* - * marker - First run after the @src runs that have been inserted - * Nominally: @marker = @loc + @ssize (location + number of runs in @src) - * If "left", then the first run in @src has been merged with one in @dst. - */ - marker = loc + ssize - left; - - /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, marker, tail, dsize - tail); - ntfs_rl_mc(dst, loc, src, left, ssize - left); - - /* We may have changed the length of the file, so fix the end marker */ - if (((dsize - tail) > 0) && (dst[marker].lcn == LCN_ENOENT)) - dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length; - - return dst; -} - -/** - * ntfs_rl_split - insert a runlist into the centre of a hole - * @dst: original runlist to be worked on - * @dsize: number of elements in @dst (including end marker) - * @src: new runlist to be inserted - * @ssize: number of elements in @src (excluding end marker) - * @loc: index in runlist @dst at which to split and insert @src - * - * Split the runlist @dst at @loc into two and insert @new in between the two - * fragments. No merging of runlists is necessary. Adjust the size of the - * holes either side. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @dst and @src are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. - */ -static runlist_element *ntfs_rl_split(runlist_element *dst, - int dsize, runlist_element *src, int ssize, int loc) -{ - if (!dst || !src) { - ntfs_log_trace("Invoked with NULL pointer!\n"); - errno = EINVAL; - return NULL; - } - - /* Space required: @dst size + @src size + one new hole. */ - dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1); - if (!dst) - return dst; - /* - * We are guaranteed to succeed from here so can start modifying the - * original runlists. - */ - - /* Move the tail of @dst out of the way, then copy in @src. */ - ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc); - ntfs_rl_mc(dst, loc + 1, src, 0, ssize); - - /* Adjust the size of the holes either size of @src. */ - dst[loc].length = dst[loc+1].vcn - dst[loc].vcn; - dst[loc+ssize+1].vcn = dst[loc+ssize].vcn + dst[loc+ssize].length; - dst[loc+ssize+1].length = dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn; - - return dst; -} - - -/** - * ntfs_runlists_merge - merge two runlists into one - * @drl: original runlist to be worked on - * @srl: new runlist to be merged into @drl - * - * First we sanity check the two runlists @srl and @drl to make sure that they - * are sensible and can be merged. The runlist @srl must be either after the - * runlist @drl or completely within a hole (or unmapped region) in @drl. - * - * Merging of runlists is necessary in two cases: - * 1. When attribute lists are used and a further extent is being mapped. - * 2. When new clusters are allocated to fill a hole or extend a file. - * - * There are four possible ways @srl can be merged. It can: - * - be inserted at the beginning of a hole, - * - split the hole in two and be inserted between the two fragments, - * - be appended at the end of a hole, or it can - * - replace the whole hole. - * It can also be appended to the end of the runlist, which is just a variant - * of the insert case. - * - * On success, return a pointer to the new, combined, runlist. Note, both - * runlists @drl and @srl are deallocated before returning so you cannot use - * the pointers for anything any more. (Strictly speaking the returned runlist - * may be the same as @dst but this is irrelevant.) - * - * On error, return NULL, with errno set to the error code. Both runlists are - * left unmodified. The following error codes are defined: - * ENOMEM Not enough memory to allocate runlist array. - * EINVAL Invalid parameters were passed in. - * ERANGE The runlists overlap and cannot be merged. - */ -runlist_element *ntfs_runlists_merge(runlist_element *drl, - runlist_element *srl) -{ - int di, si; /* Current index into @[ds]rl. */ - int sstart; /* First index with lcn > LCN_RL_NOT_MAPPED. */ - int dins; /* Index into @drl at which to insert @srl. */ - int dend, send; /* Last index into @[ds]rl. */ - int dfinal, sfinal; /* The last index into @[ds]rl with - lcn >= LCN_HOLE. */ - int marker = 0; - VCN marker_vcn = 0; - - ntfs_log_debug("dst:\n"); - ntfs_debug_runlist_dump(drl); - ntfs_log_debug("src:\n"); - ntfs_debug_runlist_dump(srl); - - /* Check for silly calling... */ - if (!srl) - return drl; - - /* Check for the case where the first mapping is being done now. */ - if (!drl) { - drl = srl; - /* Complete the source runlist if necessary. */ - if (drl[0].vcn) { - /* Scan to the end of the source runlist. */ - for (dend = 0; drl[dend].length; dend++) - ; - dend++; - drl = ntfs_rl_realloc(drl, dend, dend + 1); - if (!drl) - return drl; - /* Insert start element at the front of the runlist. */ - ntfs_rl_mm(drl, 1, 0, dend); - drl[0].vcn = 0; - drl[0].lcn = LCN_RL_NOT_MAPPED; - drl[0].length = drl[1].vcn; - } - goto finished; - } - - si = di = 0; - - /* Skip any unmapped start element(s) in the source runlist. */ - while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE) - si++; - - /* Can't have an entirely unmapped source runlist. */ - if (!srl[si].length) { - ntfs_log_debug("Eeek! ntfs_runlists_merge() received entirely " - "unmapped source runlist.\n"); - errno = EINVAL; - return NULL; - } - - /* Record the starting points. */ - sstart = si; - - /* - * Skip forward in @drl until we reach the position where @srl needs to - * be inserted. If we reach the end of @drl, @srl just needs to be - * appended to @drl. - */ - for (; drl[di].length; di++) { - if (drl[di].vcn + drl[di].length > srl[sstart].vcn) - break; - } - dins = di; - - /* Sanity check for illegal overlaps. */ - if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) && - (srl[si].lcn >= 0)) { - ntfs_log_debug("Run lists overlap. Cannot merge!\n"); - errno = ERANGE; - return NULL; - } - - /* Scan to the end of both runlists in order to know their sizes. */ - for (send = si; srl[send].length; send++) - ; - for (dend = di; drl[dend].length; dend++) - ; - - if (srl[send].lcn == (LCN)LCN_ENOENT) - marker_vcn = srl[marker = send].vcn; - - /* Scan to the last element with lcn >= LCN_HOLE. */ - for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--) - ; - for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--) - ; - - { - BOOL start; - BOOL finish; - int ds = dend + 1; /* Number of elements in drl & srl */ - int ss = sfinal - sstart + 1; - - start = ((drl[dins].lcn < LCN_RL_NOT_MAPPED) || /* End of file */ - (drl[dins].vcn == srl[sstart].vcn)); /* Start of hole */ - finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) && /* End of file */ - ((drl[dins].vcn + drl[dins].length) <= /* End of hole */ - (srl[send - 1].vcn + srl[send - 1].length))); - - /* Or we'll lose an end marker */ - if (finish && !drl[dins].length) - ss++; - if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn)) - finish = FALSE; - - ntfs_log_debug("dfinal = %i, dend = %i\n", dfinal, dend); - ntfs_log_debug("sstart = %i, sfinal = %i, send = %i\n", sstart, sfinal, send); - ntfs_log_debug("start = %i, finish = %i\n", start, finish); - ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins); - - if (start) { - if (finish) - drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins); - else - drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins); - } else { - if (finish) - drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins); - else - drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins); - } - if (!drl) { - ntfs_log_perror("Merge failed"); - return drl; - } - free(srl); - if (marker) { - ntfs_log_debug("Triggering marker code.\n"); - for (ds = dend; drl[ds].length; ds++) - ; - /* We only need to care if @srl ended after @drl. */ - if (drl[ds].vcn <= marker_vcn) { - int slots = 0; - - if (drl[ds].vcn == marker_vcn) { - ntfs_log_debug("Old marker = %lli, replacing with " - "LCN_ENOENT.\n", - (long long)drl[ds].lcn); - drl[ds].lcn = (LCN)LCN_ENOENT; - goto finished; - } - /* - * We need to create an unmapped runlist element in - * @drl or extend an existing one before adding the - * ENOENT terminator. - */ - if (drl[ds].lcn == (LCN)LCN_ENOENT) { - ds--; - slots = 1; - } - if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) { - /* Add an unmapped runlist element. */ - if (!slots) { - /* FIXME/TODO: We need to have the - * extra memory already! (AIA) - */ - drl = ntfs_rl_realloc(drl, ds, ds + 2); - if (!drl) - goto critical_error; - slots = 2; - } - ds++; - /* Need to set vcn if it isn't set already. */ - if (slots != 1) - drl[ds].vcn = drl[ds - 1].vcn + - drl[ds - 1].length; - drl[ds].lcn = (LCN)LCN_RL_NOT_MAPPED; - /* We now used up a slot. */ - slots--; - } - drl[ds].length = marker_vcn - drl[ds].vcn; - /* Finally add the ENOENT terminator. */ - ds++; - if (!slots) { - /* FIXME/TODO: We need to have the extra - * memory already! (AIA) - */ - drl = ntfs_rl_realloc(drl, ds, ds + 1); - if (!drl) - goto critical_error; - } - drl[ds].vcn = marker_vcn; - drl[ds].lcn = (LCN)LCN_ENOENT; - drl[ds].length = (s64)0; - } - } - } - -finished: - /* The merge was completed successfully. */ - ntfs_log_debug("Merged runlist:\n"); - ntfs_debug_runlist_dump(drl); - return drl; - -critical_error: - /* Critical error! We cannot afford to fail here. */ - ntfs_log_perror("libntfs: Critical error"); - ntfs_log_debug("Forcing segmentation fault!\n"); - marker_vcn = ((runlist*)NULL)->lcn; - return drl; -} - -/** - * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist - * @vol: ntfs volume on which the attribute resides - * @attr: attribute record whose mapping pairs array to decompress - * @old_rl: optional runlist in which to insert @attr's runlist - * - * Decompress the attribute @attr's mapping pairs array into a runlist. On - * success, return the decompressed runlist. - * - * If @old_rl is not NULL, decompressed runlist is inserted into the - * appropriate place in @old_rl and the resultant, combined runlist is - * returned. The original @old_rl is deallocated. - * - * On error, return NULL with errno set to the error code. @old_rl is left - * unmodified in that case. - * - * The following error codes are defined: - * ENOMEM Not enough memory to allocate runlist array. - * EIO Corrupt runlist. - * EINVAL Invalid parameters were passed in. - * ERANGE The two runlists overlap. - * - * FIXME: For now we take the conceptionally simplest approach of creating the - * new runlist disregarding the already existing one and then splicing the - * two into one, if that is possible (we check for overlap and discard the new - * runlist if overlap present before returning NULL, with errno = ERANGE). - */ -runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, - const ATTR_RECORD *attr, runlist_element *old_rl) -{ - VCN vcn; /* Current vcn. */ - LCN lcn; /* Current lcn. */ - s64 deltaxcn; /* Change in [vl]cn. */ - runlist_element *rl; /* The output runlist. */ - const u8 *buf; /* Current position in mapping pairs array. */ - const u8 *attr_end; /* End of attribute. */ - int err, rlsize; /* Size of runlist buffer. */ - u16 rlpos; /* Current runlist position in units of - runlist_elements. */ - u8 b; /* Current byte offset in buf. */ - - ntfs_log_trace("Entering for attr 0x%x.\n", - (unsigned)le32_to_cpu(attr->type)); - /* Make sure attr exists and is non-resident. */ - if (!attr || !attr->non_resident || - sle64_to_cpu(attr->u.nonres.lowest_vcn) < (VCN)0) { - errno = EINVAL; - return NULL; - } - /* Start at vcn = lowest_vcn and lcn 0. */ - vcn = sle64_to_cpu(attr->u.nonres.lowest_vcn); - lcn = 0; - /* Get start of the mapping pairs array. */ - buf = (const u8*)attr + le16_to_cpu(attr->u.nonres.mapping_pairs_offset); - attr_end = (const u8*)attr + le32_to_cpu(attr->length); - if (buf < (const u8*)attr || buf > attr_end) { - ntfs_log_debug("Corrupt attribute.\n"); - errno = EIO; - return NULL; - } - /* Current position in runlist array. */ - rlpos = 0; - /* Allocate first 4kiB block and set current runlist size to 4kiB. */ - rlsize = 0x1000; - rl = ntfs_malloc(rlsize); - if (!rl) - return NULL; - /* Insert unmapped starting element if necessary. */ - if (vcn) { - rl->vcn = (VCN)0; - rl->lcn = (LCN)LCN_RL_NOT_MAPPED; - rl->length = vcn; - rlpos++; - } - while (buf < attr_end && *buf) { - /* - * Allocate more memory if needed, including space for the - * not-mapped and terminator elements. - */ - if ((int)((rlpos + 3) * sizeof(*old_rl)) > rlsize) { - runlist_element *rl2; - - rlsize += 0x1000; - rl2 = realloc(rl, rlsize); - if (!rl2) { - int eo = errno; - free(rl); - errno = eo; - return NULL; - } - rl = rl2; - } - /* Enter the current vcn into the current runlist element. */ - rl[rlpos].vcn = vcn; - /* - * Get the change in vcn, i.e. the run length in clusters. - * Doing it this way ensures that we signextend negative values. - * A negative run length doesn't make any sense, but hey, I - * didn't make up the NTFS specs and Windows NT4 treats the run - * length as a signed value so that's how it is... - */ - b = *buf & 0xf; - if (b) { - if (buf + b > attr_end) - goto io_error; - for (deltaxcn = (s8)buf[b--]; b; b--) - deltaxcn = (deltaxcn << 8) + buf[b]; - } else { /* The length entry is compulsory. */ - ntfs_log_debug("Missing length entry in mapping pairs " - "array.\n"); - deltaxcn = (s64)-1; - } - /* - * Assume a negative length to indicate data corruption and - * hence clean-up and return NULL. - */ - if (deltaxcn < 0) { - ntfs_log_debug("Invalid length in mapping pairs array.\n"); - goto err_out; - } - /* - * Enter the current run length into the current runlist - * element. - */ - rl[rlpos].length = deltaxcn; - /* Increment the current vcn by the current run length. */ - vcn += deltaxcn; - /* - * There might be no lcn change at all, as is the case for - * sparse clusters on NTFS 3.0+, in which case we set the lcn - * to LCN_HOLE. - */ - if (!(*buf & 0xf0)) - rl[rlpos].lcn = (LCN)LCN_HOLE; - else { - /* Get the lcn change which really can be negative. */ - u8 b2 = *buf & 0xf; - b = b2 + ((*buf >> 4) & 0xf); - if (buf + b > attr_end) - goto io_error; - for (deltaxcn = (s8)buf[b--]; b > b2; b--) - deltaxcn = (deltaxcn << 8) + buf[b]; - /* Change the current lcn to it's new value. */ - lcn += deltaxcn; -#ifdef DEBUG - /* - * On NTFS 1.2-, apparently can have lcn == -1 to - * indicate a hole. But we haven't verified ourselves - * whether it is really the lcn or the deltaxcn that is - * -1. So if either is found give us a message so we - * can investigate it further! - */ - if (vol->major_ver < 3) { - if (deltaxcn == (LCN)-1) - ntfs_log_debug("lcn delta == -1\n"); - if (lcn == (LCN)-1) - ntfs_log_debug("lcn == -1\n"); - } -#endif - /* Check lcn is not below -1. */ - if (lcn < (LCN)-1) { - ntfs_log_debug("Invalid LCN < -1 in mapping pairs " - "array.\n"); - goto err_out; - } - /* Enter the current lcn into the runlist element. */ - rl[rlpos].lcn = lcn; - } - /* Get to the next runlist element. */ - rlpos++; - /* Increment the buffer position to the next mapping pair. */ - buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1; - } - if (buf >= attr_end) - goto io_error; - /* - * If there is a highest_vcn specified, it must be equal to the final - * vcn in the runlist - 1, or something has gone badly wrong. - */ - deltaxcn = sle64_to_cpu(attr->u.nonres.highest_vcn); - if (deltaxcn && vcn - 1 != deltaxcn) { -mpa_err: - ntfs_log_debug("Corrupt mapping pairs array in non-resident " - "attribute.\n"); - goto err_out; - } - /* Setup not mapped runlist element if this is the base extent. */ - if (!attr->u.nonres.lowest_vcn) { - VCN max_cluster; - - max_cluster = ((sle64_to_cpu(attr->u.nonres.allocated_size) + - vol->cluster_size - 1) >> - vol->cluster_size_bits) - 1; - /* - * A highest_vcn of zero means this is a single extent - * attribute so simply terminate the runlist with LCN_ENOENT). - */ - if (deltaxcn) { - /* - * If there is a difference between the highest_vcn and - * the highest cluster, the runlist is either corrupt - * or, more likely, there are more extents following - * this one. - */ - if (deltaxcn < max_cluster) { - ntfs_log_debug("More extents to follow; deltaxcn = " - "0x%llx, max_cluster = 0x%llx\n", - (long long)deltaxcn, - (long long)max_cluster); - rl[rlpos].vcn = vcn; - vcn += rl[rlpos].length = max_cluster - deltaxcn; - rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED; - rlpos++; - } else if (deltaxcn > max_cluster) { - ntfs_log_debug("Corrupt attribute. deltaxcn = " - "0x%llx, max_cluster = 0x%llx\n", - (long long)deltaxcn, - (long long)max_cluster); - goto mpa_err; - } - } - rl[rlpos].lcn = (LCN)LCN_ENOENT; - } else /* Not the base extent. There may be more extents to follow. */ - rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED; - - /* Setup terminating runlist element. */ - rl[rlpos].vcn = vcn; - rl[rlpos].length = (s64)0; - /* If no existing runlist was specified, we are done. */ - if (!old_rl) { - ntfs_log_debug("Mapping pairs array successfully decompressed:\n"); - ntfs_debug_runlist_dump(rl); - return rl; - } - /* Now combine the new and old runlists checking for overlaps. */ - old_rl = ntfs_runlists_merge(old_rl, rl); - if (old_rl) - return old_rl; - err = errno; - free(rl); - ntfs_log_debug("Failed to merge runlists.\n"); - errno = err; - return NULL; -io_error: - ntfs_log_debug("Corrupt attribute.\n"); -err_out: - free(rl); - errno = EIO; - return NULL; -} - -/** - * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist - * @rl: runlist to use for conversion - * @vcn: vcn to convert - * - * Convert the virtual cluster number @vcn of an attribute into a logical - * cluster number (lcn) of a device using the runlist @rl to map vcns to their - * corresponding lcns. - * - * Since lcns must be >= 0, we use negative return values with special meaning: - * - * Return value Meaning / Description - * ================================================== - * -1 = LCN_HOLE Hole / not allocated on disk. - * -2 = LCN_RL_NOT_MAPPED This is part of the runlist which has not been - * inserted into the runlist yet. - * -3 = LCN_ENOENT There is no such vcn in the attribute. - * -4 = LCN_EINVAL Input parameter error. - */ -LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) -{ - int i; - - if (vcn < (VCN)0) - return (LCN)LCN_EINVAL; - /* - * If rl is NULL, assume that we have found an unmapped runlist. The - * caller can then attempt to map it and fail appropriately if - * necessary. - */ - if (!rl) - return (LCN)LCN_RL_NOT_MAPPED; - - /* Catch out of lower bounds vcn. */ - if (vcn < rl[0].vcn) - return (LCN)LCN_ENOENT; - - for (i = 0; rl[i].length; i++) { - if (vcn < rl[i+1].vcn) { - if (rl[i].lcn >= (LCN)0) - return rl[i].lcn + (vcn - rl[i].vcn); - return rl[i].lcn; - } - } - /* - * The terminator element is setup to the correct value, i.e. one of - * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT. - */ - if (rl[i].lcn < (LCN)0) - return rl[i].lcn; - /* Just in case... We could replace this with BUG() some day. */ - return (LCN)LCN_ENOENT; -} - -/** - * ntfs_rl_pread - gather read from disk - * @vol: ntfs volume to read from - * @rl: runlist specifying where to read the data from - * @pos: byte position within runlist @rl at which to begin the read - * @count: number of bytes to read - * @b: data buffer into which to read from disk - * - * This function will read @count bytes from the volume @vol to the data buffer - * @b gathering the data as specified by the runlist @rl. The read begins at - * offset @pos into the runlist @rl. - * - * On success, return the number of successfully read bytes. If this number is - * lower than @count this means that the read reached end of file or that an - * error was encountered during the read so that the read is partial. 0 means - * nothing was read (also return 0 when @count is 0). - * - * On error and nothing has been read, return -1 with errno set appropriately - * to the return code of ntfs_pread(), or to EINVAL in case of invalid - * arguments. - * - * NOTE: If we encounter EOF while reading we return EIO because we assume that - * the run list must point to valid locations within the ntfs volume. - */ -s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b) -{ - s64 bytes_read, to_read, ofs, total; - int err = EIO; - - if (!vol || !rl || pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - if (!count) - return count; - /* Seek in @rl to the run containing @pos. */ - for (ofs = 0; rl->length && (ofs + (rl->length << - vol->cluster_size_bits) <= pos); rl++) - ofs += (rl->length << vol->cluster_size_bits); - /* Offset in the run at which to begin reading. */ - ofs = pos - ofs; - for (total = 0LL; count; rl++, ofs = 0) { - if (!rl->length) - goto rl_err_out; - if (rl->lcn < (LCN)0) { - if (rl->lcn != (LCN)LCN_HOLE) - goto rl_err_out; - /* It is a hole. Just fill buffer @b with zeroes. */ - to_read = min(count, (rl->length << - vol->cluster_size_bits) - ofs); - memset(b, 0, to_read); - /* Update counters and proceed with next run. */ - total += to_read; - count -= to_read; - b = (u8*)b + to_read; - continue; - } - /* It is a real lcn, read it from the volume. */ - to_read = min(count, (rl->length << vol->cluster_size_bits) - - ofs); -retry: - bytes_read = ntfs_pread(vol->u.dev, (rl->lcn << - vol->cluster_size_bits) + ofs, to_read, b); - /* If everything ok, update progress counters and continue. */ - if (bytes_read > 0) { - total += bytes_read; - count -= bytes_read; - b = (u8*)b + bytes_read; - continue; - } - /* If the syscall was interrupted, try again. */ - if (bytes_read == (s64)-1 && errno == EINTR) - goto retry; - if (bytes_read == (s64)-1) - err = errno; - goto rl_err_out; - } - /* Finally, return the number of bytes read. */ - return total; -rl_err_out: - if (total) - return total; - errno = err; - return -1; -} - -/** - * ntfs_rl_pwrite - scatter write to disk - * @vol: ntfs volume to write to - * @rl: runlist specifying where to write the data to - * @pos: byte position within runlist @rl at which to begin the write - * @count: number of bytes to write - * @b: data buffer to write to disk - * - * This function will write @count bytes from data buffer @b to the volume @vol - * scattering the data as specified by the runlist @rl. The write begins at - * offset @pos into the runlist @rl. - * - * On success, return the number of successfully written bytes. If this number - * is lower than @count this means that the write has been interrupted in - * flight or that an error was encountered during the write so that the write - * is partial. 0 means nothing was written (also return 0 when @count is 0). - * - * On error and nothing has been written, return -1 with errno set - * appropriately to the return code of ntfs_pwrite(), or to to EINVAL in case - * of invalid arguments. - */ -s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl, - const s64 pos, s64 count, void *b) -{ - s64 written, to_write, ofs, total; - int err = EIO; - - if (!vol || !rl || pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - if (!count) - return count; - /* Seek in @rl to the run containing @pos. */ - for (ofs = 0; rl->length && (ofs + (rl->length << - vol->cluster_size_bits) <= pos); rl++) - ofs += (rl->length << vol->cluster_size_bits); - /* Offset in the run at which to begin writing. */ - ofs = pos - ofs; - for (total = 0LL; count; rl++, ofs = 0) { - if (!rl->length) - goto rl_err_out; - if (rl->lcn < (LCN)0) { - s64 t; - int cnt; - - if (rl->lcn != (LCN)LCN_HOLE) - goto rl_err_out; - /* - * It is a hole. Check if the buffer is zero in this - * region and if not abort with error. - */ - to_write = min(count, (rl->length << - vol->cluster_size_bits) - ofs); - written = to_write / sizeof(unsigned long); - for (t = 0; t < written; t++) { - if (((unsigned long*)b)[t]) - goto rl_err_out; - } - cnt = to_write & (sizeof(unsigned long) - 1); - if (cnt) { - int i; - u8 *b2; - - b2 = (u8*)b + (to_write & - ~(sizeof(unsigned long) - 1)); - for (i = 0; i < cnt; i++) { - if (b2[i]) - goto rl_err_out; - } - } - /* - * The buffer region is zero, update progress counters - * and proceed with next run. - */ - total += to_write; - count -= to_write; - b = (u8*)b + to_write; - continue; - } - /* It is a real lcn, write it to the volume. */ - to_write = min(count, (rl->length << vol->cluster_size_bits) - - ofs); -retry: - if (!NVolReadOnly(vol)) - written = ntfs_pwrite(vol->u.dev, (rl->lcn << - vol->cluster_size_bits) + ofs, - to_write, b); - else - written = to_write; - /* If everything ok, update progress counters and continue. */ - if (written > 0) { - total += written; - count -= written; - b = (u8*)b + written; - continue; - } - /* If the syscall was interrupted, try again. */ - if (written == (s64)-1 && errno == EINTR) - goto retry; - if (written == (s64)-1) - err = errno; - goto rl_err_out; - } - /* Finally, return the number of bytes written. */ - return total; -rl_err_out: - if (total) - return total; - errno = err; - return -1; -} - -/** - * ntfs_rl_fill_zero - fill given region with zeroes - * @vol: ntfs volume to write to - * @rl: runlist specifying where to write zeroes to - * @pos: byte position within runlist @rl at which to begin the zeroing - * @count: number of bytes to fill with zeros - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -int ntfs_rl_fill_zero(const ntfs_volume *vol, const runlist *rl, s64 pos, - const s64 count) -{ - char *buf; - s64 written, size, end = pos + count; - int ret = 0; - - ntfs_log_trace("pos %lld, count %lld\n", (long long)pos, - (long long)count); - - if (!vol || !rl || pos < 0 || count < 0) { - errno = EINVAL; - return -1; - } - - buf = ntfs_calloc(NTFS_BUF_SIZE); - if (!buf) - return -1; - - while (pos < end) { - size = min(end - pos, NTFS_BUF_SIZE); - written = ntfs_rl_pwrite(vol, rl, pos, size, buf); - if (written <= 0) { - ntfs_log_perror("Failed to zero space"); - ret = -1; - break; - } - pos += written; - } - free(buf); - return ret; -} - -/** - * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number - * @n: number for which to get the number of bytes for - * - * Return the number of bytes required to store @n unambiguously as - * a signed number. - * - * This is used in the context of the mapping pairs array to determine how - * many bytes will be needed in the array to store a given logical cluster - * number (lcn) or a specific run length. - * - * Return the number of bytes written. This function cannot fail. - */ -int ntfs_get_nr_significant_bytes(const s64 n) -{ - s64 l = n; - int i; - s8 j; - - i = 0; - do { - l >>= 8; - i++; - } while (l != 0LL && l != -1LL); - j = (n >> 8 * (i - 1)) & 0xff; - /* If the sign bit is wrong, we need an extra byte. */ - if ((n < 0LL && j >= 0) || (n > 0LL && j < 0)) - i++; - return i; -} - -/** - * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array - * @vol: ntfs volume (needed for the ntfs version) - * @rl: runlist for which to determine the size of the mapping pairs - * @start_vcn: vcn at which to start the mapping pairs array - * - * Walk the runlist @rl and calculate the size in bytes of the mapping pairs - * array corresponding to the runlist @rl, starting at vcn @start_vcn. This - * for example allows us to allocate a buffer of the right size when building - * the mapping pairs array. - * - * If @rl is NULL, just return 1 (for the single terminator byte). - * - * Return the calculated size in bytes on success. On error, return -1 with - * errno set to the error code. The following error codes are defined: - * EINVAL - Run list contains unmapped elements. Make sure to only pass - * fully mapped runlists to this function. - * - @start_vcn is invalid. - * EIO - The runlist is corrupt. - */ -int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, - const runlist_element *rl, const VCN start_vcn) -{ - LCN prev_lcn; - int rls; - - if (start_vcn < 0) { - ntfs_log_trace("start_vcn %lld (should be >= 0)\n", - (long long) start_vcn); - errno = EINVAL; - return -1; - } - if (!rl) { - if (start_vcn) { - ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n", - (long long) start_vcn); - errno = EINVAL; - return -1; - } - return 1; - } - /* Skip to runlist element containing @start_vcn. */ - while (rl->length && start_vcn >= rl[1].vcn) - rl++; - if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) { - errno = EINVAL; - return -1; - } - prev_lcn = 0; - /* Always need the terminating zero byte. */ - rls = 1; - /* Do the first partial run if present. */ - if (start_vcn > rl->vcn) { - s64 delta; - - /* We know rl->length != 0 already. */ - if (rl->length < 0 || rl->lcn < LCN_HOLE) - goto err_out; - delta = start_vcn - rl->vcn; - /* Header byte + length. */ - rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta); - /* - * If the logical cluster number (lcn) denotes a hole and we - * are on NTFS 3.0+, we don't store it at all, i.e. we need - * zero space. On earlier NTFS versions we just store the lcn. - * Note: this assumes that on NTFS 1.2-, holes are stored with - * an lcn of -1 and not a delta_lcn of -1 (unless both are -1). - */ - if (rl->lcn >= 0 || vol->major_ver < 3) { - prev_lcn = rl->lcn; - if (rl->lcn >= 0) - prev_lcn += delta; - /* Change in lcn. */ - rls += ntfs_get_nr_significant_bytes(prev_lcn); - } - /* Go to next runlist element. */ - rl++; - } - /* Do the full runs. */ - for (; rl->length; rl++) { - if (rl->length < 0 || rl->lcn < LCN_HOLE) - goto err_out; - /* Header byte + length. */ - rls += 1 + ntfs_get_nr_significant_bytes(rl->length); - /* - * If the logical cluster number (lcn) denotes a hole and we - * are on NTFS 3.0+, we don't store it at all, i.e. we need - * zero space. On earlier NTFS versions we just store the lcn. - * Note: this assumes that on NTFS 1.2-, holes are stored with - * an lcn of -1 and not a delta_lcn of -1 (unless both are -1). - */ - if (rl->lcn >= 0 || vol->major_ver < 3) { - /* Change in lcn. */ - rls += ntfs_get_nr_significant_bytes(rl->lcn - - prev_lcn); - prev_lcn = rl->lcn; - } - } - return rls; -err_out: - if (rl->lcn == LCN_RL_NOT_MAPPED) - errno = EINVAL; - else - errno = EIO; - return -1; -} - -/** - * ntfs_write_significant_bytes - write the significant bytes of a number - * @dst: destination buffer to write to - * @dst_max: pointer to last byte of destination buffer for bounds checking - * @n: number whose significant bytes to write - * - * Store in @dst, the minimum bytes of the number @n which are required to - * identify @n unambiguously as a signed number, taking care not to exceed - * @dest_max, the maximum position within @dst to which we are allowed to - * write. - * - * This is used when building the mapping pairs array of a runlist to compress - * a given logical cluster number (lcn) or a specific run length to the minimum - * size possible. - * - * Return the number of bytes written on success. On error, i.e. the - * destination buffer @dst is too small, return -1 with errno set ENOSPC. - */ -int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, const s64 n) -{ - s64 l = n; - int i; - s8 j; - - i = 0; - do { - if (dst > dst_max) - goto err_out; - *dst++ = l & 0xffLL; - l >>= 8; - i++; - } while (l != 0LL && l != -1LL); - j = (n >> 8 * (i - 1)) & 0xff; - /* If the sign bit is wrong, we need an extra byte. */ - if (n < 0LL && j >= 0) { - if (dst > dst_max) - goto err_out; - i++; - *dst = (u8)-1; - } else if (n > 0LL && j < 0) { - if (dst > dst_max) - goto err_out; - i++; - *dst = 0; - } - return i; -err_out: - errno = ENOSPC; - return -1; -} - -/** - * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist - * @vol: ntfs volume (needed for the ntfs version) - * @dst: destination buffer to which to write the mapping pairs array - * @dst_len: size of destination buffer @dst in bytes - * @rl: runlist for which to build the mapping pairs array - * @start_vcn: vcn at which to start the mapping pairs array - * @stop_vcn: first vcn outside destination buffer on success or ENOSPC error - * - * Create the mapping pairs array from the runlist @rl, starting at vcn - * @start_vcn and save the array in @dst. @dst_len is the size of @dst in - * bytes and it should be at least equal to the value obtained by calling - * ntfs_get_size_for_mapping_pairs(). - * - * If @rl is NULL, just write a single terminator byte to @dst. - * - * On success or ENOSPC error, if @stop_vcn is not NULL, *@stop_vcn is set to - * the first vcn outside the destination buffer. Note that on error @dst has - * been filled with all the mapping pairs that will fit, thus it can be treated - * as partial success, in that a new attribute extent needs to be created or the - * next extent has to be used and the mapping pairs build has to be continued - * with @start_vcn set to *@stop_vcn. - * - * Return 0 on success. On error, return -1 with errno set to the error code. - * The following error codes are defined: - * EINVAL - Run list contains unmapped elements. Make sure to only pass - * fully mapped runlists to this function. - * - @start_vcn is invalid. - * EIO - The runlist is corrupt. - * ENOSPC - The destination buffer is too small. - */ -int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst, - const int dst_len, const runlist_element *rl, - const VCN start_vcn, VCN *const stop_vcn) -{ - LCN prev_lcn; - u8 *dst_max, *dst_next; - s8 len_len, lcn_len; - - if (start_vcn < 0) - goto val_err; - if (!rl) { - if (start_vcn) - goto val_err; - if (stop_vcn) - *stop_vcn = 0; - if (dst_len < 1) { - errno = ENOSPC; - return -1; - } - /* Terminator byte. */ - *dst = 0; - return 0; - } - /* Skip to runlist element containing @start_vcn. */ - while (rl->length && start_vcn >= rl[1].vcn) - rl++; - if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) - goto val_err; - /* - * @dst_max is used for bounds checking in - * ntfs_write_significant_bytes(). - */ - dst_max = dst + dst_len - 1; - prev_lcn = 0; - /* Do the first partial run if present. */ - if (start_vcn > rl->vcn) { - s64 delta; - - /* We know rl->length != 0 already. */ - if (rl->length < 0 || rl->lcn < LCN_HOLE) - goto err_out; - delta = start_vcn - rl->vcn; - /* Write length. */ - len_len = ntfs_write_significant_bytes(dst + 1, dst_max, - rl->length - delta); - if (len_len < 0) - goto size_err; - /* - * If the logical cluster number (lcn) denotes a hole and we - * are on NTFS 3.0+, we don't store it at all, i.e. we need - * zero space. On earlier NTFS versions we just write the lcn - * change. FIXME: Do we need to write the lcn change or just - * the lcn in that case? Not sure as I have never seen this - * case on NT4. - We assume that we just need to write the lcn - * change until someone tells us otherwise... (AIA) - */ - if (rl->lcn >= 0 || vol->major_ver < 3) { - prev_lcn = rl->lcn; - if (rl->lcn >= 0) - prev_lcn += delta; - /* Write change in lcn. */ - lcn_len = ntfs_write_significant_bytes(dst + 1 + - len_len, dst_max, prev_lcn); - if (lcn_len < 0) - goto size_err; - } else - lcn_len = 0; - dst_next = dst + len_len + lcn_len + 1; - if (dst_next > dst_max) - goto size_err; - /* Update header byte. */ - *dst = lcn_len << 4 | len_len; - /* Position at next mapping pairs array element. */ - dst = dst_next; - /* Go to next runlist element. */ - rl++; - } - /* Do the full runs. */ - for (; rl->length; rl++) { - if (rl->length < 0 || rl->lcn < LCN_HOLE) - goto err_out; - /* Write length. */ - len_len = ntfs_write_significant_bytes(dst + 1, dst_max, - rl->length); - if (len_len < 0) - goto size_err; - /* - * If the logical cluster number (lcn) denotes a hole and we - * are on NTFS 3.0+, we don't store it at all, i.e. we need - * zero space. On earlier NTFS versions we just write the lcn - * change. FIXME: Do we need to write the lcn change or just - * the lcn in that case? Not sure as I have never seen this - * case on NT4. - We assume that we just need to write the lcn - * change until someone tells us otherwise... (AIA) - */ - if (rl->lcn >= 0 || vol->major_ver < 3) { - /* Write change in lcn. */ - lcn_len = ntfs_write_significant_bytes(dst + 1 + - len_len, dst_max, rl->lcn - prev_lcn); - if (lcn_len < 0) - goto size_err; - prev_lcn = rl->lcn; - } else - lcn_len = 0; - dst_next = dst + len_len + lcn_len + 1; - if (dst_next > dst_max) - goto size_err; - /* Update header byte. */ - *dst = lcn_len << 4 | len_len; - /* Position at next mapping pairs array element. */ - dst += 1 + len_len + lcn_len; - } - /* Set stop vcn. */ - if (stop_vcn) - *stop_vcn = rl->vcn; - /* Add terminator byte. */ - *dst = 0; - return 0; -size_err: - /* Set stop vcn. */ - if (stop_vcn) - *stop_vcn = rl->vcn; - /* Add terminator byte. */ - *dst = 0; - errno = ENOSPC; - return -1; -val_err: - errno = EINVAL; - return -1; -err_out: - if (rl->lcn == LCN_RL_NOT_MAPPED) - errno = EINVAL; - else - errno = EIO; - return -1; -} - -/** - * ntfs_rl_truncate - truncate a runlist starting at a specified vcn - * @arl: address of runlist to truncate - * @start_vcn: first vcn which should be cut off - * - * Truncate the runlist *@arl starting at vcn @start_vcn as well as the memory - * buffer holding the runlist. - * - * Return 0 on success and -1 on error with errno set to the error code. - * - * NOTE: @arl is the address of the runlist. We need the address so we can - * modify the pointer to the runlist with the new, reallocated memory buffer. - */ -int ntfs_rl_truncate(runlist **arl, const VCN start_vcn) -{ - runlist *rl; - - if (!arl || !*arl) { - errno = EINVAL; - ntfs_log_perror("rl_truncate error: arl: %p *arl: %p", arl, *arl); - return -1; - } - - rl = *arl; - - if (start_vcn < rl->vcn) { - errno = EINVAL; - ntfs_log_perror("Start_vcn lies outside front of runlist"); - return -1; - } - - /* Find the starting vcn in the run list. */ - while (rl->length) { - if (start_vcn < rl[1].vcn) - break; - rl++; - } - - if (!rl->length) { - errno = EIO; - ntfs_log_trace("Truncating already truncated runlist?\n"); - return -1; - } - - /* Truncate the run. */ - rl->length = start_vcn - rl->vcn; - - /* - * If a run was partially truncated, make the following runlist - * element a terminator instead of the truncated runlist - * element itself. - */ - if (rl->length) { - ++rl; - rl->vcn = start_vcn; - rl->length = 0; - } - rl->lcn = (LCN)LCN_ENOENT; - return 0; -} - -/** - * ntfs_rl_sparse - check whether runlist have sparse regions or not. - * @rl: runlist to check - * - * This function just skips not mapped regions assuming they are not sparse, - * so you need to ensure that runlist is fully mapped if you want perform full - * check. - * - * Return 1 if have, 0 if not, -1 on error with errno set to the error code. - */ -int ntfs_rl_sparse(runlist *rl) -{ - runlist *rlc; - - if (!rl) { - ntfs_log_trace("Invalid argument passed.\n"); - errno = EINVAL; - return -1; - } - - for (rlc = rl; rlc->length; rlc++) { - if (rlc->lcn < 0) { - if (rlc->lcn == LCN_RL_NOT_MAPPED) - continue; - if (rlc->lcn != LCN_HOLE) { - ntfs_log_trace("Bad runlist.\n"); - errno = EIO; - return -1; - } - return 1; - } - } - return 0; -} - -/** - * ntfs_rl_get_compressed_size - calculate length of non sparse regions - * @vol: ntfs volume (need for cluster size) - * @rl: runlist to calculate for - * - * Return compressed size or -1 on error with errno set to the error code. - */ -s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl) -{ - runlist *rlc; - s64 ret = 0; - - if (!rl) { - ntfs_log_trace("Invalid argument passed.\n"); - errno = EINVAL; - return -1; - } - - for (rlc = rl; rlc->length; rlc++) { - if (rlc->lcn < 0) { - if (rlc->lcn != LCN_HOLE) { - ntfs_log_trace("Received unmapped runlist.\n"); - errno = EINVAL; - return -1; - } - } else - ret += rlc->length; - } - return ret << vol->cluster_size_bits; -} - - -#ifdef NTFS_TEST -/** - * test_rl_helper - */ -#define MKRL(R,V,L,S) \ - (R)->vcn = V; \ - (R)->lcn = L; \ - (R)->length = S; -/* -} -*/ -/** - * test_rl_dump_runlist - Runlist test: Display the contents of a runlist - * @rl: - * - * Description... - * - * Returns: - */ -static void test_rl_dump_runlist(const runlist_element *rl) -{ - int abbr = 0; /* abbreviate long lists */ - int len = 0; - int i; - const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "XXXX" }; - - if (!rl) { - printf(" Run list not present.\n"); - return; - } - - if (abbr) - for (len = 0; rl[len].length; len++) ; - - printf(" VCN LCN len\n"); - for (i = 0; ; i++, rl++) { - LCN lcn = rl->lcn; - - if ((abbr) && (len > 20)) { - if (i == 4) - printf(" ...\n"); - if ((i > 3) && (i < (len - 3))) - continue; - } - - if (lcn < (LCN)0) { - int ind = -lcn - 1; - - if (ind > -LCN_ENOENT - 1) - ind = 3; - printf("%8lld %8s %8lld\n", - rl->vcn, lcn_str[ind], rl->length); - } else - printf("%8lld %8lld %8lld\n", - rl->vcn, rl->lcn, rl->length); - if (!rl->length) - break; - } - if ((abbr) && (len > 20)) - printf(" (%d entries)\n", len+1); - printf("\n"); -} - -/** - * test_rl_runlists_merge - Runlist test: Merge two runlists - * @drl: - * @srl: - * - * Description... - * - * Returns: - */ -static runlist_element * test_rl_runlists_merge(runlist_element *drl, runlist_element *srl) -{ - runlist_element *res = NULL; - - printf("dst:\n"); - test_rl_dump_runlist(drl); - printf("src:\n"); - test_rl_dump_runlist(srl); - - res = ntfs_runlists_merge(drl, srl); - - printf("res:\n"); - test_rl_dump_runlist(res); - - return res; -} - -/** - * test_rl_read_buffer - Runlist test: Read a file containing a runlist - * @file: - * @buf: - * @bufsize: - * - * Description... - * - * Returns: - */ -static int test_rl_read_buffer(const char *file, u8 *buf, int bufsize) -{ - FILE *fptr; - - fptr = fopen(file, "r"); - if (!fptr) { - printf("open %s\n", file); - return 0; - } - - if (fread(buf, bufsize, 1, fptr) == 99) { - printf("read %s\n", file); - return 0; - } - - fclose(fptr); - return 1; -} - -/** - * test_rl_pure_src - Runlist test: Complicate the simple tests a little - * @contig: - * @multi: - * @vcn: - * @len: - * - * Description... - * - * Returns: - */ -static runlist_element * test_rl_pure_src(BOOL contig, BOOL multi, int vcn, int len) -{ - runlist_element *result; - int fudge; - - if (contig) - fudge = 0; - else - fudge = 999; - - result = ntfs_malloc(4096); - if (!result) - return NULL; - - if (multi) { - MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4) - MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4) - MKRL(result+2, vcn + (2*len/4), fudge + vcn + 1000 + (2*len/4), len / 4) - MKRL(result+3, vcn + (3*len/4), fudge + vcn + 1000 + (3*len/4), len / 4) - MKRL(result+4, vcn + (4*len/4), LCN_RL_NOT_MAPPED, 0) - } else { - MKRL(result+0, vcn, fudge + vcn + 1000, len) - MKRL(result+1, vcn + len, LCN_RL_NOT_MAPPED, 0) - } - return result; -} - -/** - * test_rl_pure_test - Runlist test: Perform tests using simple runlists - * @test: - * @contig: - * @multi: - * @vcn: - * @len: - * @file: - * @size: - * - * Description... - * - * Returns: - */ -static void test_rl_pure_test(int test, BOOL contig, BOOL multi, int vcn, int len, runlist_element *file, int size) -{ - runlist_element *src; - runlist_element *dst; - runlist_element *res; - - src = test_rl_pure_src(contig, multi, vcn, len); - dst = malloc(4096); - - memcpy(dst, file, size); - - printf("Test %2d ----------\n", test); - res = test_rl_runlists_merge(dst, src); - - free(res); -} - -/** - * test_rl_pure - Runlist test: Create tests using simple runlists - * @contig: - * @multi: - * - * Description... - * - * Returns: - */ -static void test_rl_pure(char *contig, char *multi) -{ - /* VCN, LCN, len */ - static runlist_element file1[] = { - { 0, -1, 100 }, /* HOLE */ - { 100, 1100, 100 }, /* DATA */ - { 200, -1, 100 }, /* HOLE */ - { 300, 1300, 100 }, /* DATA */ - { 400, -1, 100 }, /* HOLE */ - { 500, -3, 0 } /* NOENT */ - }; - static runlist_element file2[] = { - { 0, 1000, 100 }, /* DATA */ - { 100, -1, 100 }, /* HOLE */ - { 200, -3, 0 } /* NOENT */ - }; - static runlist_element file3[] = { - { 0, 1000, 100 }, /* DATA */ - { 100, -3, 0 } /* NOENT */ - }; - static runlist_element file4[] = { - { 0, -3, 0 } /* NOENT */ - }; - static runlist_element file5[] = { - { 0, -2, 100 }, /* NOTMAP */ - { 100, 1100, 100 }, /* DATA */ - { 200, -2, 100 }, /* NOTMAP */ - { 300, 1300, 100 }, /* DATA */ - { 400, -2, 100 }, /* NOTMAP */ - { 500, -3, 0 } /* NOENT */ - }; - static runlist_element file6[] = { - { 0, 1000, 100 }, /* DATA */ - { 100, -2, 100 }, /* NOTMAP */ - { 200, -3, 0 } /* NOENT */ - }; - BOOL c, m; - - if (strcmp(contig, "contig") == 0) - c = TRUE; - else if (strcmp(contig, "noncontig") == 0) - c = FALSE; - else { - printf("rl pure [contig|noncontig] [single|multi]\n"); - return; - } - if (strcmp(multi, "multi") == 0) - m = TRUE; - else if (strcmp(multi, "single") == 0) - m = FALSE; - else { - printf("rl pure [contig|noncontig] [single|multi]\n"); - return; - } - - test_rl_pure_test(1, c, m, 0, 40, file1, sizeof(file1)); - test_rl_pure_test(2, c, m, 40, 40, file1, sizeof(file1)); - test_rl_pure_test(3, c, m, 60, 40, file1, sizeof(file1)); - test_rl_pure_test(4, c, m, 0, 100, file1, sizeof(file1)); - test_rl_pure_test(5, c, m, 200, 40, file1, sizeof(file1)); - test_rl_pure_test(6, c, m, 240, 40, file1, sizeof(file1)); - test_rl_pure_test(7, c, m, 260, 40, file1, sizeof(file1)); - test_rl_pure_test(8, c, m, 200, 100, file1, sizeof(file1)); - test_rl_pure_test(9, c, m, 400, 40, file1, sizeof(file1)); - test_rl_pure_test(10, c, m, 440, 40, file1, sizeof(file1)); - test_rl_pure_test(11, c, m, 460, 40, file1, sizeof(file1)); - test_rl_pure_test(12, c, m, 400, 100, file1, sizeof(file1)); - test_rl_pure_test(13, c, m, 160, 100, file2, sizeof(file2)); - test_rl_pure_test(14, c, m, 100, 140, file2, sizeof(file2)); - test_rl_pure_test(15, c, m, 200, 40, file2, sizeof(file2)); - test_rl_pure_test(16, c, m, 240, 40, file2, sizeof(file2)); - test_rl_pure_test(17, c, m, 100, 40, file3, sizeof(file3)); - test_rl_pure_test(18, c, m, 140, 40, file3, sizeof(file3)); - test_rl_pure_test(19, c, m, 0, 40, file4, sizeof(file4)); - test_rl_pure_test(20, c, m, 40, 40, file4, sizeof(file4)); - test_rl_pure_test(21, c, m, 0, 40, file5, sizeof(file5)); - test_rl_pure_test(22, c, m, 40, 40, file5, sizeof(file5)); - test_rl_pure_test(23, c, m, 60, 40, file5, sizeof(file5)); - test_rl_pure_test(24, c, m, 0, 100, file5, sizeof(file5)); - test_rl_pure_test(25, c, m, 200, 40, file5, sizeof(file5)); - test_rl_pure_test(26, c, m, 240, 40, file5, sizeof(file5)); - test_rl_pure_test(27, c, m, 260, 40, file5, sizeof(file5)); - test_rl_pure_test(28, c, m, 200, 100, file5, sizeof(file5)); - test_rl_pure_test(29, c, m, 400, 40, file5, sizeof(file5)); - test_rl_pure_test(30, c, m, 440, 40, file5, sizeof(file5)); - test_rl_pure_test(31, c, m, 460, 40, file5, sizeof(file5)); - test_rl_pure_test(32, c, m, 400, 100, file5, sizeof(file5)); - test_rl_pure_test(33, c, m, 160, 100, file6, sizeof(file6)); - test_rl_pure_test(34, c, m, 100, 140, file6, sizeof(file6)); -} - -/** - * test_rl_zero - Runlist test: Merge a zero-length runlist - * - * Description... - * - * Returns: - */ -static void test_rl_zero(void) -{ - runlist_element *jim = NULL; - runlist_element *bob = NULL; - - bob = calloc(3, sizeof(runlist_element)); - if (!bob) - return; - - MKRL(bob+0, 10, 99, 5) - MKRL(bob+1, 15, LCN_RL_NOT_MAPPED, 0) - - jim = test_rl_runlists_merge(jim, bob); - if (!jim) - return; - - free(jim); -} - -/** - * test_rl_frag_combine - Runlist test: Perform tests using fragmented files - * @vol: - * @attr1: - * @attr2: - * @attr3: - * - * Description... - * - * Returns: - */ -static void test_rl_frag_combine(ntfs_volume *vol, ATTR_RECORD *attr1, ATTR_RECORD *attr2, ATTR_RECORD *attr3) -{ - runlist_element *run1; - runlist_element *run2; - runlist_element *run3; - - run1 = ntfs_mapping_pairs_decompress(vol, attr1, NULL); - if (!run1) - return; - - run2 = ntfs_mapping_pairs_decompress(vol, attr2, NULL); - if (!run2) - return; - - run1 = test_rl_runlists_merge(run1, run2); - - run3 = ntfs_mapping_pairs_decompress(vol, attr3, NULL); - if (!run3) - return; - - run1 = test_rl_runlists_merge(run1, run3); - - free(run1); -} - -/** - * test_rl_frag - Runlist test: Create tests using very fragmented files - * @test: - * - * Description... - * - * Returns: - */ -static void test_rl_frag(char *test) -{ - ntfs_volume vol; - ATTR_RECORD *attr1 = ntfs_malloc(1024); - ATTR_RECORD *attr2 = ntfs_malloc(1024); - ATTR_RECORD *attr3 = ntfs_malloc(1024); - - if (!attr1 || !attr2 || !attr3) - goto out; - - vol.sb = NULL; - vol.sector_size_bits = 9; - vol.cluster_size = 2048; - vol.cluster_size_bits = 11; - vol.major_ver = 3; - - if (!test_rl_read_buffer("runlist-data/attr1.bin", (u8*) attr1, 1024)) - goto out; - if (!test_rl_read_buffer("runlist-data/attr2.bin", (u8*) attr2, 1024)) - goto out; - if (!test_rl_read_buffer("runlist-data/attr3.bin", (u8*) attr3, 1024)) - goto out; - - if (strcmp(test, "123") == 0) test_rl_frag_combine(&vol, attr1, attr2, attr3); - else if (strcmp(test, "132") == 0) test_rl_frag_combine(&vol, attr1, attr3, attr2); - else if (strcmp(test, "213") == 0) test_rl_frag_combine(&vol, attr2, attr1, attr3); - else if (strcmp(test, "231") == 0) test_rl_frag_combine(&vol, attr2, attr3, attr1); - else if (strcmp(test, "312") == 0) test_rl_frag_combine(&vol, attr3, attr1, attr2); - else if (strcmp(test, "321") == 0) test_rl_frag_combine(&vol, attr3, attr2, attr1); - else - printf("Frag: No such test '%s'\n", test); - -out: - free(attr1); - free(attr2); - free(attr3); -} - -/** - * test_rl_main - Runlist test: Program start (main) - * @argc: - * @argv: - * - * Description... - * - * Returns: - */ -int test_rl_main(int argc, char *argv[]) -{ - if ((argc == 2) && (strcmp(argv[1], "zero") == 0)) test_rl_zero(); - else if ((argc == 3) && (strcmp(argv[1], "frag") == 0)) test_rl_frag(argv[2]); - else if ((argc == 4) && (strcmp(argv[1], "pure") == 0)) test_rl_pure(argv[2], argv[3]); - else - printf("rl [zero|frag|pure] {args}\n"); - - return 0; -} - -#endif - diff --git a/usr/src/lib/libntfs/common/libntfs/security.c b/usr/src/lib/libntfs/common/libntfs/security.c deleted file mode 100644 index ed02148179..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/security.c +++ /dev/null @@ -1,272 +0,0 @@ -/** - * security.c - Handling security/ACLs in NTFS. Part of the Linux-NTFS project. - * - * Copyright (c) 2004 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "layout.h" -#include "security.h" - -/* - * The zero GUID. - */ -static const GUID __zero_guid = { { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } } }; -const GUID *const zero_guid = &__zero_guid; - -/** - * ntfs_guid_is_zero - check if a GUID is zero - * @guid: [IN] guid to check - * - * Return TRUE if @guid is a valid pointer to a GUID and it is the zero GUID - * and FALSE otherwise. - */ -BOOL ntfs_guid_is_zero(const GUID *guid) -{ - return (memcmp(guid, zero_guid, sizeof(*zero_guid))); -} - -/** - * ntfs_guid_to_mbs - convert a GUID to a multi byte string - * @guid: [IN] guid to convert - * @guid_str: [OUT] string in which to return the GUID (optional) - * - * Convert the GUID pointed to by @guid to a multi byte string of the form - * "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX". Therefore, @guid_str (if not NULL) - * needs to be able to store at least 37 bytes. - * - * If @guid_str is not NULL it will contain the converted GUID on return. If - * it is NULL a string will be allocated and this will be returned. The caller - * is responsible for free()ing the string in that case. - * - * On success return the converted string and on failure return NULL with errno - * set to the error code. - */ -char *ntfs_guid_to_mbs(const GUID *guid, char *guid_str) -{ - char *_guid_str; - int res; - - if (!guid) { - errno = EINVAL; - return NULL; - } - _guid_str = guid_str; - if (!_guid_str) { - _guid_str = ntfs_malloc(37); - if (!_guid_str) - return _guid_str; - } - res = snprintf(_guid_str, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x-%02x%02x%02x%02x%02x%02x", guid->raw[0], - guid->raw[1], guid->raw[2], guid->raw[3], guid->raw[4], - guid->raw[5], guid->raw[6], guid->raw[7], guid->raw[8], - guid->raw[9], guid->raw[10], guid->raw[11], - guid->raw[12], guid->raw[13], guid->raw[14], - guid->raw[15]); - if (res == 36) - return _guid_str; - if (!guid_str) - free(_guid_str); - errno = EINVAL; - return NULL; -} - -/** - * ntfs_sid_to_mbs_size - determine maximum size for the string of a SID - * @sid: [IN] SID for which to determine the maximum string size - * - * Determine the maximum multi byte string size in bytes which is needed to - * store the standard textual representation of the SID pointed to by @sid. - * See ntfs_sid_to_mbs(), below. - * - * On success return the maximum number of bytes needed to store the multi byte - * string and on failure return -1 with errno set to the error code. - */ -int ntfs_sid_to_mbs_size(const SID *sid) -{ - int size, i; - - if (!ntfs_sid_is_valid(sid)) { - errno = EINVAL; - return -1; - } - /* Start with "S-". */ - size = 2; - /* - * Add the SID_REVISION. Hopefully the compiler will optimize this - * away as SID_REVISION is a constant. - */ - for (i = SID_REVISION; i > 0; i /= 10) - size++; - /* Add the "-". */ - size++; - /* - * Add the identifier authority. If it needs to be in decimal, the - * maximum is 2^32-1 = 4294967295 = 10 characters. If it needs to be - * in hexadecimal, then maximum is 0x665544332211 = 14 characters. - */ - if (!sid->identifier_authority.s.high_part) - size += 10; - else - size += 14; - /* - * Finally, add the sub authorities. For each we have a "-" followed - * by a decimal which can be up to 2^32-1 = 4294967295 = 10 characters. - */ - size += (1 + 10) * sid->sub_authority_count; - /* We need the zero byte at the end, too. */ - size++; - return size * sizeof(char); -} - -/** - * ntfs_sid_to_mbs - convert a SID to a multi byte string - * @sid: [IN] SID to convert - * @sid_str: [OUT] string in which to return the SID (optional) - * @sid_str_size: [IN] size in bytes of @sid_str - * - * Convert the SID pointed to by @sid to its standard textual representation. - * @sid_str (if not NULL) needs to be able to store at least - * ntfs_sid_to_mbs_size() bytes. @sid_str_size is the size in bytes of - * @sid_str if @sid_str is not NULL. - * - * The standard textual representation of the SID is of the form: - * S-R-I-S-S... - * Where: - * - The first "S" is the literal character 'S' identifying the following - * digits as a SID. - * - R is the revision level of the SID expressed as a sequence of digits - * in decimal. - * - I is the 48-bit identifier_authority, expressed as digits in decimal, - * if I < 2^32, or hexadecimal prefixed by "0x", if I >= 2^32. - * - S... is one or more sub_authority values, expressed as digits in - * decimal. - * - * If @sid_str is not NULL it will contain the converted SUID on return. If it - * is NULL a string will be allocated and this will be returned. The caller is - * responsible for free()ing the string in that case. - * - * On success return the converted string and on failure return NULL with errno - * set to the error code. - */ -char *ntfs_sid_to_mbs(const SID *sid, char *sid_str, size_t sid_str_size) -{ - u64 u; - char *s; - int i, j, cnt; - - /* - * No need to check @sid if !@sid_str since ntfs_sid_to_mbs_size() will - * check @sid, too. 8 is the minimum SID string size. - */ - if (sid_str && (sid_str_size < 8 || !ntfs_sid_is_valid(sid))) { - errno = EINVAL; - return NULL; - } - /* Allocate string if not provided. */ - if (!sid_str) { - cnt = ntfs_sid_to_mbs_size(sid); - if (cnt < 0) - return NULL; - s = ntfs_malloc(cnt); - if (!s) - return s; - sid_str = s; - /* So we know we allocated it. */ - sid_str_size = 0; - } else { - s = sid_str; - cnt = sid_str_size; - } - /* Start with "S-R-". */ - i = snprintf(s, cnt, "S-%hhu-", (unsigned char)sid->revision); - if (i < 0 || i >= cnt) - goto err_out; - s += i; - cnt -= i; - /* Add the identifier authority. */ - for (u = i = 0, j = 40; i < 6; i++, j -= 8) - u += (u64)sid->identifier_authority.value[i] << j; - if (!sid->identifier_authority.s.high_part) - i = snprintf(s, cnt, "%lu", (unsigned long)u); - else - i = snprintf(s, cnt, "0x%llx", (unsigned long long)u); - if (i < 0 || i >= cnt) - goto err_out; - s += i; - cnt -= i; - /* Finally, add the sub authorities. */ - for (j = 0; j < sid->sub_authority_count; j++) { - i = snprintf(s, cnt, "-%u", (unsigned int) - le32_to_cpu(sid->sub_authority[j])); - if (i < 0 || i >= cnt) - goto err_out; - s += i; - cnt -= i; - } - return sid_str; -err_out: - if (i >= cnt) - i = EMSGSIZE; - else - i = errno; - if (!sid_str_size) - free(sid_str); - errno = i; - return NULL; -} - -/** - * ntfs_generate_guid - generatates a random current guid. - * @guid: [OUT] pointer to a GUID struct to hold the generated guid. - * - * perhaps not a very good random number generator though... - */ -void ntfs_generate_guid(GUID *guid) -{ - unsigned int i; - u8 *p = (u8 *)guid; - - for (i = 0; i < sizeof(GUID); i++) { - p[i] = (u8)(random() & 0xFF); - if (i == 7) - p[7] = (p[7] & 0x0F) | 0x40; - if (i == 8) - p[8] = (p[8] & 0x3F) | 0x80; - } -} - diff --git a/usr/src/lib/libntfs/common/libntfs/unistr.c b/usr/src/lib/libntfs/common/libntfs/unistr.c deleted file mode 100644 index d5fd2eeb99..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/unistr.c +++ /dev/null @@ -1,776 +0,0 @@ -/** - * unistr.c - Unicode string handling. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_WCHAR_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "compat.h" -#include "attrib.h" -#include "endians.h" -#include "types.h" -#include "unistr.h" -#include "debug.h" -#include "logging.h" - -/* - * IMPORTANT - * ========= - * - * All these routines assume that the Unicode characters are in little endian - * encoding inside the strings!!! - */ - -/* - * This is used by the name collation functions to quickly determine what - * characters are (in)valid. - */ -#if 0 -static const u8 legal_ansi_char_array[0x40] = { - 0x00, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, - - 0x17, 0x07, 0x18, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x18, 0x16, 0x16, 0x17, 0x07, 0x00, - - 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, - 0x17, 0x17, 0x04, 0x16, 0x18, 0x16, 0x18, 0x18, -}; -#endif - -/** - * ntfs_names_are_equal - compare two Unicode names for equality - * @s1: name to compare to @s2 - * @s1_len: length in Unicode characters of @s1 - * @s2: name to compare to @s1 - * @s2_len: length in Unicode characters of @s2 - * @ic: ignore case bool - * @upcase: upcase table (only if @ic == IGNORE_CASE) - * @upcase_size: length in Unicode characters of @upcase (if present) - * - * Compare the names @s1 and @s2 and return TRUE (1) if the names are - * identical, or FALSE (0) if they are not identical. If @ic is IGNORE_CASE, - * the @upcase table is used to perform a case insensitive comparison. - */ -BOOL ntfs_names_are_equal(const ntfschar *s1, size_t s1_len, - const ntfschar *s2, size_t s2_len, - const IGNORE_CASE_BOOL ic, - const ntfschar *upcase, const u32 upcase_size) -{ - if (s1_len != s2_len) - return FALSE; - if (!s1_len) - return TRUE; - if (ic == CASE_SENSITIVE) - return ntfs_ucsncmp(s1, s2, s1_len) ? FALSE: TRUE; - return ntfs_ucsncasecmp(s1, s2, s1_len, upcase, upcase_size) ? FALSE: - TRUE; -} - -/** - * ntfs_names_collate - collate two Unicode names - * @name1: first Unicode name to compare - * @name1_len: length of first Unicode name to compare - * @name2: second Unicode name to compare - * @name2_len: length of second Unicode name to compare - * @err_val: if @name1 contains an invalid character return this value - * @ic: either CASE_SENSITIVE or IGNORE_CASE - * @upcase: upcase table (ignored if @ic is CASE_SENSITIVE) - * @upcase_len: upcase table size (ignored if @ic is CASE_SENSITIVE) - * - * ntfs_names_collate() collates two Unicode names and returns: - * - * -1 if the first name collates before the second one, - * 0 if the names match, - * 1 if the second name collates before the first one, or - * @err_val if an invalid character is found in @name1 during the comparison. - * - * The following characters are considered invalid: '"', '*', '<', '>' and '?'. - */ -int ntfs_names_collate(const ntfschar *name1, const u32 name1_len, - const ntfschar *name2, const u32 name2_len, - const int err_val __attribute__((unused)), - const IGNORE_CASE_BOOL ic, const ntfschar *upcase, - const u32 upcase_len) -{ - u32 cnt; - u16 c1, c2; - -#ifdef DEBUG - if (!name1 || !name2 || (ic && (!upcase || !upcase_len))) { - ntfs_log_debug("ntfs_names_collate received NULL pointer!\n"); - exit(1); - } -#endif - for (cnt = 0; cnt < min(name1_len, name2_len); ++cnt) { - c1 = le16_to_cpu(*name1); - name1++; - c2 = le16_to_cpu(*name2); - name2++; - if (ic) { - if (c1 < upcase_len) - c1 = le16_to_cpu(upcase[c1]); - if (c2 < upcase_len) - c2 = le16_to_cpu(upcase[c2]); - } -#if 0 - if (c1 < 64 && legal_ansi_char_array[c1] & 8) - return err_val; -#endif - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - } - if (name1_len < name2_len) - return -1; - if (name1_len == name2_len) - return 0; - /* name1_len > name2_len */ -#if 0 - c1 = le16_to_cpu(*name1); - if (c1 < 64 && legal_ansi_char_array[c1] & 8) - return err_val; -#endif - return 1; -} - -/** - * ntfs_ucsncmp - compare two little endian Unicode strings - * @s1: first string - * @s2: second string - * @n: maximum unicode characters to compare - * - * Compare the first @n characters of the Unicode strings @s1 and @s2, - * The strings in little endian format and appropriate le16_to_cpu() - * conversion is performed on non-little endian machines. - * - * The function returns an integer less than, equal to, or greater than zero - * if @s1 (or the first @n Unicode characters thereof) is found, respectively, - * to be less than, to match, or be greater than @s2. - */ -int ntfs_ucsncmp(const ntfschar *s1, const ntfschar *s2, size_t n) -{ - u16 c1, c2; - size_t i; - -#ifdef DEBUG - if (!s1 || !s2) { - ntfs_log_debug("ntfs_wcsncmp() received NULL pointer!\n"); - exit(1); - } -#endif - for (i = 0; i < n; ++i) { - c1 = le16_to_cpu(s1[i]); - c2 = le16_to_cpu(s2[i]); - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - if (!c1) - break; - } - return 0; -} - -/** - * ntfs_ucsncasecmp - compare two little endian Unicode strings, ignoring case - * @s1: first string - * @s2: second string - * @n: maximum unicode characters to compare - * @upcase: upcase table - * @upcase_size: upcase table size in Unicode characters - * - * Compare the first @n characters of the Unicode strings @s1 and @s2, - * ignoring case. The strings in little endian format and appropriate - * le16_to_cpu() conversion is performed on non-little endian machines. - * - * Each character is uppercased using the @upcase table before the comparison. - * - * The function returns an integer less than, equal to, or greater than zero - * if @s1 (or the first @n Unicode characters thereof) is found, respectively, - * to be less than, to match, or be greater than @s2. - */ -int ntfs_ucsncasecmp(const ntfschar *s1, const ntfschar *s2, size_t n, - const ntfschar *upcase, const u32 upcase_size) -{ - u16 c1, c2; - size_t i; - -#ifdef DEBUG - if (!s1 || !s2 || !upcase) { - ntfs_log_debug("ntfs_wcsncasecmp() received NULL pointer!\n"); - exit(1); - } -#endif - for (i = 0; i < n; ++i) { - if ((c1 = le16_to_cpu(s1[i])) < upcase_size) - c1 = le16_to_cpu(upcase[c1]); - if ((c2 = le16_to_cpu(s2[i])) < upcase_size) - c2 = le16_to_cpu(upcase[c2]); - if (c1 < c2) - return -1; - if (c1 > c2) - return 1; - if (!c1) - break; - } - return 0; -} - -/** - * ntfs_ucsnlen - determine the length of a little endian Unicode string - * @s: pointer to Unicode string - * @maxlen: maximum length of string @s - * - * Return the number of Unicode characters in the little endian Unicode - * string @s up to a maximum of maxlen Unicode characters, not including - * the terminating (ntfschar)'\0'. If there is no (ntfschar)'\0' between @s - * and @s + @maxlen, @maxlen is returned. - * - * This function never looks beyond @s + @maxlen. - */ -u32 ntfs_ucsnlen(const ntfschar *s, u32 maxlen) -{ - u32 i; - - for (i = 0; i < maxlen; i++) { - if (!le16_to_cpu(s[i])) - break; - } - return i; -} - -/** - * ntfs_ucsndup - duplicate little endian Unicode string - * @s: pointer to Unicode string - * @maxlen: maximum length of string @s - * - * Return a pointer to a new little endian Unicode string which is a duplicate - * of the string s. Memory for the new string is obtained with malloc(3), and - * can be freed with free(3). - * - * A maximum of @maxlen Unicode characters are copied and a terminating - * (ntfschar)'\0' little endian Unicode character is added. - * - * This function never looks beyond @s + @maxlen. - * - * Return a pointer to the new little endian Unicode string on success and NULL - * on failure with errno set to the error code. - */ -ntfschar *ntfs_ucsndup(const ntfschar *s, u32 maxlen) -{ - ntfschar *dst; - u32 len; - - len = ntfs_ucsnlen(s, maxlen); - dst = ntfs_malloc((len + 1) * sizeof(ntfschar)); - if (dst) { - memcpy(dst, s, len * sizeof(ntfschar)); - dst[len] = 0; - } - return dst; -} - -/** - * ntfs_name_upcase - Map an Unicode name to its uppercase equivalent - * @name: - * @name_len: - * @upcase: - * @upcase_len: - * - * Description... - * - * Returns: - */ -void ntfs_name_upcase(ntfschar *name, u32 name_len, const ntfschar *upcase, - const u32 upcase_len) -{ - u32 i; - u16 u; - - for (i = 0; i < name_len; i++) - if ((u = le16_to_cpu(name[i])) < upcase_len) - name[i] = upcase[u]; -} - -/** - * ntfs_file_value_upcase - Convert a filename to upper case - * @file_name_attr: - * @upcase: - * @upcase_len: - * - * Description... - * - * Returns: - */ -void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr, - const ntfschar *upcase, const u32 upcase_len) -{ - ntfs_name_upcase((ntfschar*)&file_name_attr->file_name, - file_name_attr->file_name_length, upcase, upcase_len); -} - -/** - * ntfs_file_values_compare - Which of two filenames should be listed first - * @file_name_attr1: - * @file_name_attr2: - * @err_val: - * @ic: - * @upcase: - * @upcase_len: - * - * Description... - * - * Returns: - */ -int ntfs_file_values_compare(const FILE_NAME_ATTR *file_name_attr1, - const FILE_NAME_ATTR *file_name_attr2, - const int err_val, const IGNORE_CASE_BOOL ic, - const ntfschar *upcase, const u32 upcase_len) -{ - return ntfs_names_collate((ntfschar*)&file_name_attr1->file_name, - file_name_attr1->file_name_length, - (ntfschar*)&file_name_attr2->file_name, - file_name_attr2->file_name_length, - err_val, ic, upcase, upcase_len); -} - -/** - * ntfs_ucstombs - convert a little endian Unicode string to a multibyte string - * @ins: input Unicode string buffer - * @ins_len: length of input string in Unicode characters - * @outs: on return contains the (allocated) output multibyte string - * @outs_len: length of output buffer in bytes - * - * Convert the input little endian, 2-byte Unicode string @ins, of length - * @ins_len into the multibyte string format dictated by the current locale. - * - * If *@outs is NULL, the function allocates the string and the caller is - * responsible for calling free(*@outs); when finished with it. - * - * On success the function returns the number of bytes written to the output - * string *@outs (>= 0), not counting the terminating NULL byte. If the output - * string buffer was allocated, *@outs is set to it. - * - * On error, -1 is returned, and errno is set to the error code. The following - * error codes can be expected: - * EINVAL Invalid arguments (e.g. @ins or @outs is NULL). - * EILSEQ The input string cannot be represented as a multibyte - * sequence according to the current locale. - * ENAMETOOLONG Destination buffer is too small for input string. - * ENOMEM Not enough memory to allocate destination buffer. - */ -int ntfs_ucstombs(const ntfschar *ins, const int ins_len, char **outs, - int outs_len) -{ - char *mbs; - wchar_t wc; - int i, o, mbs_len; - int cnt = 0; -#ifdef HAVE_MBSINIT - mbstate_t mbstate; -#endif - - if (!ins || !outs) { - errno = EINVAL; - return -1; - } - mbs = *outs; - mbs_len = outs_len; - if (mbs && !mbs_len) { - errno = ENAMETOOLONG; - return -1; - } - if (!mbs) { - mbs_len = (ins_len + 1) * MB_CUR_MAX; - mbs = (char*)ntfs_malloc(mbs_len); - if (!mbs) - return -1; - } -#ifdef HAVE_MBSINIT - memset(&mbstate, 0, sizeof(mbstate)); -#else - wctomb(NULL, 0); -#endif - for (i = o = 0; i < ins_len; i++) { - /* Reallocate memory if necessary or abort. */ - if ((int)(o + MB_CUR_MAX) > mbs_len) { - char *tc; - if (mbs == *outs) { - errno = ENAMETOOLONG; - return -1; - } - tc = (char*)ntfs_malloc((mbs_len + 64) & ~63); - if (!tc) - goto err_out; - memcpy(tc, mbs, mbs_len); - mbs_len = (mbs_len + 64) & ~63; - free(mbs); - mbs = tc; - } - /* Convert the LE Unicode character to a CPU wide character. */ - wc = (wchar_t)le16_to_cpu(ins[i]); - if (!wc) - break; - /* Convert the CPU endian wide character to multibyte. */ -#ifdef HAVE_MBSINIT - cnt = wcrtomb(mbs + o, wc, &mbstate); -#else - cnt = wctomb(mbs + o, wc); -#endif - if (cnt == -1) - goto err_out; - if (cnt <= 0) { - ntfs_log_debug("Eeek. cnt <= 0, cnt = %i\n", cnt); - errno = EINVAL; - goto err_out; - } - o += cnt; - } -#ifdef HAVE_MBSINIT - /* Make sure we are back in the initial state. */ - if (!mbsinit(&mbstate)) { - ntfs_log_debug("Eeek. mbstate not in initial state!\n"); - errno = EILSEQ; - goto err_out; - } -#endif - /* Now write the NULL character. */ - mbs[o] = 0; - if (*outs != mbs) - *outs = mbs; - return o; -err_out: - if (mbs != *outs) - free(mbs); - return -1; -} - -/** - * ntfs_mbstoucs - convert a multibyte string to a little endian Unicode string - * @ins: input multibyte string buffer - * @outs: on return contains the (allocated) output Unicode string - * @outs_len: length of output buffer in Unicode characters - * - * Convert the input multibyte string @ins, from the current locale into the - * corresponding little endian, 2-byte Unicode string. - * - * If *@outs is NULL, the function allocates the string and the caller is - * responsible for calling free(*@outs); when finished with it. - * - * On success the function returns the number of Unicode characters written to - * the output string *@outs (>= 0), not counting the terminating Unicode NULL - * character. If the output string buffer was allocated, *@outs is set to it. - * - * On error, -1 is returned, and errno is set to the error code. The following - * error codes can be expected: - * EINVAL Invalid arguments (e.g. @ins or @outs is NULL). - * EILSEQ The input string cannot be represented as a Unicode - * string according to the current locale. - * ENAMETOOLONG Destination buffer is too small for input string. - * ENOMEM Not enough memory to allocate destination buffer. - */ -int ntfs_mbstoucs(const char *ins, ntfschar **outs, int outs_len) -{ - ntfschar *ucs; - const char *s; - wchar_t wc; - int i, o, cnt, ins_len, ucs_len, ins_size; -#ifdef HAVE_MBSINIT - mbstate_t mbstate; -#endif - - if (!ins || !outs) { - errno = EINVAL; - return -1; - } - ucs = *outs; - ucs_len = outs_len; - if (ucs && !ucs_len) { - errno = ENAMETOOLONG; - return -1; - } - /* Determine the size of the multi-byte string in bytes. */ - ins_size = strlen(ins); - /* Determine the length of the multi-byte string. */ - s = ins; -#if defined(HAVE_MBSINIT) - memset(&mbstate, 0, sizeof(mbstate)); - ins_len = mbsrtowcs(NULL, (const char **)&s, 0, &mbstate); -#ifdef __CYGWIN32__ - if (!ins_len && *ins) { - /* Older Cygwin had broken mbsrtowcs() implementation. */ - ins_len = strlen(ins); - } -#endif -#elif !defined(DJGPP) - ins_len = mbstowcs(NULL, s, 0); -#else - /* Eeek!!! DJGPP has broken mbstowcs() implementation!!! */ - ins_len = strlen(ins); -#endif - if (ins_len == -1) - return ins_len; -#ifdef HAVE_MBSINIT - if ((s != ins) || !mbsinit(&mbstate)) { -#else - if (s != ins) { -#endif - errno = EILSEQ; - return -1; - } - /* Add the NULL terminator. */ - ins_len++; - if (!ucs) { - ucs_len = ins_len; - ucs = (ntfschar*)ntfs_malloc(ucs_len * sizeof(ntfschar)); - if (!ucs) - return -1; - } -#ifdef HAVE_MBSINIT - memset(&mbstate, 0, sizeof(mbstate)); -#else - mbtowc(NULL, NULL, 0); -#endif - for (i = o = cnt = 0; i < ins_size; i += cnt, o++) { - /* Reallocate memory if necessary or abort. */ - if (o >= ucs_len) { - ntfschar *tc; - if (ucs == *outs) { - errno = ENAMETOOLONG; - return -1; - } - /* - * We will never get here but hey, it's only a bit of - * extra code... - */ - ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63; - tc = (ntfschar*)realloc(ucs, ucs_len); - if (!tc) - goto err_out; - ucs = tc; - ucs_len /= sizeof(ntfschar); - } - /* Convert the multibyte character to a wide character. */ -#ifdef HAVE_MBSINIT - cnt = mbrtowc(&wc, ins + i, ins_size - i, &mbstate); -#else - cnt = mbtowc(&wc, ins + i, ins_size - i); -#endif - if (!cnt) - break; - if (cnt == -1) - goto err_out; - if (cnt < -1) { - ntfs_log_trace("Eeek. cnt = %i\n", cnt); - errno = EINVAL; - goto err_out; - } - /* Make sure we are not overflowing the NTFS Unicode set. */ - if ((unsigned long)wc >= (unsigned long)(1 << - (8 * sizeof(ntfschar)))) { - errno = EILSEQ; - goto err_out; - } - /* Convert the CPU wide character to a LE Unicode character. */ - ucs[o] = cpu_to_le16(wc); - } -#ifdef HAVE_MBSINIT - /* Make sure we are back in the initial state. */ - if (!mbsinit(&mbstate)) { - ntfs_log_trace("Eeek. mbstate not in initial state!\n"); - errno = EILSEQ; - goto err_out; - } -#endif - /* Now write the NULL character. */ - ucs[o] = 0; - if (*outs != ucs) - *outs = ucs; - return o; -err_out: - if (ucs != *outs) - free(ucs); - return -1; -} - -/** - * ntfs_upcase_table_build - build the default upcase table for NTFS - * @uc: destination buffer where to store the built table - * @uc_len: size of destination buffer in bytes - * - * ntfs_upcase_table_build() builds the default upcase table for NTFS and - * stores it in the caller supplied buffer @uc of size @uc_len. - * - * The generated $UpCase table is the one used by Windows Vista. - * - * Note, @uc_len must be at least 128kiB in size or bad things will happen! - */ -void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len) -{ - /* - * "Start" is inclusive and "End" is exclusive, every value has the - * value of "Add" added to it. - */ - static int add[][3] = { /* Start, End, Add */ - {0x0061, 0x007b, -32}, {0x00e0, 0x00f7, -32}, {0x00f8, 0x00ff, -32}, - {0x0256, 0x0258, -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130}, - {0x03ac, 0x03ad, -38}, {0x03ad, 0x03b0, -37}, {0x03b1, 0x03c2, -32}, - {0x03c2, 0x03c3, -31}, {0x03c3, 0x03cc, -32}, {0x03cc, 0x03cd, -64}, - {0x03cd, 0x03cf, -63}, {0x0430, 0x0450, -32}, {0x0450, 0x0460, -80}, - {0x0561, 0x0587, -48}, {0x1f00, 0x1f08, 8}, {0x1f10, 0x1f16, 8}, - {0x1f20, 0x1f28, 8}, {0x1f30, 0x1f38, 8}, {0x1f40, 0x1f46, 8}, - {0x1f51, 0x1f52, 8}, {0x1f53, 0x1f54, 8}, {0x1f55, 0x1f56, 8}, - {0x1f57, 0x1f58, 8}, {0x1f60, 0x1f68, 8}, {0x1f70, 0x1f72, 74}, - {0x1f72, 0x1f76, 86}, {0x1f76, 0x1f78, 100}, {0x1f78, 0x1f7a, 128}, - {0x1f7a, 0x1f7c, 112}, {0x1f7c, 0x1f7e, 126}, {0x1f80, 0x1f88, 8}, - {0x1f90, 0x1f98, 8}, {0x1fa0, 0x1fa8, 8}, {0x1fb0, 0x1fb2, 8}, - {0x1fb3, 0x1fb4, 9}, {0x1fcc, 0x1fcd, -9}, {0x1fd0, 0x1fd2, 8}, - {0x1fe0, 0x1fe2, 8}, {0x1fe5, 0x1fe6, 7}, {0x1ffc, 0x1ffd, -9}, - {0x2170, 0x2180, -16}, {0x24d0, 0x24ea, -26}, {0x2c30, 0x2c5f, -48}, - {0x2d00, 0x2d26, -7264}, {0xff41, 0xff5b, -32}, {0} - }; - /* - * "Start" is exclusive and "End" is inclusive, every second value is - * decremented by one. - */ - static int skip_dec[][2] = { /* Start, End */ - {0x0100, 0x012f}, {0x0132, 0x0137}, {0x0139, 0x0149}, {0x014a, 0x0178}, - {0x0179, 0x017e}, {0x01a0, 0x01a6}, {0x01b3, 0x01b7}, {0x01cd, 0x01dd}, - {0x01de, 0x01ef}, {0x01f4, 0x01f5}, {0x01f8, 0x01f9}, {0x01fa, 0x0220}, - {0x0222, 0x0234}, {0x023b, 0x023c}, {0x0241, 0x0242}, {0x0246, 0x024f}, - {0x03d8, 0x03ef}, {0x03f7, 0x03f8}, {0x03fa, 0x03fb}, {0x0460, 0x0481}, - {0x048a, 0x04bf}, {0x04c1, 0x04c4}, {0x04c5, 0x04c8}, {0x04c9, 0x04ce}, - {0x04ec, 0x04ed}, {0x04d0, 0x04eb}, {0x04ee, 0x04f5}, {0x04f6, 0x0513}, - {0x1e00, 0x1e95}, {0x1ea0, 0x1ef9}, {0x2183, 0x2184}, {0x2c60, 0x2c61}, - {0x2c67, 0x2c6c}, {0x2c75, 0x2c76}, {0x2c80, 0x2ce3}, {0} - }; - /* - * Set the Unicode character at offset "Offset" to "Value". Note, - * "Value" is host endian. - */ - static int set[][2] = { /* Offset, Value */ - {0x00ff, 0x0178}, {0x0180, 0x0243}, {0x0183, 0x0182}, {0x0185, 0x0184}, - {0x0188, 0x0187}, {0x018c, 0x018b}, {0x0192, 0x0191}, {0x0195, 0x01f6}, - {0x0199, 0x0198}, {0x019a, 0x023d}, {0x019e, 0x0220}, {0x01a8, 0x01a7}, - {0x01ad, 0x01ac}, {0x01b0, 0x01af}, {0x01b9, 0x01b8}, {0x01bd, 0x01bc}, - {0x01bf, 0x01f7}, {0x01c6, 0x01c4}, {0x01c9, 0x01c7}, {0x01cc, 0x01ca}, - {0x01dd, 0x018e}, {0x01f3, 0x01f1}, {0x023a, 0x2c65}, {0x023e, 0x2c66}, - {0x0253, 0x0181}, {0x0254, 0x0186}, {0x0259, 0x018f}, {0x025b, 0x0190}, - {0x0260, 0x0193}, {0x0263, 0x0194}, {0x0268, 0x0197}, {0x0269, 0x0196}, - {0x026b, 0x2c62}, {0x026f, 0x019c}, {0x0272, 0x019d}, {0x0275, 0x019f}, - {0x027d, 0x2c64}, {0x0280, 0x01a6}, {0x0283, 0x01a9}, {0x0288, 0x01ae}, - {0x0289, 0x0244}, {0x028c, 0x0245}, {0x0292, 0x01b7}, {0x03f2, 0x03f9}, - {0x04cf, 0x04c0}, {0x1d7d, 0x2c63}, {0x214e, 0x2132}, {0} - }; - unsigned i, r; - - memset(uc, 0, uc_len); - uc_len /= 2; - /* Start with a one-to-one mapping, i.e. no upcasing happens at all. */ - for (i = 0; i < uc_len; i++) - uc[i] = cpu_to_le16(i); - /* Adjust specified runs by the specified amount. */ - for (r = 0; add[r][0]; r++) - for (i = add[r][0]; i < add[r][1]; i++) - uc[i] = cpu_to_le16(le16_to_cpu(uc[i]) + add[r][2]); - /* Decrement every second value in specified runs. */ - for (r = 0; skip_dec[r][0]; r++) - for (i = skip_dec[r][0]; i < skip_dec[r][1]; - i += 2) - uc[i + 1] = cpu_to_le16(le16_to_cpu(uc[i + 1]) - 1); - /* Set specified characters to specified values. */ - for (r = 0; set[r][0]; r++) - uc[set[r][0]] = cpu_to_le16(set[r][1]); -} - -/** - * ntfs_str2ucs - convert a string to a valid NTFS file name - * @s: input string - * @len: length of output buffer in Unicode characters - * - * Convert the input @s string into the corresponding little endian, - * 2-byte Unicode string. The length of the converted string is less - * or equal to the maximum length allowed by the NTFS format (255). - * - * If @s is NULL then return AT_UNNAMED. - * - * On success the function returns the Unicode string in an allocated - * buffer and the caller is responsible to free it when it's not needed - * anymore. - * - * On error NULL is returned and errno is set to the error code. - */ -ntfschar *ntfs_str2ucs(const char *s, int *len) -{ - ntfschar *ucs = NULL; - - if (s && ((*len = ntfs_mbstoucs(s, &ucs, 0)) == -1)) { - ntfs_log_perror("Couldn't convert '%s' to Unicode", s); - return NULL; - } - if (*len > NTFS_MAX_NAME_LEN) { - free(ucs); - errno = ENAMETOOLONG; - return NULL; - } - if (!ucs || !*len) { - ucs = AT_UNNAMED; - *len = 0; - } - return ucs; -} - -/** - * ntfs_ucsfree - free memory allocated by ntfs_str2ucs() - * @ucs: input string to be freed - * - * Free memory at @ucs and which was allocated by ntfs_str2ucs. - * - * Return value: none. - */ -void ntfs_ucsfree(ntfschar *ucs) -{ - if (ucs && (ucs != AT_UNNAMED)) - free(ucs); -} - diff --git a/usr/src/lib/libntfs/common/libntfs/unix_io.c b/usr/src/lib/libntfs/common/libntfs/unix_io.c deleted file mode 100644 index 9299284c17..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/unix_io.c +++ /dev/null @@ -1,321 +0,0 @@ -/** - * unix_io.c - Unix style disk io functions. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_SYS_TYPES_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_SYS_IOCTL_H -#include -#endif -#ifdef HAVE_LINUX_FD_H -#include -#endif - -#include "compat.h" -#include "types.h" -#include "mst.h" -#include "debug.h" -#include "device.h" -#include "logging.h" - -#define DEV_FD(dev) (*(int *)dev->d_private) - -/* Define to nothing if not present on this system. */ -#ifndef O_EXCL -# define O_EXCL 0 -#endif - -/** - * ntfs_device_unix_io_open - Open a device and lock it exclusively - * @dev: - * @flags: - * - * Description... - * - * Returns: - */ -static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags) -{ - struct flock flk; - struct stat sbuf; - int err; - - if (NDevOpen(dev)) { - errno = EBUSY; - return -1; - } - if (!(dev->d_private = ntfs_malloc(sizeof(int)))) - return -1; - *(int*)dev->d_private = open(dev->d_name, flags); - if (*(int*)dev->d_private == -1) { - err = errno; - goto err_out; - } - /* Setup our read-only flag. */ - if ((flags & O_RDWR) != O_RDWR) - NDevSetReadOnly(dev); - /* Acquire exclusive (mandatory) lock on the whole device. */ - memset(&flk, 0, sizeof(flk)); - if (NDevReadOnly(dev)) - flk.l_type = F_RDLCK; - else - flk.l_type = F_WRLCK; - flk.l_whence = SEEK_SET; - flk.l_start = flk.l_len = 0LL; - if (fcntl(DEV_FD(dev), F_SETLK, &flk)) { - err = errno; - ntfs_log_debug("ntfs_device_unix_io_open: Could not lock %s " - "for %s\n", dev->d_name, NDevReadOnly(dev) ? - "reading" : "writing"); - if (close(DEV_FD(dev))) - ntfs_log_perror("ntfs_device_unix_io_open: Warning: " - "Could not close %s", dev->d_name); - goto err_out; - } - /* Determine if device is a block device or not, ignoring errors. */ - if (!fstat(DEV_FD(dev), &sbuf) && S_ISBLK(sbuf.st_mode)) - NDevSetBlock(dev); - /* Set our open flag. */ - NDevSetOpen(dev); - return 0; -err_out: - free(dev->d_private); - dev->d_private = NULL; - errno = err; - return -1; -} - -/** - * ntfs_device_unix_io_close - Close the device, releasing the lock - * @dev: - * - * Description... - * - * Returns: - */ -static int ntfs_device_unix_io_close(struct ntfs_device *dev) -{ - struct flock flk; - - if (!NDevOpen(dev)) { - errno = EBADF; - return -1; - } - if (NDevDirty(dev)) - fsync(DEV_FD(dev)); - /* Release exclusive (mandatory) lock on the whole device. */ - memset(&flk, 0, sizeof(flk)); - flk.l_type = F_UNLCK; - flk.l_whence = SEEK_SET; - flk.l_start = flk.l_len = 0LL; - if (fcntl(DEV_FD(dev), F_SETLK, &flk)) - ntfs_log_perror("ntfs_device_unix_io_close: Warning: Could not " - "unlock %s", dev->d_name); - /* Close the file descriptor and clear our open flag. */ - if (close(DEV_FD(dev))) - return -1; - NDevClearOpen(dev); - free(dev->d_private); - dev->d_private = NULL; - return 0; -} - -/** - * ntfs_device_unix_io_seek - Seek to a place on the device - * @dev: - * @offset: - * @whence: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_unix_io_seek(struct ntfs_device *dev, s64 offset, - int whence) -{ - return lseek(DEV_FD(dev), offset, whence); -} - -/** - * ntfs_device_unix_io_read - Read from the device, from the current location - * @dev: - * @buf: - * @count: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_unix_io_read(struct ntfs_device *dev, void *buf, - s64 count) -{ - return read(DEV_FD(dev), buf, count); -} - -/** - * ntfs_device_unix_io_write - Write to the device, at the current location - * @dev: - * @buf: - * @count: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_unix_io_write(struct ntfs_device *dev, const void *buf, - s64 count) -{ - if (NDevReadOnly(dev)) { - errno = EROFS; - return -1; - } - NDevSetDirty(dev); - return write(DEV_FD(dev), buf, count); -} - -/** - * ntfs_device_unix_io_pread - Perform a positioned read from the device - * @dev: - * @buf: - * @count: - * @offset: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_unix_io_pread(struct ntfs_device *dev, void *buf, - s64 count, s64 offset) -{ - return pread(DEV_FD(dev), buf, count, offset); -} - -/** - * ntfs_device_unix_io_pwrite - Perform a positioned write to the device - * @dev: - * @buf: - * @count: - * @offset: - * - * Description... - * - * Returns: - */ -static s64 ntfs_device_unix_io_pwrite(struct ntfs_device *dev, const void *buf, - s64 count, s64 offset) -{ - if (NDevReadOnly(dev)) { - errno = EROFS; - return -1; - } - NDevSetDirty(dev); - return pwrite(DEV_FD(dev), buf, count, offset); -} - -/** - * ntfs_device_unix_io_sync - Flush any buffered changes to the device - * @dev: - * - * Description... - * - * Returns: - */ -static int ntfs_device_unix_io_sync(struct ntfs_device *dev) -{ - if (!NDevReadOnly(dev) && NDevDirty(dev)) { - int res = fsync(DEV_FD(dev)); - if (!res) - NDevClearDirty(dev); - return res; - } - return 0; -} - -/** - * ntfs_device_unix_io_stat - Get information about the device - * @dev: - * @buf: - * - * Description... - * - * Returns: - */ -static int ntfs_device_unix_io_stat(struct ntfs_device *dev, struct stat *buf) -{ - return fstat(DEV_FD(dev), buf); -} - -/** - * ntfs_device_unix_io_ioctl - Perform an ioctl on the device - * @dev: - * @request: - * @argp: - * - * Description... - * - * Returns: - */ -static int ntfs_device_unix_io_ioctl(struct ntfs_device *dev, int request, - void *argp) -{ - return ioctl(DEV_FD(dev), request, argp); -} - -/** - * Device operations for working with unix style devices and files. - */ -struct ntfs_device_operations ntfs_device_unix_io_ops = { - .open = ntfs_device_unix_io_open, - .close = ntfs_device_unix_io_close, - .seek = ntfs_device_unix_io_seek, - .read = ntfs_device_unix_io_read, - .write = ntfs_device_unix_io_write, - .pread = ntfs_device_unix_io_pread, - .pwrite = ntfs_device_unix_io_pwrite, - .sync = ntfs_device_unix_io_sync, - .stat = ntfs_device_unix_io_stat, - .ioctl = ntfs_device_unix_io_ioctl, -}; diff --git a/usr/src/lib/libntfs/common/libntfs/version.c b/usr/src/lib/libntfs/common/libntfs/version.c deleted file mode 100644 index 7882e7177b..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/version.c +++ /dev/null @@ -1,45 +0,0 @@ -/** - * version.c - Info about the NTFS library. Part of the Linux-NTFS project. - * - * Copyright (c) 2005 Anton Altaparmakov - * Copyright (c) 2005 Richard Russon - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "version.h" - -#ifdef LTVERSION_LIBNTFS -#define LIBNTFS_VERSION_STRING LTVERSION_LIBNTFS -#else -#define LIBNTFS_VERSION_STRING "unknown" -#endif - -static const char *libntfs_version_string = LIBNTFS_VERSION_STRING; - -/** - * ntfs_libntfs_version - query version number of the ntfs library libntfs - * - * Returns pointer to a text string representing the version of libntfs. - */ -const char *ntfs_libntfs_version(void) -{ - return libntfs_version_string; -} diff --git a/usr/src/lib/libntfs/common/libntfs/volume.c b/usr/src/lib/libntfs/common/libntfs/volume.c deleted file mode 100644 index 2a783dddad..0000000000 --- a/usr/src/lib/libntfs/common/libntfs/volume.c +++ /dev/null @@ -1,1689 +0,0 @@ -/** - * volume.c - NTFS volume handling code. Part of the Linux-NTFS project. - * - * Copyright (c) 2000-2006 Anton Altaparmakov - * Copyright (c) 2002-2006 Szabolcs Szakacsits - * Copyright (c) 2004-2005 Richard Russon - * Copyright (c) 2005-2007 Yura Pakhuchiy - * - * This program/include file is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file 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 (in the main directory of the Linux-NTFS - * distribution in the file COPYING); if not, write to the Free Software - * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#ifdef HAVE_UNISTD_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif -#ifdef HAVE_SYS_STAT_H -#include -#endif -#ifdef HAVE_LIMITS_H -#include -#endif - -#include "compat.h" -#include "volume.h" -#include "attrib.h" -#include "mft.h" -#include "bootsect.h" -#include "device.h" -#include "debug.h" -#include "inode.h" -#include "runlist.h" -#include "logfile.h" -#include "dir.h" -#include "logging.h" - -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif - -/** - * ntfs_volume_alloc - Create an NTFS volume object and initialise it - * - * Description... - * - * Returns: - */ -ntfs_volume *ntfs_volume_alloc(void) -{ - ntfs_volume *vol; - int i; - - vol = calloc(1, sizeof(ntfs_volume)); - if (vol) { - for (i = 0; i < NTFS_INODE_CACHE_SIZE; i++) - INIT_LIST_HEAD(&vol->inode_cache[i]); - } - return vol; -} - -/** - * __ntfs_volume_release - Destroy an NTFS volume object - * @v: - * - * Description... - * - * Returns: - */ -static void __ntfs_volume_release(ntfs_volume *v) -{ - struct list_head *pos, *tmp; - int i; - - /* Sync and print error about not detached inodes. */ - for (i = 0; i < NTFS_INODE_CACHE_SIZE; i++) - list_for_each_safe(pos, tmp, &v->inode_cache[i]) { - ntfs_inode *ni = - list_entry(pos, ntfs_inode, list_entry); - - switch (ni->mft_no) { - case FILE_Volume: - case FILE_Bitmap: - case FILE_MFT: - case FILE_MFTMirr: - if (ni->nr_references == 1) - continue; - break; - } - - ntfs_log_error("%s(): Inode %llu still have %d " - "references.\n", "__ntfs_volume_release", - ni->mft_no, ni->nr_references); - ntfs_inode_sync(ni); - } - /* - * Clear the dirty bit if it was not set before we mounted and this is - * not a forensic mount. - */ - if (!NVolReadOnly(v) && !NVolWasDirty(v) && !NVolForensicMount(v)) { - v->flags &= ~VOLUME_IS_DIRTY; - (void)ntfs_volume_write_flags(v, v->flags); - } - if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni)) - ntfs_inode_sync(v->lcnbmp_ni); - if (v->vol_ni) - ntfs_inode_close(v->vol_ni); - if (v->lcnbmp_na) - ntfs_attr_close(v->lcnbmp_na); - if (v->lcnbmp_ni) - ntfs_inode_close(v->lcnbmp_ni); - if (v->mft_ni && NInoDirty(v->mft_ni)) - ntfs_inode_sync(v->mft_ni); - if (v->mftbmp_na) - ntfs_attr_close(v->mftbmp_na); - if (v->mft_na) - ntfs_attr_close(v->mft_na); - if (v->mft_ni) - ntfs_inode_close(v->mft_ni); - if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni)) - ntfs_inode_sync(v->mftmirr_ni); - if (v->mftmirr_na) - ntfs_attr_close(v->mftmirr_na); - if (v->mftmirr_ni) - ntfs_inode_close(v->mftmirr_ni); - if (v->u.dev) { - struct ntfs_device *dev = v->u.dev; - - if (NDevDirty(dev)) - dev->d_ops->sync(dev); - if (dev->d_ops->close(dev)) - ntfs_log_perror("Failed to close the device"); - } - free(v->vol_name); - free(v->upcase); - free(v->attrdef); - free(v); -} - -/** - * ntfs_mft_load - load the $MFT and setup the ntfs volume with it - * @vol: ntfs volume whose $MFT to load - * - * Load $MFT from @vol and setup @vol with it. After calling this function the - * volume @vol is ready for use by all read access functions provided by the - * ntfs library. - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -static int ntfs_mft_load(ntfs_volume *vol) -{ - VCN next_vcn, last_vcn, highest_vcn; - s64 l; - MFT_RECORD *mb = NULL; - ntfs_attr_search_ctx *ctx = NULL; - ATTR_RECORD *a; - STANDARD_INFORMATION *std_info; - int eo; - - /* Manually setup an ntfs_inode. */ - vol->mft_ni = ntfs_inode_allocate(vol); - mb = (MFT_RECORD*)ntfs_malloc(vol->mft_record_size); - if (!vol->mft_ni || !mb) { - ntfs_log_perror("Error allocating memory for $MFT"); - goto error_exit; - } - vol->mft_ni->mft_no = 0; - vol->mft_ni->mrec = mb; - __ntfs_inode_add_to_cache(vol->mft_ni); - /* Can't use any of the higher level functions yet! */ - l = ntfs_mst_pread(vol->u.dev, vol->mft_lcn << vol->cluster_size_bits, 1, - vol->mft_record_size, mb); - if (l != 1) { - if (l != -1) - errno = EIO; - ntfs_log_perror("Error reading $MFT"); - goto error_exit; - } - if (ntfs_is_baad_record(mb->magic)) { - ntfs_log_error("Incomplete multi sector transfer detected in " - "$MFT.\n"); - goto io_error_exit; - } - if (!ntfs_is_mft_record(mb->magic)) { - ntfs_log_error("$MFT has invalid magic.\n"); - goto io_error_exit; - } - ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL); - if (!ctx) { - ntfs_log_perror("Failed to allocate attribute search context"); - goto error_exit; - } - if (p2n(ctx->attr) < p2n(mb) || - (char*)ctx->attr > (char*)mb + vol->mft_record_size) { - ntfs_log_error("$MFT is corrupt.\n"); - goto io_error_exit; - } - /* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */ - if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, - ctx)) { - if (errno != ENOENT) { - ntfs_log_error("$MFT has corrupt attribute list.\n"); - goto io_error_exit; - } - goto mft_has_no_attr_list; - } - NInoSetAttrList(vol->mft_ni); - l = ntfs_get_attribute_value_length(ctx->attr); - if (l <= 0 || l > 0x40000) { - ntfs_log_error("$MFT/$ATTRIBUTE_LIST has invalid length.\n"); - goto io_error_exit; - } - vol->mft_ni->attr_list_size = l; - vol->mft_ni->attr_list = ntfs_malloc(l); - if (!vol->mft_ni->attr_list) - goto error_exit; - - l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list); - if (!l) { - ntfs_log_error("Failed to get value of " - "$MFT/$ATTRIBUTE_LIST.\n"); - goto io_error_exit; - } - if (l != vol->mft_ni->attr_list_size) { - ntfs_log_error("Got unexpected amount of data when " - "reading $MFT/$ATTRIBUTE_LIST.\n"); - goto io_error_exit; - } -mft_has_no_attr_list: - /* Receive attributes from STANDARD_INFORMATION. */ - std_info = ntfs_attr_readall(vol->mft_ni, AT_STANDARD_INFORMATION, - AT_UNNAMED, 0, NULL); - vol->mft_ni->flags = std_info->file_attributes; - free(std_info); - - /* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */ - - /* Get an ntfs attribute for $MFT/$DATA and set it up, too. */ - vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); - if (!vol->mft_na) { - ntfs_log_perror("Failed to open ntfs attribute"); - goto error_exit; - } - /* Read all extents from the $DATA attribute in $MFT. */ - ntfs_attr_reinit_search_ctx(ctx); - last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits; - highest_vcn = next_vcn = 0; - a = NULL; - while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0, - ctx)) { - runlist_element *nrl; - - a = ctx->attr; - /* $MFT must be non-resident. */ - if (!a->non_resident) { - ntfs_log_error("$MFT must be non-resident but a " - "resident extent was found. $MFT is " - "corrupt. Run chkdsk.\n"); - goto io_error_exit; - } - /* $MFT must be uncompressed and unencrypted. */ - if (a->flags & ATTR_COMPRESSION_MASK || - a->flags & ATTR_IS_ENCRYPTED) { - ntfs_log_error("$MFT must be uncompressed and " - "unencrypted but a compressed/encrypted" - " extent was found. $MFT is corrupt. " - "Run chkdsk.\n"); - goto io_error_exit; - } - /* - * Decompress the mapping pairs array of this extent and merge - * the result into the existing runlist. No need for locking - * as we have exclusive access to the inode at this time and we - * are a mount in progress task, too. - */ - nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl); - if (!nrl) { - ntfs_log_perror("ntfs_mapping_pairs_decompress() " - "failed"); - goto error_exit; - } - vol->mft_na->rl = nrl; - - /* Get the lowest vcn for the next extent. */ - highest_vcn = sle64_to_cpu(a->u.nonres.highest_vcn); - next_vcn = highest_vcn + 1; - - /* Only one extent or error, which we catch below. */ - if (next_vcn <= 0) - break; - - /* Avoid endless loops due to corruption. */ - if (next_vcn < sle64_to_cpu(a->u.nonres.lowest_vcn)) { - ntfs_log_error("$MFT has corrupt attribute list " - "attribute. Run chkdsk.\n"); - goto io_error_exit; - } - } - if (!a) { - ntfs_log_error("$MFT/$DATA attribute not found. " - "$MFT is corrupt. Run chkdsk.\n"); - goto io_error_exit; - } - if (highest_vcn && highest_vcn != last_vcn - 1) { - ntfs_log_error("Failed to load the complete runlist for " - "$MFT/$DATA. Bug or corrupt $MFT. " - "Run chkdsk.\n highest_vcn = 0x%llx, " - "last_vcn - 1 = 0x%llx\n", (long long) - highest_vcn, (long long)last_vcn - 1); - goto io_error_exit; - } - /* Done with the $Mft mft record. */ - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - /* - * The volume is now setup so we can use all read access functions. - */ - vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0); - if (!vol->mftbmp_na) { - ntfs_log_perror("Failed to open $MFT/$BITMAP"); - goto error_exit; - } - return 0; -io_error_exit: - errno = EIO; -error_exit: - eo = errno; - if (ctx) - ntfs_attr_put_search_ctx(ctx); - if (vol->mft_na) { - ntfs_attr_close(vol->mft_na); - vol->mft_na = NULL; - } - if (vol->mft_ni) { - ntfs_inode_close(vol->mft_ni); - vol->mft_ni = NULL; - } - ntfs_log_error("%s(): Failed.\n", "ntfs_mft_load"); - errno = eo; - return -1; -} - -/** - * ntfs_mftmirr_load - load the $MFTMirr and setup the ntfs volume with it - * @vol: ntfs volume whose $MFTMirr to load - * - * Load $MFTMirr from @vol and setup @vol with it. After calling this function - * the volume @vol is ready for use by all write access functions provided by - * the ntfs library (assuming ntfs_mft_load() has been called successfully - * beforehand). - * - * Return 0 on success and -1 on error with errno set to the error code. - */ -static int ntfs_mftmirr_load(ntfs_volume *vol) -{ - int err; - - vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr); - if (!vol->mftmirr_ni) { - ntfs_log_perror("Failed to open inode $MFTMirr"); - return -1; - } - /* Get an ntfs attribute for $MFTMirr/$DATA, too. */ - vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, - AT_UNNAMED, 0); - if (!vol->mftmirr_na) { - ntfs_log_perror("Failed to open $MFTMirr/$DATA"); - goto error_exit; - } - if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) { - ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA"); - goto error_exit; - } - /* Check $MFTMirr runlist. */ - if (vol->mftmirr_na->rl[0].lcn != vol->mftmirr_lcn || - vol->mftmirr_na->rl[0].length < (vol->mftmirr_size * - vol->mft_record_size + vol->cluster_size - 1) / - vol->cluster_size) { - ntfs_log_error("$MFTMirr location mismatch or first 4 records " - "are fragmented. Run chkdsk.\n"); - errno = EIO; - goto error_exit; - - } - return 0; -error_exit: - err = errno; - if (vol->mftmirr_na) { - ntfs_attr_close(vol->mftmirr_na); - vol->mftmirr_na = NULL; - } - ntfs_inode_close(vol->mftmirr_ni); - vol->mftmirr_ni = NULL; - errno = err; - return -1; -} - -/** - * ntfs_volume_startup - allocate and setup an ntfs volume - * @dev: device to open - * @flags: optional mount flags - * - * Load, verify, and parse bootsector; load and setup $MFT and $MFTMirr. After - * calling this function, the volume is setup sufficiently to call all read - * and write access functions provided by the library. - * - * Return the allocated volume structure on success and NULL on error with - * errno set to the error code. - */ -ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, - ntfs_mount_flags flags) -{ - LCN mft_zone_size, mft_lcn; - s64 br; - ntfs_volume *vol; - NTFS_BOOT_SECTOR *bs; - int eo; -#ifdef DEBUG - const char *OK = "OK\n"; - const char *FAILED = "FAILED\n"; - BOOL debug = 1; -#else - BOOL debug = 0; -#endif - - if (!dev || !dev->d_ops || !dev->d_name) { - errno = EINVAL; - return NULL; - } - - if (!(bs = (NTFS_BOOT_SECTOR *)ntfs_malloc(sizeof(NTFS_BOOT_SECTOR)))) - return NULL; - - /* Allocate the volume structure. */ - vol = ntfs_volume_alloc(); - if (!vol) - goto error_exit; - /* Create the default upcase table. */ - vol->upcase_len = 65536; - vol->upcase = (ntfschar*)ntfs_malloc(vol->upcase_len * - sizeof(ntfschar)); - if (!vol->upcase) - goto error_exit; - ntfs_upcase_table_build(vol->upcase, - vol->upcase_len * sizeof(ntfschar)); - if (flags & NTFS_MNT_RDONLY) - NVolSetReadOnly(vol); - if (flags & NTFS_MNT_CASE_SENSITIVE) - NVolSetCaseSensitive(vol); - if (flags & NTFS_MNT_INTERIX) - NVolSetInterix(vol); - ntfs_log_debug("Reading bootsector... "); - if (dev->d_ops->open(dev, NVolReadOnly(vol) ? O_RDONLY : - ((flags & NTFS_MNT_NOT_EXCLUSIVE) ? O_RDWR : - (O_RDWR | O_EXCL)))) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Error opening partition device"); - goto error_exit; - } - /* Attach the device to the volume. */ - vol->u.dev = dev; - /* Now read the bootsector. */ - br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs); - if (br != sizeof(NTFS_BOOT_SECTOR)) { - ntfs_log_debug(FAILED); - if (br != -1) - errno = EINVAL; - if (!br) - ntfs_log_debug("Error: partition is smaller than " - "bootsector size. Weird!\n"); - else - ntfs_log_perror("Error reading bootsector"); - goto error_exit; - } - ntfs_log_debug(OK); - if (!ntfs_boot_sector_is_ntfs(bs, !debug)) { - ntfs_log_debug("Error: %s is not a valid NTFS partition!\n", - dev->d_name); - errno = EINVAL; - goto error_exit; - } - if (ntfs_boot_sector_parse(vol, bs) < 0) { - ntfs_log_perror("Failed to parse ntfs bootsector"); - goto error_exit; - } - free(bs); - bs = NULL; - /* Now set the device block size to the sector size. */ - if (ntfs_device_block_size_set(vol->u.dev, vol->sector_size)) - ntfs_log_debug("Failed to set the device block size to the " - "sector size. This may affect performance " - "but should be harmless otherwise. Error: " - "%s\n", strerror(errno)); - /* - * We now initialize the cluster allocator. - * - * FIXME: Move this to its own function? (AIA) - */ - - // TODO: Make this tunable at mount time. (AIA) - vol->mft_zone_multiplier = 1; - - /* Determine the size of the MFT zone. */ - mft_zone_size = vol->nr_clusters; - switch (vol->mft_zone_multiplier) { /* % of volume size in clusters */ - case 4: - mft_zone_size >>= 1; /* 50% */ - break; - case 3: - mft_zone_size = mft_zone_size * 3 >> 3; /* 37.5% */ - break; - case 2: - mft_zone_size >>= 2; /* 25% */ - break; - /* case 1: */ - default: - mft_zone_size >>= 3; /* 12.5% */ - break; - } - - /* Setup the mft zone. */ - vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn; - ntfs_log_debug("mft_zone_pos = 0x%llx\n", (long long)vol->mft_zone_pos); - - /* - * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs - * source) and if the actual mft_lcn is in the expected place or even - * further to the front of the volume, extend the mft_zone to cover the - * beginning of the volume as well. This is in order to protect the - * area reserved for the mft bitmap as well within the mft_zone itself. - * On non-standard volumes we don't protect it as the overhead would be - * higher than the speed increase we would get by doing it. - */ - mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size; - if (mft_lcn * vol->cluster_size < 16 * 1024) - mft_lcn = (16 * 1024 + vol->cluster_size - 1) / - vol->cluster_size; - if (vol->mft_zone_start <= mft_lcn) - vol->mft_zone_start = 0; - ntfs_log_debug("mft_zone_start = 0x%llx\n", - (long long)vol->mft_zone_start); - - /* - * Need to cap the mft zone on non-standard volumes so that it does - * not point outside the boundaries of the volume. We do this by - * halving the zone size until we are inside the volume. - */ - vol->mft_zone_end = vol->mft_lcn + mft_zone_size; - while (vol->mft_zone_end >= vol->nr_clusters) { - mft_zone_size >>= 1; - vol->mft_zone_end = vol->mft_lcn + mft_zone_size; - } - ntfs_log_debug("mft_zone_end = 0x%llx\n", (long long)vol->mft_zone_end); - - /* - * Set the current position within each data zone to the start of the - * respective zone. - */ - vol->data1_zone_pos = vol->mft_zone_end; - ntfs_log_debug("data1_zone_pos = 0x%llx\n", vol->data1_zone_pos); - vol->data2_zone_pos = 0; - ntfs_log_debug("data2_zone_pos = 0x%llx\n", vol->data2_zone_pos); - - /* Set the mft data allocation position to mft record 24. */ - vol->mft_data_pos = 24; - - /* - * The cluster allocator is now fully operational. - */ - - /* Need to setup $MFT so we can use the library read functions. */ - ntfs_log_debug("Loading $MFT... "); - if (ntfs_mft_load(vol) < 0) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to load $MFT"); - goto error_exit; - } - ntfs_log_debug(OK); - - /* Need to setup $MFTMirr so we can use the write functions, too. */ - ntfs_log_debug("Loading $MFTMirr... "); - if (ntfs_mftmirr_load(vol) < 0) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to load $MFTMirr"); - goto error_exit; - } - ntfs_log_debug(OK); - return vol; -error_exit: - eo = errno; - free(bs); - if (vol) - __ntfs_volume_release(vol); - errno = eo; - return NULL; -} - -/** - * ntfs_volume_check_logfile - check logfile on target volume - * @vol: volume on which to check logfile - * - * Return 0 on success and -1 on error with errno set error code. - */ -static int ntfs_volume_check_logfile(ntfs_volume *vol) -{ - ntfs_inode *ni; - ntfs_attr *na = NULL; - RESTART_PAGE_HEADER *rp = NULL; - int err = 0; - - if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) { - ntfs_log_debug("Failed to open inode FILE_LogFile.\n"); - errno = EIO; - return -1; - } - if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) { - ntfs_log_debug("Failed to open $FILE_LogFile/$DATA\n"); - err = EIO; - goto exit; - } - if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) - err = EOPNOTSUPP; - free(rp); -exit: - if (na) - ntfs_attr_close(na); - ntfs_inode_close(ni); - if (err) { - errno = err; - return -1; - } - return 0; -} - -/** - * ntfs_hiberfile_open - Find and open '/hiberfil.sys' - * @vol: An ntfs volume obtained from ntfs_mount - * - * Return: inode Success, hiberfil.sys is valid - * NULL hiberfil.sys doesn't exist or some other error occurred - */ -static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol) -{ - u64 inode; - ntfs_inode *ni_root; - ntfs_inode *ni_hibr = NULL; - ntfschar *unicode = NULL; - int unicode_len; - const char *hiberfile = "hiberfil.sys"; - - if (!vol) { - errno = EINVAL; - return NULL; - } - - ni_root = ntfs_inode_open(vol, FILE_root); - if (!ni_root) { - ntfs_log_debug("Couldn't open the root directory.\n"); - return NULL; - } - - unicode_len = ntfs_mbstoucs(hiberfile, &unicode, 0); - if (unicode_len < 0) { - ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode"); - goto out; - } - - inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len); - if (inode == (u64)-1) { - ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile); - goto out; - } - - inode = MREF(inode); - ni_hibr = ntfs_inode_open(vol, inode); - if (!ni_hibr) { - ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode); - goto out; - } -out: - ntfs_inode_close(ni_root); - free(unicode); - return ni_hibr; -} - - -#define NTFS_HIBERFILE_HEADER_SIZE 4096 - -/** - * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is - * hibernated on the target volume - * @vol: volume on which to check hiberfil.sys - * - * Return: 0 if Windows isn't hibernated for sure - * -1 otherwise and errno is set to the appropriate value - */ -static int ntfs_volume_check_hiberfile(ntfs_volume *vol) -{ - ntfs_inode *ni; - ntfs_attr *na = NULL; - int bytes_read, ret = -1; - char *buf = NULL; - - ni = ntfs_hiberfile_open(vol); - if (!ni) { - if (errno == ENOENT) - return 0; - return -1; - } - - buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE); - if (!buf) - goto out; - - na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); - if (!na) { - ntfs_log_perror("Failed to open hiberfil.sys data attribute"); - goto out; - } - - bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf); - if (bytes_read == -1) { - ntfs_log_perror("Failed to read hiberfil.sys"); - goto out; - } - if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) { - ntfs_log_debug("Hibernated non-system partition, refused to " - "mount!\n"); - errno = EPERM; - goto out; - } - if (memcmp(buf, "hibr", 4) == 0) { - ntfs_log_debug("Windows is hibernated, refused to mount!\n"); - errno = EPERM; - goto out; - } - ret = 0; -out: - if (na) - ntfs_attr_close(na); - free(buf); - ntfs_inode_close(ni); - return ret; -} - -/** - * ntfs_volume_get_nr_free_mft_records - calculate number of free MFT records - * vol: ntfs volume for which perform calculations. - * - * This function initializes @vol->nr_free_mft_records. @vol->mftbmp_na should - * be already opened upon call to this function. - * - * Return 0 on success. On error return -1 with errno set appropriately and - * @vol->nr_free_mft_records is not touched in this case. - */ -static int ntfs_volume_get_nr_free_mft_records(ntfs_volume *vol) -{ - long nr_free = vol->mft_na->data_size >> vol->mft_record_size_bits; - s64 br, total = 0; - u8 *buf; - - buf = ntfs_malloc(vol->cluster_size); - if (!buf) - return -1; - while (1) { - int i, j; - - br = ntfs_attr_pread(vol->mftbmp_na, total, - vol->cluster_size, buf); - if (br <= 0) - break; - total += br; - for (i = 0; i < br; i++) - for (j = 0; j < 8; j++) - if ((buf[i] >> j) & 1) - nr_free--; - } - free(buf); - if (!total || br < 0) { - ntfs_log_error("pread: %s\n", strerror(errno)); - return -1; - } - vol->nr_free_mft_records = nr_free; - return 0; -} - -/** - * ntfs_volume_get_nr_free_clusters - calculate number of free clusters - * vol: ntfs volume for which perform calculations. - * - * This function initializes @vol->nr_free_clusters. @vol->lcnbmp_na should be - * already opened upon call to this function. - * - * Return 0 on success. On error return -1 with errno set appropriately and - * @vol->nr_free_clusters is not touched in this case. - */ -static long ntfs_volume_get_nr_free_clusters(ntfs_volume *vol) -{ - long nr_free = vol->nr_clusters; - s64 br, total = 0; - u8 *buf; - - buf = ntfs_malloc(vol->cluster_size); - if (!buf) - return -1; - while (1) { - int i, j; - - br = ntfs_attr_pread(vol->lcnbmp_na, total, - vol->cluster_size, buf); - if (br <= 0) - break; - total += br; - for (i = 0; i < br; i++) - for (j = 0; j < 8; j++) - if ((buf[i] >> j) & 1) - nr_free--; - } - free(buf); - if (!total || br < 0) { - ntfs_log_error("pread: %s\n", strerror(errno)); - return -1; - } - vol->nr_free_clusters = nr_free; - return 0; -} - -/** - * ntfs_device_mount - open ntfs volume - * @dev: device to open - * @flags: optional mount flags - * - * This function mounts an ntfs volume. @dev should describe the device which - * to mount as the ntfs volume. - * - * @flags is an optional second parameter. Some flags are similar to flags used - * as for the mount system call (man 2 mount). Currently the following flags - * are implemented: - * NTFS_MNT_RDONLY - mount volume read-only - * NTFS_MNT_CASE_SENSITIVE - treat filenames as case sensitive even if - * they are not in POSIX namespace - * NTFS_MNT_NOT_EXCLUSIVE - (unix only) do not open volume exclusively - * NTFS_MNT_FORENSIC - mount for forensic purposes, i.e. do not do - * any writing at all during the mount, i.e. no - * journal emptying, no dirty bit setting, etc. - * NTFS_MNT_INTERIX - make libntfs recognize special Interix files - * - * The function opens the device @dev and verifies that it contains a valid - * bootsector. Then, it allocates an ntfs_volume structure and initializes - * some of the values inside the structure from the information stored in the - * bootsector. It proceeds to load the necessary system files and completes - * setting up the structure. - * - * Return the allocated volume structure on success and NULL on error with - * errno set to the error code. - */ -ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) -{ - s64 l; -#ifdef DEBUG - const char *OK = "OK\n"; - const char *FAILED = "FAILED\n"; -#endif - ntfs_volume *vol; - u8 *m = NULL, *m2 = NULL; - ntfs_attr_search_ctx *ctx = NULL; - ntfs_inode *ni; - ntfs_attr *na; - ATTR_RECORD *a; - VOLUME_INFORMATION *vinf; - ntfschar *vname; - int i, j, eo; - u32 u; - - vol = ntfs_volume_startup(dev, flags); - if (!vol) { - ntfs_log_perror("Failed to startup volume"); - return NULL; - } - /* Record whether this is a forensic mount. */ - if (flags & NTFS_MNT_FORENSIC) - NVolSetForensicMount(vol); - /* Load data from $MFT and $MFTMirr and compare the contents. */ - m = (u8*)ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits); - m2 = (u8*)ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits); - if (!m || !m2) - goto error_exit; - - l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size, - vol->mft_record_size, m); - if (l != vol->mftmirr_size) { - if (l == -1) - ntfs_log_perror("Failed to read $MFT"); - else { - ntfs_log_debug("Failed to read $MFT, unexpected length " - "(%d != %lld).\n", vol->mftmirr_size, l); - errno = EIO; - } - goto error_exit; - } - l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size, - vol->mft_record_size, m2); - if (l != vol->mftmirr_size) { - if (l == -1) - ntfs_log_perror("Failed to read $MFTMirr"); - else { - ntfs_log_debug("Failed to read $MFTMirr, unexpected " - "length (%d != %lld).\n", - vol->mftmirr_size, l); - errno = EIO; - } - goto error_exit; - } - ntfs_log_debug("Comparing $MFTMirr to $MFT... "); - for (i = 0; i < vol->mftmirr_size; ++i) { - MFT_RECORD *mrec, *mrec2; - const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", - "$Volume", "$AttrDef", "root directory", "$Bitmap", - "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" }; - const char *s; - - if (i < 12) - s = ESTR[i]; - else if (i < 16) - s = "system file"; - else - s = "mft record"; - - mrec = (MFT_RECORD*)(m + i * vol->mft_record_size); - if (mrec->flags & MFT_RECORD_IN_USE) { - if (ntfs_is_baad_record(mrec->magic)) { - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("$MFT error: Incomplete multi " - "sector transfer detected in " - "%s.\n", s); - goto io_error_exit; - } - if (!ntfs_is_mft_record(mrec->magic)) { - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("$MFT error: Invalid mft " - "record for %s.\n", s); - goto io_error_exit; - } - } - mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size); - if (mrec2->flags & MFT_RECORD_IN_USE) { - if (ntfs_is_baad_record(mrec2->magic)) { - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("$MFTMirr error: Incomplete " - "multi sector transfer " - "detected in %s.\n", s); - goto io_error_exit; - } - if (!ntfs_is_mft_record(mrec2->magic)) { - ntfs_log_debug("FAILED\n"); - ntfs_log_debug("$MFTMirr error: Invalid mft " - "record for %s.\n", s); - goto io_error_exit; - } - } - if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) { - ntfs_log_debug(FAILED); - ntfs_log_debug("$MFTMirr does not match $MFT. Run " - "chkdsk.\n"); - goto io_error_exit; - } - } - ntfs_log_debug(OK); - - free(m2); - free(m); - m = m2 = NULL; - - /* Now load the bitmap from $Bitmap. */ - ntfs_log_debug("Loading $Bitmap... "); - vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap); - if (!vol->lcnbmp_ni) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open inode"); - goto error_exit; - } - /* Get an ntfs attribute for $Bitmap/$DATA. */ - vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); - if (!vol->lcnbmp_na) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open ntfs attribute"); - goto error_exit; - } - /* Done with the $Bitmap mft record. */ - ntfs_log_debug(OK); - - /* Now load the upcase table from $UpCase. */ - ntfs_log_debug("Loading $UpCase... "); - ni = ntfs_inode_open(vol, FILE_UpCase); - if (!ni) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open inode"); - goto error_exit; - } - /* Get an ntfs attribute for $UpCase/$DATA. */ - na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); - if (!na) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open ntfs attribute"); - goto error_exit; - } - /* - * Note: Normally, the upcase table has a length equal to 65536 - * 2-byte Unicode characters but allow for different cases, so no - * checks done. Just check we don't overflow 32-bits worth of Unicode - * characters. - */ - if (na->data_size & ~0x1ffffffffULL) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Upcase table is too big (max 32-bit " - "allowed).\n"); - errno = EINVAL; - goto error_exit; - } - if (vol->upcase_len != na->data_size >> 1) { - vol->upcase_len = na->data_size >> 1; - /* Throw away default table. */ - free(vol->upcase); - vol->upcase = (ntfschar*)ntfs_malloc(na->data_size); - if (!vol->upcase) { - ntfs_log_debug(FAILED); - goto error_exit; - } - } - /* Read in the $DATA attribute value into the buffer. */ - l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase); - if (l != na->data_size) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Amount of data read does not correspond to " - "expected length!\n"); - errno = EIO; - goto error_exit; - } - /* Done with the $UpCase mft record. */ - ntfs_log_debug(OK); - ntfs_attr_close(na); - if (ntfs_inode_close(ni)) - ntfs_log_perror("Failed to close inode, leaking memory"); - - /* - * Now load $Volume and set the version information and flags in the - * vol structure accordingly. - */ - ntfs_log_debug("Loading $Volume... "); - vol->vol_ni = ntfs_inode_open(vol, FILE_Volume); - if (!vol->vol_ni) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open inode"); - goto error_exit; - } - /* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */ - ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); - if (!ctx) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to allocate attribute search context"); - goto error_exit; - } - /* Find the $VOLUME_INFORMATION attribute. */ - if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, - 0, ctx)) { - ntfs_log_debug(FAILED); - ntfs_log_debug("$VOLUME_INFORMATION attribute not found in " - "$Volume?!?\n"); - goto error_exit; - } - a = ctx->attr; - /* Has to be resident. */ - if (a->non_resident) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION must be " - "resident (and it isn't)!\n"); - errno = EIO; - goto error_exit; - } - /* Get a pointer to the value of the attribute. */ - vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->u.res.value_offset) + (char*)a); - /* Sanity checks. */ - if ((char*)vinf + le32_to_cpu(a->u.res.value_length) > (char*)ctx->mrec + - le32_to_cpu(ctx->mrec->bytes_in_use) || - le16_to_cpu(a->u.res.value_offset) + le32_to_cpu( - a->u.res.value_length) > le32_to_cpu(a->length)) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Attribute $VOLUME_INFORMATION in " - "$Volume is corrupt!\n"); - errno = EIO; - goto error_exit; - } - /* Setup vol from the volume information attribute value. */ - vol->major_ver = vinf->major_ver; - vol->minor_ver = vinf->minor_ver; - /* - * Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are defined - * using cpu_to_le16() macro and hence are consistent. - */ - vol->flags = vinf->flags; - /* Record whether the volume was dirty or not. */ - if (vol->flags & VOLUME_IS_DIRTY) - NVolSetWasDirty(vol); - /* - * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup. - */ - ntfs_attr_reinit_search_ctx(ctx); - if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, - ctx)) { - if (errno != ENOENT) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Lookup of $VOLUME_NAME " - "attribute in $Volume failed. " - "This probably means something is " - "corrupt. Run chkdsk.\n"); - goto error_exit; - } - /* - * Attribute not present. This has been seen in the field. - * Treat this the same way as if the attribute was present but - * had zero length. - */ - vol->vol_name = ntfs_malloc(1); - if (!vol->vol_name) { - ntfs_log_debug(FAILED); - goto error_exit; - } - vol->vol_name[0] = '\0'; - } else { - a = ctx->attr; - /* Has to be resident. */ - if (a->non_resident) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Attribute $VOLUME_NAME must be " - "resident!\n"); - errno = EIO; - goto error_exit; - } - /* Get a pointer to the value of the attribute. */ - vname = (ntfschar*)(le16_to_cpu(a->u.res.value_offset) + (char*)a); - u = le32_to_cpu(a->u.res.value_length) / 2; - /* - * Convert Unicode volume name to current locale multibyte - * format. - */ - vol->vol_name = NULL; - if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) { - ntfs_log_perror("Error: Volume name could not be " - "converted to current locale"); - ntfs_log_debug("Forcing name into ASCII by replacing " - "non-ASCII characters with underscores.\n"); - vol->vol_name = ntfs_malloc(u + 1); - if (!vol->vol_name) { - ntfs_log_debug(FAILED); - goto error_exit; - } - for (j = 0; j < (s32)u; j++) { - u16 uc = le16_to_cpu(vname[j]); - if (uc > 0xff) - uc = (u16)'_'; - vol->vol_name[j] = (char)uc; - } - vol->vol_name[u] = 0; - } - } - ntfs_log_debug(OK); - ntfs_attr_put_search_ctx(ctx); - ctx = NULL; - /* Now load the attribute definitions from $AttrDef. */ - ntfs_log_debug("Loading $AttrDef... "); - ni = ntfs_inode_open(vol, FILE_AttrDef); - if (!ni) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open inode"); - goto error_exit; - } - /* Get an ntfs attribute for $AttrDef/$DATA. */ - na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); - if (!na) { - ntfs_log_debug(FAILED); - ntfs_log_perror("Failed to open ntfs attribute"); - goto error_exit; - } - /* Check we don't overflow 32-bits. */ - if (na->data_size > 0xffffffffLL) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Error: Attribute definition table is too big " - "(max 32-bit allowed).\n"); - errno = EINVAL; - goto error_exit; - } - vol->attrdef_len = na->data_size; - vol->attrdef = (ATTR_DEF*)ntfs_malloc(na->data_size); - if (!vol->attrdef) { - ntfs_log_debug(FAILED); - goto error_exit; - } - /* Read in the $DATA attribute value into the buffer. */ - l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef); - if (l != na->data_size) { - ntfs_log_debug(FAILED); - ntfs_log_debug("Amount of data read does not correspond to " - "expected length!\n"); - errno = EIO; - goto error_exit; - } - /* Done with the $AttrDef mft record. */ - ntfs_log_debug(OK); - ntfs_attr_close(na); - if (ntfs_inode_close(ni)) - ntfs_log_perror("Failed to close inode, leaking memory"); - /* Initialize number of free clusters and MFT records. */ - if (ntfs_volume_get_nr_free_mft_records(vol)) { - ntfs_log_perror("Failed to calculate number of free MFTs"); - goto error_exit; - } - if (ntfs_volume_get_nr_free_clusters(vol)) { - ntfs_log_perror("Failed to calculate number of free clusters"); - goto error_exit; - } - /* - * Check for dirty logfile and hibernated Windows. - * We care only about read-write mounts. - * - * If all is ok, reset the logfile and set the dirty bit on the volume. - * - * But do not do that if this is a FORENSIC mount. - */ - if (!(flags & NTFS_MNT_RDONLY)) { - if (ntfs_volume_check_hiberfile(vol) < 0) - goto error_exit; - if (ntfs_volume_check_logfile(vol) < 0) { - if (errno != EOPNOTSUPP || !(flags & NTFS_MNT_FORCE)) - goto error_exit; - ntfs_log_warning("WARNING: $LogFile is not clean, " - "forced to continue.\n"); - NVolSetWasDirty(vol); /* Leave volume dirty since we - empted logfile. */ - } - if (!NVolForensicMount(vol)) { - if (ntfs_logfile_reset(vol) < 0) - goto error_exit; - if (!(vol->flags & VOLUME_IS_DIRTY)) { - vol->flags |= VOLUME_IS_DIRTY; - if (ntfs_volume_write_flags(vol, vol->flags) < - 0) - goto error_exit; - } - } - } - return vol; -io_error_exit: - errno = EIO; -error_exit: - eo = errno; - if (ctx) - ntfs_attr_put_search_ctx(ctx); - free(m); - free(m2); - __ntfs_volume_release(vol); - errno = eo; - return NULL; -} - -/** - * ntfs_mount - open ntfs volume - * @name: name of device/file to open - * @flags: optional mount flags - * - * This function mounts an ntfs volume. @name should contain the name of the - * device/file to mount as the ntfs volume. - * - * @flags is an optional second parameter. See ntfs_device_mount comment for - * description. - * - * The function opens the device or file @name and verifies that it contains a - * valid bootsector. Then, it allocates an ntfs_volume structure and initializes - * some of the values inside the structure from the information stored in the - * bootsector. It proceeds to load the necessary system files and completes - * setting up the structure. - * - * Return the allocated volume structure on success and NULL on error with - * errno set to the error code. - * - * Note, that a copy is made of @name, and hence it can be discarded as - * soon as the function returns. - */ -ntfs_volume *ntfs_mount(const char *name __attribute__((unused)), - ntfs_mount_flags flags __attribute__((unused))) -{ -#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS - struct ntfs_device *dev; - ntfs_volume *vol; - - /* Allocate an ntfs_device structure. */ - dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL); - if (!dev) - return NULL; - /* Call ntfs_device_mount() to do the actual mount. */ - vol = ntfs_device_mount(dev, flags); - if (!vol) { - int eo = errno; - ntfs_device_free(dev); - errno = eo; - } - return vol; -#else - /* - * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is - * defined as there are no device operations available in libntfs in - * this case. - */ - errno = EOPNOTSUPP; - return NULL; -#endif -} - -/** - * ntfs_device_umount - close ntfs volume - * @vol: address of ntfs_volume structure of volume to close - * @force: if true force close the volume even if it is busy - * - * Deallocate all structures (including @vol itself) associated with the ntfs - * volume @vol. - * - * Note it is up to the caller to destroy the device associated with the volume - * being unmounted after this function returns. - * - * Return 0 on success. On error return -1 with errno set appropriately - * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that - * an operation is in progress and if you try the close later the operation - * might be completed and the close succeed. - * - * If @force is true (i.e. not zero) this function will close the volume even - * if this means that data might be lost. - * - * @vol must have previously been returned by a call to ntfs_device_mount(). - * - * @vol itself is deallocated and should no longer be dereferenced after this - * function returns success. If it returns an error then nothing has been done - * so it is safe to continue using @vol. - */ -int ntfs_device_umount(ntfs_volume *vol, - const BOOL force __attribute__((unused))) -{ - if (!vol) { - errno = EINVAL; - return -1; - } - __ntfs_volume_release(vol); - return 0; -} - -/** - * ntfs_umount - close ntfs volume - * @vol: address of ntfs_volume structure of volume to close - * @force: if true force close the volume even if it is busy - * - * Deallocate all structures (including @vol itself) associated with the ntfs - * volume @vol. - * - * Return 0 on success. On error return -1 with errno set appropriately - * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that - * an operation is in progress and if you try the close later the operation - * might be completed and the close succeed. - * - * If @force is true (i.e. not zero) this function will close the volume even - * if this means that data might be lost. - * - * @vol must have previously been returned by a call to ntfs_mount(). - * - * @vol itself is deallocated and should no longer be dereferenced after this - * function returns success. If it returns an error then nothing has been done - * so it is safe to continue using @vol. - */ -int ntfs_umount(ntfs_volume *vol, - const BOOL force __attribute__((unused))) -{ - struct ntfs_device *dev; - - if (!vol) { - errno = EINVAL; - return -1; - } - dev = vol->u.dev; - __ntfs_volume_release(vol); - ntfs_device_free(dev); - return 0; -} - -#ifdef HAVE_MNTENT_H - -#ifndef HAVE_REALPATH -/** - * realpath - If there is no realpath on the system - */ -static char *realpath(const char *path, char *resolved_path) -{ - strncpy(resolved_path, path, PATH_MAX); - resolved_path[PATH_MAX] = '\0'; - return resolved_path; -} -#endif - -/** - * ntfs_mntent_check - desc - * - * If you are wanting to use this, you actually wanted to use - * ntfs_check_if_mounted(), you just didn't realize. (-: - * - * See description of ntfs_check_if_mounted(), below. - */ -static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags) -{ - struct mntent *mnt; - char *real_file = NULL, *real_fsname = NULL; - FILE *f; - int err = 0; - - real_file = ntfs_malloc(PATH_MAX + 1); - if (!real_file) - return -1; - real_fsname = ntfs_malloc(PATH_MAX + 1); - if (!real_fsname) { - err = errno; - goto exit; - } - if (!realpath(file, real_file)) { - err = errno; - goto exit; - } - if (!(f = setmntent(MOUNTED, "r"))) { - err = errno; - goto exit; - } - while ((mnt = getmntent(f))) { - if (!realpath(mnt->mnt_fsname, real_fsname)) - continue; - if (!strcmp(real_file, real_fsname)) - break; - } - endmntent(f); - if (!mnt) - goto exit; - *mnt_flags = NTFS_MF_MOUNTED; - if (!strcmp(mnt->mnt_dir, "/")) - *mnt_flags |= NTFS_MF_ISROOT; -#ifdef HAVE_HASMNTOPT - if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw")) - *mnt_flags |= NTFS_MF_READONLY; -#endif -exit: - free(real_file); - free(real_fsname); - if (err) { - errno = err; - return -1; - } - return 0; -} -#endif /* HAVE_MNTENT_H */ - -/** - * ntfs_check_if_mounted - check if an ntfs volume is currently mounted - * @file: device file to check - * @mnt_flags: pointer into which to return the ntfs mount flags (see volume.h) - * - * If the running system does not support the {set,get,end}mntent() calls, - * just return 0 and set *@mnt_flags to zero. - * - * When the system does support the calls, ntfs_check_if_mounted() first tries - * to find the device @file in /etc/mtab (or wherever this is kept on the - * running system). If it is not found, assume the device is not mounted and - * return 0 and set *@mnt_flags to zero. - * - * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags. - * - * Further if @file is mounted as the file system root ("/"), set the flag - * NTFS_MF_ISROOT in *@mnt_flags. - * - * Finally, check if the file system is mounted read-only, and if so set the - * NTFS_MF_READONLY flag in *@mnt_flags. - * - * On success return 0 with *@mnt_flags set to the ntfs mount flags. - * - * On error return -1 with errno set to the error code. - */ -int ntfs_check_if_mounted(const char *file __attribute__((unused)), - unsigned long *mnt_flags) -{ - *mnt_flags = 0; -#ifdef HAVE_MNTENT_H - return ntfs_mntent_check(file, mnt_flags); -#else - return 0; -#endif -} - -/** - * ntfs_version_is_supported - check if NTFS version is supported. - * @vol: ntfs volume whose version we're interested in. - * - * The function checks if the NTFS volume version is known or not. - * Version 1.1 and 1.2 are used by Windows NT3.x and NT4. - * Version 2.x is used by Windows 2000 Betas. - * Version 3.0 is used by Windows 2000. - * Version 3.1 is used by Windows XP, Windows Server 2003 and Vista. - * - * Return 0 if NTFS version is supported otherwise -1 with errno set. - * - * The following error codes are defined: - * EOPNOTSUPP - Unknown NTFS version - * EINVAL - Invalid argument - */ -int ntfs_version_is_supported(ntfs_volume *vol) -{ - u8 major, minor; - - if (!vol) { - errno = EINVAL; - return -1; - } - - major = vol->major_ver; - minor = vol->minor_ver; - - if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor)) - return 0; - - if (NTFS_V2_X(major, minor)) - return 0; - - if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor)) - return 0; - - errno = EOPNOTSUPP; - return -1; -} - -/** - * ntfs_logfile_reset - "empty" $LogFile data attribute value - * @vol: ntfs volume whose $LogFile we intend to reset. - * - * Fill the value of the $LogFile data attribute, i.e. the contents of - * the file, with 0xff's, thus marking the journal as empty. - * - * FIXME(?): We might need to zero the LSN field of every single mft - * record as well. (But, first try without doing that and see what - * happens, since chkdsk might pickup the pieces and do it for us...) - * - * On success return 0. - * - * On error return -1 with errno set to the error code. - */ -int ntfs_logfile_reset(ntfs_volume *vol) -{ - ntfs_inode *ni; - ntfs_attr *na; - int eo; - - if (!vol) { - errno = EINVAL; - return -1; - } - - if ((ni = ntfs_inode_open(vol, FILE_LogFile)) == NULL) { - ntfs_log_perror("Failed to open inode FILE_LogFile."); - return -1; - } - - if ((na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0)) == NULL) { - eo = errno; - ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); - goto error_exit; - } - - if (ntfs_empty_logfile(na)) { - eo = errno; - ntfs_log_perror("Failed to empty $FILE_LogFile/$DATA"); - ntfs_attr_close(na); - goto error_exit; - } - ntfs_attr_close(na); - return ntfs_inode_close(ni); - -error_exit: - ntfs_inode_close(ni); - errno = eo; - return -1; -} - -/** - * ntfs_volume_write_flags - set the flags of an ntfs volume - * @vol: ntfs volume where we set the volume flags - * @flags: new flags - * - * Set the on-disk volume flags in the mft record of $Volume and - * on volume @vol to @flags. - * - * Return 0 if successful and -1 if not with errno set to the error code. - */ -int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags) -{ - ATTR_RECORD *a; - VOLUME_INFORMATION *c; - ntfs_attr_search_ctx *ctx; - int ret = -1; /* failure */ - - if (!vol || !vol->vol_ni) { - errno = EINVAL; - return -1; - } - /* Get a pointer to the volume information attribute. */ - ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); - if (!ctx) { - ntfs_log_perror("Failed to allocate attribute search context"); - return -1; - } - if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, - 0, ctx)) { - ntfs_log_error("Attribute $VOLUME_INFORMATION was not found " - "in $Volume!\n"); - goto err_out; - } - a = ctx->attr; - /* Sanity check. */ - if (a->non_resident) { - ntfs_log_error("Attribute $VOLUME_INFORMATION must be " - "resident (and it isn't)!\n"); - errno = EIO; - goto err_out; - } - /* Get a pointer to the value of the attribute. */ - c = (VOLUME_INFORMATION*)(le16_to_cpu(a->u.res.value_offset) + (char*)a); - /* Sanity checks. */ - if ((char*)c + le32_to_cpu(a->u.res.value_length) > (char*)ctx->mrec + - le32_to_cpu(ctx->mrec->bytes_in_use) || - le16_to_cpu(a->u.res.value_offset) + - le32_to_cpu(a->u.res.value_length) > le32_to_cpu(a->length)) { - ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is " - "corrupt!\n"); - errno = EIO; - goto err_out; - } - /* Set the volume flags. */ - vol->flags = c->flags = flags & VOLUME_FLAGS_MASK; - /* Write them to disk. */ - ntfs_inode_mark_dirty(vol->vol_ni); - if (ntfs_inode_sync(vol->vol_ni)) { - ntfs_log_perror("Error writing $Volume"); - goto err_out; - } - ret = 0; /* success */ -err_out: - ntfs_attr_put_search_ctx(ctx); - if (ret) - ntfs_log_error("%s(): Failed.\n", "ntfs_volume_write_flags"); - return ret; -} - diff --git a/usr/src/lib/libntfs/common/mapfile-vers b/usr/src/lib/libntfs/common/mapfile-vers deleted file mode 100644 index f0e4c9f3d4..0000000000 --- a/usr/src/lib/libntfs/common/mapfile-vers +++ /dev/null @@ -1,134 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -SYMBOL_VERSION SUNW_10.1 { - global: - AT_UNNAMED; - NTFS_INDEX_I30; - NTFS_INDEX_O; - NTFS_INDEX_Q; - NTFS_INDEX_R; - NTFS_INDEX_SDH; - NTFS_INDEX_SII; - ntfs_attr_add; - ntfs_attr_close; - ntfs_attr_find_in_attrdef; - ntfs_attr_get_search_ctx; - ntfs_attr_lookup; - ntfs_attr_mst_pread; - ntfs_attr_open; - ntfs_attr_pread; - ntfs_attr_put_search_ctx; - ntfs_attr_pwrite; - ntfs_attr_readall; - __ntfs_attr_truncate; - ntfs_boot_sector_is_ntfs; - ntfs_calloc; - ntfs_check_if_mounted; - ntfs_cluster_read; - ntfs_create; - ntfs_device_alloc; - ntfs_device_block_size_set; - ntfs_device_free; - ntfs_device_heads_get; - ntfs_device_partition_start_sector_get; - ntfs_device_sector_size_get; - ntfs_device_sectors_per_track_get; - ntfs_device_size_get; - ntfs_device_unix_io_ops; - ntfs_file_record_read; - ntfs_file_record_read; - ntfs_file_values_compare; - ntfs_get_attribute_value; - ntfs_get_attribute_value_length; - ntfs_get_size_for_mapping_pairs; - ntfs_guid_is_zero; - ntfs_guid_to_mbs; - ntfs_ie_get_vcn; - ntfs_index_root_get; - ntfs_inode_badclus_bad; - ntfs_inode_close; - ntfs_inode_open; - ntfs_inode_sync; - ntfs_libntfs_version; - ntfs_log_clear_levels; - ntfs_logfile_reset; - ntfs_log_get_levels; - ntfs_log_handler_outerr; - ntfs_log_handler_stderr; - ntfs_log_parse_option; - ntfs_log_redirect; - ntfs_log_set_handler; - ntfs_log_set_levels; - ntfs_malloc; - ntfs_mapping_pairs_build; - ntfs_mapping_pairs_decompress; - ntfs_mbstoucs; - ntfs_mft_record_layout; - ntfs_mft_records_write; - ntfs_mft_usn_dec; - ntfs_mount; - ntfs_mst_post_read_fixup; - ntfs_mst_post_write_fixup; - ntfs_mst_pre_write_fixup; - ntfs_mst_pwrite; - ntfs_names_are_equal; - ntfs_names_collate; - ntfs_pathname_to_inode; - ntfs_readdir; - ntfs_resident_attr_value_resize; - ntfs_rl_pread; - ntfs_rl_pwrite; - ntfs_rl_truncate; - ntfs_rl_vcn_to_lcn; - ntfs_sid_to_mbs; - ntfs_str2ucs; - ntfs_ucsfree; - ntfs_ucsnlen; - ntfs_ucstombs; - ntfs_umount; - ntfs_upcase_table_build; - ntfs_version_is_supported; - ntfs_volume_alloc; - ntfs_volume_startup; - ntfs_volume_write_flags; - local: - *; -}; diff --git a/usr/src/lib/libparted/COPYING b/usr/src/lib/libparted/COPYING deleted file mode 100644 index 4432540474..0000000000 --- a/usr/src/lib/libparted/COPYING +++ /dev/null @@ -1,676 +0,0 @@ - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. - diff --git a/usr/src/lib/libparted/Makefile b/usr/src/lib/libparted/Makefile deleted file mode 100644 index 7f0541d81c..0000000000 --- a/usr/src/lib/libparted/Makefile +++ /dev/null @@ -1,110 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -include ../Makefile.lib - -SUBDIRS = $(MACH) - -all := TARGET= all -clean := TARGET= clean -clobber := TARGET= clobber -delete := TARGET= delete -install := TARGET= install -_msg := TARGET= _msg -package := TARGET= package - -LIBRARY= libparted.a -TEXT_DOMAIN= SUNW_OST_OSLIB -XGETFLAGS= -a -POFILE= $(LIBRARY:.a=.po) -POFILES= generic.po - -SED= sed -GREP= grep - -# definitions for install_h target -HDRDIR= common/include/parted -HDRS= constraint.h \ - crc32.h \ - debug.h \ - device.h \ - disk.h \ - endian.h \ - exception.h \ - filesys.h \ - geom.h \ - natmath.h \ - parted.h \ - solaris.h \ - timer.h \ - unit.h -ROOTHDRDIR= $(ROOT)/usr/include/parted -ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%) - -.KEEP_STATE: - -all clean clobber delete install package: $(SUBDIRS) - -all install: THIRDPARTYLICENSE - -CLOBBERFILES += THIRDPARTYLICENSE - -THIRDPARTYLICENSE: $(SRC)/common/GPLDISCLAIMER COPYING - $(RM) $@ - $(CAT) $(SRC)/common/GPLDISCLAIMER COPYING > $@ - -install_h: $(ROOTHDRDIR) $(ROOTHDRS) - -$(ROOTHDRDIR): - $(INS.dir) - -# -# This open source is exempt from check -# -check: - -$(SUBDIRS): FRC - @cd $@; pwd; $(MAKE) $(TARGET) - -_msg: $(MSGDOMAIN) $(POFILE) - $(RM) $(MSGDOMAIN)/$(POFILE) - $(CP) $(POFILE) $(MSGDOMAIN) - -$(POFILE): $(POFILES) - $(RM) $@ - $(CAT) $(POFILES) > $@ - -$(POFILES): - $(RM) messages.po - $(XGETTEXT) $(XGETFLAGS) *.[ch]* */*.[ch]* - $(SED) -e '/^# msg/d' -e '/^domain/d' messages.po > $@ - $(RM) messages.po - -$(MSGDOMAIN): - $(INS.dir) - -FRC: - -include ../Makefile.targ diff --git a/usr/src/lib/libparted/Makefile.com b/usr/src/lib/libparted/Makefile.com deleted file mode 100644 index 2d79d23cc4..0000000000 --- a/usr/src/lib/libparted/Makefile.com +++ /dev/null @@ -1,132 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -LIBRARY= libparted.a -VERS= .8 - -# -# All relative to SRCDIR -# - -PLIBDIR= lib -LIBPDIR= libparted -LIBPADIR= libparted/arch -LIBPCSDIR= libparted/cs -LIBAMIGAFS= libparted/fs/amiga -LIBEXT2FS= libparted/fs/ext2 -LIBFATFS= libparted/fs/fat -LIBHFS= libparted/fs/hfs -LIBJFS= libparted/fs/jfs -LIBLINUXSWAP= libparted/fs/linux_swap -LIBNTFS= libparted/fs/ntfs -LIBREISERFS= libparted/fs/reiserfs -LIBSOLARISX86= libparted/fs/solaris_x86 -LIBUFS= libparted/fs/ufs -LIBXFS= libparted/fs/xfs -LIBLABELS= libparted/labels - -OBJECTS= $(PLIBDIR)/basename.o $(PLIBDIR)/quotearg.o \ - $(PLIBDIR)/close-stream.o $(PLIBDIR)/regex.o \ - $(PLIBDIR)/closeout.o $(PLIBDIR)/rpmatch.o \ - $(PLIBDIR)/dirname.o $(PLIBDIR)/safe-read.o \ - $(PLIBDIR)/error.o $(PLIBDIR)/safe-write.o \ - $(PLIBDIR)/exitfail.o $(PLIBDIR)/strcspn.o \ - $(PLIBDIR)/full-write.o $(PLIBDIR)/stripslash.o \ - $(PLIBDIR)/getopt.o $(PLIBDIR)/strndup.o \ - $(PLIBDIR)/version-etc-fsf.o \ - $(PLIBDIR)/localcharset.o $(PLIBDIR)/version-etc.o \ - $(PLIBDIR)/long-options.o $(PLIBDIR)/xalloc-die.o \ - $(PLIBDIR)/memcpy.o $(PLIBDIR)/xmalloc.o \ - $(PLIBDIR)/memmove.o $(PLIBDIR)/xstrndup.o \ - $(PLIBDIR)/memset.o \ - $(LIBPDIR)/debug.o $(LIBPDIR)/exception.o \ - $(LIBPDIR)/device.o $(LIBPDIR)/filesys.o \ - $(LIBPDIR)/timer.o $(LIBPDIR)/unit.o \ - $(LIBPDIR)/disk.o $(LIBPDIR)/libparted.o \ - $(LIBPADIR)/solaris.o \ - $(LIBPCSDIR)/constraint.o $(LIBPCSDIR)/geom.o \ - $(LIBPCSDIR)/natmath.o \ - $(LIBAMIGAFS)/affs.o $(LIBAMIGAFS)/amiga.o \ - $(LIBAMIGAFS)/apfs.o $(LIBAMIGAFS)/asfs.o \ - $(LIBAMIGAFS)/interface.o \ - $(LIBEXT2FS)/interface.o $(LIBEXT2FS)/ext2.o \ - $(LIBEXT2FS)/ext2_inode_relocator.o \ - $(LIBEXT2FS)/parted_io.o $(LIBEXT2FS)/ext2_meta.o \ - $(LIBEXT2FS)/ext2_block_relocator.o \ - $(LIBEXT2FS)/ext2_mkfs.o $(LIBEXT2FS)/tune.o \ - $(LIBEXT2FS)/ext2_buffer.o $(LIBEXT2FS)/ext2_resize.o \ - $(LIBFATFS)/table.o $(LIBFATFS)/bootsector.o \ - $(LIBFATFS)/clstdup.o $(LIBFATFS)/count.o \ - $(LIBFATFS)/fatio.o $(LIBFATFS)/traverse.o \ - $(LIBFATFS)/calc.o $(LIBFATFS)/context.o \ - $(LIBFATFS)/fat.o $(LIBFATFS)/resize.o \ - $(LIBHFS)/cache.o $(LIBHFS)/probe.o \ - $(LIBHFS)/advfs.o $(LIBHFS)/hfs.o \ - $(LIBHFS)/file.o $(LIBHFS)/reloc.o \ - $(LIBHFS)/advfs_plus.o $(LIBHFS)/journal.o \ - $(LIBHFS)/file_plus.o $(LIBHFS)/reloc_plus.o \ - $(LIBJFS)/jfs.o \ - $(LIBLINUXSWAP)/linux_swap.o \ - $(LIBNTFS)/ntfs.o \ - $(LIBREISERFS)/geom_dal.o $(LIBREISERFS)/reiserfs.o \ - $(LIBSOLARISX86)/solaris_x86.o \ - $(LIBUFS)/ufs.o \ - $(LIBXFS)/xfs.o \ - $(LIBLABELS)/dos.o $(LIBLABELS)/efi_crc32.o \ - $(LIBLABELS)/mac.o $(LIBLABELS)/sun.o \ - $(LIBLABELS)/aix.o $(LIBLABELS)/dvh.o \ - $(LIBLABELS)/gpt.o $(LIBLABELS)/pc98.o \ - $(LIBLABELS)/bsd.o $(LIBLABELS)/loop.o \ - $(LIBLABELS)/rdb.o \ - -# include library definitions -include ../../Makefile.lib - -SRCDIR = ../common - -C99MODE= $(C99_ENABLE) -CERRWARN += -erroff=E_EXTERN_INLINE_UNDEFINED -CERRWARN += -erroff=E_CONST_PROMOTED_UNSIGNED_LONG - -LIBS = $(DYNLIB) - -CFLAGS += $(CCVERBOSE) -CPPFLAGS += -I$(SRCDIR)/lib -I$(SRCDIR)/include -DYNFLAGS += $(ZINTERPOSE) -LDLIBS += -ldiskmgt -luuid -lc -lnvpair - -CERRWARN += -_gcc=-Wno-switch -CERRWARN += -_gcc=-Wno-unused-variable -CERRWARN += -_gcc=-Wno-type-limits - -.KEEP_STATE: - -# -# This open source is exempted from lint -# -lint: - -# include library targets -include ../../Makefile.targ diff --git a/usr/src/lib/libparted/README b/usr/src/lib/libparted/README deleted file mode 100644 index a9033959fc..0000000000 --- a/usr/src/lib/libparted/README +++ /dev/null @@ -1,22 +0,0 @@ -This is the Solaris ON port of GNU Parted v1.8.8 -For more information, please see http://www.gnu.org/software/parted/ - -parted has been broken into two pieces: src/lib/libparted and src/cmd/parted - -The Makefiles have all been replaced by ON Makefiles. - -The common directory contains these three subdirectories from parted-1.8.8: -include, lib and libparted - -$(SUBDIR)/config.status: $(SUBDIR)/configure - cd src; \ - MAKE=gmake ./configure CFLAGS=-I$(ROOT)/usr/include \ - LDFLAGS="-L$(ROOT)/lib -L$(ROOT)/usr/lib -Wl,-Bdirect -Wl,-M$(MAPFILE.NE -S) -Wl,-zignore" \ - LIBS=-ldiskmgt \ - ac_cv_sys_file_offset_bits=no \ - ac_cv_func_canonicalize_file_name=yes \ - --without-readline --disable-nls \ - --without-libintl-prefix \ - --disable-dependency-tracking \ - --disable-dynamic-loading diff --git a/usr/src/lib/libparted/THANKS.txt b/usr/src/lib/libparted/THANKS.txt deleted file mode 100644 index 466ccaca55..0000000000 --- a/usr/src/lib/libparted/THANKS.txt +++ /dev/null @@ -1,28 +0,0 @@ -In no particular order: - - * Jonathan duSaint for binary unit support and more. - * Kamil Ignacak for help with the migration of the API documentation. - * Conectiva, www.conectiva.com, for sponsoring Parted's development (in the -past). Eliphas, beber (aka Pato), baretta, fuganti, claudio, olive (anyone -else?) - * Stefan Kanthak <101.33761@germanynet.de> for lots of info on boot-loaders, -and some corrections to the documentation - * Fabian Emmes for RPM spec file, help with hidden -partitions and autoconfusion :-) - and lots of other misc. help. - * Falk Hueffner for bug fixes. - * Kevin Lindsay for lots of bug reports, etc. - * John Weismiller for lots of bug reports, etc. - * Andries Brouwer for advice on BIOS geometry - * Simon Kirby for advice on BIOS geometry - * Glenn McGrath - * Timshel Knoll for Debian stuff - * Tim Waugh for bug reports and fixes - * My friends for helping with testing: Tristan Zwalf, Menaka Lashitha Bandara, -Thomas Hambleton - * Ryan Weaver for parted.spec.in patches - * Benjamin Herrenschmidt for answering all of our questions -on Mac's - * Ethan Benson for lots of advice / testing on ppc - * Charles Stevenson - ppc stuff - * heaps of people we left out! - diff --git a/usr/src/lib/libparted/THIRDPARTYLICENSE.descrip b/usr/src/lib/libparted/THIRDPARTYLICENSE.descrip deleted file mode 100644 index 1cafc40dc0..0000000000 --- a/usr/src/lib/libparted/THIRDPARTYLICENSE.descrip +++ /dev/null @@ -1 +0,0 @@ -GNU Parted - Partition Editor diff --git a/usr/src/lib/libparted/common/include/parted/constraint.h b/usr/src/lib/libparted/common/include/parted/constraint.h deleted file mode 100644 index 7a39602f34..0000000000 --- a/usr/src/lib/libparted/common/include/parted/constraint.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_CONSTRAINT_H_INCLUDED -#define PED_CONSTRAINT_H_INCLUDED - -typedef struct _PedConstraint PedConstraint; - -#include -#include - -struct _PedConstraint { - PedAlignment* start_align; - PedAlignment* end_align; - PedGeometry* start_range; - PedGeometry* end_range; - PedSector min_size; - PedSector max_size; -}; - -extern int -ped_constraint_init ( - PedConstraint* constraint, - const PedAlignment* start_align, - const PedAlignment* end_align, - const PedGeometry* start_range, - const PedGeometry* end_range, - PedSector min_size, - PedSector max_size); - -extern PedConstraint* -ped_constraint_new ( - const PedAlignment* start_align, - const PedAlignment* end_align, - const PedGeometry* start_range, - const PedGeometry* end_range, - PedSector min_size, - PedSector max_size); - -extern PedConstraint* -ped_constraint_new_from_min_max ( - const PedGeometry* min, - const PedGeometry* max); - -extern PedConstraint* -ped_constraint_new_from_min (const PedGeometry* min); - -extern PedConstraint* -ped_constraint_new_from_max (const PedGeometry* max); - -extern PedConstraint* -ped_constraint_duplicate (const PedConstraint* constraint); - -extern void -ped_constraint_done (PedConstraint* constraint); - -extern void -ped_constraint_destroy (PedConstraint* constraint); - -extern PedConstraint* -ped_constraint_intersect (const PedConstraint* a, const PedConstraint* b); - -extern PedGeometry* -ped_constraint_solve_max (const PedConstraint* constraint); - -extern PedGeometry* -ped_constraint_solve_nearest ( - const PedConstraint* constraint, const PedGeometry* geom); - -extern int -ped_constraint_is_solution (const PedConstraint* constraint, - const PedGeometry* geom); - -extern PedConstraint* -ped_constraint_any (const PedDevice* dev); - -extern PedConstraint* -ped_constraint_exact (const PedGeometry* geom); - -#endif /* PED_CONSTRAINT_H_INCLUDED */ - diff --git a/usr/src/lib/libparted/common/include/parted/crc32.h b/usr/src/lib/libparted/common/include/parted/crc32.h deleted file mode 100644 index 73a76ff3ac..0000000000 --- a/usr/src/lib/libparted/common/include/parted/crc32.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - crc32.h - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _CRC32_H -#define _CRC32_H - -#include - -/* - * This computes a 32 bit CRC of the data in the buffer, and returns the CRC. - * The polynomial used is 0xedb88320. - */ - -extern uint32_t __efi_crc32 (const void *buf, unsigned long len, - uint32_t seed); - -#endif /* _CRC32_H */ diff --git a/usr/src/lib/libparted/common/include/parted/debug.h b/usr/src/lib/libparted/common/include/parted/debug.h deleted file mode 100644 index 6dc9e57c5f..0000000000 --- a/usr/src/lib/libparted/common/include/parted/debug.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998, 1999, 2000, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_DEBUG_H_INCLUDED -#define PED_DEBUG_H_INCLUDED - -#include - -#ifdef DEBUG - -typedef void (PedDebugHandler) ( const int level, const char* file, int line, - const char* function, const char* msg ); - -extern void ped_debug_set_handler (PedDebugHandler* handler); -extern void ped_debug ( const int level, const char* file, int line, - const char* function, const char* msg, ... ); - -extern int ped_assert ( int cond, const char* cond_text, - const char* file, int line, const char* function ); - -#if defined(__GNUC__) && !defined(__JSFTRACE__) - -#define PED_DEBUG(level, ...) \ - ped_debug ( level, __FILE__, __LINE__, __PRETTY_FUNCTION__, \ - __VA_ARGS__ ); - -#define PED_ASSERT(cond, action) \ - do { \ - if (!ped_assert ( cond, \ - #cond, \ - __FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__ )) \ - { \ - action; \ - } \ - } while (0) - -#else /* !__GNUC__ */ - -/* function because variadic macros are C99 */ -static void PED_DEBUG (int level, ...) -{ - va_list va_args; - - va_start (va_args, level); - ped_debug ( level, "unknown file", 0, "unknown function", va_args ); - va_end (va_args); -} - -#define PED_ASSERT(cond, action) \ - do { \ - if (!ped_assert ( cond, \ - #cond, \ - "unknown", \ - 0, \ - "unknown" )) \ - { \ - action; \ - } \ - } while (0) - -#endif /* __GNUC__ */ - -#else /* !DEBUG */ - -#define PED_ASSERT(cond, action) while (0) {} -#define PED_DEBUG(level, ...) while (0) {} - - -#endif /* DEBUG */ - -#endif /* PED_DEBUG_H_INCLUDED */ - diff --git a/usr/src/lib/libparted/common/include/parted/device.h b/usr/src/lib/libparted/common/include/parted/device.h deleted file mode 100644 index cf32dba7aa..0000000000 --- a/usr/src/lib/libparted/common/include/parted/device.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998 - 2001, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedDevice - * @{ - */ - -/** \file device.h */ - -#ifndef PED_DEVICE_H_INCLUDED -#define PED_DEVICE_H_INCLUDED - -#include - -/** We can address 2^63 sectors */ -typedef long long PedSector; - -/** \deprecated Removal from API planned */ -typedef enum { - PED_DEVICE_UNKNOWN = 0, - PED_DEVICE_SCSI = 1, - PED_DEVICE_IDE = 2, - PED_DEVICE_DAC960 = 3, - PED_DEVICE_CPQARRAY = 4, - PED_DEVICE_FILE = 5, - PED_DEVICE_ATARAID = 6, - PED_DEVICE_I2O = 7, - PED_DEVICE_UBD = 8, - PED_DEVICE_DASD = 9, - PED_DEVICE_VIODASD = 10, - PED_DEVICE_SX8 = 11, -#ifdef ENABLE_DEVICE_MAPPER - PED_DEVICE_DM = 12, -#endif - PED_DEVICE_XVD = 13 -} PedDeviceType; - -typedef struct _PedDevice PedDevice; -typedef struct _PedDeviceArchOps PedDeviceArchOps; -typedef struct _PedCHSGeometry PedCHSGeometry; - -/** - * A cylinder-head-sector "old-style" geometry. - * - * A device addressed in this way has C*H*S sectors. - */ -struct _PedCHSGeometry { - int cylinders; - int heads; - int sectors; -}; - -/** A block device - for example, /dev/hda, not /dev/hda3 */ -struct _PedDevice { - PedDevice* next; - - char* model; /**< \brief description of hardware - (manufacturer, model) */ - char* path; /**< device /dev entry */ - - PedDeviceType type; /**< SCSI, IDE, etc. - \deprecated \sa PedDeviceType */ - long long sector_size; /**< logical sector size */ - long long phys_sector_size; /**< physical sector size */ - PedSector length; /**< device length (LBA) */ - - int open_count; /**< the number of times this device has - been opened with ped_device_open(). */ - int read_only; - int external_mode; - int dirty; - int boot_dirty; - - PedCHSGeometry hw_geom; - PedCHSGeometry bios_geom; - short host, did; - - void* arch_specific; -}; - -/** - * List of functions implementing architecture-specific operations. - */ -struct _PedDeviceArchOps { - PedDevice* (*_new) (const char* path); - void (*destroy) (PedDevice* dev); - int (*is_busy) (PedDevice* dev); - int (*open) (PedDevice* dev); - int (*refresh_open) (PedDevice* dev); - int (*close) (PedDevice* dev); - int (*refresh_close) (PedDevice* dev); - int (*read) (const PedDevice* dev, void* buffer, - PedSector start, PedSector count); - int (*write) (PedDevice* dev, const void* buffer, - PedSector start, PedSector count); - int (*sync) (PedDevice* dev); - int (*sync_fast) (PedDevice* dev); - PedSector (*check) (PedDevice* dev, void* buffer, - PedSector start, PedSector count); - void (*probe_all) (); -}; - -extern void ped_device_probe_all (); -extern void ped_device_free_all (); - -extern PedDevice* ped_device_get (const char* name); -extern PedDevice* ped_device_get_next (const PedDevice* dev); -extern int ped_device_is_busy (PedDevice* dev); -extern int ped_device_open (PedDevice* dev); -extern int ped_device_close (PedDevice* dev); -extern void ped_device_destroy (PedDevice* dev); -extern void ped_device_cache_remove (PedDevice* dev); - -extern int ped_device_begin_external_access (PedDevice* dev); -extern int ped_device_end_external_access (PedDevice* dev); - -extern int ped_device_read (const PedDevice* dev, void* buffer, - PedSector start, PedSector count); -extern int ped_device_write (PedDevice* dev, const void* buffer, - PedSector start, PedSector count); -extern int ped_device_sync (PedDevice* dev); -extern int ped_device_sync_fast (PedDevice* dev); -extern PedSector ped_device_check (PedDevice* dev, void* buffer, - PedSector start, PedSector count); -extern PedConstraint* ped_device_get_constraint (PedDevice* dev); - -/* private stuff ;-) */ - -extern void _ped_device_probe (const char* path); - -#endif /* PED_DEVICE_H_INCLUDED */ - -/** @} */ - diff --git a/usr/src/lib/libparted/common/include/parted/disk.h b/usr/src/lib/libparted/common/include/parted/disk.h deleted file mode 100644 index eb72b739d9..0000000000 --- a/usr/src/lib/libparted/common/include/parted/disk.h +++ /dev/null @@ -1,348 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedDisk - * @{ - */ - -/** \file disk.h */ - -#ifndef PED_DISK_H_INCLUDED -#define PED_DISK_H_INCLUDED - -/** - * Partition types - */ -enum _PedPartitionType { - PED_PARTITION_NORMAL = 0x00, - PED_PARTITION_LOGICAL = 0x01, - PED_PARTITION_EXTENDED = 0x02, - PED_PARTITION_FREESPACE = 0x04, - PED_PARTITION_METADATA = 0x08, - PED_PARTITION_PROTECTED = 0x10 -}; - -/** - * Partition flags. - */ -enum _PedPartitionFlag { - PED_PARTITION_BOOT=1, - PED_PARTITION_ROOT=2, - PED_PARTITION_SWAP=3, - PED_PARTITION_HIDDEN=4, - PED_PARTITION_RAID=5, - PED_PARTITION_LVM=6, - PED_PARTITION_LBA=7, - PED_PARTITION_HPSERVICE=8, - PED_PARTITION_PALO=9, - PED_PARTITION_PREP=10, - PED_PARTITION_MSFT_RESERVED=11 -}; -#define PED_PARTITION_FIRST_FLAG PED_PARTITION_BOOT -#define PED_PARTITION_LAST_FLAG PED_PARTITION_MSFT_RESERVED - -enum _PedDiskTypeFeature { - PED_DISK_TYPE_EXTENDED=1, /**< supports extended partitions */ - PED_DISK_TYPE_PARTITION_NAME=2 /**< supports partition names */ -}; -#define PED_DISK_TYPE_FIRST_FEATURE PED_DISK_TYPE_EXTENDED -#define PED_DISK_TYPE_LAST_FEATURE PED_DISK_TYPE_PARTITION_NAME - -struct _PedDisk; -struct _PedPartition; -struct _PedDiskOps; -struct _PedDiskType; -struct _PedDiskArchOps; - -typedef enum _PedPartitionType PedPartitionType; -typedef enum _PedPartitionFlag PedPartitionFlag; -typedef enum _PedDiskTypeFeature PedDiskTypeFeature; -typedef struct _PedDisk PedDisk; -typedef struct _PedPartition PedPartition; -typedef const struct _PedDiskOps PedDiskOps; -typedef struct _PedDiskType PedDiskType; -typedef const struct _PedDiskArchOps PedDiskArchOps; - -#include -#include -#include -#include - -/** @} */ - -/** - * \addtogroup PedPartition - * - * @{ - */ - -/** \file disk.h */ - -/** - * PedPartition structure represents a partition. - */ -struct _PedPartition { - PedPartition* prev; - PedPartition* next; - - /**< the partition table of the partition */ - PedDisk* disk; - PedGeometry geom; /**< geometry of the partition */ - - /**< the partition number: In Linux, this is the - same as the minor number. No assumption - should be made about "num" and "type" - - different disk labels have different rules. */ - - int num; - PedPartitionType type; /**< the type of partition: a bit field of - PED_PARTITION_LOGICAL, PED_PARTITION_EXTENDED, - PED_PARTITION_METADATA - and PED_PARTITION_FREESPACE. - Both the first two, and the last two are - mutually exclusive. - An extended partition is a primary - partition that may contain logical partitions. - There is at most one extended partition on - a disk. - A logical partition is like a primary - partition, except it's inside an extended - partition. Internally, pseudo partitions are - allocated to represent free space, or disk - label meta-data. These have the - PED_PARTITION_FREESPACE or - PED_PARTITION_METADATA bit set. */ - - /**< The type of file system on the partition. NULL if unknown. */ - const PedFileSystemType* fs_type; - - /**< Only used for an extended partition. The list of logical - partitions (and free space and metadata within the extended - partition). */ - PedPartition* part_list; - - void* disk_specific; -}; - -/** @} */ - -/** - * \addtogroup PedDisk - * @{ - */ - -/** - * Represents a disk label (partition table). - */ -struct _PedDisk { - PedDevice* dev; /**< the device where the - partition table lies */ - const PedDiskType* type; /**< type of disk label */ - const int* block_sizes; /**< block sizes supported - by this label */ - PedPartition* part_list; /**< list of partitions. Access with - ped_disk_next_partition() */ - - void* disk_specific; - -/* office use only ;-) */ - int needs_clobber; /**< clobber before write? */ - int update_mode; /**< mode without free/metadata - partitions, for easier - update */ -}; - -struct _PedDiskOps { - /* disk label operations */ - int (*probe) (const PedDevice *dev); - int (*clobber) (PedDevice* dev); - PedDisk* (*alloc) (const PedDevice* dev); - PedDisk* (*duplicate) (const PedDisk* disk); - void (*free) (PedDisk* disk); - int (*read) (PedDisk* disk); - int (*write) (const PedDisk* disk); - /** \todo add label guessing op here */ - - /* partition operations */ - PedPartition* (*partition_new) ( - const PedDisk* disk, - PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, - PedSector end); - PedPartition* (*partition_duplicate) (const PedPartition* part); - void (*partition_destroy) (PedPartition* part); - int (*partition_set_system) (PedPartition* part, - const PedFileSystemType* fs_type); - int (*partition_set_flag) ( - PedPartition* part, - PedPartitionFlag flag, - int state); - int (*partition_get_flag) ( - const PedPartition* part, - PedPartitionFlag flag); - int (*partition_is_flag_available) ( - const PedPartition* part, - PedPartitionFlag flag); - void (*partition_set_name) (PedPartition* part, const char* name); - const char* (*partition_get_name) (const PedPartition* part); - int (*partition_align) (PedPartition* part, - const PedConstraint* constraint); - int (*partition_enumerate) (PedPartition* part); - - /* other */ - int (*alloc_metadata) (PedDisk* disk); - int (*get_max_primary_partition_count) (const PedDisk* disk); -}; - -struct _PedDiskType { - PedDiskType* next; - const char* name; /**< the name of the partition table type. - \todo not very intuitive name */ - PedDiskOps* const ops; - - PedDiskTypeFeature features; /**< bitmap of supported features */ -}; - -/** - * Architecture-specific operations. i.e. communication with kernel (or - * whatever) about changes, etc. - */ -struct _PedDiskArchOps { - char* (*partition_get_path) (const PedPartition* part); - int (*partition_is_busy) (const PedPartition* part); - int (*disk_commit) (PedDisk* disk); -}; - -extern void ped_disk_type_register (PedDiskType* type); -extern void ped_disk_type_unregister (PedDiskType* type); - -extern PedDiskType* ped_disk_type_get_next (PedDiskType* type); -extern PedDiskType* ped_disk_type_get (const char* name); -extern int ped_disk_type_check_feature (const PedDiskType* disk_type, - PedDiskTypeFeature feature); - -extern PedDiskType* ped_disk_probe (PedDevice* dev); -extern int ped_disk_clobber (PedDevice* dev); -extern int ped_disk_clobber_exclude (PedDevice* dev, - const PedDiskType* exclude); -extern PedDisk* ped_disk_new (PedDevice* dev); -extern PedDisk* ped_disk_new_fresh (PedDevice* dev, - const PedDiskType* disk_type); -extern PedDisk* ped_disk_duplicate (const PedDisk* old_disk); -extern void ped_disk_destroy (PedDisk* disk); -extern int ped_disk_commit (PedDisk* disk); -extern int ped_disk_commit_to_dev (PedDisk* disk); -extern int ped_disk_commit_to_os (PedDisk* disk); -extern int ped_disk_check (const PedDisk* disk); -extern void ped_disk_print (const PedDisk* disk); - -extern int ped_disk_get_primary_partition_count (const PedDisk* disk); -extern int ped_disk_get_last_partition_num (const PedDisk* disk); -extern int ped_disk_get_max_primary_partition_count (const PedDisk* disk); - -/** @} */ - -/** - * \addtogroup PedPartition - * - * @{ - */ - -extern PedPartition* ped_partition_new (const PedDisk* disk, - PedPartitionType type, - const PedFileSystemType* fs_type, - PedSector start, - PedSector end); -extern void ped_partition_destroy (PedPartition* part); -extern int ped_partition_is_active (const PedPartition* part); -extern int ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, - int state); -extern int ped_partition_get_flag (const PedPartition* part, - PedPartitionFlag flag); -extern int ped_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag); -extern int ped_partition_set_system (PedPartition* part, - const PedFileSystemType* fs_type); -extern int ped_partition_set_name (PedPartition* part, const char* name); -extern const char* ped_partition_get_name (const PedPartition* part); -extern int ped_partition_is_busy (const PedPartition* part); -extern char* ped_partition_get_path (const PedPartition* part); - -extern const char* ped_partition_type_get_name (PedPartitionType part_type); -extern const char* ped_partition_flag_get_name (PedPartitionFlag flag); -extern PedPartitionFlag ped_partition_flag_get_by_name (const char* name); -extern PedPartitionFlag ped_partition_flag_next (PedPartitionFlag flag); - -/** @} */ - -/** - * \addtogroup PedDisk - * @{ - */ - -extern int ped_disk_add_partition (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint); -extern int ped_disk_remove_partition (PedDisk* disk, PedPartition* part); -extern int ped_disk_delete_partition (PedDisk* disk, PedPartition* part); -extern int ped_disk_delete_all (PedDisk* disk); -extern int ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint, - PedSector start, PedSector end); -extern int ped_disk_maximize_partition (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint); -extern PedGeometry* ped_disk_get_max_partition_geometry (PedDisk* disk, - PedPartition* part, const PedConstraint* constraint); -extern int ped_disk_minimize_extended_partition (PedDisk* disk); - -extern PedPartition* ped_disk_next_partition (const PedDisk* disk, - const PedPartition* part); -extern PedPartition* ped_disk_get_partition (const PedDisk* disk, int num); -extern PedPartition* ped_disk_get_partition_by_sector (const PedDisk* disk, - PedSector sect); -extern PedPartition* ped_disk_extended_partition (const PedDisk* disk); - -/* internal functions */ -extern PedDisk* _ped_disk_alloc (const PedDevice* dev, const PedDiskType* type); -extern void _ped_disk_free (PedDisk* disk); - - -/** @} */ - -/** - * \addtogroup PedPartition - * - * @{ - */ - -extern PedPartition* _ped_partition_alloc (const PedDisk* disk, - PedPartitionType type, - const PedFileSystemType* fs_type, - PedSector start, - PedSector end); -extern void _ped_partition_free (PedPartition* part); - -extern int _ped_partition_attempt_align ( - PedPartition* part, const PedConstraint* external, - PedConstraint* internal); - -#endif /* PED_DISK_H_INCLUDED */ - -/** @} */ - diff --git a/usr/src/lib/libparted/common/include/parted/endian.h b/usr/src/lib/libparted/common/include/parted/endian.h deleted file mode 100644 index f968e2c8b1..0000000000 --- a/usr/src/lib/libparted/common/include/parted/endian.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998-2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* should only be #included by files in libparted */ - -#ifndef PED_ENDIAN_H_INCLUDED -#define PED_ENDIAN_H_INCLUDED - -#include - -/* returns the n'th least significant byte */ -#define _GET_BYTE(x, n) ( ((x) >> (8 * (n))) & 0xff ) - -#define _PED_SWAP16(x) ( (_GET_BYTE(x, 0) << 8) \ - + (_GET_BYTE(x, 1) << 0) ) - -#define _PED_SWAP32(x) ( (_GET_BYTE(x, 0) << 24) \ - + (_GET_BYTE(x, 1) << 16) \ - + (_GET_BYTE(x, 2) << 8) \ - + (_GET_BYTE(x, 3) << 0) ) - -#define _PED_SWAP64(x) ( (_GET_BYTE(x, 0) << 56) \ - + (_GET_BYTE(x, 1) << 48) \ - + (_GET_BYTE(x, 2) << 40) \ - + (_GET_BYTE(x, 3) << 32) \ - + (_GET_BYTE(x, 4) << 24) \ - + (_GET_BYTE(x, 5) << 16) \ - + (_GET_BYTE(x, 6) << 8) \ - + (_GET_BYTE(x, 7) << 0) ) - -#define PED_SWAP16(x) ((uint16_t) _PED_SWAP16( (uint16_t) (x) )) -#define PED_SWAP32(x) ((uint32_t) _PED_SWAP32( (uint32_t) (x) )) -#define PED_SWAP64(x) ((uint64_t) _PED_SWAP64( (uint64_t) (x) )) - -#ifdef WORDS_BIGENDIAN - -#define PED_CPU_TO_LE16(x) PED_SWAP16(x) -#define PED_CPU_TO_BE16(x) (x) -#define PED_CPU_TO_LE32(x) PED_SWAP32(x) -#define PED_CPU_TO_BE32(x) (x) -#define PED_CPU_TO_LE64(x) PED_SWAP64(x) -#define PED_CPU_TO_BE64(x) (x) - -#define PED_LE16_TO_CPU(x) PED_SWAP16(x) -#define PED_BE16_TO_CPU(x) (x) -#define PED_LE32_TO_CPU(x) PED_SWAP32(x) -#define PED_BE32_TO_CPU(x) (x) -#define PED_LE64_TO_CPU(x) PED_SWAP64(x) -#define PED_BE64_TO_CPU(x) (x) - -#else /* !WORDS_BIGENDIAN */ - -#define PED_CPU_TO_LE16(x) (x) -#define PED_CPU_TO_BE16(x) PED_SWAP16(x) -#define PED_CPU_TO_LE32(x) (x) -#define PED_CPU_TO_BE32(x) PED_SWAP32(x) -#define PED_CPU_TO_LE64(x) (x) -#define PED_CPU_TO_BE64(x) PED_SWAP64(x) - -#define PED_LE16_TO_CPU(x) (x) -#define PED_BE16_TO_CPU(x) PED_SWAP16(x) -#define PED_LE32_TO_CPU(x) (x) -#define PED_BE32_TO_CPU(x) PED_SWAP32(x) -#define PED_LE64_TO_CPU(x) (x) -#define PED_BE64_TO_CPU(x) PED_SWAP64(x) - -#endif /* !WORDS_BIGENDIAN */ - -#endif /* PED_ENDIAN_H_INCLUDED */ - diff --git a/usr/src/lib/libparted/common/include/parted/exception.h b/usr/src/lib/libparted/common/include/parted/exception.h deleted file mode 100644 index aa63c1a27b..0000000000 --- a/usr/src/lib/libparted/common/include/parted/exception.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedException - * @{ - */ - -/** \file exception.h */ - -#ifndef PED_EXCEPTION_H_INCLUDED -#define PED_EXCEPTION_H_INCLUDED - -typedef struct _PedException PedException; - -/** - * Exception type - */ -enum _PedExceptionType { - PED_EXCEPTION_INFORMATION=1, - PED_EXCEPTION_WARNING=2, - PED_EXCEPTION_ERROR=3, - PED_EXCEPTION_FATAL=4, - PED_EXCEPTION_BUG=5, - PED_EXCEPTION_NO_FEATURE=6, -}; -typedef enum _PedExceptionType PedExceptionType; - -/** - * Option for resolving the exception - */ -enum _PedExceptionOption { - PED_EXCEPTION_UNHANDLED=0, - PED_EXCEPTION_FIX=1, - PED_EXCEPTION_YES=2, - PED_EXCEPTION_NO=4, - PED_EXCEPTION_OK=8, - PED_EXCEPTION_RETRY=16, - PED_EXCEPTION_IGNORE=32, - PED_EXCEPTION_CANCEL=64, -}; -typedef enum _PedExceptionOption PedExceptionOption; -#define PED_EXCEPTION_OK_CANCEL (PED_EXCEPTION_OK + PED_EXCEPTION_CANCEL) -#define PED_EXCEPTION_YES_NO (PED_EXCEPTION_YES + PED_EXCEPTION_NO) -#define PED_EXCEPTION_YES_NO_CANCEL (PED_EXCEPTION_YES_NO \ - + PED_EXCEPTION_CANCEL) -#define PED_EXCEPTION_IGNORE_CANCEL (PED_EXCEPTION_IGNORE \ - + PED_EXCEPTION_CANCEL) -#define PED_EXCEPTION_RETRY_CANCEL (PED_EXCEPTION_RETRY + PED_EXCEPTION_CANCEL) -#define PED_EXCEPTION_RETRY_IGNORE_CANCEL (PED_EXCEPTION_RETRY \ - + PED_EXCEPTION_IGNORE_CANCEL) -#define PED_EXCEPTION_OPTION_FIRST PED_EXCEPTION_FIX -#define PED_EXCEPTION_OPTION_LAST PED_EXCEPTION_CANCEL - -/** - * Structure with information about exception - */ -struct _PedException { - char* message; /**< text describing what the event was */ - PedExceptionType type; /**< type of exception */ - PedExceptionOption options; /**< ORed list of options that - the exception handler can - return (the ways an exception - can be resolved) */ -}; - -typedef PedExceptionOption (PedExceptionHandler) (PedException* ex); - -extern int ped_exception; /* set to true if there's an exception */ - -extern char* ped_exception_get_type_string (PedExceptionType ex_type); -extern char* ped_exception_get_option_string (PedExceptionOption ex_opt); - -extern void ped_exception_set_handler (PedExceptionHandler* handler); -extern PedExceptionHandler *ped_exception_get_handler(void); - -extern PedExceptionOption ped_exception_default_handler (PedException* ex); - -extern PedExceptionOption ped_exception_throw (PedExceptionType ex_type, - PedExceptionOption ex_opt, - const char* message, - ...); -/* rethrows an exception - i.e. calls the exception handler, (or returns a - code to return to pass up higher) */ -extern PedExceptionOption ped_exception_rethrow (); - -/* frees an exception, indicating that the exception has been handled. - Calling an exception handler counts. */ -extern void ped_exception_catch (); - -/* indicate that exceptions should not go to the exception handler, but passed - up to the calling function(s) */ -extern void ped_exception_fetch_all (); - -/* indicate that exceptions should invoke the exception handler */ -extern void ped_exception_leave_all (); - -#endif /* PED_EXCEPTION_H_INCLUDED */ - -/** @} */ - diff --git a/usr/src/lib/libparted/common/include/parted/filesys.h b/usr/src/lib/libparted/common/include/parted/filesys.h deleted file mode 100644 index eacfa724f4..0000000000 --- a/usr/src/lib/libparted/common/include/parted/filesys.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedFileSystem - * @{ - */ - -/** \file filesys.h */ - -#ifndef PED_FILESYS_H_INCLUDED -#define PED_FILESYS_H_INCLUDED - -typedef struct _PedFileSystem PedFileSystem; -typedef struct _PedFileSystemType PedFileSystemType; -typedef const struct _PedFileSystemOps PedFileSystemOps; - -#include -#include -#include -#include -#include -#include - -struct _PedFileSystemOps { - PedGeometry* (*probe) (PedGeometry* geom); - int (*clobber) (PedGeometry* geom); - - PedFileSystem* (*open) (PedGeometry* geom); - PedFileSystem* (*create) (PedGeometry* geom, PedTimer* timer); - int (*close) (PedFileSystem* fs); - int (*check) (PedFileSystem* fs, PedTimer* timer); - PedFileSystem* (*copy) (const PedFileSystem* fs, PedGeometry* geom, - PedTimer* timer); - int (*resize) (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer); - - PedConstraint* (*get_create_constraint) (const PedDevice* dev); - PedConstraint* (*get_resize_constraint) (const PedFileSystem* fs); - PedConstraint* (*get_copy_constraint) (const PedFileSystem* fs, - const PedDevice* dev); -}; - -/** - * Structure describing type of file system - */ -struct _PedFileSystemType { - PedFileSystemType* next; - const char* const name; /**< name of the file system type */ - const int* block_sizes; - PedFileSystemOps* const ops; -}; - - -/** - * Structure describing file system - */ -struct _PedFileSystem { - PedFileSystemType* type; /**< the file system type */ - PedGeometry* geom; /**< where the file system actually is */ - int checked; /**< 1 if the file system has been checked. - 0 otherwise. */ - - void* type_specific; - -}; - -extern void ped_file_system_type_register (PedFileSystemType* type); -extern void ped_file_system_type_unregister (PedFileSystemType* type); - -extern PedFileSystemType* ped_file_system_type_get (const char* name); -extern PedFileSystemType* -ped_file_system_type_get_next (const PedFileSystemType* fs_type); - -extern PedFileSystemType* ped_file_system_probe (PedGeometry* geom); -extern PedGeometry* ped_file_system_probe_specific ( - const PedFileSystemType* fs_type, - PedGeometry* geom); -extern int ped_file_system_clobber (PedGeometry* geom); - -extern PedFileSystem* ped_file_system_open (PedGeometry* geom); -extern PedFileSystem* ped_file_system_create (PedGeometry* geom, - const PedFileSystemType* type, - PedTimer* timer); -extern int ped_file_system_close (PedFileSystem* fs); -extern int ped_file_system_check (PedFileSystem* fs, PedTimer* timer); -extern PedFileSystem* ped_file_system_copy (PedFileSystem* fs, - PedGeometry* geom, - PedTimer* timer); -extern int ped_file_system_resize (PedFileSystem* fs, PedGeometry* geom, - PedTimer* timer); - -extern PedConstraint* ped_file_system_get_create_constraint ( - const PedFileSystemType* fs_type, const PedDevice* dev); -extern PedConstraint* ped_file_system_get_resize_constraint ( - const PedFileSystem* fs); -extern PedConstraint* ped_file_system_get_copy_constraint ( - const PedFileSystem* fs, const PedDevice* dev); - -#endif /* PED_FILESYS_H_INCLUDED */ - -/** @} */ diff --git a/usr/src/lib/libparted/common/include/parted/geom.h b/usr/src/lib/libparted/common/include/parted/geom.h deleted file mode 100644 index 58fd9005a7..0000000000 --- a/usr/src/lib/libparted/common/include/parted/geom.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1998-2001, 2005, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedGeometry - * @{ - */ - -/** \file geom.h */ - -#ifndef PED_GEOM_H_INCLUDED -#define PED_GEOM_H_INCLUDED - -#include -#include - -typedef struct _PedGeometry PedGeometry; - -/** - * Geometry of the partition - */ -struct _PedGeometry { - PedDevice* dev; - PedSector start; - PedSector length; - PedSector end; -}; - -extern int ped_geometry_init (PedGeometry* geom, const PedDevice* dev, - PedSector start, PedSector length); -extern PedGeometry* ped_geometry_new (const PedDevice* dev, PedSector start, - PedSector length); -extern PedGeometry* ped_geometry_duplicate (const PedGeometry* geom); -extern PedGeometry* ped_geometry_intersect (const PedGeometry* a, - const PedGeometry* b); -extern void ped_geometry_destroy (PedGeometry* geom); -extern int ped_geometry_set (PedGeometry* geom, PedSector start, - PedSector length); -extern int ped_geometry_set_start (PedGeometry* geom, PedSector start); -extern int ped_geometry_set_end (PedGeometry* geom, PedSector end); -extern int ped_geometry_test_overlap (const PedGeometry* a, - const PedGeometry* b); -extern int ped_geometry_test_inside (const PedGeometry* a, - const PedGeometry* b); -extern int ped_geometry_test_equal (const PedGeometry* a, const PedGeometry* b); -extern int ped_geometry_test_sector_inside (const PedGeometry* geom, - PedSector sect); - -extern int ped_geometry_read (const PedGeometry* geom, void* buffer, - PedSector offset, PedSector count); -extern int ped_geometry_write (PedGeometry* geom, const void* buffer, - PedSector offset, PedSector count); -extern PedSector ped_geometry_check (PedGeometry* geom, void* buffer, - PedSector buffer_size, PedSector offset, - PedSector granularity, PedSector count, - PedTimer* timer); -extern int ped_geometry_sync (PedGeometry* geom); -extern int ped_geometry_sync_fast (PedGeometry* geom); - -/* returns -1 if "sector" is not within dest's space. */ -extern PedSector ped_geometry_map (const PedGeometry* dst, - const PedGeometry* src, - PedSector sector); - -#endif /* PED_GEOM_H_INCLUDED */ - -/** @} */ - diff --git a/usr/src/lib/libparted/common/include/parted/natmath.h b/usr/src/lib/libparted/common/include/parted/natmath.h deleted file mode 100644 index 16306655b9..0000000000 --- a/usr/src/lib/libparted/common/include/parted/natmath.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedAlignment - * @{ - */ - -/** \file natmath.h */ - -#ifndef PED_NATMATH_H_INCLUDED -#define PED_NATMATH_H_INCLUDED - - -typedef struct _PedAlignment PedAlignment; - -#include - -#define PED_MIN(a, b) ( ((a)<(b)) ? (a) : (b) ) -#define PED_MAX(a, b) ( ((a)>(b)) ? (a) : (b) ) - -/* this is weird (I'm still not sure I should be doing this!) - * - * For the functions: new, destroy, duplicate and merge: the following values - * for align are valid: - * * align == NULL (!) represents no solution - * * align->grain_size == 0 represents a single solution - * (align->offset) - * * align->grain_size > 0 represents a set of solutions - * - * These are invalid: - * * align->offset < 0 Note: this gets "normalized" - * * align->grain_size < 0 - * - * For the align_* operations, there must be a solution. i.e. align != NULL - * All solutions must be greater than zero. - */ - -struct _PedAlignment { - PedSector offset; - PedSector grain_size; -}; - -extern PedSector ped_round_up_to (PedSector sector, PedSector grain_size); -extern PedSector ped_round_down_to (PedSector sector, PedSector grain_size); -extern PedSector ped_round_to_nearest (PedSector sector, PedSector grain_size); -extern PedSector ped_greatest_common_divisor (PedSector a, PedSector b); - -extern int ped_alignment_init (PedAlignment* align, PedSector offset, - PedSector grain_size); -extern PedAlignment* ped_alignment_new (PedSector offset, PedSector grain_size); -extern void ped_alignment_destroy (PedAlignment* align); -extern PedAlignment* ped_alignment_duplicate (const PedAlignment* align); -extern PedAlignment* ped_alignment_intersect (const PedAlignment* a, - const PedAlignment* b); - -extern PedSector -ped_alignment_align_up (const PedAlignment* align, const PedGeometry* geom, - PedSector sector); -extern PedSector -ped_alignment_align_down (const PedAlignment* align, const PedGeometry* geom, - PedSector sector); -extern PedSector -ped_alignment_align_nearest (const PedAlignment* align, const PedGeometry* geom, - PedSector sector); - -extern int -ped_alignment_is_aligned (const PedAlignment* align, const PedGeometry* geom, - PedSector sector); - -extern const PedAlignment* ped_alignment_any; -extern const PedAlignment* ped_alignment_none; - -#ifdef __sun -extern PedSector -#else -extern inline PedSector -#endif -ped_div_round_up (PedSector numerator, PedSector divisor); - -#ifdef __sun -extern PedSector -#else -extern inline PedSector -#endif -ped_div_round_to_nearest (PedSector numerator, PedSector divisor); - -#endif /* PED_NATMATH_H_INCLUDED */ - -/** - * @} - */ - diff --git a/usr/src/lib/libparted/common/include/parted/parted.h b/usr/src/lib/libparted/common/include/parted/parted.h deleted file mode 100644 index 1302d8f1bc..0000000000 --- a/usr/src/lib/libparted/common/include/parted/parted.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PARTED_H_INCLUDED -#define PARTED_H_INCLUDED - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct _PedArchitecture PedArchitecture; - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct _PedArchitecture { - PedDiskArchOps* disk_ops; - PedDeviceArchOps* dev_ops; -}; - -extern const PedArchitecture* ped_architecture; - -/* the architecture can't be changed if there are any PedDevice's. - * i.e. you should only be doing this if it's the FIRST thing you do... - */ -extern int ped_set_architecture (const PedArchitecture* arch); - -extern const char* ped_get_version (); - -extern void* ped_malloc (size_t size); -extern void* ped_calloc (size_t size); -extern int ped_realloc (void** ptr, size_t size); -extern void ped_free (void* ptr); - -#ifdef __cplusplus -} -#endif - -#endif /* PARTED_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/include/parted/solaris.h b/usr/src/lib/libparted/common/include/parted/solaris.h deleted file mode 100644 index 39f404f16a..0000000000 --- a/usr/src/lib/libparted/common/include/parted/solaris.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef PED_SOLARIS_H_INCLUDED -#define PED_SOLARIS_H_INCLUDED - -#include - -#define SOLARIS_SPECIFIC(dev) ((SolarisSpecific*) (dev)->arch_specific) - -typedef struct _SolarisSpecific SolarisSpecific; - -struct _SolarisSpecific { - int fd; -}; - -extern PedArchitecture ped_solaris_arch; - -#endif /* PED_SOLARIS_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/include/parted/timer.h b/usr/src/lib/libparted/common/include/parted/timer.h deleted file mode 100644 index 702d7036dd..0000000000 --- a/usr/src/lib/libparted/common/include/parted/timer.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedTimer - * @{ - */ - -/** \file timer.h */ - -#ifndef PED_TIMER_H_INCLUDED -#define PED_TIMER_H_INCLUDED - -#include - -typedef struct _PedTimer PedTimer; - -typedef void PedTimerHandler (PedTimer* timer, void* context); - -/* - * Structure keeping track of progress and time - */ -struct _PedTimer { - float frac; /**< fraction of operation done */ - time_t start; /**< time of start of op */ - time_t now; /**< time of last update (now!) */ - time_t predicted_end; /**< expected finish time */ - const char* state_name; /**< eg: "copying data" */ - PedTimerHandler* handler; /**< who to notify on updates */ - void* context; /**< context to pass to handler */ -}; - -extern PedTimer* ped_timer_new (PedTimerHandler* handler, void* context); -extern void ped_timer_destroy (PedTimer* timer); - -/* a nested timer automatically notifies it's parent. You should only - * create one when you are going to use it (not before) - */ -extern PedTimer* ped_timer_new_nested (PedTimer* parent, float nest_frac); -extern void ped_timer_destroy_nested (PedTimer* timer); - -extern void ped_timer_touch (PedTimer* timer); -extern void ped_timer_reset (PedTimer* timer); -extern void ped_timer_update (PedTimer* timer, float new_frac); -extern void ped_timer_set_state_name (PedTimer* timer, const char* state_name); - -#endif /* PED_TIMER_H_INCLUDED */ - - -/** @} */ diff --git a/usr/src/lib/libparted/common/include/parted/unit.h b/usr/src/lib/libparted/common/include/parted/unit.h deleted file mode 100644 index 54a9790b45..0000000000 --- a/usr/src/lib/libparted/common/include/parted/unit.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedUnit - * @{ - */ - -/** \file unit.h */ - -#ifndef PED_UNIT_H_INCLUDED -#define PED_UNIT_H_INCLUDED - -#include - -#include -#include - -#define PED_SECTOR_SIZE_DEFAULT 512LL -#define PED_KILOBYTE_SIZE 1000LL -#define PED_MEGABYTE_SIZE 1000000LL -#define PED_GIGABYTE_SIZE 1000000000LL -#define PED_TERABYTE_SIZE 1000000000000LL -#define PED_KIBIBYTE_SIZE 1024LL -#define PED_MEBIBYTE_SIZE 1048576LL -#define PED_GIBIBYTE_SIZE 1073741824LL -#define PED_TEBIBYTE_SIZE 1099511627776LL - -/** - * Human-friendly unit for representation of a location within device - */ -typedef enum { - PED_UNIT_SECTOR, - PED_UNIT_BYTE, - PED_UNIT_KILOBYTE, - PED_UNIT_MEGABYTE, - PED_UNIT_GIGABYTE, - PED_UNIT_TERABYTE, - PED_UNIT_COMPACT, - PED_UNIT_CYLINDER, - PED_UNIT_CHS, - PED_UNIT_PERCENT, - PED_UNIT_KIBIBYTE, - PED_UNIT_MEBIBYTE, - PED_UNIT_GIBIBYTE, - PED_UNIT_TEBIBYTE -} PedUnit; - -#define PED_UNIT_FIRST PED_UNIT_SECTOR -#define PED_UNIT_LAST PED_UNIT_TEBIBYTE - -extern long long ped_unit_get_size (const PedDevice* dev, PedUnit unit); -extern const char* ped_unit_get_name (PedUnit unit); -extern PedUnit ped_unit_get_by_name (const char* unit_name); - -extern void ped_unit_set_default (PedUnit unit); -extern PedUnit ped_unit_get_default (); - -extern char* ped_unit_format_byte (const PedDevice* dev, PedSector byte); -extern char* ped_unit_format_custom_byte (const PedDevice* dev, PedSector byte, - PedUnit unit); - -extern char* ped_unit_format (const PedDevice* dev, PedSector sector); -extern char* ped_unit_format_custom (const PedDevice* dev, PedSector sector, - PedUnit unit); - -extern int ped_unit_parse (const char* str, const PedDevice* dev, - PedSector* sector, - PedGeometry** range); -extern int ped_unit_parse_custom (const char* str, const PedDevice* dev, - PedUnit unit, PedSector* sector, - PedGeometry** range); - -#endif /* PED_UNIT_H_INCLUDED */ - -/** @} */ - - diff --git a/usr/src/lib/libparted/common/lib/__fpending.h b/usr/src/lib/libparted/common/lib/__fpending.h deleted file mode 100644 index 8a8aabcc22..0000000000 --- a/usr/src/lib/libparted/common/lib/__fpending.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Declare __fpending. - - Copyright (C) 2000, 2003, 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - - Written by Jim Meyering. */ - -#include -#include - -#ifndef HAVE_DECL___FPENDING -"this configure-time declaration test was not run" -#endif - -#if HAVE_DECL___FPENDING -# if HAVE_STDIO_EXT_H -# include -# endif -#else -size_t __fpending (FILE *); -#endif diff --git a/usr/src/lib/libparted/common/lib/basename.c b/usr/src/lib/libparted/common/lib/basename.c deleted file mode 100644 index fbe17ff910..0000000000 --- a/usr/src/lib/libparted/common/lib/basename.c +++ /dev/null @@ -1,129 +0,0 @@ -/* basename.c -- return the last element in a file name - - Copyright (C) 1990, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "dirname.h" - -#include -#include "xalloc.h" -#include "xstrndup.h" - -/* Return the address of the last file name component of NAME. If - NAME has no relative file name components because it is a file - system root, return the empty string. */ - -char * -last_component (char const *name) -{ - char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); - char const *p; - bool saw_slash = false; - - while (ISSLASH (*base)) - base++; - - for (p = base; *p; p++) - { - if (ISSLASH (*p)) - saw_slash = true; - else if (saw_slash) - { - base = p; - saw_slash = false; - } - } - - return (char *) base; -} - - -/* In general, we can't use the builtin `basename' function if available, - since it has different meanings in different environments. - In some environments the builtin `basename' modifies its argument. - - Return the last file name component of NAME, allocated with - xmalloc. On systems with drive letters, a leading "./" - distinguishes relative names that would otherwise look like a drive - letter. Unlike POSIX basename(), NAME cannot be NULL, - base_name("") returns "", and the first trailing slash is not - stripped. - - If lstat (NAME) would succeed, then { chdir (dir_name (NAME)); - lstat (base_name (NAME)); } will access the same file. Likewise, - if the sequence { chdir (dir_name (NAME)); - rename (base_name (NAME), "foo"); } succeeds, you have renamed NAME - to "foo" in the same directory NAME was in. */ - -char * -base_name (char const *name) -{ - char const *base = last_component (name); - size_t length; - - /* If there is no last component, then name is a file system root or the - empty string. */ - if (! *base) - return xstrndup (name, base_len (name)); - - /* Collapse a sequence of trailing slashes into one. */ - length = base_len (base); - if (ISSLASH (base[length])) - length++; - - /* On systems with drive letters, `a/b:c' must return `./b:c' rather - than `b:c' to avoid confusion with a drive letter. On systems - with pure POSIX semantics, this is not an issue. */ - if (FILE_SYSTEM_PREFIX_LEN (base)) - { - char *p = xmalloc (length + 3); - p[0] = '.'; - p[1] = '/'; - memcpy (p + 2, base, length); - p[length + 2] = '\0'; - return p; - } - - /* Finally, copy the basename. */ - return xstrndup (base, length); -} - -/* Return the length of the basename NAME. Typically NAME is the - value returned by base_name or last_component. Act like strlen - (NAME), except omit all trailing slashes. */ - -size_t -base_len (char const *name) -{ - size_t len; - size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); - - for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) - continue; - - if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 - && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) - return 2; - - if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len - && len == prefix_len && ISSLASH (name[prefix_len])) - return prefix_len + 1; - - return len; -} diff --git a/usr/src/lib/libparted/common/lib/close-stream.c b/usr/src/lib/libparted/common/lib/close-stream.c deleted file mode 100644 index 72d0d6816c..0000000000 --- a/usr/src/lib/libparted/common/lib/close-stream.c +++ /dev/null @@ -1,76 +0,0 @@ -/* Close a stream, with nicer error checking than fclose's. - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "close-stream.h" - -#include -#include - -#include "__fpending.h" - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -/* Close STREAM. Return 0 if successful, EOF (setting errno) - otherwise. A failure might set errno to 0 if the error number - cannot be determined. - - If a program writes *anything* to STREAM, that program should close - STREAM and make sure that it succeeds before exiting. Otherwise, - suppose that you go to the extreme of checking the return status - of every function that does an explicit write to STREAM. The last - printf can succeed in writing to the internal stream buffer, and yet - the fclose(STREAM) could still fail (due e.g., to a disk full error) - when it tries to write out that buffered data. Thus, you would be - left with an incomplete output file and the offending program would - exit successfully. Even calling fflush is not always sufficient, - since some file systems (NFS and CODA) buffer written/flushed data - until an actual close call. - - Besides, it's wasteful to check the return value from every call - that writes to STREAM -- just let the internal stream state record - the failure. That's what the ferror test is checking below. */ - -int -close_stream (FILE *stream) -{ - bool some_pending = (__fpending (stream) != 0); - bool prev_fail = (ferror (stream) != 0); - bool fclose_fail = (fclose (stream) != 0); - - /* Return an error indication if there was a previous failure or if - fclose failed, with one exception: ignore an fclose failure if - there was no previous error, no data remains to be flushed, and - fclose failed with EBADF. That can happen when a program like cp - is invoked like this `cp a b >&-' (i.e., with standard output - closed) and doesn't generate any output (hence no previous error - and nothing to be flushed). */ - - if (prev_fail || (fclose_fail && (some_pending || errno != EBADF))) - { - if (! fclose_fail) - errno = 0; - return EOF; - } - - return 0; -} diff --git a/usr/src/lib/libparted/common/lib/close-stream.h b/usr/src/lib/libparted/common/lib/close-stream.h deleted file mode 100644 index be3d4196b0..0000000000 --- a/usr/src/lib/libparted/common/lib/close-stream.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -int close_stream (FILE *stream); diff --git a/usr/src/lib/libparted/common/lib/closeout.c b/usr/src/lib/libparted/common/lib/closeout.c deleted file mode 100644 index 830f16f8ae..0000000000 --- a/usr/src/lib/libparted/common/lib/closeout.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Close standard output and standard error, exiting with a diagnostic on error. - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "closeout.h" - -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -#include "close-stream.h" -#include "error.h" -#include "exitfail.h" -#include "quotearg.h" - -static const char *file_name; - -/* Set the file name to be reported in the event an error is detected - by close_stdout. */ -void -close_stdout_set_file_name (const char *file) -{ - file_name = file; -} - -/* Close standard output. On error, issue a diagnostic and _exit - with status 'exit_failure'. - - Also close standard error. On error, _exit with status 'exit_failure'. - - Since close_stdout is commonly registered via 'atexit', POSIX - and the C standard both say that it should not call 'exit', - because the behavior is undefined if 'exit' is called more than - once. So it calls '_exit' instead of 'exit'. If close_stdout - is registered via atexit before other functions are registered, - the other functions can act before this _exit is invoked. - - Applications that use close_stdout should flush any streams - other than stdout and stderr before exiting, since the call to - _exit will bypass other buffer flushing. Applications should - be flushing and closing other streams anyway, to check for I/O - errors. Also, applications should not use tmpfile, since _exit - can bypass the removal of these files. - - It's important to detect such failures and exit nonzero because many - tools (most notably `make' and other build-management systems) depend - on being able to detect failure in other tools via their exit status. */ - -void -close_stdout (void) -{ - if (close_stream (stdout) != 0) - { - char const *write_error = _("write error"); - if (file_name) - error (0, errno, "%s: %s", quotearg_colon (file_name), - write_error); - else - error (0, errno, "%s", write_error); - - _exit (exit_failure); - } - - if (close_stream (stderr) != 0) - _exit (exit_failure); -} diff --git a/usr/src/lib/libparted/common/lib/closeout.h b/usr/src/lib/libparted/common/lib/closeout.h deleted file mode 100644 index 8bed23b5f1..0000000000 --- a/usr/src/lib/libparted/common/lib/closeout.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Close standard output and standard error. - - Copyright (C) 1998, 2000, 2003, 2004, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef CLOSEOUT_H -# define CLOSEOUT_H 1 - -# ifdef __cplusplus -extern "C" { -# endif - -void close_stdout_set_file_name (const char *file); -void close_stdout (void); - -# ifdef __cplusplus -} -# endif - -#endif diff --git a/usr/src/lib/libparted/common/lib/config.h b/usr/src/lib/libparted/common/lib/config.h deleted file mode 100644 index 41503d0b88..0000000000 --- a/usr/src/lib/libparted/common/lib/config.h +++ /dev/null @@ -1,597 +0,0 @@ -/* lib/config.h. Generated from config.h.in by configure. */ -/* lib/config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to the number of bits in type 'ptrdiff_t'. */ -#define BITSIZEOF_PTRDIFF_T 32 - -/* Define to the number of bits in type 'sig_atomic_t'. */ -#define BITSIZEOF_SIG_ATOMIC_T 32 - -/* Define to the number of bits in type 'size_t'. */ -#define BITSIZEOF_SIZE_T 32 - -/* Define to the number of bits in type 'wchar_t'. */ -#define BITSIZEOF_WCHAR_T 32 - -/* Define to the number of bits in type 'wint_t'. */ -#define BITSIZEOF_WINT_T 32 - -/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP - systems. This function is required for `alloca.c' support on those systems. - */ -/* #undef CRAY_STACKSEG_END */ - -/* Define to 1 if using `alloca.c'. */ -/* #undef C_ALLOCA */ - -/* Enable assertions, etc. */ -#define DEBUG 1 - -/* Probing functionality only */ -/* #undef DISCOVER_ONLY */ - -/* Define to 1 if // is a file system root distinct from /. */ -/* #undef DOUBLE_SLASH_IS_DISTINCT_ROOT */ - -/* Lazy linking to fs libs */ -/* #undef DYNAMIC_LOADING */ - -/* device mapper (libdevmapper) support */ -/* #undef ENABLE_DEVICE_MAPPER */ - -/* Include file system support. i.e. libparted/fs_... */ -#define ENABLE_FS 1 - -/* Mtrace malloc() debugging */ -/* #undef ENABLE_MTRACE */ - -/* Define to 1 if translation of program messages to the user's native - language is requested. */ -/* #undef ENABLE_NLS */ - -/* Include PC98 partition tables. (Sometimes excluded to avoid collisions with - msdos partition tables */ -#define ENABLE_PC98 1 - -/* Define on systems for which file names may have a so-called `drive letter' - prefix, define this to compute the length of that prefix, including the - colon. */ -#define FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX 0 - -/* Define if the backslash character may also serve as a file name component - separator. */ -#define FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR 0 - -/* Define if a drive letter prefix denotes a relative path if it is not - followed by a file name component separator. */ -#define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 - -/* Define to make the limit macros in visible. */ -#define GL_TRIGGER_STDC_LIMIT_MACROS 1 - -/* Define to 1 when using the gnulib module close-stream. */ -#define GNULIB_CLOSE_STREAM 1 - -/* Define to 1 if you have 'alloca' after including , a header that - may be supplied by this distribution. */ -#define HAVE_ALLOCA 1 - -/* Define HAVE_ALLOCA_H for backward compatibility with older code that - includes only if HAVE_ALLOCA_H is defined. */ -#define HAVE_ALLOCA_H 1 - -/* Define to 1 if you have the `atexit' function. */ -#define HAVE_ATEXIT 1 - -/* Has backtrace support */ -#define HAVE_BACKTRACE 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_BP_SYM_H */ - -/* Define to 1 if your system has a GNU libc compatible `calloc' function, and - to 0 otherwise. */ -#define HAVE_CALLOC 1 - -/* Define to 1 if you have the `canonicalize_file_name' function. */ -#define HAVE_CANONICALIZE_FILE_NAME 1 - -/* Define to 1 if you have the MacOS X function CFLocaleCopyCurrent in the - CoreFoundation framework. */ -/* #undef HAVE_CFLOCALECOPYCURRENT */ - -/* Define to 1 if you have the MacOS X function CFPreferencesCopyAppValue in - the CoreFoundation framework. */ -/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */ - -/* Define if the GNU dcgettext() function is already present or preinstalled. - */ -/* #undef HAVE_DCGETTEXT */ - -/* Define to 1 if you have the declaration of `getc_unlocked', and to 0 if you - don't. */ -#define HAVE_DECL_GETC_UNLOCKED 1 - -/* Define to 1 if you have the declaration of `getenv', and to 0 if you don't. - */ -#define HAVE_DECL_GETENV 1 - -/* Define to 1 if you have the declaration of `imaxabs', and to 0 if you - don't. */ -#define HAVE_DECL_IMAXABS 1 - -/* Define to 1 if you have the declaration of `imaxdiv', and to 0 if you - don't. */ -#define HAVE_DECL_IMAXDIV 1 - -/* Define to 1 if you have the declaration of `isblank', and to 0 if you - don't. */ -#define HAVE_DECL_ISBLANK 1 - -/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you - don't. */ -#define HAVE_DECL_STRERROR_R 1 - -/* Define to 1 if you have the declaration of `strndup', and to 0 if you - don't. */ -#define HAVE_DECL_STRNDUP 0 - -/* Define to 1 if you have the declaration of `strnlen', and to 0 if you - don't. */ -#define HAVE_DECL_STRNLEN 1 - -/* Define to 1 if you have the declaration of `strtoimax', and to 0 if you - don't. */ -#define HAVE_DECL_STRTOIMAX 1 - -/* Define to 1 if you have the declaration of `strtoumax', and to 0 if you - don't. */ -#define HAVE_DECL_STRTOUMAX 1 - -/* Define to 1 if you have the declaration of `__fpending', and to 0 if you - don't. */ -#define HAVE_DECL___FPENDING 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_GETOPT_H 1 - -/* Define to 1 if you have the `getopt_long_only' function. */ -#define HAVE_GETOPT_LONG_ONLY 1 - -/* Define if the GNU gettext() function is already present or preinstalled. */ -/* #undef HAVE_GETTEXT */ - -/* Define to 1 if you have the `getuid' function. */ -#define HAVE_GETUID 1 - -/* Define if your compiler supports the #include_next directive. */ -#define HAVE_INCLUDE_NEXT 1 - -/* Define to 1 if the compiler supports one of the keywords 'inline', - '__inline__', '__inline' and effectively inlines functions marked as such. - */ -/* #undef HAVE_INLINE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `isblank' function. */ -#define HAVE_ISBLANK 1 - -/* Define to 1 if you have the `iswcntrl' function. */ -#define HAVE_ISWCNTRL 1 - -/* Define to 1 if you have the `iswctype' function. */ -#define HAVE_ISWCTYPE 1 - -/* Define if you have and nl_langinfo(CODESET). */ -#define HAVE_LANGINFO_CODESET 1 - -/* Define to 1 if you have the `parted' library (-lparted). */ -/* #undef HAVE_LIBPARTED */ - -/* have readline */ -/* #undef HAVE_LIBREADLINE */ - -/* Have libreiserfs */ -/* #undef HAVE_LIBREISERFS */ - -/* Define to 1 if you have the header file. */ -#define HAVE_LOCALE_H 1 - -/* Define to 1 if the system has the type `long long int'. */ -#define HAVE_LONG_LONG_INT 1 - -/* Define to 1 if your system has a GNU libc compatible `malloc' function, and - to 0 otherwise. */ -#define HAVE_MALLOC 1 - -/* Define to 1 if you have the `mbrtowc' function. */ -#define HAVE_MBRTOWC 1 - -/* Define to 1 if you have the `mbsinit' function. */ -#define HAVE_MBSINIT 1 - -/* Define to 1 if declares mbstate_t. */ -#define HAVE_MBSTATE_T 1 - -/* Define to 1 if you have the `memchr' function. */ -#define HAVE_MEMCHR 1 - -/* Define to 1 if you have the `memcpy' function. */ -/* #undef HAVE_MEMCPY */ - -/* Define to 1 if you have the `memmove' function. */ -/* #undef HAVE_MEMMOVE */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `memset' function. */ -/* #undef HAVE_MEMSET */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_READLINE_READLINE_H */ - -/* Define to 1 if your system has a GNU libc compatible `realloc' function, - and to 0 otherwise. */ -#define HAVE_REALLOC 1 - -/* Have reiserfs_fs_check() */ -/* #undef HAVE_REISERFS_FS_CHECK */ - -/* Define to 1 if you have the `rl_completion_matches' function. */ -/* #undef HAVE_RL_COMPLETION_MATCHES */ - -/* Define to 1 if you have the `rpmatch' function. */ -/* #undef HAVE_RPMATCH */ - -/* Define to 1 if you have the `sigaction' function. */ -#define HAVE_SIGACTION 1 - -/* Define to 1 if 'sig_atomic_t' is a signed integer type. */ -#define HAVE_SIGNED_SIG_ATOMIC_T 1 - -/* Define to 1 if 'wchar_t' is a signed integer type. */ -#define HAVE_SIGNED_WCHAR_T 1 - -/* Define to 1 if 'wint_t' is a signed integer type. */ -#define HAVE_SIGNED_WINT_T 1 - -/* Define to 1 if stdbool.h conforms to C99. */ -#define HAVE_STDBOOL_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_EXT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the `strcspn' function. */ -/* #undef HAVE_STRCSPN */ - -/* Define to 1 if you have the `strerror_r' function. */ -#define HAVE_STRERROR_R 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 if you have the strndup() function and it works. */ -/* #undef HAVE_STRNDUP */ - -/* Define to 1 if you have the `strtol' function. */ -#define HAVE_STRTOL 1 - -/* Define if struct utimbuf is declared -- usually in . Some systems - have utime.h but don't declare the struct anywhere. */ -#define HAVE_STRUCT_UTIMBUF 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_SYS_BITYPES_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_INTTYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef HAVE_TERMCAP_H */ - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to 1 if the system has the type `unsigned long long int'. */ -#define HAVE_UNSIGNED_LONG_LONG_INT 1 - -/* Define if utimes accepts a null argument */ -/* #undef HAVE_UTIMES_NULL */ - -/* Define to 1 if you have the header file. */ -#define HAVE_UTIME_H 1 - -/* Define to 1 if `utime(file, NULL)' sets file's timestamp to the present. */ -#define HAVE_UTIME_NULL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WCHAR_H 1 - -/* Define to 1 if you have the `wcrtomb' function. */ -#define HAVE_WCRTOMB 1 - -/* Define to 1 if you have the `wcscoll' function. */ -#define HAVE_WCSCOLL 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_WCTYPE_H 1 - -/* Define if you have the 'wint_t' type. */ -#define HAVE_WINT_T 1 - -/* Define to 1 if the system has the type `_Bool'. */ -#define HAVE__BOOL 1 - -/* Define to 1 if you have the `__fpending' function. */ -#define HAVE___FPENDING 1 - -/* Extract low level special HFS(+) files for debugging purposes when using - the "check" command (NOT FOR PACKAGING) */ -/* #undef HFS_EXTRACT_FS */ - -#if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -#else -# define ISSLASH(C) ((C) == '/') -#endif - -/* Define to 1 if assertions should be disabled. */ -/* #undef NDEBUG */ - -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ - -/* Name of package */ -#define PACKAGE "parted" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "bug-parted@gnu.org" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "GNU parted" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "GNU parted 1.8.8" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "parted" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.8.8" - -/* the number of pending output bytes on stream `fp' */ -/* #undef PENDING_OUTPUT_N_BYTES */ - -/* Define if exists and defines unusable PRI* macros. */ -/* #undef PRI_MACROS_BROKEN */ - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'ptrdiff_t'. */ -#define PTRDIFF_T_SUFFIX - -/* Disable all writing code */ -/* #undef READ_ONLY */ - -/* Define if rename does not work for source file names with a trailing slash, - like the one from SunOS 4.1.1_U1. */ -/* #undef RENAME_TRAILING_SLASH_BUG */ - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'sig_atomic_t'. */ -#define SIG_ATOMIC_T_SUFFIX - -/* The size of `off_t', as computed by sizeof. */ -#define SIZEOF_OFF_T 4 - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'size_t'. */ -#define SIZE_T_SUFFIX u - -/* If using the C implementation of alloca, define if you know the - direction of stack growth for your system; otherwise it will be - automatically deduced at runtime. - STACK_DIRECTION > 0 => grows toward higher addresses - STACK_DIRECTION < 0 => grows toward lower addresses - STACK_DIRECTION = 0 => direction of growth unknown */ -/* #undef STACK_DIRECTION */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define to 1 if strerror_r returns char *. */ -/* #undef STRERROR_R_CHAR_P */ - -/* Version number of package */ -#define VERSION "1.8.8" - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wchar_t'. */ -#define WCHAR_T_SUFFIX l - -/* Define to l, ll, u, ul, ull, etc., as suitable for constants of type - 'wint_t'. */ -#define WINT_T_SUFFIX l - -/* Define to 1 if your processor stores words with the most significant byte - first (like Motorola and SPARC, unlike Intel and VAX). */ -/* #undef WORDS_BIGENDIAN */ - -/* Define to 1 if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* # undef _ALL_SOURCE */ -#endif - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _FILE_OFFSET_BITS */ - -/* Enable GNU extensions on systems that have them. */ -#ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 -#endif - -/* Define for large files, on AIX-style hosts. */ -/* #undef _LARGE_FILES */ - -/* Define to 1 if on MINIX. */ -/* #undef _MINIX */ - -/* Define to 2 if the system does not provide POSIX.1 features except with - this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define to 1 if you need to in order for `stat' and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define if you want regoff_t to be at least as wide POSIX requires. */ -#define _REGEX_LARGE_OFFSETS 1 - -/* Enable extensions on Solaris. */ -#ifndef __EXTENSIONS__ -# define __EXTENSIONS__ 1 -#endif -#ifndef _POSIX_PTHREAD_SEMANTICS -# define _POSIX_PTHREAD_SEMANTICS 1 -#endif -#ifndef _TANDEM_SOURCE -# define _TANDEM_SOURCE 1 -#endif - -/* Define to rpl_ if the getopt replacement functions and variables should be - used. */ -#define __GETOPT_PREFIX rpl_ - -/* Ensure that defines the limit macros, since gnulib's - relies on them. */ -#if defined __cplusplus && !defined __STDC_LIMIT_MACROS && GL_TRIGGER_STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS 1 -#endif - - -/* Define to rpl_calloc if the replacement function should be used. */ -/* #undef calloc */ - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define to rpl_free if the replacement function should be used. */ -/* #undef free */ - -/* A replacement for va_copy, if needed. */ -#define gl_va_copy(a,b) ((a) = (b)) - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif - -/* Define to rpl_malloc if the replacement function should be used. */ -/* #undef malloc */ - -/* Define to a type if does not define. */ -/* #undef mbstate_t */ - -/* Define to rpl_memcmp if the replacement function should be used. */ -/* #undef memcmp */ - -/* Define to rpl_re_comp if the replacement should be used. */ -#define re_comp rpl_re_comp - -/* Define to rpl_re_compile_fastmap if the replacement should be used. */ -#define re_compile_fastmap rpl_re_compile_fastmap - -/* Define to rpl_re_compile_pattern if the replacement should be used. */ -#define re_compile_pattern rpl_re_compile_pattern - -/* Define to rpl_re_exec if the replacement should be used. */ -#define re_exec rpl_re_exec - -/* Define to rpl_re_match if the replacement should be used. */ -#define re_match rpl_re_match - -/* Define to rpl_re_match_2 if the replacement should be used. */ -#define re_match_2 rpl_re_match_2 - -/* Define to rpl_re_search if the replacement should be used. */ -#define re_search rpl_re_search - -/* Define to rpl_re_search_2 if the replacement should be used. */ -#define re_search_2 rpl_re_search_2 - -/* Define to rpl_re_set_registers if the replacement should be used. */ -#define re_set_registers rpl_re_set_registers - -/* Define to rpl_re_set_syntax if the replacement should be used. */ -#define re_set_syntax rpl_re_set_syntax - -/* Define to rpl_re_syntax_options if the replacement should be used. */ -#define re_syntax_options rpl_re_syntax_options - -/* Define to rpl_realloc if the replacement function should be used. */ -/* #undef realloc */ - -/* Define to rpl_regcomp if the replacement should be used. */ -#define regcomp rpl_regcomp - -/* Define to rpl_regerror if the replacement should be used. */ -#define regerror rpl_regerror - -/* Define to rpl_regexec if the replacement should be used. */ -#define regexec rpl_regexec - -/* Define to rpl_regfree if the replacement should be used. */ -#define regfree rpl_regfree - -/* Define to rpl_rename if the replacement function should be used. */ -/* #undef rename */ - -/* Define to equivalent of C99 restrict keyword, or to nothing if this is not - supported. Do not define if restrict is supported directly. */ -/* #undef restrict */ - -/* Define to `unsigned int' if does not define. */ -/* #undef size_t */ - -/* Define as a signed type of the same size as size_t. */ -/* #undef ssize_t */ - -/* Define to rpl_strnlen if the replacement function should be used. */ -/* #undef strnlen */ - -/* Define to rpl_strtod if the replacement function should be used. */ -/* #undef strtod */ - -/* Define to rpl_utime if the replacement function should be used. */ -/* #undef utime */ - -/* Define as a macro for copying va_list variables. */ -/* #undef va_copy */ diff --git a/usr/src/lib/libparted/common/lib/configmake.h b/usr/src/lib/libparted/common/lib/configmake.h deleted file mode 100644 index cd1b6883f7..0000000000 --- a/usr/src/lib/libparted/common/lib/configmake.h +++ /dev/null @@ -1,25 +0,0 @@ -/* DO NOT EDIT! GENERATED AUTOMATICALLY! */ -#define PREFIX "/usr/local" -#define EXEC_PREFIX "/usr/local" -#define BINDIR "/usr/local/bin" -#define SBINDIR "/usr/local/sbin" -#define LIBEXECDIR "/usr/local/libexec" -#define DATAROOTDIR "/usr/local/share" -#define DATADIR "/usr/local/share" -#define SYSCONFDIR "/usr/local/etc" -#define SHAREDSTATEDIR "/usr/local/com" -#define LOCALSTATEDIR "/usr/local/var" -#define INCLUDEDIR "/usr/local/include" -#define OLDINCLUDEDIR "/usr/include" -#define DOCDIR "/usr/local/share/doc/parted" -#define INFODIR "/usr/local/share/info" -#define HTMLDIR "/usr/local/share/doc/parted" -#define DVIDIR "/usr/local/share/doc/parted" -#define PDFDIR "/usr/local/share/doc/parted" -#define PSDIR "/usr/local/share/doc/parted" -#define LIBDIR "/usr/local/lib" -#define LOCALEDIR "/usr/local/share/locale" -#define MANDIR "/usr/local/share/man" -#define PKGDATADIR "/usr/local/share/parted" -#define PKGINCLUDEDIR "/usr/local/include/parted" -#define PKGLIBDIR "/usr/local/lib/parted" diff --git a/usr/src/lib/libparted/common/lib/dirname.c b/usr/src/lib/libparted/common/lib/dirname.c deleted file mode 100644 index 16552c64d2..0000000000 --- a/usr/src/lib/libparted/common/lib/dirname.c +++ /dev/null @@ -1,85 +0,0 @@ -/* dirname.c -- return all but the last element in a file name - - Copyright (C) 1990, 1998, 2000, 2001, 2003, 2004, 2005, 2006 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "dirname.h" - -#include -#include "xalloc.h" - -/* Return the length of the prefix of FILE that will be used by - dir_name. If FILE is in the working directory, this returns zero - even though `dir_name (FILE)' will return ".". Works properly even - if there are trailing slashes (by effectively ignoring them). */ - -size_t -dir_len (char const *file) -{ - size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); - size_t length; - - /* Advance prefix_length beyond important leading slashes. */ - prefix_length += (prefix_length != 0 - ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && ISSLASH (file[prefix_length])) - : (ISSLASH (file[0]) - ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT - && ISSLASH (file[1]) && ! ISSLASH (file[2]) - ? 2 : 1)) - : 0)); - - /* Strip the basename and any redundant slashes before it. */ - for (length = last_component (file) - file; - prefix_length < length; length--) - if (! ISSLASH (file[length - 1])) - break; - return length; -} - - -/* In general, we can't use the builtin `dirname' function if available, - since it has different meanings in different environments. - In some environments the builtin `dirname' modifies its argument. - - Return the leading directories part of FILE, allocated with xmalloc. - Works properly even if there are trailing slashes (by effectively - ignoring them). Unlike POSIX dirname(), FILE cannot be NULL. - - If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); - lstat (base_name (FILE)); } will access the same file. Likewise, - if the sequence { chdir (dir_name (FILE)); - rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE - to "foo" in the same directory FILE was in. */ - -char * -dir_name (char const *file) -{ - size_t length = dir_len (file); - bool append_dot = (length == 0 - || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE - && length == FILE_SYSTEM_PREFIX_LEN (file) - && file[2] != '\0' && ! ISSLASH (file[2]))); - char *dir = xmalloc (length + append_dot + 1); - memcpy (dir, file, length); - if (append_dot) - dir[length++] = '.'; - dir[length] = '\0'; - return dir; -} diff --git a/usr/src/lib/libparted/common/lib/dirname.h b/usr/src/lib/libparted/common/lib/dirname.h deleted file mode 100644 index 91e7ed3366..0000000000 --- a/usr/src/lib/libparted/common/lib/dirname.h +++ /dev/null @@ -1,70 +0,0 @@ -/* Take file names apart into directory and base names. - - Copyright (C) 1998, 2001, 2003-2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef DIRNAME_H_ -# define DIRNAME_H_ 1 - -# include -# include - -# ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -# endif - -# ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -# endif - -# ifndef FILE_SYSTEM_PREFIX_LEN -# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX - /* This internal macro assumes ASCII, but all hosts that support drive - letters use ASCII. */ -# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \ - <= 'z' - 'a') -# define FILE_SYSTEM_PREFIX_LEN(Filename) \ - (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) -# else -# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 -# endif -# endif - -# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE -# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 -# endif - -# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT -# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 -# endif - -# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE -# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) -# else -# define IS_ABSOLUTE_FILE_NAME(F) \ - (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F)) -# endif -# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) - -char *base_name (char const *file); -char *dir_name (char const *file); -size_t base_len (char const *file); -size_t dir_len (char const *file); -char *last_component (char const *file); - -bool strip_trailing_slashes (char *file); - -#endif /* not DIRNAME_H_ */ diff --git a/usr/src/lib/libparted/common/lib/error.c b/usr/src/lib/libparted/common/lib/error.c deleted file mode 100644 index 9cf67ff904..0000000000 --- a/usr/src/lib/libparted/common/lib/error.c +++ /dev/null @@ -1,339 +0,0 @@ -/* Error handler for noninteractive utilities - Copyright (C) 1990-1998, 2000-2007 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by David MacKenzie . */ - -#if !_LIBC -# include -#endif - -#include "error.h" - -#include -#include -#include -#include - -#if !_LIBC && ENABLE_NLS -# include "gettext.h" -# define _(msgid) gettext (msgid) -#endif - -#ifdef _LIBC -# include -# include -# include -# include -# define mbsrtowcs __mbsrtowcs -#endif - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#ifndef _ -# define _(String) String -#endif - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -unsigned int error_message_count; - -#ifdef _LIBC -/* In the GNU C library, there is a predefined variable for this. */ - -# define program_name program_invocation_name -# include -# include -# include - -/* In GNU libc we want do not want to use the common name `error' directly. - Instead make it a weak alias. */ -extern void __error (int status, int errnum, const char *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern void __error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, - ...) - __attribute__ ((__format__ (__printf__, 5, 6)));; -# define error __error -# define error_at_line __error_at_line - -# include -# define fflush(s) INTUSE(_IO_fflush) (s) -# undef putc -# define putc(c, fp) INTUSE(_IO_putc) (c, fp) - -# include - -#else /* not _LIBC */ - -# if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P -# ifndef HAVE_DECL_STRERROR_R -"this configure-time declaration test was not run" -# endif -char *strerror_r (); -# endif - -/* The calling program should define program_name and set it to the - name of the executing program. */ -extern char *program_name; - -# if HAVE_STRERROR_R || defined strerror_r -# define __strerror_r strerror_r -# endif /* HAVE_STRERROR_R || defined strerror_r */ -#endif /* not _LIBC */ - -static void -print_errno_message (int errnum) -{ - char const *s; - -#if defined HAVE_STRERROR_R || _LIBC - char errbuf[1024]; -# if STRERROR_R_CHAR_P || _LIBC - s = __strerror_r (errnum, errbuf, sizeof errbuf); -# else - if (__strerror_r (errnum, errbuf, sizeof errbuf) == 0) - s = errbuf; - else - s = 0; -# endif -#else - s = strerror (errnum); -#endif - -#if !_LIBC - if (! s) - s = _("Unknown system error"); -#endif - -#if _LIBC - __fxprintf (NULL, ": %s", s); -#else - fprintf (stderr, ": %s", s); -#endif -} - -static void -error_tail (int status, int errnum, const char *message, va_list args) -{ -#if _LIBC - if (_IO_fwide (stderr, 0) > 0) - { -# define ALLOCA_LIMIT 2000 - size_t len = strlen (message) + 1; - wchar_t *wmessage = NULL; - mbstate_t st; - size_t res; - const char *tmp; - bool use_malloc = false; - - while (1) - { - if (__libc_use_alloca (len * sizeof (wchar_t))) - wmessage = (wchar_t *) alloca (len * sizeof (wchar_t)); - else - { - if (!use_malloc) - wmessage = NULL; - - wchar_t *p = (wchar_t *) realloc (wmessage, - len * sizeof (wchar_t)); - if (p == NULL) - { - free (wmessage); - fputws_unlocked (L"out of memory\n", stderr); - return; - } - wmessage = p; - use_malloc = true; - } - - memset (&st, '\0', sizeof (st)); - tmp = message; - - res = mbsrtowcs (wmessage, &tmp, len, &st); - if (res != len) - break; - - if (__builtin_expect (len >= SIZE_MAX / 2, 0)) - { - /* This really should not happen if everything is fine. */ - res = (size_t) -1; - break; - } - - len *= 2; - } - - if (res == (size_t) -1) - { - /* The string cannot be converted. */ - if (use_malloc) - { - free (wmessage); - use_malloc = false; - } - wmessage = (wchar_t *) L"???"; - } - - __vfwprintf (stderr, wmessage, args); - - if (use_malloc) - free (wmessage); - } - else -#endif - vfprintf (stderr, message, args); - va_end (args); - - ++error_message_count; - if (errnum) - print_errno_message (errnum); -#if _LIBC - __fxprintf (NULL, "\n"); -#else - putc ('\n', stderr); -#endif - fflush (stderr); - if (status) - exit (status); -} - - -/* Print the program name and error message MESSAGE, which is a printf-style - format string with optional args. - If ERRNUM is nonzero, print its corresponding system error message. - Exit with status STATUS if it is nonzero. */ -void -error (int status, int errnum, const char *message, ...) -{ - va_list args; - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - fflush (stdout); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s: ", program_name); -#else - fprintf (stderr, "%s: ", program_name); -#endif - } - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -int error_one_per_line; - -void -error_at_line (int status, int errnum, const char *file_name, - unsigned int line_number, const char *message, ...) -{ - va_list args; - - if (error_one_per_line) - { - static const char *old_file_name; - static unsigned int old_line_number; - - if (old_line_number == line_number - && (file_name == old_file_name - || strcmp (old_file_name, file_name) == 0)) - /* Simply return and print nothing. */ - return; - - old_file_name = file_name; - old_line_number = line_number; - } - -#if defined _LIBC && defined __libc_ptf_call - /* We do not want this call to be cut short by a thread - cancellation. Therefore disable cancellation for now. */ - int state = PTHREAD_CANCEL_ENABLE; - __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state), - 0); -#endif - - fflush (stdout); -#ifdef _LIBC - _IO_flockfile (stderr); -#endif - if (error_print_progname) - (*error_print_progname) (); - else - { -#if _LIBC - __fxprintf (NULL, "%s:", program_name); -#else - fprintf (stderr, "%s:", program_name); -#endif - } - -#if _LIBC - __fxprintf (NULL, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#else - fprintf (stderr, file_name != NULL ? "%s:%d: " : " ", - file_name, line_number); -#endif - - va_start (args, message); - error_tail (status, errnum, message, args); - -#ifdef _LIBC - _IO_funlockfile (stderr); -# ifdef __libc_ptf_call - __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0); -# endif -#endif -} - -#ifdef _LIBC -/* Make the weak alias. */ -# undef error -# undef error_at_line -weak_alias (__error, error) -weak_alias (__error_at_line, error_at_line) -#endif diff --git a/usr/src/lib/libparted/common/lib/error.h b/usr/src/lib/libparted/common/lib/error.h deleted file mode 100644 index 5a5f247658..0000000000 --- a/usr/src/lib/libparted/common/lib/error.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Declaration for error-reporting function - Copyright (C) 1995, 1996, 1997, 2003, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _ERROR_H -#define _ERROR_H 1 - -#ifndef __attribute__ -/* This feature is available in gcc versions 2.5 and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__ -# define __attribute__(Spec) /* empty */ -# endif -/* The __-protected variants of `format' and `printf' attributes - are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __format__ format -# define __printf__ printf -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Print a message with `fprintf (stderr, FORMAT, ...)'; - if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). - If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ - -extern void error (int __status, int __errnum, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); - -extern void error_at_line (int __status, int __errnum, const char *__fname, - unsigned int __lineno, const char *__format, ...) - __attribute__ ((__format__ (__printf__, 5, 6))); - -/* If NULL, error will flush stdout, then print on stderr the program - name, a colon and a space. Otherwise, error will call this - function without parameters instead. */ -extern void (*error_print_progname) (void); - -/* This variable is incremented each time `error' is called. */ -extern unsigned int error_message_count; - -/* Sometimes we want to have at most one error per line. This - variable controls whether this mode is selected or not. */ -extern int error_one_per_line; - -#ifdef __cplusplus -} -#endif - -#endif /* error.h */ diff --git a/usr/src/lib/libparted/common/lib/exitfail.c b/usr/src/lib/libparted/common/lib/exitfail.c deleted file mode 100644 index 373d325c5a..0000000000 --- a/usr/src/lib/libparted/common/lib/exitfail.c +++ /dev/null @@ -1,26 +0,0 @@ -/* Failure exit status - - Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. - If not, write to the Free Software Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "exitfail.h" - -#include - -int volatile exit_failure = EXIT_FAILURE; diff --git a/usr/src/lib/libparted/common/lib/exitfail.h b/usr/src/lib/libparted/common/lib/exitfail.h deleted file mode 100644 index e46cf9c166..0000000000 --- a/usr/src/lib/libparted/common/lib/exitfail.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Failure exit status - - Copyright (C) 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. - If not, write to the Free Software Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -extern int volatile exit_failure; diff --git a/usr/src/lib/libparted/common/lib/full-write.c b/usr/src/lib/libparted/common/lib/full-write.c deleted file mode 100644 index cc168720ea..0000000000 --- a/usr/src/lib/libparted/common/lib/full-write.c +++ /dev/null @@ -1,81 +0,0 @@ -/* An interface to read and write that retries (if necessary) until complete. - - Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#ifdef FULL_READ -# include "full-read.h" -#else -# include "full-write.h" -#endif - -#include - -#ifdef FULL_READ -# include "safe-read.h" -# define safe_rw safe_read -# define full_rw full_read -# undef const -# define const /* empty */ -#else -# include "safe-write.h" -# define safe_rw safe_write -# define full_rw full_write -#endif - -#ifdef FULL_READ -/* Set errno to zero upon EOF. */ -# define ZERO_BYTE_TRANSFER_ERRNO 0 -#else -/* Some buggy drivers return 0 when one tries to write beyond - a device's end. (Example: Linux 1.2.13 on /dev/fd0.) - Set errno to ENOSPC so they get a sensible diagnostic. */ -# define ZERO_BYTE_TRANSFER_ERRNO ENOSPC -#endif - -/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if - interrupted or if a partial write(read) occurs. Return the number - of bytes transferred. - When writing, set errno if fewer than COUNT bytes are written. - When reading, if fewer than COUNT bytes are read, you must examine - errno to distinguish failure from EOF (errno == 0). */ -size_t -full_rw (int fd, const void *buf, size_t count) -{ - size_t total = 0; - const char *ptr = (const char *) buf; - - while (count > 0) - { - size_t n_rw = safe_rw (fd, ptr, count); - if (n_rw == (size_t) -1) - break; - if (n_rw == 0) - { - errno = ZERO_BYTE_TRANSFER_ERRNO; - break; - } - total += n_rw; - ptr += n_rw; - count -= n_rw; - } - - return total; -} diff --git a/usr/src/lib/libparted/common/lib/full-write.h b/usr/src/lib/libparted/common/lib/full-write.h deleted file mode 100644 index d20d2fe4ab..0000000000 --- a/usr/src/lib/libparted/common/lib/full-write.h +++ /dev/null @@ -1,35 +0,0 @@ -/* An interface to write() that writes all it is asked to write. - - Copyright (C) 2002-2003 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Write COUNT bytes at BUF to descriptor FD, retrying if interrupted - or if partial writes occur. Return the number of bytes successfully - written, setting errno if that is less than COUNT. */ -extern size_t full_write (int fd, const void *buf, size_t count); - - -#ifdef __cplusplus -} -#endif diff --git a/usr/src/lib/libparted/common/lib/getopt.c b/usr/src/lib/libparted/common/lib/getopt.c deleted file mode 100644 index 3580ad825c..0000000000 --- a/usr/src/lib/libparted/common/lib/getopt.c +++ /dev/null @@ -1,1191 +0,0 @@ -/* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to drepper@gnu.org - before changing it! - Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBC -# include -#endif - -#include "getopt.h" - -#include -#include -#include -#include - -#ifdef __VMS -# include -#endif - -#ifdef _LIBC -# include -#else -# include "gettext.h" -# define _(msgid) gettext (msgid) -#endif - -#if defined _LIBC && defined USE_IN_LIBIO -# include -#endif - -#ifndef attribute_hidden -# define attribute_hidden -#endif - -/* Unlike standard Unix `getopt', functions like `getopt_long' - let the user intersperse the options with the other arguments. - - As `getopt_long' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Using `getopt' or setting the environment variable POSIXLY_CORRECT - disables permutation. - Then the application's behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt_int.h" - -/* For communication from `getopt' to the caller. - When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ - -char *optarg; - -/* Index in ARGV of the next element to be scanned. - This is used for communication to and from the caller - and for communication between successive calls to `getopt'. - - On entry to `getopt', zero means this is the first call; initialize. - - When `getopt' returns -1, this is the index of the first of the - non-option elements that the caller should itself scan. - - Otherwise, `optind' communicates from one call to the next - how much of ARGV has been scanned so far. */ - -/* 1003.2 says this must be 1 before any call. */ -int optind = 1; - -/* Callers store zero here to inhibit the error message - for unrecognized options. */ - -int opterr = 1; - -/* Set to an option character which was unrecognized. - This must be initialized on some systems to avoid linking in the - system's own getopt implementation. */ - -int optopt = '?'; - -/* Keep a global copy of all internal members of getopt_data. */ - -static struct _getopt_data getopt_data; - - -#if defined HAVE_DECL_GETENV && !HAVE_DECL_GETENV -extern char *getenv (); -#endif - -#ifdef _LIBC -/* Stored original parameters. - XXX This is no good solution. We should rather copy the args so - that we can compare them later. But we must not use malloc(3). */ -extern int __libc_argc; -extern char **__libc_argv; - -/* Bash 2.0 gives us an environment variable containing flags - indicating ARGV elements that should not be considered arguments. */ - -# ifdef USE_NONOPTION_FLAGS -/* Defined in getopt_init.c */ -extern char *__getopt_nonoption_flags; -# endif - -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ - if (d->__nonoption_flags_len > 0) \ - { \ - char __tmp = __getopt_nonoption_flags[ch1]; \ - __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ - __getopt_nonoption_flags[ch2] = __tmp; \ - } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ - -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (char **argv, struct _getopt_data *d) -{ - int bottom = d->__first_nonopt; - int middle = d->__last_nonopt; - int top = d->optind; - char *tem; - - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - d->__nonoption_flags_max_len), - '\0', top + 1 - d->__nonoption_flags_max_len); - d->__nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } - } -#endif - - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } - } - - /* Update records for the slots the non-options now occupy. */ - - d->__first_nonopt += (d->optind - d->__last_nonopt); - d->__last_nonopt = d->optind; -} - -/* Initialize the internal data when the first call is made. */ - -static const char * -_getopt_initialize (int argc, char **argv, const char *optstring, - int posixly_correct, struct _getopt_data *d) -{ - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ - - d->__first_nonopt = d->__last_nonopt = d->optind; - - d->__nextchar = NULL; - - d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - d->__ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - d->__ordering = REQUIRE_ORDER; - ++optstring; - } - else if (d->__posixly_correct) - d->__ordering = REQUIRE_ORDER; - else - d->__ordering = PERMUTE; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - if (!d->__posixly_correct - && argc == __libc_argc && argv == __libc_argv) - { - if (d->__nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - d->__nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = d->__nonoption_flags_max_len = strlen (orig_str); - if (d->__nonoption_flags_max_len < argc) - d->__nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (d->__nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - d->__nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', d->__nonoption_flags_max_len - len); - } - } - d->__nonoption_flags_len = d->__nonoption_flags_max_len; - } - else - d->__nonoption_flags_len = 0; -#endif - - return optstring; -} - -/* Scan elements of ARGV (whose length is ARGC) for option characters - given in OPTSTRING. - - If an element of ARGV starts with '-', and is not exactly "-" or "--", - then it is an option element. The characters of this element - (aside from the initial '-') are option characters. If `getopt' - is called repeatedly, it returns successively each of the option characters - from each of the option elements. - - If `getopt' finds another option character, it returns that character, - updating `optind' and `nextchar' so that the next call to `getopt' can - resume the scan with the following option character or ARGV-element. - - If there are no more option characters, `getopt' returns -1. - Then `optind' is the index in ARGV of the first ARGV-element - that is not an option. (The ARGV-elements have been permuted - so that those that are not options now come last.) - - OPTSTRING is a string containing the legitimate option characters. - If an option character is seen that is not listed in OPTSTRING, - return '?' after printing an error message. If you set `opterr' to - zero, the error message is suppressed but we still return '?'. - - If a char in OPTSTRING is followed by a colon, that means it wants an arg, - so the following text in the same ARGV-element, or the text of the following - ARGV-element, is returned in `optarg'. Two colons mean an option that - wants an optional arg; if there is text in the current ARGV-element, - it is returned in `optarg', otherwise `optarg' is set to zero. - - If OPTSTRING starts with `-' or `+', it requests different methods of - handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. - - Long-named options begin with `--' instead of `-'. - Their names may be abbreviated as long as the abbreviation is unique - or is an exact match for some defined option. If they have an - argument, it follows the option name in the same ARGV-element, separated - from the option name by a `=', or else the in next ARGV-element. - When `getopt' finds a long-named option, it returns 0 if that option's - `flag' field is nonzero, the value of the option's `val' field - if the `flag' field is zero. - - LONGOPTS is a vector of `struct option' terminated by an - element containing a name which is zero. - - LONGIND returns the index in LONGOPT of the long-named option found. - It is only valid when a long-named option has been found by the most - recent call. - - If LONG_ONLY is nonzero, '-' as well as '--' can introduce - long-named options. - - If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT - environment variable were set. */ - -int -_getopt_internal_r (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, int posixly_correct, struct _getopt_data *d) -{ - int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; - - if (argc < 1) - return -1; - - d->optarg = NULL; - - if (d->optind == 0 || !d->__initialized) - { - if (d->optind == 0) - d->optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring, - posixly_correct, d); - d->__initialized = 1; - } - - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ -#if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ - || (d->optind < d->__nonoption_flags_len \ - && __getopt_nonoption_flags[d->optind] == '1')) -#else -# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') -#endif - - if (d->__nextchar == NULL || *d->__nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (d->__last_nonopt > d->optind) - d->__last_nonopt = d->optind; - if (d->__first_nonopt > d->optind) - d->__first_nonopt = d->optind; - - if (d->__ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__last_nonopt != d->optind) - d->__first_nonopt = d->optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (d->optind < argc && NONOPTION_P) - d->optind++; - d->__last_nonopt = d->optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (d->optind != argc && !strcmp (argv[d->optind], "--")) - { - d->optind++; - - if (d->__first_nonopt != d->__last_nonopt - && d->__last_nonopt != d->optind) - exchange ((char **) argv, d); - else if (d->__first_nonopt == d->__last_nonopt) - d->__first_nonopt = d->optind; - d->__last_nonopt = argc; - - d->optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (d->optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (d->__first_nonopt != d->__last_nonopt) - d->optind = d->__first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (d->__ordering == REQUIRE_ORDER) - return -1; - d->optarg = argv[d->optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - d->__nextchar = (argv[d->optind] + 1 - + (longopts != NULL && argv[d->optind][1] == '-')); - } - - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[d->optind][1] == '-' - || (long_only && (argv[d->optind][2] - || !strchr (optstring, argv[d->optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[d->optind]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - d->optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - d->optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind - 1][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#else - fprintf (stderr, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#else - fprintf (stderr, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[d->optind - 1][0], - pfound->name); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - - d->__nextchar += strlen (d->__nextchar); - - d->optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[d->optind][1] == '-' - || strchr (optstring, *d->__nextchar) == NULL) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (argv[d->optind][1] == '-') - { - /* --option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), - argv[0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], d->__nextchar); -#endif - } - else - { - /* +option or -option */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#else - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[d->optind][0], d->__nextchar); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->__nextchar = (char *) ""; - d->optind++; - d->optopt = 0; - return '?'; - } - } - - /* Look at and handle the next short option-character. */ - - { - char c = *d->__nextchar++; - char *temp = strchr (optstring, c); - - /* Increment `optind' when we start to process its last character. */ - if (*d->__nextchar == '\0') - ++d->optind; - - if (temp == NULL || c == ':') - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; -#endif - - if (d->__posixly_correct) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: illegal option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); -#endif - } - else - { -#if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: invalid option -- %c\n"), - argv[0], c); -#else - fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); -#endif - } - -#if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#endif - } - d->optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, - _("%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `d->optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; - nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) - { - if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - d->optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - d->optarg = nameend + 1; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); -#endif - } - - d->__nextchar += strlen (d->__nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (d->optind < argc) - d->optarg = argv[d->optind++]; - else - { - if (print_errors) - { -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 - |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); -#endif - } - d->__nextchar += strlen (d->__nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - d->__nextchar += strlen (d->__nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - d->__nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - d->optind++; - } - else - d->optarg = NULL; - d->__nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*d->__nextchar != '\0') - { - d->optarg = d->__nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - d->optind++; - } - else if (d->optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ -#if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - _IO_flockfile (stderr); - - int old_flags2 = ((_IO_FILE *) stderr)->_flags2; - ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; - - __fxprintf (NULL, "%s", buf); - - ((_IO_FILE *) stderr)->_flags2 = old_flags2; - _IO_funlockfile (stderr); - - free (buf); - } -#else - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); -#endif - } - d->optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - d->optarg = argv[d->optind++]; - d->__nextchar = NULL; - } - } - return c; - } -} - -int -_getopt_internal (int argc, char **argv, const char *optstring, - const struct option *longopts, int *longind, - int long_only, int posixly_correct) -{ - int result; - - getopt_data.optind = optind; - getopt_data.opterr = opterr; - - result = _getopt_internal_r (argc, argv, optstring, longopts, longind, - long_only, posixly_correct, &getopt_data); - - optind = getopt_data.optind; - optarg = getopt_data.optarg; - optopt = getopt_data.optopt; - - return result; -} - -/* glibc gets a LSB-compliant getopt. - Standalone applications get a POSIX-compliant getopt. */ -#if _LIBC -enum { POSIXLY_CORRECT = 0 }; -#else -enum { POSIXLY_CORRECT = 1 }; -#endif - -int -getopt (int argc, char *const *argv, const char *optstring) -{ - return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, - POSIXLY_CORRECT); -} - - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ - -int -main (int argc, char **argv) -{ - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); -} - -#endif /* TEST */ diff --git a/usr/src/lib/libparted/common/lib/getopt_int.h b/usr/src/lib/libparted/common/lib/getopt_int.h deleted file mode 100644 index 401579fd28..0000000000 --- a/usr/src/lib/libparted/common/lib/getopt_int.h +++ /dev/null @@ -1,131 +0,0 @@ -/* Internal declarations for getopt. - Copyright (C) 1989-1994,1996-1999,2001,2003,2004 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _GETOPT_INT_H -#define _GETOPT_INT_H 1 - -extern int _getopt_internal (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct); - - -/* Reentrant versions which can handle parsing multiple argument - vectors at the same time. */ - -/* Data type for reentrant functions. */ -struct _getopt_data -{ - /* These have exactly the same meaning as the corresponding global - variables, except that they are used for the reentrant - versions of getopt. */ - int optind; - int opterr; - int optopt; - char *optarg; - - /* Internal members. */ - - /* True if the internal members have been initialized. */ - int __initialized; - - /* The next char to be scanned in the option-element - in which the last option character we returned was found. - This allows us to pick up the scan where we left off. - - If this is zero, or a null string, it means resume the scan - by advancing to the next ARGV-element. */ - char *__nextchar; - - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - - enum - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; - - /* If the POSIXLY_CORRECT environment variable is set - or getopt was called. */ - int __posixly_correct; - - - /* Handle permutation of arguments. */ - - /* Describe the part of ARGV that contains non-options that have - been skipped. `first_nonopt' is the index in ARGV of the first - of them; `last_nonopt' is the index after the last of them. */ - - int __first_nonopt; - int __last_nonopt; - -#if defined _LIBC && defined USE_NONOPTION_FLAGS - int __nonoption_flags_max_len; - int __nonoption_flags_len; -# endif -}; - -/* The initializer is necessary to set OPTIND and OPTERR to their - default values and to clear the initialization flag. */ -#define _GETOPT_DATA_INITIALIZER { 1, 1 } - -extern int _getopt_internal_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only, int __posixly_correct, - struct _getopt_data *__data); - -extern int _getopt_long_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - struct _getopt_data *__data); - -extern int _getopt_long_only_r (int ___argc, char **___argv, - const char *__shortopts, - const struct option *__longopts, - int *__longind, - struct _getopt_data *__data); - -#endif /* getopt_int.h */ diff --git a/usr/src/lib/libparted/common/lib/gettext.h b/usr/src/lib/libparted/common/lib/gettext.h deleted file mode 100644 index 9d76ec9afc..0000000000 --- a/usr/src/lib/libparted/common/lib/gettext.h +++ /dev/null @@ -1,270 +0,0 @@ -/* Convenience header for conditional use of GNU . - Copyright (C) 1995-1998, 2000-2002, 2004-2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LIBGETTEXT_H -#define _LIBGETTEXT_H 1 - -/* NLS can be disabled through the configure --disable-nls option. */ -#if ENABLE_NLS - -/* Get declarations of GNU message catalog functions. */ -# include - -/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by - the gettext() and ngettext() macros. This is an alternative to calling - textdomain(), and is useful for libraries. */ -# ifdef DEFAULT_TEXT_DOMAIN -# undef gettext -# define gettext(Msgid) \ - dgettext (DEFAULT_TEXT_DOMAIN, Msgid) -# undef ngettext -# define ngettext(Msgid1, Msgid2, N) \ - dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N) -# endif - -#else - -/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which - chokes if dcgettext is defined as a macro. So include it now, to make - later inclusions of a NOP. We don't include - as well because people using "gettext.h" will not include , - and also including would fail on SunOS 4, whereas - is OK. */ -#if defined(__sun) -# include -#endif - -/* Many header files from the libstdc++ coming with g++ 3.3 or newer include - , which chokes if dcgettext is defined as a macro. So include - it now, to make later inclusions of a NOP. */ -#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3) -# include -# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H -# include -# endif -#endif - -/* Disabled NLS. - The casts to 'const char *' serve the purpose of producing warnings - for invalid uses of the value returned from these functions. - On pre-ANSI systems without 'const', the config.h file is supposed to - contain "#define const". */ -# define gettext(Msgid) ((const char *) (Msgid)) -# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid)) -# define dcgettext(Domainname, Msgid, Category) \ - ((void) (Category), dgettext (Domainname, Msgid)) -# define ngettext(Msgid1, Msgid2, N) \ - ((N) == 1 \ - ? ((void) (Msgid2), (const char *) (Msgid1)) \ - : ((void) (Msgid1), (const char *) (Msgid2))) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ - ((void) (Domainname), ngettext (Msgid1, Msgid2, N)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ - ((void) (Category), dngettext(Domainname, Msgid1, Msgid2, N)) -# define textdomain(Domainname) ((const char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) \ - ((void) (Domainname), (const char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) \ - ((void) (Domainname), (const char *) (Codeset)) - -#endif - -/* A pseudo function call that serves as a marker for the automated - extraction of messages, but does not call gettext(). The run-time - translation is done at a different place in the code. - The argument, String, should be a literal string. Concatenated strings - and other string expressions won't work. - The macro's expansion is not parenthesized, so that it is suitable as - initializer for static 'char[]' or 'const char[]' variables. */ -#define gettext_noop(String) String - -/* The separator between msgctxt and msgid in a .mo file. */ -#define GETTEXT_CONTEXT_GLUE "\004" - -/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a - MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be - short and rarely need to change. - The letter 'p' stands for 'particular' or 'special'. */ -#ifdef DEFAULT_TEXT_DOMAIN -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#else -# define pgettext(Msgctxt, Msgid) \ - pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#endif -#define dpgettext(Domainname, Msgctxt, Msgid) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES) -#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \ - pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category) -#ifdef DEFAULT_TEXT_DOMAIN -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#else -# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#endif -#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \ - npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -pgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - int category) -{ - const char *translation = dcgettext (domain, msg_ctxt_id, category); - if (translation == msg_ctxt_id) - return msgid; - else - return translation; -} - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -npgettext_aux (const char *domain, - const char *msg_ctxt_id, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - const char *translation = - dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); - if (translation == msg_ctxt_id || translation == msgid_plural) - return (n == 1 ? msgid : msgid_plural); - else - return translation; -} - -/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID - can be arbitrary expressions. But for string literals these macros are - less efficient than those above. */ - -#include - -#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \ - (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \ - /* || __STDC_VERSION__ >= 199901L */ ) - -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS -#include -#endif - -#define pgettext_expr(Msgctxt, Msgid) \ - dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES) -#define dpgettext_expr(Domainname, Msgctxt, Msgid) \ - dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcgettext (domain, msg_ctxt_id, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (translation != msg_ctxt_id) - return translation; - } - return msgid; -} - -#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) -#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \ - dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES) - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -static const char * -dcnpgettext_expr (const char *domain, - const char *msgctxt, const char *msgid, - const char *msgid_plural, unsigned long int n, - int category) -{ - size_t msgctxt_len = strlen (msgctxt) + 1; - size_t msgid_len = strlen (msgid) + 1; - const char *translation; -#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - char msg_ctxt_id[msgctxt_len + msgid_len]; -#else - char buf[1024]; - char *msg_ctxt_id = - (msgctxt_len + msgid_len <= sizeof (buf) - ? buf - : (char *) malloc (msgctxt_len + msgid_len)); - if (msg_ctxt_id != NULL) -#endif - { - memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1); - msg_ctxt_id[msgctxt_len - 1] = '\004'; - memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len); - translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category); -#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS - if (msg_ctxt_id != buf) - free (msg_ctxt_id); -#endif - if (!(translation == msg_ctxt_id || translation == msgid_plural)) - return translation; - } - return (n == 1 ? msgid : msgid_plural); -} - -#endif /* _LIBGETTEXT_H */ diff --git a/usr/src/lib/libparted/common/lib/localcharset.c b/usr/src/lib/libparted/common/lib/localcharset.c deleted file mode 100644 index a0f7cca691..0000000000 --- a/usr/src/lib/libparted/common/lib/localcharset.c +++ /dev/null @@ -1,460 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - - Copyright (C) 2000-2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Bruno Haible . */ - -#include - -/* Specification. */ -#include "localcharset.h" - -#include -#include -#include -#include - -#if defined _WIN32 || defined __WIN32__ -# define WIN32_NATIVE -#endif - -#if defined __EMX__ -/* Assume EMX program runs on OS/2, even if compiled under DOS. */ -# define OS2 -#endif - -#if !defined WIN32_NATIVE -# if HAVE_LANGINFO_CODESET -# include -# else -# if 0 /* see comment below */ -# include -# endif -# endif -# ifdef __CYGWIN__ -# define WIN32_LEAN_AND_MEAN -# include -# endif -#elif defined WIN32_NATIVE -# define WIN32_LEAN_AND_MEAN -# include -#endif -#if defined OS2 -# define INCL_DOS -# include -#endif - -#if ENABLE_RELOCATABLE -# include "relocatable.h" -#else -# define relocate(pathname) (pathname) -#endif - -/* Get LIBDIR. */ -#ifndef LIBDIR -# include "configmake.h" -#endif - -#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ - /* Win32, Cygwin, OS/2, DOS */ -# define ISSLASH(C) ((C) == '/' || (C) == '\\') -#endif - -#ifndef DIRECTORY_SEPARATOR -# define DIRECTORY_SEPARATOR '/' -#endif - -#ifndef ISSLASH -# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) -#endif - -#if HAVE_DECL_GETC_UNLOCKED -# undef getc -# define getc getc_unlocked -#endif - -/* The following static variable is declared 'volatile' to avoid a - possible multithread problem in the function get_charset_aliases. If we - are running in a threaded environment, and if two threads initialize - 'charset_aliases' simultaneously, both will produce the same value, - and everything will be ok if the two assignments to 'charset_aliases' - are atomic. But I don't know what will happen if the two assignments mix. */ -#if __STDC__ != 1 -# define volatile /* empty */ -#endif -/* Pointer to the contents of the charset.alias file, if it has already been - read, else NULL. Its format is: - ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ -static const char * volatile charset_aliases; - -/* Return a pointer to the contents of the charset.alias file. */ -static const char * -get_charset_aliases (void) -{ - const char *cp; - - cp = charset_aliases; - if (cp == NULL) - { -#if !(defined VMS || defined WIN32_NATIVE || defined __CYGWIN__) - FILE *fp; - const char *dir; - const char *base = "charset.alias"; - char *file_name; - - /* Make it possible to override the charset.alias location. This is - necessary for running the testsuite before "make install". */ - dir = getenv ("CHARSETALIASDIR"); - if (dir == NULL || dir[0] == '\0') - dir = relocate (LIBDIR); - - /* Concatenate dir and base into freshly allocated file_name. */ - { - size_t dir_len = strlen (dir); - size_t base_len = strlen (base); - int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); - file_name = (char *) malloc (dir_len + add_slash + base_len + 1); - if (file_name != NULL) - { - memcpy (file_name, dir, dir_len); - if (add_slash) - file_name[dir_len] = DIRECTORY_SEPARATOR; - memcpy (file_name + dir_len + add_slash, base, base_len + 1); - } - } - - if (file_name == NULL || (fp = fopen (file_name, "r")) == NULL) - /* Out of memory or file not found, treat it as empty. */ - cp = ""; - else - { - /* Parse the file's contents. */ - char *res_ptr = NULL; - size_t res_size = 0; - - for (;;) - { - int c; - char buf1[50+1]; - char buf2[50+1]; - size_t l1, l2; - char *old_res_ptr; - - c = getc (fp); - if (c == EOF) - break; - if (c == '\n' || c == ' ' || c == '\t') - continue; - if (c == '#') - { - /* Skip comment, to end of line. */ - do - c = getc (fp); - while (!(c == EOF || c == '\n')); - if (c == EOF) - break; - continue; - } - ungetc (c, fp); - if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) - break; - l1 = strlen (buf1); - l2 = strlen (buf2); - old_res_ptr = res_ptr; - if (res_size == 0) - { - res_size = l1 + 1 + l2 + 1; - res_ptr = (char *) malloc (res_size + 1); - } - else - { - res_size += l1 + 1 + l2 + 1; - res_ptr = (char *) realloc (res_ptr, res_size + 1); - } - if (res_ptr == NULL) - { - /* Out of memory. */ - res_size = 0; - if (old_res_ptr != NULL) - free (old_res_ptr); - break; - } - strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); - strcpy (res_ptr + res_size - (l2 + 1), buf2); - } - fclose (fp); - if (res_size == 0) - cp = ""; - else - { - *(res_ptr + res_size) = '\0'; - cp = res_ptr; - } - } - - if (file_name != NULL) - free (file_name); - -#else - -# if defined VMS - /* To avoid the troubles of an extra file charset.alias_vms in the - sources of many GNU packages, simply inline the aliases here. */ - /* The list of encodings is taken from the OpenVMS 7.3-1 documentation - "Compaq C Run-Time Library Reference Manual for OpenVMS systems" - section 10.7 "Handling Different Character Sets". */ - cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" - "ISO8859-2" "\0" "ISO-8859-2" "\0" - "ISO8859-5" "\0" "ISO-8859-5" "\0" - "ISO8859-7" "\0" "ISO-8859-7" "\0" - "ISO8859-8" "\0" "ISO-8859-8" "\0" - "ISO8859-9" "\0" "ISO-8859-9" "\0" - /* Japanese */ - "eucJP" "\0" "EUC-JP" "\0" - "SJIS" "\0" "SHIFT_JIS" "\0" - "DECKANJI" "\0" "DEC-KANJI" "\0" - "SDECKANJI" "\0" "EUC-JP" "\0" - /* Chinese */ - "eucTW" "\0" "EUC-TW" "\0" - "DECHANYU" "\0" "DEC-HANYU" "\0" - "DECHANZI" "\0" "GB2312" "\0" - /* Korean */ - "DECKOREAN" "\0" "EUC-KR" "\0"; -# endif - -# if defined WIN32_NATIVE || defined __CYGWIN__ - /* To avoid the troubles of installing a separate file in the same - directory as the DLL and of retrieving the DLL's directory at - runtime, simply inline the aliases here. */ - - cp = "CP936" "\0" "GBK" "\0" - "CP1361" "\0" "JOHAB" "\0" - "CP20127" "\0" "ASCII" "\0" - "CP20866" "\0" "KOI8-R" "\0" - "CP20936" "\0" "GB2312" "\0" - "CP21866" "\0" "KOI8-RU" "\0" - "CP28591" "\0" "ISO-8859-1" "\0" - "CP28592" "\0" "ISO-8859-2" "\0" - "CP28593" "\0" "ISO-8859-3" "\0" - "CP28594" "\0" "ISO-8859-4" "\0" - "CP28595" "\0" "ISO-8859-5" "\0" - "CP28596" "\0" "ISO-8859-6" "\0" - "CP28597" "\0" "ISO-8859-7" "\0" - "CP28598" "\0" "ISO-8859-8" "\0" - "CP28599" "\0" "ISO-8859-9" "\0" - "CP28605" "\0" "ISO-8859-15" "\0" - "CP38598" "\0" "ISO-8859-8" "\0" - "CP51932" "\0" "EUC-JP" "\0" - "CP51936" "\0" "GB2312" "\0" - "CP51949" "\0" "EUC-KR" "\0" - "CP51950" "\0" "EUC-TW" "\0" - "CP54936" "\0" "GB18030" "\0" - "CP65001" "\0" "UTF-8" "\0"; -# endif -#endif - - charset_aliases = cp; - } - - return cp; -} - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ - -#ifdef STATIC -STATIC -#endif -const char * -locale_charset (void) -{ - const char *codeset; - const char *aliases; - -#if !(defined WIN32_NATIVE || defined OS2) - -# if HAVE_LANGINFO_CODESET - - /* Most systems support nl_langinfo (CODESET) nowadays. */ - codeset = nl_langinfo (CODESET); - -# ifdef __CYGWIN__ - /* Cygwin 2006 does not have locales. nl_langinfo (CODESET) always - returns "US-ASCII". As long as this is not fixed, return the suffix - of the locale name from the environment variables (if present) or - the codepage as a number. */ - if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) - { - const char *locale; - static char buf[2 + 10 + 1]; - - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - if (locale != NULL && locale[0] != '\0') - { - /* If the locale name contains an encoding after the dot, return - it. */ - const char *dot = strchr (locale, '.'); - - if (dot != NULL) - { - const char *modifier; - - dot++; - /* Look for the possible @... trailer and remove it, if any. */ - modifier = strchr (dot, '@'); - if (modifier == NULL) - return dot; - if (modifier - dot < sizeof (buf)) - { - memcpy (buf, dot, modifier - dot); - buf [modifier - dot] = '\0'; - return buf; - } - } - } - - /* Woe32 has a function returning the locale's codepage as a number. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - } -# endif - -# else - - /* On old systems which lack it, use setlocale or getenv. */ - const char *locale = NULL; - - /* But most old systems don't have a complete set of locales. Some - (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't - use setlocale here; it would return "C" when it doesn't support the - locale name the user has set. */ -# if 0 - locale = setlocale (LC_CTYPE, NULL); -# endif - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - } - - /* On some old systems, one used to set locale = "iso8859_1". On others, - you set it to "language_COUNTRY.charset". In any case, we resolve it - through the charset.alias file. */ - codeset = locale; - -# endif - -#elif defined WIN32_NATIVE - - static char buf[2 + 10 + 1]; - - /* Woe32 has a function returning the locale's codepage as a number. */ - sprintf (buf, "CP%u", GetACP ()); - codeset = buf; - -#elif defined OS2 - - const char *locale; - static char buf[2 + 10 + 1]; - ULONG cp[3]; - ULONG cplen; - - /* Allow user to override the codeset, as set in the operating system, - with standard language environment variables. */ - locale = getenv ("LC_ALL"); - if (locale == NULL || locale[0] == '\0') - { - locale = getenv ("LC_CTYPE"); - if (locale == NULL || locale[0] == '\0') - locale = getenv ("LANG"); - } - if (locale != NULL && locale[0] != '\0') - { - /* If the locale name contains an encoding after the dot, return it. */ - const char *dot = strchr (locale, '.'); - - if (dot != NULL) - { - const char *modifier; - - dot++; - /* Look for the possible @... trailer and remove it, if any. */ - modifier = strchr (dot, '@'); - if (modifier == NULL) - return dot; - if (modifier - dot < sizeof (buf)) - { - memcpy (buf, dot, modifier - dot); - buf [modifier - dot] = '\0'; - return buf; - } - } - - /* Resolve through the charset.alias file. */ - codeset = locale; - } - else - { - /* OS/2 has a function returning the locale's codepage as a number. */ - if (DosQueryCp (sizeof (cp), cp, &cplen)) - codeset = ""; - else - { - sprintf (buf, "CP%u", cp[0]); - codeset = buf; - } - } - -#endif - - if (codeset == NULL) - /* The canonical name cannot be determined. */ - codeset = ""; - - /* Resolve alias. */ - for (aliases = get_charset_aliases (); - *aliases != '\0'; - aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) - if (strcmp (codeset, aliases) == 0 - || (aliases[0] == '*' && aliases[1] == '\0')) - { - codeset = aliases + strlen (aliases) + 1; - break; - } - - /* Don't return an empty string. GNU libc and GNU libiconv interpret - the empty string as denoting "the locale's character encoding", - thus GNU libiconv would call this function a second time. */ - if (codeset[0] == '\0') - codeset = "ASCII"; - - return codeset; -} diff --git a/usr/src/lib/libparted/common/lib/localcharset.h b/usr/src/lib/libparted/common/lib/localcharset.h deleted file mode 100644 index 5030210d11..0000000000 --- a/usr/src/lib/libparted/common/lib/localcharset.h +++ /dev/null @@ -1,41 +0,0 @@ -/* Determine a canonical name for the current locale's character encoding. - Copyright (C) 2000-2003 Free Software Foundation, Inc. - This file is part of the GNU CHARSET Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _LOCALCHARSET_H -#define _LOCALCHARSET_H - - -#ifdef __cplusplus -extern "C" { -#endif - - -/* Determine the current locale's character encoding, and canonicalize it - into one of the canonical names listed in config.charset. - The result must not be freed; it is statically allocated. - If the canonical name cannot be determined, the result is a non-canonical - name. */ -extern const char * locale_charset (void); - - -#ifdef __cplusplus -} -#endif - - -#endif /* _LOCALCHARSET_H */ diff --git a/usr/src/lib/libparted/common/lib/long-options.c b/usr/src/lib/libparted/common/lib/long-options.c deleted file mode 100644 index fb61661aac..0000000000 --- a/usr/src/lib/libparted/common/lib/long-options.c +++ /dev/null @@ -1,89 +0,0 @@ -/* Utility to accept --help and --version options as unobtrusively as possible. - - Copyright (C) 1993, 1994, 1998, 1999, 2000, 2002, 2003, 2004, 2005, - 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#include - -/* Specification. */ -#include "long-options.h" - -#include -#include -#include -#include - -#include "version-etc.h" - -static struct option const long_options[] = -{ - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'v'}, - {NULL, 0, NULL, 0} -}; - -/* Process long options --help and --version, but only if argc == 2. - Be careful not to gobble up `--'. */ - -void -parse_long_options (int argc, - char **argv, - const char *command_name, - const char *package, - const char *version, - void (*usage_func) (int), - /* const char *author1, ...*/ ...) -{ - int c; - int saved_opterr; - - saved_opterr = opterr; - - /* Don't print an error message for unrecognized options. */ - opterr = 0; - - if (argc == 2 - && (c = getopt_long (argc, argv, "+", long_options, NULL)) != -1) - { - switch (c) - { - case 'h': - (*usage_func) (EXIT_SUCCESS); - - case 'v': - { - va_list authors; - va_start (authors, usage_func); - version_etc_va (stdout, command_name, package, version, authors); - exit (0); - } - - default: - /* Don't process any other long-named options. */ - break; - } - } - - /* Restore previous value. */ - opterr = saved_opterr; - - /* Reset this to zero so that getopt internals get initialized from - the probably-new parameters when/if getopt is called later. */ - optind = 0; -} diff --git a/usr/src/lib/libparted/common/lib/long-options.h b/usr/src/lib/libparted/common/lib/long-options.h deleted file mode 100644 index 03106a8def..0000000000 --- a/usr/src/lib/libparted/common/lib/long-options.h +++ /dev/null @@ -1,26 +0,0 @@ -/* long-options.h -- declaration for --help- and --version-handling function. - Copyright (C) 1993, 1994, 1998, 1999, 2003 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -void parse_long_options (int _argc, - char **_argv, - const char *_command_name, - const char *_package, - const char *_version, - void (*_usage) (int), - /* const char *author1, ...*/ ...); diff --git a/usr/src/lib/libparted/common/lib/memcpy.c b/usr/src/lib/libparted/common/lib/memcpy.c deleted file mode 100644 index d1e49c6fc7..0000000000 --- a/usr/src/lib/libparted/common/lib/memcpy.c +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (C) 1995, 1997, 2000, 2003, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering . */ - -#include - -#include - -/* Copy LEN bytes starting at SRCADDR to DESTADDR. Result undefined - if the source overlaps with the destination. - Return DESTADDR. */ - -void * -memcpy (void *destaddr, void const *srcaddr, size_t len) -{ - char *dest = destaddr; - char const *src = srcaddr; - - while (len-- > 0) - *dest++ = *src++; - return destaddr; -} diff --git a/usr/src/lib/libparted/common/lib/memmove.c b/usr/src/lib/libparted/common/lib/memmove.c deleted file mode 100644 index c5ff8b520d..0000000000 --- a/usr/src/lib/libparted/common/lib/memmove.c +++ /dev/null @@ -1,26 +0,0 @@ -/* memmove.c -- copy memory. - Copy LENGTH bytes from SOURCE to DEST. Does not null-terminate. - In the public domain. - By David MacKenzie . */ - -#include - -#include - -void * -memmove (void *dest0, void const *source0, size_t length) -{ - char *dest = dest0; - char const *source = source0; - if (source < dest) - /* Moving from low mem to hi mem; start at end. */ - for (source += length, dest += length; length; --length) - *--dest = *--source; - else if (source != dest) - { - /* Moving from hi mem to low mem; start at beginning. */ - for (; length; --length) - *dest++ = *source++; - } - return dest0; -} diff --git a/usr/src/lib/libparted/common/lib/memset.c b/usr/src/lib/libparted/common/lib/memset.c deleted file mode 100644 index 890cbf12d0..0000000000 --- a/usr/src/lib/libparted/common/lib/memset.c +++ /dev/null @@ -1,28 +0,0 @@ -/* memset.c -- set an area of memory to a given value - Copyright (C) 1991, 2003 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -void * -memset (void *str, int c, size_t len) -{ - register char *st = str; - - while (len-- > 0) - *st++ = c; - return str; -} diff --git a/usr/src/lib/libparted/common/lib/quotearg.c b/usr/src/lib/libparted/common/lib/quotearg.c deleted file mode 100644 index f7f326ac50..0000000000 --- a/usr/src/lib/libparted/common/lib/quotearg.c +++ /dev/null @@ -1,697 +0,0 @@ -/* quotearg.c - quote arguments for output - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert */ - -#include - -#include "quotearg.h" - -#include "xalloc.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gettext.h" -#define _(msgid) gettext (msgid) -#define N_(msgid) msgid - -#if !HAVE_MBRTOWC -/* Disable multibyte processing entirely. Since MB_CUR_MAX is 1, the - other macros are defined only for documentation and to satisfy C - syntax. */ -# undef MB_CUR_MAX -# define MB_CUR_MAX 1 -# undef mbstate_t -# define mbstate_t int -# define mbrtowc(pwc, s, n, ps) ((*(pwc) = *(s)) != 0) -# define iswprint(wc) isprint ((unsigned char) (wc)) -# undef HAVE_MBSINIT -#endif - -#if !defined mbsinit && !HAVE_MBSINIT -# define mbsinit(ps) 1 -#endif - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#define INT_BITS (sizeof (int) * CHAR_BIT) - -struct quoting_options -{ - /* Basic quoting style. */ - enum quoting_style style; - - /* Quote the characters indicated by this bit vector even if the - quoting style would not normally require them to be quoted. */ - unsigned int quote_these_too[(UCHAR_MAX / INT_BITS) + 1]; -}; - -/* Names of quoting styles. */ -char const *const quoting_style_args[] = -{ - "literal", - "shell", - "shell-always", - "c", - "escape", - "locale", - "clocale", - 0 -}; - -/* Correspondences to quoting style names. */ -enum quoting_style const quoting_style_vals[] = -{ - literal_quoting_style, - shell_quoting_style, - shell_always_quoting_style, - c_quoting_style, - escape_quoting_style, - locale_quoting_style, - clocale_quoting_style -}; - -/* The default quoting options. */ -static struct quoting_options default_quoting_options; - -/* Allocate a new set of quoting options, with contents initially identical - to O if O is not null, or to the default if O is null. - It is the caller's responsibility to free the result. */ -struct quoting_options * -clone_quoting_options (struct quoting_options *o) -{ - int e = errno; - struct quoting_options *p = xmemdup (o ? o : &default_quoting_options, - sizeof *o); - errno = e; - return p; -} - -/* Get the value of O's quoting style. If O is null, use the default. */ -enum quoting_style -get_quoting_style (struct quoting_options *o) -{ - return (o ? o : &default_quoting_options)->style; -} - -/* In O (or in the default if O is null), - set the value of the quoting style to S. */ -void -set_quoting_style (struct quoting_options *o, enum quoting_style s) -{ - (o ? o : &default_quoting_options)->style = s; -} - -/* In O (or in the default if O is null), - set the value of the quoting options for character C to I. - Return the old value. Currently, the only values defined for I are - 0 (the default) and 1 (which means to quote the character even if - it would not otherwise be quoted). */ -int -set_char_quoting (struct quoting_options *o, char c, int i) -{ - unsigned char uc = c; - unsigned int *p = - (o ? o : &default_quoting_options)->quote_these_too + uc / INT_BITS; - int shift = uc % INT_BITS; - int r = (*p >> shift) & 1; - *p ^= ((i & 1) ^ r) << shift; - return r; -} - -/* MSGID approximates a quotation mark. Return its translation if it - has one; otherwise, return either it or "\"", depending on S. */ -static char const * -gettext_quote (char const *msgid, enum quoting_style s) -{ - char const *translation = _(msgid); - if (translation == msgid && s == clocale_quoting_style) - translation = "\""; - return translation; -} - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using QUOTING_STYLE and the - non-quoting-style part of O to control quoting. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is SIZE_MAX, use the string length of the argument for ARGSIZE. - - This function acts like quotearg_buffer (BUFFER, BUFFERSIZE, ARG, - ARGSIZE, O), except it uses QUOTING_STYLE instead of the quoting - style specified by O, and O may not be null. */ - -static size_t -quotearg_buffer_restyled (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - enum quoting_style quoting_style, - struct quoting_options const *o) -{ - size_t i; - size_t len = 0; - char const *quote_string = 0; - size_t quote_string_len = 0; - bool backslash_escapes = false; - bool unibyte_locale = MB_CUR_MAX == 1; - -#define STORE(c) \ - do \ - { \ - if (len < buffersize) \ - buffer[len] = (c); \ - len++; \ - } \ - while (0) - - switch (quoting_style) - { - case c_quoting_style: - STORE ('"'); - backslash_escapes = true; - quote_string = "\""; - quote_string_len = 1; - break; - - case escape_quoting_style: - backslash_escapes = true; - break; - - case locale_quoting_style: - case clocale_quoting_style: - { - /* TRANSLATORS: - Get translations for open and closing quotation marks. - - The message catalog should translate "`" to a left - quotation mark suitable for the locale, and similarly for - "'". If the catalog has no translation, - locale_quoting_style quotes `like this', and - clocale_quoting_style quotes "like this". - - For example, an American English Unicode locale should - translate "`" to U+201C (LEFT DOUBLE QUOTATION MARK), and - should translate "'" to U+201D (RIGHT DOUBLE QUOTATION - MARK). A British English Unicode locale should instead - translate these to U+2018 (LEFT SINGLE QUOTATION MARK) and - U+2019 (RIGHT SINGLE QUOTATION MARK), respectively. - - If you don't know what to put here, please see - - and use glyphs suitable for your language. */ - - char const *left = gettext_quote (N_("`"), quoting_style); - char const *right = gettext_quote (N_("'"), quoting_style); - for (quote_string = left; *quote_string; quote_string++) - STORE (*quote_string); - backslash_escapes = true; - quote_string = right; - quote_string_len = strlen (quote_string); - } - break; - - case shell_always_quoting_style: - STORE ('\''); - quote_string = "'"; - quote_string_len = 1; - break; - - default: - break; - } - - for (i = 0; ! (argsize == SIZE_MAX ? arg[i] == '\0' : i == argsize); i++) - { - unsigned char c; - unsigned char esc; - - if (backslash_escapes - && quote_string_len - && i + quote_string_len <= argsize - && memcmp (arg + i, quote_string, quote_string_len) == 0) - STORE ('\\'); - - c = arg[i]; - switch (c) - { - case '\0': - if (backslash_escapes) - { - STORE ('\\'); - STORE ('0'); - STORE ('0'); - c = '0'; - } - break; - - case '?': - switch (quoting_style) - { - case shell_quoting_style: - goto use_shell_always_quoting_style; - - case c_quoting_style: - if (i + 2 < argsize && arg[i + 1] == '?') - switch (arg[i + 2]) - { - case '!': case '\'': - case '(': case ')': case '-': case '/': - case '<': case '=': case '>': - /* Escape the second '?' in what would otherwise be - a trigraph. */ - c = arg[i + 2]; - i += 2; - STORE ('?'); - STORE ('\\'); - STORE ('?'); - break; - - default: - break; - } - break; - - default: - break; - } - break; - - case '\a': esc = 'a'; goto c_escape; - case '\b': esc = 'b'; goto c_escape; - case '\f': esc = 'f'; goto c_escape; - case '\n': esc = 'n'; goto c_and_shell_escape; - case '\r': esc = 'r'; goto c_and_shell_escape; - case '\t': esc = 't'; goto c_and_shell_escape; - case '\v': esc = 'v'; goto c_escape; - case '\\': esc = c; goto c_and_shell_escape; - - c_and_shell_escape: - if (quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - c_escape: - if (backslash_escapes) - { - c = esc; - goto store_escape; - } - break; - - case '{': case '}': /* sometimes special if isolated */ - if (! (argsize == SIZE_MAX ? arg[1] == '\0' : argsize == 1)) - break; - /* Fall through. */ - case '#': case '~': - if (i != 0) - break; - /* Fall through. */ - case ' ': - case '!': /* special in bash */ - case '"': case '$': case '&': - case '(': case ')': case '*': case ';': - case '<': - case '=': /* sometimes special in 0th or (with "set -k") later args */ - case '>': case '[': - case '^': /* special in old /bin/sh, e.g. SunOS 4.1.4 */ - case '`': case '|': - /* A shell special character. In theory, '$' and '`' could - be the first bytes of multibyte characters, which means - we should check them with mbrtowc, but in practice this - doesn't happen so it's not worth worrying about. */ - if (quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - break; - - case '\'': - switch (quoting_style) - { - case shell_quoting_style: - goto use_shell_always_quoting_style; - - case shell_always_quoting_style: - STORE ('\''); - STORE ('\\'); - STORE ('\''); - break; - - default: - break; - } - break; - - case '%': case '+': case ',': case '-': case '.': case '/': - case '0': case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': case ':': - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': - case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': - case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': - case 'Y': case 'Z': case ']': case '_': case 'a': case 'b': - case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': - case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': - case 'o': case 'p': case 'q': case 'r': case 's': case 't': - case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': - /* These characters don't cause problems, no matter what the - quoting style is. They cannot start multibyte sequences. */ - break; - - default: - /* If we have a multibyte sequence, copy it until we reach - its end, find an error, or come back to the initial shift - state. For C-like styles, if the sequence has - unprintable characters, escape the whole sequence, since - we can't easily escape single characters within it. */ - { - /* Length of multibyte sequence found so far. */ - size_t m; - - bool printable; - - if (unibyte_locale) - { - m = 1; - printable = isprint (c) != 0; - } - else - { - mbstate_t mbstate; - memset (&mbstate, 0, sizeof mbstate); - - m = 0; - printable = true; - if (argsize == SIZE_MAX) - argsize = strlen (arg); - - do - { - wchar_t w; - size_t bytes = mbrtowc (&w, &arg[i + m], - argsize - (i + m), &mbstate); - if (bytes == 0) - break; - else if (bytes == (size_t) -1) - { - printable = false; - break; - } - else if (bytes == (size_t) -2) - { - printable = false; - while (i + m < argsize && arg[i + m]) - m++; - break; - } - else - { - /* Work around a bug with older shells that "see" a '\' - that is really the 2nd byte of a multibyte character. - In practice the problem is limited to ASCII - chars >= '@' that are shell special chars. */ - if ('[' == 0x5b && quoting_style == shell_quoting_style) - { - size_t j; - for (j = 1; j < bytes; j++) - switch (arg[i + m + j]) - { - case '[': case '\\': case '^': - case '`': case '|': - goto use_shell_always_quoting_style; - - default: - break; - } - } - - if (! iswprint (w)) - printable = false; - m += bytes; - } - } - while (! mbsinit (&mbstate)); - } - - if (1 < m || (backslash_escapes && ! printable)) - { - /* Output a multibyte sequence, or an escaped - unprintable unibyte character. */ - size_t ilim = i + m; - - for (;;) - { - if (backslash_escapes && ! printable) - { - STORE ('\\'); - STORE ('0' + (c >> 6)); - STORE ('0' + ((c >> 3) & 7)); - c = '0' + (c & 7); - } - if (ilim <= i + 1) - break; - STORE (c); - c = arg[++i]; - } - - goto store_c; - } - } - } - - if (! (backslash_escapes - && o->quote_these_too[c / INT_BITS] & (1 << (c % INT_BITS)))) - goto store_c; - - store_escape: - STORE ('\\'); - - store_c: - STORE (c); - } - - if (i == 0 && quoting_style == shell_quoting_style) - goto use_shell_always_quoting_style; - - if (quote_string) - for (; *quote_string; quote_string++) - STORE (*quote_string); - - if (len < buffersize) - buffer[len] = '\0'; - return len; - - use_shell_always_quoting_style: - return quotearg_buffer_restyled (buffer, buffersize, arg, argsize, - shell_always_quoting_style, o); -} - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using O to control quoting. - If O is null, use the default. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is SIZE_MAX, use the string length of the argument for - ARGSIZE. */ -size_t -quotearg_buffer (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - struct quoting_options const *o) -{ - struct quoting_options const *p = o ? o : &default_quoting_options; - int e = errno; - size_t r = quotearg_buffer_restyled (buffer, buffersize, arg, argsize, - p->style, p); - errno = e; - return r; -} - -/* Like quotearg_buffer (..., ARG, ARGSIZE, O), except return newly - allocated storage containing the quoted string. */ -char * -quotearg_alloc (char const *arg, size_t argsize, - struct quoting_options const *o) -{ - int e = errno; - size_t bufsize = quotearg_buffer (0, 0, arg, argsize, o) + 1; - char *buf = xcharalloc (bufsize); - quotearg_buffer (buf, bufsize, arg, argsize, o); - errno = e; - return buf; -} - -/* A storage slot with size and pointer to a value. */ -struct slotvec -{ - size_t size; - char *val; -}; - -/* Preallocate a slot 0 buffer, so that the caller can always quote - one small component of a "memory exhausted" message in slot 0. */ -static char slot0[256]; -static unsigned int nslots = 1; -static struct slotvec slotvec0 = {sizeof slot0, slot0}; -static struct slotvec *slotvec = &slotvec0; - -void -quotearg_free (void) -{ - struct slotvec *sv = slotvec; - unsigned int i; - for (i = 1; i < nslots; i++) - free (sv[i].val); - if (sv[0].val != slot0) - { - free (sv[0].val); - slotvec0.size = sizeof slot0; - slotvec0.val = slot0; - } - if (sv != &slotvec0) - { - free (sv); - slotvec = &slotvec0; - } - nslots = 1; -} - -/* Use storage slot N to return a quoted version of argument ARG. - ARG is of size ARGSIZE, but if that is SIZE_MAX, ARG is a - null-terminated string. - OPTIONS specifies the quoting options. - The returned value points to static storage that can be - reused by the next call to this function with the same value of N. - N must be nonnegative. N is deliberately declared with type "int" - to allow for future extensions (using negative values). */ -static char * -quotearg_n_options (int n, char const *arg, size_t argsize, - struct quoting_options const *options) -{ - int e = errno; - - unsigned int n0 = n; - struct slotvec *sv = slotvec; - - if (n < 0) - abort (); - - if (nslots <= n0) - { - /* FIXME: technically, the type of n1 should be `unsigned int', - but that evokes an unsuppressible warning from gcc-4.0.1 and - older. If gcc ever provides an option to suppress that warning, - revert to the original type, so that the test in xalloc_oversized - is once again performed only at compile time. */ - size_t n1 = n0 + 1; - bool preallocated = (sv == &slotvec0); - - if (xalloc_oversized (n1, sizeof *sv)) - xalloc_die (); - - slotvec = sv = xrealloc (preallocated ? NULL : sv, n1 * sizeof *sv); - if (preallocated) - *sv = slotvec0; - memset (sv + nslots, 0, (n1 - nslots) * sizeof *sv); - nslots = n1; - } - - { - size_t size = sv[n].size; - char *val = sv[n].val; - size_t qsize = quotearg_buffer (val, size, arg, argsize, options); - - if (size <= qsize) - { - sv[n].size = size = qsize + 1; - if (val != slot0) - free (val); - sv[n].val = val = xcharalloc (size); - quotearg_buffer (val, size, arg, argsize, options); - } - - errno = e; - return val; - } -} - -char * -quotearg_n (int n, char const *arg) -{ - return quotearg_n_options (n, arg, SIZE_MAX, &default_quoting_options); -} - -char * -quotearg (char const *arg) -{ - return quotearg_n (0, arg); -} - -/* Return quoting options for STYLE, with no extra quoting. */ -static struct quoting_options -quoting_options_from_style (enum quoting_style style) -{ - struct quoting_options o; - o.style = style; - memset (o.quote_these_too, 0, sizeof o.quote_these_too); - return o; -} - -char * -quotearg_n_style (int n, enum quoting_style s, char const *arg) -{ - struct quoting_options const o = quoting_options_from_style (s); - return quotearg_n_options (n, arg, SIZE_MAX, &o); -} - -char * -quotearg_n_style_mem (int n, enum quoting_style s, - char const *arg, size_t argsize) -{ - struct quoting_options const o = quoting_options_from_style (s); - return quotearg_n_options (n, arg, argsize, &o); -} - -char * -quotearg_style (enum quoting_style s, char const *arg) -{ - return quotearg_n_style (0, s, arg); -} - -char * -quotearg_char (char const *arg, char ch) -{ - struct quoting_options options; - options = default_quoting_options; - set_char_quoting (&options, ch, 1); - return quotearg_n_options (0, arg, SIZE_MAX, &options); -} - -char * -quotearg_colon (char const *arg) -{ - return quotearg_char (arg, ':'); -} diff --git a/usr/src/lib/libparted/common/lib/quotearg.h b/usr/src/lib/libparted/common/lib/quotearg.h deleted file mode 100644 index 4887df3b6d..0000000000 --- a/usr/src/lib/libparted/common/lib/quotearg.h +++ /dev/null @@ -1,140 +0,0 @@ -/* quotearg.h - quote arguments for output - - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Paul Eggert */ - -#ifndef QUOTEARG_H_ -# define QUOTEARG_H_ 1 - -# include - -/* Basic quoting styles. */ -enum quoting_style - { - /* Output names as-is (ls --quoting-style=literal). */ - literal_quoting_style, - - /* Quote names for the shell if they contain shell metacharacters - or would cause ambiguous output (ls --quoting-style=shell). */ - shell_quoting_style, - - /* Quote names for the shell, even if they would normally not - require quoting (ls --quoting-style=shell-always). */ - shell_always_quoting_style, - - /* Quote names as for a C language string (ls --quoting-style=c). */ - c_quoting_style, - - /* Like c_quoting_style except omit the surrounding double-quote - characters (ls --quoting-style=escape). */ - escape_quoting_style, - - /* Like clocale_quoting_style, but quote `like this' instead of - "like this" in the default C locale (ls --quoting-style=locale). */ - locale_quoting_style, - - /* Like c_quoting_style except use quotation marks appropriate for - the locale (ls --quoting-style=clocale). */ - clocale_quoting_style - }; - -/* For now, --quoting-style=literal is the default, but this may change. */ -# ifndef DEFAULT_QUOTING_STYLE -# define DEFAULT_QUOTING_STYLE literal_quoting_style -# endif - -/* Names of quoting styles and their corresponding values. */ -extern char const *const quoting_style_args[]; -extern enum quoting_style const quoting_style_vals[]; - -struct quoting_options; - -/* The functions listed below set and use a hidden variable - that contains the default quoting style options. */ - -/* Allocate a new set of quoting options, with contents initially identical - to O if O is not null, or to the default if O is null. - It is the caller's responsibility to free the result. */ -struct quoting_options *clone_quoting_options (struct quoting_options *o); - -/* Get the value of O's quoting style. If O is null, use the default. */ -enum quoting_style get_quoting_style (struct quoting_options *o); - -/* In O (or in the default if O is null), - set the value of the quoting style to S. */ -void set_quoting_style (struct quoting_options *o, enum quoting_style s); - -/* In O (or in the default if O is null), - set the value of the quoting options for character C to I. - Return the old value. Currently, the only values defined for I are - 0 (the default) and 1 (which means to quote the character even if - it would not otherwise be quoted). */ -int set_char_quoting (struct quoting_options *o, char c, int i); - -/* Place into buffer BUFFER (of size BUFFERSIZE) a quoted version of - argument ARG (of size ARGSIZE), using O to control quoting. - If O is null, use the default. - Terminate the output with a null character, and return the written - size of the output, not counting the terminating null. - If BUFFERSIZE is too small to store the output string, return the - value that would have been returned had BUFFERSIZE been large enough. - If ARGSIZE is -1, use the string length of the argument for ARGSIZE. */ -size_t quotearg_buffer (char *buffer, size_t buffersize, - char const *arg, size_t argsize, - struct quoting_options const *o); - -/* Like quotearg_buffer, except return the result in a newly allocated - buffer. It is the caller's responsibility to free the result. */ -char *quotearg_alloc (char const *arg, size_t argsize, - struct quoting_options const *o); - -/* Use storage slot N to return a quoted version of the string ARG. - Use the default quoting options. - The returned value points to static storage that can be - reused by the next call to this function with the same value of N. - N must be nonnegative. */ -char *quotearg_n (int n, char const *arg); - -/* Equivalent to quotearg_n (0, ARG). */ -char *quotearg (char const *arg); - -/* Use style S and storage slot N to return a quoted version of the string ARG. - This is like quotearg_n (N, ARG), except that it uses S with no other - options to specify the quoting method. */ -char *quotearg_n_style (int n, enum quoting_style s, char const *arg); - -/* Use style S and storage slot N to return a quoted version of the - argument ARG of size ARGSIZE. This is like quotearg_n_style - (N, S, ARG), except it can quote null bytes. */ -char *quotearg_n_style_mem (int n, enum quoting_style s, - char const *arg, size_t argsize); - -/* Equivalent to quotearg_n_style (0, S, ARG). */ -char *quotearg_style (enum quoting_style s, char const *arg); - -/* Like quotearg (ARG), except also quote any instances of CH. */ -char *quotearg_char (char const *arg, char ch); - -/* Equivalent to quotearg_char (ARG, ':'). */ -char *quotearg_colon (char const *arg); - -/* Free any dynamically allocated memory. */ -void quotearg_free (void); - -#endif /* !QUOTEARG_H_ */ diff --git a/usr/src/lib/libparted/common/lib/regcomp.c b/usr/src/lib/libparted/common/lib/regcomp.c deleted file mode 100644 index fe4d243d54..0000000000 --- a/usr/src/lib/libparted/common/lib/regcomp.c +++ /dev/null @@ -1,3832 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, - size_t length, reg_syntax_t syntax); -static void re_compile_fastmap_iter (regex_t *bufp, - const re_dfastate_t *init_state, - char *fastmap); -static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); -#ifdef RE_ENABLE_I18N -static void free_charset (re_charset_t *cset); -#endif /* RE_ENABLE_I18N */ -static void free_workarea_compile (regex_t *preg); -static reg_errcode_t create_initial_state (re_dfa_t *dfa); -#ifdef RE_ENABLE_I18N -static void optimize_utf8 (re_dfa_t *dfa); -#endif -static reg_errcode_t analyze (regex_t *preg); -static reg_errcode_t preorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t postorder (bin_tree_t *root, - reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra); -static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); -static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); -static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, - bin_tree_t *node); -static reg_errcode_t calc_first (void *extra, bin_tree_t *node); -static reg_errcode_t calc_next (void *extra, bin_tree_t *node); -static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); -static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint); -static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint); -static reg_errcode_t calc_eclosure (re_dfa_t *dfa); -static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, - Idx node, bool root); -static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); -static Idx fetch_number (re_string_t *input, re_token_t *token, - reg_syntax_t syntax); -static int peek_token (re_token_t *token, re_string_t *input, - reg_syntax_t syntax) internal_function; -static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, - re_token_t *token, reg_syntax_t syntax, - Idx nest, reg_errcode_t *err); -static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, - re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err); -static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, - reg_errcode_t *err); -static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token, int token_len, - re_dfa_t *dfa, - reg_syntax_t syntax, - bool accept_hyphen); -static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, - re_string_t *regexp, - re_token_t *token); -#ifdef RE_ENABLE_I18N -static reg_errcode_t build_equiv_class (bitset_t sbcset, - re_charset_t *mbcset, - Idx *equiv_class_alloc, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - re_charset_t *mbcset, - Idx *char_class_alloc, - const unsigned char *class_name, - reg_syntax_t syntax); -#else /* not RE_ENABLE_I18N */ -static reg_errcode_t build_equiv_class (bitset_t sbcset, - const unsigned char *name); -static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, - bitset_t sbcset, - const unsigned char *class_name, - reg_syntax_t syntax); -#endif /* not RE_ENABLE_I18N */ -static bin_tree_t *build_charclass_op (re_dfa_t *dfa, - RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, - bool non_match, reg_errcode_t *err); -static bin_tree_t *create_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - re_token_type_t type); -static bin_tree_t *create_token_tree (re_dfa_t *dfa, - bin_tree_t *left, bin_tree_t *right, - const re_token_t *token); -static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); -static void free_token (re_token_t *node); -static reg_errcode_t free_tree (void *extra, bin_tree_t *node); -static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); - -/* This table gives an error message for each of the error codes listed - in regex.h. Obviously the order here has to be same as there. - POSIX doesn't require that we do anything for REG_NOERROR, - but why not be nice? */ - -static const char __re_error_msgid[] = - { -#define REG_NOERROR_IDX 0 - gettext_noop ("Success") /* REG_NOERROR */ - "\0" -#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") - gettext_noop ("No match") /* REG_NOMATCH */ - "\0" -#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") - gettext_noop ("Invalid regular expression") /* REG_BADPAT */ - "\0" -#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") - gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ - "\0" -#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") - gettext_noop ("Invalid character class name") /* REG_ECTYPE */ - "\0" -#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") - gettext_noop ("Trailing backslash") /* REG_EESCAPE */ - "\0" -#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") - gettext_noop ("Invalid back reference") /* REG_ESUBREG */ - "\0" -#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") - gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ - "\0" -#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") - gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ - "\0" -#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") - gettext_noop ("Unmatched \\{") /* REG_EBRACE */ - "\0" -#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") - gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ - "\0" -#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") - gettext_noop ("Invalid range end") /* REG_ERANGE */ - "\0" -#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") - gettext_noop ("Memory exhausted") /* REG_ESPACE */ - "\0" -#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") - gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ - "\0" -#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") - gettext_noop ("Premature end of regular expression") /* REG_EEND */ - "\0" -#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") - gettext_noop ("Regular expression too big") /* REG_ESIZE */ - "\0" -#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") - gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ - }; - -static const size_t __re_error_msgid_idx[] = - { - REG_NOERROR_IDX, - REG_NOMATCH_IDX, - REG_BADPAT_IDX, - REG_ECOLLATE_IDX, - REG_ECTYPE_IDX, - REG_EESCAPE_IDX, - REG_ESUBREG_IDX, - REG_EBRACK_IDX, - REG_EPAREN_IDX, - REG_EBRACE_IDX, - REG_BADBR_IDX, - REG_ERANGE_IDX, - REG_ESPACE_IDX, - REG_BADRPT_IDX, - REG_EEND_IDX, - REG_ESIZE_IDX, - REG_ERPAREN_IDX - }; - -/* Entry points for GNU code. */ - -/* re_compile_pattern is the GNU regular expression compiler: it - compiles PATTERN (of length LENGTH) and puts the result in BUFP. - Returns 0 if the pattern was valid, otherwise an error string. - - Assumes the `allocated' (and perhaps `buffer') and `translate' fields - are set in BUFP on entry. */ - -#ifdef _LIBC -const char * -re_compile_pattern (pattern, length, bufp) - const char *pattern; - size_t length; - struct re_pattern_buffer *bufp; -#else /* size_t might promote */ -const char * -re_compile_pattern (const char *pattern, size_t length, - struct re_pattern_buffer *bufp) -#endif -{ - reg_errcode_t ret; - - /* And GNU code determines whether or not to get register information - by passing null for the REGS argument to re_match, etc., not by - setting no_sub, unless RE_NO_SUB is set. */ - bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); - - /* Match anchors at newline. */ - bufp->newline_anchor = 1; - - ret = re_compile_internal (bufp, pattern, length, re_syntax_options); - - if (!ret) - return NULL; - return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} -#ifdef _LIBC -weak_alias (__re_compile_pattern, re_compile_pattern) -#endif - -/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can - also be assigned to arbitrarily: each pattern buffer stores its own - syntax, so it can be changed between regex compilations. */ -/* This has no initializer because initialized variables in Emacs - become read-only after dumping. */ -reg_syntax_t re_syntax_options; - - -/* Specify the precise syntax of regexps for compilation. This provides - for compatibility for various utilities which historically have - different, incompatible syntaxes. - - The argument SYNTAX is a bit mask comprised of the various bits - defined in regex.h. We return the old syntax. */ - -reg_syntax_t -re_set_syntax (syntax) - reg_syntax_t syntax; -{ - reg_syntax_t ret = re_syntax_options; - - re_syntax_options = syntax; - return ret; -} -#ifdef _LIBC -weak_alias (__re_set_syntax, re_set_syntax) -#endif - -int -re_compile_fastmap (bufp) - struct re_pattern_buffer *bufp; -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - char *fastmap = bufp->fastmap; - - memset (fastmap, '\0', sizeof (char) * SBC_MAX); - re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); - if (dfa->init_state != dfa->init_state_word) - re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); - if (dfa->init_state != dfa->init_state_nl) - re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); - if (dfa->init_state != dfa->init_state_begbuf) - re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); - bufp->fastmap_accurate = 1; - return 0; -} -#ifdef _LIBC -weak_alias (__re_compile_fastmap, re_compile_fastmap) -#endif - -static inline void -__attribute ((always_inline)) -re_set_fastmap (char *fastmap, bool icase, int ch) -{ - fastmap[ch] = 1; - if (icase) - fastmap[tolower (ch)] = 1; -} - -/* Helper function for re_compile_fastmap. - Compile fastmap for the initial_state INIT_STATE. */ - -static void -re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, - char *fastmap) -{ - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; - Idx node_cnt; - bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); - for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) - { - Idx node = init_state->nodes.elems[node_cnt]; - re_token_type_t type = dfa->nodes[node].type; - - if (type == CHARACTER) - { - re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); -#ifdef RE_ENABLE_I18N - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - unsigned char buf[MB_LEN_MAX]; - unsigned char *p; - wchar_t wc; - mbstate_t state; - - p = buf; - *p++ = dfa->nodes[node].opr.c; - while (++node < dfa->nodes_len - && dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].mb_partial) - *p++ = dfa->nodes[node].opr.c; - memset (&state, '\0', sizeof (state)); - if (mbrtowc (&wc, (const char *) buf, p - buf, - &state) == p - buf - && (__wcrtomb ((char *) buf, towlower (wc), &state) - != (size_t) -1)) - re_set_fastmap (fastmap, false, buf[0]); - } -#endif - } - else if (type == SIMPLE_BRACKET) - { - int i, ch; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - { - int j; - bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (w & ((bitset_word_t) 1 << j)) - re_set_fastmap (fastmap, icase, ch); - } - } -#ifdef RE_ENABLE_I18N - else if (type == COMPLEX_BRACKET) - { - Idx i; - re_charset_t *cset = dfa->nodes[node].opr.mbcset; - if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes - || cset->nranges || cset->nchar_classes) - { -# ifdef _LIBC - if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) - { - /* In this case we want to catch the bytes which are - the first byte of any collation elements. - e.g. In da_DK, we want to catch 'a' since "aa" - is a valid collation element, and don't catch - 'b' since 'b' is the only collation element - which starts from 'b'. */ - const int32_t *table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - for (i = 0; i < SBC_MAX; ++i) - if (table[i] < 0) - re_set_fastmap (fastmap, icase, i); - } -# else - if (dfa->mb_cur_max > 1) - for (i = 0; i < SBC_MAX; ++i) - if (__btowc (i) == WEOF) - re_set_fastmap (fastmap, icase, i); -# endif /* not _LIBC */ - } - for (i = 0; i < cset->nmbchars; ++i) - { - char buf[256]; - mbstate_t state; - memset (&state, '\0', sizeof (state)); - if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) - re_set_fastmap (fastmap, icase, *(unsigned char *) buf); - if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) - { - if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) - != (size_t) -1) - re_set_fastmap (fastmap, false, *(unsigned char *) buf); - } - } - } -#endif /* RE_ENABLE_I18N */ - else if (type == OP_PERIOD -#ifdef RE_ENABLE_I18N - || type == OP_UTF8_PERIOD -#endif /* RE_ENABLE_I18N */ - || type == END_OF_RE) - { - memset (fastmap, '\1', sizeof (char) * SBC_MAX); - if (type == END_OF_RE) - bufp->can_be_null = 1; - return; - } - } -} - -/* Entry point for POSIX code. */ -/* regcomp takes a regular expression as a string and compiles it. - - PREG is a regex_t *. We do not expect any fields to be initialized, - since POSIX says we shouldn't. Thus, we set - - `buffer' to the compiled pattern; - `used' to the length of the compiled pattern; - `syntax' to RE_SYNTAX_POSIX_EXTENDED if the - REG_EXTENDED bit in CFLAGS is set; otherwise, to - RE_SYNTAX_POSIX_BASIC; - `newline_anchor' to REG_NEWLINE being set in CFLAGS; - `fastmap' to an allocated space for the fastmap; - `fastmap_accurate' to zero; - `re_nsub' to the number of subexpressions in PATTERN. - - PATTERN is the address of the pattern string. - - CFLAGS is a series of bits which affect compilation. - - If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we - use POSIX basic syntax. - - If REG_NEWLINE is set, then . and [^...] don't match newline. - Also, regexec will try a match beginning after every newline. - - If REG_ICASE is set, then we considers upper- and lowercase - versions of letters to be equivalent when matching. - - If REG_NOSUB is set, then when PREG is passed to regexec, that - routine will report only success or failure, and nothing about the - registers. - - It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for - the return codes and their meanings.) */ - -int -regcomp (preg, pattern, cflags) - regex_t *_Restrict_ preg; - const char *_Restrict_ pattern; - int cflags; -{ - reg_errcode_t ret; - reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED - : RE_SYNTAX_POSIX_BASIC); - - preg->buffer = NULL; - preg->allocated = 0; - preg->used = 0; - - /* Try to allocate space for the fastmap. */ - preg->fastmap = re_malloc (char, SBC_MAX); - if (BE (preg->fastmap == NULL, 0)) - return REG_ESPACE; - - syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; - - /* If REG_NEWLINE is set, newlines are treated differently. */ - if (cflags & REG_NEWLINE) - { /* REG_NEWLINE implies neither . nor [^...] match newline. */ - syntax &= ~RE_DOT_NEWLINE; - syntax |= RE_HAT_LISTS_NOT_NEWLINE; - /* It also changes the matching behavior. */ - preg->newline_anchor = 1; - } - else - preg->newline_anchor = 0; - preg->no_sub = !!(cflags & REG_NOSUB); - preg->translate = NULL; - - ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); - - /* POSIX doesn't distinguish between an unmatched open-group and an - unmatched close-group: both are REG_EPAREN. */ - if (ret == REG_ERPAREN) - ret = REG_EPAREN; - - /* We have already checked preg->fastmap != NULL. */ - if (BE (ret == REG_NOERROR, 1)) - /* Compute the fastmap now, since regexec cannot modify the pattern - buffer. This function never fails in this implementation. */ - (void) re_compile_fastmap (preg); - else - { - /* Some error occurred while compiling the expression. */ - re_free (preg->fastmap); - preg->fastmap = NULL; - } - - return (int) ret; -} -#ifdef _LIBC -weak_alias (__regcomp, regcomp) -#endif - -/* Returns a message corresponding to an error code, ERRCODE, returned - from either regcomp or regexec. We don't use PREG here. */ - -#ifdef _LIBC -size_t -regerror (errcode, preg, errbuf, errbuf_size) - int errcode; - const regex_t *_Restrict_ preg; - char *_Restrict_ errbuf; - size_t errbuf_size; -#else /* size_t might promote */ -size_t -regerror (int errcode, const regex_t *_Restrict_ preg, - char *_Restrict_ errbuf, size_t errbuf_size) -#endif -{ - const char *msg; - size_t msg_size; - - if (BE (errcode < 0 - || errcode >= (int) (sizeof (__re_error_msgid_idx) - / sizeof (__re_error_msgid_idx[0])), 0)) - /* Only error codes returned by the rest of the code should be passed - to this routine. If we are given anything else, or if other regex - code generates an invalid error code, then the program has a bug. - Dump core so we can fix it. */ - abort (); - - msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); - - msg_size = strlen (msg) + 1; /* Includes the null. */ - - if (BE (errbuf_size != 0, 1)) - { - size_t cpy_size = msg_size; - if (BE (msg_size > errbuf_size, 0)) - { - cpy_size = errbuf_size - 1; - errbuf[cpy_size] = '\0'; - } - memcpy (errbuf, msg, cpy_size); - } - - return msg_size; -} -#ifdef _LIBC -weak_alias (__regerror, regerror) -#endif - - -#ifdef RE_ENABLE_I18N -/* This static array is used for the map to single-byte characters when - UTF-8 is used. Otherwise we would allocate memory just to initialize - it the same all the time. UTF-8 is the preferred encoding so this is - a worthwhile optimization. */ -static const bitset_t utf8_sb_map = -{ - /* Set the first 128 bits. */ -# if 4 * BITSET_WORD_BITS < ASCII_CHARS -# error "bitset_word_t is narrower than 32 bits" -# elif 3 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 2 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, BITSET_WORD_MAX, -# elif 1 * BITSET_WORD_BITS < ASCII_CHARS - BITSET_WORD_MAX, -# endif - (BITSET_WORD_MAX - >> (SBC_MAX % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS)) -}; -#endif - - -static void -free_dfa_content (re_dfa_t *dfa) -{ - Idx i, j; - - if (dfa->nodes) - for (i = 0; i < dfa->nodes_len; ++i) - free_token (dfa->nodes + i); - re_free (dfa->nexts); - for (i = 0; i < dfa->nodes_len; ++i) - { - if (dfa->eclosures != NULL) - re_node_set_free (dfa->eclosures + i); - if (dfa->inveclosures != NULL) - re_node_set_free (dfa->inveclosures + i); - if (dfa->edests != NULL) - re_node_set_free (dfa->edests + i); - } - re_free (dfa->edests); - re_free (dfa->eclosures); - re_free (dfa->inveclosures); - re_free (dfa->nodes); - - if (dfa->state_table) - for (i = 0; i <= dfa->state_hash_mask; ++i) - { - struct re_state_table_entry *entry = dfa->state_table + i; - for (j = 0; j < entry->num; ++j) - { - re_dfastate_t *state = entry->array[j]; - free_state (state); - } - re_free (entry->array); - } - re_free (dfa->state_table); -#ifdef RE_ENABLE_I18N - if (dfa->sb_char != utf8_sb_map) - re_free (dfa->sb_char); -#endif - re_free (dfa->subexp_map); -#ifdef DEBUG - re_free (dfa->re_str); -#endif - - re_free (dfa); -} - - -/* Free dynamically allocated space used by PREG. */ - -void -regfree (preg) - regex_t *preg; -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - if (BE (dfa != NULL, 1)) - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - - re_free (preg->fastmap); - preg->fastmap = NULL; - - re_free (preg->translate); - preg->translate = NULL; -} -#ifdef _LIBC -weak_alias (__regfree, regfree) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC - -/* BSD has one and only one pattern buffer. */ -static struct re_pattern_buffer re_comp_buf; - -char * -# ifdef _LIBC -/* Make these definitions weak in libc, so POSIX programs can redefine - these names if they don't use our functions, and still use - regcomp/regexec above without link errors. */ -weak_function -# endif -re_comp (s) - const char *s; -{ - reg_errcode_t ret; - char *fastmap; - - if (!s) - { - if (!re_comp_buf.buffer) - return gettext ("No previous regular expression"); - return 0; - } - - if (re_comp_buf.buffer) - { - fastmap = re_comp_buf.fastmap; - re_comp_buf.fastmap = NULL; - __regfree (&re_comp_buf); - memset (&re_comp_buf, '\0', sizeof (re_comp_buf)); - re_comp_buf.fastmap = fastmap; - } - - if (re_comp_buf.fastmap == NULL) - { - re_comp_buf.fastmap = (char *) malloc (SBC_MAX); - if (re_comp_buf.fastmap == NULL) - return (char *) gettext (__re_error_msgid - + __re_error_msgid_idx[(int) REG_ESPACE]); - } - - /* Since `re_exec' always passes NULL for the `regs' argument, we - don't need to initialize the pattern buffer fields which affect it. */ - - /* Match anchors at newlines. */ - re_comp_buf.newline_anchor = 1; - - ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options); - - if (!ret) - return NULL; - - /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ - return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); -} - -#ifdef _LIBC -libc_freeres_fn (free_mem) -{ - __regfree (&re_comp_buf); -} -#endif - -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. - Compile the regular expression PATTERN, whose length is LENGTH. - SYNTAX indicate regular expression's syntax. */ - -static reg_errcode_t -re_compile_internal (regex_t *preg, const char * pattern, size_t length, - reg_syntax_t syntax) -{ - reg_errcode_t err = REG_NOERROR; - re_dfa_t *dfa; - re_string_t regexp; - - /* Initialize the pattern buffer. */ - preg->fastmap_accurate = 0; - preg->syntax = syntax; - preg->not_bol = preg->not_eol = 0; - preg->used = 0; - preg->re_nsub = 0; - preg->can_be_null = 0; - preg->regs_allocated = REGS_UNALLOCATED; - - /* Initialize the dfa. */ - dfa = (re_dfa_t *) preg->buffer; - if (BE (preg->allocated < sizeof (re_dfa_t), 0)) - { - /* If zero allocated, but buffer is non-null, try to realloc - enough space. This loses if buffer's address is bogus, but - that is the user's responsibility. If ->buffer is NULL this - is a simple allocation. */ - dfa = re_realloc (preg->buffer, re_dfa_t, 1); - if (dfa == NULL) - return REG_ESPACE; - preg->allocated = sizeof (re_dfa_t); - preg->buffer = (unsigned char *) dfa; - } - preg->used = sizeof (re_dfa_t); - - err = init_dfa (dfa, length); - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } -#ifdef DEBUG - /* Note: length+1 will not overflow since it is checked in init_dfa. */ - dfa->re_str = re_malloc (char, length + 1); - strncpy (dfa->re_str, pattern, length + 1); -#endif - - __libc_lock_init (dfa->lock); - - err = re_string_construct (®exp, pattern, length, preg->translate, - syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - { - re_compile_internal_free_return: - free_workarea_compile (preg); - re_string_destruct (®exp); - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - return err; - } - - /* Parse the regular expression, and build a structure tree. */ - preg->re_nsub = 0; - dfa->str_tree = parse (®exp, preg, syntax, &err); - if (BE (dfa->str_tree == NULL, 0)) - goto re_compile_internal_free_return; - - /* Analyze the tree and create the nfa. */ - err = analyze (preg); - if (BE (err != REG_NOERROR, 0)) - goto re_compile_internal_free_return; - -#ifdef RE_ENABLE_I18N - /* If possible, do searching in single byte encoding to speed things up. */ - if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) - optimize_utf8 (dfa); -#endif - - /* Then create the initial state of the dfa. */ - err = create_initial_state (dfa); - - /* Release work areas. */ - free_workarea_compile (preg); - re_string_destruct (®exp); - - if (BE (err != REG_NOERROR, 0)) - { - free_dfa_content (dfa); - preg->buffer = NULL; - preg->allocated = 0; - } - - return err; -} - -/* Initialize DFA. We use the length of the regular expression PAT_LEN - as the initial length of some arrays. */ - -static reg_errcode_t -init_dfa (re_dfa_t *dfa, size_t pat_len) -{ - __re_size_t table_size; -#ifdef RE_ENABLE_I18N - size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); -#else - size_t max_i18n_object_size = 0; -#endif - size_t max_object_size = - MAX (sizeof (struct re_state_table_entry), - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - MAX (sizeof (regmatch_t), - max_i18n_object_size)))); - - memset (dfa, '\0', sizeof (re_dfa_t)); - - /* Force allocation of str_tree_storage the first time. */ - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - - /* Avoid overflows. The extra "/ 2" is for the table_size doubling - calculation below, and for similar doubling calculations - elsewhere. And it's <= rather than <, because some of the - doubling calculations add 1 afterwards. */ - if (BE (SIZE_MAX / max_object_size / 2 <= pat_len, 0)) - return REG_ESPACE; - - dfa->nodes_alloc = pat_len + 1; - dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); - - /* table_size = 2 ^ ceil(log pat_len) */ - for (table_size = 1; ; table_size <<= 1) - if (table_size > pat_len) - break; - - dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); - dfa->state_hash_mask = table_size - 1; - - dfa->mb_cur_max = MB_CUR_MAX; -#ifdef _LIBC - if (dfa->mb_cur_max == 6 - && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) - dfa->is_utf8 = 1; - dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) - != 0); -#else - if (strcmp (locale_charset (), "UTF-8") == 0) - dfa->is_utf8 = 1; - - /* We check exhaustively in the loop below if this charset is a - superset of ASCII. */ - dfa->map_notascii = 0; -#endif - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - if (dfa->is_utf8) - dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; - else - { - int i, j, ch; - - dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); - if (BE (dfa->sb_char == NULL, 0)) - return REG_ESPACE; - - /* Set the bits corresponding to single byte chars. */ - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - { - wint_t wch = __btowc (ch); - if (wch != WEOF) - dfa->sb_char[i] |= (bitset_word_t) 1 << j; -# ifndef _LIBC - if (isascii (ch) && wch != ch) - dfa->map_notascii = 1; -# endif - } - } - } -#endif - - if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -/* Initialize WORD_CHAR table, which indicate which character is - "word". In this case "word" means that it is the word construction - character used by some operators like "\<", "\>", etc. */ - -static void -internal_function -init_word_char (re_dfa_t *dfa) -{ - int i, j, ch; - dfa->word_ops_used = 1; - for (i = 0, ch = 0; i < BITSET_WORDS; ++i) - for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) - if (isalnum (ch) || ch == '_') - dfa->word_char[i] |= (bitset_word_t) 1 << j; -} - -/* Free the work area which are only used while compiling. */ - -static void -free_workarea_compile (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_storage_t *storage, *next; - for (storage = dfa->str_tree_storage; storage; storage = next) - { - next = storage->next; - re_free (storage); - } - dfa->str_tree_storage = NULL; - dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; - dfa->str_tree = NULL; - re_free (dfa->org_indices); - dfa->org_indices = NULL; -} - -/* Create initial states for all contexts. */ - -static reg_errcode_t -create_initial_state (re_dfa_t *dfa) -{ - Idx first, i; - reg_errcode_t err; - re_node_set init_nodes; - - /* Initial states have the epsilon closure of the node which is - the first node of the regular expression. */ - first = dfa->str_tree->first->node_idx; - dfa->init_node = first; - err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* The back-references which are in initial states can epsilon transit, - since in this case all of the subexpressions can be null. - Then we add epsilon closures of the nodes which are the next nodes of - the back-references. */ - if (dfa->nbackref > 0) - for (i = 0; i < init_nodes.nelem; ++i) - { - Idx node_idx = init_nodes.elems[i]; - re_token_type_t type = dfa->nodes[node_idx].type; - - Idx clexp_idx; - if (type != OP_BACK_REF) - continue; - for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) - { - re_token_t *clexp_node; - clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; - if (clexp_node->type == OP_CLOSE_SUBEXP - && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) - break; - } - if (clexp_idx == init_nodes.nelem) - continue; - - if (type == OP_BACK_REF) - { - Idx dest_idx = dfa->edests[node_idx].elems[0]; - if (!re_node_set_contains (&init_nodes, dest_idx)) - { - re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); - i = 0; - } - } - } - - /* It must be the first time to invoke acquire_state. */ - dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); - /* We don't check ERR here, since the initial state must not be NULL. */ - if (BE (dfa->init_state == NULL, 0)) - return err; - if (dfa->init_state->has_constraint) - { - dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_WORD); - dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, - CONTEXT_NEWLINE); - dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, - &init_nodes, - CONTEXT_NEWLINE - | CONTEXT_BEGBUF); - if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return err; - } - else - dfa->init_state_word = dfa->init_state_nl - = dfa->init_state_begbuf = dfa->init_state; - - re_node_set_free (&init_nodes); - return REG_NOERROR; -} - -#ifdef RE_ENABLE_I18N -/* If it is possible to do searching in single byte encoding instead of UTF-8 - to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change - DFA nodes where needed. */ - -static void -optimize_utf8 (re_dfa_t *dfa) -{ - Idx node; - int i; - bool mb_chars = false; - bool has_period = false; - - for (node = 0; node < dfa->nodes_len; ++node) - switch (dfa->nodes[node].type) - { - case CHARACTER: - if (dfa->nodes[node].opr.c >= ASCII_CHARS) - mb_chars = true; - break; - case ANCHOR: - switch (dfa->nodes[node].opr.idx) - { - case LINE_FIRST: - case LINE_LAST: - case BUF_FIRST: - case BUF_LAST: - break; - default: - /* Word anchors etc. cannot be handled. */ - return; - } - break; - case OP_PERIOD: - has_period = true; - break; - case OP_BACK_REF: - case OP_ALT: - case END_OF_RE: - case OP_DUP_ASTERISK: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - break; - case COMPLEX_BRACKET: - return; - case SIMPLE_BRACKET: - /* Just double check. */ - { - int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0 - ? 0 - : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS); - for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) - { - if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0) - return; - rshift = 0; - } - } - break; - default: - abort (); - } - - if (mb_chars || has_period) - for (node = 0; node < dfa->nodes_len; ++node) - { - if (dfa->nodes[node].type == CHARACTER - && dfa->nodes[node].opr.c >= ASCII_CHARS) - dfa->nodes[node].mb_partial = 0; - else if (dfa->nodes[node].type == OP_PERIOD) - dfa->nodes[node].type = OP_UTF8_PERIOD; - } - - /* The search can be in single byte locale. */ - dfa->mb_cur_max = 1; - dfa->is_utf8 = 0; - dfa->has_mb_node = dfa->nbackref > 0 || has_period; -} -#endif - -/* Analyze the structure tree, and calculate "first", "next", "edest", - "eclosure", and "inveclosure". */ - -static reg_errcode_t -analyze (regex_t *preg) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - reg_errcode_t ret; - - /* Allocate arrays. */ - dfa->nexts = re_malloc (Idx, dfa->nodes_alloc); - dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc); - dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); - dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); - if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL - || dfa->eclosures == NULL, 0)) - return REG_ESPACE; - - dfa->subexp_map = re_malloc (Idx, preg->re_nsub); - if (dfa->subexp_map != NULL) - { - Idx i; - for (i = 0; i < preg->re_nsub; i++) - dfa->subexp_map[i] = i; - preorder (dfa->str_tree, optimize_subexps, dfa); - for (i = 0; i < preg->re_nsub; i++) - if (dfa->subexp_map[i] != i) - break; - if (i == preg->re_nsub) - { - free (dfa->subexp_map); - dfa->subexp_map = NULL; - } - } - - ret = postorder (dfa->str_tree, lower_subexps, preg); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = postorder (dfa->str_tree, calc_first, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - preorder (dfa->str_tree, calc_next, dfa); - ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - ret = calc_eclosure (dfa); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - /* We only need this during the prune_impossible_nodes pass in regexec.c; - skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ - if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) - || dfa->nbackref) - { - dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); - if (BE (dfa->inveclosures == NULL, 0)) - return REG_ESPACE; - ret = calc_inveclosure (dfa); - } - - return ret; -} - -/* Our parse trees are very unbalanced, so we cannot use a stack to - implement parse tree visits. Instead, we use parent pointers and - some hairy code in these two functions. */ -static reg_errcode_t -postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node, *prev; - - for (node = root; ; ) - { - /* Descend down the tree, preferably to the left (or to the right - if that's the only child). */ - while (node->left || node->right) - if (node->left) - node = node->left; - else - node = node->right; - - do - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - if (node->parent == NULL) - return REG_NOERROR; - prev = node; - node = node->parent; - } - /* Go up while we have a node that is reached from the right. */ - while (node->right == prev || node->right == NULL); - node = node->right; - } -} - -static reg_errcode_t -preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), - void *extra) -{ - bin_tree_t *node; - - for (node = root; ; ) - { - reg_errcode_t err = fn (extra, node); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Go to the left node, or up and to the right. */ - if (node->left) - node = node->left; - else - { - bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - if (!node) - return REG_NOERROR; - } - node = node->right; - } - } -} - -/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell - re_search_internal to map the inner one's opr.idx to this one's. Adjust - backreferences as well. Requires a preorder visit. */ -static reg_errcode_t -optimize_subexps (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - - if (node->token.type == OP_BACK_REF && dfa->subexp_map) - { - int idx = node->token.opr.idx; - node->token.opr.idx = dfa->subexp_map[idx]; - dfa->used_bkref_map |= 1 << node->token.opr.idx; - } - - else if (node->token.type == SUBEXP - && node->left && node->left->token.type == SUBEXP) - { - Idx other_idx = node->left->token.opr.idx; - - node->left = node->left->left; - if (node->left) - node->left->parent = node; - - dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; - if (other_idx < BITSET_WORD_BITS) - dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); - } - - return REG_NOERROR; -} - -/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation - of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ -static reg_errcode_t -lower_subexps (void *extra, bin_tree_t *node) -{ - regex_t *preg = (regex_t *) extra; - reg_errcode_t err = REG_NOERROR; - - if (node->left && node->left->token.type == SUBEXP) - { - node->left = lower_subexp (&err, preg, node->left); - if (node->left) - node->left->parent = node; - } - if (node->right && node->right->token.type == SUBEXP) - { - node->right = lower_subexp (&err, preg, node->right); - if (node->right) - node->right->parent = node; - } - - return err; -} - -static bin_tree_t * -lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *body = node->left; - bin_tree_t *op, *cls, *tree1, *tree; - - if (preg->no_sub - /* We do not optimize empty subexpressions, because otherwise we may - have bad CONCAT nodes with NULL children. This is obviously not - very common, so we do not lose much. An example that triggers - this case is the sed "script" /\(\)/x. */ - && node->left != NULL - && (node->token.opr.idx >= BITSET_WORD_BITS - || !(dfa->used_bkref_map - & ((bitset_word_t) 1 << node->token.opr.idx)))) - return node->left; - - /* Convert the SUBEXP node to the concatenation of an - OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ - op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); - cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); - tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; - tree = create_tree (dfa, op, tree1, CONCAT); - if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - - op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; - op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; - return tree; -} - -/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton - nodes. Requires a postorder visit. */ -static reg_errcode_t -calc_first (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - if (node->token.type == CONCAT) - { - node->first = node->left->first; - node->node_idx = node->left->node_idx; - } - else - { - node->first = node; - node->node_idx = re_dfa_add_node (dfa, node->token); - if (BE (node->node_idx == REG_MISSING, 0)) - return REG_ESPACE; - } - return REG_NOERROR; -} - -/* Pass 2: compute NEXT on the tree. Preorder visit. */ -static reg_errcode_t -calc_next (void *extra, bin_tree_t *node) -{ - switch (node->token.type) - { - case OP_DUP_ASTERISK: - node->left->next = node; - break; - case CONCAT: - node->left->next = node->right->first; - node->right->next = node->next; - break; - default: - if (node->left) - node->left->next = node->next; - if (node->right) - node->right->next = node->next; - break; - } - return REG_NOERROR; -} - -/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ -static reg_errcode_t -link_nfa_nodes (void *extra, bin_tree_t *node) -{ - re_dfa_t *dfa = (re_dfa_t *) extra; - Idx idx = node->node_idx; - reg_errcode_t err = REG_NOERROR; - - switch (node->token.type) - { - case CONCAT: - break; - - case END_OF_RE: - assert (node->next == NULL); - break; - - case OP_DUP_ASTERISK: - case OP_ALT: - { - Idx left, right; - dfa->has_plural_match = 1; - if (node->left != NULL) - left = node->left->first->node_idx; - else - left = node->next->node_idx; - if (node->right != NULL) - right = node->right->first->node_idx; - else - right = node->next->node_idx; - assert (REG_VALID_INDEX (left)); - assert (REG_VALID_INDEX (right)); - err = re_node_set_init_2 (dfa->edests + idx, left, right); - } - break; - - case ANCHOR: - case OP_OPEN_SUBEXP: - case OP_CLOSE_SUBEXP: - err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); - break; - - case OP_BACK_REF: - dfa->nexts[idx] = node->next->node_idx; - if (node->token.type == OP_BACK_REF) - re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); - break; - - default: - assert (!IS_EPSILON_NODE (node->token.type)); - dfa->nexts[idx] = node->next->node_idx; - break; - } - - return err; -} - -/* Duplicate the epsilon closure of the node ROOT_NODE. - Note that duplicated nodes have constraint INIT_CONSTRAINT in addition - to their own constraint. */ - -static reg_errcode_t -internal_function -duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node, - Idx root_node, unsigned int init_constraint) -{ - Idx org_node, clone_node; - bool ok; - unsigned int constraint = init_constraint; - for (org_node = top_org_node, clone_node = top_clone_node;;) - { - Idx org_dest, clone_dest; - if (dfa->nodes[org_node].type == OP_BACK_REF) - { - /* If the back reference epsilon-transit, its destination must - also have the constraint. Then duplicate the epsilon closure - of the destination of the back reference, and store it in - edests of the back reference. */ - org_dest = dfa->nexts[org_node]; - re_node_set_empty (dfa->edests + clone_node); - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - dfa->nexts[clone_node] = dfa->nexts[org_node]; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else if (dfa->edests[org_node].nelem == 0) - { - /* In case of the node can't epsilon-transit, don't duplicate the - destination and store the original destination as the - destination of the node. */ - dfa->nexts[clone_node] = dfa->nexts[org_node]; - break; - } - else if (dfa->edests[org_node].nelem == 1) - { - /* In case of the node can epsilon-transit, and it has only one - destination. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - if (dfa->nodes[org_node].type == ANCHOR) - { - /* In case of the node has another constraint, append it. */ - if (org_node == root_node && clone_node != org_node) - { - /* ...but if the node is root_node itself, it means the - epsilon closure have a loop, then tie it to the - destination of the root_node. */ - ok = re_node_set_insert (dfa->edests + clone_node, org_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - break; - } - constraint |= dfa->nodes[org_node].opr.ctx_type; - } - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - else /* dfa->edests[org_node].nelem == 2 */ - { - /* In case of the node can epsilon-transit, and it has two - destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ - org_dest = dfa->edests[org_node].elems[0]; - re_node_set_empty (dfa->edests + clone_node); - /* Search for a duplicated node which satisfies the constraint. */ - clone_dest = search_duplicated_node (dfa, org_dest, constraint); - if (clone_dest == REG_MISSING) - { - /* There are no such a duplicated node, create a new one. */ - reg_errcode_t err; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - err = duplicate_node_closure (dfa, org_dest, clone_dest, - root_node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - { - /* There are a duplicated node which satisfy the constraint, - use it to avoid infinite loop. */ - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - org_dest = dfa->edests[org_node].elems[1]; - clone_dest = duplicate_node (dfa, org_dest, constraint); - if (BE (clone_dest == REG_MISSING, 0)) - return REG_ESPACE; - ok = re_node_set_insert (dfa->edests + clone_node, clone_dest); - if (BE (! ok, 0)) - return REG_ESPACE; - } - org_node = org_dest; - clone_node = clone_dest; - } - return REG_NOERROR; -} - -/* Search for a node which is duplicated from the node ORG_NODE, and - satisfies the constraint CONSTRAINT. */ - -static Idx -search_duplicated_node (const re_dfa_t *dfa, Idx org_node, - unsigned int constraint) -{ - Idx idx; - for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) - { - if (org_node == dfa->org_indices[idx] - && constraint == dfa->nodes[idx].constraint) - return idx; /* Found. */ - } - return REG_MISSING; /* Not found. */ -} - -/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. - Return the index of the new node, or REG_MISSING if insufficient storage is - available. */ - -static Idx -duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint) -{ - Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); - if (BE (dup_idx != REG_MISSING, 1)) - { - dfa->nodes[dup_idx].constraint = constraint; - if (dfa->nodes[org_idx].type == ANCHOR) - dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; - dfa->nodes[dup_idx].duplicated = 1; - - /* Store the index of the original node. */ - dfa->org_indices[dup_idx] = org_idx; - } - return dup_idx; -} - -static reg_errcode_t -calc_inveclosure (re_dfa_t *dfa) -{ - Idx src, idx; - bool ok; - for (idx = 0; idx < dfa->nodes_len; ++idx) - re_node_set_init_empty (dfa->inveclosures + idx); - - for (src = 0; src < dfa->nodes_len; ++src) - { - Idx *elems = dfa->eclosures[src].elems; - for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) - { - ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); - if (BE (! ok, 0)) - return REG_ESPACE; - } - } - - return REG_NOERROR; -} - -/* Calculate "eclosure" for all the node in DFA. */ - -static reg_errcode_t -calc_eclosure (re_dfa_t *dfa) -{ - Idx node_idx; - bool incomplete; -#ifdef DEBUG - assert (dfa->nodes_len > 0); -#endif - incomplete = false; - /* For each nodes, calculate epsilon closure. */ - for (node_idx = 0; ; ++node_idx) - { - reg_errcode_t err; - re_node_set eclosure_elem; - if (node_idx == dfa->nodes_len) - { - if (!incomplete) - break; - incomplete = false; - node_idx = 0; - } - -#ifdef DEBUG - assert (dfa->eclosures[node_idx].nelem != REG_MISSING); -#endif - - /* If we have already calculated, skip it. */ - if (dfa->eclosures[node_idx].nelem != 0) - continue; - /* Calculate epsilon closure of `node_idx'. */ - err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (dfa->eclosures[node_idx].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - return REG_NOERROR; -} - -/* Calculate epsilon closure of NODE. */ - -static reg_errcode_t -calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root) -{ - reg_errcode_t err; - unsigned int constraint; - Idx i; - bool incomplete; - bool ok; - re_node_set eclosure; - incomplete = false; - err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* This indicates that we are calculating this node now. - We reference this value to avoid infinite loop. */ - dfa->eclosures[node].nelem = REG_MISSING; - - constraint = ((dfa->nodes[node].type == ANCHOR) - ? dfa->nodes[node].opr.ctx_type : 0); - /* If the current node has constraints, duplicate all nodes. - Since they must inherit the constraints. */ - if (constraint - && dfa->edests[node].nelem - && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) - { - err = duplicate_node_closure (dfa, node, node, node, constraint); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Expand each epsilon destination nodes. */ - if (IS_EPSILON_NODE(dfa->nodes[node].type)) - for (i = 0; i < dfa->edests[node].nelem; ++i) - { - re_node_set eclosure_elem; - Idx edest = dfa->edests[node].elems[i]; - /* If calculating the epsilon closure of `edest' is in progress, - return intermediate result. */ - if (dfa->eclosures[edest].nelem == REG_MISSING) - { - incomplete = true; - continue; - } - /* If we haven't calculated the epsilon closure of `edest' yet, - calculate now. Otherwise use calculated epsilon closure. */ - if (dfa->eclosures[edest].nelem == 0) - { - err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - eclosure_elem = dfa->eclosures[edest]; - /* Merge the epsilon closure of `edest'. */ - re_node_set_merge (&eclosure, &eclosure_elem); - /* If the epsilon closure of `edest' is incomplete, - the epsilon closure of this node is also incomplete. */ - if (dfa->eclosures[edest].nelem == 0) - { - incomplete = true; - re_node_set_free (&eclosure_elem); - } - } - - /* Epsilon closures include itself. */ - ok = re_node_set_insert (&eclosure, node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (incomplete && !root) - dfa->eclosures[node].nelem = 0; - else - dfa->eclosures[node] = eclosure; - *new_set = eclosure; - return REG_NOERROR; -} - -/* Functions for token which are used in the parser. */ - -/* Fetch a token from INPUT. - We must not use this function inside bracket expressions. */ - -static void -internal_function -fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) -{ - re_string_skip_bytes (input, peek_token (result, input, syntax)); -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function inside bracket expressions. */ - -static int -internal_function -peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - - c = re_string_peek_byte (input, 0); - token->opr.c = c; - - token->word_char = 0; -#ifdef RE_ENABLE_I18N - token->mb_partial = 0; - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - token->mb_partial = 1; - return 1; - } -#endif - if (c == '\\') - { - unsigned char c2; - if (re_string_cur_idx (input) + 1 >= re_string_length (input)) - { - token->type = BACK_SLASH; - return 1; - } - - c2 = re_string_peek_byte_case (input, 1); - token->opr.c = c2; - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, - re_string_cur_idx (input) + 1); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (c2) != 0; - - switch (c2) - { - case '|': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '1': case '2': case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - if (!(syntax & RE_NO_BK_REFS)) - { - token->type = OP_BACK_REF; - token->opr.idx = c2 - '1'; - } - break; - case '<': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_FIRST; - } - break; - case '>': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_LAST; - } - break; - case 'b': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = WORD_DELIM; - } - break; - case 'B': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = NOT_WORD_DELIM; - } - break; - case 'w': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_WORD; - break; - case 'W': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTWORD; - break; - case 's': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_SPACE; - break; - case 'S': - if (!(syntax & RE_NO_GNU_OPS)) - token->type = OP_NOTSPACE; - break; - case '`': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_FIRST; - } - break; - case '\'': - if (!(syntax & RE_NO_GNU_OPS)) - { - token->type = ANCHOR; - token->opr.ctx_type = BUF_LAST; - } - break; - case '(': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (!(syntax & RE_NO_BK_PARENS)) - token->type = OP_CLOSE_SUBEXP; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) - token->type = OP_CLOSE_DUP_NUM; - break; - default: - break; - } - return 2; - } - - token->type = CHARACTER; -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); - token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; - } - else -#endif - token->word_char = IS_WORD_CHAR (token->opr.c); - - switch (c) - { - case '\n': - if (syntax & RE_NEWLINE_ALT) - token->type = OP_ALT; - break; - case '|': - if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) - token->type = OP_ALT; - break; - case '*': - token->type = OP_DUP_ASTERISK; - break; - case '+': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_PLUS; - break; - case '?': - if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) - token->type = OP_DUP_QUESTION; - break; - case '{': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_OPEN_DUP_NUM; - break; - case '}': - if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) - token->type = OP_CLOSE_DUP_NUM; - break; - case '(': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_OPEN_SUBEXP; - break; - case ')': - if (syntax & RE_NO_BK_PARENS) - token->type = OP_CLOSE_SUBEXP; - break; - case '[': - token->type = OP_OPEN_BRACKET; - break; - case '.': - token->type = OP_PERIOD; - break; - case '^': - if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && - re_string_cur_idx (input) != 0) - { - char prev = re_string_peek_byte (input, -1); - if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_FIRST; - break; - case '$': - if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && - re_string_cur_idx (input) + 1 != re_string_length (input)) - { - re_token_t next; - re_string_skip_bytes (input, 1); - peek_token (&next, input, syntax); - re_string_skip_bytes (input, -1); - if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) - break; - } - token->type = ANCHOR; - token->opr.ctx_type = LINE_LAST; - break; - default: - break; - } - return 1; -} - -/* Peek a token from INPUT, and return the length of the token. - We must not use this function out of bracket expressions. */ - -static int -internal_function -peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) -{ - unsigned char c; - if (re_string_eoi (input)) - { - token->type = END_OF_RE; - return 0; - } - c = re_string_peek_byte (input, 0); - token->opr.c = c; - -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1 && - !re_string_first_byte (input, re_string_cur_idx (input))) - { - token->type = CHARACTER; - return 1; - } -#endif /* RE_ENABLE_I18N */ - - if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) - && re_string_cur_idx (input) + 1 < re_string_length (input)) - { - /* In this case, '\' escape a character. */ - unsigned char c2; - re_string_skip_bytes (input, 1); - c2 = re_string_peek_byte (input, 0); - token->opr.c = c2; - token->type = CHARACTER; - return 1; - } - if (c == '[') /* '[' is a special char in a bracket exps. */ - { - unsigned char c2; - int token_len; - if (re_string_cur_idx (input) + 1 < re_string_length (input)) - c2 = re_string_peek_byte (input, 1); - else - c2 = 0; - token->opr.c = c2; - token_len = 2; - switch (c2) - { - case '.': - token->type = OP_OPEN_COLL_ELEM; - break; - case '=': - token->type = OP_OPEN_EQUIV_CLASS; - break; - case ':': - if (syntax & RE_CHAR_CLASSES) - { - token->type = OP_OPEN_CHAR_CLASS; - break; - } - /* else fall through. */ - default: - token->type = CHARACTER; - token->opr.c = c; - token_len = 1; - break; - } - return token_len; - } - switch (c) - { - case '-': - token->type = OP_CHARSET_RANGE; - break; - case ']': - token->type = OP_CLOSE_BRACKET; - break; - case '^': - token->type = OP_NON_MATCH_LIST; - break; - default: - token->type = CHARACTER; - } - return 1; -} - -/* Functions for parser. */ - -/* Entry point of the parser. - Parse the regular expression REGEXP and return the structure tree. - If an error is occured, ERR is set by error code, and return NULL. - This function build the following tree, from regular expression : - CAT - / \ - / \ - EOR - - CAT means concatenation. - EOR means end of regular expression. */ - -static bin_tree_t * -parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, - reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *eor, *root; - re_token_t current_token; - dfa->syntax = syntax; - fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); - tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - eor = create_tree (dfa, NULL, NULL, END_OF_RE); - if (tree != NULL) - root = create_tree (dfa, tree, eor, CONCAT); - else - root = eor; - if (BE (eor == NULL || root == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - return root; -} - -/* This function build the following tree, from regular expression - |: - ALT - / \ - / \ - - - ALT means alternative, which represents the operator `|'. */ - -static bin_tree_t * -parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree, *branch = NULL; - tree = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type == OP_ALT) - { - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - if (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - branch = parse_branch (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && branch == NULL, 0)) - return NULL; - } - else - branch = NULL; - tree = create_tree (dfa, tree, branch, OP_ALT); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - return tree; -} - -/* This function build the following tree, from regular expression - : - CAT - / \ - / \ - - - CAT means concatenation. */ - -static bin_tree_t * -parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - bin_tree_t *tree, *expr; - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - tree = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - - while (token->type != OP_ALT && token->type != END_OF_RE - && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) - { - expr = parse_expression (regexp, preg, token, syntax, nest, err); - if (BE (*err != REG_NOERROR && expr == NULL, 0)) - { - return NULL; - } - if (tree != NULL && expr != NULL) - { - tree = create_tree (dfa, tree, expr, CONCAT); - if (tree == NULL) - { - *err = REG_ESPACE; - return NULL; - } - } - else if (tree == NULL) - tree = expr; - /* Otherwise expr == NULL, we don't need to create new tree. */ - } - return tree; -} - -/* This function build the following tree, from regular expression a*: - * - | - a -*/ - -static bin_tree_t * -parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - switch (token->type) - { - case CHARACTER: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (!re_string_eoi (regexp) - && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) - { - bin_tree_t *mbc_remain; - fetch_token (token, regexp, syntax); - mbc_remain = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree, mbc_remain, CONCAT); - if (BE (mbc_remain == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - } -#endif - break; - case OP_OPEN_SUBEXP: - tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_OPEN_BRACKET: - tree = parse_bracket_exp (regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_BACK_REF: - if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) - { - *err = REG_ESUBREG; - return NULL; - } - dfa->used_bkref_map |= 1 << token->opr.idx; - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - ++dfa->nbackref; - dfa->has_mb_node = 1; - break; - case OP_OPEN_DUP_NUM: - if (syntax & RE_CONTEXT_INVALID_DUP) - { - *err = REG_BADRPT; - return NULL; - } - /* FALLTHROUGH */ - case OP_DUP_ASTERISK: - case OP_DUP_PLUS: - case OP_DUP_QUESTION: - if (syntax & RE_CONTEXT_INVALID_OPS) - { - *err = REG_BADRPT; - return NULL; - } - else if (syntax & RE_CONTEXT_INDEP_OPS) - { - fetch_token (token, regexp, syntax); - return parse_expression (regexp, preg, token, syntax, nest, err); - } - /* else fall through */ - case OP_CLOSE_SUBEXP: - if ((token->type == OP_CLOSE_SUBEXP) && - !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) - { - *err = REG_ERPAREN; - return NULL; - } - /* else fall through */ - case OP_CLOSE_DUP_NUM: - /* We treat it as a normal character. */ - - /* Then we can these characters as normal characters. */ - token->type = CHARACTER; - /* mb_partial and word_char bits should be initialized already - by peek_token. */ - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - break; - case ANCHOR: - if ((token->opr.ctx_type - & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) - && dfa->word_ops_used == 0) - init_word_char (dfa); - if (token->opr.ctx_type == WORD_DELIM - || token->opr.ctx_type == NOT_WORD_DELIM) - { - bin_tree_t *tree_first, *tree_last; - if (token->opr.ctx_type == WORD_DELIM) - { - token->opr.ctx_type = WORD_FIRST; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = WORD_LAST; - } - else - { - token->opr.ctx_type = INSIDE_WORD; - tree_first = create_token_tree (dfa, NULL, NULL, token); - token->opr.ctx_type = INSIDE_NOTWORD; - } - tree_last = create_token_tree (dfa, NULL, NULL, token); - tree = create_tree (dfa, tree_first, tree_last, OP_ALT); - if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - else - { - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - } - /* We must return here, since ANCHORs can't be followed - by repetition operators. - eg. RE"^*" is invalid or "", - it must not be "". */ - fetch_token (token, regexp, syntax); - return tree; - case OP_PERIOD: - tree = create_token_tree (dfa, NULL, NULL, token); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - if (dfa->mb_cur_max > 1) - dfa->has_mb_node = 1; - break; - case OP_WORD: - case OP_NOTWORD: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "alnum", - (const unsigned char *) "_", - token->type == OP_NOTWORD, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_SPACE: - case OP_NOTSPACE: - tree = build_charclass_op (dfa, regexp->trans, - (const unsigned char *) "space", - (const unsigned char *) "", - token->type == OP_NOTSPACE, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - break; - case OP_ALT: - case END_OF_RE: - return NULL; - case BACK_SLASH: - *err = REG_EESCAPE; - return NULL; - default: - /* Must not happen? */ -#ifdef DEBUG - assert (0); -#endif - return NULL; - } - fetch_token (token, regexp, syntax); - - while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS - || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) - { - tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); - if (BE (*err != REG_NOERROR && tree == NULL, 0)) - return NULL; - /* In BRE consecutive duplications are not allowed. */ - if ((syntax & RE_CONTEXT_INVALID_DUP) - && (token->type == OP_DUP_ASTERISK - || token->type == OP_OPEN_DUP_NUM)) - { - *err = REG_BADRPT; - return NULL; - } - } - - return tree; -} - -/* This function build the following tree, from regular expression - (): - SUBEXP - | - -*/ - -static bin_tree_t * -parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, - reg_syntax_t syntax, Idx nest, reg_errcode_t *err) -{ - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; - bin_tree_t *tree; - size_t cur_nsub; - cur_nsub = preg->re_nsub++; - - fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); - - /* The subexpression may be a null string. */ - if (token->type == OP_CLOSE_SUBEXP) - tree = NULL; - else - { - tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); - if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) - *err = REG_EPAREN; - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - - if (cur_nsub <= '9' - '1') - dfa->completed_bkref_map |= 1 << cur_nsub; - - tree = create_tree (dfa, tree, NULL, SUBEXP); - if (BE (tree == NULL, 0)) - { - *err = REG_ESPACE; - return NULL; - } - tree->token.opr.idx = cur_nsub; - return tree; -} - -/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ - -static bin_tree_t * -parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, - re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) -{ - bin_tree_t *tree = NULL, *old_tree = NULL; - Idx i, start, end, start_idx = re_string_cur_idx (regexp); - re_token_t start_token = *token; - - if (token->type == OP_OPEN_DUP_NUM) - { - end = 0; - start = fetch_number (regexp, token, syntax); - if (start == REG_MISSING) - { - if (token->type == CHARACTER && token->opr.c == ',') - start = 0; /* We treat "{,m}" as "{0,m}". */ - else - { - *err = REG_BADBR; /* {} is invalid. */ - return NULL; - } - } - if (BE (start != REG_ERROR, 1)) - { - /* We treat "{n}" as "{n,n}". */ - end = ((token->type == OP_CLOSE_DUP_NUM) ? start - : ((token->type == CHARACTER && token->opr.c == ',') - ? fetch_number (regexp, token, syntax) : REG_ERROR)); - } - if (BE (start == REG_ERROR || end == REG_ERROR, 0)) - { - /* Invalid sequence. */ - if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) - { - if (token->type == END_OF_RE) - *err = REG_EBRACE; - else - *err = REG_BADBR; - - return NULL; - } - - /* If the syntax bit is set, rollback. */ - re_string_set_index (regexp, start_idx); - *token = start_token; - token->type = CHARACTER; - /* mb_partial and word_char bits should be already initialized by - peek_token. */ - return elem; - } - - if (BE (end != REG_MISSING && start > end, 0)) - { - /* First number greater than second. */ - *err = REG_BADBR; - return NULL; - } - } - else - { - start = (token->type == OP_DUP_PLUS) ? 1 : 0; - end = (token->type == OP_DUP_QUESTION) ? 1 : REG_MISSING; - } - - fetch_token (token, regexp, syntax); - - if (BE (elem == NULL, 0)) - return NULL; - if (BE (start == 0 && end == 0, 0)) - { - postorder (elem, free_tree, NULL); - return NULL; - } - - /* Extract "{n,m}" to "...{0,}". */ - if (BE (start > 0, 0)) - { - tree = elem; - for (i = 2; i <= start; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (start == end) - return tree; - - /* Duplicate ELEM before it is marked optional. */ - elem = duplicate_tree (elem, dfa); - old_tree = tree; - } - else - old_tree = NULL; - - if (elem->token.type == SUBEXP) - postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); - - tree = create_tree (dfa, elem, NULL, - (end == REG_MISSING ? OP_DUP_ASTERISK : OP_ALT)); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - - /* This loop is actually executed only when end != REG_MISSING, - to rewrite {0,n} as ((...?)?)?... We have - already created the start+1-th copy. */ - if ((Idx) -1 < 0 || end != REG_MISSING) - for (i = start + 2; i <= end; ++i) - { - elem = duplicate_tree (elem, dfa); - tree = create_tree (dfa, tree, elem, CONCAT); - if (BE (elem == NULL || tree == NULL, 0)) - goto parse_dup_op_espace; - - tree = create_tree (dfa, tree, NULL, OP_ALT); - if (BE (tree == NULL, 0)) - goto parse_dup_op_espace; - } - - if (old_tree) - tree = create_tree (dfa, old_tree, tree, CONCAT); - - return tree; - - parse_dup_op_espace: - *err = REG_ESPACE; - return NULL; -} - -/* Size of the names for collating symbol/equivalence_class/character_class. - I'm not sure, but maybe enough. */ -#define BRACKET_NAME_BUF_SIZE 32 - -#ifndef _LIBC - /* Local function for parse_bracket_exp only used in case of NOT _LIBC. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - -static reg_errcode_t -internal_function -# ifdef RE_ENABLE_I18N -build_range_exp (bitset_t sbcset, re_charset_t *mbcset, Idx *range_alloc, - bracket_elem_t *start_elem, bracket_elem_t *end_elem) -# else /* not RE_ENABLE_I18N */ -build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, - bracket_elem_t *end_elem) -# endif /* not RE_ENABLE_I18N */ -{ - unsigned int start_ch, end_ch; - /* Equivalence Classes and Character Classes can't be a range start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - /* We can handle no multi character collating elements without libc - support. */ - if (BE ((start_elem->type == COLL_SYM - && strlen ((char *) start_elem->opr.name) > 1) - || (end_elem->type == COLL_SYM - && strlen ((char *) end_elem->opr.name) > 1), 0)) - return REG_ECOLLATE; - -# ifdef RE_ENABLE_I18N - { - wchar_t wc; - wint_t start_wc; - wint_t end_wc; - wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - - start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) - ? __btowc (start_ch) : start_elem->opr.wch); - end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) - ? __btowc (end_ch) : end_elem->opr.wch); - if (start_wc == WEOF || end_wc == WEOF) - return REG_ECOLLATE; - cmp_buf[0] = start_wc; - cmp_buf[4] = end_wc; - if (wcscoll (cmp_buf, cmp_buf + 4) > 0) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, for !_LIBC we have no collation elements: if the - character set is single byte, the single byte character set - that we build below suffices. parse_bracket_exp passes - no MBCSET if dfa->mb_cur_max == 1. */ - if (mbcset) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - wchar_t *new_array_start, *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - /* Use realloc since mbcset->range_starts and mbcset->range_ends - are NULL if *range_alloc == 0. */ - new_array_start = re_realloc (mbcset->range_starts, wchar_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, wchar_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_wc; - mbcset->range_ends[mbcset->nranges++] = end_wc; - } - - /* Build the table for single byte characters. */ - for (wc = 0; wc < SBC_MAX; ++wc) - { - cmp_buf[2] = wc; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - bitset_set (sbcset, wc); - } - } -# else /* not RE_ENABLE_I18N */ - { - unsigned int ch; - start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch - : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] - : 0)); - end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch - : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] - : 0)); - if (start_ch > end_ch) - return REG_ERANGE; - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ++ch) - if (start_ch <= ch && ch <= end_ch) - bitset_set (sbcset, ch); - } -# endif /* not RE_ENABLE_I18N */ - return REG_NOERROR; -} -#endif /* not _LIBC */ - -#ifndef _LIBC -/* Helper function for parse_bracket_exp only used in case of NOT _LIBC.. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument since we may update it. */ - -static reg_errcode_t -internal_function -build_collating_symbol (bitset_t sbcset, -# ifdef RE_ENABLE_I18N - re_charset_t *mbcset, Idx *coll_sym_alloc, -# endif - const unsigned char *name) -{ - size_t name_len = strlen ((const char *) name); - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } -} -#endif /* not _LIBC */ - -/* This function parse bracket expression like "[abc]", "[a-c]", - "[[.a-a.]]" etc. */ - -static bin_tree_t * -parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, - reg_syntax_t syntax, reg_errcode_t *err) -{ -#ifdef _LIBC - const unsigned char *collseqmb; - const char *collseqwc; - uint32_t nrules; - int32_t table_size; - const int32_t *symb_table; - const unsigned char *extra; - - /* Local function for parse_bracket_exp used in _LIBC environement. - Seek the collating symbol entry correspondings to NAME. - Return the index of the symbol in the SYMB_TABLE. */ - - auto inline int32_t - __attribute ((always_inline)) - seek_collating_symbol_entry (name, name_len) - const unsigned char *name; - size_t name_len; - { - int32_t hash = elem_hash ((const char *) name, name_len); - int32_t elem = hash % table_size; - if (symb_table[2 * elem] != 0) - { - int32_t second = hash % (table_size - 2) + 1; - - do - { - /* First compare the hashing value. */ - if (symb_table[2 * elem] == hash - /* Compare the length of the name. */ - && name_len == extra[symb_table[2 * elem + 1]] - /* Compare the name. */ - && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], - name_len) == 0) - { - /* Yep, this is the entry. */ - break; - } - - /* Next entry. */ - elem += second; - } - while (symb_table[2 * elem] != 0); - } - return elem; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Look up the collation sequence value of BR_ELEM. - Return the value if succeeded, UINT_MAX otherwise. */ - - auto inline unsigned int - __attribute ((always_inline)) - lookup_collation_sequence_value (br_elem) - bracket_elem_t *br_elem; - { - if (br_elem->type == SB_CHAR) - { - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - return collseqmb[br_elem->opr.ch]; - else - { - wint_t wc = __btowc (br_elem->opr.ch); - return __collseq_table_lookup (collseqwc, wc); - } - } - else if (br_elem->type == MB_CHAR) - { - return __collseq_table_lookup (collseqwc, br_elem->opr.wch); - } - else if (br_elem->type == COLL_SYM) - { - size_t sym_name_len = strlen ((char *) br_elem->opr.name); - if (nrules != 0) - { - int32_t elem, idx; - elem = seek_collating_symbol_entry (br_elem->opr.name, - sym_name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - /* Skip the byte sequence of the collating element. */ - idx += 1 + extra[idx]; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the multibyte collation sequence value. */ - idx += sizeof (unsigned int); - /* Skip the wide char sequence of the collating element. */ - idx += sizeof (unsigned int) * - (1 + *(unsigned int *) (extra + idx)); - /* Return the collation sequence value. */ - return *(unsigned int *) (extra + idx); - } - else if (symb_table[2 * elem] == 0 && sym_name_len == 1) - { - /* No valid character. Match it as a single byte - character. */ - return collseqmb[br_elem->opr.name[0]]; - } - } - else if (sym_name_len == 1) - return collseqmb[br_elem->opr.name[0]]; - } - return UINT_MAX; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the range expression which starts from START_ELEM, and ends - at END_ELEM. The result are written to MBCSET and SBCSET. - RANGE_ALLOC is the allocated size of mbcset->range_starts, and - mbcset->range_ends, is a pointer argument sinse we may - update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem) - re_charset_t *mbcset; - Idx *range_alloc; - bitset_t sbcset; - bracket_elem_t *start_elem, *end_elem; - { - unsigned int ch; - uint32_t start_collseq; - uint32_t end_collseq; - - /* Equivalence Classes and Character Classes can't be a range - start/end. */ - if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS - || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, - 0)) - return REG_ERANGE; - - start_collseq = lookup_collation_sequence_value (start_elem); - end_collseq = lookup_collation_sequence_value (end_elem); - /* Check start/end collation sequence values. */ - if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) - return REG_ECOLLATE; - if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) - return REG_ERANGE; - - /* Got valid collation sequence values, add them as a new entry. - However, if we have no collation elements, and the character set - is single byte, the single byte character set that we - build below suffices. */ - if (nrules > 0 || dfa->mb_cur_max > 1) - { - /* Check the space of the arrays. */ - if (BE (*range_alloc == mbcset->nranges, 0)) - { - /* There is not enough space, need realloc. */ - uint32_t *new_array_start; - uint32_t *new_array_end; - Idx new_nranges; - - /* +1 in case of mbcset->nranges is 0. */ - new_nranges = 2 * mbcset->nranges + 1; - new_array_start = re_realloc (mbcset->range_starts, uint32_t, - new_nranges); - new_array_end = re_realloc (mbcset->range_ends, uint32_t, - new_nranges); - - if (BE (new_array_start == NULL || new_array_end == NULL, 0)) - return REG_ESPACE; - - mbcset->range_starts = new_array_start; - mbcset->range_ends = new_array_end; - *range_alloc = new_nranges; - } - - mbcset->range_starts[mbcset->nranges] = start_collseq; - mbcset->range_ends[mbcset->nranges++] = end_collseq; - } - - /* Build the table for single byte characters. */ - for (ch = 0; ch < SBC_MAX; ch++) - { - uint32_t ch_collseq; - /* - if (MB_CUR_MAX == 1) - */ - if (nrules == 0) - ch_collseq = collseqmb[ch]; - else - ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); - if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) - bitset_set (sbcset, ch); - } - return REG_NOERROR; - } - - /* Local function for parse_bracket_exp used in _LIBC environement. - Build the collating element which is represented by NAME. - The result are written to MBCSET and SBCSET. - COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a - pointer argument sinse we may update it. */ - - auto inline reg_errcode_t - __attribute ((always_inline)) - build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name) - re_charset_t *mbcset; - Idx *coll_sym_alloc; - bitset_t sbcset; - const unsigned char *name; - { - int32_t elem, idx; - size_t name_len = strlen ((const char *) name); - if (nrules != 0) - { - elem = seek_collating_symbol_entry (name, name_len); - if (symb_table[2 * elem] != 0) - { - /* We found the entry. */ - idx = symb_table[2 * elem + 1]; - /* Skip the name of collating element name. */ - idx += 1 + extra[idx]; - } - else if (symb_table[2 * elem] == 0 && name_len == 1) - { - /* No valid character, treat it as a normal - character. */ - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - else - return REG_ECOLLATE; - - /* Got valid collation sequence, add it as a new entry. */ - /* Check the space of the arrays. */ - if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->ncoll_syms is 0. */ - Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; - /* Use realloc since mbcset->coll_syms is NULL - if *alloc == 0. */ - int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, - new_coll_sym_alloc); - if (BE (new_coll_syms == NULL, 0)) - return REG_ESPACE; - mbcset->coll_syms = new_coll_syms; - *coll_sym_alloc = new_coll_sym_alloc; - } - mbcset->coll_syms[mbcset->ncoll_syms++] = idx; - return REG_NOERROR; - } - else - { - if (BE (name_len != 1, 0)) - return REG_ECOLLATE; - else - { - bitset_set (sbcset, name[0]); - return REG_NOERROR; - } - } - } -#endif - - re_token_t br_token; - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; - Idx equiv_class_alloc = 0, char_class_alloc = 0; -#endif /* not RE_ENABLE_I18N */ - bool non_match = false; - bin_tree_t *work_tree; - int token_len; - bool first_round = true; -#ifdef _LIBC - collseqmb = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules) - { - /* - if (MB_CUR_MAX > 1) - */ - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); - symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_TABLEMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_SYMB_EXTRAMB); - } -#endif - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else - if (BE (sbcset == NULL, 0)) -#endif /* RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_NON_MATCH_LIST) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - non_match = true; - if (syntax & RE_HAT_LISTS_NOT_NEWLINE) - bitset_set (sbcset, '\n'); - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - token_len = peek_token_bracket (token, regexp, syntax); - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_BADPAT; - goto parse_bracket_exp_free_return; - } - } - - /* We treat the first ']' as a normal character. */ - if (token->type == OP_CLOSE_BRACKET) - token->type = CHARACTER; - - while (1) - { - bracket_elem_t start_elem, end_elem; - unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; - unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; - reg_errcode_t ret; - int token_len2 = 0; - bool is_range_exp = false; - re_token_t token2; - - start_elem.opr.name = start_name_buf; - ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, - syntax, first_round); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - first_round = false; - - /* Get information about the next token. We need it in any case. */ - token_len = peek_token_bracket (token, regexp, syntax); - - /* Do not check for ranges if we know they are not allowed. */ - if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) - { - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CHARSET_RANGE) - { - re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ - token_len2 = peek_token_bracket (&token2, regexp, syntax); - if (BE (token2.type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token2.type == OP_CLOSE_BRACKET) - { - /* We treat the last '-' as a normal character. */ - re_string_skip_bytes (regexp, -token_len); - token->type = CHARACTER; - } - else - is_range_exp = true; - } - } - - if (is_range_exp == true) - { - end_elem.opr.name = end_name_buf; - ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, - dfa, syntax, true); - if (BE (ret != REG_NOERROR, 0)) - { - *err = ret; - goto parse_bracket_exp_free_return; - } - - token_len = peek_token_bracket (token, regexp, syntax); - -#ifdef _LIBC - *err = build_range_exp (sbcset, mbcset, &range_alloc, - &start_elem, &end_elem); -#else -# ifdef RE_ENABLE_I18N - *err = build_range_exp (sbcset, - dfa->mb_cur_max > 1 ? mbcset : NULL, - &range_alloc, &start_elem, &end_elem); -# else - *err = build_range_exp (sbcset, &start_elem, &end_elem); -# endif -#endif /* RE_ENABLE_I18N */ - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - } - else - { - switch (start_elem.type) - { - case SB_CHAR: - bitset_set (sbcset, start_elem.opr.ch); - break; -#ifdef RE_ENABLE_I18N - case MB_CHAR: - /* Check whether the array has enough space. */ - if (BE (mbchar_alloc == mbcset->nmbchars, 0)) - { - wchar_t *new_mbchars; - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nmbchars is 0. */ - mbchar_alloc = 2 * mbcset->nmbchars + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - new_mbchars = re_realloc (mbcset->mbchars, wchar_t, - mbchar_alloc); - if (BE (new_mbchars == NULL, 0)) - goto parse_bracket_exp_espace; - mbcset->mbchars = new_mbchars; - } - mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; - break; -#endif /* RE_ENABLE_I18N */ - case EQUIV_CLASS: - *err = build_equiv_class (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &equiv_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case COLL_SYM: - *err = build_collating_symbol (sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &coll_sym_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - case CHAR_CLASS: - *err = build_charclass (regexp->trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &char_class_alloc, -#endif /* RE_ENABLE_I18N */ - start_elem.opr.name, syntax); - if (BE (*err != REG_NOERROR, 0)) - goto parse_bracket_exp_free_return; - break; - default: - assert (0); - break; - } - } - if (BE (token->type == END_OF_RE, 0)) - { - *err = REG_EBRACK; - goto parse_bracket_exp_free_return; - } - if (token->type == OP_CLOSE_BRACKET) - break; - } - - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); - - if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes - || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes - || mbcset->non_match))) - { - bin_tree_t *mbc_tree; - int sbc_idx; - /* Build a tree for complex bracket. */ - dfa->has_mb_node = 1; - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto parse_bracket_exp_espace; - for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) - if (sbcset[sbc_idx]) - break; - /* If there are no bits set in sbcset, there is no point - of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ - if (sbc_idx < BITSET_WORDS) - { - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - - /* Then join them by ALT node. */ - work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - else - { - re_free (sbcset); - work_tree = mbc_tree; - } - } - else -#endif /* not RE_ENABLE_I18N */ - { -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - work_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (work_tree == NULL, 0)) - goto parse_bracket_exp_espace; - } - return work_tree; - - parse_bracket_exp_espace: - *err = REG_ESPACE; - parse_bracket_exp_free_return: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - return NULL; -} - -/* Parse an element in the bracket expression. */ - -static reg_errcode_t -parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token, int token_len, re_dfa_t *dfa, - reg_syntax_t syntax, bool accept_hyphen) -{ -#ifdef RE_ENABLE_I18N - int cur_char_size; - cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); - if (cur_char_size > 1) - { - elem->type = MB_CHAR; - elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); - re_string_skip_bytes (regexp, cur_char_size); - return REG_NOERROR; - } -#endif /* RE_ENABLE_I18N */ - re_string_skip_bytes (regexp, token_len); /* Skip a token. */ - if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS - || token->type == OP_OPEN_EQUIV_CLASS) - return parse_bracket_symbol (elem, regexp, token); - if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) - { - /* A '-' must only appear as anything but a range indicator before - the closing bracket. Everything else is an error. */ - re_token_t token2; - (void) peek_token_bracket (&token2, regexp, syntax); - if (token2.type != OP_CLOSE_BRACKET) - /* The actual error value is not standardized since this whole - case is undefined. But ERANGE makes good sense. */ - return REG_ERANGE; - } - elem->type = SB_CHAR; - elem->opr.ch = token->opr.c; - return REG_NOERROR; -} - -/* Parse a bracket symbol in the bracket expression. Bracket symbols are - such as [::], [..], and - [==]. */ - -static reg_errcode_t -parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, - re_token_t *token) -{ - unsigned char ch, delim = token->opr.c; - int i = 0; - if (re_string_eoi(regexp)) - return REG_EBRACK; - for (;; ++i) - { - if (i >= BRACKET_NAME_BUF_SIZE) - return REG_EBRACK; - if (token->type == OP_OPEN_CHAR_CLASS) - ch = re_string_fetch_byte_case (regexp); - else - ch = re_string_fetch_byte (regexp); - if (re_string_eoi(regexp)) - return REG_EBRACK; - if (ch == delim && re_string_peek_byte (regexp, 0) == ']') - break; - elem->opr.name[i] = ch; - } - re_string_skip_bytes (regexp, 1); - elem->opr.name[i] = '\0'; - switch (token->type) - { - case OP_OPEN_COLL_ELEM: - elem->type = COLL_SYM; - break; - case OP_OPEN_EQUIV_CLASS: - elem->type = EQUIV_CLASS; - break; - case OP_OPEN_CHAR_CLASS: - elem->type = CHAR_CLASS; - break; - default: - break; - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the equivalence class which is represented by NAME. - The result are written to MBCSET and SBCSET. - EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, - Idx *equiv_class_alloc, const unsigned char *name) -#else /* not RE_ENABLE_I18N */ -build_equiv_class (bitset_t sbcset, const unsigned char *name) -#endif /* not RE_ENABLE_I18N */ -{ -#ifdef _LIBC - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - const int32_t *table, *indirect; - const unsigned char *weights, *extra, *cp; - unsigned char char_buf[2]; - int32_t idx1, idx2; - unsigned int ch; - size_t len; - /* This #include defines a local function! */ -# include - /* Calculate the index for equivalence class. */ - cp = name; - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - idx1 = findidx (&cp); - if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) - /* This isn't a valid character. */ - return REG_ECOLLATE; - - /* Build single byte matcing table for this equivalence class. */ - char_buf[1] = (unsigned char) '\0'; - len = weights[idx1]; - for (ch = 0; ch < SBC_MAX; ++ch) - { - char_buf[0] = ch; - cp = char_buf; - idx2 = findidx (&cp); -/* - idx2 = table[ch]; -*/ - if (idx2 == 0) - /* This isn't a valid character. */ - continue; - if (len == weights[idx2]) - { - int cnt = 0; - while (cnt <= len && - weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) - ++cnt; - - if (cnt > len) - bitset_set (sbcset, ch); - } - } - /* Check whether the array has enough space. */ - if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nequiv_classes is 0. */ - Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; - /* Use realloc since the array is NULL if *alloc == 0. */ - int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, - int32_t, - new_equiv_class_alloc); - if (BE (new_equiv_classes == NULL, 0)) - return REG_ESPACE; - mbcset->equiv_classes = new_equiv_classes; - *equiv_class_alloc = new_equiv_class_alloc; - } - mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; - } - else -#endif /* _LIBC */ - { - if (BE (strlen ((const char *) name) != 1, 0)) - return REG_ECOLLATE; - bitset_set (sbcset, *name); - } - return REG_NOERROR; -} - - /* Helper function for parse_bracket_exp. - Build the character class which is represented by NAME. - The result are written to MBCSET and SBCSET. - CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, - is a pointer argument sinse we may update it. */ - -static reg_errcode_t -#ifdef RE_ENABLE_I18N -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - re_charset_t *mbcset, Idx *char_class_alloc, - const unsigned char *class_name, reg_syntax_t syntax) -#else /* not RE_ENABLE_I18N */ -build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, - const unsigned char *class_name, reg_syntax_t syntax) -#endif /* not RE_ENABLE_I18N */ -{ - int i; - const char *name = (const char *) class_name; - - /* In case of REG_ICASE "upper" and "lower" match the both of - upper and lower cases. */ - if ((syntax & RE_ICASE) - && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) - name = "alpha"; - -#ifdef RE_ENABLE_I18N - /* Check the space of the arrays. */ - if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) - { - /* Not enough, realloc it. */ - /* +1 in case of mbcset->nchar_classes is 0. */ - Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1; - /* Use realloc since array is NULL if *alloc == 0. */ - wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, - new_char_class_alloc); - if (BE (new_char_classes == NULL, 0)) - return REG_ESPACE; - mbcset->char_classes = new_char_classes; - *char_class_alloc = new_char_class_alloc; - } - mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); -#endif /* RE_ENABLE_I18N */ - -#define BUILD_CHARCLASS_LOOP(ctype_func) \ - do { \ - if (BE (trans != NULL, 0)) \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, trans[i]); \ - } \ - else \ - { \ - for (i = 0; i < SBC_MAX; ++i) \ - if (ctype_func (i)) \ - bitset_set (sbcset, i); \ - } \ - } while (0) - - if (strcmp (name, "alnum") == 0) - BUILD_CHARCLASS_LOOP (isalnum); - else if (strcmp (name, "cntrl") == 0) - BUILD_CHARCLASS_LOOP (iscntrl); - else if (strcmp (name, "lower") == 0) - BUILD_CHARCLASS_LOOP (islower); - else if (strcmp (name, "space") == 0) - BUILD_CHARCLASS_LOOP (isspace); - else if (strcmp (name, "alpha") == 0) - BUILD_CHARCLASS_LOOP (isalpha); - else if (strcmp (name, "digit") == 0) - BUILD_CHARCLASS_LOOP (isdigit); - else if (strcmp (name, "print") == 0) - BUILD_CHARCLASS_LOOP (isprint); - else if (strcmp (name, "upper") == 0) - BUILD_CHARCLASS_LOOP (isupper); - else if (strcmp (name, "blank") == 0) - BUILD_CHARCLASS_LOOP (isblank); - else if (strcmp (name, "graph") == 0) - BUILD_CHARCLASS_LOOP (isgraph); - else if (strcmp (name, "punct") == 0) - BUILD_CHARCLASS_LOOP (ispunct); - else if (strcmp (name, "xdigit") == 0) - BUILD_CHARCLASS_LOOP (isxdigit); - else - return REG_ECTYPE; - - return REG_NOERROR; -} - -static bin_tree_t * -build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, - const unsigned char *class_name, - const unsigned char *extra, bool non_match, - reg_errcode_t *err) -{ - re_bitset_ptr_t sbcset; -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; - Idx alloc = 0; -#endif /* not RE_ENABLE_I18N */ - reg_errcode_t ret; - re_token_t br_token; - bin_tree_t *tree; - - sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1); -#ifdef RE_ENABLE_I18N - mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1); -#endif /* RE_ENABLE_I18N */ - -#ifdef RE_ENABLE_I18N - if (BE (sbcset == NULL || mbcset == NULL, 0)) -#else /* not RE_ENABLE_I18N */ - if (BE (sbcset == NULL, 0)) -#endif /* not RE_ENABLE_I18N */ - { - *err = REG_ESPACE; - return NULL; - } - - if (non_match) - { -#ifdef RE_ENABLE_I18N - mbcset->non_match = 1; -#endif /* not RE_ENABLE_I18N */ - } - - /* We don't care the syntax in this case. */ - ret = build_charclass (trans, sbcset, -#ifdef RE_ENABLE_I18N - mbcset, &alloc, -#endif /* RE_ENABLE_I18N */ - class_name, 0); - - if (BE (ret != REG_NOERROR, 0)) - { - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = ret; - return NULL; - } - /* \w match '_' also. */ - for (; *extra; extra++) - bitset_set (sbcset, *extra); - - /* If it is non-matching list. */ - if (non_match) - bitset_not (sbcset); - -#ifdef RE_ENABLE_I18N - /* Ensure only single byte characters are set. */ - if (dfa->mb_cur_max > 1) - bitset_mask (sbcset, dfa->sb_char); -#endif - - /* Build a tree for simple bracket. */ - br_token.type = SIMPLE_BRACKET; - br_token.opr.sbcset = sbcset; - tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (tree == NULL, 0)) - goto build_word_op_espace; - -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - bin_tree_t *mbc_tree; - /* Build a tree for complex bracket. */ - br_token.type = COMPLEX_BRACKET; - br_token.opr.mbcset = mbcset; - dfa->has_mb_node = 1; - mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); - if (BE (mbc_tree == NULL, 0)) - goto build_word_op_espace; - /* Then join them by ALT node. */ - tree = create_tree (dfa, tree, mbc_tree, OP_ALT); - if (BE (mbc_tree != NULL, 1)) - return tree; - } - else - { - free_charset (mbcset); - return tree; - } -#else /* not RE_ENABLE_I18N */ - return tree; -#endif /* not RE_ENABLE_I18N */ - - build_word_op_espace: - re_free (sbcset); -#ifdef RE_ENABLE_I18N - free_charset (mbcset); -#endif /* RE_ENABLE_I18N */ - *err = REG_ESPACE; - return NULL; -} - -/* This is intended for the expressions like "a{1,3}". - Fetch a number from `input', and return the number. - Return REG_MISSING if the number field is empty like "{,1}". - Return REG_ERROR if an error occurred. */ - -static Idx -fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) -{ - Idx num = REG_MISSING; - unsigned char c; - while (1) - { - fetch_token (token, input, syntax); - c = token->opr.c; - if (BE (token->type == END_OF_RE, 0)) - return REG_ERROR; - if (token->type == OP_CLOSE_DUP_NUM || c == ',') - break; - num = ((token->type != CHARACTER || c < '0' || '9' < c - || num == REG_ERROR) - ? REG_ERROR - : ((num == REG_MISSING) ? c - '0' : num * 10 + c - '0')); - num = (num > RE_DUP_MAX) ? REG_ERROR : num; - } - return num; -} - -#ifdef RE_ENABLE_I18N -static void -free_charset (re_charset_t *cset) -{ - re_free (cset->mbchars); -# ifdef _LIBC - re_free (cset->coll_syms); - re_free (cset->equiv_classes); - re_free (cset->range_starts); - re_free (cset->range_ends); -# endif - re_free (cset->char_classes); - re_free (cset); -} -#endif /* RE_ENABLE_I18N */ - -/* Functions for binary tree operation. */ - -/* Create a tree node. */ - -static bin_tree_t * -create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - re_token_type_t type) -{ - re_token_t t; - t.type = type; - return create_token_tree (dfa, left, right, &t); -} - -static bin_tree_t * -create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, - const re_token_t *token) -{ - bin_tree_t *tree; - if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) - { - bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); - - if (storage == NULL) - return NULL; - storage->next = dfa->str_tree_storage; - dfa->str_tree_storage = storage; - dfa->str_tree_storage_idx = 0; - } - tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; - - tree->parent = NULL; - tree->left = left; - tree->right = right; - tree->token = *token; - tree->token.duplicated = 0; - tree->token.opt_subexp = 0; - tree->first = NULL; - tree->next = NULL; - tree->node_idx = REG_MISSING; - - if (left != NULL) - left->parent = tree; - if (right != NULL) - right->parent = tree; - return tree; -} - -/* Mark the tree SRC as an optional subexpression. - To be called from preorder or postorder. */ - -static reg_errcode_t -mark_opt_subexp (void *extra, bin_tree_t *node) -{ - Idx idx = (Idx) (long) extra; - if (node->token.type == SUBEXP && node->token.opr.idx == idx) - node->token.opt_subexp = 1; - - return REG_NOERROR; -} - -/* Free the allocated memory inside NODE. */ - -static void -free_token (re_token_t *node) -{ -#ifdef RE_ENABLE_I18N - if (node->type == COMPLEX_BRACKET && node->duplicated == 0) - free_charset (node->opr.mbcset); - else -#endif /* RE_ENABLE_I18N */ - if (node->type == SIMPLE_BRACKET && node->duplicated == 0) - re_free (node->opr.sbcset); -} - -/* Worker function for tree walking. Free the allocated memory inside NODE - and its children. */ - -static reg_errcode_t -free_tree (void *extra, bin_tree_t *node) -{ - free_token (&node->token); - return REG_NOERROR; -} - - -/* Duplicate the node SRC, and return new node. This is a preorder - visit similar to the one implemented by the generic visitor, but - we need more infrastructure to maintain two parallel trees --- so, - it's easier to duplicate. */ - -static bin_tree_t * -duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) -{ - const bin_tree_t *node; - bin_tree_t *dup_root; - bin_tree_t **p_new = &dup_root, *dup_node = root->parent; - - for (node = root; ; ) - { - /* Create a new tree and link it back to the current parent. */ - *p_new = create_token_tree (dfa, NULL, NULL, &node->token); - if (*p_new == NULL) - return NULL; - (*p_new)->parent = dup_node; - (*p_new)->token.duplicated = 1; - dup_node = *p_new; - - /* Go to the left node, or up and to the right. */ - if (node->left) - { - node = node->left; - p_new = &dup_node->left; - } - else - { - const bin_tree_t *prev = NULL; - while (node->right == prev || node->right == NULL) - { - prev = node; - node = node->parent; - dup_node = dup_node->parent; - if (!node) - return dup_root; - } - node = node->right; - p_new = &dup_node->right; - } - } -} diff --git a/usr/src/lib/libparted/common/lib/regex.c b/usr/src/lib/libparted/common/lib/regex.c deleted file mode 100644 index 720b2f5b1d..0000000000 --- a/usr/src/lib/libparted/common/lib/regex.c +++ /dev/null @@ -1,71 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Make sure noone compiles this code with a C++ compiler. */ -#if defined __cplusplus && defined _LIBC -# error "This is C code, use a C compiler" -#endif - -#ifdef _LIBC -/* We have to keep the namespace clean. */ -# define regfree(preg) __regfree (preg) -# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef) -# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags) -# define regerror(errcode, preg, errbuf, errbuf_size) \ - __regerror(errcode, preg, errbuf, errbuf_size) -# define re_set_registers(bu, re, nu, st, en) \ - __re_set_registers (bu, re, nu, st, en) -# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \ - __re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop) -# define re_match(bufp, string, size, pos, regs) \ - __re_match (bufp, string, size, pos, regs) -# define re_search(bufp, string, size, startpos, range, regs) \ - __re_search (bufp, string, size, startpos, range, regs) -# define re_compile_pattern(pattern, length, bufp) \ - __re_compile_pattern (pattern, length, bufp) -# define re_set_syntax(syntax) __re_set_syntax (syntax) -# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \ - __re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop) -# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp) - -# include "../locale/localeinfo.h" -#endif - -/* On some systems, limits.h sets RE_DUP_MAX to a lower value than - GNU regex allows. Include it before , which correctly - #undefs RE_DUP_MAX and sets it to the right value. */ -#include - -#include "regex.h" -#include "regex_internal.h" - -#include "regex_internal.c" -#include "regcomp.c" -#include "regexec.c" - -/* Binary backward compatibility. */ -#if _LIBC -# include -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) -link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.") -int re_max_failures = 2000; -# endif -#endif diff --git a/usr/src/lib/libparted/common/lib/regex.h b/usr/src/lib/libparted/common/lib/regex.h deleted file mode 100644 index 7a79ca3724..0000000000 --- a/usr/src/lib/libparted/common/lib/regex.h +++ /dev/null @@ -1,675 +0,0 @@ -/* Definitions for data structures and routines for the regular - expression library. - Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006 - Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_H -#define _REGEX_H 1 - -#include - -/* Allow the use in C++ code. */ -#ifdef __cplusplus -extern "C" { -#endif - -/* Define __USE_GNU_REGEX to declare GNU extensions that violate the - POSIX name space rules. */ -#undef __USE_GNU_REGEX -#if (defined _GNU_SOURCE \ - || (!defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE \ - && !defined _XOPEN_SOURCE)) -# define __USE_GNU_REGEX 1 -#endif - -#ifdef _REGEX_LARGE_OFFSETS - -/* Use types and values that are wide enough to represent signed and - unsigned byte offsets in memory. This currently works only when - the regex code is used outside of the GNU C library; it is not yet - supported within glibc itself, and glibc users should not define - _REGEX_LARGE_OFFSETS. */ - -/* The type of the offset of a byte within a string. - For historical reasons POSIX 1003.1-2004 requires that regoff_t be - at least as wide as off_t. However, many common POSIX platforms set - regoff_t to the more-sensible ssize_t and the Open Group has - signalled its intention to change the requirement to be that - regoff_t be at least as wide as ptrdiff_t and ssize_t; see XBD ERN - 60 (2005-08-25). We don't know of any hosts where ssize_t or - ptrdiff_t is wider than ssize_t, so ssize_t is safe. */ -typedef ssize_t regoff_t; - -/* The type of nonnegative object indexes. Traditionally, GNU regex - uses 'int' for these. Code that uses __re_idx_t should work - regardless of whether the type is signed. */ -typedef size_t __re_idx_t; - -/* The type of object sizes. */ -typedef size_t __re_size_t; - -/* The type of object sizes, in places where the traditional code - uses unsigned long int. */ -typedef size_t __re_long_size_t; - -#else - -/* Use types that are binary-compatible with the traditional GNU regex - implementation, which mishandles strings longer than INT_MAX. */ - -typedef int regoff_t; -typedef int __re_idx_t; -typedef unsigned int __re_size_t; -typedef unsigned long int __re_long_size_t; - -#endif - -/* The following two types have to be signed and unsigned integer type - wide enough to hold a value of a pointer. For most ANSI compilers - ptrdiff_t and size_t should be likely OK. Still size of these two - types is 2 for Microsoft C. Ugh... */ -typedef long int s_reg_t; -typedef unsigned long int active_reg_t; - -/* The following bits are used to determine the regexp syntax we - recognize. The set/not-set meanings are chosen so that Emacs syntax - remains the value 0. The bits are given in alphabetical order, and - the definitions shifted by one from the previous bit; thus, when we - add or remove a bit, only one other definition need change. */ -typedef unsigned long int reg_syntax_t; - -#ifdef __USE_GNU_REGEX - -/* If this bit is not set, then \ inside a bracket expression is literal. - If set, then such a \ quotes the following character. */ -# define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) - -/* If this bit is not set, then + and ? are operators, and \+ and \? are - literals. - If set, then \+ and \? are operators and + and ? are literals. */ -# define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) - -/* If this bit is set, then character classes are supported. They are: - [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], - [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. - If not set, then character classes are not supported. */ -# define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) - -/* If this bit is set, then ^ and $ are always anchors (outside bracket - expressions, of course). - If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. - - This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because - POSIX draft 11.2 says that * etc. in leading positions is undefined. - We already implemented a previous draft which made those constructs - invalid, though, so we haven't changed the code back. */ -# define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) - -/* If this bit is set, then special characters are always special - regardless of where they are in the pattern. - If this bit is not set, then special characters are special only in - some contexts; otherwise they are ordinary. Specifically, - * + ? and intervals are only special when not after the beginning, - open-group, or alternation operator. */ -# define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) - -/* If this bit is set, then *, +, ?, and { cannot be first in an re or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) - -/* If this bit is set, then . matches newline. - If not set, then it doesn't. */ -# define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) - -/* If this bit is set, then . doesn't match NUL. - If not set, then it does. */ -# define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) - -/* If this bit is set, nonmatching lists [^...] do not match newline. - If not set, they do. */ -# define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) - -/* If this bit is set, either \{...\} or {...} defines an - interval, depending on RE_NO_BK_BRACES. - If not set, \{, \}, {, and } are literals. */ -# define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) - -/* If this bit is set, +, ? and | aren't recognized as operators. - If not set, they are. */ -# define RE_LIMITED_OPS (RE_INTERVALS << 1) - -/* If this bit is set, newline is an alternation operator. - If not set, newline is literal. */ -# define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) - -/* If this bit is set, then `{...}' defines an interval, and \{ and \} - are literals. - If not set, then `\{...\}' defines an interval. */ -# define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) - -/* If this bit is set, (...) defines a group, and \( and \) are literals. - If not set, \(...\) defines a group, and ( and ) are literals. */ -# define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) - -/* If this bit is set, then \ matches . - If not set, then \ is a back-reference. */ -# define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) - -/* If this bit is set, then | is an alternation operator, and \| is literal. - If not set, then \| is an alternation operator, and | is literal. */ -# define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) - -/* If this bit is set, then an ending range point collating higher - than the starting range point, as in [z-a], is invalid. - If not set, then when ending range point collates higher than the - starting range point, the range is ignored. */ -# define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) - -/* If this bit is set, then an unmatched ) is ordinary. - If not set, then an unmatched ) is invalid. */ -# define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) - -/* If this bit is set, succeed as soon as we match the whole pattern, - without further backtracking. */ -# define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) - -/* If this bit is set, do not process the GNU regex operators. - If not set, then the GNU regex operators are recognized. */ -# define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) - -/* If this bit is set, turn on internal regex debugging. - If not set, and debugging was on, turn it off. - This only works if regex.c is compiled -DDEBUG. - We define this bit always, so that all that's needed to turn on - debugging is to recompile regex.c; the calling code can always have - this bit set, and it won't affect anything in the normal case. */ -# define RE_DEBUG (RE_NO_GNU_OPS << 1) - -/* If this bit is set, a syntactically invalid interval is treated as - a string of ordinary characters. For example, the ERE 'a{1' is - treated as 'a\{1'. */ -# define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -# define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) - -/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only - for ^, because it is difficult to scan the regex backwards to find - whether ^ should be special. */ -# define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) - -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ -# define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) - -/* If this bit is set, then no_sub will be set to 1 during - re_compile_pattern. */ -# define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) - -#endif /* defined __USE_GNU_REGEX */ - -/* This global variable defines the particular regexp syntax to use (for - some interfaces). When a regexp is compiled, the syntax used is - stored in the pattern buffer, so changing this does not affect - already-compiled regexps. */ -extern reg_syntax_t re_syntax_options; - -#ifdef __USE_GNU_REGEX -/* Define combinations of the above bits for the standard possibilities. - (The [[[ comments delimit what gets put into the Texinfo file, so - don't delete them!) */ -/* [[[begin syntaxes]]] */ -# define RE_SYNTAX_EMACS 0 - -# define RE_SYNTAX_AWK \ - (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ - | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ - | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GNU_AWK \ - ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ - & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ - | RE_CONTEXT_INVALID_OPS )) - -# define RE_SYNTAX_POSIX_AWK \ - (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ - | RE_INTERVALS | RE_NO_GNU_OPS) - -# define RE_SYNTAX_GREP \ - (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ - | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ - | RE_NEWLINE_ALT) - -# define RE_SYNTAX_EGREP \ - (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ - | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ - | RE_NO_BK_VBAR) - -# define RE_SYNTAX_POSIX_EGREP \ - (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ - | RE_INVALID_INTERVAL_ORD) - -/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ -# define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC - -# define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC - -/* Syntax bits common to both basic and extended POSIX regex syntax. */ -# define _RE_SYNTAX_POSIX_COMMON \ - (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ - | RE_INTERVALS | RE_NO_EMPTY_RANGES) - -# define RE_SYNTAX_POSIX_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) - -/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes - RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this - isn't minimal, since other operators, such as \`, aren't disabled. */ -# define RE_SYNTAX_POSIX_MINIMAL_BASIC \ - (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) - -# define RE_SYNTAX_POSIX_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ - | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) - -/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is - removed and RE_NO_BK_REFS is added. */ -# define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ - (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ - | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ - | RE_NO_BK_PARENS | RE_NO_BK_REFS \ - | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) -/* [[[end syntaxes]]] */ - -#endif /* defined __USE_GNU_REGEX */ - -#ifdef __USE_GNU_REGEX - -/* Maximum number of duplicates an interval can allow. POSIX-conforming - systems might define this in , but we want our - value, so remove any previous define. */ -# ifdef RE_DUP_MAX -# undef RE_DUP_MAX -# endif - -/* RE_DUP_MAX is 2**15 - 1 because an earlier implementation stored - the counter as a 2-byte signed integer. This is no longer true, so - RE_DUP_MAX could be increased to (INT_MAX / 10 - 1), or to - ((SIZE_MAX - 2) / 10 - 1) if _REGEX_LARGE_OFFSETS is defined. - However, there would be a huge performance problem if someone - actually used a pattern like a\{214748363\}, so RE_DUP_MAX retains - its historical value. */ -# define RE_DUP_MAX (0x7fff) - -#endif /* defined __USE_GNU_REGEX */ - - -/* POSIX `cflags' bits (i.e., information for `regcomp'). */ - -/* If this bit is set, then use extended regular expression syntax. - If not set, then use basic regular expression syntax. */ -#define REG_EXTENDED 1 - -/* If this bit is set, then ignore case when matching. - If not set, then case is significant. */ -#define REG_ICASE (1 << 1) - -/* If this bit is set, then anchors do not match at newline - characters in the string. - If not set, then anchors do match at newlines. */ -#define REG_NEWLINE (1 << 2) - -/* If this bit is set, then report only success or fail in regexec. - If not set, then returns differ between not matching and errors. */ -#define REG_NOSUB (1 << 3) - - -/* POSIX `eflags' bits (i.e., information for regexec). */ - -/* If this bit is set, then the beginning-of-line operator doesn't match - the beginning of the string (presumably because it's not the - beginning of a line). - If not set, then the beginning-of-line operator does match the - beginning of the string. */ -#define REG_NOTBOL 1 - -/* Like REG_NOTBOL, except for the end-of-line. */ -#define REG_NOTEOL (1 << 1) - -/* Use PMATCH[0] to delimit the start and end of the search in the - buffer. */ -#define REG_STARTEND (1 << 2) - - -/* If any error codes are removed, changed, or added, update the - `__re_error_msgid' table in regcomp.c. */ - -typedef enum -{ - _REG_ENOSYS = -1, /* This will never happen for this implementation. */ - _REG_NOERROR = 0, /* Success. */ - _REG_NOMATCH, /* Didn't find a match (for regexec). */ - - /* POSIX regcomp return error codes. (In the order listed in the - standard.) */ - _REG_BADPAT, /* Invalid pattern. */ - _REG_ECOLLATE, /* Invalid collating element. */ - _REG_ECTYPE, /* Invalid character class name. */ - _REG_EESCAPE, /* Trailing backslash. */ - _REG_ESUBREG, /* Invalid back reference. */ - _REG_EBRACK, /* Unmatched left bracket. */ - _REG_EPAREN, /* Parenthesis imbalance. */ - _REG_EBRACE, /* Unmatched \{. */ - _REG_BADBR, /* Invalid contents of \{\}. */ - _REG_ERANGE, /* Invalid range end. */ - _REG_ESPACE, /* Ran out of memory. */ - _REG_BADRPT, /* No preceding re for repetition op. */ - - /* Error codes we've added. */ - _REG_EEND, /* Premature end. */ - _REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ - _REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ -} reg_errcode_t; - -#ifdef _XOPEN_SOURCE -# define REG_ENOSYS _REG_ENOSYS -#endif -#define REG_NOERROR _REG_NOERROR -#define REG_NOMATCH _REG_NOMATCH -#define REG_BADPAT _REG_BADPAT -#define REG_ECOLLATE _REG_ECOLLATE -#define REG_ECTYPE _REG_ECTYPE -#define REG_EESCAPE _REG_EESCAPE -#define REG_ESUBREG _REG_ESUBREG -#define REG_EBRACK _REG_EBRACK -#define REG_EPAREN _REG_EPAREN -#define REG_EBRACE _REG_EBRACE -#define REG_BADBR _REG_BADBR -#define REG_ERANGE _REG_ERANGE -#define REG_ESPACE _REG_ESPACE -#define REG_BADRPT _REG_BADRPT -#define REG_EEND _REG_EEND -#define REG_ESIZE _REG_ESIZE -#define REG_ERPAREN _REG_ERPAREN - -/* struct re_pattern_buffer normally uses member names like `buffer' - that POSIX does not allow. In POSIX mode these members have names - with leading `re_' (e.g., `re_buffer'). */ -#ifdef __USE_GNU_REGEX -# define _REG_RE_NAME(id) id -# define _REG_RM_NAME(id) id -#else -# define _REG_RE_NAME(id) re_##id -# define _REG_RM_NAME(id) rm_##id -#endif - -/* The user can specify the type of the re_translate member by - defining the macro RE_TRANSLATE_TYPE, which defaults to unsigned - char *. This pollutes the POSIX name space, so in POSIX mode just - use unsigned char *. */ -#ifdef __USE_GNU_REGEX -# ifndef RE_TRANSLATE_TYPE -# define RE_TRANSLATE_TYPE unsigned char * -# endif -# define REG_TRANSLATE_TYPE RE_TRANSLATE_TYPE -#else -# define REG_TRANSLATE_TYPE unsigned char * -#endif - -/* This data structure represents a compiled pattern. Before calling - the pattern compiler, the fields `buffer', `allocated', `fastmap', - `translate', and `no_sub' can be set. After the pattern has been - compiled, the `re_nsub' field is available. All other fields are - private to the regex routines. */ - -struct re_pattern_buffer -{ - /* Space that holds the compiled pattern. It is declared as - `unsigned char *' because its elements are sometimes used as - array indexes. */ - unsigned char *_REG_RE_NAME (buffer); - - /* Number of bytes to which `buffer' points. */ - __re_long_size_t _REG_RE_NAME (allocated); - - /* Number of bytes actually used in `buffer'. */ - __re_long_size_t _REG_RE_NAME (used); - - /* Syntax setting with which the pattern was compiled. */ - reg_syntax_t _REG_RE_NAME (syntax); - - /* Pointer to a fastmap, if any, otherwise zero. re_search uses the - fastmap, if there is one, to skip over impossible starting points - for matches. */ - char *_REG_RE_NAME (fastmap); - - /* Either a translate table to apply to all characters before - comparing them, or zero for no translation. The translation is - applied to a pattern when it is compiled and to a string when it - is matched. */ - REG_TRANSLATE_TYPE _REG_RE_NAME (translate); - - /* Number of subexpressions found by the compiler. */ - size_t re_nsub; - - /* Zero if this pattern cannot match the empty string, one else. - Well, in truth it's used only in `re_search_2', to see whether or - not we should use the fastmap, so we don't set this absolutely - perfectly; see `re_compile_fastmap' (the `duplicate' case). */ - unsigned int _REG_RE_NAME (can_be_null) : 1; - - /* If REGS_UNALLOCATED, allocate space in the `regs' structure - for `max (RE_NREGS, re_nsub + 1)' groups. - If REGS_REALLOCATE, reallocate space if necessary. - If REGS_FIXED, use what's there. */ -#ifdef __USE_GNU_REGEX -# define REGS_UNALLOCATED 0 -# define REGS_REALLOCATE 1 -# define REGS_FIXED 2 -#endif - unsigned int _REG_RE_NAME (regs_allocated) : 2; - - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ - unsigned int _REG_RE_NAME (fastmap_accurate) : 1; - - /* If set, `re_match_2' does not return information about - subexpressions. */ - unsigned int _REG_RE_NAME (no_sub) : 1; - - /* If set, a beginning-of-line anchor doesn't match at the beginning - of the string. */ - unsigned int _REG_RE_NAME (not_bol) : 1; - - /* Similarly for an end-of-line anchor. */ - unsigned int _REG_RE_NAME (not_eol) : 1; - - /* If true, an anchor at a newline matches. */ - unsigned int _REG_RE_NAME (newline_anchor) : 1; - -/* [[[end pattern_buffer]]] */ -}; - -typedef struct re_pattern_buffer regex_t; - -/* This is the structure we store register match data in. See - regex.texinfo for a full description of what registers match. */ -struct re_registers -{ - __re_size_t _REG_RM_NAME (num_regs); - regoff_t *_REG_RM_NAME (start); - regoff_t *_REG_RM_NAME (end); -}; - - -/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, - `re_match_2' returns information about at least this many registers - the first time a `regs' structure is passed. */ -#if !defined RE_NREGS && defined __USE_GNU_REGEX -# define RE_NREGS 30 -#endif - - -/* POSIX specification for registers. Aside from the different names than - `re_registers', POSIX uses an array of structures, instead of a - structure of arrays. */ -typedef struct -{ - regoff_t rm_so; /* Byte offset from string's start to substring's start. */ - regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ -} regmatch_t; - -/* Declarations for routines. */ - -/* Sets the current default syntax to SYNTAX, and return the old syntax. - You can also simply assign to the `re_syntax_options' variable. */ -extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); - -/* Compile the regular expression PATTERN, with length LENGTH - and syntax given by the global `re_syntax_options', into the buffer - BUFFER. Return NULL if successful, and an error string if not. */ -extern const char *re_compile_pattern (const char *__pattern, size_t __length, - struct re_pattern_buffer *__buffer); - - -/* Compile a fastmap for the compiled pattern in BUFFER; used to - accelerate searches. Return 0 if successful and -2 if was an - internal error. */ -extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); - - -/* Search in the string STRING (with length LENGTH) for the pattern - compiled into BUFFER. Start searching at position START, for RANGE - characters. Return the starting position of the match, -1 for no - match, or -2 for an internal error. Also return register - information in REGS (if REGS and BUFFER->no_sub are nonzero). */ -extern regoff_t re_search (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs); - - -/* Like `re_search', but search in the concatenation of STRING1 and - STRING2. Also, stop searching at index START + STOP. */ -extern regoff_t re_search_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, regoff_t __range, - struct re_registers *__regs, - __re_idx_t __stop); - - -/* Like `re_search', but return how many characters in STRING the regexp - in BUFFER matched, starting at position START. */ -extern regoff_t re_match (struct re_pattern_buffer *__buffer, - const char *__string, __re_idx_t __length, - __re_idx_t __start, struct re_registers *__regs); - - -/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ -extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, - const char *__string1, __re_idx_t __length1, - const char *__string2, __re_idx_t __length2, - __re_idx_t __start, struct re_registers *__regs, - __re_idx_t __stop); - - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using BUFFER and REGS will use this memory - for recording register information. STARTS and ENDS must be - allocated with malloc, and must each be at least `NUM_REGS * sizeof - (regoff_t)' bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ -extern void re_set_registers (struct re_pattern_buffer *__buffer, - struct re_registers *__regs, - __re_size_t __num_regs, - regoff_t *__starts, regoff_t *__ends); - -#if defined _REGEX_RE_COMP || defined _LIBC -# ifndef _CRAY -/* 4.2 bsd compatibility. */ -extern char *re_comp (const char *); -extern int re_exec (const char *); -# endif -#endif - -/* GCC 2.95 and later have "__restrict"; C99 compilers have - "restrict", and "configure" may have defined "restrict". - Other compilers use __restrict, __restrict__, and _Restrict, and - 'configure' might #define 'restrict' to those words, so pick a - different name. */ -#ifndef _Restrict_ -# if 199901L <= __STDC_VERSION__ -# define _Restrict_ restrict -# elif 2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__) -# define _Restrict_ __restrict -# else -# define _Restrict_ -# endif -#endif -/* gcc 3.1 and up support the [restrict] syntax. Don't trust - sys/cdefs.h's definition of __restrict_arr, though, as it - mishandles gcc -ansi -pedantic. */ -#ifndef _Restrict_arr_ -# if ((199901L <= __STDC_VERSION__ \ - || ((3 < __GNUC__ || (3 == __GNUC__ && 1 <= __GNUC_MINOR__)) \ - && !__STRICT_ANSI__)) \ - && !defined __GNUG__) -# define _Restrict_arr_ _Restrict_ -# else -# define _Restrict_arr_ -# endif -#endif - -/* POSIX compatibility. */ -extern int regcomp (regex_t *_Restrict_ __preg, - const char *_Restrict_ __pattern, - int __cflags); - -extern int regexec (const regex_t *_Restrict_ __preg, - const char *_Restrict_ __string, size_t __nmatch, - regmatch_t __pmatch[_Restrict_arr_], - int __eflags); - -extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg, - char *_Restrict_ __errbuf, size_t __errbuf_size); - -extern void regfree (regex_t *__preg); - - -#ifdef __cplusplus -} -#endif /* C++ */ - -#endif /* regex.h */ diff --git a/usr/src/lib/libparted/common/lib/regex_internal.c b/usr/src/lib/libparted/common/lib/regex_internal.c deleted file mode 100644 index 21298889a3..0000000000 --- a/usr/src/lib/libparted/common/lib/regex_internal.c +++ /dev/null @@ -1,1741 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software - Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static void re_string_construct_common (const char *str, Idx len, - re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) internal_function; -static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - re_hashval_t hash) internal_function; -static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, - const re_node_set *nodes, - unsigned int context, - re_hashval_t hash) internal_function; - -/* Functions for string operation. */ - -/* This function allocate the buffers. It is necessary to call - re_string_reconstruct before using the object. */ - -static reg_errcode_t -internal_function -re_string_allocate (re_string_t *pstr, const char *str, Idx len, Idx init_len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - Idx init_buf_len; - - /* Ensure at least one character fits into the buffers. */ - if (init_len < dfa->mb_cur_max) - init_len = dfa->mb_cur_max; - init_buf_len = (len + 1 < init_len) ? len + 1: init_len; - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - ret = re_string_realloc_buffers (pstr, init_buf_len); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - pstr->word_char = dfa->word_char; - pstr->word_ops_used = dfa->word_ops_used; - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; - pstr->valid_raw_len = pstr->valid_len; - return REG_NOERROR; -} - -/* This function allocate the buffers, and initialize them. */ - -static reg_errcode_t -internal_function -re_string_construct (re_string_t *pstr, const char *str, Idx len, - RE_TRANSLATE_TYPE trans, bool icase, const re_dfa_t *dfa) -{ - reg_errcode_t ret; - memset (pstr, '\0', sizeof (re_string_t)); - re_string_construct_common (str, len, pstr, trans, icase, dfa); - - if (len > 0) - { - ret = re_string_realloc_buffers (pstr, len + 1); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; - - if (icase) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - { - while (1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - if (pstr->valid_raw_len >= len) - break; - if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) - break; - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (trans != NULL) - re_string_translate_buffer (pstr); - else - { - pstr->valid_len = pstr->bufs_len; - pstr->valid_raw_len = pstr->bufs_len; - } - } - } - - return REG_NOERROR; -} - -/* Helper functions for re_string_allocate, and re_string_construct. */ - -static reg_errcode_t -internal_function -re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len) -{ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - wint_t *new_wcs; - - /* Avoid overflow. */ - size_t max_object_size = MAX (sizeof (wint_t), sizeof (Idx)); - if (BE (SIZE_MAX / max_object_size < new_buf_len, 0)) - return REG_ESPACE; - - new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); - if (BE (new_wcs == NULL, 0)) - return REG_ESPACE; - pstr->wcs = new_wcs; - if (pstr->offsets != NULL) - { - Idx *new_offsets = re_realloc (pstr->offsets, Idx, new_buf_len); - if (BE (new_offsets == NULL, 0)) - return REG_ESPACE; - pstr->offsets = new_offsets; - } - } -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - { - unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, - new_buf_len); - if (BE (new_mbs == NULL, 0)) - return REG_ESPACE; - pstr->mbs = new_mbs; - } - pstr->bufs_len = new_buf_len; - return REG_NOERROR; -} - - -static void -internal_function -re_string_construct_common (const char *str, Idx len, re_string_t *pstr, - RE_TRANSLATE_TYPE trans, bool icase, - const re_dfa_t *dfa) -{ - pstr->raw_mbs = (const unsigned char *) str; - pstr->len = len; - pstr->raw_len = len; - pstr->trans = trans; - pstr->icase = icase; - pstr->mbs_allocated = (trans != NULL || icase); - pstr->mb_cur_max = dfa->mb_cur_max; - pstr->is_utf8 = dfa->is_utf8; - pstr->map_notascii = dfa->map_notascii; - pstr->stop = pstr->len; - pstr->raw_stop = pstr->stop; -} - -#ifdef RE_ENABLE_I18N - -/* Build wide character buffer PSTR->WCS. - If the byte sequence of the string are: - (0), (1), (0), (1), - Then wide character buffer will be: - , WEOF , , WEOF , - We use WEOF for padding, they indicate that the position isn't - a first byte of a multibyte character. - - Note that this function assumes PSTR->VALID_LEN elements are already - built and starts from PSTR->VALID_LEN. */ - -static void -internal_function -build_wcs_buffer (re_string_t *pstr) -{ -#ifdef _LIBC - unsigned char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - unsigned char buf[64]; -#endif - mbstate_t prev_st; - Idx byte_idx, end_idx, remain_len; - size_t mbclen; - - /* Build the buffers from pstr->valid_len to either pstr->len or - pstr->bufs_len. */ - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - for (byte_idx = pstr->valid_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - /* Apply the translation if we need. */ - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; - buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2, 0)) - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a singlebyte character. */ - mbclen = 1; - wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - if (BE (pstr->trans != NULL, 0)) - wc = pstr->trans[wc]; - pstr->cur_state = prev_st; - } - - /* Write wide character and padding. */ - pstr->wcs[byte_idx++] = wc; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; -} - -/* Build wide character buffer PSTR->WCS like build_wcs_buffer, - but for REG_ICASE. */ - -static reg_errcode_t -internal_function -build_wcs_upper_buffer (re_string_t *pstr) -{ - mbstate_t prev_st; - Idx src_idx, byte_idx, end_idx, remain_len; - size_t mbclen; -#ifdef _LIBC - char buf[MB_LEN_MAX]; - assert (MB_LEN_MAX >= pstr->mb_cur_max); -#else - char buf[64]; -#endif - - byte_idx = pstr->valid_len; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - /* The following optimization assumes that ASCII characters can be - mapped to wide characters with a simple cast. */ - if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) - { - while (byte_idx < end_idx) - { - wchar_t wc; - - if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) - && mbsinit (&pstr->cur_state)) - { - /* In case of a singlebyte character. */ - pstr->mbs[byte_idx] - = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); - /* The next step uses the assumption that wchar_t is encoded - ASCII-safe: all ASCII values can be converted like this. */ - pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; - ++byte_idx; - continue; - } - - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc, - ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx - + byte_idx), remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb (buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else - { - src_idx = byte_idx; - goto offsets_needed; - } - } - else - memcpy (pstr->mbs + byte_idx, - pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; - pstr->mbs[byte_idx] = ch; - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = byte_idx; - return REG_NOERROR; - } - else - for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) - { - wchar_t wc; - const char *p; - offsets_needed: - remain_len = end_idx - byte_idx; - prev_st = pstr->cur_state; - if (BE (pstr->trans != NULL, 0)) - { - int i, ch; - - for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) - { - ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; - buf[i] = pstr->trans[ch]; - } - p = (const char *) buf; - } - else - p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; - mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); - if (BE (mbclen < (size_t) -2, 1)) - { - wchar_t wcu = wc; - if (iswlower (wc)) - { - size_t mbcdlen; - - wcu = towupper (wc); - mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); - if (BE (mbclen == mbcdlen, 1)) - memcpy (pstr->mbs + byte_idx, buf, mbclen); - else if (mbcdlen != (size_t) -1) - { - size_t i; - - if (byte_idx + mbcdlen > pstr->bufs_len) - { - pstr->cur_state = prev_st; - break; - } - - if (pstr->offsets == NULL) - { - pstr->offsets = re_malloc (Idx, pstr->bufs_len); - - if (pstr->offsets == NULL) - return REG_ESPACE; - } - if (!pstr->offsets_needed) - { - for (i = 0; i < (size_t) byte_idx; ++i) - pstr->offsets[i] = i; - pstr->offsets_needed = 1; - } - - memcpy (pstr->mbs + byte_idx, buf, mbcdlen); - pstr->wcs[byte_idx] = wcu; - pstr->offsets[byte_idx] = src_idx; - for (i = 1; i < mbcdlen; ++i) - { - pstr->offsets[byte_idx + i] - = src_idx + (i < mbclen ? i : mbclen - 1); - pstr->wcs[byte_idx + i] = WEOF; - } - pstr->len += mbcdlen - mbclen; - if (pstr->raw_stop > src_idx) - pstr->stop += mbcdlen - mbclen; - end_idx = (pstr->bufs_len > pstr->len) - ? pstr->len : pstr->bufs_len; - byte_idx += mbcdlen; - src_idx += mbclen; - continue; - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - } - else - memcpy (pstr->mbs + byte_idx, p, mbclen); - - if (BE (pstr->offsets_needed != 0, 0)) - { - size_t i; - for (i = 0; i < mbclen; ++i) - pstr->offsets[byte_idx + i] = src_idx + i; - } - src_idx += mbclen; - - pstr->wcs[byte_idx++] = wcu; - /* Write paddings. */ - for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) - pstr->wcs[byte_idx++] = WEOF; - } - else if (mbclen == (size_t) -1 || mbclen == 0) - { - /* It is an invalid character or '\0'. Just use the byte. */ - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; - - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans [ch]; - pstr->mbs[byte_idx] = ch; - - if (BE (pstr->offsets_needed != 0, 0)) - pstr->offsets[byte_idx] = src_idx; - ++src_idx; - - /* And also cast it to wide char. */ - pstr->wcs[byte_idx++] = (wchar_t) ch; - if (BE (mbclen == (size_t) -1, 0)) - pstr->cur_state = prev_st; - } - else - { - /* The buffer doesn't have enough space, finish to build. */ - pstr->cur_state = prev_st; - break; - } - } - pstr->valid_len = byte_idx; - pstr->valid_raw_len = src_idx; - return REG_NOERROR; -} - -/* Skip characters until the index becomes greater than NEW_RAW_IDX. - Return the index. */ - -static Idx -internal_function -re_string_skip_chars (re_string_t *pstr, Idx new_raw_idx, wint_t *last_wc) -{ - mbstate_t prev_st; - Idx rawbuf_idx; - size_t mbclen; - wint_t wc = WEOF; - - /* Skip the characters which are not necessary to check. */ - for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; - rawbuf_idx < new_raw_idx;) - { - wchar_t wc2; - Idx remain_len; - remain_len = pstr->len - rawbuf_idx; - prev_st = pstr->cur_state; - mbclen = mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx, - remain_len, &pstr->cur_state); - if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) - { - /* We treat these cases as a single byte character. */ - if (mbclen == 0 || remain_len == 0) - wc = L'\0'; - else - wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx); - mbclen = 1; - pstr->cur_state = prev_st; - } - else - wc = wc2; - /* Then proceed the next character. */ - rawbuf_idx += mbclen; - } - *last_wc = wc; - return rawbuf_idx; -} -#endif /* RE_ENABLE_I18N */ - -/* Build the buffer PSTR->MBS, and apply the translation if we need. - This function is used in case of REG_ICASE. */ - -static void -internal_function -build_upper_buffer (re_string_t *pstr) -{ - Idx char_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; - if (BE (pstr->trans != NULL, 0)) - ch = pstr->trans[ch]; - if (islower (ch)) - pstr->mbs[char_idx] = toupper (ch); - else - pstr->mbs[char_idx] = ch; - } - pstr->valid_len = char_idx; - pstr->valid_raw_len = char_idx; -} - -/* Apply TRANS to the buffer in PSTR. */ - -static void -internal_function -re_string_translate_buffer (re_string_t *pstr) -{ - Idx buf_idx, end_idx; - end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; - - for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) - { - int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; - pstr->mbs[buf_idx] = pstr->trans[ch]; - } - - pstr->valid_len = buf_idx; - pstr->valid_raw_len = buf_idx; -} - -/* This function re-construct the buffers. - Concretely, convert to wide character in case of pstr->mb_cur_max > 1, - convert to upper case in case of REG_ICASE, apply translation. */ - -static reg_errcode_t -internal_function -re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) -{ - Idx offset; - - if (BE (pstr->raw_mbs_idx <= idx, 0)) - offset = idx - pstr->raw_mbs_idx; - else - { - /* Reset buffer. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); -#endif /* RE_ENABLE_I18N */ - pstr->len = pstr->raw_len; - pstr->stop = pstr->raw_stop; - pstr->valid_len = 0; - pstr->raw_mbs_idx = 0; - pstr->valid_raw_len = 0; - pstr->offsets_needed = 0; - pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF); - if (!pstr->mbs_allocated) - pstr->mbs = (unsigned char *) pstr->raw_mbs; - offset = idx; - } - - if (BE (offset != 0, 1)) - { - /* Should the already checked characters be kept? */ - if (BE (offset < pstr->valid_raw_len, 1)) - { - /* Yes, move them to the front of the buffer. */ -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - Idx low = 0, high = pstr->valid_len, mid; - do - { - mid = (high + low) / 2; - if (pstr->offsets[mid] > offset) - high = mid; - else if (pstr->offsets[mid] < offset) - low = mid + 1; - else - break; - } - while (low < high); - if (pstr->offsets[mid] < offset) - ++mid; - pstr->tip_context = re_string_context_at (pstr, mid - 1, - eflags); - /* This can be quite complicated, so handle specially - only the common and easy case where the character with - different length representation of lower and upper - case is present at or after offset. */ - if (pstr->valid_len > offset - && mid == offset && pstr->offsets[mid] == offset) - { - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); - memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; - for (low = 0; low < pstr->valid_len; low++) - pstr->offsets[low] = pstr->offsets[low + offset] - offset; - } - else - { - /* Otherwise, just find out how long the partial multibyte - character at offset is and fill it with WEOF/255. */ - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - while (mid > 0 && pstr->offsets[mid - 1] == offset) - --mid; - while (mid < pstr->valid_len) - if (pstr->wcs[mid] != WEOF) - break; - else - ++mid; - if (mid == pstr->valid_len) - pstr->valid_len = 0; - else - { - pstr->valid_len = pstr->offsets[mid] - offset; - if (pstr->valid_len) - { - for (low = 0; low < pstr->valid_len; ++low) - pstr->wcs[low] = WEOF; - memset (pstr->mbs, 255, pstr->valid_len); - } - } - pstr->valid_raw_len = pstr->valid_len; - } - } - else -#endif - { - pstr->tip_context = re_string_context_at (pstr, offset - 1, - eflags); -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - memmove (pstr->wcs, pstr->wcs + offset, - (pstr->valid_len - offset) * sizeof (wint_t)); -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - memmove (pstr->mbs, pstr->mbs + offset, - pstr->valid_len - offset); - pstr->valid_len -= offset; - pstr->valid_raw_len -= offset; -#if DEBUG - assert (pstr->valid_len > 0); -#endif - } - } - else - { - /* No, skip all characters until IDX. */ - Idx prev_valid_len = pstr->valid_len; - -#ifdef RE_ENABLE_I18N - if (BE (pstr->offsets_needed, 0)) - { - pstr->len = pstr->raw_len - idx + offset; - pstr->stop = pstr->raw_stop - idx + offset; - pstr->offsets_needed = 0; - } -#endif - pstr->valid_len = 0; -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - Idx wcs_idx; - wint_t wc = WEOF; - - if (pstr->is_utf8) - { - const unsigned char *raw, *p, *end; - - /* Special case UTF-8. Multi-byte chars start with any - byte other than 0x80 - 0xbf. */ - raw = pstr->raw_mbs + pstr->raw_mbs_idx; - end = raw + (offset - pstr->mb_cur_max); - if (end < pstr->raw_mbs) - end = pstr->raw_mbs; - p = raw + offset - 1; -#ifdef _LIBC - /* We know the wchar_t encoding is UCS4, so for the simple - case, ASCII characters, skip the conversion step. */ - if (isascii (*p) && BE (pstr->trans == NULL, 1)) - { - memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); - /* pstr->valid_len = 0; */ - wc = (wchar_t) *p; - } - else -#endif - for (; p >= end; --p) - if ((*p & 0xc0) != 0x80) - { - mbstate_t cur_state; - wchar_t wc2; - Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; - size_t mbclen; - - if (BE (pstr->trans != NULL, 0)) - { - int i = mlen < 6 ? mlen : 6; - while (--i >= 0) - buf[i] = pstr->trans[p[i]]; - } - /* XXX Don't use mbrtowc, we know which conversion - to use (UTF-8 -> UCS4). */ - memset (&cur_state, 0, sizeof (cur_state)); - mbclen = mbrtowc (&wc2, (const char *) p, mlen, - &cur_state); - if (raw + offset - p <= mbclen - && mbclen < (size_t) -2) - { - memset (&pstr->cur_state, '\0', - sizeof (mbstate_t)); - pstr->valid_len = mbclen - (raw + offset - p); - wc = wc2; - } - break; - } - } - - if (wc == WEOF) - pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; - if (wc == WEOF) - pstr->tip_context - = re_string_context_at (pstr, prev_valid_len - 1, eflags); - else - pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) - && IS_WIDE_WORD_CHAR (wc)) - ? CONTEXT_WORD - : ((IS_WIDE_NEWLINE (wc) - && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - if (BE (pstr->valid_len, 0)) - { - for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) - pstr->wcs[wcs_idx] = WEOF; - if (pstr->mbs_allocated) - memset (pstr->mbs, 255, pstr->valid_len); - } - pstr->valid_raw_len = pstr->valid_len; - } - else -#endif /* RE_ENABLE_I18N */ - { - int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; - pstr->valid_raw_len = 0; - if (pstr->trans) - c = pstr->trans[c]; - pstr->tip_context = (bitset_contain (pstr->word_char, c) - ? CONTEXT_WORD - : ((IS_NEWLINE (c) && pstr->newline_anchor) - ? CONTEXT_NEWLINE : 0)); - } - } - if (!BE (pstr->mbs_allocated, 0)) - pstr->mbs += offset; - } - pstr->raw_mbs_idx = idx; - pstr->len -= offset; - pstr->stop -= offset; - - /* Then build the buffers. */ -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - if (pstr->icase) - { - reg_errcode_t ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else - build_wcs_buffer (pstr); - } - else -#endif /* RE_ENABLE_I18N */ - if (BE (pstr->mbs_allocated, 0)) - { - if (pstr->icase) - build_upper_buffer (pstr); - else if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - else - pstr->valid_len = pstr->len; - - pstr->cur_idx = 0; - return REG_NOERROR; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_peek_byte_case (const re_string_t *pstr, Idx idx) -{ - int ch; - Idx off; - - /* Handle the common (easiest) cases first. */ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_peek_byte (pstr, idx); - -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1 - && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) - return re_string_peek_byte (pstr, idx); -#endif - - off = pstr->cur_idx + idx; -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - off = pstr->offsets[off]; -#endif - - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - -#ifdef RE_ENABLE_I18N - /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I - this function returns CAPITAL LETTER I instead of first byte of - DOTLESS SMALL LETTER I. The latter would confuse the parser, - since peek_byte_case doesn't advance cur_idx in any way. */ - if (pstr->offsets_needed && !isascii (ch)) - return re_string_peek_byte (pstr, idx); -#endif - - return ch; -} - -static unsigned char -internal_function __attribute ((pure)) -re_string_fetch_byte_case (re_string_t *pstr) -{ - if (BE (!pstr->mbs_allocated, 1)) - return re_string_fetch_byte (pstr); - -#ifdef RE_ENABLE_I18N - if (pstr->offsets_needed) - { - Idx off; - int ch; - - /* For tr_TR.UTF-8 [[:islower:]] there is - [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip - in that case the whole multi-byte character and return - the original letter. On the other side, with - [[: DOTLESS SMALL LETTER I return [[:I, as doing - anything else would complicate things too much. */ - - if (!re_string_first_byte (pstr, pstr->cur_idx)) - return re_string_fetch_byte (pstr); - - off = pstr->offsets[pstr->cur_idx]; - ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; - - if (! isascii (ch)) - return re_string_fetch_byte (pstr); - - re_string_skip_bytes (pstr, - re_string_char_size_at (pstr, pstr->cur_idx)); - return ch; - } -#endif - - return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; -} - -static void -internal_function -re_string_destruct (re_string_t *pstr) -{ -#ifdef RE_ENABLE_I18N - re_free (pstr->wcs); - re_free (pstr->offsets); -#endif /* RE_ENABLE_I18N */ - if (pstr->mbs_allocated) - re_free (pstr->mbs); -} - -/* Return the context at IDX in INPUT. */ - -static unsigned int -internal_function -re_string_context_at (const re_string_t *input, Idx idx, int eflags) -{ - int c; - if (BE (! REG_VALID_INDEX (idx), 0)) - /* In this case, we use the value stored in input->tip_context, - since we can't know the character in input->mbs[-1] here. */ - return input->tip_context; - if (BE (idx == input->len, 0)) - return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF - : CONTEXT_NEWLINE | CONTEXT_ENDBUF); -#ifdef RE_ENABLE_I18N - if (input->mb_cur_max > 1) - { - wint_t wc; - Idx wc_idx = idx; - while(input->wcs[wc_idx] == WEOF) - { -#ifdef DEBUG - /* It must not happen. */ - assert (REG_VALID_INDEX (wc_idx)); -#endif - --wc_idx; - if (! REG_VALID_INDEX (wc_idx)) - return input->tip_context; - } - wc = input->wcs[wc_idx]; - if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) - return CONTEXT_WORD; - return (IS_WIDE_NEWLINE (wc) && input->newline_anchor - ? CONTEXT_NEWLINE : 0); - } - else -#endif - { - c = re_string_byte_at (input, idx); - if (bitset_contain (input->word_char, c)) - return CONTEXT_WORD; - return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; - } -} - -/* Functions for set operation. */ - -static reg_errcode_t -internal_function -re_node_set_alloc (re_node_set *set, Idx size) -{ - set->alloc = size; - set->nelem = 0; - set->elems = re_malloc (Idx, size); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_1 (re_node_set *set, Idx elem) -{ - set->alloc = 1; - set->nelem = 1; - set->elems = re_malloc (Idx, 1); - if (BE (set->elems == NULL, 0)) - { - set->alloc = set->nelem = 0; - return REG_ESPACE; - } - set->elems[0] = elem; - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_2 (re_node_set *set, Idx elem1, Idx elem2) -{ - set->alloc = 2; - set->elems = re_malloc (Idx, 2); - if (BE (set->elems == NULL, 0)) - return REG_ESPACE; - if (elem1 == elem2) - { - set->nelem = 1; - set->elems[0] = elem1; - } - else - { - set->nelem = 2; - if (elem1 < elem2) - { - set->elems[0] = elem1; - set->elems[1] = elem2; - } - else - { - set->elems[0] = elem2; - set->elems[1] = elem1; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -re_node_set_init_copy (re_node_set *dest, const re_node_set *src) -{ - dest->nelem = src->nelem; - if (src->nelem > 0) - { - dest->alloc = dest->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - { - dest->alloc = dest->nelem = 0; - return REG_ESPACE; - } - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - } - else - re_node_set_init_empty (dest); - return REG_NOERROR; -} - -/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. - Note: We assume dest->elems is NULL, when dest->alloc is 0. */ - -static reg_errcode_t -internal_function -re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, is, id, delta, sbase; - if (src1->nelem == 0 || src2->nelem == 0) - return REG_NOERROR; - - /* We need dest->nelem + 2 * elems_in_intersection; this is a - conservative estimate. */ - if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) - { - Idx new_alloc = src1->nelem + src2->nelem + dest->alloc; - Idx *new_elems = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_elems == NULL, 0)) - return REG_ESPACE; - dest->elems = new_elems; - dest->alloc = new_alloc; - } - - /* Find the items in the intersection of SRC1 and SRC2, and copy - into the top of DEST those that are not already in DEST itself. */ - sbase = dest->nelem + src1->nelem + src2->nelem; - i1 = src1->nelem - 1; - i2 = src2->nelem - 1; - id = dest->nelem - 1; - for (;;) - { - if (src1->elems[i1] == src2->elems[i2]) - { - /* Try to find the item in DEST. Maybe we could binary search? */ - while (REG_VALID_INDEX (id) && dest->elems[id] > src1->elems[i1]) - --id; - - if (! REG_VALID_INDEX (id) || dest->elems[id] != src1->elems[i1]) - dest->elems[--sbase] = src1->elems[i1]; - - if (! REG_VALID_INDEX (--i1) || ! REG_VALID_INDEX (--i2)) - break; - } - - /* Lower the highest of the two items. */ - else if (src1->elems[i1] < src2->elems[i2]) - { - if (! REG_VALID_INDEX (--i2)) - break; - } - else - { - if (! REG_VALID_INDEX (--i1)) - break; - } - } - - id = dest->nelem - 1; - is = dest->nelem + src1->nelem + src2->nelem - 1; - delta = is - sbase + 1; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place; this is more or - less the same loop that is in re_node_set_merge. */ - dest->nelem += delta; - if (delta > 0 && REG_VALID_INDEX (id)) - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - break; - } - } - - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, delta * sizeof (Idx)); - - return REG_NOERROR; -} - -/* Calculate the union set of the sets SRC1 and SRC2. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_init_union (re_node_set *dest, const re_node_set *src1, - const re_node_set *src2) -{ - Idx i1, i2, id; - if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) - { - dest->alloc = src1->nelem + src2->nelem; - dest->elems = re_malloc (Idx, dest->alloc); - if (BE (dest->elems == NULL, 0)) - return REG_ESPACE; - } - else - { - if (src1 != NULL && src1->nelem > 0) - return re_node_set_init_copy (dest, src1); - else if (src2 != NULL && src2->nelem > 0) - return re_node_set_init_copy (dest, src2); - else - re_node_set_init_empty (dest); - return REG_NOERROR; - } - for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) - { - if (src1->elems[i1] > src2->elems[i2]) - { - dest->elems[id++] = src2->elems[i2++]; - continue; - } - if (src1->elems[i1] == src2->elems[i2]) - ++i2; - dest->elems[id++] = src1->elems[i1++]; - } - if (i1 < src1->nelem) - { - memcpy (dest->elems + id, src1->elems + i1, - (src1->nelem - i1) * sizeof (Idx)); - id += src1->nelem - i1; - } - else if (i2 < src2->nelem) - { - memcpy (dest->elems + id, src2->elems + i2, - (src2->nelem - i2) * sizeof (Idx)); - id += src2->nelem - i2; - } - dest->nelem = id; - return REG_NOERROR; -} - -/* Calculate the union set of the sets DEST and SRC. And store it to - DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ - -static reg_errcode_t -internal_function -re_node_set_merge (re_node_set *dest, const re_node_set *src) -{ - Idx is, id, sbase, delta; - if (src == NULL || src->nelem == 0) - return REG_NOERROR; - if (dest->alloc < 2 * src->nelem + dest->nelem) - { - Idx new_alloc = 2 * (src->nelem + dest->alloc); - Idx *new_buffer = re_realloc (dest->elems, Idx, new_alloc); - if (BE (new_buffer == NULL, 0)) - return REG_ESPACE; - dest->elems = new_buffer; - dest->alloc = new_alloc; - } - - if (BE (dest->nelem == 0, 0)) - { - dest->nelem = src->nelem; - memcpy (dest->elems, src->elems, src->nelem * sizeof (Idx)); - return REG_NOERROR; - } - - /* Copy into the top of DEST the items of SRC that are not - found in DEST. Maybe we could binary search in DEST? */ - for (sbase = dest->nelem + 2 * src->nelem, - is = src->nelem - 1, id = dest->nelem - 1; - REG_VALID_INDEX (is) && REG_VALID_INDEX (id); ) - { - if (dest->elems[id] == src->elems[is]) - is--, id--; - else if (dest->elems[id] < src->elems[is]) - dest->elems[--sbase] = src->elems[is--]; - else /* if (dest->elems[id] > src->elems[is]) */ - --id; - } - - if (REG_VALID_INDEX (is)) - { - /* If DEST is exhausted, the remaining items of SRC must be unique. */ - sbase -= is + 1; - memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (Idx)); - } - - id = dest->nelem - 1; - is = dest->nelem + 2 * src->nelem - 1; - delta = is - sbase + 1; - if (delta == 0) - return REG_NOERROR; - - /* Now copy. When DELTA becomes zero, the remaining - DEST elements are already in place. */ - dest->nelem += delta; - for (;;) - { - if (dest->elems[is] > dest->elems[id]) - { - /* Copy from the top. */ - dest->elems[id + delta--] = dest->elems[is--]; - if (delta == 0) - break; - } - else - { - /* Slide from the bottom. */ - dest->elems[id + delta] = dest->elems[id]; - if (! REG_VALID_INDEX (--id)) - { - /* Copy remaining SRC elements. */ - memcpy (dest->elems, dest->elems + sbase, - delta * sizeof (Idx)); - break; - } - } - } - - return REG_NOERROR; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have ELEM. - Return true if successful. */ - -static bool -internal_function -re_node_set_insert (re_node_set *set, Idx elem) -{ - Idx idx; - /* In case the set is empty. */ - if (set->alloc == 0) - return BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1); - - if (BE (set->nelem, 0) == 0) - { - /* We already guaranteed above that set->alloc != 0. */ - set->elems[0] = elem; - ++set->nelem; - return true; - } - - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = set->alloc * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Move the elements which follows the new element. Test the - first element separately to skip a check in the inner loop. */ - if (elem < set->elems[0]) - { - idx = 0; - for (idx = set->nelem; idx > 0; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - else - { - for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) - set->elems[idx] = set->elems[idx - 1]; - } - - /* Insert the new element. */ - set->elems[idx] = elem; - ++set->nelem; - return true; -} - -/* Insert the new element ELEM to the re_node_set* SET. - SET should not already have any element greater than or equal to ELEM. - Return true if successful. */ - -static bool -internal_function -re_node_set_insert_last (re_node_set *set, Idx elem) -{ - /* Realloc if we need. */ - if (set->alloc == set->nelem) - { - Idx *new_elems; - set->alloc = (set->alloc + 1) * 2; - new_elems = re_realloc (set->elems, Idx, set->alloc); - if (BE (new_elems == NULL, 0)) - return false; - set->elems = new_elems; - } - - /* Insert the new element. */ - set->elems[set->nelem++] = elem; - return true; -} - -/* Compare two node sets SET1 and SET2. - Return true if SET1 and SET2 are equivalent. */ - -static bool -internal_function __attribute ((pure)) -re_node_set_compare (const re_node_set *set1, const re_node_set *set2) -{ - Idx i; - if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) - return false; - for (i = set1->nelem ; REG_VALID_INDEX (--i) ; ) - if (set1->elems[i] != set2->elems[i]) - return false; - return true; -} - -/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ - -static Idx -internal_function __attribute ((pure)) -re_node_set_contains (const re_node_set *set, Idx elem) -{ - __re_size_t idx, right, mid; - if (! REG_VALID_NONZERO_INDEX (set->nelem)) - return 0; - - /* Binary search the element. */ - idx = 0; - right = set->nelem - 1; - while (idx < right) - { - mid = (idx + right) / 2; - if (set->elems[mid] < elem) - idx = mid + 1; - else - right = mid; - } - return set->elems[idx] == elem ? idx + 1 : 0; -} - -static void -internal_function -re_node_set_remove_at (re_node_set *set, Idx idx) -{ - if (idx < 0 || idx >= set->nelem) - return; - --set->nelem; - for (; idx < set->nelem; idx++) - set->elems[idx] = set->elems[idx + 1]; -} - - -/* Add the token TOKEN to dfa->nodes, and return the index of the token. - Or return REG_MISSING if an error occurred. */ - -static Idx -internal_function -re_dfa_add_node (re_dfa_t *dfa, re_token_t token) -{ - if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) - { - size_t new_nodes_alloc = dfa->nodes_alloc * 2; - Idx *new_nexts, *new_indices; - re_node_set *new_edests, *new_eclosures; - re_token_t *new_nodes; - size_t max_object_size = - MAX (sizeof (re_token_t), - MAX (sizeof (re_node_set), - sizeof (Idx))); - - /* Avoid overflows. */ - if (BE (SIZE_MAX / 2 / max_object_size < dfa->nodes_alloc, 0)) - return REG_MISSING; - - new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); - if (BE (new_nodes == NULL, 0)) - return REG_MISSING; - dfa->nodes = new_nodes; - new_nexts = re_realloc (dfa->nexts, Idx, new_nodes_alloc); - new_indices = re_realloc (dfa->org_indices, Idx, new_nodes_alloc); - new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); - new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); - if (BE (new_nexts == NULL || new_indices == NULL - || new_edests == NULL || new_eclosures == NULL, 0)) - return REG_MISSING; - dfa->nexts = new_nexts; - dfa->org_indices = new_indices; - dfa->edests = new_edests; - dfa->eclosures = new_eclosures; - dfa->nodes_alloc = new_nodes_alloc; - } - dfa->nodes[dfa->nodes_len] = token; - dfa->nodes[dfa->nodes_len].constraint = 0; -#ifdef RE_ENABLE_I18N - { - int type = token.type; - dfa->nodes[dfa->nodes_len].accept_mb = - (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; - } -#endif - dfa->nexts[dfa->nodes_len] = REG_MISSING; - re_node_set_init_empty (dfa->edests + dfa->nodes_len); - re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); - return dfa->nodes_len++; -} - -static inline re_hashval_t -internal_function -calc_state_hash (const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash = nodes->nelem + context; - Idx i; - for (i = 0 ; i < nodes->nelem ; i++) - hash += nodes->elems[i]; - return hash; -} - -/* Search for the state whose node_set is equivalent to NODES. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (BE (nodes->nelem == 0, 0)) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, 0); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (hash != state->hash) - continue; - if (re_node_set_compare (&state->nodes, nodes)) - return state; - } - - /* There are no appropriate state in the dfa, create the new one. */ - new_state = create_ci_newstate (dfa, nodes, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Search for the state whose node_set is equivalent to NODES and - whose context is equivalent to CONTEXT. - Return the pointer to the state, if we found it in the DFA. - Otherwise create the new one and return it. In case of an error - return NULL and set the error code in ERR. - Note: - We assume NULL as the invalid state, then it is possible that - return value is NULL and ERR is REG_NOERROR. - - We never return non-NULL value in case of any errors, it is for - optimization. */ - -static re_dfastate_t * -internal_function -re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, - const re_node_set *nodes, unsigned int context) -{ - re_hashval_t hash; - re_dfastate_t *new_state; - struct re_state_table_entry *spot; - Idx i; -#ifdef lint - /* Suppress bogus uninitialized-variable warnings. */ - *err = REG_NOERROR; -#endif - if (nodes->nelem == 0) - { - *err = REG_NOERROR; - return NULL; - } - hash = calc_state_hash (nodes, context); - spot = dfa->state_table + (hash & dfa->state_hash_mask); - - for (i = 0 ; i < spot->num ; i++) - { - re_dfastate_t *state = spot->array[i]; - if (state->hash == hash - && state->context == context - && re_node_set_compare (state->entrance_nodes, nodes)) - return state; - } - /* There are no appropriate state in `dfa', create the new one. */ - new_state = create_cd_newstate (dfa, nodes, context, hash); - if (BE (new_state == NULL, 0)) - *err = REG_ESPACE; - - return new_state; -} - -/* Finish initialization of the new state NEWSTATE, and using its hash value - HASH put in the appropriate bucket of DFA's state table. Return value - indicates the error code if failed. */ - -static reg_errcode_t -register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, - re_hashval_t hash) -{ - struct re_state_table_entry *spot; - reg_errcode_t err; - Idx i; - - newstate->hash = hash; - err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < newstate->nodes.nelem; i++) - { - Idx elem = newstate->nodes.elems[i]; - if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) - if (BE (! re_node_set_insert_last (&newstate->non_eps_nodes, elem), 0)) - return REG_ESPACE; - } - - spot = dfa->state_table + (hash & dfa->state_hash_mask); - if (BE (spot->alloc <= spot->num, 0)) - { - Idx new_alloc = 2 * spot->num + 2; - re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, - new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - spot->array = new_array; - spot->alloc = new_alloc; - } - spot->array[spot->num++] = newstate; - return REG_NOERROR; -} - -static void -free_state (re_dfastate_t *state) -{ - re_node_set_free (&state->non_eps_nodes); - re_node_set_free (&state->inveclosure); - if (state->entrance_nodes != &state->nodes) - { - re_node_set_free (state->entrance_nodes); - re_free (state->entrance_nodes); - } - re_node_set_free (&state->nodes); - re_free (state->word_trtable); - re_free (state->trtable); - re_free (state); -} - -/* Create the new state which is independ of contexts. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - re_hashval_t hash) -{ - Idx i; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->entrance_nodes = &newstate->nodes; - for (i = 0 ; i < nodes->nelem ; i++) - { - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (type == CHARACTER && !node->constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR || node->constraint) - newstate->has_constraint = 1; - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} - -/* Create the new state which is depend on the context CONTEXT. - Return the new state if succeeded, otherwise return NULL. */ - -static re_dfastate_t * -internal_function -create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, - unsigned int context, re_hashval_t hash) -{ - Idx i, nctx_nodes = 0; - reg_errcode_t err; - re_dfastate_t *newstate; - - newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1); - if (BE (newstate == NULL, 0)) - return NULL; - err = re_node_set_init_copy (&newstate->nodes, nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_free (newstate); - return NULL; - } - - newstate->context = context; - newstate->entrance_nodes = &newstate->nodes; - - for (i = 0 ; i < nodes->nelem ; i++) - { - unsigned int constraint = 0; - re_token_t *node = dfa->nodes + nodes->elems[i]; - re_token_type_t type = node->type; - if (node->constraint) - constraint = node->constraint; - - if (type == CHARACTER && !constraint) - continue; -#ifdef RE_ENABLE_I18N - newstate->accept_mb |= node->accept_mb; -#endif /* RE_ENABLE_I18N */ - - /* If the state has the halt node, the state is a halt state. */ - if (type == END_OF_RE) - newstate->halt = 1; - else if (type == OP_BACK_REF) - newstate->has_backref = 1; - else if (type == ANCHOR) - constraint = node->opr.ctx_type; - - if (constraint) - { - if (newstate->entrance_nodes == &newstate->nodes) - { - newstate->entrance_nodes = re_malloc (re_node_set, 1); - if (BE (newstate->entrance_nodes == NULL, 0)) - { - free_state (newstate); - return NULL; - } - re_node_set_init_copy (newstate->entrance_nodes, nodes); - nctx_nodes = 0; - newstate->has_constraint = 1; - } - - if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) - { - re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); - ++nctx_nodes; - } - } - } - err = register_state (dfa, newstate, hash); - if (BE (err != REG_NOERROR, 0)) - { - free_state (newstate); - newstate = NULL; - } - return newstate; -} diff --git a/usr/src/lib/libparted/common/lib/regex_internal.h b/usr/src/lib/libparted/common/lib/regex_internal.h deleted file mode 100644 index 14d043f01b..0000000000 --- a/usr/src/lib/libparted/common/lib/regex_internal.h +++ /dev/null @@ -1,853 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _REGEX_INTERNAL_H -#define _REGEX_INTERNAL_H 1 - -#include -#include -#include -#include -#include -#include - -#ifdef _LIBC -# include -#else -# include "localcharset.h" -#endif -#if defined HAVE_LOCALE_H || defined _LIBC -# include -#endif - -#include -#include -#include -#if defined _LIBC -# include -#else -# define __libc_lock_init(NAME) do { } while (0) -# define __libc_lock_lock(NAME) do { } while (0) -# define __libc_lock_unlock(NAME) do { } while (0) -#endif - -/* In case that the system doesn't have isblank(). */ -#if !defined _LIBC && ! (defined isblank || (HAVE_ISBLANK && HAVE_DECL_ISBLANK)) -# define isblank(ch) ((ch) == ' ' || (ch) == '\t') -#endif - -#ifdef _LIBC -# ifndef _RE_DEFINE_LOCALE_FUNCTIONS -# define _RE_DEFINE_LOCALE_FUNCTIONS 1 -# include -# include -# include -# endif -#endif - -/* This is for other GNU distributions with internationalized messages. */ -#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC -# include -# ifdef _LIBC -# undef gettext -# define gettext(msgid) \ - INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES) -# endif -#else -# define gettext(msgid) (msgid) -#endif - -#ifndef gettext_noop -/* This define is so xgettext can find the internationalizable - strings. */ -# define gettext_noop(String) String -#endif - -/* For loser systems without the definition. */ -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_ISWCTYPE && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC -# define RE_ENABLE_I18N -#endif - -#if __GNUC__ >= 3 -# define BE(expr, val) __builtin_expect (expr, val) -#else -# define BE(expr, val) (expr) -# ifdef _LIBC -# define inline -# endif -#endif - -/* Number of ASCII characters. */ -#define ASCII_CHARS 0x80 - -/* Number of single byte characters. */ -#define SBC_MAX (UCHAR_MAX + 1) - -#define COLL_ELEM_LEN_MAX 8 - -/* The character which represents newline. */ -#define NEWLINE_CHAR '\n' -#define WIDE_NEWLINE_CHAR L'\n' - -/* Rename to standard API for using out of glibc. */ -#ifndef _LIBC -# define __wctype wctype -# define __iswctype iswctype -# define __btowc btowc -# define __wcrtomb wcrtomb -# define __regfree regfree -# define attribute_hidden -#endif /* not _LIBC */ - -#if __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -# define __attribute(arg) __attribute__ (arg) -#else -# define __attribute(arg) -#endif - -typedef __re_idx_t Idx; - -/* Special return value for failure to match. */ -#define REG_MISSING ((Idx) -1) - -/* Special return value for internal error. */ -#define REG_ERROR ((Idx) -2) - -/* Test whether N is a valid index, and is not one of the above. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_INDEX(n) ((Idx) (n) < REG_ERROR) -#else -# define REG_VALID_INDEX(n) (0 <= (n)) -#endif - -/* Test whether N is a valid nonzero index. */ -#ifdef _REGEX_LARGE_OFFSETS -# define REG_VALID_NONZERO_INDEX(n) ((Idx) ((n) - 1) < (Idx) (REG_ERROR - 1)) -#else -# define REG_VALID_NONZERO_INDEX(n) (0 < (n)) -#endif - -/* A hash value, suitable for computing hash tables. */ -typedef __re_size_t re_hashval_t; - -/* An integer used to represent a set of bits. It must be unsigned, - and must be at least as wide as unsigned int. */ -typedef unsigned long int bitset_word_t; -/* All bits set in a bitset_word_t. */ -#define BITSET_WORD_MAX ULONG_MAX - -/* Number of bits in a bitset_word_t. For portability to hosts with - padding bits, do not use '(sizeof (bitset_word_t) * CHAR_BIT)'; - instead, deduce it directly from BITSET_WORD_MAX. Avoid - greater-than-32-bit integers and unconditional shifts by more than - 31 bits, as they're not portable. */ -#if BITSET_WORD_MAX == 0xffffffff -# define BITSET_WORD_BITS 32 -#elif BITSET_WORD_MAX >> 31 >> 5 == 1 -# define BITSET_WORD_BITS 36 -#elif BITSET_WORD_MAX >> 31 >> 16 == 1 -# define BITSET_WORD_BITS 48 -#elif BITSET_WORD_MAX >> 31 >> 28 == 1 -# define BITSET_WORD_BITS 60 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 1 == 1 -# define BITSET_WORD_BITS 64 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 9 == 1 -# define BITSET_WORD_BITS 72 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 3 == 1 -# define BITSET_WORD_BITS 128 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 == 1 -# define BITSET_WORD_BITS 256 -#elif BITSET_WORD_MAX >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 31 >> 7 > 1 -# define BITSET_WORD_BITS 257 /* any value > SBC_MAX will do here */ -# if BITSET_WORD_BITS <= SBC_MAX -# error "Invalid SBC_MAX" -# endif -#else -# error "Add case for new bitset_word_t size" -#endif - -/* Number of bitset_word_t values in a bitset_t. */ -#define BITSET_WORDS ((SBC_MAX + BITSET_WORD_BITS - 1) / BITSET_WORD_BITS) - -typedef bitset_word_t bitset_t[BITSET_WORDS]; -typedef bitset_word_t *re_bitset_ptr_t; -typedef const bitset_word_t *re_const_bitset_ptr_t; - -#define PREV_WORD_CONSTRAINT 0x0001 -#define PREV_NOTWORD_CONSTRAINT 0x0002 -#define NEXT_WORD_CONSTRAINT 0x0004 -#define NEXT_NOTWORD_CONSTRAINT 0x0008 -#define PREV_NEWLINE_CONSTRAINT 0x0010 -#define NEXT_NEWLINE_CONSTRAINT 0x0020 -#define PREV_BEGBUF_CONSTRAINT 0x0040 -#define NEXT_ENDBUF_CONSTRAINT 0x0080 -#define WORD_DELIM_CONSTRAINT 0x0100 -#define NOT_WORD_DELIM_CONSTRAINT 0x0200 - -typedef enum -{ - INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, - WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, - LINE_FIRST = PREV_NEWLINE_CONSTRAINT, - LINE_LAST = NEXT_NEWLINE_CONSTRAINT, - BUF_FIRST = PREV_BEGBUF_CONSTRAINT, - BUF_LAST = NEXT_ENDBUF_CONSTRAINT, - WORD_DELIM = WORD_DELIM_CONSTRAINT, - NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT -} re_context_type; - -typedef struct -{ - Idx alloc; - Idx nelem; - Idx *elems; -} re_node_set; - -typedef enum -{ - NON_TYPE = 0, - - /* Node type, These are used by token, node, tree. */ - CHARACTER = 1, - END_OF_RE = 2, - SIMPLE_BRACKET = 3, - OP_BACK_REF = 4, - OP_PERIOD = 5, -#ifdef RE_ENABLE_I18N - COMPLEX_BRACKET = 6, - OP_UTF8_PERIOD = 7, -#endif /* RE_ENABLE_I18N */ - - /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used - when the debugger shows values of this enum type. */ -#define EPSILON_BIT 8 - OP_OPEN_SUBEXP = EPSILON_BIT | 0, - OP_CLOSE_SUBEXP = EPSILON_BIT | 1, - OP_ALT = EPSILON_BIT | 2, - OP_DUP_ASTERISK = EPSILON_BIT | 3, - ANCHOR = EPSILON_BIT | 4, - - /* Tree type, these are used only by tree. */ - CONCAT = 16, - SUBEXP = 17, - - /* Token type, these are used only by token. */ - OP_DUP_PLUS = 18, - OP_DUP_QUESTION, - OP_OPEN_BRACKET, - OP_CLOSE_BRACKET, - OP_CHARSET_RANGE, - OP_OPEN_DUP_NUM, - OP_CLOSE_DUP_NUM, - OP_NON_MATCH_LIST, - OP_OPEN_COLL_ELEM, - OP_CLOSE_COLL_ELEM, - OP_OPEN_EQUIV_CLASS, - OP_CLOSE_EQUIV_CLASS, - OP_OPEN_CHAR_CLASS, - OP_CLOSE_CHAR_CLASS, - OP_WORD, - OP_NOTWORD, - OP_SPACE, - OP_NOTSPACE, - BACK_SLASH - -} re_token_type_t; - -#ifdef RE_ENABLE_I18N -typedef struct -{ - /* Multibyte characters. */ - wchar_t *mbchars; - - /* Collating symbols. */ -# ifdef _LIBC - int32_t *coll_syms; -# endif - - /* Equivalence classes. */ -# ifdef _LIBC - int32_t *equiv_classes; -# endif - - /* Range expressions. */ -# ifdef _LIBC - uint32_t *range_starts; - uint32_t *range_ends; -# else /* not _LIBC */ - wchar_t *range_starts; - wchar_t *range_ends; -# endif /* not _LIBC */ - - /* Character classes. */ - wctype_t *char_classes; - - /* If this character set is the non-matching list. */ - unsigned int non_match : 1; - - /* # of multibyte characters. */ - Idx nmbchars; - - /* # of collating symbols. */ - Idx ncoll_syms; - - /* # of equivalence classes. */ - Idx nequiv_classes; - - /* # of range expressions. */ - Idx nranges; - - /* # of character classes. */ - Idx nchar_classes; -} re_charset_t; -#endif /* RE_ENABLE_I18N */ - -typedef struct -{ - union - { - unsigned char c; /* for CHARACTER */ - re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ -#ifdef RE_ENABLE_I18N - re_charset_t *mbcset; /* for COMPLEX_BRACKET */ -#endif /* RE_ENABLE_I18N */ - Idx idx; /* for BACK_REF */ - re_context_type ctx_type; /* for ANCHOR */ - } opr; -#if __GNUC__ >= 2 && !__STRICT_ANSI__ - re_token_type_t type : 8; -#else - re_token_type_t type; -#endif - unsigned int constraint : 10; /* context constraint */ - unsigned int duplicated : 1; - unsigned int opt_subexp : 1; -#ifdef RE_ENABLE_I18N - unsigned int accept_mb : 1; - /* These 2 bits can be moved into the union if needed (e.g. if running out - of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ - unsigned int mb_partial : 1; -#endif - unsigned int word_char : 1; -} re_token_t; - -#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) - -struct re_string_t -{ - /* Indicate the raw buffer which is the original string passed as an - argument of regexec(), re_search(), etc.. */ - const unsigned char *raw_mbs; - /* Store the multibyte string. In case of "case insensitive mode" like - REG_ICASE, upper cases of the string are stored, otherwise MBS points - the same address that RAW_MBS points. */ - unsigned char *mbs; -#ifdef RE_ENABLE_I18N - /* Store the wide character string which is corresponding to MBS. */ - wint_t *wcs; - Idx *offsets; - mbstate_t cur_state; -#endif - /* Index in RAW_MBS. Each character mbs[i] corresponds to - raw_mbs[raw_mbs_idx + i]. */ - Idx raw_mbs_idx; - /* The length of the valid characters in the buffers. */ - Idx valid_len; - /* The corresponding number of bytes in raw_mbs array. */ - Idx valid_raw_len; - /* The length of the buffers MBS and WCS. */ - Idx bufs_len; - /* The index in MBS, which is updated by re_string_fetch_byte. */ - Idx cur_idx; - /* length of RAW_MBS array. */ - Idx raw_len; - /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ - Idx len; - /* End of the buffer may be shorter than its length in the cases such - as re_match_2, re_search_2. Then, we use STOP for end of the buffer - instead of LEN. */ - Idx raw_stop; - /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ - Idx stop; - - /* The context of mbs[0]. We store the context independently, since - the context of mbs[0] may be different from raw_mbs[0], which is - the beginning of the input string. */ - unsigned int tip_context; - /* The translation passed as a part of an argument of re_compile_pattern. */ - RE_TRANSLATE_TYPE trans; - /* Copy of re_dfa_t's word_char. */ - re_const_bitset_ptr_t word_char; - /* true if REG_ICASE. */ - unsigned char icase; - unsigned char is_utf8; - unsigned char map_notascii; - unsigned char mbs_allocated; - unsigned char offsets_needed; - unsigned char newline_anchor; - unsigned char word_ops_used; - int mb_cur_max; -}; -typedef struct re_string_t re_string_t; - - -struct re_dfa_t; -typedef struct re_dfa_t re_dfa_t; - -#ifndef _LIBC -# ifdef __i386__ -# define internal_function __attribute ((regparm (3), stdcall)) -# else -# define internal_function -# endif -#endif - -static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, - Idx new_buf_len) - internal_function; -#ifdef RE_ENABLE_I18N -static void build_wcs_buffer (re_string_t *pstr) internal_function; -static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) - internal_function; -#endif /* RE_ENABLE_I18N */ -static void build_upper_buffer (re_string_t *pstr) internal_function; -static void re_string_translate_buffer (re_string_t *pstr) internal_function; -static unsigned int re_string_context_at (const re_string_t *input, Idx idx, - int eflags) - internal_function __attribute ((pure)); -#define re_string_peek_byte(pstr, offset) \ - ((pstr)->mbs[(pstr)->cur_idx + offset]) -#define re_string_fetch_byte(pstr) \ - ((pstr)->mbs[(pstr)->cur_idx++]) -#define re_string_first_byte(pstr, idx) \ - ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) -#define re_string_is_single_byte_char(pstr, idx) \ - ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ - || (pstr)->wcs[(idx) + 1] != WEOF)) -#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) -#define re_string_cur_idx(pstr) ((pstr)->cur_idx) -#define re_string_get_buffer(pstr) ((pstr)->mbs) -#define re_string_length(pstr) ((pstr)->len) -#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) -#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) -#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) - -#include - -#ifndef _LIBC -# if HAVE_ALLOCA -/* The OS usually guarantees only one guard page at the bottom of the stack, - and a page size can be as small as 4096 bytes. So we cannot safely - allocate anything larger than 4096 bytes. Also care for the possibility - of a few compiler-allocated temporary stack slots. */ -# define __libc_use_alloca(n) ((n) < 4032) -# else -/* alloca is implemented with malloc, so just use malloc. */ -# define __libc_use_alloca(n) 0 -# endif -#endif - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) -#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) -#define re_free(p) free (p) - -struct bin_tree_t -{ - struct bin_tree_t *parent; - struct bin_tree_t *left; - struct bin_tree_t *right; - struct bin_tree_t *first; - struct bin_tree_t *next; - - re_token_t token; - - /* `node_idx' is the index in dfa->nodes, if `type' == 0. - Otherwise `type' indicate the type of this node. */ - Idx node_idx; -}; -typedef struct bin_tree_t bin_tree_t; - -#define BIN_TREE_STORAGE_SIZE \ - ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) - -struct bin_tree_storage_t -{ - struct bin_tree_storage_t *next; - bin_tree_t data[BIN_TREE_STORAGE_SIZE]; -}; -typedef struct bin_tree_storage_t bin_tree_storage_t; - -#define CONTEXT_WORD 1 -#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) -#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) -#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) - -#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) -#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) -#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) -#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) -#define IS_ORDINARY_CONTEXT(c) ((c) == 0) - -#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') -#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) -#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') -#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) - -#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ - ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ - || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) - -#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ - ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ - || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ - || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) - -struct re_dfastate_t -{ - re_hashval_t hash; - re_node_set nodes; - re_node_set non_eps_nodes; - re_node_set inveclosure; - re_node_set *entrance_nodes; - struct re_dfastate_t **trtable, **word_trtable; - unsigned int context : 4; - unsigned int halt : 1; - /* If this state can accept `multi byte'. - Note that we refer to multibyte characters, and multi character - collating elements as `multi byte'. */ - unsigned int accept_mb : 1; - /* If this state has backreference node(s). */ - unsigned int has_backref : 1; - unsigned int has_constraint : 1; -}; -typedef struct re_dfastate_t re_dfastate_t; - -struct re_state_table_entry -{ - Idx num; - Idx alloc; - re_dfastate_t **array; -}; - -/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ - -typedef struct -{ - Idx next_idx; - Idx alloc; - re_dfastate_t **array; -} state_array_t; - -/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ - -typedef struct -{ - Idx node; - Idx str_idx; /* The position NODE match at. */ - state_array_t path; -} re_sub_match_last_t; - -/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. - And information about the node, whose type is OP_CLOSE_SUBEXP, - corresponding to NODE is stored in LASTS. */ - -typedef struct -{ - Idx str_idx; - Idx node; - state_array_t *path; - Idx alasts; /* Allocation size of LASTS. */ - Idx nlasts; /* The number of LASTS. */ - re_sub_match_last_t **lasts; -} re_sub_match_top_t; - -struct re_backref_cache_entry -{ - Idx node; - Idx str_idx; - Idx subexp_from; - Idx subexp_to; - char more; - char unused; - unsigned short int eps_reachable_subexps_map; -}; - -typedef struct -{ - /* The string object corresponding to the input string. */ - re_string_t input; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - const re_dfa_t *const dfa; -#else - const re_dfa_t *dfa; -#endif - /* EFLAGS of the argument of regexec. */ - int eflags; - /* Where the matching ends. */ - Idx match_last; - Idx last_node; - /* The state log used by the matcher. */ - re_dfastate_t **state_log; - Idx state_log_top; - /* Back reference cache. */ - Idx nbkref_ents; - Idx abkref_ents; - struct re_backref_cache_entry *bkref_ents; - int max_mb_elem_len; - Idx nsub_tops; - Idx asub_tops; - re_sub_match_top_t **sub_tops; -} re_match_context_t; - -typedef struct -{ - re_dfastate_t **sifted_states; - re_dfastate_t **limited_states; - Idx last_node; - Idx last_str_idx; - re_node_set limits; -} re_sift_context_t; - -struct re_fail_stack_ent_t -{ - Idx idx; - Idx node; - regmatch_t *regs; - re_node_set eps_via_nodes; -}; - -struct re_fail_stack_t -{ - Idx num; - Idx alloc; - struct re_fail_stack_ent_t *stack; -}; - -struct re_dfa_t -{ - re_token_t *nodes; - size_t nodes_alloc; - size_t nodes_len; - Idx *nexts; - Idx *org_indices; - re_node_set *edests; - re_node_set *eclosures; - re_node_set *inveclosures; - struct re_state_table_entry *state_table; - re_dfastate_t *init_state; - re_dfastate_t *init_state_word; - re_dfastate_t *init_state_nl; - re_dfastate_t *init_state_begbuf; - bin_tree_t *str_tree; - bin_tree_storage_t *str_tree_storage; - re_bitset_ptr_t sb_char; - int str_tree_storage_idx; - - /* number of subexpressions `re_nsub' is in regex_t. */ - re_hashval_t state_hash_mask; - Idx init_node; - Idx nbackref; /* The number of backreference in this dfa. */ - - /* Bitmap expressing which backreference is used. */ - bitset_word_t used_bkref_map; - bitset_word_t completed_bkref_map; - - unsigned int has_plural_match : 1; - /* If this dfa has "multibyte node", which is a backreference or - a node which can accept multibyte character or multi character - collating element. */ - unsigned int has_mb_node : 1; - unsigned int is_utf8 : 1; - unsigned int map_notascii : 1; - unsigned int word_ops_used : 1; - int mb_cur_max; - bitset_t word_char; - reg_syntax_t syntax; - Idx *subexp_map; -#ifdef DEBUG - char* re_str; -#endif -#ifdef _LIBC - __libc_lock_define (, lock) -#endif -}; - -#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) -#define re_node_set_remove(set,id) \ - (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) -#define re_node_set_empty(p) ((p)->nelem = 0) -#define re_node_set_free(set) re_free ((set)->elems) - - -typedef enum -{ - SB_CHAR, - MB_CHAR, - EQUIV_CLASS, - COLL_SYM, - CHAR_CLASS -} bracket_elem_type; - -typedef struct -{ - bracket_elem_type type; - union - { - unsigned char ch; - unsigned char *name; - wchar_t wch; - } opr; -} bracket_elem_t; - - -/* Inline functions for bitset_t operation. */ - -static inline void -bitset_set (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS; -} - -static inline void -bitset_clear (bitset_t set, Idx i) -{ - set[i / BITSET_WORD_BITS] &= ~ ((bitset_word_t) 1 << i % BITSET_WORD_BITS); -} - -static inline bool -bitset_contain (const bitset_t set, Idx i) -{ - return (set[i / BITSET_WORD_BITS] >> i % BITSET_WORD_BITS) & 1; -} - -static inline void -bitset_empty (bitset_t set) -{ - memset (set, '\0', sizeof (bitset_t)); -} - -static inline void -bitset_set_all (bitset_t set) -{ - memset (set, -1, sizeof (bitset_word_t) * (SBC_MAX / BITSET_WORD_BITS)); - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1; -} - -static inline void -bitset_copy (bitset_t dest, const bitset_t src) -{ - memcpy (dest, src, sizeof (bitset_t)); -} - -static inline void -bitset_not (bitset_t set) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < SBC_MAX / BITSET_WORD_BITS; ++bitset_i) - set[bitset_i] = ~set[bitset_i]; - if (SBC_MAX % BITSET_WORD_BITS != 0) - set[BITSET_WORDS - 1] = - ((((bitset_word_t) 1 << SBC_MAX % BITSET_WORD_BITS) - 1) - & ~set[BITSET_WORDS - 1]); -} - -static inline void -bitset_merge (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] |= src[bitset_i]; -} - -static inline void -bitset_mask (bitset_t dest, const bitset_t src) -{ - int bitset_i; - for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) - dest[bitset_i] &= src[bitset_i]; -} - -#ifdef RE_ENABLE_I18N -/* Inline functions for re_string. */ -static inline int -internal_function __attribute ((pure)) -re_string_char_size_at (const re_string_t *pstr, Idx idx) -{ - int byte_idx; - if (pstr->mb_cur_max == 1) - return 1; - for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) - if (pstr->wcs[idx + byte_idx] != WEOF) - break; - return byte_idx; -} - -static inline wint_t -internal_function __attribute ((pure)) -re_string_wchar_at (const re_string_t *pstr, Idx idx) -{ - if (pstr->mb_cur_max == 1) - return (wint_t) pstr->mbs[idx]; - return (wint_t) pstr->wcs[idx]; -} - -static int -internal_function __attribute ((pure)) -re_string_elem_size_at (const re_string_t *pstr, Idx idx) -{ -# ifdef _LIBC - const unsigned char *p, *extra; - const int32_t *table, *indirect; - int32_t tmp; -# include - uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - - if (nrules != 0) - { - table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, - _NL_COLLATE_INDIRECTMB); - p = pstr->mbs + idx; - tmp = findidx (&p); - return p - pstr->mbs - idx; - } - else -# endif /* _LIBC */ - return 1; -} -#endif /* RE_ENABLE_I18N */ - -#endif /* _REGEX_INTERNAL_H */ diff --git a/usr/src/lib/libparted/common/lib/regexec.c b/usr/src/lib/libparted/common/lib/regexec.c deleted file mode 100644 index b136570820..0000000000 --- a/usr/src/lib/libparted/common/lib/regexec.c +++ /dev/null @@ -1,4399 +0,0 @@ -/* Extended regular expression matching and search library. - Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, - Inc. - This file is part of the GNU C Library. - Contributed by Isamu Hasegawa . - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, - Idx n) internal_function; -static void match_ctx_clean (re_match_context_t *mctx) internal_function; -static void match_ctx_free (re_match_context_t *cache) internal_function; -static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, Idx node, - Idx str_idx, Idx from, Idx to) - internal_function; -static Idx search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) - internal_function; -static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, Idx node, - Idx str_idx) internal_function; -static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, - Idx node, Idx str_idx) - internal_function; -static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, - Idx last_str_idx) - internal_function; -static reg_errcode_t re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) internal_function; -static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, - struct re_registers *regs, - Idx stop, bool ret_len) internal_function; -static regoff_t re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, Idx start, - regoff_t range, Idx stop, - struct re_registers *regs, - bool ret_len) internal_function; -static unsigned int re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, - Idx nregs, int regs_allocated) - internal_function; -static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) - internal_function; -static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) internal_function; -static Idx check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) - internal_function; -static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, - Idx cur_idx, Idx nmatch) internal_function; -static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, - Idx str_idx, Idx dest_node, Idx nregs, - regmatch_t *regs, - re_node_set *eps_via_nodes) - internal_function; -static reg_errcode_t set_regs (const regex_t *preg, - const re_match_context_t *mctx, - size_t nmatch, regmatch_t *pmatch, - bool fl_backtrack) internal_function; -static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) - internal_function; - -#ifdef RE_ENABLE_I18N -static int sift_states_iter_mb (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, - re_sift_context_t *sctx) - internal_function; -static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *cur_dest) - internal_function; -static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, - re_node_set *dest_nodes) - internal_function; -static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates) - internal_function; -static bool check_dst_limits (const re_match_context_t *mctx, - const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, - Idx src_idx) internal_function; -static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, - int boundaries, Idx subexp_idx, - Idx from_node, Idx bkref_idx) - internal_function; -static int check_dst_limits_calc_pos (const re_match_context_t *mctx, - Idx limit, Idx subexp_idx, - Idx node, Idx str_idx, - Idx bkref_idx) internal_function; -static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, - re_node_set *dest_nodes, - const re_node_set *candidates, - re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, - Idx str_idx) internal_function; -static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, - re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) - internal_function; -static reg_errcode_t merge_state_array (const re_dfa_t *dfa, - re_dfastate_t **dst, - re_dfastate_t **src, Idx num) - internal_function; -static re_dfastate_t *find_recover_state (reg_errcode_t *err, - re_match_context_t *mctx) internal_function; -static re_dfastate_t *transit_state (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *state) internal_function; -static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *next_state) - internal_function; -static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, - re_node_set *cur_nodes, - Idx str_idx) internal_function; -#if 0 -static re_dfastate_t *transit_state_sb (reg_errcode_t *err, - re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif -#ifdef RE_ENABLE_I18N -static reg_errcode_t transit_state_mb (re_match_context_t *mctx, - re_dfastate_t *pstate) - internal_function; -#endif /* RE_ENABLE_I18N */ -static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, - const re_node_set *nodes) - internal_function; -static reg_errcode_t get_subexp (re_match_context_t *mctx, - Idx bkref_node, Idx bkref_str_idx) - internal_function; -static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, - const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, - Idx bkref_node, Idx bkref_str) - internal_function; -static Idx find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) internal_function; -static reg_errcode_t check_arrival (re_match_context_t *mctx, - state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, - int type) internal_function; -static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, - Idx str_idx, - re_node_set *cur_nodes, - re_node_set *next_nodes) - internal_function; -static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, - re_node_set *cur_nodes, - Idx ex_subexp, int type) - internal_function; -static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, - re_node_set *dst_nodes, - Idx target, Idx ex_subexp, - int type) internal_function; -static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, - re_node_set *cur_nodes, Idx cur_str, - Idx subexp_num, int type) - internal_function; -static bool build_trtable (const re_dfa_t *dfa, - re_dfastate_t *state) internal_function; -#ifdef RE_ENABLE_I18N -static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx idx) - internal_function; -# ifdef _LIBC -static unsigned int find_collation_sequence_value (const unsigned char *mbs, - size_t name_len) - internal_function; -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ -static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa, - const re_dfastate_t *state, - re_node_set *states_node, - bitset_t *states_ch) internal_function; -static bool check_node_accept (const re_match_context_t *mctx, - const re_token_t *node, Idx idx) - internal_function; -static reg_errcode_t extend_buffers (re_match_context_t *mctx) - internal_function; - -/* Entry point for POSIX code. */ - -/* regexec searches for a given pattern, specified by PREG, in the - string STRING. - - If NMATCH is zero or REG_NOSUB was set in the cflags argument to - `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at - least NMATCH elements, and we set them to the offsets of the - corresponding matched substrings. - - EFLAGS specifies `execution flags' which affect matching: if - REG_NOTBOL is set, then ^ does not match at the beginning of the - string; if REG_NOTEOL is set, then $ does not match at the end. - - We return 0 if we find a match and REG_NOMATCH if not. */ - -int -regexec (preg, string, nmatch, pmatch, eflags) - const regex_t *_Restrict_ preg; - const char *_Restrict_ string; - size_t nmatch; - regmatch_t pmatch[_Restrict_arr_]; - int eflags; -{ - reg_errcode_t err; - Idx start, length; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) preg->buffer; -#endif - - if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) - return REG_BADPAT; - - if (eflags & REG_STARTEND) - { - start = pmatch[0].rm_so; - length = pmatch[0].rm_eo; - } - else - { - start = 0; - length = strlen (string); - } - - __libc_lock_lock (dfa->lock); - if (preg->no_sub) - err = re_search_internal (preg, string, length, start, length, - length, 0, NULL, eflags); - else - err = re_search_internal (preg, string, length, start, length, - length, nmatch, pmatch, eflags); - __libc_lock_unlock (dfa->lock); - return err != REG_NOERROR; -} - -#ifdef _LIBC -# include -versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4); - -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) -__typeof__ (__regexec) __compat_regexec; - -int -attribute_compat_text_section -__compat_regexec (const regex_t *_Restrict_ preg, - const char *_Restrict_ string, size_t nmatch, - regmatch_t pmatch[], int eflags) -{ - return regexec (preg, string, nmatch, pmatch, - eflags & (REG_NOTBOL | REG_NOTEOL)); -} -compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0); -# endif -#endif - -/* Entry points for GNU code. */ - -/* re_match, re_search, re_match_2, re_search_2 - - The former two functions operate on STRING with length LENGTH, - while the later two operate on concatenation of STRING1 and STRING2 - with lengths LENGTH1 and LENGTH2, respectively. - - re_match() matches the compiled pattern in BUFP against the string, - starting at index START. - - re_search() first tries matching at index START, then it tries to match - starting from index START + 1, and so on. The last start position tried - is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same - way as re_match().) - - The parameter STOP of re_{match,search}_2 specifies that no match exceeding - the first STOP characters of the concatenation of the strings should be - concerned. - - If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match - and all groups is stored in REGS. (For the "_2" variants, the offsets are - computed relative to the concatenation, not relative to the individual - strings.) - - On success, re_match* functions return the length of the match, re_search* - return the position of the start of the match. Return value -1 means no - match was found and -2 indicates an internal error. */ - -regoff_t -re_match (bufp, string, length, start, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, 0, length, regs, true); -} -#ifdef _LIBC -weak_alias (__re_match, re_match) -#endif - -regoff_t -re_search (bufp, string, length, start, range, regs) - struct re_pattern_buffer *bufp; - const char *string; - Idx length, start; - regoff_t range; - struct re_registers *regs; -{ - return re_search_stub (bufp, string, length, start, range, length, regs, - false); -} -#ifdef _LIBC -weak_alias (__re_search, re_search) -#endif - -regoff_t -re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, 0, regs, stop, true); -} -#ifdef _LIBC -weak_alias (__re_match_2, re_match_2) -#endif - -regoff_t -re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop) - struct re_pattern_buffer *bufp; - const char *string1, *string2; - Idx length1, length2, start, stop; - regoff_t range; - struct re_registers *regs; -{ - return re_search_2_stub (bufp, string1, length1, string2, length2, - start, range, regs, stop, false); -} -#ifdef _LIBC -weak_alias (__re_search_2, re_search_2) -#endif - -static regoff_t -internal_function -re_search_2_stub (struct re_pattern_buffer *bufp, - const char *string1, Idx length1, - const char *string2, Idx length2, - Idx start, regoff_t range, struct re_registers *regs, - Idx stop, bool ret_len) -{ - const char *str; - regoff_t rval; - Idx len = length1 + length2; - char *s = NULL; - - if (BE (length1 < 0 || length2 < 0 || stop < 0 || len < length1, 0)) - return -2; - - /* Concatenate the strings. */ - if (length2 > 0) - if (length1 > 0) - { - s = re_malloc (char, len); - - if (BE (s == NULL, 0)) - return -2; -#ifdef _LIBC - memcpy (__mempcpy (s, string1, length1), string2, length2); -#else - memcpy (s, string1, length1); - memcpy (s + length1, string2, length2); -#endif - str = s; - } - else - str = string2; - else - str = string1; - - rval = re_search_stub (bufp, str, len, start, range, stop, regs, - ret_len); - re_free (s); - return rval; -} - -/* The parameters have the same meaning as those of re_search. - Additional parameters: - If RET_LEN is true the length of the match is returned (re_match style); - otherwise the position of the match is returned. */ - -static regoff_t -internal_function -re_search_stub (struct re_pattern_buffer *bufp, - const char *string, Idx length, - Idx start, regoff_t range, Idx stop, struct re_registers *regs, - bool ret_len) -{ - reg_errcode_t result; - regmatch_t *pmatch; - Idx nregs; - regoff_t rval; - int eflags = 0; -#ifdef _LIBC - re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; -#endif - Idx last_start = start + range; - - /* Check for out-of-range. */ - if (BE (start < 0 || start > length, 0)) - return -1; - if (BE (length < last_start || (0 <= range && last_start < start), 0)) - last_start = length; - else if (BE (last_start < 0 || (range < 0 && start <= last_start), 0)) - last_start = 0; - - __libc_lock_lock (dfa->lock); - - eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; - eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; - - /* Compile fastmap if we haven't yet. */ - if (start < last_start && bufp->fastmap != NULL && !bufp->fastmap_accurate) - re_compile_fastmap (bufp); - - if (BE (bufp->no_sub, 0)) - regs = NULL; - - /* We need at least 1 register. */ - if (regs == NULL) - nregs = 1; - else if (BE (bufp->regs_allocated == REGS_FIXED - && regs->num_regs <= bufp->re_nsub, 0)) - { - nregs = regs->num_regs; - if (BE (nregs < 1, 0)) - { - /* Nothing can be copied to regs. */ - regs = NULL; - nregs = 1; - } - } - else - nregs = bufp->re_nsub + 1; - pmatch = re_malloc (regmatch_t, nregs); - if (BE (pmatch == NULL, 0)) - { - rval = -2; - goto out; - } - - result = re_search_internal (bufp, string, length, start, last_start, stop, - nregs, pmatch, eflags); - - rval = 0; - - /* I hope we needn't fill ther regs with -1's when no match was found. */ - if (result != REG_NOERROR) - rval = -1; - else if (regs != NULL) - { - /* If caller wants register contents data back, copy them. */ - bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, - bufp->regs_allocated); - if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) - rval = -2; - } - - if (BE (rval == 0, 1)) - { - if (ret_len) - { - assert (pmatch[0].rm_so == start); - rval = pmatch[0].rm_eo - start; - } - else - rval = pmatch[0].rm_so; - } - re_free (pmatch); - out: - __libc_lock_unlock (dfa->lock); - return rval; -} - -static unsigned int -internal_function -re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs, - int regs_allocated) -{ - int rval = REGS_REALLOCATE; - Idx i; - Idx need_regs = nregs + 1; - /* We need one extra element beyond `num_regs' for the `-1' marker GNU code - uses. */ - - /* Have the register data arrays been allocated? */ - if (regs_allocated == REGS_UNALLOCATED) - { /* No. So allocate them with malloc. */ - regs->start = re_malloc (regoff_t, need_regs); - if (BE (regs->start == NULL, 0)) - return REGS_UNALLOCATED; - regs->end = re_malloc (regoff_t, need_regs); - if (BE (regs->end == NULL, 0)) - { - re_free (regs->start); - return REGS_UNALLOCATED; - } - regs->num_regs = need_regs; - } - else if (regs_allocated == REGS_REALLOCATE) - { /* Yes. If we need more elements than were already - allocated, reallocate them. If we need fewer, just - leave it alone. */ - if (BE (need_regs > regs->num_regs, 0)) - { - regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); - regoff_t *new_end; - if (BE (new_start == NULL, 0)) - return REGS_UNALLOCATED; - new_end = re_realloc (regs->end, regoff_t, need_regs); - if (BE (new_end == NULL, 0)) - { - re_free (new_start); - return REGS_UNALLOCATED; - } - regs->start = new_start; - regs->end = new_end; - regs->num_regs = need_regs; - } - } - else - { - assert (regs_allocated == REGS_FIXED); - /* This function may not be called with REGS_FIXED and nregs too big. */ - assert (regs->num_regs >= nregs); - rval = REGS_FIXED; - } - - /* Copy the regs. */ - for (i = 0; i < nregs; ++i) - { - regs->start[i] = pmatch[i].rm_so; - regs->end[i] = pmatch[i].rm_eo; - } - for ( ; i < regs->num_regs; ++i) - regs->start[i] = regs->end[i] = -1; - - return rval; -} - -/* Set REGS to hold NUM_REGS registers, storing them in STARTS and - ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use - this memory for recording register information. STARTS and ENDS - must be allocated using the malloc library routine, and must each - be at least NUM_REGS * sizeof (regoff_t) bytes long. - - If NUM_REGS == 0, then subsequent matches should allocate their own - register data. - - Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ - -void -re_set_registers (bufp, regs, num_regs, starts, ends) - struct re_pattern_buffer *bufp; - struct re_registers *regs; - __re_size_t num_regs; - regoff_t *starts, *ends; -{ - if (num_regs) - { - bufp->regs_allocated = REGS_REALLOCATE; - regs->num_regs = num_regs; - regs->start = starts; - regs->end = ends; - } - else - { - bufp->regs_allocated = REGS_UNALLOCATED; - regs->num_regs = 0; - regs->start = regs->end = NULL; - } -} -#ifdef _LIBC -weak_alias (__re_set_registers, re_set_registers) -#endif - -/* Entry points compatible with 4.2 BSD regex library. We don't define - them unless specifically requested. */ - -#if defined _REGEX_RE_COMP || defined _LIBC -int -# ifdef _LIBC -weak_function -# endif -re_exec (s) - const char *s; -{ - return 0 == regexec (&re_comp_buf, s, 0, NULL, 0); -} -#endif /* _REGEX_RE_COMP */ - -/* Internal entry point. */ - -/* Searches for a compiled pattern PREG in the string STRING, whose - length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same - meaning as with regexec. LAST_START is START + RANGE, where - START and RANGE have the same meaning as with re_search. - Return REG_NOERROR if we find a match, and REG_NOMATCH if not, - otherwise return the error code. - Note: We assume front end functions already check ranges. - (0 <= LAST_START && LAST_START <= LENGTH) */ - -static reg_errcode_t -internal_function -re_search_internal (const regex_t *preg, - const char *string, Idx length, - Idx start, Idx last_start, Idx stop, - size_t nmatch, regmatch_t pmatch[], - int eflags) -{ - reg_errcode_t err; - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx left_lim, right_lim; - int incr; - bool fl_longest_match; - int match_kind; - Idx match_first; - Idx match_last = REG_MISSING; - Idx extra_nmatch; - bool sb; - int ch; -#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) - re_match_context_t mctx = { .dfa = dfa }; -#else - re_match_context_t mctx; -#endif - char *fastmap = ((preg->fastmap != NULL && preg->fastmap_accurate - && start != last_start && !preg->can_be_null) - ? preg->fastmap : NULL); - RE_TRANSLATE_TYPE t = preg->translate; - -#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) - memset (&mctx, '\0', sizeof (re_match_context_t)); - mctx.dfa = dfa; -#endif - - extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; - nmatch -= extra_nmatch; - - /* Check if the DFA haven't been compiled. */ - if (BE (preg->used == 0 || dfa->init_state == NULL - || dfa->init_state_word == NULL || dfa->init_state_nl == NULL - || dfa->init_state_begbuf == NULL, 0)) - return REG_NOMATCH; - -#ifdef DEBUG - /* We assume front-end functions already check them. */ - assert (0 <= last_start && last_start <= length); -#endif - - /* If initial states with non-begbuf contexts have no elements, - the regex must be anchored. If preg->newline_anchor is set, - we'll never use init_state_nl, so do not check it. */ - if (dfa->init_state->nodes.nelem == 0 - && dfa->init_state_word->nodes.nelem == 0 - && (dfa->init_state_nl->nodes.nelem == 0 - || !preg->newline_anchor)) - { - if (start != 0 && last_start != 0) - return REG_NOMATCH; - start = last_start = 0; - } - - /* We must check the longest matching, if nmatch > 0. */ - fl_longest_match = (nmatch != 0 || dfa->nbackref); - - err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, - preg->translate, preg->syntax & RE_ICASE, dfa); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - mctx.input.stop = stop; - mctx.input.raw_stop = stop; - mctx.input.newline_anchor = preg->newline_anchor; - - err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* We will log all the DFA states through which the dfa pass, - if nmatch > 1, or this dfa has "multibyte node", which is a - back-reference or a node which can accept multibyte character or - multi character collating element. */ - if (nmatch > 1 || dfa->has_mb_node) - { - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= mctx.input.bufs_len, 0)) - { - err = REG_ESPACE; - goto free_return; - } - - mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); - if (BE (mctx.state_log == NULL, 0)) - { - err = REG_ESPACE; - goto free_return; - } - } - else - mctx.state_log = NULL; - - match_first = start; - mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF - : CONTEXT_NEWLINE | CONTEXT_BEGBUF; - - /* Check incrementally whether of not the input string match. */ - incr = (last_start < start) ? -1 : 1; - left_lim = (last_start < start) ? last_start : start; - right_lim = (last_start < start) ? start : last_start; - sb = dfa->mb_cur_max == 1; - match_kind = - (fastmap - ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) - | (start <= last_start ? 2 : 0) - | (t != NULL ? 1 : 0)) - : 8); - - for (;; match_first += incr) - { - err = REG_NOMATCH; - if (match_first < left_lim || right_lim < match_first) - goto free_return; - - /* Advance as rapidly as possible through the string, until we - find a plausible place to start matching. This may be done - with varying efficiency, so there are various possibilities: - only the most common of them are specialized, in order to - save on code size. We use a switch statement for speed. */ - switch (match_kind) - { - case 8: - /* No fastmap. */ - break; - - case 7: - /* Fastmap with single-byte translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[t[(unsigned char) string[match_first]]]) - ++match_first; - goto forward_match_found_start_or_reached_end; - - case 6: - /* Fastmap without translation, match forward. */ - while (BE (match_first < right_lim, 1) - && !fastmap[(unsigned char) string[match_first]]) - ++match_first; - - forward_match_found_start_or_reached_end: - if (BE (match_first == right_lim, 0)) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (!fastmap[t ? t[ch] : ch]) - goto free_return; - } - break; - - case 4: - case 5: - /* Fastmap without multi-byte translation, match backwards. */ - while (match_first >= left_lim) - { - ch = match_first >= length - ? 0 : (unsigned char) string[match_first]; - if (fastmap[t ? t[ch] : ch]) - break; - --match_first; - } - if (match_first < left_lim) - goto free_return; - break; - - default: - /* In this case, we can't determine easily the current byte, - since it might be a component byte of a multibyte - character. Then we use the constructed buffer instead. */ - for (;;) - { - /* If MATCH_FIRST is out of the valid range, reconstruct the - buffers. */ - __re_size_t offset = match_first - mctx.input.raw_mbs_idx; - if (BE (offset >= (__re_size_t) mctx.input.valid_raw_len, 0)) - { - err = re_string_reconstruct (&mctx.input, match_first, - eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - offset = match_first - mctx.input.raw_mbs_idx; - } - /* If MATCH_FIRST is out of the buffer, leave it as '\0'. - Note that MATCH_FIRST must not be smaller than 0. */ - ch = (match_first >= length - ? 0 : re_string_byte_at (&mctx.input, offset)); - if (fastmap[ch]) - break; - match_first += incr; - if (match_first < left_lim || match_first > right_lim) - { - err = REG_NOMATCH; - goto free_return; - } - } - break; - } - - /* Reconstruct the buffers so that the matcher can assume that - the matching starts from the beginning of the buffer. */ - err = re_string_reconstruct (&mctx.input, match_first, eflags); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - -#ifdef RE_ENABLE_I18N - /* Don't consider this char as a possible match start if it part, - yet isn't the head, of a multibyte character. */ - if (!sb && !re_string_first_byte (&mctx.input, 0)) - continue; -#endif - - /* It seems to be appropriate one, then use the matcher. */ - /* We assume that the matching starts from 0. */ - mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; - match_last = check_matching (&mctx, fl_longest_match, - start <= last_start ? &match_first : NULL); - if (match_last != REG_MISSING) - { - if (BE (match_last == REG_ERROR, 0)) - { - err = REG_ESPACE; - goto free_return; - } - else - { - mctx.match_last = match_last; - if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) - { - re_dfastate_t *pstate = mctx.state_log[match_last]; - mctx.last_node = check_halt_state_context (&mctx, pstate, - match_last); - } - if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) - || dfa->nbackref) - { - err = prune_impossible_nodes (&mctx); - if (err == REG_NOERROR) - break; - if (BE (err != REG_NOMATCH, 0)) - goto free_return; - match_last = REG_MISSING; - } - else - break; /* We found a match. */ - } - } - - match_ctx_clean (&mctx); - } - -#ifdef DEBUG - assert (match_last != REG_MISSING); - assert (err == REG_NOERROR); -#endif - - /* Set pmatch[] if we need. */ - if (nmatch > 0) - { - Idx reg_idx; - - /* Initialize registers. */ - for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) - pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; - - /* Set the points where matching start/end. */ - pmatch[0].rm_so = 0; - pmatch[0].rm_eo = mctx.match_last; - /* FIXME: This function should fail if mctx.match_last exceeds - the maximum possible regoff_t value. We need a new error - code REG_OVERFLOW. */ - - if (!preg->no_sub && nmatch > 1) - { - err = set_regs (preg, &mctx, nmatch, pmatch, - dfa->has_plural_match && dfa->nbackref > 0); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* At last, add the offset to the each registers, since we slided - the buffers so that we could assume that the matching starts - from 0. */ - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so != -1) - { -#ifdef RE_ENABLE_I18N - if (BE (mctx.input.offsets_needed != 0, 0)) - { - pmatch[reg_idx].rm_so = - (pmatch[reg_idx].rm_so == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_so]); - pmatch[reg_idx].rm_eo = - (pmatch[reg_idx].rm_eo == mctx.input.valid_len - ? mctx.input.valid_raw_len - : mctx.input.offsets[pmatch[reg_idx].rm_eo]); - } -#else - assert (mctx.input.offsets_needed == 0); -#endif - pmatch[reg_idx].rm_so += match_first; - pmatch[reg_idx].rm_eo += match_first; - } - for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) - { - pmatch[nmatch + reg_idx].rm_so = -1; - pmatch[nmatch + reg_idx].rm_eo = -1; - } - - if (dfa->subexp_map) - for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) - if (dfa->subexp_map[reg_idx] != reg_idx) - { - pmatch[reg_idx + 1].rm_so - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; - pmatch[reg_idx + 1].rm_eo - = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; - } - } - - free_return: - re_free (mctx.state_log); - if (dfa->nbackref) - match_ctx_free (&mctx); - re_string_destruct (&mctx.input); - return err; -} - -static reg_errcode_t -internal_function -prune_impossible_nodes (re_match_context_t *mctx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx halt_node, match_last; - reg_errcode_t ret; - re_dfastate_t **sifted_states; - re_dfastate_t **lim_states = NULL; - re_sift_context_t sctx; -#ifdef DEBUG - assert (mctx->state_log != NULL); -#endif - match_last = mctx->match_last; - halt_node = mctx->last_node; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= match_last, 0)) - return REG_ESPACE; - - sifted_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (sifted_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - if (dfa->nbackref) - { - lim_states = re_malloc (re_dfastate_t *, match_last + 1); - if (BE (lim_states == NULL, 0)) - { - ret = REG_ESPACE; - goto free_return; - } - while (1) - { - memset (lim_states, '\0', - sizeof (re_dfastate_t *) * (match_last + 1)); - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, - match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - if (sifted_states[0] != NULL || lim_states[0] != NULL) - break; - do - { - --match_last; - if (! REG_VALID_INDEX (match_last)) - { - ret = REG_NOMATCH; - goto free_return; - } - } while (mctx->state_log[match_last] == NULL - || !mctx->state_log[match_last]->halt); - halt_node = check_halt_state_context (mctx, - mctx->state_log[match_last], - match_last); - } - ret = merge_state_array (dfa, sifted_states, lim_states, - match_last + 1); - re_free (lim_states); - lim_states = NULL; - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - else - { - sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); - ret = sift_states_backward (mctx, &sctx); - re_node_set_free (&sctx.limits); - if (BE (ret != REG_NOERROR, 0)) - goto free_return; - } - re_free (mctx->state_log); - mctx->state_log = sifted_states; - sifted_states = NULL; - mctx->last_node = halt_node; - mctx->match_last = match_last; - ret = REG_NOERROR; - free_return: - re_free (sifted_states); - re_free (lim_states); - return ret; -} - -/* Acquire an initial state and return it. - We must select appropriate initial state depending on the context, - since initial states may have constraints like "\<", "^", etc.. */ - -static inline re_dfastate_t * -__attribute ((always_inline)) internal_function -acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, - Idx idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - if (dfa->init_state->has_constraint) - { - unsigned int context; - context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return dfa->init_state_word; - else if (IS_ORDINARY_CONTEXT (context)) - return dfa->init_state; - else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_begbuf; - else if (IS_NEWLINE_CONTEXT (context)) - return dfa->init_state_nl; - else if (IS_BEGBUF_CONTEXT (context)) - { - /* It is relatively rare case, then calculate on demand. */ - return re_acquire_state_context (err, dfa, - dfa->init_state->entrance_nodes, - context); - } - else - /* Must not happen? */ - return dfa->init_state; - } - else - return dfa->init_state; -} - -/* Check whether the regular expression match input string INPUT or not, - and return the index where the matching end. Return REG_MISSING if - there is no match, and return REG_ERROR in case of an error. - FL_LONGEST_MATCH means we want the POSIX longest matching. - If P_MATCH_FIRST is not NULL, and the match fails, it is set to the - next place where we may want to try matching. - Note that the matcher assume that the maching starts from the current - index of the buffer. */ - -static Idx -internal_function -check_matching (re_match_context_t *mctx, bool fl_longest_match, - Idx *p_match_first) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx match = 0; - Idx match_last = REG_MISSING; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - re_dfastate_t *cur_state; - bool at_init_state = p_match_first != NULL; - Idx next_start_idx = cur_str_idx; - - err = REG_NOERROR; - cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); - /* An initial state must not be NULL (invalid). */ - if (BE (cur_state == NULL, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - - if (mctx->state_log != NULL) - { - mctx->state_log[cur_str_idx] = cur_state; - - /* Check OP_OPEN_SUBEXP in the initial state in case that we use them - later. E.g. Processing back references. */ - if (BE (dfa->nbackref, 0)) - { - at_init_state = false; - err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (cur_state->has_backref) - { - err = transit_state_bkref (mctx, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - - /* If the RE accepts NULL string. */ - if (BE (cur_state->halt, 0)) - { - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, cur_str_idx)) - { - if (!fl_longest_match) - return cur_str_idx; - else - { - match_last = cur_str_idx; - match = 1; - } - } - } - - while (!re_string_eoi (&mctx->input)) - { - re_dfastate_t *old_state = cur_state; - Idx next_char_idx = re_string_cur_idx (&mctx->input) + 1; - - if (BE (next_char_idx >= mctx->input.bufs_len, 0) - || (BE (next_char_idx >= mctx->input.valid_len, 0) - && mctx->input.valid_len < mctx->input.len)) - { - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - { - assert (err == REG_ESPACE); - return REG_ERROR; - } - } - - cur_state = transit_state (&err, mctx, cur_state); - if (mctx->state_log != NULL) - cur_state = merge_state_with_log (&err, mctx, cur_state); - - if (cur_state == NULL) - { - /* Reached the invalid state or an error. Try to recover a valid - state using the state log, if available and if we have not - already found a valid (even if not the longest) match. */ - if (BE (err != REG_NOERROR, 0)) - return REG_ERROR; - - if (mctx->state_log == NULL - || (match && !fl_longest_match) - || (cur_state = find_recover_state (&err, mctx)) == NULL) - break; - } - - if (BE (at_init_state, 0)) - { - if (old_state == cur_state) - next_start_idx = next_char_idx; - else - at_init_state = false; - } - - if (cur_state->halt) - { - /* Reached a halt state. - Check the halt state can satisfy the current context. */ - if (!cur_state->has_constraint - || check_halt_state_context (mctx, cur_state, - re_string_cur_idx (&mctx->input))) - { - /* We found an appropriate halt state. */ - match_last = re_string_cur_idx (&mctx->input); - match = 1; - - /* We found a match, do not modify match_first below. */ - p_match_first = NULL; - if (!fl_longest_match) - break; - } - } - } - - if (p_match_first) - *p_match_first += next_start_idx; - - return match_last; -} - -/* Check NODE match the current context. */ - -static bool -internal_function -check_halt_node_context (const re_dfa_t *dfa, Idx node, unsigned int context) -{ - re_token_type_t type = dfa->nodes[node].type; - unsigned int constraint = dfa->nodes[node].constraint; - if (type != END_OF_RE) - return false; - if (!constraint) - return true; - if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) - return false; - return true; -} - -/* Check the halt state STATE match the current context. - Return 0 if not match, if the node, STATE has, is a halt node and - match the context, return the node. */ - -static Idx -internal_function -check_halt_state_context (const re_match_context_t *mctx, - const re_dfastate_t *state, Idx idx) -{ - Idx i; - unsigned int context; -#ifdef DEBUG - assert (state->halt); -#endif - context = re_string_context_at (&mctx->input, idx, mctx->eflags); - for (i = 0; i < state->nodes.nelem; ++i) - if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) - return state->nodes.elems[i]; - return 0; -} - -/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA - corresponding to the DFA). - Return the destination node, and update EPS_VIA_NODES; - return REG_MISSING in case of errors. */ - -static Idx -internal_function -proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs, - Idx *pidx, Idx node, re_node_set *eps_via_nodes, - struct re_fail_stack_t *fs) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx i; - bool ok; - if (IS_EPSILON_NODE (dfa->nodes[node].type)) - { - re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; - re_node_set *edests = &dfa->edests[node]; - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - /* Pick up a valid destination, or return REG_MISSING if none - is found. */ - for (dest_node = REG_MISSING, i = 0; i < edests->nelem; ++i) - { - Idx candidate = edests->elems[i]; - if (!re_node_set_contains (cur_nodes, candidate)) - continue; - if (dest_node == REG_MISSING) - dest_node = candidate; - - else - { - /* In order to avoid infinite loop like "(a*)*", return the second - epsilon-transition if the first was already considered. */ - if (re_node_set_contains (eps_via_nodes, dest_node)) - return candidate; - - /* Otherwise, push the second epsilon-transition on the fail stack. */ - else if (fs != NULL - && push_fail_stack (fs, *pidx, candidate, nregs, regs, - eps_via_nodes)) - return REG_ERROR; - - /* We know we are going to exit. */ - break; - } - } - return dest_node; - } - else - { - Idx naccepted = 0; - re_token_type_t type = dfa->nodes[node].type; - -#ifdef RE_ENABLE_I18N - if (dfa->nodes[node].accept_mb) - naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); - else -#endif /* RE_ENABLE_I18N */ - if (type == OP_BACK_REF) - { - Idx subexp_idx = dfa->nodes[node].opr.idx + 1; - naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; - if (fs != NULL) - { - if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) - return REG_MISSING; - else if (naccepted) - { - char *buf = (char *) re_string_get_buffer (&mctx->input); - if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, - naccepted) != 0) - return REG_MISSING; - } - } - - if (naccepted == 0) - { - Idx dest_node; - ok = re_node_set_insert (eps_via_nodes, node); - if (BE (! ok, 0)) - return REG_ERROR; - dest_node = dfa->edests[node].elems[0]; - if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node)) - return dest_node; - } - } - - if (naccepted != 0 - || check_node_accept (mctx, dfa->nodes + node, *pidx)) - { - Idx dest_node = dfa->nexts[node]; - *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; - if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL - || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, - dest_node))) - return REG_MISSING; - re_node_set_empty (eps_via_nodes); - return dest_node; - } - } - return REG_MISSING; -} - -static reg_errcode_t -internal_function -push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node, - Idx nregs, regmatch_t *regs, re_node_set *eps_via_nodes) -{ - reg_errcode_t err; - Idx num = fs->num++; - if (fs->num == fs->alloc) - { - struct re_fail_stack_ent_t *new_array; - new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) - * fs->alloc * 2)); - if (new_array == NULL) - return REG_ESPACE; - fs->alloc *= 2; - fs->stack = new_array; - } - fs->stack[num].idx = str_idx; - fs->stack[num].node = dest_node; - fs->stack[num].regs = re_malloc (regmatch_t, nregs); - if (fs->stack[num].regs == NULL) - return REG_ESPACE; - memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); - err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); - return err; -} - -static Idx -internal_function -pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs, - regmatch_t *regs, re_node_set *eps_via_nodes) -{ - Idx num = --fs->num; - assert (REG_VALID_INDEX (num)); - *pidx = fs->stack[num].idx; - memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); - re_node_set_free (eps_via_nodes); - re_free (fs->stack[num].regs); - *eps_via_nodes = fs->stack[num].eps_via_nodes; - return fs->stack[num].node; -} - -/* Set the positions where the subexpressions are starts/ends to registers - PMATCH. - Note: We assume that pmatch[0] is already set, and - pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ - -static reg_errcode_t -internal_function -set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, - regmatch_t *pmatch, bool fl_backtrack) -{ - const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; - Idx idx, cur_node; - re_node_set eps_via_nodes; - struct re_fail_stack_t *fs; - struct re_fail_stack_t fs_body = { 0, 2, NULL }; - regmatch_t *prev_idx_match; - bool prev_idx_match_malloced = false; - -#ifdef DEBUG - assert (nmatch > 1); - assert (mctx->state_log != NULL); -#endif - if (fl_backtrack) - { - fs = &fs_body; - fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); - if (fs->stack == NULL) - return REG_ESPACE; - } - else - fs = NULL; - - cur_node = dfa->init_node; - re_node_set_init_empty (&eps_via_nodes); - - if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) - prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); - else - { - prev_idx_match = re_malloc (regmatch_t, nmatch); - if (prev_idx_match == NULL) - { - free_fail_stack_return (fs); - return REG_ESPACE; - } - prev_idx_match_malloced = true; - } - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - - for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) - { - update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); - - if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) - { - Idx reg_idx; - if (fs) - { - for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) - if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) - break; - if (reg_idx == nmatch) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); - } - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - } - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOERROR; - } - } - - /* Proceed to next node. */ - cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, - &eps_via_nodes, fs); - - if (BE (! REG_VALID_INDEX (cur_node), 0)) - { - if (BE (cur_node == REG_ERROR, 0)) - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - free_fail_stack_return (fs); - return REG_ESPACE; - } - if (fs) - cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, - &eps_via_nodes); - else - { - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return REG_NOMATCH; - } - } - } - re_node_set_free (&eps_via_nodes); - if (prev_idx_match_malloced) - re_free (prev_idx_match); - return free_fail_stack_return (fs); -} - -static reg_errcode_t -internal_function -free_fail_stack_return (struct re_fail_stack_t *fs) -{ - if (fs) - { - Idx fs_idx; - for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) - { - re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); - re_free (fs->stack[fs_idx].regs); - } - re_free (fs->stack); - } - return REG_NOERROR; -} - -static void -internal_function -update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, - regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch) -{ - int type = dfa->nodes[cur_node].type; - if (type == OP_OPEN_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - - /* We are at the first node of this sub expression. */ - if (reg_num < nmatch) - { - pmatch[reg_num].rm_so = cur_idx; - pmatch[reg_num].rm_eo = -1; - } - } - else if (type == OP_CLOSE_SUBEXP) - { - Idx reg_num = dfa->nodes[cur_node].opr.idx + 1; - if (reg_num < nmatch) - { - /* We are at the last node of this sub expression. */ - if (pmatch[reg_num].rm_so < cur_idx) - { - pmatch[reg_num].rm_eo = cur_idx; - /* This is a non-empty match or we are not inside an optional - subexpression. Accept this right away. */ - memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); - } - else - { - if (dfa->nodes[cur_node].opt_subexp - && prev_idx_match[reg_num].rm_so != -1) - /* We transited through an empty match for an optional - subexpression, like (a?)*, and this is not the subexp's - first match. Copy back the old content of the registers - so that matches of an inner subexpression are undone as - well, like in ((a?))*. */ - memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); - else - /* We completed a subexpression, but it may be part of - an optional one, so do not update PREV_IDX_MATCH. */ - pmatch[reg_num].rm_eo = cur_idx; - } - } - } -} - -/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 - and sift the nodes in each states according to the following rules. - Updated state_log will be wrote to STATE_LOG. - - Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... - 1. When STR_IDX == MATCH_LAST(the last index in the state_log): - If `a' isn't the LAST_NODE and `a' can't epsilon transit to - the LAST_NODE, we throw away the node `a'. - 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts - string `s' and transit to `b': - i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw - away the node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is - thrown away, we throw away the node `a'. - 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': - i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the - node `a'. - ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, - we throw away the node `a'. */ - -#define STATE_NODE_CONTAINS(state,node) \ - ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) - -static reg_errcode_t -internal_function -sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) -{ - reg_errcode_t err; - int null_cnt = 0; - Idx str_idx = sctx->last_str_idx; - re_node_set cur_dest; - -#ifdef DEBUG - assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); -#endif - - /* Build sifted state_log[str_idx]. It has the nodes which can epsilon - transit to the last_node and the last_node itself. */ - err = re_node_set_init_1 (&cur_dest, sctx->last_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* Then check each states in the state_log. */ - while (str_idx > 0) - { - /* Update counters. */ - null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; - if (null_cnt > mctx->max_mb_elem_len) - { - memset (sctx->sifted_states, '\0', - sizeof (re_dfastate_t *) * str_idx); - re_node_set_free (&cur_dest); - return REG_NOERROR; - } - re_node_set_empty (&cur_dest); - --str_idx; - - if (mctx->state_log[str_idx]) - { - err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - - /* Add all the nodes which satisfy the following conditions: - - It can epsilon transit to a node in CUR_DEST. - - It is in CUR_SRC. - And update state_log. */ - err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - err = REG_NOERROR; - free_return: - re_node_set_free (&cur_dest); - return err; -} - -static reg_errcode_t -internal_function -build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, re_node_set *cur_dest) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; - Idx i; - - /* Then build the next sifted state. - We build the next sifted state on `cur_dest', and update - `sifted_states[str_idx]' with `cur_dest'. - Note: - `cur_dest' is the sifted state from `state_log[str_idx + 1]'. - `cur_src' points the node_set of the old `state_log[str_idx]' - (with the epsilon nodes pre-filtered out). */ - for (i = 0; i < cur_src->nelem; i++) - { - Idx prev_node = cur_src->elems[i]; - int naccepted = 0; - bool ok; - -#ifdef DEBUG - re_token_type_t type = dfa->nodes[prev_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[prev_node].accept_mb) - naccepted = sift_states_iter_mb (mctx, sctx, prev_node, - str_idx, sctx->last_str_idx); -#endif /* RE_ENABLE_I18N */ - - /* We don't check backreferences here. - See update_cur_sifted_state(). */ - if (!naccepted - && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) - && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], - dfa->nexts[prev_node])) - naccepted = 1; - - if (naccepted == 0) - continue; - - if (sctx->limits.nelem) - { - Idx to_idx = str_idx + naccepted; - if (check_dst_limits (mctx, &sctx->limits, - dfa->nexts[prev_node], to_idx, - prev_node, str_idx)) - continue; - } - ok = re_node_set_insert (cur_dest, prev_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - - return REG_NOERROR; -} - -/* Helper functions. */ - -static reg_errcode_t -internal_function -clean_state_log_if_needed (re_match_context_t *mctx, Idx next_state_log_idx) -{ - Idx top = mctx->state_log_top; - - if (next_state_log_idx >= mctx->input.bufs_len - || (next_state_log_idx >= mctx->input.valid_len - && mctx->input.valid_len < mctx->input.len)) - { - reg_errcode_t err; - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (top < next_state_log_idx) - { - memset (mctx->state_log + top + 1, '\0', - sizeof (re_dfastate_t *) * (next_state_log_idx - top)); - mctx->state_log_top = next_state_log_idx; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, - re_dfastate_t **src, Idx num) -{ - Idx st_idx; - reg_errcode_t err; - for (st_idx = 0; st_idx < num; ++st_idx) - { - if (dst[st_idx] == NULL) - dst[st_idx] = src[st_idx]; - else if (src[st_idx] != NULL) - { - re_node_set merged_set; - err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, - &src[st_idx]->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); - re_node_set_free (&merged_set); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -update_cur_sifted_state (const re_match_context_t *mctx, - re_sift_context_t *sctx, Idx str_idx, - re_node_set *dest_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - const re_node_set *candidates; - candidates = ((mctx->state_log[str_idx] == NULL) ? NULL - : &mctx->state_log[str_idx]->nodes); - - if (dest_nodes->nelem == 0) - sctx->sifted_states[str_idx] = NULL; - else - { - if (candidates) - { - /* At first, add the nodes which can epsilon transit to a node in - DEST_NODE. */ - err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - - /* Then, check the limitations in the current sift_context. */ - if (sctx->limits.nelem) - { - err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, - mctx->bkref_ents, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - - sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (candidates && mctx->state_log[str_idx]->has_backref) - { - err = sift_states_bkref (mctx, sctx, str_idx, candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - reg_errcode_t err = REG_NOERROR; - Idx i; - - re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - - if (!state->inveclosure.alloc) - { - err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return REG_ESPACE; - for (i = 0; i < dest_nodes->nelem; i++) - re_node_set_merge (&state->inveclosure, - dfa->inveclosures + dest_nodes->elems[i]); - } - return re_node_set_add_intersect (dest_nodes, candidates, - &state->inveclosure); -} - -static reg_errcode_t -internal_function -sub_epsilon_src_nodes (const re_dfa_t *dfa, Idx node, re_node_set *dest_nodes, - const re_node_set *candidates) -{ - Idx ecl_idx; - reg_errcode_t err; - re_node_set *inv_eclosure = dfa->inveclosures + node; - re_node_set except_nodes; - re_node_set_init_empty (&except_nodes); - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (cur_node == node) - continue; - if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) - { - Idx edst1 = dfa->edests[cur_node].elems[0]; - Idx edst2 = ((dfa->edests[cur_node].nelem > 1) - ? dfa->edests[cur_node].elems[1] : REG_MISSING); - if ((!re_node_set_contains (inv_eclosure, edst1) - && re_node_set_contains (dest_nodes, edst1)) - || (REG_VALID_NONZERO_INDEX (edst2) - && !re_node_set_contains (inv_eclosure, edst2) - && re_node_set_contains (dest_nodes, edst2))) - { - err = re_node_set_add_intersect (&except_nodes, candidates, - dfa->inveclosures + cur_node); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&except_nodes); - return err; - } - } - } - } - for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) - { - Idx cur_node = inv_eclosure->elems[ecl_idx]; - if (!re_node_set_contains (&except_nodes, cur_node)) - { - Idx idx = re_node_set_contains (dest_nodes, cur_node) - 1; - re_node_set_remove_at (dest_nodes, idx); - } - } - re_node_set_free (&except_nodes); - return REG_NOERROR; -} - -static bool -internal_function -check_dst_limits (const re_match_context_t *mctx, const re_node_set *limits, - Idx dst_node, Idx dst_idx, Idx src_node, Idx src_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx lim_idx, src_pos, dst_pos; - - Idx dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); - Idx src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = mctx->bkref_ents + limits->elems[lim_idx]; - subexp_idx = dfa->nodes[ent->node].opr.idx; - - dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, dst_node, dst_idx, - dst_bkref_idx); - src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], - subexp_idx, src_node, src_idx, - src_bkref_idx); - - /* In case of: - ( ) - ( ) - ( ) */ - if (src_pos == dst_pos) - continue; /* This is unrelated limitation. */ - else - return true; - } - return false; -} - -static int -internal_function -check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, - Idx subexp_idx, Idx from_node, Idx bkref_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - const re_node_set *eclosures = dfa->eclosures + from_node; - Idx node_idx; - - /* Else, we are on the boundary: examine the nodes on the epsilon - closure. */ - for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) - { - Idx node = eclosures->elems[node_idx]; - switch (dfa->nodes[node].type) - { - case OP_BACK_REF: - if (bkref_idx != REG_MISSING) - { - struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; - do - { - Idx dst; - int cpos; - - if (ent->node != node) - continue; - - if (subexp_idx < BITSET_WORD_BITS - && !(ent->eps_reachable_subexps_map - & ((bitset_word_t) 1 << subexp_idx))) - continue; - - /* Recurse trying to reach the OP_OPEN_SUBEXP and - OP_CLOSE_SUBEXP cases below. But, if the - destination node is the same node as the source - node, don't recurse because it would cause an - infinite loop: a regex that exhibits this behavior - is ()\1*\1* */ - dst = dfa->edests[node].elems[0]; - if (dst == from_node) - { - if (boundaries & 1) - return -1; - else /* if (boundaries & 2) */ - return 0; - } - - cpos = - check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - dst, bkref_idx); - if (cpos == -1 /* && (boundaries & 1) */) - return -1; - if (cpos == 0 && (boundaries & 2)) - return 0; - - if (subexp_idx < BITSET_WORD_BITS) - ent->eps_reachable_subexps_map - &= ~((bitset_word_t) 1 << subexp_idx); - } - while (ent++->more); - } - break; - - case OP_OPEN_SUBEXP: - if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) - return -1; - break; - - case OP_CLOSE_SUBEXP: - if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) - return 0; - break; - - default: - break; - } - } - - return (boundaries & 2) ? 1 : 0; -} - -static int -internal_function -check_dst_limits_calc_pos (const re_match_context_t *mctx, Idx limit, - Idx subexp_idx, Idx from_node, Idx str_idx, - Idx bkref_idx) -{ - struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; - int boundaries; - - /* If we are outside the range of the subexpression, return -1 or 1. */ - if (str_idx < lim->subexp_from) - return -1; - - if (lim->subexp_to < str_idx) - return 1; - - /* If we are within the subexpression, return 0. */ - boundaries = (str_idx == lim->subexp_from); - boundaries |= (str_idx == lim->subexp_to) << 1; - if (boundaries == 0) - return 0; - - /* Else, examine epsilon closure. */ - return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, - from_node, bkref_idx); -} - -/* Check the limitations of sub expressions LIMITS, and remove the nodes - which are against limitations from DEST_NODES. */ - -static reg_errcode_t -internal_function -check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, - const re_node_set *candidates, re_node_set *limits, - struct re_backref_cache_entry *bkref_ents, Idx str_idx) -{ - reg_errcode_t err; - Idx node_idx, lim_idx; - - for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) - { - Idx subexp_idx; - struct re_backref_cache_entry *ent; - ent = bkref_ents + limits->elems[lim_idx]; - - if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) - continue; /* This is unrelated limitation. */ - - subexp_idx = dfa->nodes[ent->node].opr.idx; - if (ent->subexp_to == str_idx) - { - Idx ops_node = REG_MISSING; - Idx cls_node = REG_MISSING; - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_OPEN_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - ops_node = node; - else if (type == OP_CLOSE_SUBEXP - && subexp_idx == dfa->nodes[node].opr.idx) - cls_node = node; - } - - /* Check the limitation of the open subexpression. */ - /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ - if (REG_VALID_INDEX (ops_node)) - { - err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - - /* Check the limitation of the close subexpression. */ - if (REG_VALID_INDEX (cls_node)) - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - if (!re_node_set_contains (dfa->inveclosures + node, - cls_node) - && !re_node_set_contains (dfa->eclosures + node, - cls_node)) - { - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - --node_idx; - } - } - } - else /* (ent->subexp_to != str_idx) */ - { - for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) - { - Idx node = dest_nodes->elems[node_idx]; - re_token_type_t type = dfa->nodes[node].type; - if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) - { - if (subexp_idx != dfa->nodes[node].opr.idx) - continue; - /* It is against this limitation. - Remove it form the current sifted state. */ - err = sub_epsilon_src_nodes (dfa, node, dest_nodes, - candidates); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - } - } - return REG_NOERROR; -} - -static reg_errcode_t -internal_function -sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx str_idx, const re_node_set *candidates) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx node_idx, node; - re_sift_context_t local_sctx; - Idx first_idx = search_cur_bkref_entry (mctx, str_idx); - - if (first_idx == REG_MISSING) - return REG_NOERROR; - - local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ - - for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) - { - Idx enabled_idx; - re_token_type_t type; - struct re_backref_cache_entry *entry; - node = candidates->elems[node_idx]; - type = dfa->nodes[node].type; - /* Avoid infinite loop for the REs like "()\1+". */ - if (node == sctx->last_node && str_idx == sctx->last_str_idx) - continue; - if (type != OP_BACK_REF) - continue; - - entry = mctx->bkref_ents + first_idx; - enabled_idx = first_idx; - do - { - Idx subexp_len; - Idx to_idx; - Idx dst_node; - bool ok; - re_dfastate_t *cur_state; - - if (entry->node != node) - continue; - subexp_len = entry->subexp_to - entry->subexp_from; - to_idx = str_idx + subexp_len; - dst_node = (subexp_len ? dfa->nexts[node] - : dfa->edests[node].elems[0]); - - if (to_idx > sctx->last_str_idx - || sctx->sifted_states[to_idx] == NULL - || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) - || check_dst_limits (mctx, &sctx->limits, node, - str_idx, dst_node, to_idx)) - continue; - - if (local_sctx.sifted_states == NULL) - { - local_sctx = *sctx; - err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.last_node = node; - local_sctx.last_str_idx = str_idx; - ok = re_node_set_insert (&local_sctx.limits, enabled_idx); - if (BE (! ok, 0)) - { - err = REG_ESPACE; - goto free_return; - } - cur_state = local_sctx.sifted_states[str_idx]; - err = sift_states_backward (mctx, &local_sctx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - if (sctx->limited_states != NULL) - { - err = merge_state_array (dfa, sctx->limited_states, - local_sctx.sifted_states, - str_idx + 1); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - local_sctx.sifted_states[str_idx] = cur_state; - re_node_set_remove (&local_sctx.limits, enabled_idx); - - /* mctx->bkref_ents may have changed, reload the pointer. */ - entry = mctx->bkref_ents + enabled_idx; - } - while (enabled_idx++, entry++->more); - } - err = REG_NOERROR; - free_return: - if (local_sctx.sifted_states != NULL) - { - re_node_set_free (&local_sctx.limits); - } - - return err; -} - - -#ifdef RE_ENABLE_I18N -static int -internal_function -sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, - Idx node_idx, Idx str_idx, Idx max_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - int naccepted; - /* Check the node can accept `multi byte'. */ - naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); - if (naccepted > 0 && str_idx + naccepted <= max_str_idx && - !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], - dfa->nexts[node_idx])) - /* The node can't accept the `multi byte', or the - destination was already thrown away, then the node - could't accept the current input `multi byte'. */ - naccepted = 0; - /* Otherwise, it is sure that the node could accept - `naccepted' bytes input. */ - return naccepted; -} -#endif /* RE_ENABLE_I18N */ - - -/* Functions for state transition. */ - -/* Return the next state to which the current state STATE will transit by - accepting the current input byte, and update STATE_LOG if necessary. - If STATE can accept a multibyte char/collating element/back reference - update the destination of STATE_LOG. */ - -static re_dfastate_t * -internal_function -transit_state (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - re_dfastate_t **trtable; - unsigned char ch; - -#ifdef RE_ENABLE_I18N - /* If the current state can accept multibyte. */ - if (BE (state->accept_mb, 0)) - { - *err = transit_state_mb (mctx, state); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } -#endif /* RE_ENABLE_I18N */ - - /* Then decide the next state with the single byte. */ -#if 0 - if (0) - /* don't use transition table */ - return transit_state_sb (err, mctx, state); -#endif - - /* Use transition table */ - ch = re_string_fetch_byte (&mctx->input); - for (;;) - { - trtable = state->trtable; - if (BE (trtable != NULL, 1)) - return trtable[ch]; - - trtable = state->word_trtable; - if (BE (trtable != NULL, 1)) - { - unsigned int context; - context - = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - if (IS_WORD_CONTEXT (context)) - return trtable[ch + SBC_MAX]; - else - return trtable[ch]; - } - - if (!build_trtable (mctx->dfa, state)) - { - *err = REG_ESPACE; - return NULL; - } - - /* Retry, we now have a transition table. */ - } -} - -/* Update the state_log if we need */ -static re_dfastate_t * -internal_function -merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *next_state) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx cur_idx = re_string_cur_idx (&mctx->input); - - if (cur_idx > mctx->state_log_top) - { - mctx->state_log[cur_idx] = next_state; - mctx->state_log_top = cur_idx; - } - else if (mctx->state_log[cur_idx] == 0) - { - mctx->state_log[cur_idx] = next_state; - } - else - { - re_dfastate_t *pstate; - unsigned int context; - re_node_set next_nodes, *log_nodes, *table_nodes = NULL; - /* If (state_log[cur_idx] != 0), it implies that cur_idx is - the destination of a multibyte char/collating element/ - back reference. Then the next state is the union set of - these destinations and the results of the transition table. */ - pstate = mctx->state_log[cur_idx]; - log_nodes = pstate->entrance_nodes; - if (next_state != NULL) - { - table_nodes = next_state->entrance_nodes; - *err = re_node_set_init_union (&next_nodes, table_nodes, - log_nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - } - else - next_nodes = *log_nodes; - /* Note: We already add the nodes of the initial state, - then we don't need to add them here. */ - - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input) - 1, - mctx->eflags); - next_state = mctx->state_log[cur_idx] - = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - if (table_nodes != NULL) - re_node_set_free (&next_nodes); - } - - if (BE (dfa->nbackref, 0) && next_state != NULL) - { - /* Check OP_OPEN_SUBEXP in the current state in case that we use them - later. We must check them here, since the back references in the - next state might use them. */ - *err = check_subexp_matching_top (mctx, &next_state->nodes, - cur_idx); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - - /* If the next state has back references. */ - if (next_state->has_backref) - { - *err = transit_state_bkref (mctx, &next_state->nodes); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - next_state = mctx->state_log[cur_idx]; - } - } - - return next_state; -} - -/* Skip bytes in the input that correspond to part of a - multi-byte match, then look in the log for a state - from which to restart matching. */ -static re_dfastate_t * -internal_function -find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) -{ - re_dfastate_t *cur_state; - do - { - Idx max = mctx->state_log_top; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - do - { - if (++cur_str_idx > max) - return NULL; - re_string_skip_bytes (&mctx->input, 1); - } - while (mctx->state_log[cur_str_idx] == NULL); - - cur_state = merge_state_with_log (err, mctx, NULL); - } - while (*err == REG_NOERROR && cur_state == NULL); - return cur_state; -} - -/* Helper functions for transit_state. */ - -/* From the node set CUR_NODES, pick up the nodes whose types are - OP_OPEN_SUBEXP and which have corresponding back references in the regular - expression. And register them to use them later for evaluating the - correspoding back references. */ - -static reg_errcode_t -internal_function -check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx node_idx; - reg_errcode_t err; - - /* TODO: This isn't efficient. - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) - { - Idx node = cur_nodes->elems[node_idx]; - if (dfa->nodes[node].type == OP_OPEN_SUBEXP - && dfa->nodes[node].opr.idx < BITSET_WORD_BITS - && (dfa->used_bkref_map - & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) - { - err = match_ctx_add_subtop (mctx, node, str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - } - } - return REG_NOERROR; -} - -#if 0 -/* Return the next state to which the current state STATE will transit by - accepting the current input byte. */ - -static re_dfastate_t * -transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, - re_dfastate_t *state) -{ - const re_dfa_t *const dfa = mctx->dfa; - re_node_set next_nodes; - re_dfastate_t *next_state; - Idx node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); - unsigned int context; - - *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); - if (BE (*err != REG_NOERROR, 0)) - return NULL; - for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) - { - Idx cur_node = state->nodes.elems[node_cnt]; - if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) - { - *err = re_node_set_merge (&next_nodes, - dfa->eclosures + dfa->nexts[cur_node]); - if (BE (*err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return NULL; - } - } - } - context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); - next_state = re_acquire_state_context (err, dfa, &next_nodes, context); - /* We don't need to check errors here, since the return value of - this function is next_state and ERR is already set. */ - - re_node_set_free (&next_nodes); - re_string_skip_bytes (&mctx->input, 1); - return next_state; -} -#endif - -#ifdef RE_ENABLE_I18N -static reg_errcode_t -internal_function -transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - - for (i = 0; i < pstate->nodes.nelem; ++i) - { - re_node_set dest_nodes, *new_nodes; - Idx cur_node_idx = pstate->nodes.elems[i]; - int naccepted; - Idx dest_idx; - unsigned int context; - re_dfastate_t *dest_state; - - if (!dfa->nodes[cur_node_idx].accept_mb) - continue; - - if (dfa->nodes[cur_node_idx].constraint) - { - context = re_string_context_at (&mctx->input, - re_string_cur_idx (&mctx->input), - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, - context)) - continue; - } - - /* How many bytes the node can accept? */ - naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, - re_string_cur_idx (&mctx->input)); - if (naccepted == 0) - continue; - - /* The node can accepts `naccepted' bytes. */ - dest_idx = re_string_cur_idx (&mctx->input) + naccepted; - mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted - : mctx->max_mb_elem_len); - err = clean_state_log_if_needed (mctx, dest_idx); - if (BE (err != REG_NOERROR, 0)) - return err; -#ifdef DEBUG - assert (dfa->nexts[cur_node_idx] != REG_MISSING); -#endif - new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; - - dest_state = mctx->state_log[dest_idx]; - if (dest_state == NULL) - dest_nodes = *new_nodes; - else - { - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, new_nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - context = re_string_context_at (&mctx->input, dest_idx - 1, - mctx->eflags); - mctx->state_log[dest_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - if (dest_state != NULL) - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) - return err; - } - return REG_NOERROR; -} -#endif /* RE_ENABLE_I18N */ - -static reg_errcode_t -internal_function -transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx i; - Idx cur_str_idx = re_string_cur_idx (&mctx->input); - - for (i = 0; i < nodes->nelem; ++i) - { - Idx dest_str_idx, prev_nelem, bkc_idx; - Idx node_idx = nodes->elems[i]; - unsigned int context; - const re_token_t *node = dfa->nodes + node_idx; - re_node_set *new_dest_nodes; - - /* Check whether `node' is a backreference or not. */ - if (node->type != OP_BACK_REF) - continue; - - if (node->constraint) - { - context = re_string_context_at (&mctx->input, cur_str_idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - continue; - } - - /* `node' is a backreference. - Check the substring which the substring matched. */ - bkc_idx = mctx->nbkref_ents; - err = get_subexp (mctx, node_idx, cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - - /* And add the epsilon closures (which is `new_dest_nodes') of - the backreference to appropriate state_log. */ -#ifdef DEBUG - assert (dfa->nexts[node_idx] != REG_MISSING); -#endif - for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) - { - Idx subexp_len; - re_dfastate_t *dest_state; - struct re_backref_cache_entry *bkref_ent; - bkref_ent = mctx->bkref_ents + bkc_idx; - if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) - continue; - subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; - new_dest_nodes = (subexp_len == 0 - ? dfa->eclosures + dfa->edests[node_idx].elems[0] - : dfa->eclosures + dfa->nexts[node_idx]); - dest_str_idx = (cur_str_idx + bkref_ent->subexp_to - - bkref_ent->subexp_from); - context = re_string_context_at (&mctx->input, dest_str_idx - 1, - mctx->eflags); - dest_state = mctx->state_log[dest_str_idx]; - prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 - : mctx->state_log[cur_str_idx]->nodes.nelem); - /* Add `new_dest_node' to state_log. */ - if (dest_state == NULL) - { - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, new_dest_nodes, - context); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - else - { - re_node_set dest_nodes; - err = re_node_set_init_union (&dest_nodes, - dest_state->entrance_nodes, - new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&dest_nodes); - goto free_return; - } - mctx->state_log[dest_str_idx] - = re_acquire_state_context (&err, dfa, &dest_nodes, context); - re_node_set_free (&dest_nodes); - if (BE (mctx->state_log[dest_str_idx] == NULL - && err != REG_NOERROR, 0)) - goto free_return; - } - /* We need to check recursively if the backreference can epsilon - transit. */ - if (subexp_len == 0 - && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) - { - err = check_subexp_matching_top (mctx, new_dest_nodes, - cur_str_idx); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - err = transit_state_bkref (mctx, new_dest_nodes); - if (BE (err != REG_NOERROR, 0)) - goto free_return; - } - } - } - err = REG_NOERROR; - free_return: - return err; -} - -/* Enumerate all the candidates which the backreference BKREF_NODE can match - at BKREF_STR_IDX, and register them by match_ctx_add_entry(). - Note that we might collect inappropriate candidates here. - However, the cost of checking them strictly here is too high, then we - delay these checking for prune_impossible_nodes(). */ - -static reg_errcode_t -internal_function -get_subexp (re_match_context_t *mctx, Idx bkref_node, Idx bkref_str_idx) -{ - const re_dfa_t *const dfa = mctx->dfa; - Idx subexp_num, sub_top_idx; - const char *buf = (const char *) re_string_get_buffer (&mctx->input); - /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ - Idx cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); - if (cache_idx != REG_MISSING) - { - const struct re_backref_cache_entry *entry - = mctx->bkref_ents + cache_idx; - do - if (entry->node == bkref_node) - return REG_NOERROR; /* We already checked it. */ - while (entry++->more); - } - - subexp_num = dfa->nodes[bkref_node].opr.idx; - - /* For each sub expression */ - for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) - { - reg_errcode_t err; - re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; - re_sub_match_last_t *sub_last; - Idx sub_last_idx, sl_str, bkref_str_off; - - if (dfa->nodes[sub_top->node].opr.idx != subexp_num) - continue; /* It isn't related. */ - - sl_str = sub_top->str_idx; - bkref_str_off = bkref_str_idx; - /* At first, check the last node of sub expressions we already - evaluated. */ - for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) - { - regoff_t sl_str_diff; - sub_last = sub_top->lasts[sub_last_idx]; - sl_str_diff = sub_last->str_idx - sl_str; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_diff > 0) - { - if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) - { - /* Not enough chars for a successful match. */ - if (bkref_str_off + sl_str_diff > mctx->input.len) - break; - - err = clean_state_log_if_needed (mctx, - bkref_str_off - + sl_str_diff); - if (BE (err != REG_NOERROR, 0)) - return err; - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) - /* We don't need to search this sub expression any more. */ - break; - } - bkref_str_off += sl_str_diff; - sl_str += sl_str_diff; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - - /* Reload buf, since the preceding call might have reallocated - the buffer. */ - buf = (const char *) re_string_get_buffer (&mctx->input); - - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - } - - if (sub_last_idx < sub_top->nlasts) - continue; - if (sub_last_idx > 0) - ++sl_str; - /* Then, search for the other last nodes of the sub expression. */ - for (; sl_str <= bkref_str_idx; ++sl_str) - { - Idx cls_node; - regoff_t sl_str_off; - const re_node_set *nodes; - sl_str_off = sl_str - sub_top->str_idx; - /* The matched string by the sub expression match with the substring - at the back reference? */ - if (sl_str_off > 0) - { - if (BE (bkref_str_off >= mctx->input.valid_len, 0)) - { - /* If we are at the end of the input, we cannot match. */ - if (bkref_str_off >= mctx->input.len) - break; - - err = extend_buffers (mctx); - if (BE (err != REG_NOERROR, 0)) - return err; - - buf = (const char *) re_string_get_buffer (&mctx->input); - } - if (buf [bkref_str_off++] != buf[sl_str - 1]) - break; /* We don't need to search this sub expression - any more. */ - } - if (mctx->state_log[sl_str] == NULL) - continue; - /* Does this state have a ')' of the sub expression? */ - nodes = &mctx->state_log[sl_str]->nodes; - cls_node = find_subexp_node (dfa, nodes, subexp_num, - OP_CLOSE_SUBEXP); - if (cls_node == REG_MISSING) - continue; /* No. */ - if (sub_top->path == NULL) - { - sub_top->path = calloc (sizeof (state_array_t), - sl_str - sub_top->str_idx + 1); - if (sub_top->path == NULL) - return REG_ESPACE; - } - /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node - in the current context? */ - err = check_arrival (mctx, sub_top->path, sub_top->node, - sub_top->str_idx, cls_node, sl_str, - OP_CLOSE_SUBEXP); - if (err == REG_NOMATCH) - continue; - if (BE (err != REG_NOERROR, 0)) - return err; - sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); - if (BE (sub_last == NULL, 0)) - return REG_ESPACE; - err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, - bkref_str_idx); - if (err == REG_NOMATCH) - continue; - } - } - return REG_NOERROR; -} - -/* Helper functions for get_subexp(). */ - -/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. - If it can arrive, register the sub expression expressed with SUB_TOP - and SUB_LAST. */ - -static reg_errcode_t -internal_function -get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, - re_sub_match_last_t *sub_last, Idx bkref_node, Idx bkref_str) -{ - reg_errcode_t err; - Idx to_idx; - /* Can the subexpression arrive the back reference? */ - err = check_arrival (mctx, &sub_last->path, sub_last->node, - sub_last->str_idx, bkref_node, bkref_str, - OP_OPEN_SUBEXP); - if (err != REG_NOERROR) - return err; - err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, - sub_last->str_idx); - if (BE (err != REG_NOERROR, 0)) - return err; - to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; - return clean_state_log_if_needed (mctx, to_idx); -} - -/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. - Search '(' if FL_OPEN, or search ')' otherwise. - TODO: This function isn't efficient... - Because there might be more than one nodes whose types are - OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all - nodes. - E.g. RE: (a){2} */ - -static Idx -internal_function -find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, - Idx subexp_idx, int type) -{ - Idx cls_idx; - for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) - { - Idx cls_node = nodes->elems[cls_idx]; - const re_token_t *node = dfa->nodes + cls_node; - if (node->type == type - && node->opr.idx == subexp_idx) - return cls_node; - } - return REG_MISSING; -} - -/* Check whether the node TOP_NODE at TOP_STR can arrive to the node - LAST_NODE at LAST_STR. We record the path onto PATH since it will be - heavily reused. - Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ - -static reg_errcode_t -internal_function -check_arrival (re_match_context_t *mctx, state_array_t *path, Idx top_node, - Idx top_str, Idx last_node, Idx last_str, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err = REG_NOERROR; - Idx subexp_num, backup_cur_idx, str_idx, null_cnt; - re_dfastate_t *cur_state = NULL; - re_node_set *cur_nodes, next_nodes; - re_dfastate_t **backup_state_log; - unsigned int context; - - subexp_num = dfa->nodes[top_node].opr.idx; - /* Extend the buffer if we need. */ - if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) - { - re_dfastate_t **new_array; - Idx old_alloc = path->alloc; - Idx new_alloc = old_alloc + last_str + mctx->max_mb_elem_len + 1; - if (BE (new_alloc < old_alloc, 0) - || BE (SIZE_MAX / sizeof (re_dfastate_t *) < new_alloc, 0)) - return REG_ESPACE; - new_array = re_realloc (path->array, re_dfastate_t *, new_alloc); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - path->array = new_array; - path->alloc = new_alloc; - memset (new_array + old_alloc, '\0', - sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); - } - - str_idx = path->next_idx ? path->next_idx : top_str; - - /* Temporary modify MCTX. */ - backup_state_log = mctx->state_log; - backup_cur_idx = mctx->input.cur_idx; - mctx->state_log = path->array; - mctx->input.cur_idx = str_idx; - - /* Setup initial node set. */ - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - if (str_idx == top_str) - { - err = re_node_set_init_1 (&next_nodes, top_node); - if (BE (err != REG_NOERROR, 0)) - return err; - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - else - { - cur_state = mctx->state_log[str_idx]; - if (cur_state && cur_state->has_backref) - { - err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); - if (BE (err != REG_NOERROR, 0)) - return err; - } - else - re_node_set_init_empty (&next_nodes); - } - if (str_idx == top_str || (cur_state && cur_state->has_backref)) - { - if (next_nodes.nelem) - { - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - } - - for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) - { - re_node_set_empty (&next_nodes); - if (mctx->state_log[str_idx + 1]) - { - err = re_node_set_merge (&next_nodes, - &mctx->state_log[str_idx + 1]->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - if (cur_state) - { - err = check_arrival_add_next_nodes (mctx, str_idx, - &cur_state->non_eps_nodes, - &next_nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - ++str_idx; - if (next_nodes.nelem) - { - err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - err = expand_bkref_cache (mctx, &next_nodes, str_idx, - subexp_num, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - } - context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); - cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); - if (BE (cur_state == NULL && err != REG_NOERROR, 0)) - { - re_node_set_free (&next_nodes); - return err; - } - mctx->state_log[str_idx] = cur_state; - null_cnt = cur_state == NULL ? null_cnt + 1 : 0; - } - re_node_set_free (&next_nodes); - cur_nodes = (mctx->state_log[last_str] == NULL ? NULL - : &mctx->state_log[last_str]->nodes); - path->next_idx = str_idx; - - /* Fix MCTX. */ - mctx->state_log = backup_state_log; - mctx->input.cur_idx = backup_cur_idx; - - /* Then check the current node set has the node LAST_NODE. */ - if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) - return REG_NOERROR; - - return REG_NOMATCH; -} - -/* Helper functions for check_arrival. */ - -/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them - to NEXT_NODES. - TODO: This function is similar to the functions transit_state*(), - however this function has many additional works. - Can't we unify them? */ - -static reg_errcode_t -internal_function -check_arrival_add_next_nodes (re_match_context_t *mctx, Idx str_idx, - re_node_set *cur_nodes, re_node_set *next_nodes) -{ - const re_dfa_t *const dfa = mctx->dfa; - bool ok; - Idx cur_idx; - reg_errcode_t err = REG_NOERROR; - re_node_set union_set; - re_node_set_init_empty (&union_set); - for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) - { - int naccepted = 0; - Idx cur_node = cur_nodes->elems[cur_idx]; -#ifdef DEBUG - re_token_type_t type = dfa->nodes[cur_node].type; - assert (!IS_EPSILON_NODE (type)); -#endif -#ifdef RE_ENABLE_I18N - /* If the node may accept `multi byte'. */ - if (dfa->nodes[cur_node].accept_mb) - { - naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, - str_idx); - if (naccepted > 1) - { - re_dfastate_t *dest_state; - Idx next_node = dfa->nexts[cur_node]; - Idx next_idx = str_idx + naccepted; - dest_state = mctx->state_log[next_idx]; - re_node_set_empty (&union_set); - if (dest_state) - { - err = re_node_set_merge (&union_set, &dest_state->nodes); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - ok = re_node_set_insert (&union_set, next_node); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - mctx->state_log[next_idx] = re_acquire_state (&err, dfa, - &union_set); - if (BE (mctx->state_log[next_idx] == NULL - && err != REG_NOERROR, 0)) - { - re_node_set_free (&union_set); - return err; - } - } - } -#endif /* RE_ENABLE_I18N */ - if (naccepted - || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) - { - ok = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); - if (BE (! ok, 0)) - { - re_node_set_free (&union_set); - return REG_ESPACE; - } - } - } - re_node_set_free (&union_set); - return REG_NOERROR; -} - -/* For all the nodes in CUR_NODES, add the epsilon closures of them to - CUR_NODES, however exclude the nodes which are: - - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. - - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. -*/ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, - Idx ex_subexp, int type) -{ - reg_errcode_t err; - Idx idx, outside_node; - re_node_set new_nodes; -#ifdef DEBUG - assert (cur_nodes->nelem); -#endif - err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); - if (BE (err != REG_NOERROR, 0)) - return err; - /* Create a new node set NEW_NODES with the nodes which are epsilon - closures of the node in CUR_NODES. */ - - for (idx = 0; idx < cur_nodes->nelem; ++idx) - { - Idx cur_node = cur_nodes->elems[idx]; - const re_node_set *eclosure = dfa->eclosures + cur_node; - outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); - if (outside_node == REG_MISSING) - { - /* There are no problematic nodes, just merge them. */ - err = re_node_set_merge (&new_nodes, eclosure); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - else - { - /* There are problematic nodes, re-calculate incrementally. */ - err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - { - re_node_set_free (&new_nodes); - return err; - } - } - } - re_node_set_free (cur_nodes); - *cur_nodes = new_nodes; - return REG_NOERROR; -} - -/* Helper function for check_arrival_expand_ecl. - Check incrementally the epsilon closure of TARGET, and if it isn't - problematic append it to DST_NODES. */ - -static reg_errcode_t -internal_function -check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, - Idx target, Idx ex_subexp, int type) -{ - Idx cur_node; - for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) - { - bool ok; - - if (dfa->nodes[cur_node].type == type - && dfa->nodes[cur_node].opr.idx == ex_subexp) - { - if (type == OP_CLOSE_SUBEXP) - { - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - } - break; - } - ok = re_node_set_insert (dst_nodes, cur_node); - if (BE (! ok, 0)) - return REG_ESPACE; - if (dfa->edests[cur_node].nelem == 0) - break; - if (dfa->edests[cur_node].nelem == 2) - { - reg_errcode_t err; - err = check_arrival_expand_ecl_sub (dfa, dst_nodes, - dfa->edests[cur_node].elems[1], - ex_subexp, type); - if (BE (err != REG_NOERROR, 0)) - return err; - } - cur_node = dfa->edests[cur_node].elems[0]; - } - return REG_NOERROR; -} - - -/* For all the back references in the current state, calculate the - destination of the back references by the appropriate entry - in MCTX->BKREF_ENTS. */ - -static reg_errcode_t -internal_function -expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, - Idx cur_str, Idx subexp_num, int type) -{ - const re_dfa_t *const dfa = mctx->dfa; - reg_errcode_t err; - Idx cache_idx_start = search_cur_bkref_entry (mctx, cur_str); - struct re_backref_cache_entry *ent; - - if (cache_idx_start == REG_MISSING) - return REG_NOERROR; - - restart: - ent = mctx->bkref_ents + cache_idx_start; - do - { - Idx to_idx, next_node; - - /* Is this entry ENT is appropriate? */ - if (!re_node_set_contains (cur_nodes, ent->node)) - continue; /* No. */ - - to_idx = cur_str + ent->subexp_to - ent->subexp_from; - /* Calculate the destination of the back reference, and append it - to MCTX->STATE_LOG. */ - if (to_idx == cur_str) - { - /* The backreference did epsilon transit, we must re-check all the - node in the current state. */ - re_node_set new_dests; - reg_errcode_t err2, err3; - next_node = dfa->edests[ent->node].elems[0]; - if (re_node_set_contains (cur_nodes, next_node)) - continue; - err = re_node_set_init_1 (&new_dests, next_node); - err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); - err3 = re_node_set_merge (cur_nodes, &new_dests); - re_node_set_free (&new_dests); - if (BE (err != REG_NOERROR || err2 != REG_NOERROR - || err3 != REG_NOERROR, 0)) - { - err = (err != REG_NOERROR ? err - : (err2 != REG_NOERROR ? err2 : err3)); - return err; - } - /* TODO: It is still inefficient... */ - goto restart; - } - else - { - re_node_set union_set; - next_node = dfa->nexts[ent->node]; - if (mctx->state_log[to_idx]) - { - bool ok; - if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, - next_node)) - continue; - err = re_node_set_init_copy (&union_set, - &mctx->state_log[to_idx]->nodes); - ok = re_node_set_insert (&union_set, next_node); - if (BE (err != REG_NOERROR || ! ok, 0)) - { - re_node_set_free (&union_set); - err = err != REG_NOERROR ? err : REG_ESPACE; - return err; - } - } - else - { - err = re_node_set_init_1 (&union_set, next_node); - if (BE (err != REG_NOERROR, 0)) - return err; - } - mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); - re_node_set_free (&union_set); - if (BE (mctx->state_log[to_idx] == NULL - && err != REG_NOERROR, 0)) - return err; - } - } - while (ent++->more); - return REG_NOERROR; -} - -/* Build transition table for the state. - Return true if successful. */ - -static bool -internal_function -build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) -{ - reg_errcode_t err; - Idx i, j; - int ch; - bool need_word_trtable = false; - bitset_word_t elem, mask; - bool dests_node_malloced = false; - bool dest_states_malloced = false; - Idx ndests; /* Number of the destination states from `state'. */ - re_dfastate_t **trtable; - re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; - re_node_set follows, *dests_node; - bitset_t *dests_ch; - bitset_t acceptable; - - struct dests_alloc - { - re_node_set dests_node[SBC_MAX]; - bitset_t dests_ch[SBC_MAX]; - } *dests_alloc; - - /* We build DFA states which corresponds to the destination nodes - from `state'. `dests_node[i]' represents the nodes which i-th - destination state contains, and `dests_ch[i]' represents the - characters which i-th destination state accepts. */ - if (__libc_use_alloca (sizeof (struct dests_alloc))) - dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); - else - { - dests_alloc = re_malloc (struct dests_alloc, 1); - if (BE (dests_alloc == NULL, 0)) - return false; - dests_node_malloced = true; - } - dests_node = dests_alloc->dests_node; - dests_ch = dests_alloc->dests_ch; - - /* Initialize transiton table. */ - state->word_trtable = state->trtable = NULL; - - /* At first, group all nodes belonging to `state' into several - destinations. */ - ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); - if (BE (! REG_VALID_NONZERO_INDEX (ndests), 0)) - { - if (dests_node_malloced) - free (dests_alloc); - if (ndests == 0) - { - state->trtable = (re_dfastate_t **) - calloc (sizeof (re_dfastate_t *), SBC_MAX); - return true; - } - return false; - } - - err = re_node_set_alloc (&follows, ndests + 1); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - - /* Avoid arithmetic overflow in size calculation. */ - if (BE ((((SIZE_MAX - (sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX) - / (3 * sizeof (re_dfastate_t *))) - < ndests), - 0)) - goto out_free; - - if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX - + ndests * 3 * sizeof (re_dfastate_t *))) - dest_states = (re_dfastate_t **) - alloca (ndests * 3 * sizeof (re_dfastate_t *)); - else - { - dest_states = (re_dfastate_t **) - malloc (ndests * 3 * sizeof (re_dfastate_t *)); - if (BE (dest_states == NULL, 0)) - { -out_free: - if (dest_states_malloced) - free (dest_states); - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - if (dests_node_malloced) - free (dests_alloc); - return false; - } - dest_states_malloced = true; - } - dest_states_word = dest_states + ndests; - dest_states_nl = dest_states_word + ndests; - bitset_empty (acceptable); - - /* Then build the states for all destinations. */ - for (i = 0; i < ndests; ++i) - { - Idx next_node; - re_node_set_empty (&follows); - /* Merge the follows of this destination states. */ - for (j = 0; j < dests_node[i].nelem; ++j) - { - next_node = dfa->nexts[dests_node[i].elems[j]]; - if (next_node != REG_MISSING) - { - err = re_node_set_merge (&follows, dfa->eclosures + next_node); - if (BE (err != REG_NOERROR, 0)) - goto out_free; - } - } - dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); - if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - /* If the new state has context constraint, - build appropriate states for these contexts. */ - if (dest_states[i]->has_constraint) - { - dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_WORD); - if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - - if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) - need_word_trtable = true; - - dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, - CONTEXT_NEWLINE); - if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) - goto out_free; - } - else - { - dest_states_word[i] = dest_states[i]; - dest_states_nl[i] = dest_states[i]; - } - bitset_merge (acceptable, dests_ch[i]); - } - - if (!BE (need_word_trtable, 0)) - { - /* We don't care about whether the following character is a word - character, or we are in a single-byte character set so we can - discern by looking at the character code: allocate a - 256-entry transition table. */ - trtable = state->trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - if (dfa->word_char[i] & mask) - trtable[ch] = dest_states_word[j]; - else - trtable[ch] = dest_states[j]; - } - } - else - { - /* We care about whether the following character is a word - character, and we are in a multi-byte character set: discern - by looking at the character code: build two 256-entry - transition tables, one starting at trtable[0] and one - starting at trtable[SBC_MAX]. */ - trtable = state->word_trtable = - (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); - if (BE (trtable == NULL, 0)) - goto out_free; - - /* For all characters ch...: */ - for (i = 0; i < BITSET_WORDS; ++i) - for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; - elem; - mask <<= 1, elem >>= 1, ++ch) - if (BE (elem & 1, 0)) - { - /* There must be exactly one destination which accepts - character ch. See group_nodes_into_DFAstates. */ - for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) - ; - - /* j-th destination accepts the word character ch. */ - trtable[ch] = dest_states[j]; - trtable[ch + SBC_MAX] = dest_states_word[j]; - } - } - - /* new line */ - if (bitset_contain (acceptable, NEWLINE_CHAR)) - { - /* The current state accepts newline character. */ - for (j = 0; j < ndests; ++j) - if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) - { - /* k-th destination accepts newline character. */ - trtable[NEWLINE_CHAR] = dest_states_nl[j]; - if (need_word_trtable) - trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; - /* There must be only one destination which accepts - newline. See group_nodes_into_DFAstates. */ - break; - } - } - - if (dest_states_malloced) - free (dest_states); - - re_node_set_free (&follows); - for (i = 0; i < ndests; ++i) - re_node_set_free (dests_node + i); - - if (dests_node_malloced) - free (dests_alloc); - - return true; -} - -/* Group all nodes belonging to STATE into several destinations. - Then for all destinations, set the nodes belonging to the destination - to DESTS_NODE[i] and set the characters accepted by the destination - to DEST_CH[i]. This function return the number of destinations. */ - -static Idx -internal_function -group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, - re_node_set *dests_node, bitset_t *dests_ch) -{ - reg_errcode_t err; - bool ok; - Idx i, j, k; - Idx ndests; /* Number of the destinations from `state'. */ - bitset_t accepts; /* Characters a node can accept. */ - const re_node_set *cur_nodes = &state->nodes; - bitset_empty (accepts); - ndests = 0; - - /* For all the nodes belonging to `state', */ - for (i = 0; i < cur_nodes->nelem; ++i) - { - re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; - re_token_type_t type = node->type; - unsigned int constraint = node->constraint; - - /* Enumerate all single byte character this node can accept. */ - if (type == CHARACTER) - bitset_set (accepts, node->opr.c); - else if (type == SIMPLE_BRACKET) - { - bitset_merge (accepts, node->opr.sbcset); - } - else if (type == OP_PERIOD) - { -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - bitset_merge (accepts, dfa->sb_char); - else -#endif - bitset_set_all (accepts); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#ifdef RE_ENABLE_I18N - else if (type == OP_UTF8_PERIOD) - { - if (ASCII_CHARS % BITSET_WORD_BITS == 0) - memset (accepts, -1, ASCII_CHARS / CHAR_BIT); - else - bitset_merge (accepts, utf8_sb_map); - if (!(dfa->syntax & RE_DOT_NEWLINE)) - bitset_clear (accepts, '\n'); - if (dfa->syntax & RE_DOT_NOT_NULL) - bitset_clear (accepts, '\0'); - } -#endif - else - continue; - - /* Check the `accepts' and sift the characters which are not - match it the context. */ - if (constraint) - { - if (constraint & NEXT_NEWLINE_CONSTRAINT) - { - bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); - bitset_empty (accepts); - if (accepts_newline) - bitset_set (accepts, NEWLINE_CHAR); - else - continue; - } - if (constraint & NEXT_ENDBUF_CONSTRAINT) - { - bitset_empty (accepts); - continue; - } - - if (constraint & NEXT_WORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && !node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= dfa->word_char[j]); - if (!any_set) - continue; - } - if (constraint & NEXT_NOTWORD_CONSTRAINT) - { - bitset_word_t any_set = 0; - if (type == CHARACTER && node->word_char) - { - bitset_empty (accepts); - continue; - } -#ifdef RE_ENABLE_I18N - if (dfa->mb_cur_max > 1) - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); - else -#endif - for (j = 0; j < BITSET_WORDS; ++j) - any_set |= (accepts[j] &= ~dfa->word_char[j]); - if (!any_set) - continue; - } - } - - /* Then divide `accepts' into DFA states, or create a new - state. Above, we make sure that accepts is not empty. */ - for (j = 0; j < ndests; ++j) - { - bitset_t intersec; /* Intersection sets, see below. */ - bitset_t remains; - /* Flags, see below. */ - bitset_word_t has_intersec, not_subset, not_consumed; - - /* Optimization, skip if this state doesn't accept the character. */ - if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) - continue; - - /* Enumerate the intersection set of this state and `accepts'. */ - has_intersec = 0; - for (k = 0; k < BITSET_WORDS; ++k) - has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; - /* And skip if the intersection set is empty. */ - if (!has_intersec) - continue; - - /* Then check if this state is a subset of `accepts'. */ - not_subset = not_consumed = 0; - for (k = 0; k < BITSET_WORDS; ++k) - { - not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; - not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; - } - - /* If this state isn't a subset of `accepts', create a - new group state, which has the `remains'. */ - if (not_subset) - { - bitset_copy (dests_ch[ndests], remains); - bitset_copy (dests_ch[j], intersec); - err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - } - - /* Put the position in the current group. */ - ok = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); - if (BE (! ok, 0)) - goto error_return; - - /* If all characters are consumed, go to next node. */ - if (!not_consumed) - break; - } - /* Some characters remain, create a new group. */ - if (j == ndests) - { - bitset_copy (dests_ch[ndests], accepts); - err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); - if (BE (err != REG_NOERROR, 0)) - goto error_return; - ++ndests; - bitset_empty (accepts); - } - } - return ndests; - error_return: - for (j = 0; j < ndests; ++j) - re_node_set_free (dests_node + j); - return REG_MISSING; -} - -#ifdef RE_ENABLE_I18N -/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. - Return the number of the bytes the node accepts. - STR_IDX is the current index of the input string. - - This function handles the nodes which can accept one character, or - one collating element like '.', '[a-z]', opposite to the other nodes - can only accept one byte. */ - -static int -internal_function -check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx, - const re_string_t *input, Idx str_idx) -{ - const re_token_t *node = dfa->nodes + node_idx; - int char_len, elem_len; - Idx i; - - if (BE (node->type == OP_UTF8_PERIOD, 0)) - { - unsigned char c = re_string_byte_at (input, str_idx), d; - if (BE (c < 0xc2, 1)) - return 0; - - if (str_idx + 2 > input->len) - return 0; - - d = re_string_byte_at (input, str_idx + 1); - if (c < 0xe0) - return (d < 0x80 || d > 0xbf) ? 0 : 2; - else if (c < 0xf0) - { - char_len = 3; - if (c == 0xe0 && d < 0xa0) - return 0; - } - else if (c < 0xf8) - { - char_len = 4; - if (c == 0xf0 && d < 0x90) - return 0; - } - else if (c < 0xfc) - { - char_len = 5; - if (c == 0xf8 && d < 0x88) - return 0; - } - else if (c < 0xfe) - { - char_len = 6; - if (c == 0xfc && d < 0x84) - return 0; - } - else - return 0; - - if (str_idx + char_len > input->len) - return 0; - - for (i = 1; i < char_len; ++i) - { - d = re_string_byte_at (input, str_idx + i); - if (d < 0x80 || d > 0xbf) - return 0; - } - return char_len; - } - - char_len = re_string_char_size_at (input, str_idx); - if (node->type == OP_PERIOD) - { - if (char_len <= 1) - return 0; - /* FIXME: I don't think this if is needed, as both '\n' - and '\0' are char_len == 1. */ - /* '.' accepts any one character except the following two cases. */ - if ((!(dfa->syntax & RE_DOT_NEWLINE) && - re_string_byte_at (input, str_idx) == '\n') || - ((dfa->syntax & RE_DOT_NOT_NULL) && - re_string_byte_at (input, str_idx) == '\0')) - return 0; - return char_len; - } - - elem_len = re_string_elem_size_at (input, str_idx); - if ((elem_len <= 1 && char_len <= 1) || char_len == 0) - return 0; - - if (node->type == COMPLEX_BRACKET) - { - const re_charset_t *cset = node->opr.mbcset; -# ifdef _LIBC - const unsigned char *pin - = ((const unsigned char *) re_string_get_buffer (input) + str_idx); - Idx j; - uint32_t nrules; -# endif /* _LIBC */ - int match_len = 0; - wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) - ? re_string_wchar_at (input, str_idx) : 0); - - /* match with multibyte character? */ - for (i = 0; i < cset->nmbchars; ++i) - if (wc == cset->mbchars[i]) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - /* match with character_class? */ - for (i = 0; i < cset->nchar_classes; ++i) - { - wctype_t wt = cset->char_classes[i]; - if (__iswctype (wc, wt)) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - -# ifdef _LIBC - nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules != 0) - { - unsigned int in_collseq = 0; - const int32_t *table, *indirect; - const unsigned char *weights, *extra; - const char *collseqwc; - int32_t idx; - /* This #include defines a local function! */ -# include - - /* match with collating_symbol? */ - if (cset->ncoll_syms) - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - for (i = 0; i < cset->ncoll_syms; ++i) - { - const unsigned char *coll_sym = extra + cset->coll_syms[i]; - /* Compare the length of input collating element and - the length of current collating element. */ - if (*coll_sym != elem_len) - continue; - /* Compare each bytes. */ - for (j = 0; j < *coll_sym; j++) - if (pin[j] != coll_sym[1 + j]) - break; - if (j == *coll_sym) - { - /* Match if every bytes is equal. */ - match_len = j; - goto check_node_accept_bytes_match; - } - } - - if (cset->nranges) - { - if (elem_len <= char_len) - { - collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); - in_collseq = __collseq_table_lookup (collseqwc, wc); - } - else - in_collseq = find_collation_sequence_value (pin, elem_len); - } - /* match with range expression? */ - for (i = 0; i < cset->nranges; ++i) - if (cset->range_starts[i] <= in_collseq - && in_collseq <= cset->range_ends[i]) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - - /* match with equivalence_class? */ - if (cset->nequiv_classes) - { - const unsigned char *cp = pin; - table = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); - weights = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); - extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); - indirect = (const int32_t *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); - idx = findidx (&cp); - if (idx > 0) - for (i = 0; i < cset->nequiv_classes; ++i) - { - int32_t equiv_class_idx = cset->equiv_classes[i]; - size_t weight_len = weights[idx]; - if (weight_len == weights[equiv_class_idx]) - { - Idx cnt = 0; - while (cnt <= weight_len - && (weights[equiv_class_idx + 1 + cnt] - == weights[idx + 1 + cnt])) - ++cnt; - if (cnt > weight_len) - { - match_len = elem_len; - goto check_node_accept_bytes_match; - } - } - } - } - } - else -# endif /* _LIBC */ - { - /* match with range expression? */ -#if __GNUC__ >= 2 && ! (__STDC_VERSION__ < 199901L && __STRICT_ANSI__) - wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'}; -#else - wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; - cmp_buf[2] = wc; -#endif - for (i = 0; i < cset->nranges; ++i) - { - cmp_buf[0] = cset->range_starts[i]; - cmp_buf[4] = cset->range_ends[i]; - if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 - && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) - { - match_len = char_len; - goto check_node_accept_bytes_match; - } - } - } - check_node_accept_bytes_match: - if (!cset->non_match) - return match_len; - else - { - if (match_len > 0) - return 0; - else - return (elem_len > char_len) ? elem_len : char_len; - } - } - return 0; -} - -# ifdef _LIBC -static unsigned int -internal_function -find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) -{ - uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); - if (nrules == 0) - { - if (mbs_len == 1) - { - /* No valid character. Match it as a single byte character. */ - const unsigned char *collseq = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); - return collseq[mbs[0]]; - } - return UINT_MAX; - } - else - { - int32_t idx; - const unsigned char *extra = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); - int32_t extrasize = (const unsigned char *) - _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; - - for (idx = 0; idx < extrasize;) - { - int mbs_cnt; - bool found = false; - int32_t elem_mbs_len; - /* Skip the name of collating element name. */ - idx = idx + extra[idx] + 1; - elem_mbs_len = extra[idx++]; - if (mbs_len == elem_mbs_len) - { - for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) - if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) - break; - if (mbs_cnt == elem_mbs_len) - /* Found the entry. */ - found = true; - } - /* Skip the byte sequence of the collating element. */ - idx += elem_mbs_len; - /* Adjust for the alignment. */ - idx = (idx + 3) & ~3; - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - /* Skip the wide char sequence of the collating element. */ - idx = idx + sizeof (uint32_t) * (extra[idx] + 1); - /* If we found the entry, return the sequence value. */ - if (found) - return *(uint32_t *) (extra + idx); - /* Skip the collation sequence value. */ - idx += sizeof (uint32_t); - } - return UINT_MAX; - } -} -# endif /* _LIBC */ -#endif /* RE_ENABLE_I18N */ - -/* Check whether the node accepts the byte which is IDX-th - byte of the INPUT. */ - -static bool -internal_function -check_node_accept (const re_match_context_t *mctx, const re_token_t *node, - Idx idx) -{ - unsigned char ch; - ch = re_string_byte_at (&mctx->input, idx); - switch (node->type) - { - case CHARACTER: - if (node->opr.c != ch) - return false; - break; - - case SIMPLE_BRACKET: - if (!bitset_contain (node->opr.sbcset, ch)) - return false; - break; - -#ifdef RE_ENABLE_I18N - case OP_UTF8_PERIOD: - if (ch >= ASCII_CHARS) - return false; - /* FALLTHROUGH */ -#endif - case OP_PERIOD: - if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) - || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) - return false; - break; - - default: - return false; - } - - if (node->constraint) - { - /* The node has constraints. Check whether the current context - satisfies the constraints. */ - unsigned int context = re_string_context_at (&mctx->input, idx, - mctx->eflags); - if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) - return false; - } - - return true; -} - -/* Extend the buffers, if the buffers have run out. */ - -static reg_errcode_t -internal_function -extend_buffers (re_match_context_t *mctx) -{ - reg_errcode_t ret; - re_string_t *pstr = &mctx->input; - - /* Avoid overflow. */ - if (BE (SIZE_MAX / 2 / sizeof (re_dfastate_t *) <= pstr->bufs_len, 0)) - return REG_ESPACE; - - /* Double the lengthes of the buffers. */ - ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); - if (BE (ret != REG_NOERROR, 0)) - return ret; - - if (mctx->state_log != NULL) - { - /* And double the length of state_log. */ - /* XXX We have no indication of the size of this buffer. If this - allocation fail we have no indication that the state_log array - does not have the right size. */ - re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, - pstr->bufs_len + 1); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->state_log = new_array; - } - - /* Then reconstruct the buffers. */ - if (pstr->icase) - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - { - ret = build_wcs_upper_buffer (pstr); - if (BE (ret != REG_NOERROR, 0)) - return ret; - } - else -#endif /* RE_ENABLE_I18N */ - build_upper_buffer (pstr); - } - else - { -#ifdef RE_ENABLE_I18N - if (pstr->mb_cur_max > 1) - build_wcs_buffer (pstr); - else -#endif /* RE_ENABLE_I18N */ - { - if (pstr->trans != NULL) - re_string_translate_buffer (pstr); - } - } - return REG_NOERROR; -} - - -/* Functions for matching context. */ - -/* Initialize MCTX. */ - -static reg_errcode_t -internal_function -match_ctx_init (re_match_context_t *mctx, int eflags, Idx n) -{ - mctx->eflags = eflags; - mctx->match_last = REG_MISSING; - if (n > 0) - { - /* Avoid overflow. */ - size_t max_object_size = - MAX (sizeof (struct re_backref_cache_entry), - sizeof (re_sub_match_top_t *)); - if (BE (SIZE_MAX / max_object_size < n, 0)) - return REG_ESPACE; - - mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); - mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); - if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) - return REG_ESPACE; - } - /* Already zero-ed by the caller. - else - mctx->bkref_ents = NULL; - mctx->nbkref_ents = 0; - mctx->nsub_tops = 0; */ - mctx->abkref_ents = n; - mctx->max_mb_elem_len = 1; - mctx->asub_tops = n; - return REG_NOERROR; -} - -/* Clean the entries which depend on the current input in MCTX. - This function must be invoked when the matcher changes the start index - of the input, or changes the input string. */ - -static void -internal_function -match_ctx_clean (re_match_context_t *mctx) -{ - Idx st_idx; - for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) - { - Idx sl_idx; - re_sub_match_top_t *top = mctx->sub_tops[st_idx]; - for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) - { - re_sub_match_last_t *last = top->lasts[sl_idx]; - re_free (last->path.array); - re_free (last); - } - re_free (top->lasts); - if (top->path) - { - re_free (top->path->array); - re_free (top->path); - } - free (top); - } - - mctx->nsub_tops = 0; - mctx->nbkref_ents = 0; -} - -/* Free all the memory associated with MCTX. */ - -static void -internal_function -match_ctx_free (re_match_context_t *mctx) -{ - /* First, free all the memory associated with MCTX->SUB_TOPS. */ - match_ctx_clean (mctx); - re_free (mctx->sub_tops); - re_free (mctx->bkref_ents); -} - -/* Add a new backreference entry to MCTX. - Note that we assume that caller never call this function with duplicate - entry, and call with STR_IDX which isn't smaller than any existing entry. -*/ - -static reg_errcode_t -internal_function -match_ctx_add_entry (re_match_context_t *mctx, Idx node, Idx str_idx, Idx from, - Idx to) -{ - if (mctx->nbkref_ents >= mctx->abkref_ents) - { - struct re_backref_cache_entry* new_entry; - new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, - mctx->abkref_ents * 2); - if (BE (new_entry == NULL, 0)) - { - re_free (mctx->bkref_ents); - return REG_ESPACE; - } - mctx->bkref_ents = new_entry; - memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', - sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); - mctx->abkref_ents *= 2; - } - if (mctx->nbkref_ents > 0 - && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) - mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; - - mctx->bkref_ents[mctx->nbkref_ents].node = node; - mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; - mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; - mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; - - /* This is a cache that saves negative results of check_dst_limits_calc_pos. - If bit N is clear, means that this entry won't epsilon-transition to - an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If - it is set, check_dst_limits_calc_pos_1 will recurse and try to find one - such node. - - A backreference does not epsilon-transition unless it is empty, so set - to all zeros if FROM != TO. */ - mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map - = (from == to ? -1 : 0); - - mctx->bkref_ents[mctx->nbkref_ents++].more = 0; - if (mctx->max_mb_elem_len < to - from) - mctx->max_mb_elem_len = to - from; - return REG_NOERROR; -} - -/* Return the first entry with the same str_idx, or REG_MISSING if none is - found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ - -static Idx -internal_function -search_cur_bkref_entry (const re_match_context_t *mctx, Idx str_idx) -{ - Idx left, right, mid, last; - last = right = mctx->nbkref_ents; - for (left = 0; left < right;) - { - mid = (left + right) / 2; - if (mctx->bkref_ents[mid].str_idx < str_idx) - left = mid + 1; - else - right = mid; - } - if (left < last && mctx->bkref_ents[left].str_idx == str_idx) - return left; - else - return REG_MISSING; -} - -/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches - at STR_IDX. */ - -static reg_errcode_t -internal_function -match_ctx_add_subtop (re_match_context_t *mctx, Idx node, Idx str_idx) -{ -#ifdef DEBUG - assert (mctx->sub_tops != NULL); - assert (mctx->asub_tops > 0); -#endif - if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) - { - Idx new_asub_tops = mctx->asub_tops * 2; - re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, - re_sub_match_top_t *, - new_asub_tops); - if (BE (new_array == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops = new_array; - mctx->asub_tops = new_asub_tops; - } - mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); - if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) - return REG_ESPACE; - mctx->sub_tops[mctx->nsub_tops]->node = node; - mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; - return REG_NOERROR; -} - -/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches - at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ - -static re_sub_match_last_t * -internal_function -match_ctx_add_sublast (re_sub_match_top_t *subtop, Idx node, Idx str_idx) -{ - re_sub_match_last_t *new_entry; - if (BE (subtop->nlasts == subtop->alasts, 0)) - { - Idx new_alasts = 2 * subtop->alasts + 1; - re_sub_match_last_t **new_array = re_realloc (subtop->lasts, - re_sub_match_last_t *, - new_alasts); - if (BE (new_array == NULL, 0)) - return NULL; - subtop->lasts = new_array; - subtop->alasts = new_alasts; - } - new_entry = calloc (1, sizeof (re_sub_match_last_t)); - if (BE (new_entry != NULL, 1)) - { - subtop->lasts[subtop->nlasts] = new_entry; - new_entry->node = node; - new_entry->str_idx = str_idx; - ++subtop->nlasts; - } - return new_entry; -} - -static void -internal_function -sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, - re_dfastate_t **limited_sts, Idx last_node, Idx last_str_idx) -{ - sctx->sifted_states = sifted_sts; - sctx->limited_states = limited_sts; - sctx->last_node = last_node; - sctx->last_str_idx = last_str_idx; - re_node_set_init_empty (&sctx->limits); -} diff --git a/usr/src/lib/libparted/common/lib/rpmatch.c b/usr/src/lib/libparted/common/lib/rpmatch.c deleted file mode 100644 index e5f79f8228..0000000000 --- a/usr/src/lib/libparted/common/lib/rpmatch.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Determine whether string value is affirmation or negative response - according to current locale's data. - - Copyright (C) 1996, 1998, 2000, 2002, 2003, 2006 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# include -# include -# include "gettext.h" -# define _(msgid) gettext (msgid) - -static int -try (const char *response, const char *pattern, const int match, - const int nomatch, const char **lastp, regex_t *re) -{ - if (pattern != *lastp) - { - /* The pattern has changed. */ - if (*lastp) - { - /* Free the old compiled pattern. */ - regfree (re); - *lastp = NULL; - } - /* Compile the pattern and cache it for future runs. */ - if (regcomp (re, pattern, REG_EXTENDED) != 0) - return -1; - *lastp = pattern; - } - - /* See if the regular expression matches RESPONSE. */ - return regexec (re, response, 0, NULL, 0) == 0 ? match : nomatch; -} -#endif - - -int -rpmatch (const char *response) -{ -#if ENABLE_NLS - /* Match against one of the response patterns, compiling the pattern - first if necessary. */ - - /* We cache the response patterns and compiled regexps here. */ - static const char *yesexpr, *noexpr; - static regex_t yesre, nore; - int result; - - return ((result = try (response, _("^[yY]"), 1, 0, - &yesexpr, &yesre)) - ? result - : try (response, _("^[nN]"), 0, -1, &noexpr, &nore)); -#else - /* Test against "^[yY]" and "^[nN]", hardcoded to avoid requiring regex */ - return (*response == 'y' || *response == 'Y' ? 1 - : *response == 'n' || *response == 'N' ? 0 : -1); -#endif -} diff --git a/usr/src/lib/libparted/common/lib/safe-read.c b/usr/src/lib/libparted/common/lib/safe-read.c deleted file mode 100644 index b7bf1d5cd6..0000000000 --- a/usr/src/lib/libparted/common/lib/safe-read.c +++ /dev/null @@ -1,78 +0,0 @@ -/* An interface to read and write that retries after interrupts. - - Copyright (C) 1993, 1994, 1998, 2002, 2003, 2004, 2005, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#ifdef SAFE_WRITE -# include "safe-write.h" -#else -# include "safe-read.h" -#endif - -/* Get ssize_t. */ -#include -#include - -#include - -#ifdef EINTR -# define IS_EINTR(x) ((x) == EINTR) -#else -# define IS_EINTR(x) 0 -#endif - -#include - -#ifdef SAFE_WRITE -# define safe_rw safe_write -# define rw write -#else -# define safe_rw safe_read -# define rw read -# undef const -# define const /* empty */ -#endif - -/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if - interrupted. Return the actual number of bytes read(written), zero for EOF, - or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error. */ -size_t -safe_rw (int fd, void const *buf, size_t count) -{ - /* Work around a bug in Tru64 5.1. Attempting to read more than - INT_MAX bytes fails with errno == EINVAL. See - . - When decreasing COUNT, keep it block-aligned. */ - enum { BUGGY_READ_MAXIMUM = INT_MAX & ~8191 }; - - for (;;) - { - ssize_t result = rw (fd, buf, count); - - if (0 <= result) - return result; - else if (IS_EINTR (errno)) - continue; - else if (errno == EINVAL && BUGGY_READ_MAXIMUM < count) - count = BUGGY_READ_MAXIMUM; - else - return result; - } -} diff --git a/usr/src/lib/libparted/common/lib/safe-read.h b/usr/src/lib/libparted/common/lib/safe-read.h deleted file mode 100644 index 3451955ad4..0000000000 --- a/usr/src/lib/libparted/common/lib/safe-read.h +++ /dev/null @@ -1,35 +0,0 @@ -/* An interface to read() that retries after interrupts. - Copyright (C) 2002, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -#define SAFE_READ_ERROR ((size_t) -1) - -/* Read up to COUNT bytes at BUF from descriptor FD, retrying if interrupted. - Return the actual number of bytes read, zero for EOF, or SAFE_READ_ERROR - upon error. */ -extern size_t safe_read (int fd, void *buf, size_t count); - - -#ifdef __cplusplus -} -#endif diff --git a/usr/src/lib/libparted/common/lib/safe-write.c b/usr/src/lib/libparted/common/lib/safe-write.c deleted file mode 100644 index 4c375a6ca1..0000000000 --- a/usr/src/lib/libparted/common/lib/safe-write.c +++ /dev/null @@ -1,19 +0,0 @@ -/* An interface to write that retries after interrupts. - Copyright (C) 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#define SAFE_WRITE -#include "safe-read.c" diff --git a/usr/src/lib/libparted/common/lib/safe-write.h b/usr/src/lib/libparted/common/lib/safe-write.h deleted file mode 100644 index c194636209..0000000000 --- a/usr/src/lib/libparted/common/lib/safe-write.h +++ /dev/null @@ -1,25 +0,0 @@ -/* An interface to write() that retries after interrupts. - Copyright (C) 2002 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#define SAFE_WRITE_ERROR ((size_t) -1) - -/* Write up to COUNT bytes at BUF to descriptor FD, retrying if interrupted. - Return the actual number of bytes written, zero for EOF, or SAFE_WRITE_ERROR - upon error. */ -extern size_t safe_write (int fd, const void *buf, size_t count); diff --git a/usr/src/lib/libparted/common/lib/strcspn.c b/usr/src/lib/libparted/common/lib/strcspn.c deleted file mode 100644 index 5a8d6f9c17..0000000000 --- a/usr/src/lib/libparted/common/lib/strcspn.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 1991, 1994, 1996-1997, 2002-2003, 2005-2006 Free Software Foundation, Inc. - - NOTE: The canonical source of this file is maintained with the GNU C Library. - Bugs can be reported to bug-glibc@gnu.org. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include -#include - -#undef strcspn - -/* Return the length of the maximum initial segment of S - which contains no characters from REJECT. */ -size_t -strcspn (const char *s, const char *reject) -{ - size_t count = 0; - - while (*s != '\0') - if (strchr (reject, *s++) == NULL) - ++count; - else - return count; - - return count; -} diff --git a/usr/src/lib/libparted/common/lib/stripslash.c b/usr/src/lib/libparted/common/lib/stripslash.c deleted file mode 100644 index 342d497c89..0000000000 --- a/usr/src/lib/libparted/common/lib/stripslash.c +++ /dev/null @@ -1,45 +0,0 @@ -/* stripslash.c -- remove redundant trailing slashes from a file name - - Copyright (C) 1990, 2001, 2003-2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "dirname.h" - -/* Remove trailing slashes from FILE. Return true if a trailing slash - was removed. This is useful when using file name completion from a - shell that adds a "/" after directory names (such as tcsh and - bash), because on symlinks to directories, several system calls - have different semantics according to whether a trailing slash is - present. */ - -bool -strip_trailing_slashes (char *file) -{ - char *base = last_component (file); - char *base_lim; - bool had_slash; - - /* last_component returns "" for file system roots, but we need to turn - `///' into `/'. */ - if (! *base) - base = file; - base_lim = base + base_len (base); - had_slash = (*base_lim != '\0'); - *base_lim = '\0'; - return had_slash; -} diff --git a/usr/src/lib/libparted/common/lib/strndup.c b/usr/src/lib/libparted/common/lib/strndup.c deleted file mode 100644 index 3a1b0eae2e..0000000000 --- a/usr/src/lib/libparted/common/lib/strndup.c +++ /dev/null @@ -1,37 +0,0 @@ -/* A replacement function, for systems that lack strndup. - - Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2005, 2006, 2007 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include - -#include - -char * -strndup (char const *s, size_t n) -{ - size_t len = strnlen (s, n); - char *new = malloc (len + 1); - - if (new == NULL) - return NULL; - - new[len] = '\0'; - return memcpy (new, s, len); -} diff --git a/usr/src/lib/libparted/common/lib/version-etc-fsf.c b/usr/src/lib/libparted/common/lib/version-etc-fsf.c deleted file mode 100644 index f25eb653ea..0000000000 --- a/usr/src/lib/libparted/common/lib/version-etc-fsf.c +++ /dev/null @@ -1,31 +0,0 @@ -/* Variable with FSF copyright information, for version-etc. - Copyright (C) 1999-2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#include - -/* Specification. */ -#include "version-etc.h" - -/* Default copyright goes to the FSF. */ - -const char version_etc_copyright[] = - /* Do *not* mark this string for translation. %s is a copyright - symbol suitable for this locale, and %d is the copyright - year. */ - "Copyright %s %d Free Software Foundation, Inc."; diff --git a/usr/src/lib/libparted/common/lib/version-etc.c b/usr/src/lib/libparted/common/lib/version-etc.c deleted file mode 100644 index 14f101e553..0000000000 --- a/usr/src/lib/libparted/common/lib/version-etc.c +++ /dev/null @@ -1,173 +0,0 @@ -/* Utility to help print --version output in a consistent format. - Copyright (C) 1999-2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#include - -/* Specification. */ -#include "version-etc.h" - -#include -#include -#include - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -enum { COPYRIGHT_YEAR = 2007 }; - -/* Like version_etc, below, but with the NULL-terminated author list - provided via a variable of type va_list. */ -void -version_etc_va (FILE *stream, - const char *command_name, const char *package, - const char *version, va_list authors) -{ - size_t n_authors; - - /* Count the number of authors. */ - { - va_list tmp_authors; - - va_copy (tmp_authors, authors); - - n_authors = 0; - while (va_arg (tmp_authors, const char *) != NULL) - ++n_authors; - } - - if (command_name) - fprintf (stream, "%s (%s) %s\n", command_name, package, version); - else - fprintf (stream, "%s %s\n", package, version); - - /* TRANSLATORS: Translate "(C)" to the copyright symbol - (C-in-a-circle), if this symbol is available in the user's - locale. Otherwise, do not translate "(C)"; leave it as-is. */ - fprintf (stream, version_etc_copyright, _("(C)"), COPYRIGHT_YEAR); - - fputs (_("\ -\n\ -License GPLv3+: GNU GPL version 3 or later \n\ -This is free software: you are free to change and redistribute it.\n\ -There is NO WARRANTY, to the extent permitted by law.\n\ -\n\ -"), - stream); - - switch (n_authors) - { - case 0: - /* The caller must provide at least one author name. */ - abort (); - case 1: - /* TRANSLATORS: %s denotes an author name. */ - vfprintf (stream, _("Written by %s.\n"), authors); - break; - case 2: - /* TRANSLATORS: Each %s denotes an author name. */ - vfprintf (stream, _("Written by %s and %s.\n"), authors); - break; - case 3: - /* TRANSLATORS: Each %s denotes an author name. */ - vfprintf (stream, _("Written by %s, %s, and %s.\n"), authors); - break; - case 4: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("Written by %s, %s, %s,\nand %s.\n"), authors); - break; - case 5: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("Written by %s, %s, %s,\n%s, and %s.\n"), authors); - break; - case 6: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, and %s.\n"), - authors); - break; - case 7: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("Written by %s, %s, %s,\n%s, %s, %s, and %s.\n"), - authors); - break; - case 8: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("\ -Written by %s, %s, %s,\n%s, %s, %s, %s,\nand %s.\n"), - authors); - break; - case 9: - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("\ -Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, and %s.\n"), - authors); - break; - default: - /* 10 or more authors. Use an abbreviation, since the human reader - will probably not want to read the entire list anyway. */ - /* TRANSLATORS: Each %s denotes an author name. - You can use line breaks, estimating that each author name occupies - ca. 16 screen columns and that a screen line has ca. 80 columns. */ - vfprintf (stream, _("\ -Written by %s, %s, %s,\n%s, %s, %s, %s,\n%s, %s, and others.\n"), - authors); - break; - } - va_end (authors); -} - - -/* Display the --version information the standard way. - - If COMMAND_NAME is NULL, the PACKAGE is asumed to be the name of - the program. The formats are therefore: - - PACKAGE VERSION - - or - - COMMAND_NAME (PACKAGE) VERSION. - - The author names are passed as separate arguments, with an additional - NULL argument at the end. */ -void -version_etc (FILE *stream, - const char *command_name, const char *package, - const char *version, /* const char *author1, ...*/ ...) -{ - va_list authors; - - va_start (authors, version); - version_etc_va (stream, command_name, package, version, authors); -} diff --git a/usr/src/lib/libparted/common/lib/version-etc.h b/usr/src/lib/libparted/common/lib/version-etc.h deleted file mode 100644 index 84da535001..0000000000 --- a/usr/src/lib/libparted/common/lib/version-etc.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Utility to help print --version output in a consistent format. - Copyright (C) 1999, 2003, 2005 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Jim Meyering. */ - -#ifndef VERSION_ETC_H -# define VERSION_ETC_H 1 - -# include -# include - -extern const char version_etc_copyright[]; - -extern void version_etc_va (FILE *stream, - const char *command_name, const char *package, - const char *version, va_list authors); - -extern void version_etc (FILE *stream, - const char *command_name, const char *package, - const char *version, - /* const char *author1, ...*/ ...); - -#endif /* VERSION_ETC_H */ diff --git a/usr/src/lib/libparted/common/lib/xalloc-die.c b/usr/src/lib/libparted/common/lib/xalloc-die.c deleted file mode 100644 index 090f060df7..0000000000 --- a/usr/src/lib/libparted/common/lib/xalloc-die.c +++ /dev/null @@ -1,42 +0,0 @@ -/* Report a memory allocation failure and exit. - - Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2006 Free - Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#include "xalloc.h" - -#include - -#include "error.h" -#include "exitfail.h" - -#include "gettext.h" -#define _(msgid) gettext (msgid) - -void -xalloc_die (void) -{ - error (exit_failure, 0, "%s", _("memory exhausted")); - - /* The `noreturn' cannot be given to error, since it may return if - its first argument is 0. To help compilers understand the - xalloc_die does not return, call abort. Also, the abort is a - safety feature if exit_failure is 0 (which shouldn't happen). */ - abort (); -} diff --git a/usr/src/lib/libparted/common/lib/xalloc.h b/usr/src/lib/libparted/common/lib/xalloc.h deleted file mode 100644 index 0c6d8dcf50..0000000000 --- a/usr/src/lib/libparted/common/lib/xalloc.h +++ /dev/null @@ -1,271 +0,0 @@ -/* xalloc.h -- malloc with out-of-memory checking - - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef XALLOC_H_ -# define XALLOC_H_ - -# include - - -# ifdef __cplusplus -extern "C" { -# endif - - -# ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ -# define __attribute__(x) -# endif -# endif - -# ifndef ATTRIBUTE_NORETURN -# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) -# endif - -/* This function is always triggered when memory is exhausted. - It must be defined by the application, either explicitly - or by using gnulib's xalloc-die module. This is the - function to call when one wants the program to die because of a - memory allocation failure. */ -extern void xalloc_die (void) ATTRIBUTE_NORETURN; - -void *xmalloc (size_t s); -void *xzalloc (size_t s); -void *xcalloc (size_t n, size_t s); -void *xrealloc (void *p, size_t s); -void *x2realloc (void *p, size_t *pn); -void *xmemdup (void const *p, size_t s); -char *xstrdup (char const *str); - -/* Return 1 if an array of N objects, each of size S, cannot exist due - to size arithmetic overflow. S must be positive and N must be - nonnegative. This is a macro, not an inline function, so that it - works correctly even when SIZE_MAX < N. - - By gnulib convention, SIZE_MAX represents overflow in size - calculations, so the conservative dividend to use here is - SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. - However, malloc (SIZE_MAX) fails on all known hosts where - sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for - exactly-SIZE_MAX allocations on such hosts; this avoids a test and - branch when S is known to be 1. */ -# define xalloc_oversized(n, s) \ - ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) - - -/* In the following macros, T must be an elementary or structure/union or - typedef'ed type, or a pointer to such a type. To apply one of the - following macros to a function pointer or array type, you need to typedef - it first and use the typedef name. */ - -/* Allocate an object of type T dynamically, with error checking. */ -/* extern t *XMALLOC (typename t); */ -# define XMALLOC(t) ((t *) xmalloc (sizeof (t))) - -/* Allocate memory for N elements of type T, with error checking. */ -/* extern t *XNMALLOC (size_t n, typename t); */ -# define XNMALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xmalloc (n) : xnmalloc (n, sizeof (t)))) - -/* Allocate an object of type T dynamically, with error checking, - and zero it. */ -/* extern t *XZALLOC (typename t); */ -# define XZALLOC(t) ((t *) xzalloc (sizeof (t))) - -/* Allocate memory for N elements of type T, with error checking, - and zero it. */ -/* extern t *XCALLOC (size_t n, typename t); */ -# define XCALLOC(n, t) \ - ((t *) (sizeof (t) == 1 ? xzalloc (n) : xcalloc (n, sizeof (t)))) - - -# if HAVE_INLINE -# define static_inline static inline -# else - void *xnmalloc (size_t n, size_t s); - void *xnrealloc (void *p, size_t n, size_t s); - void *x2nrealloc (void *p, size_t *pn, size_t s); - char *xcharalloc (size_t n); -# endif - -# ifdef static_inline - -/* Allocate an array of N objects, each with S bytes of memory, - dynamically, with error checking. S must be nonzero. */ - -static_inline void * -xnmalloc (size_t n, size_t s) -{ - if (xalloc_oversized (n, s)) - xalloc_die (); - return xmalloc (n * s); -} - -/* Change the size of an allocated block of memory P to an array of N - objects each of S bytes, with error checking. S must be nonzero. */ - -static_inline void * -xnrealloc (void *p, size_t n, size_t s) -{ - if (xalloc_oversized (n, s)) - xalloc_die (); - return xrealloc (p, n * s); -} - -/* If P is null, allocate a block of at least *PN such objects; - otherwise, reallocate P so that it contains more than *PN objects - each of S bytes. *PN must be nonzero unless P is null, and S must - be nonzero. Set *PN to the new number of objects, and return the - pointer to the new block. *PN is never set to zero, and the - returned pointer is never null. - - Repeated reallocations are guaranteed to make progress, either by - allocating an initial block with a nonzero size, or by allocating a - larger block. - - In the following implementation, nonzero sizes are increased by a - factor of approximately 1.5 so that repeated reallocations have - O(N) overall cost rather than O(N**2) cost, but the - specification for this function does not guarantee that rate. - - Here is an example of use: - - int *p = NULL; - size_t used = 0; - size_t allocated = 0; - - void - append_int (int value) - { - if (used == allocated) - p = x2nrealloc (p, &allocated, sizeof *p); - p[used++] = value; - } - - This causes x2nrealloc to allocate a block of some nonzero size the - first time it is called. - - To have finer-grained control over the initial size, set *PN to a - nonzero value before calling this function with P == NULL. For - example: - - int *p = NULL; - size_t used = 0; - size_t allocated = 0; - size_t allocated1 = 1000; - - void - append_int (int value) - { - if (used == allocated) - { - p = x2nrealloc (p, &allocated1, sizeof *p); - allocated = allocated1; - } - p[used++] = value; - } - - */ - -static_inline void * -x2nrealloc (void *p, size_t *pn, size_t s) -{ - size_t n = *pn; - - if (! p) - { - if (! n) - { - /* The approximate size to use for initial small allocation - requests, when the invoking code specifies an old size of - zero. 64 bytes is the largest "small" request for the - GNU C library malloc. */ - enum { DEFAULT_MXFAST = 64 }; - - n = DEFAULT_MXFAST / s; - n += !n; - } - } - else - { - /* Set N = ceil (1.5 * N) so that progress is made if N == 1. - Check for overflow, so that N * S stays in size_t range. - The check is slightly conservative, but an exact check isn't - worth the trouble. */ - if ((size_t) -1 / 3 * 2 / s <= n) - xalloc_die (); - n += (n + 1) / 2; - } - - *pn = n; - return xrealloc (p, n * s); -} - -/* Return a pointer to a new buffer of N bytes. This is like xmalloc, - except it returns char *. */ - -static_inline char * -xcharalloc (size_t n) -{ - return XNMALLOC (n, char); -} - -# endif - -# ifdef __cplusplus -} - -/* C++ does not allow conversions from void * to other pointer types - without a cast. Use templates to work around the problem when - possible. */ - -template inline T * -xrealloc (T *p, size_t s) -{ - return (T *) xrealloc ((void *) p, s); -} - -template inline T * -xnrealloc (T *p, size_t n, size_t s) -{ - return (T *) xnrealloc ((void *) p, n, s); -} - -template inline T * -x2realloc (T *p, size_t *pn) -{ - return (T *) x2realloc ((void *) p, pn); -} - -template inline T * -x2nrealloc (T *p, size_t *pn, size_t s) -{ - return (T *) x2nrealloc ((void *) p, pn, s); -} - -template inline T * -xmemdup (T const *p, size_t s) -{ - return (T *) xmemdup ((void const *) p, s); -} - -# endif - - -#endif /* !XALLOC_H_ */ diff --git a/usr/src/lib/libparted/common/lib/xmalloc.c b/usr/src/lib/libparted/common/lib/xmalloc.c deleted file mode 100644 index 318e0ddb5a..0000000000 --- a/usr/src/lib/libparted/common/lib/xmalloc.c +++ /dev/null @@ -1,123 +0,0 @@ -/* xmalloc.c -- malloc with out of memory checking - - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, - Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -#if ! HAVE_INLINE -# define static_inline -#endif -#include "xalloc.h" -#undef static_inline - -#include -#include - -#ifndef SIZE_MAX -# define SIZE_MAX ((size_t) -1) -#endif - -/* 1 if calloc is known to be compatible with GNU calloc. This - matters if we are not also using the calloc module, which defines - HAVE_CALLOC and supports the GNU API even on non-GNU platforms. */ -#if defined HAVE_CALLOC || defined __GLIBC__ -enum { HAVE_GNU_CALLOC = 1 }; -#else -enum { HAVE_GNU_CALLOC = 0 }; -#endif - -/* Allocate N bytes of memory dynamically, with error checking. */ - -void * -xmalloc (size_t n) -{ - void *p = malloc (n); - if (!p && n != 0) - xalloc_die (); - return p; -} - -/* Change the size of an allocated block of memory P to N bytes, - with error checking. */ - -void * -xrealloc (void *p, size_t n) -{ - p = realloc (p, n); - if (!p && n != 0) - xalloc_die (); - return p; -} - -/* If P is null, allocate a block of at least *PN bytes; otherwise, - reallocate P so that it contains more than *PN bytes. *PN must be - nonzero unless P is null. Set *PN to the new block's size, and - return the pointer to the new block. *PN is never set to zero, and - the returned pointer is never null. */ - -void * -x2realloc (void *p, size_t *pn) -{ - return x2nrealloc (p, pn, 1); -} - -/* Allocate S bytes of zeroed memory dynamically, with error checking. - There's no need for xnzalloc (N, S), since it would be equivalent - to xcalloc (N, S). */ - -void * -xzalloc (size_t s) -{ - return memset (xmalloc (s), 0, s); -} - -/* Allocate zeroed memory for N elements of S bytes, with error - checking. S must be nonzero. */ - -void * -xcalloc (size_t n, size_t s) -{ - void *p; - /* Test for overflow, since some calloc implementations don't have - proper overflow checks. But omit overflow and size-zero tests if - HAVE_GNU_CALLOC, since GNU calloc catches overflow and never - returns NULL if successful. */ - if ((! HAVE_GNU_CALLOC && xalloc_oversized (n, s)) - || (! (p = calloc (n, s)) && (HAVE_GNU_CALLOC || n != 0))) - xalloc_die (); - return p; -} - -/* Clone an object P of size S, with error checking. There's no need - for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any - need for an arithmetic overflow check. */ - -void * -xmemdup (void const *p, size_t s) -{ - return memcpy (xmalloc (s), p, s); -} - -/* Clone STRING. */ - -char * -xstrdup (char const *string) -{ - return xmemdup (string, strlen (string) + 1); -} diff --git a/usr/src/lib/libparted/common/lib/xstrndup.c b/usr/src/lib/libparted/common/lib/xstrndup.c deleted file mode 100644 index 7ccefd798a..0000000000 --- a/usr/src/lib/libparted/common/lib/xstrndup.c +++ /dev/null @@ -1,37 +0,0 @@ -/* Duplicate a bounded initial segment of a string, with out-of-memory - checking. - Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Specification. */ -#include "xstrndup.h" - -#include -#include "xalloc.h" - -/* Return a newly allocated copy of at most N bytes of STRING. - In other words, return a copy of the initial segment of length N of - STRING. */ -char * -xstrndup (const char *string, size_t n) -{ - char *s = strndup (string, n); - if (! s) - xalloc_die (); - return s; -} diff --git a/usr/src/lib/libparted/common/lib/xstrndup.h b/usr/src/lib/libparted/common/lib/xstrndup.h deleted file mode 100644 index e65acc13e2..0000000000 --- a/usr/src/lib/libparted/common/lib/xstrndup.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Duplicate a bounded initial segment of a string, with out-of-memory - checking. - Copyright (C) 2003 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#include - -/* Return a newly allocated copy of at most N bytes of STRING. - In other words, return a copy of the initial segment of length N of - STRING. */ -extern char *strndup (const char *string, size_t n); -extern char *xstrndup (const char *string, size_t n); diff --git a/usr/src/lib/libparted/common/libparted/arch/solaris.c b/usr/src/lib/libparted/common/libparted/arch/solaris.c deleted file mode 100644 index 7059be5321..0000000000 --- a/usr/src/lib/libparted/common/libparted/arch/solaris.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999 - 2005 Free Software Foundation, Inc. - Copyright (C) 2007 Nikhil,Sujay,Nithin,Srivatsa. - - Bug fixes and completion of the module in 2009 by Mark.Logan@sun.com. - - 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 St, Fifth Floor, Boston, MA 02110-1301, USA -*/ - -#include -#include -#include "config.h" -#include "xalloc.h" -#include - -/* - * __attribute doesn't exist on solaris - */ -#define __attribute__(X) /* nothing */ - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#if ENABLE_NLS -#include -#define _(String) dgettext(PACKAGE, String) -#else -#define _(String) (String) -#endif /* ENABLE_NLS */ - -#ifndef UINT_MAX64 -#define UINT_MAX64 0xffffffffffffffffULL -#endif - -/* - * Macro to convert a device number into a partition number - */ -#define PARTITION(dev) (minor(dev) & 0x07) - - -char * -canonicalize_file_name(const char *name) -{ - char *buf; - - buf = malloc(MAXPATHLEN); - if (!buf) { - errno = ENOMEM; - return (NULL); - } - - return (strcpy(buf, name)); -} - -static int -_device_stat(PedDevice* dev, struct stat *dev_stat) -{ - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(!dev->external_mode, return (0)); - - while (1) { - if (!stat(dev->path, dev_stat)) { - return (1); - } else { - if (ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_CANCEL, - _("Could not stat device %s - %s."), - dev->path, strerror(errno)) != PED_EXCEPTION_RETRY) - return (0); - } - } -} - -static void -_device_set_length_and_sector_size(PedDevice* dev) -{ - SolarisSpecific* arch_specific; - PedSector size; - struct dk_minfo dk_minfo; - struct dk_geom dk_geom; - - PED_ASSERT(dev != NULL, return); - PED_ASSERT(dev->open_count > 0, return); - - arch_specific = SOLARIS_SPECIFIC(dev); - - dev->sector_size = PED_SECTOR_SIZE_DEFAULT; - dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT; - - /* this ioctl requires the raw device */ - if (ioctl(arch_specific->fd, DKIOCGMEDIAINFO, &dk_minfo) < 0) { - printf("_device_get_length: ioctl DKIOCGMEDIAINFO failed\n"); - ped_exception_throw( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("Unable to determine the size of %s (%s)."), - dev->path, - strerror(errno)); - } else { - size = dk_minfo.dki_capacity; - dev->length = size; - dev->sector_size = dk_minfo.dki_lbsize; - if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK, - _("Device %s has a logical sector size of " - "%lld. Not all parts of GNU Parted support " - "this at the moment, and the working code " - "is HIGHLY EXPERIMENTAL.\n"), - dev->path, dev->sector_size); - } - if (size > 0) { - return; - } - } - - /* - * On some disks DKIOCGMEDIAINFO doesn't work, it returns 0, - * so try DKIOCG_PHYGEOM next. - */ - /* this ioctl requires the raw device */ - if (ioctl(arch_specific->fd, DKIOCG_PHYGEOM, &dk_geom) < 0) { - printf("_device_get_length: ioctl DKIOCG_PHYGEOM failed\n"); - ped_exception_throw( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("Unable to determine the size of %s (%s)."), - dev->path, strerror(errno)); - - return; - } - - /* - * XXX For large disks, I am adding 16064 to the size of the disk. - * Solaris underreports the size of the disk, because it rounds down to - * a multiple of 16065. This causes a problem with Vista because Vista - * creates a partition that occupies the whole disk, including the - * blocks at the end of the disk that Solaris loses. - */ - if (dk_geom.dkg_nhead == 255 && dk_geom.dkg_nsect == 63) { - size = ((PedSector) dk_geom.dkg_pcyl * - (255 * 63)) + ((255*63)-1); - } else { - size = (PedSector) dk_geom.dkg_pcyl * - dk_geom.dkg_nhead * dk_geom.dkg_nsect; - } - - dev->length = size; -} - -static int -_device_probe_geometry(PedDevice* dev) -{ - SolarisSpecific* arch_specific; - struct stat dev_stat; - struct dk_geom dk_geom; - - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - _device_set_length_and_sector_size(dev); - if (dev->length == 0) { - printf("_device_probe_geometry: _device_get_length = 0\n"); - return (0); - } - - dev->bios_geom.sectors = 63; - dev->bios_geom.heads = 255; - dev->bios_geom.cylinders = dev->length / (63 * 255); - if ((ioctl(arch_specific->fd, DKIOCG_PHYGEOM, &dk_geom) >= 0) && - dk_geom.dkg_nsect && dk_geom.dkg_nhead) { - dev->hw_geom.sectors = dk_geom.dkg_nsect; - dev->hw_geom.heads = dk_geom.dkg_nhead; - dev->hw_geom.cylinders = dk_geom.dkg_pcyl; - } else { - perror("_device_probe_geometry: DKIOCG_PHYGEOM"); - dev->hw_geom = dev->bios_geom; - } - - return (1); -} - -static int -init_ide(PedDevice *dev) -{ - struct stat dev_stat; - - PED_ASSERT(dev != NULL, return (0)); - - if (!_device_stat(dev, &dev_stat)) { - printf("init_ide: _device_stat failed\n"); - goto error; - } - if (!ped_device_open(dev)) { - printf("init_ide: ped_device_open failed\n"); - goto error; - } - if (!_device_probe_geometry(dev)) { - printf("init_ide: _device_probe_geometry failed\n"); - goto error_close_dev; - } - - ped_device_close(dev); - return (1); - -error_close_dev: - ped_device_close(dev); -error: - return (0); -} - -static PedDevice* -solaris_new(const char *path) -{ - PedDevice* dev; - - PED_ASSERT(path != NULL, return (NULL)); - - dev = (PedDevice*) ped_malloc(sizeof (PedDevice)); - if (!dev) - goto error; - - dev->path = strdup(path); - if (!dev->path) - goto error_free_dev; - - dev->arch_specific - = (SolarisSpecific*) ped_malloc(sizeof (SolarisSpecific)); - if (!dev->arch_specific) - goto error_free_path; - - dev->open_count = 0; - dev->read_only = 0; - dev->external_mode = 0; - dev->dirty = 0; - dev->boot_dirty = 0; - dev->model = strdup("Generic Ide"); - dev->type = PED_DEVICE_IDE; - if (!init_ide(dev)) { - goto error_free_arch_specific; - } - - return (dev); - -error_free_arch_specific: - ped_free(dev->arch_specific); - ped_free(dev->model); -error_free_path: - ped_free(dev->path); -error_free_dev: - ped_free(dev); -error: - return (NULL); -} - -static void -solaris_destroy(PedDevice* dev) -{ - PED_ASSERT(dev != NULL, return); - - ped_free(dev->arch_specific); - ped_free(dev->model); - ped_free(dev->path); - ped_free(dev); -} - -/* - * This function constructs the Solaris device name for - * partition num on a disk given the *p0 device for that disk. - * For example: partition 2 of /dev/dsk/c0d0p0 becomes /dev/dsk/c0d0p2. - */ -static char * -_device_get_part_path(PedDevice* dev, int num) -{ - int path_len = strlen(dev->path); - int result_len = path_len + 16; - char *result; - - PED_ASSERT(dev != NULL, return (NULL)); - PED_ASSERT(num >= 1, return (NULL)); - - result = (char *)ped_malloc(result_len); - if (!result) - return (NULL); - - strncpy(result, dev->path, result_len); - if (path_len > 10 && result[path_len - 2] == 'p' && - result[path_len - 1] == '0') { - (void) snprintf(result + path_len - 1, - result_len - path_len + 1, "%d", num); - } else { - (void) snprintf(result, result_len, "partition %d", num); - } - - return (result); -} - -static struct swaptable * -getswapentries(void) -{ - register struct swaptable *st; - register struct swapent *swapent; - int i, num; - char fullpathname[MAXPATHLEN]; - - /* - * get the number of swap entries - */ - if ((num = swapctl(SC_GETNSWP, (void *)NULL)) == -1) { - perror("getswapentries: swapctl SC_GETNSWP"); - return (NULL); - } - if (num == 0) - return (NULL); - if ((st = (swaptbl_t *)malloc(num * sizeof (swapent_t) + sizeof (int))) - == NULL) { - printf("getswapentries: malloc 1 failed.\n"); - return (NULL); - } - swapent = st->swt_ent; - for (i = 0; i < num; i++, swapent++) { - if ((swapent->ste_path = malloc(MAXPATHLEN)) == NULL) { - printf("getswapentries: malloc 2 failed.\n"); - goto error; - } - } - st->swt_n = num; - if ((num = swapctl(SC_LIST, (void *)st)) == -1) { - perror("getswapentries: swapctl SC_LIST"); - goto error; - } - swapent = st->swt_ent; - for (i = 0; i < num; i++, swapent++) { - if (*swapent->ste_path != '/') { - printf("getswapentries: %s\n", swapent->ste_path); - (void) snprintf(fullpathname, sizeof (fullpathname), - "/dev/%s", swapent->ste_path); - (void) strcpy(swapent->ste_path, fullpathname); - } - } - - return (st); - -error: - free(st); - return (NULL); -} - -static void -freeswapentries(st) -struct swaptable *st; -{ - register struct swapent *swapent; - int i; - - swapent = st->swt_ent; - for (i = 0; i < st->swt_n; i++, swapent++) - free(swapent->ste_path); - free(st); -} - -/* - * function getpartition: - */ -static int -getpartition(PedDevice* dev, char *pathname) -{ - SolarisSpecific* arch_specific; - int mfd; - struct dk_cinfo dkinfo; - struct dk_cinfo cur_disk_dkinfo; - struct stat stbuf; - char raw_device[MAXPATHLEN]; - int found = -1; - - PED_ASSERT(dev != NULL, return (found)); - PED_ASSERT(pathname != NULL, return (found)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - /* - * Map the block device name to the raw device name. - * If it doesn't appear to be a device name, skip it. - */ - if (strncmp(pathname, "/dev/", 5)) - return (found); - (void) strcpy(raw_device, "/dev/r"); - (void) strcat(raw_device, pathname + strlen("/dev/")); - /* - * Determine if this appears to be a disk device. - * First attempt to open the device. If if fails, skip it. - */ - if ((mfd = open(raw_device, O_RDWR | O_NDELAY)) < 0) { - return (found); - } - if (fstat(mfd, &stbuf) == -1) { - perror("getpartition: fstat raw_device"); - (void) close(mfd); - return (found); - } - /* - * Must be a character device - */ - if (!S_ISCHR(stbuf.st_mode)) { - printf("getpartition: not character device\n"); - (void) close(mfd); - return (found); - } - /* - * Attempt to read the configuration info on the disk. - */ - if (ioctl(mfd, DKIOCINFO, &dkinfo) < 0) { - perror("getpartition: ioctl DKIOCINFO raw_device"); - (void) close(mfd); - return (found); - } - /* - * Finished with the opened device - */ - (void) close(mfd); - - /* - * Now get the info about the current disk - */ - if (ioctl(arch_specific->fd, DKIOCINFO, &cur_disk_dkinfo) < 0) { - (void) close(mfd); - return (found); - } - - /* - * If it's not the disk we're interested in, it doesn't apply. - */ - if (cur_disk_dkinfo.dki_ctype != dkinfo.dki_ctype || - cur_disk_dkinfo.dki_cnum != dkinfo.dki_cnum || - cur_disk_dkinfo.dki_unit != dkinfo.dki_unit || - strcmp(cur_disk_dkinfo.dki_dname, dkinfo.dki_dname) != 0) { - return (found); - } - - /* - * Extract the partition that is mounted. - */ - return (PARTITION(stbuf.st_rdev)); -} - -/* - * This Routine checks to see if there are partitions used for swapping overlaps - * a given portion of a disk. If the start parameter is < 0, it means - * that the entire disk should be checked - */ -static int -checkswap(PedDevice* dev, diskaddr_t start, diskaddr_t end) -{ - SolarisSpecific* arch_specific; - struct extvtoc extvtoc; - struct swaptable *st; - struct swapent *swapent; - int i; - int found = 0; - int part; - diskaddr_t p_start; - diskaddr_t p_size; - - PED_ASSERT(dev != NULL, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - if (ioctl(arch_specific->fd, DKIOCGEXTVTOC, &extvtoc) == -1) { - return (0); - } - - /* - * check for swap entries - */ - st = getswapentries(); - /* - * if there are no swap entries return. - */ - if (st == (struct swaptable *)NULL) - return (0); - swapent = st->swt_ent; - for (i = 0; i < st->swt_n; i++, swapent++) { - if ((part = getpartition(dev, swapent->ste_path)) != -1) { - if (start == UINT_MAX64) { - found = -1; - break; - } - p_start = extvtoc.v_part[part].p_start; - p_size = extvtoc.v_part[part].p_size; - if (start >= p_start + p_size || end < p_start) { - continue; - } - found = -1; - break; - } - } - freeswapentries(st); - - return (found); -} - -/* - * Determines if there are partitions that are a part of an SVM, VxVM, zpool - * volume or a live upgrade device, overlapping a given portion of a disk. - * Mounts and swap devices are checked in legacy format code. - */ -static int -checkdevinuse(PedDevice *dev, diskaddr_t start, diskaddr_t end, int print) -{ - int error; - int found = 0; - int check = 0; - int i; - int part = 0; - uint64_t slice_start, slice_size; - dm_descriptor_t *slices = NULL; - nvlist_t *attrs = NULL; - char *usage; - char *name; - char cur_disk_path[MAXPATHLEN]; - char *pcur_disk_path; - - PED_ASSERT(dev != NULL, return (found)); - - /* - * Truncate the characters following "d*", such as "s*" or "p*" - */ - strcpy(cur_disk_path, dev->path); - pcur_disk_path = basename(cur_disk_path); - name = strrchr(pcur_disk_path, 'd'); - if (name) { - name++; - for (; (*name <= '9') && (*name >= '0'); name++) - ; - *name = (char)0; - } - - /* - * For format, we get basic 'in use' details from libdiskmgt. After - * that we must do the appropriate checking to see if the 'in use' - * details require a bit of additional work. - */ - - dm_get_slices(pcur_disk_path, &slices, &error); - if (error) { - /* - * If ENODEV, it actually means the device is not in use. - * We will return (0) without displaying error. - */ - if (error != ENODEV) { - printf("checkdevinuse: Error1 occurred with device in " - "use checking: %s\n", strerror(error)); - return (found); - } - } - if (slices == NULL) - return (found); - - for (i = 0; slices[i] != NULL; i++) { - /* - * If we are checking the whole disk - * then any and all in use data is - * relevant. - */ - if (start == UINT_MAX64) { - name = dm_get_name(slices[i], &error); - if (error != 0 || !name) { - printf("checkdevinuse: Error2 occurred with " - "device in use checking: %s\n", - strerror(error)); - continue; - } - printf("checkdevinuse: name1 %s\n", name); - if (dm_inuse(name, &usage, DM_WHO_FORMAT, &error) || - error) { - if (error != 0) { - dm_free_name(name); - name = NULL; - printf("checkdevinuse: Error3 " - "occurred with device " - "in use checking: %s\n", - strerror(error)); - continue; - } - dm_free_name(name); - name = NULL; - /* - * If this is a dump device, then it is - * a failure. You cannot format a slice - * that is a dedicated dump device. - */ - - if (strstr(usage, DM_USE_DUMP)) { - if (print) { - printf(usage); - free(usage); - } - dm_free_descriptors(slices); - return (1); - } - /* - * We really found a device that is in use. - * Set 'found' for the return value. - */ - found ++; - check = 1; - if (print) { - printf(usage); - free(usage); - } - } - } else { - /* - * Before getting the in use data, verify that the - * current slice is within the range we are checking. - */ - attrs = dm_get_attributes(slices[i], &error); - if (error) { - printf("checkdevinuse: Error4 occurred with " - "device in use checking: %s\n", - strerror(error)); - continue; - } - if (attrs == NULL) { - continue; - } - - (void) nvlist_lookup_uint64(attrs, DM_START, - &slice_start); - (void) nvlist_lookup_uint64(attrs, DM_SIZE, - &slice_size); - if (start >= (slice_start + slice_size) || - (end < slice_start)) { - nvlist_free(attrs); - attrs = NULL; - continue; - } - name = dm_get_name(slices[i], &error); - if (error != 0 || !name) { - printf("checkdevinuse: Error5 occurred with " - "device in use checking: %s\n", - strerror(error)); - nvlist_free(attrs); - attrs = NULL; - continue; - } - if (dm_inuse(name, &usage, - DM_WHO_FORMAT, &error) || error) { - if (error != 0) { - dm_free_name(name); - name = NULL; - printf("checkdevinuse: Error6 " - "occurred with device " - "in use checking: %s\n", - strerror(error)); - nvlist_free(attrs); - attrs = NULL; - continue; - } - dm_free_name(name); - name = NULL; - /* - * If this is a dump device, then it is - * a failure. You cannot format a slice - * that is a dedicated dump device. - */ - if (strstr(usage, DM_USE_DUMP)) { - if (print) { - printf(usage); - free(usage); - } - dm_free_descriptors(slices); - nvlist_free(attrs); - return (1); - } - /* - * We really found a device that is in use. - * Set 'found' for the return value. - */ - found ++; - check = 1; - if (print) { - printf(usage); - free(usage); - } - } - } - /* - * If check is set it means we found a slice(the current slice) - * on this device in use in some way. We potentially want - * to check this slice when labeling is requested. - */ - if (check) { - name = dm_get_name(slices[i], &error); - if (error != 0 || !name) { - printf("checkdevinuse: Error7 occurred with " - "device in use checking: %s\n", - strerror(error)); - nvlist_free(attrs); - attrs = NULL; - continue; - } - part = getpartition(dev, name); - dm_free_name(name); - name = NULL; - check = 0; - } - /* - * If we have attributes then we have successfully - * found the slice we were looking for and we also - * know this means we are not searching the whole - * disk so break out of the loop - * now. - */ - if (attrs) { - nvlist_free(attrs); - break; - } - } - - if (slices) { - dm_free_descriptors(slices); - } - - return (found); -} - -/* - * This routine checks to see if there are mounted partitions overlapping - * a given portion of a disk. If the start parameter is < 0, it means - * that the entire disk should be checked. - */ -static int -checkmount(PedDevice* dev, diskaddr_t start, diskaddr_t end) -{ - SolarisSpecific* arch_specific; - struct extvtoc extvtoc; - diskaddr_t p_start; - diskaddr_t p_size; - FILE *fp; - int found = 0; - int part; - struct mnttab mnt_record; - struct mnttab *mp = &mnt_record; - - PED_ASSERT(dev != NULL, return (found)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - if (ioctl(arch_specific->fd, DKIOCGEXTVTOC, &extvtoc) == -1) { - return (0); - } - - /* - * Open the mount table. - */ - fp = fopen(MNTTAB, "r"); - if (fp == NULL) { - printf("checkmount: Unable to open mount table.\n"); - return (0); - } - /* - * Loop through the mount table until we run out of entries. - */ - while ((getmntent(fp, mp)) != -1) { - - if ((part = getpartition(dev, mp->mnt_special)) == -1) - continue; - - /* - * It's a mount on the disk we're checking. If we are - * checking whole disk, then we found trouble. We can - * quit searching. - */ - if (start == UINT_MAX64) { - found = -1; - break; - } - - /* - * If the partition overlaps the zone we're checking, - * then we found trouble. We can quit searching. - */ - p_start = extvtoc.v_part[part].p_start; - p_size = extvtoc.v_part[part].p_size; - if (start >= p_start + p_size || end < p_start) { - continue; - } - found = -1; - break; - } - /* - * Close down the mount table. - */ - (void) fclose(fp); - - return (found); -} - -/* - * Return 1 if the device is busy, 0 otherwise. - */ -static int -solaris_is_busy(PedDevice* dev) -{ - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - - if (checkmount(dev, (diskaddr_t)-1, (diskaddr_t)-1)) - return (1); - - if (checkswap(dev, (diskaddr_t)-1, (diskaddr_t)-1)) - return (1); - - if (checkdevinuse(dev, (diskaddr_t)-1, (diskaddr_t)-1, 1)) - return (1); - - return (0); -} - -/* - * This will accept a dev->path that looks like this: - * /devices/pci@0,0/pci-ide@1f,2/ide@0/cmdk@0,0:q - * /devices/pci@0,0/pci-ide@1f,2/ide@0/cmdk@0,0:q,raw - * or this: - * /dev/dsk/c0d0p0 - * /dev/rdsk/c0d0p0 - * It has to open the raw device, so it converts to it locally, if necessary. - */ -static int -solaris_open(PedDevice* dev) -{ - SolarisSpecific* arch_specific; - char rawname[MAXPATHLEN]; - - PED_ASSERT(dev != NULL, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - /* - * Convert to the raw device, unless it already is. - */ - if (strncmp(dev->path, "/devices", 8) == 0) { - if (strncmp(&dev->path[strlen(dev->path)-4], ",raw", 4)) { - snprintf(rawname, sizeof (rawname), "%s,raw", - dev->path); - } else { - strcpy(rawname, dev->path); - } - } else { - /* - * Assumes it is of the form: /dev/dsk/ or /dev/rdsk/ - */ - if (strncmp(dev->path, "/dev/dsk/", 9) == 0) { - snprintf(rawname, sizeof (rawname), "/dev/rdsk/%s", - &dev->path[9]); - } else { - strcpy(rawname, dev->path); - } - } - -retry: - arch_specific->fd = open(rawname, O_RDWR); - - if (arch_specific->fd == -1) { - char *rw_error_msg = strerror(errno); - - arch_specific->fd = open(rawname, O_RDONLY); - - if (arch_specific->fd == -1) { - printf("solaris_open: open(\"%s\") failed\n", rawname); - if (ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_CANCEL, - _("Error opening %s: %s"), - rawname, strerror(errno)) != PED_EXCEPTION_RETRY) { - return (0); - } else { - goto retry; - } - } else { - ped_exception_throw( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK, - _("Unable to open %s read-write (%s). %s has " - "been opened read-only."), - rawname, rw_error_msg, rawname); - dev->read_only = 1; - } - } else { - dev->read_only = 0; - } - - return (1); -} - -static int -solaris_refresh_open(PedDevice* dev) -{ - return (1); -} - -static int -solaris_close(PedDevice* dev) -{ - SolarisSpecific* arch_specific; - - PED_ASSERT(dev != NULL, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - close(arch_specific->fd); - return (1); -} - -static int -_do_fsync(PedDevice* dev) -{ - SolarisSpecific* arch_specific; - int status; - PedExceptionOption ex_status; - - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - while (1) { - status = fsync(arch_specific->fd); - if (status >= 0) - break; - - ex_status = ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_IGNORE_CANCEL, - _("%s during fsync on %s"), - strerror(errno), dev->path); - - switch (ex_status) { - case PED_EXCEPTION_IGNORE: - return (1); - - case PED_EXCEPTION_RETRY: - break; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch(); - case PED_EXCEPTION_CANCEL: - return (0); - } - } - return (1); -} - -static int -solaris_refresh_close(PedDevice* dev) -{ - if (dev->dirty) - _do_fsync(dev); - return (1); -} - -static int -_device_seek(const PedDevice* dev, PedSector sector) -{ - SolarisSpecific* arch_specific; - - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - PED_ASSERT(!dev->external_mode, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - if (sizeof (off_t) < 8) { - off64_t pos = (off64_t)(sector * dev->sector_size); - return (lseek64(arch_specific->fd, pos, SEEK_SET) == pos); - } else { - off_t pos = sector * dev->sector_size; - return (lseek(arch_specific->fd, pos, SEEK_SET) == pos); - } -} - -static int -solaris_read(const PedDevice* dev, void* vbuffer, PedSector start, - PedSector count) -{ - SolarisSpecific* arch_specific; - int status; - PedExceptionOption ex_status; - size_t read_length = count * dev->sector_size; - void *diobuf; - char *buffer = vbuffer; - - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - PED_ASSERT(!dev->external_mode, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - while (1) { - if (_device_seek(dev, start)) - break; - - ex_status = ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_IGNORE_CANCEL, - _("%s during seek for read on %s"), - strerror(errno), dev->path); - - switch (ex_status) { - case PED_EXCEPTION_IGNORE: - return (1); - - case PED_EXCEPTION_RETRY: - break; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch(); - case PED_EXCEPTION_CANCEL: - return (0); - } - } - - diobuf = memalign(dev->sector_size, read_length); - if (diobuf == NULL) { - printf("solaris_read: cannot memalign %u\n", read_length); - return (0); - } - - while (1) { - status = read(arch_specific->fd, diobuf, read_length); - - if (status > 0) - memcpy(buffer, diobuf, status); - - if (status == read_length) - break; - - if (status > 0) { - printf("solaris_read: partial read %d of %d\n", - status, read_length); - read_length -= status; - buffer += status; - continue; - } - - ex_status = ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_IGNORE_CANCEL, - _("%s during read on %s"), - strerror(errno), - dev->path); - - switch (ex_status) { - case PED_EXCEPTION_IGNORE: - free(diobuf); - return (1); - - case PED_EXCEPTION_RETRY: - break; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch(); - case PED_EXCEPTION_CANCEL: - free(diobuf); - return (0); - } - } - - free(diobuf); - - return (1); -} - -static int -solaris_write(PedDevice* dev, const void* buffer, PedSector start, - PedSector count) -{ - SolarisSpecific* arch_specific; - int status; - PedExceptionOption ex_status; - size_t write_length = count * dev->sector_size; - char *diobuf; - char *diobuf_start; - - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return (0)); - PED_ASSERT(dev->open_count > 0, return (0)); - PED_ASSERT(!dev->external_mode, return (0)); - - arch_specific = SOLARIS_SPECIFIC(dev); - - if (dev->read_only) { - if (ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Can't write to %s, because it is opened read-only."), - dev->path) != PED_EXCEPTION_IGNORE) - return (0); - else - return (1); - } - - while (1) { - if (_device_seek(dev, start)) - break; - - ex_status = ped_exception_throw( - PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL, - _("%s during seek for write on %s"), - strerror(errno), dev->path); - - switch (ex_status) { - case PED_EXCEPTION_IGNORE: - return (1); - - case PED_EXCEPTION_RETRY: - break; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch(); - case PED_EXCEPTION_CANCEL: - return (0); - } - } - -#ifdef READ_ONLY - printf("solaris_write(\"%s\", %p, %d, %d)\n", - dev->path, buffer, (int)start, (int)count); -#else - dev->dirty = 1; - - diobuf = memalign((size_t)PED_SECTOR_SIZE_DEFAULT, write_length); - if (diobuf == NULL) { - printf("solaris_write: cannot memalign %u\n", write_length); - return (0); - } - - memcpy(diobuf, buffer, write_length); - diobuf_start = diobuf; - while (1) { - status = write(arch_specific->fd, diobuf, write_length); - if (status == write_length) - break; - if (status > 0) { - printf("solaris_write: partial write %d of %d\n", - status, write_length); - write_length -= status; - diobuf += status; - continue; - } - - ex_status = ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_RETRY_IGNORE_CANCEL, - _("%s during write on %s"), - strerror(errno), dev->path); - - switch (ex_status) { - case PED_EXCEPTION_IGNORE: - free(diobuf_start); - return (1); - - case PED_EXCEPTION_RETRY: - break; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch(); - case PED_EXCEPTION_CANCEL: - free(diobuf_start); - return (0); - } - } - free(diobuf_start); -#endif /* !READ_ONLY */ - - return (1); -} - - -/* - * returns the number of sectors that are ok. - * This is never called. It would get called through ped_device_check(). - */ -static PedSector -solaris_check(PedDevice* dev, void* buffer, PedSector start, PedSector count) -{ - SolarisSpecific* arch_specific; - PedSector done; - int status; - void* diobuf; - - PED_ASSERT(dev != NULL, return (0LL)); - PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, - return (0LL)); - PED_ASSERT(dev->open_count > 0, return (0LL)); - PED_ASSERT(!dev->external_mode, return (0LL)); - - printf("solaris_check: start %lld count %lld\n", start, count); - - arch_specific = SOLARIS_SPECIFIC(dev); - - if (!_device_seek(dev, start)) - return (0LL); - - diobuf = memalign(PED_SECTOR_SIZE_DEFAULT, count * dev->sector_size); - if (diobuf == NULL) { - printf("solaris_check: cannot memalign %u\n", - count * dev->sector_size); - return (0LL); - } - - for (done = 0; done < count; done += status / dev->sector_size) { - status = read(arch_specific->fd, diobuf, - (size_t)((count - done) * dev->sector_size)); - if (status < 0) - break; - } - free(diobuf); - - return (done); -} - -static int -solaris_sync(PedDevice* dev) -{ - PED_ASSERT(dev != NULL, return (0)); - PED_ASSERT(!dev->external_mode, return (0)); - - if (dev->read_only) - return (1); - if (!_do_fsync(dev)) - return (0); - return (1); -} - -/* - * Returns all *p0 block devices. - * open the raw device so ioctl works. - */ -static void -solaris_probe_all() -{ - DIR *dir; - struct dirent *dp; - char *pname; - char block_path[256]; - char raw_path[256]; - struct stat buffer; - int fd; - - dir = opendir("/dev/dsk"); - while ((dp = readdir(dir)) != NULL) { - - pname = dp->d_name + strlen(dp->d_name) - 2; - if (strcmp(pname, "p0") == 0) { - - strncpy(block_path, "/dev/dsk/", sizeof (block_path)); - strncat(block_path, dp->d_name, sizeof (block_path)); - - strncpy(raw_path, "/dev/rdsk/", sizeof (raw_path)); - strncat(raw_path, dp->d_name, sizeof (raw_path)); - - if (stat(block_path, &buffer) == 0) { - - if ((fd = open(raw_path, O_RDONLY)) < 0) { - continue; - } - -#ifdef DONT_ALLOW_REMOVEABLE_DEVICES - int n = 0; - if (ioctl(fd, DKIOCREMOVABLE, &n) < 0) { - char msg[MAXPATHLEN]; - snprintf(msg, sizeof (msg), - "ioctl(\"%s\", DKIOCREMOVABLE)", - raw_path); - perror(msg); - } else if (!n) { - /* - * Not a removable device - * printf("solaris_probe_all: %s\n", - * block_path); - */ - } -#endif /* DONT_ALLOW_REMOVEABLE_DEVICES */ - - _ped_device_probe(block_path); - close(fd); - } - } - } -} - -static char * -solaris_partition_get_path(const PedPartition* part) -{ - return (_device_get_part_path(part->disk->dev, part->num)); -} - -/* - * Returns 1 if the partition is busy in some way, 0 otherwise. - */ -static int -solaris_partition_is_busy(const PedPartition* part) -{ - int r1, r2, r3; - - PED_ASSERT(part != NULL, return (0)); - - r1 = checkmount(part->geom.dev, part->geom.start, part->geom.end); - r2 = checkswap(part->geom.dev, part->geom.start, part->geom.end); - r3 = checkdevinuse(part->geom.dev, part->geom.start, part->geom.end, 1); - - if (r1 || r2 || r3) - return (1); - - return (0); -} - -static int -solaris_disk_commit(PedDisk* disk) -{ - return (1); -} - -static PedDeviceArchOps solaris_dev_ops = { - ._new = solaris_new, - .destroy = solaris_destroy, - .is_busy = solaris_is_busy, - .open = solaris_open, - .refresh_open = solaris_refresh_open, - .close = solaris_close, - .refresh_close = solaris_refresh_close, - .read = solaris_read, - .write = solaris_write, - .check = solaris_check, - .sync = solaris_sync, - .sync_fast = solaris_sync, - .probe_all = solaris_probe_all -}; - -PedDiskArchOps solaris_disk_ops = { - .partition_get_path = solaris_partition_get_path, - .partition_is_busy = solaris_partition_is_busy, - .disk_commit = solaris_disk_commit -}; - -PedArchitecture ped_solaris_arch = { - .dev_ops = &solaris_dev_ops, - .disk_ops = &solaris_disk_ops -}; diff --git a/usr/src/lib/libparted/common/libparted/cs/constraint.c b/usr/src/lib/libparted/common/libparted/cs/constraint.c deleted file mode 100644 index 5595db3213..0000000000 --- a/usr/src/lib/libparted/common/libparted/cs/constraint.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \addtogroup PedConstraint - * - * \brief Constraint solver interface. - * - * Constraints are used to communicate restrictions on operations Constraints - * are restrictions on the location and alignment of the start and end of a - * partition, and the minimum and maximum size. - * - * Constraints are closed under intersection (for the proof see the source - * code). For background information see the Chinese Remainder Theorem. - * - * This interface consists of construction constraints, finding the intersection - * of constraints, and finding solutions to constraints. - * - * The constraint solver allows you to specify constraints on where a partition - * or file system (or any PedGeometry) may be placed/resized/etc. For example, - * you might want to make sure that a file system is at least 10 Gb, or that it - * starts at the beginning of new cylinder. - * - * The constraint solver in this file unifies solver in geom.c (which allows you - * to specify constraints on ranges) and natmath.c (which allows you to specify - * alignment constraints). - * - * @{ - */ - -#include -#include -#include - -/** - * Initializes a pre-allocated piece of memory to contain a constraint - * with the supplied default values. - * - * \return \c 0 on failure. - */ -int -ped_constraint_init ( - PedConstraint* constraint, - const PedAlignment* start_align, - const PedAlignment* end_align, - const PedGeometry* start_range, - const PedGeometry* end_range, - PedSector min_size, - PedSector max_size) -{ - PED_ASSERT (constraint != NULL, return 0); - PED_ASSERT (start_range != NULL, return 0); - PED_ASSERT (end_range != NULL, return 0); - PED_ASSERT (min_size > 0, return 0); - PED_ASSERT (max_size > 0, return 0); - - constraint->start_align = ped_alignment_duplicate (start_align); - constraint->end_align = ped_alignment_duplicate (end_align); - constraint->start_range = ped_geometry_duplicate (start_range); - constraint->end_range = ped_geometry_duplicate (end_range); - constraint->min_size = min_size; - constraint->max_size = max_size; - - return 1; -} - -/** - * Convenience wrapper for ped_constraint_init(). - * - * Allocates a new piece of memory and initializes the constraint. - * - * \return \c NULL on failure. - */ -PedConstraint* -ped_constraint_new ( - const PedAlignment* start_align, - const PedAlignment* end_align, - const PedGeometry* start_range, - const PedGeometry* end_range, - PedSector min_size, - PedSector max_size) -{ - PedConstraint* constraint; - - constraint = (PedConstraint*) ped_malloc (sizeof (PedConstraint)); - if (!constraint) - goto error; - if (!ped_constraint_init (constraint, start_align, end_align, - start_range, end_range, min_size, max_size)) - goto error_free_constraint; - return constraint; - -error_free_constraint: - ped_free (constraint); -error: - return NULL; -} - -/** - * Return a constraint that requires a region to be entirely contained inside - * \p max, and to entirely contain \p min. - * - * \return \c NULL on failure. - */ -PedConstraint* -ped_constraint_new_from_min_max ( - const PedGeometry* min, - const PedGeometry* max) -{ - PedGeometry start_range; - PedGeometry end_range; - - PED_ASSERT (min != NULL, return NULL); - PED_ASSERT (max != NULL, return NULL); - PED_ASSERT (ped_geometry_test_inside (max, min), return NULL); - - ped_geometry_init (&start_range, min->dev, max->start, - min->start - max->start + 1); - ped_geometry_init (&end_range, min->dev, min->end, - max->end - min->end + 1); - - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - &start_range, &end_range, - min->length, max->length); -} - -/** - * Return a constraint that requires a region to entirely contain \p min. - * - * \return \c NULL on failure. - */ -PedConstraint* -ped_constraint_new_from_min (const PedGeometry* min) -{ - PedGeometry full_dev; - - PED_ASSERT (min != NULL, return NULL); - - ped_geometry_init (&full_dev, min->dev, 0, min->dev->length); - return ped_constraint_new_from_min_max (min, &full_dev); -} - -/** - * Return a constraint that requires a region to be entirely contained inside - * \p max. - * - * \return \c NULL on failure. - */ -PedConstraint* -ped_constraint_new_from_max (const PedGeometry* max) -{ - PED_ASSERT (max != NULL, return NULL); - - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - max, max, 1, max->length); -} - -/** - * Duplicate a constraint. - * - * \return \c NULL on failure. - */ -PedConstraint* -ped_constraint_duplicate (const PedConstraint* constraint) -{ - PED_ASSERT (constraint != NULL, return NULL); - - return ped_constraint_new ( - constraint->start_align, - constraint->end_align, - constraint->start_range, - constraint->end_range, - constraint->min_size, - constraint->max_size); -} - -/** - * Return a constraint that requires a region to satisfy both \p a and \p b. - * - * Moreover, any region satisfying \p a and \p b will also satisfy the returned - * constraint. - * - * \return \c NULL if no solution could be found (note that \c NULL is a valid - * PedConstraint). - */ -PedConstraint* -ped_constraint_intersect (const PedConstraint* a, const PedConstraint* b) -{ - PedAlignment* start_align; - PedAlignment* end_align; - PedGeometry* start_range; - PedGeometry* end_range; - PedSector min_size; - PedSector max_size; - PedConstraint* constraint; - - if (!a || !b) - return NULL; - - start_align = ped_alignment_intersect (a->start_align, b->start_align); - if (!start_align) - goto empty; - end_align = ped_alignment_intersect (a->end_align, b->end_align); - if (!end_align) - goto empty_destroy_start_align; - start_range = ped_geometry_intersect (a->start_range, b->start_range); - if (!start_range) - goto empty_destroy_end_align; - end_range = ped_geometry_intersect (a->end_range, b->end_range); - if (!end_range) - goto empty_destroy_start_range; - min_size = PED_MAX (a->min_size, b->min_size); - max_size = PED_MIN (a->max_size, b->max_size); - - constraint = ped_constraint_new ( - start_align, end_align, start_range, end_range, - min_size, max_size); - if (!constraint) - goto empty_destroy_end_range; - - ped_alignment_destroy (start_align); - ped_alignment_destroy (end_align); - ped_geometry_destroy (start_range); - ped_geometry_destroy (end_range); - return constraint; - -empty_destroy_end_range: - ped_geometry_destroy (end_range); -empty_destroy_start_range: - ped_geometry_destroy (start_range); -empty_destroy_end_align: - ped_alignment_destroy (end_align); -empty_destroy_start_align: - ped_alignment_destroy (start_align); -empty: - return NULL; -} - -/** - * Release the memory allocated for a PedConstraint constructed with - * ped_constraint_init(). - */ -void -ped_constraint_done (PedConstraint* constraint) -{ - PED_ASSERT (constraint != NULL, return); - - ped_alignment_destroy (constraint->start_align); - ped_alignment_destroy (constraint->end_align); - ped_geometry_destroy (constraint->start_range); - ped_geometry_destroy (constraint->end_range); -} - -/** - * Release the memory allocated for a PedConstraint constructed with - * ped_constraint_new(). - */ -void -ped_constraint_destroy (PedConstraint* constraint) -{ - if (constraint) { - ped_constraint_done (constraint); - ped_free (constraint); - } -} - -/* - * Return the region within which the start must lie - * in order to satisfy a constriant. It takes into account - * constraint->start_range, constraint->min_size and constraint->max_size. - * All sectors in this range that also satisfy alignment requirements have - * an end, such that the (start, end) satisfy the constraint. - */ -static PedGeometry* -_constraint_get_canonical_start_range (const PedConstraint* constraint) -{ - PedSector first_end_soln; - PedSector last_end_soln; - PedSector min_start; - PedSector max_start; - PedGeometry start_min_max_range; - - if (constraint->min_size > constraint->max_size) - return NULL; - - first_end_soln = ped_alignment_align_down ( - constraint->end_align, constraint->end_range, - constraint->end_range->start); - last_end_soln = ped_alignment_align_up ( - constraint->end_align, constraint->end_range, - constraint->end_range->end); - if (first_end_soln == -1 || last_end_soln == -1 - || first_end_soln > last_end_soln - || last_end_soln < constraint->min_size) - return NULL; - - min_start = first_end_soln - constraint->max_size + 1; - if (min_start < 0) - min_start = 0; - max_start = last_end_soln - constraint->min_size + 1; - if (max_start < 0) - return NULL; - - ped_geometry_init ( - &start_min_max_range, constraint->start_range->dev, - min_start, max_start - min_start + 1); - - return ped_geometry_intersect (&start_min_max_range, - constraint->start_range); -} - -/* - * Return the nearest start that will have at least one other end that - * together satisfy the constraint. - */ -static PedSector -_constraint_get_nearest_start_soln (const PedConstraint* constraint, - PedSector start) -{ - PedGeometry* start_range; - PedSector result; - - start_range = _constraint_get_canonical_start_range (constraint); - if (!start_range) - return -1; - result = ped_alignment_align_nearest ( - constraint->start_align, start_range, start); - ped_geometry_destroy (start_range); - return result; -} - -/* - * Given a constraint and a start ("half of the solution"), find the - * range of all possible ends, such that all (start, end) are solutions - * to constraint (subject to additional alignment requirements). - */ -static PedGeometry* -_constraint_get_end_range (const PedConstraint* constraint, PedSector start) -{ - PedDevice* dev = constraint->end_range->dev; - PedSector first_min_max_end; - PedSector last_min_max_end; - PedGeometry end_min_max_range; - - if (start + constraint->min_size - 1 > dev->length - 1) - return NULL; - - first_min_max_end = start + constraint->min_size - 1; - last_min_max_end = start + constraint->max_size - 1; - if (last_min_max_end > dev->length - 1) - last_min_max_end = dev->length - 1; - - ped_geometry_init (&end_min_max_range, dev, - first_min_max_end, - last_min_max_end - first_min_max_end + 1); - - return ped_geometry_intersect (&end_min_max_range, - constraint->end_range); -} - -/* - * Given "constraint" and "start", find the end that is nearest to - * "end", such that ("start", the end) together form a solution to - * "constraint". - */ -static PedSector -_constraint_get_nearest_end_soln (const PedConstraint* constraint, - PedSector start, PedSector end) -{ - PedGeometry* end_range; - PedSector result; - - end_range = _constraint_get_end_range (constraint, start); - if (!end_range) - return -1; - - result = ped_alignment_align_nearest (constraint->end_align, end_range, - end); - ped_geometry_destroy (end_range); - return result; -} - -/** - * Return the nearest region to \p geom that satisfy a \p constraint. - * - * Note that "nearest" is somewhat ambiguous. This function makes - * no guarantees about how this ambiguity is resovled. - * - * \return PedGeometry, or NULL when a \p constrain cannot be satisfied - */ -PedGeometry* -ped_constraint_solve_nearest ( - const PedConstraint* constraint, const PedGeometry* geom) -{ - PedSector start; - PedSector end; - PedGeometry* result; - - if (constraint == NULL) - return NULL; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (constraint->start_range->dev == geom->dev, return NULL); - - start = _constraint_get_nearest_start_soln (constraint, geom->start); - if (start == -1) - return NULL; - end = _constraint_get_nearest_end_soln (constraint, start, geom->end); - if (end == -1) - return NULL; - - result = ped_geometry_new (geom->dev, start, end - start + 1); - if (!result) - return NULL; - PED_ASSERT (ped_constraint_is_solution (constraint, result), - return NULL); - return result; -} - -/** - * Find the largest region that satisfies a constraint. - * - * There might be more than one solution. This function makes no - * guarantees about which solution it will choose in this case. - */ -PedGeometry* -ped_constraint_solve_max (const PedConstraint* constraint) -{ - PedDevice* dev; - PedGeometry full_dev; - - if (!constraint) - return NULL; - dev = constraint->start_range->dev; - ped_geometry_init (&full_dev, dev, 0, dev->length - 1); - return ped_constraint_solve_nearest (constraint, &full_dev); -} - -/** - * Check whether \p geom satisfies the given constraint. - * - * \return \c 1 if it does. - **/ -int -ped_constraint_is_solution (const PedConstraint* constraint, - const PedGeometry* geom) -{ - PED_ASSERT (constraint != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - - if (!ped_alignment_is_aligned (constraint->start_align, NULL, - geom->start)) - return 0; - if (!ped_alignment_is_aligned (constraint->end_align, NULL, geom->end)) - return 0; - if (!ped_geometry_test_sector_inside (constraint->start_range, - geom->start)) - return 0; - if (!ped_geometry_test_sector_inside (constraint->end_range, geom->end)) - return 0; - if (geom->length < constraint->min_size) - return 0; - if (geom->length > constraint->max_size) - return 0; - return 1; -} - -/** - * Return a constraint that any region on the given device will satisfy. - */ -PedConstraint* -ped_constraint_any (const PedDevice* dev) -{ - PedGeometry full_dev; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length)) - return NULL; - - return ped_constraint_new ( - ped_alignment_any, - ped_alignment_any, - &full_dev, - &full_dev, - 1, - dev->length); -} - -/** - * Return a constraint that only the given region will satisfy. - */ -PedConstraint* -ped_constraint_exact (const PedGeometry* geom) -{ - PedAlignment start_align; - PedAlignment end_align; - PedGeometry start_sector; - PedGeometry end_sector; - - ped_alignment_init (&start_align, geom->start, 0); - ped_alignment_init (&end_align, geom->end, 0); - ped_geometry_init (&start_sector, geom->dev, geom->start, 1); - ped_geometry_init (&end_sector, geom->dev, geom->end, 1); - - return ped_constraint_new (&start_align, &end_align, - &start_sector, &end_sector, 1, - geom->dev->length); -} - -/** - * @} - */ - diff --git a/usr/src/lib/libparted/common/libparted/cs/geom.c b/usr/src/lib/libparted/common/libparted/cs/geom.c deleted file mode 100644 index 620fac88ce..0000000000 --- a/usr/src/lib/libparted/common/libparted/cs/geom.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file geom.c */ - - -/** - * \addtogroup PedGeometry - * - * \brief PedGeometry represents a continuous region on a device. All addressing - * through a PedGeometry object is in terms of the start of the continuous - * region. - * - * The following conditions are always true on a PedGeometry object manipulated - * with the GNU Parted API: - * - * - start + length - 1 == end - * - length > 0 - * - start >= 0 - * - end < dev->length - * - * @{ - */ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/** - * Initialize the previously allocated PedGeometry \p geom. - */ -int -ped_geometry_init (PedGeometry* geom, const PedDevice* dev, - PedSector start, PedSector length) -{ - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (dev != NULL, return 0); - - geom->dev = (PedDevice*) dev; - return ped_geometry_set (geom, start, length); -} - -/** - * Create a new PedGeometry object on \p disk, starting at \p start with a - * size of \p length sectors. - * - * \return NULL on failure. - */ -PedGeometry* -ped_geometry_new (const PedDevice* dev, PedSector start, PedSector length) -{ - PedGeometry* geom; - - PED_ASSERT (dev != NULL, return NULL); - - geom = (PedGeometry*) ped_malloc (sizeof (PedGeometry)); - if (!geom) - goto error; - if (!ped_geometry_init (geom, dev, start, length)) - goto error_free_geom; - return geom; - -error_free_geom: - ped_free (geom); -error: - return NULL; -} - -/** - * Duplicate a PedGeometry object. - * - * This function constructs a PedGeometry object that is an identical but - * independent copy of \p geom. Both the input, \p geom, and the output - * should be destroyed with ped_geometry_destroy() when they are no - * longer needed. - * - * \return NULL on failure. - */ -PedGeometry* -ped_geometry_duplicate (const PedGeometry* geom) -{ - PED_ASSERT (geom != NULL, return NULL); - return ped_geometry_new (geom->dev, geom->start, geom->length); -} - -/** - * Return a PedGeometry object that refers to the intersection of - * \p a and \p b. - * - * This function constructs a PedGeometry object that describes the - * region that is common to both a and b. If there is no such common - * region, it returns NULL. (This situation is not treated as an - * error by much of GNU Parted.) - */ -PedGeometry* -ped_geometry_intersect (const PedGeometry* a, const PedGeometry* b) -{ - PedSector start; - PedSector end; - - if (!a || !b || a->dev != b->dev) - return NULL; - - start = PED_MAX (a->start, b->start); - end = PED_MIN (a->end, b->end); - if (start > end) - return NULL; - - return ped_geometry_new (a->dev, start, end - start + 1); -} - -/** - * Destroy a PedGeometry object. - */ -void -ped_geometry_destroy (PedGeometry* geom) -{ - PED_ASSERT (geom != NULL, return); - - ped_free (geom); -} - -/** - * Assign a new \p start, \p end (implicitly) and \p length to \p geom. - * - * \p geom->end is calculated from \p start and \p length. - */ -int -ped_geometry_set (PedGeometry* geom, PedSector start, PedSector length) -{ - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (geom->dev != NULL, return 0); - - if (length < 1) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have the end before the start!")); - return 0; - } - if (start < 0 || start + length - 1 >= geom->dev->length) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have a partition outside the disk!")); - return 0; - } - - geom->start = start; - geom->length = length; - geom->end = start + length - 1; - - return 1; -} - -/** - * Assign a new start to \p geom without changing \p geom->end. - * - * \p geom->length is updated accordingly. - */ -int -ped_geometry_set_start (PedGeometry* geom, PedSector start) -{ - return ped_geometry_set (geom, start, geom->end - start + 1); -} - -/** - * Assign a new end to \p geom without changing \p geom->start. - * - * \p geom->length is updated accordingly. - */ -int -ped_geometry_set_end (PedGeometry* geom, PedSector end) -{ - return ped_geometry_set (geom, geom->start, end - geom->start + 1); -} -/** - * Test if \p a overlaps with \p b. - * - * That is, they lie on the same physical device, and they share - * the same physical region at least partially. - * - * \return 1 if \p a and \p b overlap. - */ -int -ped_geometry_test_overlap (const PedGeometry* a, const PedGeometry* b) -{ - PED_ASSERT (a != NULL, return 0); - PED_ASSERT (b != NULL, return 0); - - if (a->dev != b->dev) - return 0; - - if (a->start < b->start) - return a->end >= b->start; - else - return b->end >= a->start; -} - -/** - * Tests if \p b lies completely within \p a. That is, they lie on the same - * physical device, and all of the \p b's region is contained inside - * \p a's. - * - * \return 1 if the region \p b describes is contained entirely inside \p a -*/ -int -ped_geometry_test_inside (const PedGeometry* a, const PedGeometry* b) -{ - PED_ASSERT (a != NULL, return 0); - PED_ASSERT (b != NULL, return 0); - - if (a->dev != b->dev) - return 0; - - return b->start >= a->start && b->end <= a->end; -} - -/** - * Tests if \a a and \p b refer to the same physical region. - * - * \return 1 if \p a and \p b describe the same regions - * - */ -int -ped_geometry_test_equal (const PedGeometry* a, const PedGeometry* b) -{ - PED_ASSERT (a != NULL, return 0); - PED_ASSERT (b != NULL, return 0); - - return a->dev == b->dev - && a->start == b->start - && a->end == b->end; -} - -/** - * Tests if \p sector is inside \p geom. - * - * \return 1 if sector lies within the \p region that \p geom describes - */ -int -ped_geometry_test_sector_inside (const PedGeometry* geom, PedSector sector) -{ - PED_ASSERT (geom != NULL, return 0); - - return sector >= geom->start && sector <= geom->end; -} - -/** - * Reads data from the region represented by \p geom. \p offset is the - * location from within the region, not from the start of the disk. - * \p count sectors are read into \p buffer. - * This is essentially equivalent to: - * \code - * ped_device_read (geom->disk->dev, buffer, geom->start + offset, count) - * \endcode - * - * \throws PED_EXCEPTION_ERROR when attempting to read sectors outside of - * partition - * - * \return 0 on failure - */ -int -ped_geometry_read (const PedGeometry* geom, void* buffer, PedSector offset, - PedSector count) -{ - PedSector real_start; - - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (buffer != NULL, return 0); - PED_ASSERT (offset >= 0, return 0); - PED_ASSERT (count >= 0, return 0); - - real_start = geom->start + offset; - - if (real_start + count - 1 > geom->end) - return 0; - - if (!ped_device_read (geom->dev, buffer, real_start, count)) - return 0; - return 1; -} - -/** - * Flushes the cache on \p geom. - * - * This function flushes all write-behind caches that might be holding - * writes made by ped_geometry_write() to \p geom. It is slow, because - * it guarantees cache coherency among all relevant caches. - * - * \return 0 on failure - */ -int -ped_geometry_sync (PedGeometry* geom) -{ - PED_ASSERT (geom != NULL, return 0); - return ped_device_sync (geom->dev); -} - -/** - * Flushes the cache on \p geom. - * - * This function flushes all write-behind caches that might be holding writes - * made by ped_geometry_write() to \p geom. It does NOT ensure cache coherency - * with other caches that cache data in the region described by \p geom. - * If you need cache coherency, use ped_geometry_sync() instead. - * - * \return 0 on failure - */ -int -ped_geometry_sync_fast (PedGeometry* geom) -{ - PED_ASSERT (geom != NULL, return 0); - return ped_device_sync_fast (geom->dev); -} - -/** - * Writes data into the region represented by \p geom. \p offset is the - * location from within the region, not from the start of the disk. - * \p count sectors are written. - * - * \return 0 on failure - */ -int -ped_geometry_write (PedGeometry* geom, const void* buffer, PedSector offset, - PedSector count) -{ - int exception_status; - PedSector real_start; - - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (buffer != NULL, return 0); - PED_ASSERT (offset >= 0, return 0); - PED_ASSERT (count >= 0, return 0); - - real_start = geom->start + offset; - - if (real_start + count - 1 > geom->end) { - exception_status = ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Attempt to write sectors %ld-%ld outside of " - "partition on %s."), - (long) offset, (long) (offset + count - 1), - geom->dev->path); - return exception_status == PED_EXCEPTION_IGNORE; - } - - if (!ped_device_write (geom->dev, buffer, real_start, count)) - return 0; - return 1; -} - -/** - * Checks for physical disk errors. \todo use ped_device_check() - * - * Checks a region for physical defects on \p geom. \p buffer is used - * for temporary storage for ped_geometry_check(), and has an undefined - * value. \p buffer is \p buffer_size sectors long. - * The region checked starts at \p offset sectors inside the - * region represented by \p geom, and is \p count sectors long. - * \p granularity specificies how sectors should be grouped - * together. The first bad sector to be returned will always be in - * the form: - * offset + n * granularity - * - * \return the first bad sector, or 0 if there were no physical errors - */ -PedSector -ped_geometry_check (PedGeometry* geom, void* buffer, PedSector buffer_size, - PedSector offset, PedSector granularity, PedSector count, - PedTimer* timer) -{ - PedSector group; - PedSector i; - PedSector read_len; - - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (buffer != NULL, return 0); - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("checking for bad blocks")); - -retry: - ped_exception_fetch_all(); - for (group = offset; group < offset + count; group += buffer_size) { - ped_timer_update (timer, 1.0 * (group - offset) / count); - read_len = PED_MIN (buffer_size, offset + count - group); - if (!ped_geometry_read (geom, buffer, group, read_len)) - goto found_error; - } - ped_exception_leave_all(); - ped_timer_update (timer, 1.0); - return 0; - -found_error: - ped_exception_catch(); - for (i = group; i + granularity < group + count; i += granularity) { - if (!ped_geometry_read (geom, buffer, i, granularity)) { - ped_exception_catch(); - ped_exception_leave_all(); - return i; - } - } - ped_exception_leave_all(); - goto retry; /* weird: failure on group read, but not individually */ -} - -/** - * This function takes a \p sector inside the region described by src, and - * returns that sector's address inside dst. This means that - * - * \code - * ped_geometry_read (dst, buf, ped_geometry_map(dst, src, sector), 1) - * \endcode - * - * does the same thing as - * - * \code - * ped_geometry_read (src, buf, sector, 1) - * \endcode - * - * Clearly, this will only work if \p src and \p dst overlap. - * - * \return -1 if \p sector is not within \p dst's space, - * or \p sector's address inside \p dst - * - */ -PedSector -ped_geometry_map (const PedGeometry* dst, const PedGeometry* src, - PedSector sector) -{ - PedSector result; - - PED_ASSERT (dst != NULL, return 0); - PED_ASSERT (src != NULL, return 0); - - if (!ped_geometry_test_sector_inside (src, sector)) - return -1; - if (dst->dev != src->dev) - return -1; - - result = src->start + sector - dst->start; - if (result < 0 || result > dst->length) - return -1; - - return result; -} - -/** @} */ - diff --git a/usr/src/lib/libparted/common/libparted/cs/natmath.c b/usr/src/lib/libparted/common/libparted/cs/natmath.c deleted file mode 100644 index 3a04aaa140..0000000000 --- a/usr/src/lib/libparted/common/libparted/cs/natmath.c +++ /dev/null @@ -1,503 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * \file natmath.c - */ - -/** - * \addtogroup PedAlignment - * - * \brief Alignment constraint model. - * - * This part of libparted models alignment constraints. - * - * @{ - */ - -#include -#include -#include -#include -#include - -/* Arrrghhh! Why doesn't C have tuples? */ -typedef struct { - PedSector gcd; /* "converges" to the gcd */ - PedSector x; - PedSector y; -} EuclidTriple; - -static const PedAlignment _any = { - .offset = 0, - .grain_size = 1 -}; - -const PedAlignment* ped_alignment_any = &_any; -const PedAlignment* ped_alignment_none = NULL; - -/* This function returns "a mod b", the way C should have done it! - * Mathematicians prefer -3 mod 4 to be 3. Reason: division by N - * is all about adding or subtracting N, and we like our remainders - * to be between 0 and N - 1. - */ -PedSector -abs_mod (PedSector a, PedSector b) -{ - if (a < 0) - return a % b + b; - else - return a % b; -} - -/* Rounds a number down to the closest number that is a multiple of - * grain_size. - */ -PedSector -ped_round_down_to (PedSector sector, PedSector grain_size) -{ - return sector - abs_mod (sector, grain_size); -} - -#ifdef __sun -extern PedSector -#else -extern inline PedSector -#endif -ped_div_round_up (PedSector numerator, PedSector divisor) -{ - return (numerator + divisor - 1) / divisor; -} - -#ifdef __sun -extern PedSector -#else -extern inline PedSector -#endif -ped_div_round_to_nearest (PedSector numerator, PedSector divisor) -{ - return (numerator + divisor/2) / divisor; -} - -/* Rounds a number up to the closest number that is a multiple of - * grain_size. - */ -PedSector -ped_round_up_to (PedSector sector, PedSector grain_size) -{ - if (sector % grain_size) - return ped_round_down_to (sector, grain_size) + grain_size; - else - return sector; -} - -/* Rounds a number to the closest number that is a multiple of grain_size. */ -PedSector -ped_round_to_nearest (PedSector sector, PedSector grain_size) -{ - if (sector % grain_size > grain_size/2) - return ped_round_up_to (sector, grain_size); - else - return ped_round_down_to (sector, grain_size); -} - -/* This function returns the largest number that divides both a and b. - * It uses the ancient Euclidean algorithm. - */ -PedSector -ped_greatest_common_divisor (PedSector a, PedSector b) -{ - PED_ASSERT (a >= 0, return 0); - PED_ASSERT (b >= 0, return 0); - - /* Put the arguments in the "right" format. (Recursive calls made by - * this function are always in the right format.) - */ - if (b > a) - return ped_greatest_common_divisor (b, a); - - if (b) - return ped_greatest_common_divisor (b, a % b); - else - return a; -} - -/** - * Initialize a preallocated piece of memory for an alignment object - * (used by PedConstraint). - * - * The object will represent all sectors \e s for which the equation - * s = offset + X * grain_size holds. - */ -int -ped_alignment_init (PedAlignment* align, PedSector offset, PedSector grain_size) -{ - PED_ASSERT (align != NULL, return 0); - - if (grain_size < 0) - return 0; - - if (grain_size) - align->offset = abs_mod (offset, grain_size); - else - align->offset = offset; - align->grain_size = grain_size; - - return 1; -} - -/** - * Return an alignment object (used by PedConstraint), representing all - * PedSector's that are of the form offset + X * grain_size. - */ -PedAlignment* -ped_alignment_new (PedSector offset, PedSector grain_size) -{ - PedAlignment* align; - - align = (PedAlignment*) ped_malloc (sizeof (PedAlignment)); - if (!align) - goto error; - - if (!ped_alignment_init (align, offset, grain_size)) - goto error_free_align; - - return align; - -error_free_align: - ped_free (align); -error: - return NULL; -} - -/** - * Free up memory associated with \p align. - */ -void -ped_alignment_destroy (PedAlignment* align) -{ - if (align) - ped_free (align); -} - -/** - * Return a duplicate of \p align. - */ -PedAlignment* -ped_alignment_duplicate (const PedAlignment* align) -{ - if (!align) - return NULL; - return ped_alignment_new (align->offset, align->grain_size); -} - -/* the extended Euclid algorithm. - * - * input: - * a and b, a > b - * - * output: - * gcd, x and y, such that: - * - * gcd = greatest common divisor of a and b - * gcd = x*a + y*b - */ -EuclidTriple -extended_euclid (int a, int b) -{ - EuclidTriple result; - EuclidTriple tmp; - - if (b == 0) { - result.gcd = a; - result.x = 1; - result.y = 0; - return result; - } - - tmp = extended_euclid (b, a % b); - result.gcd = tmp.gcd; - result.x = tmp.y; - result.y = tmp.x - (a/b) * tmp.y; - return result; -} - -/** - * This function computes a PedAlignment object that describes the - * intersection of two alignments. That is, a sector satisfies the - * new alignment object if and only if it satisfies both of the original - * ones. (See ped_alignment_is_aligned() for the meaning of "satisfies") - * - * Apart from the trivial cases (where one or both of the alignment objects - * constraints have no sectors that satisfy them), this is what we're trying to - * do: - * - two input constraints: \p a and \p b. - * - the new grain_size is going to be the lowest common multiple of - * \p a->grain_size and \p b->grain_size - * - hard part - solve the simultaneous equations, for offset, where offset, - * X and Y are variables. (Note: offset can be obtained from either X or Y, - * by substituing into either equation) - * - * \code - * offset = \p a->offset + X * \p a->grain_size (1) - * offset = \p b->offset + Y * \p b->grain_size (2) - * \endcode - * - * or, abbreviated: - * - * \code - * o = Ao + X*Ag (1) - * o = Bo + Y*Bg (2) - * - * => Ao + X*Ag = Bo + Y*Bg (1) = (2) - * X*Ag - Y*Bg = Bo - Ao (3) - * \endcode - * - * As it turns out, there only exists a solution if (Bo - Ao) is a multiple - * of the GCD of Ag and Bg. Reason: all linear combinations of Ag and Bg are - * multiples of the GCD. - * - * Proof: - * - * \code - * A * Ag + B * Bg - * = A * (\p a * gcd) + B * (\p b * gcd) - * = gcd * (A * \p a + B * \p b) - * \endcode - * - * gcd is a factor of the linear combination. QED - * - * Anyway, \p a * Ag + \p b * Bg = gcd can be solved (for \p a, \p b and gcd) - * with Euclid's extended algorithm. Then, we just multiply through by - * (Bo - Ao) / gcd to get (3). - * - * i.e. - * \code - * A * Ag + B * Bg = gcd - * A*(Bo-Ao)/gcd * Ag + B(Bo-Ao)/gcd * Bg = gcd * (Bo-Ao)/gcd - * X*Ag - Y*Bg = Bo - Ao (3) - * - * X = A*(Bo-Ao)/gcd - * Y = - B*(Bo-Ao)/gcd - * \endcode - * - * then: - * \code - * o = Ao + X*Ag (1) - * = Ao + A*(Bo-Ao)/gcd*Ag - * o = Bo + Y*Bg (2) - * = Bo - B*(Bo-Ao)/gcd*Ag - * \endcode - * - * Thanks go to Nathan Hurst (njh@hawthorn.csse.monash.edu.au) for figuring - * this algorithm out :-) - * - * \note Returned \c NULL is a valid PedAlignment object, and can be used - for ped_alignment_*() function. - * - * \return a PedAlignment on success, \c NULL on failure - */ -PedAlignment* -ped_alignment_intersect (const PedAlignment* a, const PedAlignment* b) -{ - PedSector new_grain_size; - PedSector new_offset; - PedSector delta_on_gcd; - EuclidTriple gcd_factors; - - - if (!a || !b) - return NULL; - - /*PED_DEBUG (0x10, "intersecting alignments (%d,%d) and (%d,%d)", - a->offset, a->grain_size, b->offset, b->grain_size); - */ - - if (a->grain_size < b->grain_size) { - const PedAlignment* tmp; - tmp = a; a = b; b = tmp; - } - - /* weird/trivial case: where the solution space for "a" or "b" is - * either empty or contains exactly one solution - */ - if (a->grain_size == 0 && b->grain_size == 0) { - if (a->offset == b->offset) - return ped_alignment_duplicate (a); - else - return NULL; - } - - /* general case */ - gcd_factors = extended_euclid (a->grain_size, b->grain_size); - - delta_on_gcd = (b->offset - a->offset) / gcd_factors.gcd; - new_offset = a->offset + gcd_factors.x * delta_on_gcd * a->grain_size; - new_grain_size = a->grain_size * b->grain_size / gcd_factors.gcd; - - /* inconsistency => no solution */ - if (new_offset - != b->offset - gcd_factors.y * delta_on_gcd * b->grain_size) - return NULL; - - return ped_alignment_new (new_offset, new_grain_size); -} - -/* This function returns the sector closest to "sector" that lies inside - * geom and satisfies the alignment constraint. - */ -static PedSector -_closest_inside_geometry (const PedAlignment* align, const PedGeometry* geom, - PedSector sector) -{ - PED_ASSERT (align != NULL, return -1); - - if (!align->grain_size) { - if (ped_alignment_is_aligned (align, geom, sector) - && (!geom || ped_geometry_test_sector_inside (geom, - sector))) - return sector; - else - return -1; - } - - if (sector < geom->start) - sector += ped_round_up_to (geom->start - sector, - align->grain_size); - if (sector > geom->end) - sector -= ped_round_up_to (sector - geom->end, - align->grain_size); - - if (!ped_geometry_test_sector_inside (geom, sector)) - return -1; - return sector; -} - -/** - * This function returns the closest sector to \p sector that lies inside - * \p geom that satisfies the given alignment constraint \p align. It prefers - * sectors that are beyond \p sector (are not smaller than \p sector), - * but does not guarantee that this. - * - * \return a PedSector on success, \c -1 on failure - */ -PedSector -ped_alignment_align_up (const PedAlignment* align, const PedGeometry* geom, - PedSector sector) -{ - PedSector result; - - PED_ASSERT (align != NULL, return -1); - - if (!align->grain_size) - result = align->offset; - else - result = ped_round_up_to (sector - align->offset, - align->grain_size) - + align->offset; - - if (geom) - result = _closest_inside_geometry (align, geom, result); - return result; -} - -/** - * This function returns the closest sector to \p sector that lies inside - * \p geom that satisfies the given alignment constraint \p align. It prefers - * sectors that are before \p sector (are not larger than \p sector), - * but does not guarantee that this. - * - * \return a PedSector on success, \c -1 on failure - */ -PedSector -ped_alignment_align_down (const PedAlignment* align, const PedGeometry* geom, - PedSector sector) -{ - PedSector result; - - PED_ASSERT (align != NULL, return -1); - - if (!align->grain_size) - result = align->offset; - else - result = ped_round_down_to (sector - align->offset, - align->grain_size) - + align->offset; - - if (geom) - result = _closest_inside_geometry (align, geom, result); - return result; -} - -/* Returns either a or b, depending on which is closest to "sector". */ -static PedSector -closest (PedSector sector, PedSector a, PedSector b) -{ - if (a == -1) - return b; - if (b == -1) - return a; - - if (abs (sector - a) < abs (sector - b)) - return a; - else - return b; -} - -/** - * This function returns the sector that is closest to \p sector, - * satisfies the \p align constraint and lies inside \p geom. - * - * \return a PedSector on success, \c -1 on failure - */ -PedSector -ped_alignment_align_nearest (const PedAlignment* align, const PedGeometry* geom, - PedSector sector) -{ - PED_ASSERT (align != NULL, return -1); - - return closest (sector, ped_alignment_align_up (align, geom, sector), - ped_alignment_align_down (align, geom, sector)); -} - -/** - * This function returns 1 if \p sector satisfies the alignment - * constraint \p align and lies inside \p geom. - * - * \return \c 1 on success, \c 0 on failure - */ -int -ped_alignment_is_aligned (const PedAlignment* align, const PedGeometry* geom, - PedSector sector) -{ - if (!align) - return 0; - - if (geom && !ped_geometry_test_sector_inside (geom, sector)) - return 0; - - if (align->grain_size) - return (sector - align->offset) % align->grain_size == 0; - else - return sector == align->offset; -} - -/** - * @} - */ - diff --git a/usr/src/lib/libparted/common/libparted/debug.c b/usr/src/lib/libparted/common/libparted/debug.c deleted file mode 100644 index 4d45e4c132..0000000000 --- a/usr/src/lib/libparted/common/libparted/debug.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#ifdef DEBUG - -#if HAVE_BACKTRACE -#include -#endif - -static void default_handler ( const int level, const char* file, int line, - const char* function, const char* msg ); -static PedDebugHandler* debug_handler = &default_handler; - - -/** - * Default debug handler. - * Will print all information to stderr. - */ -static void default_handler ( const int level, const char* file, int line, - const char* function, const char* msg ) -{ - fprintf ( stderr, "[%d] %s:%d (%s): %s\n", - level, file, line, function, msg ); -} - -/** - * Send a debug message. - * Do not call this directly -- use PED_DEBUG() instead. - * - * level log level, 0 ~= "print definitely" - */ -void ped_debug ( const int level, const char* file, int line, - const char* function, const char* msg, ... ) -{ - va_list arg_list; - char* msg_concat = ped_malloc(8192); - - va_start ( arg_list, msg ); - vsnprintf ( msg_concat, 8192, msg, arg_list ); - va_end ( arg_list ); - - debug_handler ( level, file, line, function, msg_concat ); - - ped_free ( msg_concat ); -} - -/* - * handler debug handler; NULL for default handler - */ -void ped_debug_set_handler ( PedDebugHandler* handler ) -{ - debug_handler = ( handler ? handler : default_handler ); -} - -/* - * Check an assertion. - * Do not call this directly -- use PED_ASSERT() instead. - */ -int ped_assert ( int cond, const char* cond_text, - const char* file, int line, const char* function ) -{ - PedExceptionOption opt; - - if ( cond ) - return 1; - -#if HAVE_BACKTRACE - /* Print backtrace stack */ - void *stack[20]; - char **strings, **string; - int size = backtrace(stack, 20); - strings = backtrace_symbols(stack, size); - - if (strings) { - printf(_("Backtrace has %d calls on stack:\n"), size); - for (string = strings; size > 0; size--, string++) - printf(" %d: %s\n", size, *string); - - free(strings); - } -#endif - - /* Throw the exception */ - opt = ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_IGNORE_CANCEL, - _("Assertion (%s) at %s:%d in function %s() failed."), - cond_text, file, line, function ); - - return ( opt == PED_EXCEPTION_IGNORE ); -} - -#endif /* DEBUG */ - diff --git a/usr/src/lib/libparted/common/libparted/device.c b/usr/src/lib/libparted/common/libparted/device.c deleted file mode 100644 index 07e0a0fe6a..0000000000 --- a/usr/src/lib/libparted/common/libparted/device.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999 - 2001, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file device.c */ - -/** - * \addtogroup PedDevice - * - * \brief Device access. - * - * When ped_device_probe_all() is called, libparted attempts to detect all - * devices. It constructs a list which can be accessed with - * ped_device_get_next(). - * - * If you want to use a device that isn't on the list, use - * ped_device_get(). Also, there may be OS-specific constructors, for creating - * devices from file descriptors, stores, etc. For example, - * ped_device_new_from_store(). - * - * @{ - */ - -#include - -#include -#include - -#include -#include -#include - -static PedDevice* devices; /* legal advice says: initialized to NULL, - under section 6.7.8 part 10 - of ISO/EIC 9899:1999 */ - -#ifndef HAVE_CANONICALIZE_FILE_NAME -char * -canonicalize_file_name (const char *name) -{ - char * buf; - int size; - char * result; - -#ifdef PATH_MAX - size = PATH_MAX; -#else - /* Bigger is better; realpath has no way todo bounds checking. */ - size = 4096; -#endif - - /* Just in case realpath does not NULL terminate the string - * or it just fits in SIZE without a NULL terminator. */ - buf = calloc (size + 1, sizeof(char)); - if (! buf) { - errno = ENOMEM; - return NULL; - } - - result = realpath (name, buf); - if (! result) - free (buf); - - return result; -} -#else -extern char *canonicalize_file_name (const char *name); -#endif /* !HAVE_CANONICALIZE_FILE_NAME */ - -static void -_device_register (PedDevice* dev) -{ - PedDevice* walk; - for (walk = devices; walk && walk->next; walk = walk->next); - if (walk) - walk->next = dev; - else - devices = dev; - dev->next = NULL; -} - -static void -_device_unregister (PedDevice* dev) -{ - PedDevice* walk; - PedDevice* last = NULL; - - for (walk = devices; walk != NULL; last = walk, walk = walk->next) { - if (walk == dev) break; - } - - if (last) - last->next = dev->next; - else - devices = dev->next; -} - -/** - * Returns the next device that was detected by ped_device_probe_all(), or - * calls to ped_device_get_next(). - * If dev is NULL, returns the first device. - * - * \return NULL if dev is the last device. - */ -PedDevice* -ped_device_get_next (const PedDevice* dev) -{ - if (dev) - return dev->next; - else - return devices; -} - -void -_ped_device_probe (const char* path) -{ - PedDevice* dev; - - PED_ASSERT (path != NULL, return); - - ped_exception_fetch_all (); - dev = ped_device_get (path); - if (!dev) - ped_exception_catch (); - ped_exception_leave_all (); -} - -/** - * Attempts to detect all devices. - */ -void -ped_device_probe_all () -{ - ped_architecture->dev_ops->probe_all (); -} - -/** - * Close/free all devices. - * Called by ped_done(), so you do not need to worry about it. - */ -void -ped_device_free_all () -{ - while (devices) - ped_device_destroy (devices); -} - -/** - * Gets the device "name", where name is usually the block device, e.g. - * /dev/sdb. If the device wasn't detected with ped_device_probe_all(), - * an attempt will be made to detect it again. If it is found, it will - * be added to the list. - */ -PedDevice* -ped_device_get (const char* path) -{ - PedDevice* walk; - char* normal_path; - - PED_ASSERT (path != NULL, return NULL); - normal_path = canonicalize_file_name (path); - if (!normal_path) - /* Well, maybe it is just that the file does not exist. - * Try it anyway. */ - normal_path = strdup (path); - if (!normal_path) - return NULL; - - for (walk = devices; walk != NULL; walk = walk->next) { - if (!strcmp (walk->path, normal_path)) { - ped_free (normal_path); - return walk; - } - } - - walk = ped_architecture->dev_ops->_new (normal_path); - ped_free (normal_path); - if (!walk) - return NULL; - - _device_register (walk); - return walk; -} - -/** - * Destroys a device and removes it from the device list, and frees - * all resources associated with the device (all resources allocated - * when the device was created). - */ -void -ped_device_destroy (PedDevice* dev) -{ - _device_unregister (dev); - - while (dev->open_count) { - if (!ped_device_close (dev)) - break; - } - - ped_architecture->dev_ops->destroy (dev); -} - -void -ped_device_cache_remove(PedDevice *dev) -{ - _device_unregister (dev); -} - -int -ped_device_is_busy (PedDevice* dev) -{ - return ped_architecture->dev_ops->is_busy (dev); -} - -/** - * Attempt to open a device to allow use of read, write and sync functions. - * - * The meaning of "open" is architecture-dependent. Apart from requesting - * access to the device from the operating system, it does things like flushing - * caches. - * \note May allocate resources. Any resources allocated here will - * be freed by a final ped_device_close(). (ped_device_open() may be - * called multiple times -- it's a ref-count-like mechanism) - * - * \return zero on failure - */ -int -ped_device_open (PedDevice* dev) -{ - int status; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - - if (dev->open_count) - status = ped_architecture->dev_ops->refresh_open (dev); - else - status = ped_architecture->dev_ops->open (dev); - if (status) - dev->open_count++; - return status; -} - -/** - * Close dev. - * If this is the final close, then resources allocated by - * ped_device_open() are freed. - * - * \return zero on failure - */ -int -ped_device_close (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - if (--dev->open_count) - return ped_architecture->dev_ops->refresh_close (dev); - else - return ped_architecture->dev_ops->close (dev); -} - -/** - * Begins external access mode. External access mode allows you to - * safely do IO on the device. If a PedDevice is open, then you should - * not do any IO on that device, e.g. by calling an external program - * like e2fsck, unless you put it in external access mode. You should - * not use any libparted commands that do IO to a device, e.g. - * ped_file_system_{open|resize|copy}, ped_disk_{read|write}), while - * a device is in external access mode. - * Also, you should not ped_device_close() a device, while it is - * in external access mode. - * Note: ped_device_begin_external_access_mode() does things like - * tell the kernel to flush its caches. - * - * Close a device while pretending it is still open. - * This is useful for temporarily suspending libparted access to the device - * in order for an external program to access it. - * (Running external programs while the device is open can cause cache - * coherency problems.) - * - * In particular, this function keeps track of dev->open_count, so that - * reference counting isn't screwed up. - * - * \return zero on failure. - */ -int -ped_device_begin_external_access (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - - dev->external_mode = 1; - if (dev->open_count) - return ped_architecture->dev_ops->close (dev); - else - return 1; -} - -/** - * \brief Complementary function to ped_device_begin_external_access. - * - * \note does things like tell the kernel to flush the device's cache. - * - * \return zero on failure. - */ -int -ped_device_end_external_access (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (dev->external_mode, return 0); - - dev->external_mode = 0; - if (dev->open_count) - return ped_architecture->dev_ops->open (dev); - else - return 1; -} - -/** - * \internal Read count sectors from dev into buffer, beginning with sector - * start. - * - * \return zero on failure. - */ -int -ped_device_read (const PedDevice* dev, void* buffer, PedSector start, - PedSector count) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (buffer != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - return (ped_architecture->dev_ops->read) (dev, buffer, start, count); -} - -/** - * \internal Write count sectors from buffer to dev, starting at sector - * start. - * - * \return zero on failure. - * - * \sa PedDevice::sector_size - * \sa PedDevice::phys_sector_size - */ -int -ped_device_write (PedDevice* dev, const void* buffer, PedSector start, - PedSector count) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (buffer != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - return (ped_architecture->dev_ops->write) (dev, buffer, start, count); -} - -PedSector -ped_device_check (PedDevice* dev, void* buffer, PedSector start, - PedSector count) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - return (ped_architecture->dev_ops->check) (dev, buffer, start, count); -} - -/** - * \internal Flushes all write-behind caches that might be holding up - * writes. - * It is slow because it guarantees cache coherency among all relevant caches. - * - * \return zero on failure - */ -int -ped_device_sync (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - return ped_architecture->dev_ops->sync (dev); -} - -/** - * \internal Flushes all write-behind caches that might be holding writes. - * \warning Does NOT ensure cache coherency with other caches. - * If you need cache coherency, use ped_device_sync() instead. - * - * \return zero on failure - */ -int -ped_device_sync_fast (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (!dev->external_mode, return 0); - PED_ASSERT (dev->open_count > 0, return 0); - - return ped_architecture->dev_ops->sync_fast (dev); -} - -/** - * Get a constraint that represents hardware requirements on alignment and - * geometry. - * This is, for example, important for media that have a physical sector - * size that is a multiple of the logical sector size. - * - * \warning This function is experimental for physical sector sizes not equal to - * 2^9. - */ -PedConstraint* -ped_device_get_constraint (PedDevice* dev) -{ - int multiplier = dev->phys_sector_size / dev->sector_size; - - PedAlignment* start_align = ped_alignment_new (multiplier, multiplier); - - PedConstraint* c = ped_constraint_new ( - start_align, ped_alignment_any, - ped_geometry_new (dev, 0, dev->length), - ped_geometry_new (dev, 0, dev->length), - 1, dev->length); - - return c; -} - -/** @} */ - diff --git a/usr/src/lib/libparted/common/libparted/disk.c b/usr/src/lib/libparted/common/libparted/disk.c deleted file mode 100644 index 1582f26e05..0000000000 --- a/usr/src/lib/libparted/common/libparted/disk.c +++ /dev/null @@ -1,2265 +0,0 @@ - /* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005, 2007 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file disk.c */ - -/** - * \addtogroup PedDisk - * - * \brief Disk label access. - * - * Most programs will need to use ped_disk_new() or ped_disk_new_fresh() to get - * anything done. A PedDisk is always associated with a device and has a - * partition table. There are different types of partition tables (or disk - * labels). These are represented by the PedDiskType enumeration. - * - * @{ - */ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -# define N_(String) (String) -#else -# define _(String) (String) -# define N_(String) (String) -#endif /* ENABLE_NLS */ - -/* UPDATE MODE functions */ -#ifdef DEBUG -static int _disk_check_sanity (PedDisk* disk); -#endif -static void _disk_push_update_mode (PedDisk* disk); -static void _disk_pop_update_mode (PedDisk* disk); -static int _disk_raw_insert_before (PedDisk* disk, PedPartition* loc, - PedPartition* part); -static int _disk_raw_insert_after (PedDisk* disk, PedPartition* loc, - PedPartition* part); -static int _disk_raw_remove (PedDisk* disk, PedPartition* part); -static int _disk_raw_add (PedDisk* disk, PedPartition* part); - -static PedDiskType* disk_types = NULL; - -void -ped_disk_type_register (PedDiskType* disk_type) -{ - PED_ASSERT (disk_type != NULL, return); - PED_ASSERT (disk_type->ops != NULL, return); - PED_ASSERT (disk_type->name != NULL, return); - - /* pretend that "next" isn't part of the struct :-) */ - ((struct _PedDiskType*) disk_type)->next = disk_types; - disk_types = (struct _PedDiskType*) disk_type; -} - -void -ped_disk_type_unregister (PedDiskType* disk_type) -{ - PedDiskType* walk; - PedDiskType* last = NULL; - - PED_ASSERT (disk_types != NULL, return); - PED_ASSERT (disk_type != NULL, return); - - for (walk = disk_types; walk && walk != disk_type; - last = walk, walk = walk->next); - - PED_ASSERT (walk != NULL, return); - if (last) - ((struct _PedDiskType*) last)->next = disk_type->next; - else - disk_types = disk_type->next; -} - -/** - * Deprecated: use ped_disk_type_regiser. - */ -void -ped_register_disk_type (PedDiskType* disk_type) -{ - ped_disk_type_register (disk_type); -} - -/** - * Deprecated: use ped_disk_type_unregiser. - */ -void -ped_unregister_disk_type (PedDiskType* disk_type) -{ - ped_disk_type_unregister (disk_type); -} - -/** - * Return the next disk type registers, after "type". If "type" is - * NULL, returns the first disk type. - * - * \return Next disk; NULL if "type" is the last registered disk type. - */ -PedDiskType* -ped_disk_type_get_next (PedDiskType* type) -{ - if (type) - return type->next; - else - return disk_types; -} - -/** - * Return the disk type with a name of "name". - * - * \return Disk type; NULL if no match. - */ -PedDiskType* -ped_disk_type_get (const char* name) -{ - PedDiskType* walk = NULL; - - PED_ASSERT (name != NULL, return NULL); - - for (walk = ped_disk_type_get_next (NULL); walk; - walk = ped_disk_type_get_next (walk)) - if (strcasecmp (walk->name, name) == 0) - break; - - return walk; -} - -/** - * Return the type of partition table detected on "dev". - * - * \return Type; NULL if none was detected. - */ -PedDiskType* -ped_disk_probe (PedDevice* dev) -{ - PedDiskType *walk = NULL; - - PED_ASSERT (dev != NULL, return NULL); - - if (!ped_device_open (dev)) - return NULL; - - ped_exception_fetch_all (); - for (walk = ped_disk_type_get_next (NULL); walk; - walk = ped_disk_type_get_next (walk)) { - if (walk->ops->probe (dev)) - break; - } - - if (ped_exception) - ped_exception_catch (); - ped_exception_leave_all (); - - ped_device_close (dev); - return walk; -} - -/** - * Read the partition table off a device (if one is found). - * - * \warning May modify \p dev->cylinders, \p dev->heads and \p dev->sectors - * if the partition table indicates that the existing values - * are incorrect. - * - * \return A new \link _PedDisk PedDisk \endlink object; - * NULL on failure (e.g. partition table not detected). - */ -PedDisk* -ped_disk_new (PedDevice* dev) -{ - PedDiskType* type; - PedDisk* disk; - - PED_ASSERT (dev != NULL, return NULL); - - if (!ped_device_open (dev)) - goto error; - - type = ped_disk_probe (dev); - if (!type) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s: unrecognised disk label"), - dev->path); - goto error_close_dev; - } - disk = ped_disk_new_fresh (dev, type); - if (!disk) - goto error_close_dev; - if (!type->ops->read (disk)) - goto error_destroy_disk; - disk->needs_clobber = 0; - ped_device_close (dev); - return disk; - -error_destroy_disk: - ped_disk_destroy (disk); -error_close_dev: - ped_device_close (dev); -error: - return NULL; -} - -static int -_add_duplicate_part (PedDisk* disk, PedPartition* old_part) -{ - PedPartition* new_part; - PedConstraint* constraint_exact; - - new_part = disk->type->ops->partition_duplicate (old_part); - if (!new_part) - goto error; - new_part->disk = disk; - - constraint_exact = ped_constraint_exact (&new_part->geom); - if (!constraint_exact) - goto error_destroy_new_part; - if (!ped_disk_add_partition (disk, new_part, constraint_exact)) - goto error_destroy_constraint_exact; - ped_constraint_destroy (constraint_exact); - return 1; - -error_destroy_constraint_exact: - ped_constraint_destroy (constraint_exact); -error_destroy_new_part: - ped_partition_destroy (new_part); -error: - return 0; -} - -/** - * Clone a \link _PedDisk PedDisk \endlink object. - * - * \return Deep copy of \p old_disk, NULL on failure. - */ -PedDisk* -ped_disk_duplicate (const PedDisk* old_disk) -{ - PedDisk* new_disk; - PedPartition* old_part; - - PED_ASSERT (old_disk != NULL, return NULL); - PED_ASSERT (!old_disk->update_mode, return NULL); - PED_ASSERT (old_disk->type->ops->duplicate != NULL, return NULL); - PED_ASSERT (old_disk->type->ops->partition_duplicate != NULL, - return NULL); - - new_disk = old_disk->type->ops->duplicate (old_disk); - if (!new_disk) - goto error; - - _disk_push_update_mode (new_disk); - for (old_part = ped_disk_next_partition (old_disk, NULL); old_part; - old_part = ped_disk_next_partition (old_disk, old_part)) { - if (ped_partition_is_active (old_part)) { - if (!_add_duplicate_part (new_disk, old_part)) - goto error_destroy_new_disk; - } - } - _disk_pop_update_mode (new_disk); - return new_disk; - -error_destroy_new_disk: - ped_disk_destroy (new_disk); -error: - return NULL; -} - -/** - * Remove all identifying signatures of a partition table, - * except for partition tables of a given type. - * - * \return 0 on error, 1 otherwise. - * - * \sa ped_disk_clobber() - */ -int -ped_disk_clobber_exclude (PedDevice* dev, const PedDiskType* exclude) -{ - PedDiskType* walk; - - PED_ASSERT (dev != NULL, goto error); - - if (!ped_device_open (dev)) - goto error; - - for (walk = ped_disk_type_get_next (NULL); walk; - walk = ped_disk_type_get_next (walk)) { - int probed; - - if (walk == exclude) - continue; - - ped_exception_fetch_all (); - probed = walk->ops->probe (dev); - if (!probed) - ped_exception_catch (); - ped_exception_leave_all (); - - if (probed && walk->ops->clobber) { - if (!walk->ops->clobber (dev)) - goto error_close_dev; - } - } - ped_device_close (dev); - return 1; - -error_close_dev: - ped_device_close (dev); -error: - return 0; -} - -/** - * Remove all identifying signatures of a partition table, - * - * \return 0 on error, 1 otherwise. - * - * \sa ped_disk_clobber_exclude() - */ -int -ped_disk_clobber (PedDevice* dev) -{ - return ped_disk_clobber_exclude (dev, NULL); -} - -/** - * Create a new partition table on \p dev. - * - * This new partition table is only created in-memory, and nothing is written - * to disk until ped_disk_commit_to_dev() is called. - * - * \return The newly constructed \link _PedDisk PedDisk \endlink, - * NULL on failure. - */ -PedDisk* -ped_disk_new_fresh (PedDevice* dev, const PedDiskType* type) -{ - PedDisk* disk; - - PED_ASSERT (dev != NULL, return NULL); - PED_ASSERT (type != NULL, return NULL); - PED_ASSERT (type->ops->alloc != NULL, return NULL); - - disk = type->ops->alloc (dev); - if (!disk) - goto error; - _disk_pop_update_mode (disk); - PED_ASSERT (disk->update_mode == 0, goto error_destroy_disk); - - disk->needs_clobber = 1; - return disk; - -error_destroy_disk: - ped_disk_destroy (disk); -error: - return NULL; -} - -PedDisk* -_ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type) -{ - PedDisk* disk; - - disk = (PedDisk*) ped_malloc (sizeof (PedDisk)); - if (!disk) - goto error; - - disk->dev = (PedDevice*)dev; - disk->type = disk_type; - disk->update_mode = 1; - disk->part_list = NULL; - return disk; - - ped_free (disk); -error: - return NULL; -} - -void -_ped_disk_free (PedDisk* disk) -{ - _disk_push_update_mode (disk); - ped_disk_delete_all (disk); - ped_free (disk); -} - -/** - * Close \p disk. - * - * What this function does depends on the PedDiskType of \p disk, - * but you can generally assume that outstanding writes are flushed - * (this mainly means that _ped_disk_free is called). - */ -void -ped_disk_destroy (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return); - PED_ASSERT (!disk->update_mode, return); - - disk->type->ops->free (disk); -} - -/** - * Tell the operating system kernel about the partition table layout - * of \p disk. - * - * This is rather loosely defined: for example, on old versions of Linux, - * it simply calls the BLKRRPART ioctl, which tells the kernel to - * reread the partition table. On newer versions (2.4.x), it will - * use the new blkpg interface to tell Linux where each partition - * starts/ends, etc. In this case, Linux does not need to have support for - * a specific type of partition table. - * - * \return 0 on failure, 1 otherwise. - */ -int -ped_disk_commit_to_os (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return 0); - - if (!ped_device_open (disk->dev)) - goto error; - if (!ped_architecture->disk_ops->disk_commit (disk)) - goto error_close_dev; - ped_device_close (disk->dev); - return 1; - -error_close_dev: - ped_device_close (disk->dev); -error: - return 0; -} - -/** - * Write the changes made to the in-memory description - * of a partition table to the device. - * - * \return 0 on failure, 1 otherwise. - */ -int -ped_disk_commit_to_dev (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, goto error); - PED_ASSERT (!disk->update_mode, goto error); - - if (!disk->type->ops->write) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("This libparted doesn't have write support for " - "%s. Perhaps it was compiled read-only."), - disk->type->name); - goto error; - } - - if (!ped_device_open (disk->dev)) - goto error; - - if (disk->needs_clobber) { - if (!ped_disk_clobber_exclude (disk->dev, disk->type)) - goto error_close_dev; - disk->needs_clobber = 0; - } - if (!disk->type->ops->write (disk)) - goto error_close_dev; - ped_device_close (disk->dev); - return 1; - -error_close_dev: - ped_device_close (disk->dev); -error: - return 0; -} - -/* - * This function writes the in-memory changes to a partition table to - * disk and informs the operating system of the changes. - * - * \note Equivalent to calling first ped_disk_commit_to_dev(), then - * ped_disk_commit_to_os(). - * - * \return 0 on failure, 1 otherwise. - */ -int -ped_disk_commit (PedDisk* disk) -{ - if (!ped_disk_commit_to_dev (disk)) - return 0; - return ped_disk_commit_to_os (disk); -} - -/** - * \addtogroup PedPartition - * - * @{ - */ - -/** - * Check whether a partition is mounted or busy in some - * other way. - * - * \note An extended partition is busy if any logical partitions are mounted. - * - * \return \c 1 if busy. - */ -int -ped_partition_is_busy (const PedPartition* part) -{ - PED_ASSERT (part != NULL, return 1); - - return ped_architecture->disk_ops->partition_is_busy (part); -} - -/** - * Return a path that can be used to address the partition in the - * operating system. - */ -char* -ped_partition_get_path (const PedPartition* part) -{ - PED_ASSERT (part != NULL, return NULL); - - return ped_architecture->disk_ops->partition_get_path (part); -} - -/** @} */ - -/** - * \addtogroup PedDisk - * - * @{ - */ - -/** - * Perform a sanity check on a partition table. - * - * \note The check performed is generic (i.e. it does not depends on the label - * type of the disk. - * - * \throws PED_EXCEPTION_WARNING if a partition type ID does not match the file - * system on it. - * - * \return 0 if the check fails, 1 otherwise. - */ -int -ped_disk_check (const PedDisk* disk) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - const PedFileSystemType* fs_type = walk->fs_type; - PedGeometry* geom; - PedSector length_error; - PedSector max_length_error; - - if (!ped_partition_is_active (walk) || !fs_type) - continue; - - geom = ped_file_system_probe_specific (fs_type, &walk->geom); - if (!geom) - continue; - - length_error = abs (walk->geom.length - geom->length); - max_length_error = PED_MAX (4096, walk->geom.length / 100); - if (!ped_geometry_test_inside (&walk->geom, geom) - || length_error > max_length_error) { - char* part_size = ped_unit_format (disk->dev, walk->geom.length); - char* fs_size = ped_unit_format (disk->dev, geom->length); - PedExceptionOption choice; - - choice = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("Partition %d is %s, but the file system is " - "%s."), - walk->num, part_size, fs_size); - - ped_free (part_size); - ped_free (fs_size); - - if (choice != PED_EXCEPTION_IGNORE) - return 0; - } - } - - return 1; -} - -/** - * This function checks if a particular type of partition table supports - * a feature. - * - * \return 1 if \p disk_type supports \p feature, 0 otherwise. - */ -int -ped_disk_type_check_feature (const PedDiskType* disk_type, - PedDiskTypeFeature feature) -{ - return (disk_type->features & feature) != 0; -} - -/** - * Get the number of primary partitions. - */ -int -ped_disk_get_primary_partition_count (const PedDisk* disk) -{ - PedPartition* walk; - int count = 0; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - if (ped_partition_is_active (walk) - && ! (walk->type & PED_PARTITION_LOGICAL)) - count++; - } - - return count; -} - -/** - * Get the highest partition number on \p disk. - */ -int -ped_disk_get_last_partition_num (const PedDisk* disk) -{ - PedPartition* walk; - int highest = -1; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - if (walk->num > highest) - highest = walk->num; - } - - return highest; -} - -/** - * Get the maximum number of (primary) partitions the disk label supports. - * - * For example, MacIntosh partition maps can have different sizes, - * and accordingly support a different number of partitions. - */ -int -ped_disk_get_max_primary_partition_count (const PedDisk* disk) -{ - PED_ASSERT (disk->type != NULL, return 0); - PED_ASSERT (disk->type->ops->get_max_primary_partition_count != NULL, - return 0); - - return disk->type->ops->get_max_primary_partition_count (disk); -} - -/** - * \internal We turned a really nasty bureaucracy problem into an elegant maths - * problem :-) Basically, there are some constraints to a partition's - * geometry: - * - * (1) it must start and end on a "disk" block, determined by the disk label - * (not the hardware). (constraint represented by a PedAlignment) - * - * (2) if we're resizing a partition, we MIGHT need to keep each block aligned. - * Eg: if an ext2 file system has 4k blocks, then we can only move the start - * by a multiple of 4k. (constraint represented by a PedAlignment) - * - * (3) we need to keep the start and end within the device's physical - * boundaries. (constraint represented by a PedGeometry) - * - * Satisfying (1) and (2) simultaneously required a bit of fancy maths ;-) See - * ped_alignment_intersect() - * - * The application of these constraints is in disk_*.c's *_partition_align() - * function. - */ -static int -_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - const PedDiskType* disk_type; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->num != -1, return 0); - PED_ASSERT (part->disk != NULL, return 0); - disk_type = part->disk->type; - PED_ASSERT (disk_type != NULL, return 0); - PED_ASSERT (disk_type->ops->partition_align != NULL, return 0); - PED_ASSERT (part->disk->update_mode, return 0); - - return disk_type->ops->partition_align (part, constraint); -} - -static int -_partition_enumerate (PedPartition* part) -{ - const PedDiskType* disk_type; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - disk_type = part->disk->type; - PED_ASSERT (disk_type != NULL, return 0); - PED_ASSERT (disk_type->ops->partition_enumerate != NULL, return 0); - - return disk_type->ops->partition_enumerate (part); -} - -/** - * Gives all the (active) partitions a number. It should preserve the numbers - * and orders as much as possible. - */ -static int -ped_disk_enumerate_partitions (PedDisk* disk) -{ - PedPartition* walk; - int i; - int end; - - PED_ASSERT (disk != NULL, return 0); - -/* first "sort" already-numbered partitions. (e.g. if a logical partition - * is removed, then all logical partitions that were number higher MUST be - * renumbered) - */ - end = ped_disk_get_last_partition_num (disk); - for (i=1; i<=end; i++) { - walk = ped_disk_get_partition (disk, i); - if (walk) { - if (!_partition_enumerate (walk)) - return 0; - } - } - -/* now, number un-numbered partitions */ - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - if (ped_partition_is_active (walk) && walk->num == -1) { - if (!_partition_enumerate (walk)) - return 0; - } - } - - return 1; -} - -static int -_disk_remove_metadata (PedDisk* disk) -{ - PedPartition* walk = NULL; - PedPartition* next; - - PED_ASSERT (disk != NULL, return 0); - - next = ped_disk_next_partition (disk, walk); - - while (next) { - walk = next; - while (1) { - next = ped_disk_next_partition (disk, next); - if (!next || next->type & PED_PARTITION_METADATA) - break; - } - if (walk->type & PED_PARTITION_METADATA) - ped_disk_delete_partition (disk, walk); - } - return 1; -} - -static int -_disk_alloc_metadata (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return 0); - - if (!disk->update_mode) - _disk_remove_metadata (disk); - - return disk->type->ops->alloc_metadata (disk); -} - -static int -_disk_remove_freespace (PedDisk* disk) -{ - PedPartition* walk; - PedPartition* next; - - walk = ped_disk_next_partition (disk, NULL); - for (; walk; walk = next) { - next = ped_disk_next_partition (disk, walk); - - if (walk->type & PED_PARTITION_FREESPACE) { - _disk_raw_remove (disk, walk); - ped_partition_destroy (walk); - } - } - - return 1; -} - -static int -_alloc_extended_freespace (PedDisk* disk) -{ - PedSector last_end; - PedPartition* walk; - PedPartition* last; - PedPartition* free_space; - PedPartition* extended_part; - - extended_part = ped_disk_extended_partition (disk); - if (!extended_part) - return 1; - - last_end = extended_part->geom.start; - last = NULL; - - for (walk = extended_part->part_list; walk; walk = walk->next) { - if (walk->geom.start > last_end + 1) { - free_space = ped_partition_new ( - disk, - PED_PARTITION_FREESPACE - | PED_PARTITION_LOGICAL, - NULL, - last_end + 1, walk->geom.start - 1); - _disk_raw_insert_before (disk, walk, free_space); - } - - last = walk; - last_end = last->geom.end; - } - - if (last_end < extended_part->geom.end) { - free_space = ped_partition_new ( - disk, - PED_PARTITION_FREESPACE | PED_PARTITION_LOGICAL, - NULL, - last_end + 1, extended_part->geom.end); - - if (last) - return _disk_raw_insert_after (disk, last, free_space); - else - extended_part->part_list = free_space; - } - - return 1; -} - -static int -_disk_alloc_freespace (PedDisk* disk) -{ - PedSector last_end; - PedPartition* walk; - PedPartition* last; - PedPartition* free_space; - - if (!_disk_remove_freespace (disk)) - return 0; - if (!_alloc_extended_freespace (disk)) - return 0; - - last = NULL; - last_end = -1; - - for (walk = disk->part_list; walk; walk = walk->next) { - if (walk->geom.start > last_end + 1) { - free_space = ped_partition_new (disk, - PED_PARTITION_FREESPACE, NULL, - last_end + 1, walk->geom.start - 1); - _disk_raw_insert_before (disk, walk, free_space); - } - - last = walk; - last_end = last->geom.end; - } - - if (last_end < disk->dev->length - 1) { - free_space = ped_partition_new (disk, - PED_PARTITION_FREESPACE, NULL, - last_end + 1, disk->dev->length - 1); - if (last) - return _disk_raw_insert_after (disk, last, free_space); - else - disk->part_list = free_space; - } - - return 1; -} - -/** - * Update mode: used when updating the internal representation of the partition - * table. In update mode, the metadata and freespace placeholder/virtual - * partitions are removed, making it much easier for various manipulation - * routines... - */ -static void -_disk_push_update_mode (PedDisk* disk) -{ - if (!disk->update_mode) { -#ifdef DEBUG - _disk_check_sanity (disk); -#endif - - _disk_remove_freespace (disk); - disk->update_mode++; - _disk_remove_metadata (disk); - -#ifdef DEBUG - _disk_check_sanity (disk); -#endif - } else { - disk->update_mode++; - } -} - -static void -_disk_pop_update_mode (PedDisk* disk) -{ - PED_ASSERT (disk->update_mode, return); - - if (disk->update_mode == 1) { - /* re-allocate metadata BEFORE leaving update mode, to prevent infinite - * recursion (metadata allocation requires update mode) - */ -#ifdef DEBUG - _disk_check_sanity (disk); -#endif - - _disk_alloc_metadata (disk); - disk->update_mode--; - _disk_alloc_freespace (disk); - -#ifdef DEBUG - _disk_check_sanity (disk); -#endif - } else { - disk->update_mode--; - } -} - -/** @} */ - -/** - * \addtogroup PedPartition - * - * \brief Partition access. - * - * @{ - */ - -PedPartition* -_ped_partition_alloc (const PedDisk* disk, PedPartitionType type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - - PED_ASSERT (disk != NULL, return 0); - - part = (PedPartition*) ped_malloc (sizeof (PedPartition)); - if (!part) - goto error; - - part->prev = NULL; - part->next = NULL; - - part->disk = (PedDisk*) disk; - if (!ped_geometry_init (&part->geom, disk->dev, start, end - start + 1)) - goto error_free_part; - - part->num = -1; - part->type = type; - part->part_list = NULL; - part->fs_type = fs_type; - - return part; - -error_free_part: - ped_free (part); -error: - return NULL; -} - -void -_ped_partition_free (PedPartition* part) -{ - ped_free (part); -} - -int -_ped_partition_attempt_align (PedPartition* part, - const PedConstraint* external, - PedConstraint* internal) -{ - PedConstraint* intersection; - PedGeometry* solution; - - intersection = ped_constraint_intersect (external, internal); - ped_constraint_destroy (internal); - if (!intersection) - goto fail; - - solution = ped_constraint_solve_nearest (intersection, &part->geom); - if (!solution) - goto fail_free_intersection; - ped_geometry_set (&part->geom, solution->start, solution->length); - ped_geometry_destroy (solution); - ped_constraint_destroy (intersection); - return 1; - -fail_free_intersection: - ped_constraint_destroy (intersection); -fail: - return 0; -} - -/** - * Create a new \link _PedPartition PedPartition \endlink on \p disk. - * - * \param type One of \p PED_PARTITION_NORMAL, \p PED_PARTITION_EXTENDED, - * \p PED_PARTITION_LOGICAL. - * - * \note The constructed partition is not added to disk's - * partition table. Use ped_disk_add_partition() to do this. - * - * \return A new \link _PedPartition PedPartition \endlink object, - * NULL on failure. - * - * \throws PED_EXCEPTION_ERROR if \p type is \p EXTENDED or \p LOGICAL but the - * label does not support this concept. - */ -PedPartition* -ped_partition_new (const PedDisk* disk, PedPartitionType type, - const PedFileSystemType* fs_type, PedSector start, - PedSector end) -{ - int supports_extended; - PedPartition* part; - - PED_ASSERT (disk != NULL, return NULL); - PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL); - - supports_extended = ped_disk_type_check_feature (disk->type, - PED_DISK_TYPE_EXTENDED); - - if (!supports_extended - && (type == PED_PARTITION_EXTENDED - || type == PED_PARTITION_LOGICAL)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s disk labels do not support extended " - "partitions."), - disk->type->name); - goto error; - } - - part = disk->type->ops->partition_new (disk, type, fs_type, start, end); - if (!part) - goto error; - - if (fs_type || part->type == PED_PARTITION_EXTENDED) { - if (!ped_partition_set_system (part, fs_type)) - goto error_destroy_part; - } - return part; - -error_destroy_part: - ped_partition_destroy (part); -error: - return NULL; -} - -/** - * Destroy a \link _PedPartition PedPartition \endlink object. - * - * \note Should not be called on a partition that is in a partition table. - * Use ped_disk_delete_partition() instead. - */ -void -ped_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - PED_ASSERT (part->disk != NULL, return); - PED_ASSERT (part->disk->type->ops->partition_new != NULL, return); - - part->disk->type->ops->partition_destroy (part); -} - - -/** - * Return whether or not the partition is "active". - * - * A partition is active if \p part->type is neither \p PED_PARTITION_METADATA - * nor \p PED_PARTITION_FREE. - */ -int -ped_partition_is_active (const PedPartition* part) -{ - PED_ASSERT (part != NULL, return 0); - - return !(part->type & PED_PARTITION_FREESPACE - || part->type & PED_PARTITION_METADATA); -} - -/** - * Set the state (\c 1 or \c 0) of a flag on a partition. - * - * Flags are disk label specific, although they have a global - * "namespace": the flag PED_PARTITION_BOOT, for example, roughly means - * "this" partition is bootable". But this means different things on different - * disk labels (and may not be defined on some disk labels). For example, - * on MS-DOS disk labels, there can only be one boot partition, and this - * refers to the partition that will be booted from on startup. On PC98 - * disk labels, the user can choose from any bootable partition on startup. - * - * \note It is an error to call this on an unavailable flag -- use - * ped_partition_is_flag_available() to determine which flags are available - * for a given disk label. - * - * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this - * label. - */ -int -ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - PedDiskOps* ops; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - - ops = part->disk->type->ops; - PED_ASSERT (ops->partition_set_flag != NULL, return 0); - PED_ASSERT (ops->partition_is_flag_available != NULL, return 0); - - if (!ops->partition_is_flag_available (part, flag)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - "The flag '%s' is not available for %s disk labels.", - ped_partition_flag_get_name (flag), - part->disk->type->name); - return 0; - } - - return ops->partition_set_flag (part, flag, state); -} - -/** - * Get the state (\c 1 or \c 0) of a flag on a partition. - * - * See ped_partition_set_flag() for conditions that must hold. - * - * \todo Where's the check for flag availability? - */ -int -ped_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (part->disk->type->ops->partition_get_flag != NULL, - return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - - return part->disk->type->ops->partition_get_flag (part, flag); -} - -/** - * Check whether a given flag is available on a partition. - * - * \return \c 1 if the flag is available. - */ -int -ped_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (part->disk->type->ops->partition_is_flag_available != NULL, - return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - - return part->disk->type->ops->partition_is_flag_available (part, flag); -} - -/** - * Sets the system type on the partition to \p fs_type. - * - * \note The file system may be opened, to get more information about the - * file system, e.g. to determine if it's FAT16 or FAT32. - * - * \return \c 0 on failure. - */ -int -ped_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - const PedDiskType* disk_type; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - PED_ASSERT (part->disk != NULL, return 0); - disk_type = part->disk->type; - PED_ASSERT (disk_type != NULL, return 0); - PED_ASSERT (disk_type->ops != NULL, return 0); - PED_ASSERT (disk_type->ops->partition_set_system != NULL, return 0); - - return disk_type->ops->partition_set_system (part, fs_type); -} - -static int -_assert_partition_name_feature (const PedDiskType* disk_type) -{ - if (!ped_disk_type_check_feature ( - disk_type, PED_DISK_TYPE_PARTITION_NAME)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - "%s disk labels do not support partition names.", - disk_type->name); - return 0; - } - return 1; -} - -/** - * Sets the name of a partition. - * - * \note This will only work if the disk label supports it. - * You can use - * \code - * ped_disk_type_check_feature (part->disk->type, PED_DISK_TYPE_PARTITION_NAME); - * \endcode - * to check whether this feature is enabled for a label. - * - * \note \p name will not be modified by libparted. It can be freed - * by the caller immediately after ped_partition_set_name() is called. - * - * \return \c 1 on success, \c 0 otherwise. - */ -int -ped_partition_set_name (PedPartition* part, const char* name) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - PED_ASSERT (name != NULL, return 0); - - if (!_assert_partition_name_feature (part->disk->type)) - return 0; - - PED_ASSERT (part->disk->type->ops->partition_set_name != NULL, - return 0); - part->disk->type->ops->partition_set_name (part, name); - return 1; -} - -/** - * Returns the name of a partition \p part. This will only work if the disk - * label supports it. - * - * \note The returned string should not be modified. It should - * not be referenced after the partition is destroyed. - */ -const char* -ped_partition_get_name (const PedPartition* part) -{ - PED_ASSERT (part != NULL, return NULL); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (ped_partition_is_active (part), return 0); - - if (!_assert_partition_name_feature (part->disk->type)) - return NULL; - - PED_ASSERT (part->disk->type->ops->partition_get_name != NULL, - return NULL); - return part->disk->type->ops->partition_get_name (part); -} - -/** @} */ - -/** - * \addtogroup PedDisk - * - * @{ - */ - -PedPartition* -ped_disk_extended_partition (const PedDisk* disk) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; walk = walk->next) { - if (walk->type == PED_PARTITION_EXTENDED) - break; - } - return walk; -} - -/** - * Return the next partition after \p part on \p disk. If \p part is \c NULL, - * return the first partition. If \p part is the last partition, returns - * \c NULL. If \p part is an extended partition, returns the first logical - * partition. If this is called repeatedly passing the return value as \p part, - * a depth-first traversal is executed. - * - * \return The next partition, \c NULL if no more partitions left. - */ -PedPartition* -ped_disk_next_partition (const PedDisk* disk, const PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - - if (!part) - return disk->part_list; - if (part->type == PED_PARTITION_EXTENDED) - return part->part_list ? part->part_list : part->next; - if (part->next) - return part->next; - if (part->type & PED_PARTITION_LOGICAL) - return ped_disk_extended_partition (disk)->next; - return NULL; -} - -/** @} */ - -#ifdef DEBUG -static int -_disk_check_sanity (PedDisk* disk) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; walk = walk->next) { - PED_ASSERT (!(walk->type & PED_PARTITION_LOGICAL), return 0); - PED_ASSERT (!walk->prev || walk->prev->next == walk, return 0); - } - - if (!ped_disk_extended_partition (disk)) - return 1; - - for (walk = ped_disk_extended_partition (disk)->part_list; walk; - walk = walk->next) { - PED_ASSERT (walk->type & PED_PARTITION_LOGICAL, return 0); - if (walk->prev) - PED_ASSERT (walk->prev->next == walk, return 0); - } - return 1; -} -#endif - -/** - * Returns the partition numbered \p num. - * - * \return \c NULL if the specified partition does not exist. - */ -PedPartition* -ped_disk_get_partition (const PedDisk* disk, int num) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - if (walk->num == num && !(walk->type & PED_PARTITION_FREESPACE)) - return walk; - } - - return NULL; -} - -/** - * Returns the partition that contains sect. If sect lies within a logical - * partition, then the logical partition is returned (not the extended - * partition). - */ -PedPartition* -ped_disk_get_partition_by_sector (const PedDisk* disk, PedSector sect) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - - for (walk = disk->part_list; walk; - walk = ped_disk_next_partition (disk, walk)) { - if (ped_geometry_test_sector_inside (&walk->geom, sect) - && walk->type != PED_PARTITION_EXTENDED) - return walk; - } - - /* should never get here, unless sect is outside of disk's useable - * part, or we're in "update mode", and the free space place-holders - * have been removed with _disk_remove_freespace() - */ - return NULL; -} - -/* I'm beginning to agree with Sedgewick :-/ */ -static int -_disk_raw_insert_before (PedDisk* disk, PedPartition* loc, PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (loc != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - part->prev = loc->prev; - part->next = loc; - if (part->prev) { - part->prev->next = part; - } else { - if (loc->type & PED_PARTITION_LOGICAL) - ped_disk_extended_partition (disk)->part_list = part; - else - disk->part_list = part; - } - loc->prev = part; - - return 1; -} - -static int -_disk_raw_insert_after (PedDisk* disk, PedPartition* loc, PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (loc != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - part->prev = loc; - part->next = loc->next; - if (loc->next) - loc->next->prev = part; - loc->next = part; - - return 1; -} - -static int -_disk_raw_remove (PedDisk* disk, PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - if (part->prev) { - part->prev->next = part->next; - if (part->next) - part->next->prev = part->prev; - } else { - if (part->type & PED_PARTITION_LOGICAL) { - ped_disk_extended_partition (disk)->part_list - = part->next; - } else { - disk->part_list = part->next; - } - if (part->next) - part->next->prev = NULL; - } - - return 1; -} - -/* - *UPDATE MODE ONLY - */ -static int -_disk_raw_add (PedDisk* disk, PedPartition* part) -{ - PedPartition* walk; - PedPartition* last; - PedPartition* ext_part; - - PED_ASSERT (disk->update_mode, return 0); - - ext_part = ped_disk_extended_partition (disk); - - last = NULL; - walk = (part->type & PED_PARTITION_LOGICAL) ? - ext_part->part_list : disk->part_list; - - for (; walk; last = walk, walk = walk->next) { - if (walk->geom.start > part->geom.end) - break; - } - - if (walk) { - return _disk_raw_insert_before (disk, walk, part); - } else { - if (last) { - return _disk_raw_insert_after (disk, last, part); - } else { - if (part->type & PED_PARTITION_LOGICAL) - ext_part->part_list = part; - else - disk->part_list = part; - } - } - - return 1; -} - -static PedConstraint* -_partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom) -{ - PedSector min_start; - PedSector max_end; - PedPartition* walk; - PedGeometry free_space; - - PED_ASSERT (part->disk->update_mode, return NULL); - PED_ASSERT (part->geom.dev == geom->dev, return NULL); - - if (part->type & PED_PARTITION_LOGICAL) { - PedPartition* ext_part; - - ext_part = ped_disk_extended_partition (part->disk); - PED_ASSERT (ext_part != NULL, return NULL); - - min_start = ext_part->geom.start; - max_end = ext_part->geom.end; - walk = ext_part->part_list; - } else { - min_start = 0; - max_end = part->disk->dev->length - 1; - walk = part->disk->part_list; - } - - while (walk != NULL - && (walk->geom.start < geom->start - || min_start >= walk->geom.start)) { - if (walk != part) - min_start = walk->geom.end + 1; - walk = walk->next; - } - - if (walk == part) - walk = walk->next; - - if (walk) - max_end = walk->geom.start - 1; - - if (min_start >= max_end) - return NULL; - - ped_geometry_init (&free_space, part->disk->dev, - min_start, max_end - min_start + 1); - return ped_constraint_new_from_max (&free_space); -} - -/* - * Returns \c 0 if the partition, \p part overlaps with any partitions on the - * \p disk. The geometry of \p part is taken to be \p geom, NOT \p part->geom - * (the idea here is to check if \p geom is valid, before changing \p part). - * - * This is useful for seeing if a resized partitions new geometry is going to - * fit, without the existing geomtry getting in the way. - * - * Note: overlap with an extended partition is also allowed, provided that - * \p geom lies completely inside the extended partition. - */ -static int -_disk_check_part_overlaps (PedDisk* disk, PedPartition* part) -{ - PedPartition* walk; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - for (walk = ped_disk_next_partition (disk, NULL); walk; - walk = ped_disk_next_partition (disk, walk)) { - if (walk->type & PED_PARTITION_FREESPACE) - continue; - if (walk == part) - continue; - if (part->type & PED_PARTITION_EXTENDED - && walk->type & PED_PARTITION_LOGICAL) - continue; - - if (ped_geometry_test_overlap (&walk->geom, &part->geom)) { - if (walk->type & PED_PARTITION_EXTENDED - && part->type & PED_PARTITION_LOGICAL - && ped_geometry_test_inside (&walk->geom, - &part->geom)) - continue; - return 0; - } - } - - return 1; -} - -static int -_partition_check_basic_sanity (PedDisk* disk, PedPartition* part) -{ - PedPartition* ext_part = ped_disk_extended_partition (disk); - - PED_ASSERT (part->disk == disk, return 0); - - PED_ASSERT (part->geom.start >= 0, return 0); - PED_ASSERT (part->geom.end < disk->dev->length, return 0); - PED_ASSERT (part->geom.start <= part->geom.end, return 0); - - if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED) - && (part->type == PED_PARTITION_EXTENDED - || part->type == PED_PARTITION_LOGICAL)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s disk labels don't support logical or extended " - "partitions."), - disk->type->name); - return 0; - } - - if (ped_partition_is_active (part) - && ! (part->type & PED_PARTITION_LOGICAL)) { - if (ped_disk_get_primary_partition_count (disk) + 1 - > ped_disk_get_max_primary_partition_count (disk)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Too many primary partitions.")); - return 0; - } - } - - if ((part->type & PED_PARTITION_LOGICAL) && !ext_part) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't add a logical partition to %s, because " - "there is no extended partition."), - disk->dev->path); - return 0; - } - - return 1; -} - -static int -_check_extended_partition (PedDisk* disk, PedPartition* part) -{ - PedPartition* walk; - PedPartition* ext_part; - - PED_ASSERT (disk != NULL, return 0); - ext_part = ped_disk_extended_partition (disk); - if (!ext_part) ext_part = part; - PED_ASSERT (ext_part != NULL, return 0); - - if (part != ext_part) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have more than one extended partition on %s."), - disk->dev->path); - return 0; - } - - for (walk = ext_part->part_list; walk; walk = walk->next) { - if (!ped_geometry_test_inside (&ext_part->geom, &walk->geom)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have logical partitions outside of " - "the extended partition.")); - return 0; - } - } - return 1; -} - -static int -_check_partition (PedDisk* disk, PedPartition* part) -{ - PedPartition* ext_part = ped_disk_extended_partition (disk); - - PED_ASSERT (part->geom.start <= part->geom.end, return 0); - - if (part->type == PED_PARTITION_EXTENDED) { - if (!_check_extended_partition (disk, part)) - return 0; - } - - if (part->type & PED_PARTITION_LOGICAL - && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have a logical partition outside of the " - "extended partition on %s."), - disk->dev->path); - return 0; - } - - if (!_disk_check_part_overlaps (disk, part)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have overlapping partitions.")); - return 0; - } - - if (! (part->type & PED_PARTITION_LOGICAL) - && ext_part && ext_part != part - && ped_geometry_test_inside (&ext_part->geom, &part->geom)) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't have a primary partition inside an extended " - "partition.")); - return 0; - } - - return 1; -} - -/** - * Adds PedPartition \p part to PedPartition \p disk. - * - * \warning The partition's geometry may be changed, subject to \p constraint. - * You could set \p constraint to ped_constraint_exact(&part->geom), - * but many partition table schemes have special requirements on the start - * and end of partitions. Therefore, having an overly strict constraint - * will probably mean that this function will fail (in which - * case \p part will be left unmodified) - * \p part is assigned a number (\p part->num) in this process. - * - * \return \c 0 on failure. - */ -int -ped_disk_add_partition (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint) -{ - PedConstraint* overlap_constraint = NULL; - PedConstraint* constraints = NULL; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - if (!_partition_check_basic_sanity (disk, part)) - return 0; - - _disk_push_update_mode (disk); - - if (ped_partition_is_active (part)) { - overlap_constraint - = _partition_get_overlap_constraint (part, &part->geom); - constraints = ped_constraint_intersect (overlap_constraint, - constraint); - - if (!constraints && constraint) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have overlapping partitions.")); - goto error; - } - - if (!_partition_enumerate (part)) - goto error; - if (!_partition_align (part, constraints)) - goto error; - } - if (!_check_partition (disk, part)) - goto error; - if (!_disk_raw_add (disk, part)) - goto error; - - ped_constraint_destroy (overlap_constraint); - ped_constraint_destroy (constraints); - _disk_pop_update_mode (disk); -#ifdef DEBUG - if (!_disk_check_sanity (disk)) - return 0; -#endif - return 1; - -error: - ped_constraint_destroy (overlap_constraint); - ped_constraint_destroy (constraints); - _disk_pop_update_mode (disk); - return 0; -} - -/** - * Removes PedPartition \p part from PedDisk \p disk. - * - * If \p part is an extended partition, it must not contain any logical - * partitions. \p part is *NOT* destroyed. The caller must call - * ped_partition_destroy(), or use ped_disk_delete_partition() instead. - * - * \return \c 0 on error. - */ -int -ped_disk_remove_partition (PedDisk* disk, PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - _disk_push_update_mode (disk); - PED_ASSERT (part->part_list == NULL, goto error); - _disk_raw_remove (disk, part); - _disk_pop_update_mode (disk); - ped_disk_enumerate_partitions (disk); - return 1; - -error: - _disk_pop_update_mode (disk); - return 0; -} - -static int -ped_disk_delete_all_logical (PedDisk* disk); - -/** - * Removes \p part from \p disk, and destroys \p part. - * - * \return \c 0 on failure. - */ -int -ped_disk_delete_partition (PedDisk* disk, PedPartition* part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - _disk_push_update_mode (disk); - if (part->type == PED_PARTITION_EXTENDED) - ped_disk_delete_all_logical (disk); - ped_disk_remove_partition (disk, part); - ped_partition_destroy (part); - _disk_pop_update_mode (disk); - - return 1; -} - -static int -ped_disk_delete_all_logical (PedDisk* disk) -{ - PedPartition* walk; - PedPartition* next; - PedPartition* ext_part; - - PED_ASSERT (disk != NULL, return 0); - ext_part = ped_disk_extended_partition (disk); - PED_ASSERT (ext_part != NULL, return 0); - - for (walk = ext_part->part_list; walk; walk = next) { - next = walk->next; - - if (!ped_disk_delete_partition (disk, walk)) - return 0; - } - return 1; -} - -/** - * Removes and destroys all partitions on \p disk. - * - * \return \c 0 on failure. - */ -int -ped_disk_delete_all (PedDisk* disk) -{ - PedPartition* walk; - PedPartition* next; - - PED_ASSERT (disk != NULL, return 0); - - _disk_push_update_mode (disk); - - for (walk = disk->part_list; walk; walk = next) { - next = walk->next; - - if (!ped_disk_delete_partition (disk, walk)) - return 0; - } - - _disk_pop_update_mode (disk); - - return 1; -} - -/** - * Sets the geometry of \p part (i.e. change a partitions location). This can - * fail for many reasons, e.g. can't overlap with other partitions. If it - * does fail, \p part will remain unchanged. Returns \c 0 on failure. \p part's - * geometry may be set to something different from \p start and \p end subject - * to \p constraint. - * - * \warning The constraint warning from ped_disk_add_partition() applies. - * - * \note this function does not modify the contents of the partition. You need - * to call ped_file_system_resize() separately. - */ -int -ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint, - PedSector start, PedSector end) -{ - PedConstraint* overlap_constraint = NULL; - PedConstraint* constraints = NULL; - PedGeometry old_geom; - PedGeometry new_geom; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk == disk, return 0); - - old_geom = part->geom; - ped_geometry_init (&new_geom, part->geom.dev, start, end - start + 1); - - _disk_push_update_mode (disk); - - overlap_constraint - = _partition_get_overlap_constraint (part, &new_geom); - constraints = ped_constraint_intersect (overlap_constraint, constraint); - if (!constraints && constraint) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't have overlapping partitions.")); - goto error_pop_update_mode; - } - - part->geom = new_geom; - if (!_partition_align (part, constraints)) - goto error_pop_update_mode; - if (!_check_partition (disk, part)) - goto error_pop_update_mode; - - /* remove and add, to ensure the ordering gets updated if necessary */ - _disk_raw_remove (disk, part); - _disk_raw_add (disk, part); - - _disk_pop_update_mode (disk); - - ped_constraint_destroy (overlap_constraint); - ped_constraint_destroy (constraints); - return 1; - -error_pop_update_mode: - _disk_pop_update_mode (disk); - ped_constraint_destroy (overlap_constraint); - ped_constraint_destroy (constraints); - part->geom = old_geom; - return 0; -} - -/** - * Grow PedPartition \p part geometry to the maximum possible subject to - * \p constraint. The new geometry will be a superset of the old geometry. - * - * \return 0 on failure - */ -int -ped_disk_maximize_partition (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint) -{ - PedGeometry old_geom; - PedSector global_min_start; - PedSector global_max_end; - PedSector new_start; - PedSector new_end; - PedPartition* ext_part = ped_disk_extended_partition (disk); - PedConstraint* constraint_any; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - if (part->type & PED_PARTITION_LOGICAL) { - PED_ASSERT (ext_part != NULL, return 0); - global_min_start = ext_part->geom.start; - global_max_end = ext_part->geom.end; - } else { - global_min_start = 0; - global_max_end = disk->dev->length - 1; - } - - old_geom = part->geom; - - _disk_push_update_mode (disk); - - if (part->prev) - new_start = part->prev->geom.end + 1; - else - new_start = global_min_start; - - if (part->next) - new_end = part->next->geom.start - 1; - else - new_end = global_max_end; - - if (!ped_disk_set_partition_geom (disk, part, constraint, new_start, - new_end)) - goto error; - - _disk_pop_update_mode (disk); - return 1; - -error: - constraint_any = ped_constraint_any (disk->dev); - ped_disk_set_partition_geom (disk, part, constraint_any, - old_geom.start, old_geom.end); - ped_constraint_destroy (constraint_any); - _disk_pop_update_mode (disk); - return 0; -} - -/** - * Get the maximum geometry \p part can be grown to, subject to - * \p constraint. - * - * \return \c NULL on failure. - */ -PedGeometry* -ped_disk_get_max_partition_geometry (PedDisk* disk, PedPartition* part, - const PedConstraint* constraint) -{ - PedGeometry old_geom; - PedGeometry* max_geom; - PedConstraint* constraint_exact; - - PED_ASSERT(disk != NULL, return NULL); - PED_ASSERT(part != NULL, return NULL); - PED_ASSERT(ped_partition_is_active (part), return NULL); - - old_geom = part->geom; - if (!ped_disk_maximize_partition (disk, part, constraint)) - return NULL; - max_geom = ped_geometry_duplicate (&part->geom); - - constraint_exact = ped_constraint_exact (&old_geom); - ped_disk_set_partition_geom (disk, part, constraint_exact, - old_geom.start, old_geom.end); - ped_constraint_destroy (constraint_exact); - - /* this assertion should never fail, because the old - * geometry was valid - */ - PED_ASSERT (ped_geometry_test_equal (&part->geom, &old_geom), - return NULL); - - return max_geom; -} - -/** - * Reduce the size of the extended partition to a minimum while still wrapping - * its logical partitions. If there are no logical partitions, remove the - * extended partition. - * - * \return 0 on failure. - */ -int -ped_disk_minimize_extended_partition (PedDisk* disk) -{ - PedPartition* first_logical; - PedPartition* last_logical; - PedPartition* walk; - PedPartition* ext_part; - PedConstraint* constraint; - int status; - - PED_ASSERT (disk != NULL, return 0); - - ext_part = ped_disk_extended_partition (disk); - if (!ext_part) - return 1; - - _disk_push_update_mode (disk); - - first_logical = ext_part->part_list; - if (!first_logical) { - _disk_pop_update_mode (disk); - return ped_disk_delete_partition (disk, ext_part); - } - - for (walk = first_logical; walk->next; walk = walk->next); - last_logical = walk; - - constraint = ped_constraint_any (disk->dev); - status = ped_disk_set_partition_geom (disk, ext_part, constraint, - first_logical->geom.start, - last_logical->geom.end); - ped_constraint_destroy (constraint); - - _disk_pop_update_mode (disk); - return status; -} - -/** - * @} - */ - -/** - * \addtogroup PedPartition - * - * @{ - */ - -/** - * Returns a name that seems mildly appropriate for a partition type \p type. - * - * Eg, if you pass (PED_PARTITION_LOGICAL & PED_PARTITION_FREESPACE), it - * will return "free". This isn't to be taken too seriously - it's just - * useful for user interfaces, so you can show the user something ;-) - * - * \note The returned string will be in English. However, - * translations are provided, so the caller can call - * dgettext("parted", RESULT) on the result. - * - */ -const char* -ped_partition_type_get_name (PedPartitionType type) -{ - if (type & PED_PARTITION_METADATA) - return N_("metadata"); - else if (type & PED_PARTITION_FREESPACE) - return N_("free"); - else if (type & PED_PARTITION_EXTENDED) - return N_("extended"); - else if (type & PED_PARTITION_LOGICAL) - return N_("logical"); - else - return N_("primary"); -} - - -/** - * Returns a name for a \p flag, e.g. PED_PARTITION_BOOT will return "boot". - * - * \note The returned string will be in English. However, - * translations are provided, so the caller can call - * dgettext("parted", RESULT) on the result. - */ -const char* -ped_partition_flag_get_name (PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_BOOT: - return N_("boot"); - case PED_PARTITION_ROOT: - return N_("root"); - case PED_PARTITION_SWAP: - return N_("swap"); - case PED_PARTITION_HIDDEN: - return N_("hidden"); - case PED_PARTITION_RAID: - return N_("raid"); - case PED_PARTITION_LVM: - return N_("lvm"); - case PED_PARTITION_LBA: - return N_("lba"); - case PED_PARTITION_HPSERVICE: - return N_("hp-service"); - case PED_PARTITION_PALO: - return N_("palo"); - case PED_PARTITION_PREP: - return N_("prep"); - case PED_PARTITION_MSFT_RESERVED: - return N_("msftres"); - - default: - ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("Unknown partition flag, %d."), - flag); - return NULL; - } -} - -/** - * Iterates through all flags. - * - * ped_partition_flag_next(0) returns the first flag - * - * \return the next flag, or 0 if there are no more flags - */ -PedPartitionFlag -ped_partition_flag_next (PedPartitionFlag flag) -{ - return (flag + 1) % (PED_PARTITION_LAST_FLAG + 1); -} - -/** - * Returns the flag associated with \p name. - * - * \p name can be the English - * string, or the translation for the native language. - */ -PedPartitionFlag -ped_partition_flag_get_by_name (const char* name) -{ - PedPartitionFlag flag; - const char* flag_name; - - for (flag = ped_partition_flag_next (0); flag; - flag = ped_partition_flag_next (flag)) { - flag_name = ped_partition_flag_get_name (flag); - if (strcasecmp (name, flag_name) == 0 - || strcasecmp (name, _(flag_name)) == 0) - return flag; - } - - return 0; -} - -static void -ped_partition_print (const PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - printf (" %-10s %02d (%d->%d)\n", - ped_partition_type_get_name (part->type), - part->num, - (int) part->geom.start, (int) part->geom.end); -} - -/** @} */ - -/** - * \addtogroup PedDisk - * - * @{ - */ - -/** - * Prints a summary of disk's partitions. Useful for debugging. - */ -void -ped_disk_print (const PedDisk* disk) -{ - PedPartition* part; - - PED_ASSERT (disk != NULL, return); - - for (part = disk->part_list; part; - part = ped_disk_next_partition (disk, part)) - ped_partition_print (part); -} - -/** @} */ diff --git a/usr/src/lib/libparted/common/libparted/exception.c b/usr/src/lib/libparted/common/libparted/exception.c deleted file mode 100644 index 0940d65456..0000000000 --- a/usr/src/lib/libparted/common/libparted/exception.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file exception.c */ - -/** - * \addtogroup PedException - * - * \brief Exception handling. - * - * There are a few types of exceptions: PED_EXCEPTION_INFORMATION, - * PED_EXCEPTION_WARNING, PED_EXCEPTION_ERROR, PED_EXCEPTION_FATAL, - * PED_EXCEPTION_BUG. - * - * They are "thrown" when one of the above events occur while executing - * a libparted function. For example, if ped_device_open() fails - * because the device doesn't exist, an exception will be thrown. - * Exceptions contain text describing what the event was. It will give - * at least one option for resolving the exception: PED_EXCEPTION_FIX, - * PED_EXCEPTION_YES, PED_EXCEPTION_NO, PED_EXCEPTION_OK, PED_EXCEPTION_RETRY, - * PED_EXCEPTION_IGNORE, PED_EXCEPTION_CANCEL. After an exception is thrown, - * there are two things that can happen: - * - * -# an exception handler is called, which selects how the exception should be - * resolved (usually by asking the user). Also note: an exception handler may - * choose to return PED_EXCEPTION_UNHANDLED. In this case, a default action - * will be taken by libparted (respectively the code that threw the - * exception). In general, a default action will be "safe". - * -# the exception is not handled, because the caller of the function wants to - * handle everything itself. In this case, PED_EXCEPTION_UNHANDLED is - * returned. - * - * @{ - */ - -#include - -#include -#include - -#define N_(String) String -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include -#include - -int ped_exception = 0; - -static PedExceptionOption default_handler (PedException* ex); - -static PedExceptionHandler* ex_handler = default_handler; -static PedException* ex = NULL; -static int ex_fetch_count = 0; - -static char* type_strings [] = { - N_("Information"), - N_("Warning"), - N_("Error"), - N_("Fatal"), - N_("Bug"), - N_("No Implementation") -}; - -static char* option_strings [] = { - N_("Fix"), - N_("Yes"), - N_("No"), - N_("OK"), - N_("Retry"), - N_("Ignore"), - N_("Cancel") -}; - -/** - * Return a string describing an exception type. - */ -char* -ped_exception_get_type_string (PedExceptionType ex_type) -{ - return type_strings [ex_type - 1]; -} - -/* FIXME: move this out to the prospective math.c */ -/* FIXME: this can probably be done more efficiently */ -static int -ped_log2 (int n) -{ - int x; - - PED_ASSERT (n > 0, return -1); - - for (x=0; 1 << x <= n; x++); - - return x - 1; -} - -/** - * Return a string describing an exception option. - */ -char* -ped_exception_get_option_string (PedExceptionOption ex_opt) -{ - return option_strings [ped_log2 (ex_opt)]; -} - -static PedExceptionOption -default_handler (PedException* e) -{ - if (e->type == PED_EXCEPTION_BUG) - fprintf (stderr, - _("A bug has been detected in GNU Parted. " - "Refer to the web site of parted " - "http://www.gnu.org/software/parted/parted.html " - "for more informations of what could be useful " - "for bug submitting! " - "Please email a bug report to " - "bug-parted@gnu.org containing at least the " - "version (%s) and the following message: "), - VERSION); - else - fprintf (stderr, "%s: ", - ped_exception_get_type_string (e->type)); - fprintf (stderr, "%s\n", e->message); - - switch (e->options) { - case PED_EXCEPTION_OK: - case PED_EXCEPTION_CANCEL: - case PED_EXCEPTION_IGNORE: - return e->options; - - default: - return PED_EXCEPTION_UNHANDLED; - } -} - -/** - * Set the exception handler. - * - * The exception handler should return ONE of the options set in ex->options, - * indicating the way the event should be resolved. - */ -void -ped_exception_set_handler (PedExceptionHandler* handler) -{ - if (handler) - ex_handler = handler; - else - ex_handler = default_handler; -} - -/** - * Get the current exception handler. - */ -PedExceptionHandler * -ped_exception_get_handler (void) -{ - if (ex_handler) - return ex_handler; - return default_handler; -} - -/** - * Assert that the current exception has been resolved. - */ -void -ped_exception_catch () -{ - if (ped_exception) { - ped_exception = 0; - - ped_free (ex->message); - ped_free (ex); - ex = NULL; - } -} - -static PedExceptionOption -do_throw () -{ - PedExceptionOption ex_opt; - - ped_exception = 1; - - if (ex_fetch_count) { - return PED_EXCEPTION_UNHANDLED; - } else { - ex_opt = ex_handler (ex); - ped_exception_catch (); - return ex_opt; - } -} - -/** - * Throw an exception. - * - * You can also use this in a program using libparted. - * "message" is a printf-like format string, so you can do - * - * \code - * ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_CANCEL, - * "Can't open %s", file_name); - * \endcode - * - * Returns the option selected to resolve the exception. If the exception was - * unhandled, PED_EXCEPTION_UNHANDLED is returned. - */ -PedExceptionOption -ped_exception_throw (PedExceptionType ex_type, - PedExceptionOption ex_opts, const char* message, ...) -{ - va_list arg_list; - int result; - static int size = 1000; - - if (ex) - ped_exception_catch (); - - ex = (PedException*) malloc (sizeof (PedException)); - if (!ex) - goto no_memory; - - ex->type = ex_type; - ex->options = ex_opts; - - while (1) { - ex->message = (char*) malloc (size); - if (!ex->message) - goto no_memory; - - va_start (arg_list, message); - result = vsnprintf (ex->message, size, message, arg_list); - va_end (arg_list); - - if (result > -1 && result < size) - break; - - size += 10; - } - - return do_throw (); - -no_memory: - fputs ("Out of memory in exception handler!\n", stderr); - - va_start (arg_list, message); - vfprintf (stderr, message, arg_list); - va_end (arg_list); - - return PED_EXCEPTION_UNHANDLED; -} - -/** - * Rethrow an unhandled exception. - * This means repeating the last ped_exception_throw() statement. - */ -PedExceptionOption -ped_exception_rethrow () -{ - return do_throw (); -} - -/** - * Indicates that exceptions should not go to the exception handler, but - * passed up to the calling function(s). All calls to - * ped_exception_throw() will return PED_EXCEPTION_UNHANDLED. - */ -void -ped_exception_fetch_all () -{ - ex_fetch_count++; -} - -/** - * Indicates that the calling function does not want to accept any - * responsibility for exceptions any more. - * - * \note a caller of that function may still want responsibility, so - * ped_exception_throw() may not invoke the exception handler. - * - * \warning every call to this function must have a preceding - * ped_exception_fetch_all(). - */ -void -ped_exception_leave_all () -{ - PED_ASSERT (ex_fetch_count > 0, return); - ex_fetch_count--; -} - -/** @} */ - diff --git a/usr/src/lib/libparted/common/libparted/filesys.c b/usr/src/lib/libparted/common/libparted/filesys.c deleted file mode 100644 index 986f0ca35e..0000000000 --- a/usr/src/lib/libparted/common/libparted/filesys.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file filesys.c */ - -/** - * \addtogroup PedFileSystem - * - * \note File systems exist on a PedGeometry - NOT a PedPartition. - * - * @{ - */ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define BUFFER_SIZE 4096 /* in sectors */ - -static PedFileSystemType* fs_types = NULL; - -void -ped_file_system_type_register (PedFileSystemType* fs_type) -{ - PED_ASSERT (fs_type != NULL, return); - PED_ASSERT (fs_type->ops != NULL, return); - PED_ASSERT (fs_type->name != NULL, return); - - /* pretend that "next" isn't part of the struct :-) */ - ((struct _PedFileSystemType*) fs_type)->next = fs_types; - fs_types = (struct _PedFileSystemType*) fs_type; -} - -void -ped_file_system_type_unregister (PedFileSystemType* fs_type) -{ - PedFileSystemType* walk; - PedFileSystemType* last = NULL; - - PED_ASSERT (fs_types != NULL, return); - PED_ASSERT (fs_type != NULL, return); - - for (walk = fs_types; walk && walk != fs_type; - last = walk, walk = walk->next); - - PED_ASSERT (walk != NULL, return); - if (last) - ((struct _PedFileSystemType*) last)->next = fs_type->next; - else - fs_types = fs_type->next; -} - -/** - * Get a PedFileSystemType by its @p name. - * - * @return @c NULL if none found. - */ -PedFileSystemType* -ped_file_system_type_get (const char* name) -{ - PedFileSystemType* walk; - - PED_ASSERT (name != NULL, return NULL); - - for (walk = fs_types; walk != NULL; walk = walk->next) { - if (!strcasecmp (walk->name, name)) - break; - } - return walk; -} - -/** - * Get the next PedFileSystemType after @p fs_type. - * - * @return @c NULL if @p fs_type is the last item in the list. - */ -PedFileSystemType* -ped_file_system_type_get_next (const PedFileSystemType* fs_type) -{ - if (fs_type) - return fs_type->next; - else - return fs_types; -} - -/** - * Attempt to find a file system and return the region it occupies. - * - * @param fs_type The file system type to probe for. - * @param geom The region to be searched. - * - * @return @p NULL if @p fs_type file system wasn't detected - */ -PedGeometry* -ped_file_system_probe_specific ( - const PedFileSystemType* fs_type, PedGeometry* geom) -{ - PedGeometry* result; - - PED_ASSERT (fs_type != NULL, return NULL); - PED_ASSERT (fs_type->ops->probe != NULL, return NULL); - PED_ASSERT (geom != NULL, return NULL); - - if (!ped_device_open (geom->dev)) - return 0; - result = fs_type->ops->probe (geom); - ped_device_close (geom->dev); - return result; -} - -static int -_test_open (PedFileSystemType* fs_type, PedGeometry* geom) -{ - PedFileSystem* fs; - - ped_exception_fetch_all (); - fs = fs_type->ops->open (geom); - if (fs) - fs_type->ops->close (fs); - else - ped_exception_catch (); - ped_exception_leave_all (); - return fs != NULL; -} - -static PedFileSystemType* -_probe_with_open (PedGeometry* geom, int detected_count, - PedFileSystemType* detected[]) -{ - int i; - PedFileSystemType* open_detected = NULL; - - ped_device_open (geom->dev); - - /* If one and only one file system that Parted is able to open - * can be successfully opened on this geometry, return it. - * If more than one can be, return NULL. - */ - for (i=0; iops->open || !_test_open (detected [i], geom)) - continue; - - if (open_detected) { - ped_device_close (geom->dev); - return NULL; - } else { - open_detected = detected [i]; - } - } - - /* If no file system has been successfully opened, and - * if Parted has detected at most one unopenable file system, - * return it. - */ - if (!open_detected) - for (i=0; iops->open) - continue; - if (open_detected) { - ped_device_close (geom->dev); - return NULL; - } else { - open_detected = detected [i]; - } - } - - ped_device_close (geom->dev); - return open_detected; -} - -static int -_geometry_error (const PedGeometry* a, const PedGeometry* b) -{ - PedSector start_delta = a->start - b->start; - PedSector end_delta = a->end - b->end; - - return abs (start_delta) + abs (end_delta); -} - -static PedFileSystemType* -_best_match (const PedGeometry* geom, PedFileSystemType* detected [], - const int detected_error [], int detected_count) -{ - int best_match = 0; - int i; - PedSector min_error; - - min_error = PED_MAX (4096, geom->length / 100); - - for (i = 1; i < detected_count; i++) { - if (detected_error [i] < detected_error [best_match]) - best_match = i; - } - - /* make sure the best match is significantly better than all the - * other matches - */ - for (i = 0; i < detected_count; i++) { - if (i == best_match) - continue; - - if (abs (detected_error [best_match] - detected_error [i]) - < min_error) - return NULL; - } - - return detected [best_match]; -} - - -/** - * Attempt to detect a file system in region \p geom. - * This function tries to be clever at dealing with ambiguous - * situations, such as when one file system was not completely erased before a - * new file system was created on top of it. - * - * \return a new PedFileSystem on success, \c NULL on failure - */ -PedFileSystemType* -ped_file_system_probe (PedGeometry* geom) -{ - PedFileSystemType* detected[32]; - int detected_error[32]; - int detected_count = 0; - PedFileSystemType* walk = NULL; - - PED_ASSERT (geom != NULL, return NULL); - - if (!ped_device_open (geom->dev)) - return NULL; - - ped_exception_fetch_all (); - while ( (walk = ped_file_system_type_get_next (walk)) ) { - PedGeometry* probed; - - probed = ped_file_system_probe_specific (walk, geom); - if (probed) { - detected [detected_count] = walk; - detected_error [detected_count] - = _geometry_error (geom, probed); - detected_count++; - ped_geometry_destroy (probed); - } else { - ped_exception_catch (); - } - } - ped_exception_leave_all (); - - ped_device_close (geom->dev); - - if (!detected_count) - return NULL; - walk = _best_match (geom, detected, detected_error, detected_count); - if (walk) - return walk; - return _probe_with_open (geom, detected_count, detected); -} - -/** - * This function erases all file system signatures that indicate that a - * file system occupies a given region described by \p geom. - * After this operation ped_file_system_probe() won't detect any file system. - * - * \note ped_file_system_create() calls this before creating a new file system. - * - * \return \c 1 on success, \c 0 on failure - */ -int -ped_file_system_clobber (PedGeometry* geom) -{ - PedFileSystemType* fs_type = NULL; - - PED_ASSERT (geom != NULL, return 0); - - if (!ped_device_open (geom->dev)) - goto error; - - ped_exception_fetch_all (); - while ((fs_type = ped_file_system_type_get_next (fs_type))) { - PedGeometry* probed; - - if (!fs_type->ops->clobber) - continue; - - probed = ped_file_system_probe_specific (fs_type, geom); - if (!probed) { - ped_exception_catch (); - continue; - } - ped_geometry_destroy (probed); - - if (fs_type->ops->clobber && !fs_type->ops->clobber (geom)) { - ped_exception_leave_all (); - goto error_close_dev; - } - } - ped_device_close (geom->dev); - ped_exception_leave_all (); - return 1; - -error_close_dev: - ped_device_close (geom->dev); -error: - return 0; -} - -/* This function erases all signatures that indicate the presence of - * a file system in a particular region, without erasing any data - * contained inside the "exclude" region. - */ -static int -ped_file_system_clobber_exclude (PedGeometry* geom, - const PedGeometry* exclude) -{ - PedGeometry* clobber_geom; - int status; - - if (ped_geometry_test_sector_inside (exclude, geom->start)) - return 1; - - clobber_geom = ped_geometry_duplicate (geom); - if (ped_geometry_test_overlap (clobber_geom, exclude)) - ped_geometry_set_end (clobber_geom, exclude->start - 1); - - status = ped_file_system_clobber (clobber_geom); - ped_geometry_destroy (clobber_geom); - return status; -} - -/** - * This function opens the file system stored on \p geom, if it - * can find one. - * It is often called in the following manner: - * \code - * fs = ped_file_system_open (&part.geom) - * \endcode - * - * \throws PED_EXCEPTION_ERROR if file system could not be detected - * \throws PED_EXCEPTION_ERROR if the file system is bigger than its volume - * \throws PED_EXCEPTION_NO_FEATURE if opening of a file system stored on - * \p geom is not implemented - * - * \return a PedFileSystem on success, \c NULL on failure. - */ -PedFileSystem* -ped_file_system_open (PedGeometry* geom) -{ - PedFileSystemType* type; - PedFileSystem* fs; - PedGeometry* probed_geom; - - PED_ASSERT (geom != NULL, return NULL); - - if (!ped_device_open (geom->dev)) - goto error; - - type = ped_file_system_probe (geom); - if (!type) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Could not detect file system.")); - goto error_close_dev; - } - - probed_geom = ped_file_system_probe_specific (type, geom); - if (!probed_geom) - goto error_close_dev; - if (!ped_geometry_test_inside (geom, probed_geom)) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("The file system is bigger than its volume!")) - != PED_EXCEPTION_IGNORE) - goto error_destroy_probed_geom; - } - - if (!type->ops->open) { - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for opening %s file systems " - "is not implemented yet."), - type->name); - goto error_destroy_probed_geom; - } - - fs = type->ops->open (probed_geom); - if (!fs) - goto error_destroy_probed_geom; - ped_geometry_destroy (probed_geom); - return fs; - -error_destroy_probed_geom: - ped_geometry_destroy (probed_geom); -error_close_dev: - ped_device_close (geom->dev); -error: - return 0; -} - -/** - * This function initializes a new file system of type \p type on - * a region described by \p geom, writing out appropriate metadata and - * signatures. If \p timer is non-NULL, it is used as the progress meter. - * - * \throws PED_EXCEPTION_NO_FEATURE if creating file system type \p type - * is not implemented yet - * - * \return a PedFileSystem on success, \c NULL on failure - */ -PedFileSystem* -ped_file_system_create (PedGeometry* geom, const PedFileSystemType* type, - PedTimer* timer) -{ - PedFileSystem* fs; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (type != NULL, return NULL); - - if (!type->ops->create) { - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for creating %s file systems " - "is not implemented yet."), - type->name); - goto error; - } - - if (!ped_device_open (geom->dev)) - goto error; - - if (!ped_file_system_clobber (geom)) - goto error_close_dev; - fs = type->ops->create (geom, timer); - if (!fs) - goto error_close_dev; - return fs; - -error_close_dev: - ped_device_close (geom->dev); -error: - return 0; -} - -/** - * Close file system \p fs. - * - * \return \c 1 on success, \c 0 on failure - */ -int -ped_file_system_close (PedFileSystem* fs) -{ - PedDevice* dev = fs->geom->dev; - - PED_ASSERT (fs != NULL, goto error_close_dev); - - if (!fs->type->ops->close (fs)) - goto error_close_dev; - ped_device_close (dev); - return 1; - -error_close_dev: - ped_device_close (dev); - return 0; -} - -/** - * Check \p fs file system for errors. - * - * \throws PED_EXCEPTION_NO_FEATURE if checking file system \p fs is - * not implemented yet - * - * \return \c 0 on failure (i.e. unfixed errors) - */ -int -ped_file_system_check (PedFileSystem* fs, PedTimer* timer) -{ - PED_ASSERT (fs != NULL, return 0); - - if (!fs->type->ops->check) { - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for checking %s file systems " - "is not implemented yet."), - fs->type->name); - return 0; - } - return fs->type->ops->check (fs, timer); -} - -static int -_raw_copy (const PedGeometry* src, PedGeometry* dest, PedTimer* timer) -{ - char* buf; - PedSector pos; - - PED_ASSERT (src != NULL, goto error); - PED_ASSERT (dest != NULL, goto error); - PED_ASSERT (src->length <= dest->length, goto error); - - buf = ped_malloc (BUFFER_SIZE * 512); /* FIXME */ - if (!buf) - goto error; - - if (!ped_device_open (src->dev)) - goto error_free_buf; - if (!ped_device_open (dest->dev)) - goto error_close_src; - - for (pos = 0; pos + BUFFER_SIZE < src->length; pos += BUFFER_SIZE) { - ped_timer_update (timer, 1.0 * pos / src->length); - if (!ped_geometry_read (src, buf, pos, BUFFER_SIZE)) - goto error_close_dest; - if (!ped_geometry_write (dest, buf, pos, BUFFER_SIZE)) - goto error_close_dest; - } - if (pos < src->length) { - ped_timer_update (timer, 1.0 * pos / src->length); - if (!ped_geometry_read (src, buf, pos, src->length - pos)) - goto error_close_dest; - if (!ped_geometry_write (dest, buf, pos, src->length - pos)) - goto error_close_dest; - } - ped_timer_update (timer, 1.0); - - ped_device_close (src->dev); - ped_device_close (dest->dev); - ped_free (buf); - return 1; - -error_close_dest: - ped_device_close (dest->dev); -error_close_src: - ped_device_close (src->dev); -error_free_buf: - ped_free (buf); -error: - return 0; -} - -static PedFileSystem* -_raw_copy_and_resize (const PedFileSystem* fs, PedGeometry* geom, - PedTimer* timer) -{ - PedFileSystem* new_fs; - PedTimer* sub_timer = NULL; - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("raw block copying")); - - sub_timer = ped_timer_new_nested (timer, 0.95); - if (!_raw_copy (fs->geom, geom, sub_timer)) - goto error; - ped_timer_destroy_nested (sub_timer); - - new_fs = ped_file_system_open (geom); - if (!new_fs) - goto error; - - ped_timer_set_state_name (timer, _("growing file system")); - - sub_timer = ped_timer_new_nested (timer, 0.05); - if (!ped_file_system_resize (new_fs, geom, sub_timer)) - goto error_close_new_fs; - ped_timer_destroy_nested (sub_timer); - return new_fs; - -error_close_new_fs: - ped_file_system_close (new_fs); -error: - ped_timer_destroy_nested (sub_timer); - return NULL; -} - -/** - * Create a new file system (of the same type) on \p geom, and - * copy the contents of \p fs into the new filesystem. - * If \p timer is non-NULL, it is used as the progress meter. - * - * \throws PED_EXCEPTION_ERROR when trying to copy onto an overlapping partition - * \throws PED_EXCEPTION_NO_FEATURE if copying of file system \p fs - * is not implemented yet - * - * \return a new PedFileSystem on success, \c NULL on failure - */ -PedFileSystem* -ped_file_system_copy (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - PedFileSystem* new_fs; - - PED_ASSERT (fs != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - - if (!ped_device_open (geom->dev)) - goto error; - - if (ped_geometry_test_overlap (fs->geom, geom)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Can't copy onto an overlapping partition.")); - goto error_close_dev; - } - - if (!fs->checked && fs->type->ops->check) { - if (!ped_file_system_check (fs, timer)) - goto error_close_dev; - } - - if (!ped_file_system_clobber_exclude (geom, fs->geom)) - goto error_close_dev; - - if (!fs->type->ops->copy) { - if (fs->type->ops->resize) { - if (fs->geom->length <= geom->length) - return _raw_copy_and_resize ( - fs, (PedGeometry*) geom, - timer); - - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Direct support for copying file systems is " - "not yet implemented for %s. However, " - "support for resizing is implemented. " - "Therefore, the file system can be copied if " - "the new partition is at least as big as the " - "old one. So, either shrink the partition " - "you are trying to copy, or copy to a bigger " - "partition."), - fs->type->name); - goto error_close_dev; - } else { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for copying %s file systems is not " - "implemented yet."), - fs->type->name); - goto error_close_dev; - } - } - new_fs = fs->type->ops->copy (fs, geom, timer); - if (!new_fs) - goto error_close_dev; - return new_fs; - -error_close_dev: - ped_device_close (geom->dev); -error: - return NULL;; -} - -/** - * Resize \p fs to new geometry \p geom. - * - * \p geom should satisfy the ped_file_system_get_resize_constraint(). - * (This isn't asserted, so it's not a bug not to... just it's likely - * to fail ;) If \p timer is non-NULL, it is used as the progress meter. - * - * \throws PED_EXCEPTION_NO_FEATURE if resizing of file system \p fs - * is not implemented yet - * - * \return \c 0 on failure - */ -int -ped_file_system_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - PED_ASSERT (fs != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - - if (!fs->type->ops->resize) { - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for resizing %s file systems " - "is not implemented yet."), - fs->type->name); - return 0; - } - if (!fs->checked && fs->type->ops->check) { - if (!ped_file_system_check (fs, timer)) - return 0; - } - if (!ped_file_system_clobber_exclude (geom, fs->geom)) - return 0; - - return fs->type->ops->resize (fs, geom, timer); -} - -/** - * This function returns a constraint on the region that all file systems - * of a particular type \p fs_type created on device \p dev with - * ped_file_system_create() must satisfy. For example, FAT16 file systems must - * be at least 32 megabytes. - * - * \return \c NULL on failure - */ -PedConstraint* -ped_file_system_get_create_constraint (const PedFileSystemType* fs_type, - const PedDevice* dev) -{ - PED_ASSERT (fs_type != NULL, return NULL); - PED_ASSERT (dev != NULL, return NULL); - - if (!fs_type->ops->get_create_constraint) - return NULL; - return fs_type->ops->get_create_constraint (dev); -} -/** - * Return a constraint, that represents all of the possible ways the - * file system \p fs can be resized with ped_file_system_resize(). - * This takes into account the amount of used space on - * the filesystem \p fs and the capabilities of the resize algorithm. - * Hints: - * -# if constraint->start_align->grain_size == 0, or - * constraint->start_geom->length == 1, then the start can not be moved - * -# constraint->min_size is the minimum size you can resize the partition - * to. You might want to tell the user this ;-). - * - * \return a PedConstraint on success, \c NULL on failure - */ -PedConstraint* -ped_file_system_get_resize_constraint (const PedFileSystem* fs) -{ - PED_ASSERT (fs != NULL, return 0); - - if (!fs->type->ops->get_resize_constraint) - return NULL; - return fs->type->ops->get_resize_constraint (fs); -} - -/** - * Get the constraint on copying \p fs with ped_file_system_copy() - * to somewhere on \p dev. - * - * \return a PedConstraint on success, \c NULL on failure - */ -PedConstraint* -ped_file_system_get_copy_constraint (const PedFileSystem* fs, - const PedDevice* dev) -{ - PedGeometry full_dev; - - PED_ASSERT (fs != NULL, return NULL); - PED_ASSERT (dev != NULL, return NULL); - - if (fs->type->ops->get_copy_constraint) - return fs->type->ops->get_copy_constraint (fs, dev); - - if (fs->type->ops->resize) { - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - fs->geom->length, dev->length); - } - - return NULL; -} - -/** @} */ diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/affs.c b/usr/src/lib/libparted/common/libparted/fs/amiga/affs.c deleted file mode 100644 index 0f5fd96a60..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/affs.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - affs.c -- parted support for affs file systems - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#include "amiga.h" -#include "affs.h" - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -static int -_affs_probe_root (uint32_t *block, int blocksize) { - int i; - uint32_t sum; - - if (PED_BE32_TO_CPU (block[0]) != 2) return 0; - if (PED_BE32_TO_CPU (block[128*blocksize-1]) != 1) return 0; - for (i = 0, sum = 0; i < 128*blocksize; i++) - sum += PED_BE32_TO_CPU (block[i]); - if (sum) return 0; - return 1; -} - -static PedGeometry* -_generic_affs_probe (PedGeometry* geom, uint32_t kind) -{ - uint32_t *block; - PedSector root, len, pos; - struct PartitionBlock * part; - int blocksize = 1, reserved = 2, prealloc = 0; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (geom->dev != NULL, return NULL); - - /* Finds the blocksize, prealloc and reserved values of the partition block */ - if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate partition block\n"), __func__); - goto error_part; - } - if (amiga_find_part(geom, part) != NULL) { - prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); - reserved = PED_BE32_TO_CPU (part->de_Reserved); - reserved = reserved == 0 ? 1 : reserved; - blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) - * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; - } - ped_free (part); - - /* Test boot block */ - if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate block\n"), __func__); - goto error_block; - } - if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); - goto error; - } - if (PED_BE32_TO_CPU (block[0]) != kind) { - goto error; - } - - /* Find and test the root block */ - len = geom->length / blocksize - reserved; - pos = (len - 1) / 2; - root = geom->start + (pos + reserved) * blocksize; - printf ("Pralloc = %d, Reserved = %d, blocksize = %d, root block at %llu\n", - prealloc, reserved, blocksize, root); - - if (!ped_device_read (geom->dev, block, root, blocksize)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read root block %llu\n"), __func__, root); - goto error; - } - if (_affs_probe_root(block, blocksize) == 1) { - ped_free (block); - return ped_geometry_duplicate (geom); - } - -error: - ped_free (block); -error_block: -error_part: - return NULL; -} -static PedGeometry* -_affs0_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5300); -} -static PedGeometry* -_affs1_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5301); -} -static PedGeometry* -_affs2_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5302); -} -static PedGeometry* -_affs3_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5303); -} -static PedGeometry* -_affs4_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5304); -} -static PedGeometry* -_affs5_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5305); -} -static PedGeometry* -_affs6_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5306); -} -static PedGeometry* -_affs7_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x444f5307); -} -static PedGeometry* -_amufs_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754653); -} -static PedGeometry* -_amufs0_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754600); -} -static PedGeometry* -_amufs1_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754601); -} -static PedGeometry* -_amufs2_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754602); -} -static PedGeometry* -_amufs3_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754603); -} -static PedGeometry* -_amufs4_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754604); -} -static PedGeometry* -_amufs5_probe (PedGeometry* geom) { - return _generic_affs_probe (geom, 0x6d754605); -} - -static PedFileSystemOps _affs0_ops = { - .probe = _affs0_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs1_ops = { - .probe = _affs1_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs2_ops = { - .probe = _affs2_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs3_ops = { - .probe = _affs3_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs4_ops = { - .probe = _affs4_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs5_ops = { - .probe = _affs5_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs6_ops = { - .probe = _affs6_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _affs7_ops = { - .probe = _affs7_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs_ops = { - .probe = _amufs_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs0_ops = { - .probe = _amufs0_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs1_ops = { - .probe = _amufs1_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs2_ops = { - .probe = _amufs2_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs3_ops = { - .probe = _amufs3_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs4_ops = { - .probe = _amufs4_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _amufs5_ops = { - .probe = _amufs5_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; - -#define AFFS_BLOCK_SIZES ((int[5]){512, 1024, 2048, 4096, 0}) -#define AMUFS_BLOCK_SIZES ((int[2]){512, 0}) - - -PedFileSystemType _affs0_type = { - .next = NULL, - .ops = &_affs0_ops, - .name = "affs0", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs1_type = { - .next = NULL, - .ops = &_affs1_ops, - .name = "affs1", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs2_type = { - .next = NULL, - .ops = &_affs2_ops, - .name = "affs2", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs3_type = { - .next = NULL, - .ops = &_affs3_ops, - .name = "affs3", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs4_type = { - .next = NULL, - .ops = &_affs4_ops, - .name = "affs4", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs5_type = { - .next = NULL, - .ops = &_affs5_ops, - .name = "affs5", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs6_type = { - .next = NULL, - .ops = &_affs6_ops, - .name = "affs6", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _affs7_type = { - .next = NULL, - .ops = &_affs7_ops, - .name = "affs7", - .block_sizes = AFFS_BLOCK_SIZES -}; -PedFileSystemType _amufs_type = { - .next = NULL, - .ops = &_amufs_ops, - .name = "amufs", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs0_type = { - .next = NULL, - .ops = &_amufs0_ops, - .name = "amufs0", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs1_type = { - .next = NULL, - .ops = &_amufs1_ops, - .name = "amufs1", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs2_type = { - .next = NULL, - .ops = &_amufs2_ops, - .name = "amufs2", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs3_type = { - .next = NULL, - .ops = &_amufs3_ops, - .name = "amufs3", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs4_type = { - .next = NULL, - .ops = &_amufs4_ops, - .name = "amufs4", - .block_sizes = AMUFS_BLOCK_SIZES -}; -PedFileSystemType _amufs5_type = { - .next = NULL, - .ops = &_amufs5_ops, - .name = "amufs5", - .block_sizes = AMUFS_BLOCK_SIZES -}; diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/affs.h b/usr/src/lib/libparted/common/libparted/fs/amiga/affs.h deleted file mode 100644 index 4138061445..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/affs.h +++ /dev/null @@ -1,19 +0,0 @@ - -/* - affs.h -- parted suppoer for affs filesystems header files - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.c b/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.c deleted file mode 100644 index 3983f54226..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - libparted/fs_amiga - amiga file system support. - Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - Contributor: Sven Luther -*/ - -#include -#include -#include -#include - -#include "amiga.h" - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define IDNAME_RIGIDDISK (uint32_t)0x5244534B /* 'RDSK' */ -#define IDNAME_BADBLOCK (uint32_t)0x42414442 /* 'BADB' */ -#define IDNAME_PARTITION (uint32_t)0x50415254 /* 'PART' */ -#define IDNAME_FILESYSHEADER (uint32_t)0x46534844 /* 'FSHD' */ -#define IDNAME_LOADSEG (uint32_t)0x4C534547 /* 'LSEG' */ -#define IDNAME_BOOT (uint32_t)0x424f4f54 /* 'BOOT' */ -#define IDNAME_FREE (uint32_t)0xffffffff - -static const char * -_amiga_block_id (uint32_t id) { - switch (id) { - case IDNAME_RIGIDDISK : - return "RDSK"; - case IDNAME_BADBLOCK : - return "BADB"; - case IDNAME_PARTITION : - return "PART"; - case IDNAME_FILESYSHEADER : - return "FSHD"; - case IDNAME_LOADSEG : - return "LSEG"; - case IDNAME_BOOT : - return "BOOT"; - case IDNAME_FREE : - return ""; - default : - return ""; - } -} - -struct AmigaIds * -_amiga_add_id (uint32_t id, struct AmigaIds *ids) { - struct AmigaIds *newid; - - if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate id list element\n"), __func__); - return 0; - } - newid->ID = id; - newid->next = ids; - return newid; -} - -void -_amiga_free_ids (struct AmigaIds *ids) { - struct AmigaIds *current, *next; - - for (current = ids; current != NULL; current = next) { - next = current->next; - ped_free (current); - } -} -int -_amiga_id_in_list (uint32_t id, struct AmigaIds *ids) { - struct AmigaIds *current; - - for (current = ids; current != NULL; current = current->next) { - if (id == current->ID) - return 1; - } - return 0; -} - -#define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff) - -struct AmigaBlock { - uint32_t amiga_ID; /* Identifier 32 bit word */ - uint32_t amiga_SummedLongss; /* Size of the structure for checksums */ - int32_t amiga_ChkSum; /* Checksum of the structure */ -}; -#define AMIGA(pos) ((struct AmigaBlock *)(pos)) - -struct RigidDiskBlock { - uint32_t rdb_ID; /* Identifier 32 bit word : 'RDSK' */ - uint32_t rdb_SummedLongs; /* Size of the structure for checksums */ - int32_t rdb_ChkSum; /* Checksum of the structure */ - uint32_t rdb_HostID; /* SCSI Target ID of host, not really used */ - uint32_t rdb_BlockBytes; /* Size of disk blocks */ - uint32_t rdb_Flags; /* RDB Flags */ - /* block list heads */ - uint32_t rdb_BadBlockList; /* Bad block list */ - uint32_t rdb_PartitionList; /* Partition list */ - uint32_t rdb_FileSysHeaderList; /* File system header list */ - uint32_t rdb_DriveInit; /* Drive specific init code */ - uint32_t rdb_BootBlockList; /* Amiga OS 4 Boot Blocks */ - uint32_t rdb_Reserved1[5]; /* Unused word, need to be set to $ffffffff */ - /* physical drive characteristics */ - uint32_t rdb_Cylinders; /* Number of the cylinders of the drive */ - uint32_t rdb_Sectors; /* Number of sectors of the drive */ - uint32_t rdb_Heads; /* Number of heads of the drive */ - uint32_t rdb_Interleave; /* Interleave */ - uint32_t rdb_Park; /* Head parking cylinder */ - uint32_t rdb_Reserved2[3]; /* Unused word, need to be set to $ffffffff */ - uint32_t rdb_WritePreComp; /* Starting cylinder of write precompensation */ - uint32_t rdb_ReducedWrite; /* Starting cylinder of reduced write current */ - uint32_t rdb_StepRate; /* Step rate of the drive */ - uint32_t rdb_Reserved3[5]; /* Unused word, need to be set to $ffffffff */ - /* logical drive characteristics */ - uint32_t rdb_RDBBlocksLo; /* low block of range reserved for hardblocks */ - uint32_t rdb_RDBBlocksHi; /* high block of range for these hardblocks */ - uint32_t rdb_LoCylinder; /* low cylinder of partitionable disk area */ - uint32_t rdb_HiCylinder; /* high cylinder of partitionable data area */ - uint32_t rdb_CylBlocks; /* number of blocks available per cylinder */ - uint32_t rdb_AutoParkSeconds; /* zero for no auto park */ - uint32_t rdb_HighRDSKBlock; /* highest block used by RDSK */ - /* (not including replacement bad blocks) */ - uint32_t rdb_Reserved4; - /* drive identification */ - char rdb_DiskVendor[8]; - char rdb_DiskProduct[16]; - char rdb_DiskRevision[4]; - char rdb_ControllerVendor[8]; - char rdb_ControllerProduct[16]; - char rdb_ControllerRevision[4]; - uint32_t rdb_Reserved5[10]; -}; - -#define AMIGA_MAX_PARTITIONS 128 -#define RDB_LOCATION_LIMIT 16 -#define RDSK(pos) ((struct RigidDiskBlock *)(pos)) - -static int -_amiga_checksum (struct AmigaBlock *blk) { - uint32_t *rdb = (uint32_t *) blk; - uint32_t sum; - int i, end; - - sum = PED_BE32_TO_CPU (rdb[0]); - end = PED_BE32_TO_CPU (rdb[1]); - - if (end > PED_SECTOR_SIZE_DEFAULT) end = PED_SECTOR_SIZE_DEFAULT; - - for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]); - - return sum; -} - -static void -_amiga_calculate_checksum (struct AmigaBlock *blk) { - - blk->amiga_ChkSum = PED_CPU_TO_BE32( - PED_BE32_TO_CPU(blk->amiga_ChkSum) - - _amiga_checksum((struct AmigaBlock *) blk)); - return; -} - - -static struct AmigaBlock * -_amiga_read_block (PedDevice *dev, struct AmigaBlock *blk, PedSector block, struct AmigaIds *ids) { - if (!ped_device_read (dev, blk, block, 1)) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Couldn't read block %llu\n"), __func__, block)) - { - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - return NULL; - } - } - if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids)) - return NULL; - if (_amiga_checksum (blk) != 0) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, - _("%s : Bad checksum on block %llu of type %s\n"), - __func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID)))) - { - case PED_EXCEPTION_CANCEL : - return NULL; - case PED_EXCEPTION_FIX : - _amiga_calculate_checksum(AMIGA(blk)); - if (!ped_device_write (dev, blk, block, 1)) { - switch (ped_exception_throw(PED_EXCEPTION_FATAL, - PED_EXCEPTION_CANCEL, - _("%s : Couldn't write block %d\n"), __func__, block)) - { - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - return NULL; - } - } - case PED_EXCEPTION_IGNORE : - case PED_EXCEPTION_UNHANDLED : - default : - return blk; - } - } - return blk; -} - -static uint32_t -_amiga_find_rdb (PedDevice *dev, struct RigidDiskBlock *rdb) { - int i; - struct AmigaIds *ids; - - ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL); - - for (i = 0; irdb_ID) == IDNAME_RIGIDDISK) { - _amiga_free_ids (ids); - return i; - } - } - _amiga_free_ids (ids); - return AMIGA_RDB_NOT_FOUND; -} - -static int -_amiga_loop_check (uint32_t block, uint32_t * blocklist, uint32_t max) -{ - uint32_t i; - - for (i = 0; i < max; i++) - if (block == blocklist[i]) { - /* We are looping, let's stop. */ - return 1; - } - blocklist[max] = block; - return 0; -} - -/* We have already allocated a rdb, we are now reading it from the disk */ -struct PartitionBlock * -amiga_find_part (PedGeometry *geom, struct PartitionBlock *part) -{ - struct RigidDiskBlock *rdb; - uint32_t partblock; - uint32_t partlist[AMIGA_MAX_PARTITIONS]; - int i; - - PED_ASSERT(geom!= NULL, return NULL); - PED_ASSERT(geom->dev!= NULL, return NULL); - - if (!(rdb = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate disk_specific rdb block\n"), __func__)) - { - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - return NULL; - } - } - if (_amiga_find_rdb (geom->dev, rdb) == AMIGA_RDB_NOT_FOUND) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Didn't find rdb block, should never happen\n"), __func__)) - { - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - ped_free(rdb); - return NULL; - } - } - - /* We initialize the hardblock free list to detect loops */ - for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = IDNAME_FREE; - - for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList); - i < AMIGA_MAX_PARTITIONS && partblock != IDNAME_FREE; - i++, partblock = PED_BE32_TO_CPU(part->pb_Next)) - { - PedSector start, end; - PedSector cylblocks; - - /* Let's look for loops in the partition table */ - if (_amiga_loop_check(partblock, partlist, i)) { - ped_free (rdb); - return NULL; - } - /* Let's read a partition block to get its geometry*/ - if (!ped_device_read (geom->dev, part, (PedSector)partblock, 1)) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to read partition block %llu\n"), - __func__, (PedSector)partblock)) - { - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - ped_free(rdb); - return NULL; - } - } - - /* Current block is not a Partition Block */ - if (part->pb_ID != IDNAME_PARTITION) { - ped_free (rdb); - return NULL; - } - - /* Calculate the geometry of the partition */ - cylblocks = ((PedSector) PED_BE32_TO_CPU (part->de_Surfaces)) * - ((PedSector) PED_BE32_TO_CPU (part->de_BlocksPerTrack)); - start = ((PedSector) PED_BE32_TO_CPU (part->de_LowCyl)) * cylblocks; - end = ((((PedSector) PED_BE32_TO_CPU (part->de_HighCyl))+1) * (cylblocks))-1; - - /* And check if it is the one we are searching for */ - if (start == geom->start && end == geom->end) { - ped_free (rdb); - return part; - } - } - - ped_free (rdb); - return NULL; -} diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.h b/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.h deleted file mode 100644 index da46fdc689..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/amiga.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - util.h -- amiga partition table headers. - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -struct PartitionBlock { - uint32_t pb_ID; /* Identifier 32 bit word : 'PART' */ - uint32_t pb_SummedLongs; /* Size of the structure for checksums */ - int32_t pb_ChkSum; /* Checksum of the structure */ - uint32_t pb_HostID; /* SCSI Target ID of host, not really used */ - uint32_t pb_Next; /* Block number of the next PartitionBlock */ - uint32_t pb_Flags; /* Part Flags (NOMOUNT and BOOTABLE) */ - uint32_t pb_Reserved1[2]; - uint32_t pb_DevFlags; /* Preferred flags for OpenDevice */ - uint8_t pb_DriveName[32]; /* Preferred DOS device name: BSTR form */ - uint32_t pb_Reserved2[15]; - uint32_t de_TableSize; /* Size of Environment vector */ - uint32_t de_SizeBlock; /* Size of the blocks in 32 bit words, usually 128 */ - uint32_t de_SecOrg; /* Not used; must be 0 */ - uint32_t de_Surfaces; /* Number of heads (surfaces) */ - uint32_t de_SectorPerBlock; /* Disk sectors per block, used with SizeBlock, usually 1 */ - uint32_t de_BlocksPerTrack; /* Blocks per track. drive specific */ - uint32_t de_Reserved; /* DOS reserved blocks at start of partition. */ - uint32_t de_PreAlloc; /* DOS reserved blocks at end of partition */ - uint32_t de_Interleave; /* Not used, usually 0 */ - uint32_t de_LowCyl; /* First cylinder of the partition */ - uint32_t de_HighCyl; /* Last cylinder of the partition */ - uint32_t de_NumBuffers; /* Initial # DOS of buffers. */ - uint32_t de_BufMemType; /* Type of mem to allocate for buffers */ - uint32_t de_MaxTransfer; /* Max number of bytes to transfer at a time */ - uint32_t de_Mask; /* Address Mask to block out certain memory */ - int32_t de_BootPri; /* Boot priority for autoboot */ - uint32_t de_DosType; /* Dostype of the file system */ - uint32_t de_Baud; /* Baud rate for serial handler */ - uint32_t de_Control; /* Control word for handler/filesystem */ - uint32_t de_BootBlocks; /* Number of blocks containing boot code */ - uint32_t pb_EReserved[12]; -}; - -#define PART(pos) ((struct PartitionBlock *)(pos)) - -#define PBFB_BOOTABLE 0 /* this partition is intended to be bootable */ -#define PBFF_BOOTABLE 1L /* (expected directories and files exist) */ -#define PBFB_NOMOUNT 1 /* do not mount this partition (e.g. manually */ -#define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */ - -struct PartitionBlock * amiga_find_part (PedGeometry *geom, struct PartitionBlock *part); - -struct AmigaIds { - uint32_t ID; - struct AmigaIds *next; -}; - -struct AmigaIds * _amiga_add_id (uint32_t id, struct AmigaIds *ids); -void _amiga_free_ids (struct AmigaIds *ids); -int _amiga_id_in_list (uint32_t id, struct AmigaIds *ids); - diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.c b/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.c deleted file mode 100644 index 912b72bc8b..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - apfs.c -- parted support for apfs file systems - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#include "amiga.h" -#include "apfs.h" - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -static int -_apfs_probe_root (uint32_t *block, uint32_t blocksize, uint32_t kind) { - if (PED_BE32_TO_CPU (block[0]) != kind) return 0; - return 1; -} - -static PedGeometry* -_generic_apfs_probe (PedGeometry* geom, uint32_t kind) -{ - uint32_t *block; - PedSector root; - struct PartitionBlock * part; - uint32_t blocksize = 1, reserved = 2, prealloc = 0; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (geom->dev != NULL, return NULL); - - /* Finds the blocksize, prealloc and reserved values of the partition block */ - if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate partition block\n"), __func__); - goto error_part; - } - if (amiga_find_part(geom, part) != NULL) { - prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); - reserved = PED_BE32_TO_CPU (part->de_Reserved); - blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) - * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; - } - ped_free (part); - - /* Test boot block */ - if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate block\n"), __func__); - goto error_block; - } - if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); - goto error; - } - if (PED_BE32_TO_CPU (block[0]) != kind) { - goto error; - } - - /* Find and test the root block */ - root = geom->start+reserved*blocksize; - if (!ped_device_read (geom->dev, block, root, blocksize)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read root block %llu\n"), __func__, root); - goto error; - } - if (_apfs_probe_root(block, blocksize, kind) == 1) { - ped_free(block); - return ped_geometry_duplicate (geom); - } - -error: - ped_free (block); -error_block: -error_part: - return NULL; -} - -static PedGeometry* -_apfs1_probe (PedGeometry* geom) { - return _generic_apfs_probe (geom, 0x50463101); -} - -static PedGeometry* -_apfs2_probe (PedGeometry* geom) { - return _generic_apfs_probe (geom, 0x50463102); -} - -static PedFileSystemOps _apfs1_ops = { - .probe = _apfs1_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; -static PedFileSystemOps _apfs2_ops = { - .probe = _apfs2_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; - -#define APFS_BLOCK_SIZES ((int[2]){512, 0}) - -PedFileSystemType _apfs1_type = { - .next = NULL, - .ops = &_apfs1_ops, - .name = "apfs1", - .block_sizes = APFS_BLOCK_SIZES -}; -PedFileSystemType _apfs2_type = { - .next = NULL, - .ops = &_apfs2_ops, - .name = "apfs2", - .block_sizes = APFS_BLOCK_SIZES -}; diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.h b/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.h deleted file mode 100644 index 7dadb91d2c..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/apfs.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - apfs.h -- parted support for apfs file systems header files - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.c b/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.c deleted file mode 100644 index 774a2c3c83..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - asfs.c -- parted asfs filesystem support - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#include "amiga.h" -#include "asfs.h" - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -static int -_asfs_probe_root (PedGeometry *geom, uint32_t *block, int blocksize, PedSector root) { - int i, sum; - PedSector start, end; - - if (PED_BE32_TO_CPU (block[0]) != 0x53465300) return 0; - for (i = 0, sum = 1; i < 128*blocksize; i++) sum += PED_BE32_TO_CPU (block[i]); - if (sum != 0) return 0; - if (PED_BE32_TO_CPU (block[2]) * blocksize + geom->start != root) { - return 0; - } - start = ((((PedSector) PED_BE32_TO_CPU (block[8])) << 32) - + (PedSector) PED_BE32_TO_CPU (block[9])) / 512; - end = (((((PedSector) PED_BE32_TO_CPU (block[10])) << 32) - + (PedSector) PED_BE32_TO_CPU (block[11])) / 512) - 1; - if (start != geom->start || end != geom->end) return 0; - return 1; -} - -static PedGeometry* -_asfs_probe (PedGeometry* geom) -{ - uint32_t *block; - struct PartitionBlock * part; - int blocksize = 1, reserved = 1, prealloc = 1; - PedSector root; - int found = 0; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (geom->dev != NULL, return NULL); - - /* Finds the blocksize, prealloc and reserved values of the partition block */ - if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate partition block\n"), __func__); - goto error_part; - } - if (amiga_find_part(geom, part) != NULL) { - prealloc = PED_BE32_TO_CPU (part->de_PreAlloc) == 0 ? - 1 : PED_BE32_TO_CPU (part->de_PreAlloc); - reserved = PED_BE32_TO_CPU (part->de_Reserved) == 0 ? - 1 : PED_BE32_TO_CPU (part->de_Reserved); - blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) - * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; - } - ped_free (part); - - /* Test boot block */ - if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Failed to allocate block\n"), __func__); - goto error_block; - } - root = geom->start; - if (!ped_device_read (geom->dev, block, root, blocksize)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read root block %llu\n"), __func__, root); - goto error; - } - if (PED_BE32_TO_CPU (block[0]) != 0x53465300) { - goto error; - } - - /* Find and test the root blocks */ - if (_asfs_probe_root(geom, block, blocksize, root)) { - found++; - } - root = geom->end - blocksize - (geom->length % blocksize) + 1; - if (!ped_device_read (geom->dev, block, root, 1)) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Couldn't read root block %llu\n"), __func__, root); - goto error; - } - if (_asfs_probe_root(geom, block, blocksize, root)) { - found++; - } - if (found != 0) { - ped_free (block); - return ped_geometry_duplicate (geom); - } - -error: - ped_free (block); -error_block: -error_part: - return NULL; -} - -static PedFileSystemOps _asfs_ops = { - .probe = _asfs_probe, - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -}; - -PedFileSystemType _asfs_type = { - .next = NULL, - .ops = &_asfs_ops, - .name = "asfs", - .block_sizes = ((int[2]){512, 0}) -}; diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.h b/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.h deleted file mode 100644 index 141677e1be..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/asfs.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - asfs.h -- parted asfs filesystem support header files - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ diff --git a/usr/src/lib/libparted/common/libparted/fs/amiga/interface.c b/usr/src/lib/libparted/common/libparted/fs/amiga/interface.c deleted file mode 100644 index 4bbe5a4d25..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/amiga/interface.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - interface.c -- parted support amiga file systems - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#include - -#include -#include -#include - -extern PedFileSystemType _affs0_type; -extern PedFileSystemType _affs1_type; -extern PedFileSystemType _affs2_type; -extern PedFileSystemType _affs3_type; -extern PedFileSystemType _affs4_type; -extern PedFileSystemType _affs5_type; -extern PedFileSystemType _affs6_type; -extern PedFileSystemType _affs7_type; -extern PedFileSystemType _amufs_type; -extern PedFileSystemType _amufs0_type; -extern PedFileSystemType _amufs1_type; -extern PedFileSystemType _amufs2_type; -extern PedFileSystemType _amufs3_type; -extern PedFileSystemType _amufs4_type; -extern PedFileSystemType _amufs5_type; -extern PedFileSystemType _asfs_type; -extern PedFileSystemType _apfs1_type; -extern PedFileSystemType _apfs2_type; - -void ped_file_system_amiga_init () -{ - ped_file_system_type_register (&_affs0_type); - ped_file_system_type_register (&_affs1_type); - ped_file_system_type_register (&_affs2_type); - ped_file_system_type_register (&_affs3_type); - ped_file_system_type_register (&_affs4_type); - ped_file_system_type_register (&_affs5_type); - ped_file_system_type_register (&_affs6_type); - ped_file_system_type_register (&_affs7_type); - ped_file_system_type_register (&_amufs_type); - ped_file_system_type_register (&_amufs0_type); - ped_file_system_type_register (&_amufs1_type); - ped_file_system_type_register (&_amufs2_type); - ped_file_system_type_register (&_amufs3_type); - ped_file_system_type_register (&_amufs4_type); - ped_file_system_type_register (&_amufs5_type); - ped_file_system_type_register (&_asfs_type); - ped_file_system_type_register (&_apfs1_type); - ped_file_system_type_register (&_apfs2_type); -} - -void ped_file_system_amiga_done () -{ - ped_file_system_type_unregister (&_affs0_type); - ped_file_system_type_unregister (&_affs1_type); - ped_file_system_type_unregister (&_affs2_type); - ped_file_system_type_unregister (&_affs3_type); - ped_file_system_type_unregister (&_affs4_type); - ped_file_system_type_unregister (&_affs5_type); - ped_file_system_type_unregister (&_affs6_type); - ped_file_system_type_unregister (&_affs7_type); - ped_file_system_type_unregister (&_amufs_type); - ped_file_system_type_unregister (&_amufs0_type); - ped_file_system_type_unregister (&_amufs1_type); - ped_file_system_type_unregister (&_amufs2_type); - ped_file_system_type_unregister (&_amufs3_type); - ped_file_system_type_unregister (&_amufs4_type); - ped_file_system_type_unregister (&_amufs5_type); - ped_file_system_type_unregister (&_asfs_type); - ped_file_system_type_unregister (&_apfs1_type); - ped_file_system_type_unregister (&_apfs2_type); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c deleted file mode 100644 index 618fca9c4a..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c +++ /dev/null @@ -1,792 +0,0 @@ -/* - ext2.c -- generic ext2 stuff - Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include -#include -#include -#include "ext2.h" - -/* ext2 stuff ****************************************************************/ - -unsigned char _bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; - -int ext2_copy_block(struct ext2_fs *fs, blk_t from, blk_t to) -{ - unsigned char* buf = ped_malloc (fs->blocksize); - - if (!ext2_bcache_flush(fs, from)) return 0; - if (!ext2_bcache_flush(fs, to)) return 0; - - if (!ext2_read_blocks(fs, buf, from, 1)) return 0; - if (!ext2_write_blocks(fs, buf, to, 1)) return 0; - - return 1; -} - -int ext2_get_block_state(struct ext2_fs *fs, blk_t block) -{ - struct ext2_buffer_head *bh; - int group; - int offset; - int state; - - block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); - state = bh->data[offset>>3] & _bitmap[offset&7]; - ext2_brelse(bh, 0); - - return state; -} - -blk_t ext2_find_free_block(struct ext2_fs *fs) -{ - int i; - - for (i=0;inumgroups;i++) - if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i])) - { - blk_t j; - blk_t offset; - - offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - for (j=fs->adminblocks; - jsb); - j++) - if (ext2_is_data_block(fs, offset + j) && - !ext2_get_block_state(fs, offset + j)) - return offset + j; - - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Inconsistent group descriptors!")); - } - - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system full!")); - return 0; -} - -ino_t ext2_find_free_inode(struct ext2_fs *fs) -{ - int i; - - for (i=0;inumgroups;i++) - if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i])) - { - ino_t j; - ino_t offset; - - offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; - for (j=0;jsb);j++) - if (!ext2_get_inode_state(fs, offset + j)) - return offset + j; - - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Inconsistent group descriptors!")); - } - - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system full!")); - return 0; -} - -int ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest) -{ - unsigned char *buf; - blk_t i; - - ped_exception_fetch_all(); - if ((buf = ped_malloc(num << fs->logsize)) != NULL) - { - ped_exception_leave_all(); - - if (!ext2_bcache_flush_range(fs, src, num)) return 0; - if (!ext2_bcache_flush_range(fs, dest, num)) return 0; - - if (!ext2_read_blocks(fs, buf, src, num)) return 0; - if (!ext2_write_blocks(fs, buf, dest, num)) return 0; - - ped_free(buf); - return 1; - } - ped_exception_catch(); - ped_exception_leave_all(); - - if (src > dest) - { - for (i=0;i0;i--) - if (!ext2_copy_block(fs, src+i, dest+i)) - return 0; - } - return 1; -} - -int ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num) -{ - return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num); -} - -int ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata) -{ - struct ext2_buffer_head *bh; - int group; - int offset; - - block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); - bh->dirty = 1; - if (state) - bh->data[offset>>3] |= _bitmap[offset&7]; - else - bh->data[offset>>3] &= ~_bitmap[offset&7]; - ext2_brelse(bh, 0); - - if (updatemetadata) - { - int diff; - - diff = state ? -1 : 1; - - fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16 - (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff); - fs->sb.s_free_blocks_count = PED_CPU_TO_LE32 - (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff); - fs->metadirty |= EXT2_META_SB | EXT2_META_GD; - } - return 1; -} - -int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num) -{ - return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num); -} - -int ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num) -{ - unsigned char *buf; - blk_t i; - - ped_exception_fetch_all(); - buf = ped_malloc (num << fs->logsize); - if (buf) - { - ped_exception_leave_all(); - - memset(buf, 0, num << fs->logsize); - if (!ext2_bcache_flush_range(fs, block, num)) - goto error_free_buf; - if (!ext2_write_blocks(fs, buf, block, num)) - goto error_free_buf; - ped_free(buf); - return 1; - } - ped_exception_catch(); - - buf = ped_malloc (fs->blocksize); - if (buf) - { - ped_exception_leave_all(); - - memset(buf, 0, fs->blocksize); - - for (i=0;idirty = 1; - if (!ext2_brelse(bh, 1)) - goto error; - } - return 1; - -error_free_buf: - ped_free(buf); -error: - return 0; -} - -off_t ext2_get_inode_offset(struct ext2_fs *fs, ino_t inode, blk_t *block) -{ - int group; - int offset; - - inode--; - - group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); - offset = (inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb)) - * sizeof(struct ext2_inode); - - *block = EXT2_GROUP_INODE_TABLE(fs->gd[group]) - + (offset >> fs->logsize); - - return offset & (fs->blocksize - 1); -} - -int ext2_get_inode_state(struct ext2_fs *fs, ino_t inode) -{ - struct ext2_buffer_head *bh; - int group; - int offset; - int ret; - - inode--; - group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); - offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb); - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group])); - ret = bh->data[offset>>3] & _bitmap[offset&7]; - ext2_brelse(bh, 0); - - return ret; -} - -int ext2_read_inode(struct ext2_fs *fs, ino_t inode, struct ext2_inode *data) -{ - struct ext2_buffer_head *bh; - blk_t blk; - off_t off; - - off = ext2_get_inode_offset(fs, inode, &blk); - - bh = ext2_bread(fs, blk); - if (!bh) - return 0; - - memcpy(data, bh->data + off, sizeof(struct ext2_inode)); - ext2_brelse(bh, 0); - return 1; -} - -int ext2_set_inode_state(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata) -{ - struct ext2_buffer_head *bh; - int group; - int offset; - - inode--; - group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb); - offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb); - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group])); - if (!bh) - return 0; - bh->dirty = 1; - if (state) - bh->data[offset>>3] |= _bitmap[offset&7]; - else - bh->data[offset>>3] &= ~_bitmap[offset&7]; - ext2_brelse(bh, 0); - - if (updatemetadata) - { - int diff; - - diff = state ? -1 : 1; - - fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16 - (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) + diff); - fs->sb.s_free_inodes_count = PED_CPU_TO_LE32 - (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) + diff); - fs->metadirty = EXT2_META_SB | EXT2_META_GD; - } - return 1; -} - -static void -_inode_update_size(struct ext2_fs *fs, struct ext2_inode *inode, int delta) -{ - int i512perblock = 1 << (fs->logsize - 9); - uint64_t size; - - /* i_blocks is in 512 byte blocks */ - inode->i_blocks = PED_CPU_TO_LE32(EXT2_INODE_BLOCKS(*inode) - + delta * i512perblock); - size = EXT2_INODE_SIZE(*inode) + delta * fs->blocksize; - inode->i_size = PED_CPU_TO_LE32(size % (1LL << 32)); - inode->i_size_high = PED_CPU_TO_LE32(size / (1LL << 32)); - inode->i_mtime = PED_CPU_TO_LE32(time(NULL)); -} - -int ext2_do_inode(struct ext2_fs *fs, struct ext2_inode *inode, blk_t block, - int action) -{ - struct ext2_buffer_head *bh; - uint32_t *udata; - blk_t count = 0; - int i; - int u32perblock = fs->blocksize >> 2; - int i512perblock = 1 << (fs->logsize - 9); - - if (block == 0 || EXT2_INODE_MODE(*inode) == 0) - return -1; - - if (fs->opt_debug) - switch (action) - { - case EXT2_ACTION_ADD: - fprintf(stderr,"adding 0x%04x to inode\n", - block); - break; - case EXT2_ACTION_DELETE: - fprintf(stderr,"deleting 0x%04x from inode\n", - block); - break; - case EXT2_ACTION_FIND: - fprintf(stderr,"finding 0x%04x in inode\n", - block); - break; - } - - /* Direct blocks for first 12 blocks */ - for (i = 0; i < EXT2_NDIR_BLOCKS; i++) - { - if (action == EXT2_ACTION_ADD && !EXT2_INODE_BLOCK(*inode, i)) - { - inode->i_block[i] = PED_CPU_TO_LE32(block); - _inode_update_size (fs, inode, 1); - ext2_set_block_state(fs, block, 1, 1); - return i; - } - if (EXT2_INODE_BLOCK(*inode, i) == block) - { - if (action == EXT2_ACTION_DELETE) - { - inode->i_block[i] = 0; - _inode_update_size (fs, inode, -1); - ext2_set_block_state(fs, block, 0, 1); - } - return i; - } - if (EXT2_INODE_BLOCK(*inode, i)) - count += i512perblock; - } - - count += EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ? i512perblock : 0; - count += EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ? i512perblock : 0; - count += EXT2_INODE_BLOCK(*inode, EXT2_TIND_BLOCK) ? i512perblock : 0; - - if (!EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) || - (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD)) - return -1; - - bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK)); - udata = (uint32_t *)bh->data; - - /* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */ - for (i = 0; i < u32perblock; i++) { - if (action == EXT2_ACTION_ADD && !udata[i]) { - bh->dirty = 1; - udata[i] = PED_CPU_TO_LE32(block); - _inode_update_size (fs, inode, 1); - ext2_set_block_state(fs, block, 1, 1); - ext2_brelse(bh, 0); - return EXT2_NDIR_BLOCKS + i; - } - if (PED_LE32_TO_CPU(udata[i]) == block) { - if (action == EXT2_ACTION_DELETE) { - bh->dirty = 1; - udata[i] = 0; - _inode_update_size (fs, inode, -1); - ext2_set_block_state(fs, block, 0, 1); - } - ext2_brelse(bh, 0); - return EXT2_NDIR_BLOCKS + i; - } - if (udata[i]) - { - count += i512perblock; - if (count >= EXT2_INODE_BLOCKS(*inode) && - action != EXT2_ACTION_ADD) - return -1; - } - } - - ext2_brelse(bh, 0); - - if (!EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) || - (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD)) - return -1; - bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK)); - udata = (uint32_t *)bh->data; - - /* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */ - for (i = 0; i < u32perblock; i++) { - struct ext2_buffer_head *bh2; - uint32_t *udata2; - int j; - - if (!udata[i]) { - ext2_brelse(bh, 0); - return -1; - } - bh2 = ext2_bread(fs, PED_LE32_TO_CPU(udata[i])); - udata2 = (uint32_t *)bh2->data; - count += i512perblock; - - for (j = 0; j < u32perblock; j++) { - if (action == EXT2_ACTION_ADD && !udata2[j]) { - bh2->dirty = 1; - udata2[j] = PED_CPU_TO_LE32(block); - _inode_update_size (fs, inode, 1); - ext2_set_block_state(fs, block, 1, 1); - ext2_brelse(bh, 0); - ext2_brelse(bh2, 0); - return EXT2_NDIR_BLOCKS + i * u32perblock + j; - } - if (PED_LE32_TO_CPU(udata2[j]) == block) { - if (action == EXT2_ACTION_DELETE) { - bh2->dirty = 1; - udata2[j] = 0; - _inode_update_size (fs, inode, -1); - ext2_set_block_state(fs, block, 0, 1); - } - ext2_brelse(bh, 0); - ext2_brelse(bh2, 0); - return EXT2_NDIR_BLOCKS + i * u32perblock + j; - } - if (udata2[j]) - { - count += i512perblock; - if (count >= EXT2_INODE_BLOCKS(*inode) && - action != EXT2_ACTION_ADD) - return -1; - } - } - ext2_brelse(bh2, 0); - } - ext2_brelse(bh, 0); - - /* FIXME: we should check for triple-indirect blocks here, but it - * would be nice to have a better routine to traverse blocks, and - * file systems that need triple-indirect blocks for the resize - * inode are too big to worry about yet. - */ - - return -1; -} - -int ext2_write_inode(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *data) -{ - struct ext2_buffer_head *bh; - blk_t blk; - off_t off; - - off = ext2_get_inode_offset(fs, inode, &blk); - - bh = ext2_bread(fs, blk); - if (!bh) - return 0; - bh->dirty = 1; - memcpy(bh->data + off, data, sizeof(struct ext2_inode)); - ext2_brelse(bh, 0); - - return 1; -} - -int ext2_zero_inode(struct ext2_fs *fs, ino_t inode) -{ - struct ext2_inode buf; - - memset(&buf, 0, sizeof(struct ext2_inode)); - return ext2_write_inode(fs, inode, &buf); -} - - - - - -/* check whether y is root of x - * (formula grabbed from linux ext2 kernel source) */ -static int is_root(int x, int y) -{ - if (!x) - return 1; - - while (1) - { - if (x == 1) - return 1; - - if (x % y) - return 0; - - x /= y; - } -} - -/* check whether group contains a superblock copy on file systems - * where not all groups have one (sparse superblock feature) */ -int ext2_is_group_sparse(struct ext2_fs *fs, int group) -{ - if (!fs->sparse) - return 1; - - if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7)) - return 1; - - return 0; -} - -void ext2_close(struct ext2_fs *fs) -{ - ext2_commit_metadata(fs, EXT2_META_PRIMARY | EXT2_META_BACKUP); - ext2_sync(fs); - - ext2_bcache_deinit(fs); - - fs->devhandle->ops->close(fs->devhandle->cookie); - - ped_free(fs->gd); - ped_free(fs); -} - -int ext2_commit_metadata(struct ext2_fs *fs, int copies) -{ - int i; - int num; - int wmeta = fs->metadirty & copies; - unsigned char* sb = ped_malloc(fs->blocksize); - struct ext2_super_block *sb_for_io; - int sb_block; - - /* See if there is even anything to write... */ - if (wmeta == EXT2_META_CLEAN) - return 1; - - fs->sb.s_r_blocks_count = PED_CPU_TO_LE32 ( - fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb) - / 100); - - if (!ext2_read_blocks (fs, sb, 0, 1)) - return 0; - - if (EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) { - memcpy(sb, &fs->sb, 1024); - sb_for_io = (struct ext2_super_block *) sb; - } else { - memcpy(sb+1024, &fs->sb, 1024); - sb_for_io = (struct ext2_super_block *) (sb + 1024); - } - - num = copies & EXT2_META_BACKUP ? fs->numgroups : 1; - - for (i = 0, sb_block = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); i < num; - i++, sb_block += EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - { - - if (!ext2_is_group_sparse(fs, i)) - continue; - - if (fs->dynamic_version) - sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i); - - if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) || - (i != 0 && wmeta & EXT2_META_SB)) - { - if (!ext2_bcache_flush_range(fs, sb_block, 1)) - return 0; - if (!ext2_write_blocks(fs, sb, sb_block, 1)) - return 0; - } - if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) || - (i != 0 && wmeta & EXT2_META_GD)) - { - if (!ext2_bcache_flush_range(fs, sb_block + 1, - fs->gdblocks)) - return 0; - if (!ext2_write_blocks(fs, fs->gd, sb_block + 1, - fs->gdblocks)) - return 0; - } - } - - sb_for_io->s_block_group_nr = 0; - - /* Clear the flags of the components we just finished writing. */ - fs->metadirty &= ~copies; - - return 1; -} - -int ext2_sync(struct ext2_fs *fs) -{ - if (!ext2_commit_metadata(fs, EXT2_META_PRIMARY)) return 0; - if (!ext2_bcache_sync(fs)) return 0; - if (!fs->devhandle->ops->sync(fs->devhandle->cookie)) return 0; - return 1; -} - -struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, int state) -{ - struct ext2_fs *fs; - - if ((fs = (struct ext2_fs *) ped_malloc(sizeof(struct ext2_fs))) - == NULL) - goto error; - - handle->ops->set_blocksize(handle->cookie, 10); - - if (!handle->ops->read(handle->cookie, &fs->sb, 1, 1) - || EXT2_SUPER_MAGIC(fs->sb) != EXT2_SUPER_MAGIC_CONST) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Invalid superblock. Are you sure this is an ext2 " - "file system?")); - goto error_free_fs; - } - - - fs->opt_debug = 1; - fs->opt_safe = 1; - fs->opt_verbose = 0; - - if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS & ~(state & EXT2_ERROR_FS)) - { - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, - _("File system has errors! You should run e2fsck.")) - == PED_EXCEPTION_CANCEL) - goto error_free_fs; - } - - if (!((EXT2_SUPER_STATE(fs->sb) | state) & EXT2_VALID_FS) - || (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb) - & EXT3_FEATURE_INCOMPAT_RECOVER)) - { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, - _("File system was not cleanly unmounted! " - "You should run e2fsck. Modifying an unclean " - "file system could cause severe corruption.")) - != PED_EXCEPTION_IGNORE) - goto error_free_fs; - } - - fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0; - - if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb) - & ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL | - EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) || - (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb) - & ~(EXT2_FEATURE_INCOMPAT_FILETYPE | - EXT3_FEATURE_INCOMPAT_RECOVER)) || - (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb) - & ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER | - EXT2_FEATURE_RO_COMPAT_LARGE_FILE))) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an incompatible feature enabled.")); - goto error_free_fs; - } - - fs->devhandle = handle; - fs->logsize = EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb) + 10; - handle->ops->set_blocksize(handle->cookie, fs->logsize); - - if (!ext2_bcache_init(fs)) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Error allocating buffer cache.")); - goto error_free_fs; - } - - fs->blocksize = 1 << fs->logsize; - - fs->numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(fs->sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), - EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - fs->gdblocks = ped_div_round_up (fs->numgroups - * sizeof(struct ext2_group_desc), - fs->blocksize); - fs->inodeblocks = ped_div_round_up (EXT2_SUPER_INODES_PER_GROUP(fs->sb) - * sizeof(struct ext2_inode), - fs->blocksize); - fs->r_frac = ped_div_round_up (100 * (loff_t)EXT2_SUPER_R_BLOCKS_COUNT(fs->sb), - EXT2_SUPER_BLOCKS_COUNT(fs->sb)); - fs->adminblocks = 3 + fs->gdblocks + fs->inodeblocks; - - fs->sparse = 0; - if (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb) - & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER) - fs->sparse = 1; - - fs->has_journal = 0 < (EXT2_SUPER_FEATURE_COMPAT(fs->sb) - & EXT3_FEATURE_COMPAT_HAS_JOURNAL); - fs->has_internal_journal - = fs->has_journal - && uuid_is_null(EXT2_SUPER_JOURNAL_UUID(fs->sb)) - && EXT2_SUPER_JOURNAL_INUM(fs->sb); - - fs->gd = ped_malloc (fs->numgroups * sizeof (struct ext2_group_desc) - + fs->blocksize); - if (!fs->gd) - goto error_deinit_bcache; - - ext2_read_blocks(fs, fs->gd, EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 1, - fs->gdblocks); - - fs->metadirty = 0; - return fs; - - ped_free(fs->gd); -error_deinit_bcache: - ext2_bcache_deinit(fs); -error_free_fs: - ped_free(fs); -error: - return NULL; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.h b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.h deleted file mode 100644 index 2e9db64ae5..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - ext2.h -- ext2 header - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _EXT2_H -#define _EXT2_H - -#include -#include -#include -#include "tune.h" - -#if HAVE_INTTYPES_H -# include -#endif - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - - -/* Ehrm.... sorry, pedanticists! :-) */ -#ifndef offsetof -# define offsetof(type, field) ((size_t)(&(((type *)0)->field))) -#endif - -#ifdef __BEOS__ - typedef off_t loff_t; -#endif - -#if defined(__sun) -typedef off_t loff_t; -typedef uint32_t blk_t; -#else -typedef u_int32_t blk_t; -#endif - -#ifdef HAVE_LINUX_EXT2_FS_H -#define _LINUX_TYPES_H -#define i_version i_generation -#include -#else -#include "ext2_fs.h" -#endif - -extern unsigned char _bitmap[8]; - -struct ext2_buffer_cache -{ - struct ext2_buffer_head *cache; - struct ext2_buffer_head *heads; - struct ext2_buffer_head **hash; - struct ext2_fs *fs; - - int size; - int numalloc; - unsigned char *buffermem; -}; - -struct ext2_buffer_head -{ - struct ext2_buffer_head *next; - struct ext2_buffer_head *prev; - unsigned char *data; - blk_t block; - - int usecount; - int dirty; - - struct ext2_buffer_cache *bc; - int alloc; -}; - -struct ext2_dev_ops -{ - int (*close)(void *cookie); - blk_t (*get_size)(void *cookie); - int (*read)(void *cookie, void *ptr, blk_t block, blk_t num); - int (*set_blocksize)(void *cookie, int logsize); - int (*sync)(void *cookie); - int (*write)(void *cookie, void *ptr, blk_t block, blk_t num); -}; - -struct ext2_dev_handle -{ - struct ext2_dev_ops *ops; - void *cookie; -}; - -struct ext2_fs -{ - struct ext2_dev_handle *devhandle; - - struct ext2_super_block sb; - struct ext2_group_desc *gd; - struct ext2_buffer_cache *bc; - int metadirty; /* 0:all sb&gd copies clean - 1:all sb&gd copies dirty - 2:only first sb&gd copy clean */ - - int dynamic_version; - int sparse; /* sparse superblocks */ - int has_journal; /* journal */ - int has_internal_journal; - - int blocksize; - int logsize; - blk_t adminblocks; - blk_t gdblocks; - blk_t itoffset; - blk_t inodeblocks; - int numgroups; - int r_frac; /* reserved % of blocks */ - - unsigned char *relocator_pool; - unsigned char *relocator_pool_end; - - int opt_debug; - int opt_safe; - int opt_verbose; - - void *journal; -}; - - -#define EXT2_ACTION_ADD 1 -#define EXT2_ACTION_DELETE 2 -#define EXT2_ACTION_FIND 3 - -#define EXT2_META_CLEAN 0 -#define EXT2_META_PRIMARY_SB 1 -#define EXT2_META_BACKUP_SB 2 -#define EXT2_META_PRIMARY_GD 4 -#define EXT2_META_BACKUP_GD 8 - -#define EXT2_META_PRIMARY (EXT2_META_PRIMARY_SB | EXT2_META_PRIMARY_GD) -#define EXT2_META_BACKUP (EXT2_META_BACKUP_SB | EXT2_META_BACKUP_GD) -#define EXT2_META_SB (EXT2_META_PRIMARY_SB | EXT2_META_BACKUP_SB) -#define EXT2_META_GD (EXT2_META_PRIMARY_GD | EXT2_META_BACKUP_GD) - -/* generic stuff */ -int ext2_copy_block (struct ext2_fs *fs, blk_t from, blk_t to); -void ext2_close (struct ext2_fs *fs); -int ext2_commit_metadata (struct ext2_fs *fs, int copies); -off_t ext2_get_inode_offset (struct ext2_fs *fs, ino_t inode, blk_t *block); -blk_t ext2_find_free_block (struct ext2_fs *fs); -ino_t ext2_find_free_inode (struct ext2_fs *fs); -int ext2_get_inode_state (struct ext2_fs *fs, ino_t inode); -int ext2_is_group_sparse (struct ext2_fs *fs, int group); -int ext2_move_blocks (struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest); -struct ext2_fs *ext2_open (struct ext2_dev_handle *handle, int state); -int ext2_read_blocks (struct ext2_fs *fs, void *ptr, blk_t block, blk_t numblocks); -int ext2_read_inode (struct ext2_fs *fs, ino_t inode, struct ext2_inode *inodep); -int ext2_set_inode_state (struct ext2_fs *fs, ino_t inode, int state, int updatemetadata); -int ext2_do_inode (struct ext2_fs *fs, struct ext2_inode *inode, blk_t block, int action); -int ext2_sync (struct ext2_fs *fs); -int ext2_write_blocks (struct ext2_fs *fs, void *ptr, blk_t block, blk_t numblocks); -int ext2_write_inode (struct ext2_fs *fs, ino_t inode, const struct ext2_inode *inodep); -int ext2_zero_blocks (struct ext2_fs *fs, blk_t block, blk_t num); -int ext2_zero_inode (struct ext2_fs *fs, ino_t inode); - -/* block related */ -void ext2_bgbitmap_cache_deinit (struct ext2_fs *fs); -int ext2_bgbitmap_cache_flush (struct ext2_fs *fs); -int ext2_bgbitmap_cache_init (struct ext2_fs *fs); -int ext2_get_block_state (struct ext2_fs *, blk_t block); -int ext2_set_block_state (struct ext2_fs *, blk_t block, int state, int updatemetadata); - -/* block relocator */ -int ext2_block_relocate (struct ext2_fs *fs, blk_t newsize); - -/* buffer */ -void ext2_bcache_deinit (struct ext2_fs *fs); -void ext2_bcache_dump (struct ext2_fs *fs); -int ext2_bcache_flush (struct ext2_fs *fs, blk_t block); -int ext2_bcache_flush_range (struct ext2_fs *fs, blk_t first, blk_t last); -int ext2_bcache_init (struct ext2_fs *fs); -int ext2_bcache_sync (struct ext2_fs *fs); -struct ext2_buffer_head *ext2_bcreate (struct ext2_fs *fs, blk_t block); -struct ext2_buffer_head *ext2_bread (struct ext2_fs *fs, blk_t block); -int ext2_brelse (struct ext2_buffer_head *bh, int forget); - -/* inode relocator */ -int ext2_inode_relocate (struct ext2_fs *fs, int newgroups); - -/* journalling */ -void ext2_journal_deinit (struct ext2_fs *fs); -int ext2_journal_init (struct ext2_fs *fs); - -/* metadata mover */ -int ext2_metadata_push (struct ext2_fs *fs, blk_t newsize); - -/* fs creation */ -struct ext2_fs *ext2_mkfs (struct ext2_dev_handle *handle, blk_t numblocks, int log_block_size, blk_t blocks_per_group, int inodes_per_group, int sparse_sb, int reserved_block_percentage, PedTimer* timer); - -/* resize */ -int ext2_resize_fs (struct ext2_fs *fs, blk_t newsize, PedTimer* timer); - -/* unix I/O */ -struct ext2_dev_handle *ext2_make_dev_handle_from_file(char *dev); - - - - -static __inline__ int ext2_is_data_block(struct ext2_fs *fs, blk_t block) -{ - blk_t blk; - int group; - - PED_ASSERT (block >= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), return 0); - PED_ASSERT (block < EXT2_SUPER_BLOCKS_COUNT(fs->sb), return 0); - - blk = block - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - - group = blk / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - blk %= EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - if (ext2_is_group_sparse(fs, group) && blk <= fs->gdblocks) - return 0; - - if (block == EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]) || - block == EXT2_GROUP_INODE_BITMAP(fs->gd[group])) - return 0; - - if (block >= EXT2_GROUP_INODE_TABLE(fs->gd[group]) && - block < EXT2_GROUP_INODE_TABLE(fs->gd[group]) + fs->inodeblocks) - return 0; - - return 1; -} - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_block_relocator.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_block_relocator.c deleted file mode 100644 index b75a4c5b2d..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_block_relocator.c +++ /dev/null @@ -1,927 +0,0 @@ -/* - ext2_block_relocator.c -- ext2 block relocator - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include "ext2.h" - - -/* This struct describes a single block that will be relocated. The - * block's original location is "num", and its new location is "dest". - * The block is presumebly referred to by some other block in the file - * system, which is recorded as "refblock". (Only one reference to - * the block is allowed by the block relocator.) "refoffset" describes - * the location within the refblock in which the block is referenced. - * "isindirect" is 0 for direct, 1 for single-indirect, 2 for - * double-indirect, etc. - * - * The algorithms in the file fill the entries of this struct in this order: - * num, refblock/refoffset/isindirectblock, dest. - */ -struct ext2_block_entry -{ - blk_t num; - blk_t dest; - blk_t refblock; - unsigned refoffset:16; - unsigned isindirectblock:16; -}; - -/* This struct contains all data structures relevant to the block relocator. - * - newallocoffset is the distance between the start of a block group, - * and the first data block in the group. This can change when a - * filesystem is resized, because the size of the group descriptors is - * proportional to the size of the filesystem. - * - * - allocentries is the size of the "block" array. It is a tuneable - * parameter that determines how many blocks can be moved in each - * pass. - * - * - usedentries says how many entries of the "block" array have been - * used. That is, how many blocks have been scheduled so far to - * be moved. - * - * - resolvedentries is the number of blocks whose referencing block - * has been found and recorded in block[.]->refblock, etc. - * - * - block is an array that records which blocks need to be moved, and - * where they will be moved to, etc. At some point in the algorithm, this - * array gets sorted (grep for qsort!) by indirectness. - * - * - start: each entry in this array corresponds to a level of - * indirectness (0-3). Each level has two items: dst and num. "num" - * is the number of blocks inside "block" of that level of indirectness. - * After doscan() is finished, and the level of indirectness of each - * block is known, "block" is sorted (see above). The "dst" pointer - * is a pointer inside "block" that indicates the start of the portion - * of the array containg blocks of that level of indirectness. - */ -struct ext2_block_relocator_state -{ - blk_t newallocoffset; - blk_t allocentries; - blk_t usedentries; - blk_t resolvedentries; - struct ext2_block_entry *block; - - struct { - struct ext2_block_entry *dst; - int num; - } start[4]; -}; - - - -static int compare_block_entries(const void *x0, const void *x1) -{ - const struct ext2_block_entry *b0; - const struct ext2_block_entry *b1; - - b0 = (const struct ext2_block_entry *)x0; - b1 = (const struct ext2_block_entry *)x1; - - if (b0->num < b1->num) - return -1; - - if (b0->num > b1->num) - return 1; - - return 0; -} - -static int compare_block_entries_ind(const void *x0, const void *x1) -{ - const struct ext2_block_entry *b0; - const struct ext2_block_entry *b1; - - b0 = (const struct ext2_block_entry *)x0; - b1 = (const struct ext2_block_entry *)x1; - - if (b0->isindirectblock > b1->isindirectblock) - return -1; - - if (b0->isindirectblock < b1->isindirectblock) - return 1; - - return 0; -} - -static int compare_block_entries_ref(const void *x0, const void *x1) -{ - const struct ext2_block_entry *b0; - const struct ext2_block_entry *b1; - - b0 = (const struct ext2_block_entry *)x0; - b1 = (const struct ext2_block_entry *)x1; - - if (b0->refblock < b1->refblock) - return -1; - - if (b0->refblock > b1->refblock) - return 1; - - return 0; -} - -struct ext2_block_entry *findit(struct ext2_block_relocator_state *state, blk_t block) -{ - int min; - int max; - struct ext2_block_entry *retv; - int t; - blk_t tval; - - max = state->usedentries - 1; - min = 0; - retv = NULL; - - repeat: - if (min > max) - goto out; - - t = (min + max) >> 1; - tval = state->block[t].num; - - if (tval > block) - max = t - 1; - - if (tval < block) - min = t + 1; - - if (tval != block) - goto repeat; - - retv = &state->block[t]; - - out: - return retv; -} - -/* This function adds records a reference to a block ("blk"), if that - * block is scheduled to be moved. - */ -static int doblock(struct ext2_fs *fs, - struct ext2_block_relocator_state *state, - blk_t blk, - blk_t refblock, - off_t refoffset, - int indirect) -{ - struct ext2_block_entry *ent; - - if ((ent = findit(state, blk)) == NULL) - return 1; - - if (ent->refblock) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Cross-linked blocks found! Better go run e2fsck " - "first!")); - return 0; - } - - ent->refblock = refblock; - ent->refoffset = refoffset; - ent->isindirectblock = indirect; - - state->resolvedentries++; - state->start[indirect].num++; - - return 1; -} - -static int doindblock(struct ext2_fs *fs, - struct ext2_block_relocator_state *state, - blk_t blk, - blk_t refblock, - off_t refoffset) -{ - struct ext2_buffer_head *bh; - int i; - uint32_t *uptr; - - if (!doblock(fs, state, blk, refblock, refoffset, 1)) - return 0; - - bh = ext2_bread(fs, blk); - if (!bh) - return 0; - uptr = (uint32_t *)bh->data; - - for (i=0;i<(fs->blocksize >> 2);i++) - if (uptr[i]) - if (!doblock(fs, state, PED_LE32_TO_CPU(uptr[i]), blk, - i<<2, 0)) - return 0; - - if (!ext2_brelse(bh, 0)) - return 0; - - return 1; -} - -static int dodindblock(struct ext2_fs *fs, - struct ext2_block_relocator_state *state, - blk_t blk, - blk_t refblock, - off_t refoffset) -{ - struct ext2_buffer_head *bh; - int i; - uint32_t *uptr; - - if (!doblock(fs, state, blk, refblock, refoffset, 2)) - return 0; - - bh = ext2_bread(fs, blk); - if (!bh) - return 0; - uptr = (uint32_t *)bh->data; - - for (i=0;i<(fs->blocksize >> 2);i++) - if (uptr[i]) - if (!doindblock(fs, state, PED_LE32_TO_CPU(uptr[i]), - blk, i<<2)) - return 0; - - if (!ext2_brelse(bh, 0)) - return 0; - - return 1; -} - -static int dotindblock(struct ext2_fs *fs, - struct ext2_block_relocator_state *state, - blk_t blk, - blk_t refblock, - off_t refoffset) -{ - struct ext2_buffer_head *bh; - int i; - uint32_t *uptr; - - if (!doblock(fs, state, blk, refblock, refoffset, 3)) - return 0; - - bh = ext2_bread(fs, blk); - if (!bh) - return 0; - uptr = (uint32_t *)bh->data; - - for (i=0;i<(fs->blocksize >> 2);i++) - if (uptr[i]) - if (!dodindblock(fs, state, PED_LE32_TO_CPU(uptr[i]), - blk, i<<2)) - return 0; - - if (!ext2_brelse(bh, 0)) - return 0; - - return 1; -} - - -/* This function records any block references from an inode to blocks that are - * scheduled to be moved. - */ -static int doinode(struct ext2_fs *fs, struct ext2_block_relocator_state *state, int inode) -{ - struct ext2_inode buf; - - if (!ext2_read_inode(fs, inode, &buf)) - return 0; - - if (EXT2_INODE_BLOCKS(buf)) - { - blk_t blk; - int i; - off_t inodeoffset; - blk_t inodeblock; - - inodeoffset = ext2_get_inode_offset(fs, inode, &inodeblock); - - /* do Hurd block, if there is one... */ - if (EXT2_SUPER_CREATOR_OS(fs->sb) == EXT2_OS_HURD - && EXT2_INODE_TRANSLATOR(buf)) { - if (!doblock(fs, - state, - EXT2_INODE_TRANSLATOR(buf), - inodeblock, - inodeoffset + offsetof(struct ext2_inode, - osd1.hurd1.h_i_translator), - 0)) - return 0; - } - - for (i=0;istart[0].num = 0; - state->start[1].num = 0; - state->start[2].num = 0; - state->start[3].num = 0; - - for (i=0;inumgroups;i++) - { - struct ext2_buffer_head *bh; - unsigned int j; - int offset; - - if (fs->opt_verbose) - { - fprintf(stderr, " scanning group %i.... ", i); - fflush(stderr); - } - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[i])); - if (!bh) - return 0; - offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; - - for (j=0;jsb);j++) - if (bh->data[j>>3] & _bitmap[j&7]) - { - if (!doinode(fs, state, offset + j)) - { - ext2_brelse(bh, 0); - return 0; - } - - if (state->resolvedentries == state->usedentries) - break; - } - - ext2_brelse(bh, 0); - - if (fs->opt_verbose) - { - fprintf(stderr, "%i/%i blocks resolved\r", - state->resolvedentries, - state->usedentries); - fflush(stderr); - } - - if (state->resolvedentries == state->usedentries) - break; - } - - if (fs->opt_verbose) - fputc('\n', stderr); - - state->start[3].dst = state->block; - state->start[2].dst = state->start[3].dst + state->start[3].num; - state->start[1].dst = state->start[2].dst + state->start[2].num; - state->start[0].dst = state->start[1].dst + state->start[1].num; - - return 1; -} - - - - - -static int ext2_block_relocator_copy(struct ext2_fs *fs, struct ext2_block_relocator_state *state) -{ - unsigned char *buf; - - ped_exception_fetch_all(); - buf = (unsigned char *) ped_malloc(MAXCONT << fs->logsize); - if (buf) - { - int num; - int numleft; - struct ext2_block_entry *ptr; - - ped_exception_leave_all(); - - numleft = state->usedentries; - ptr = state->block; - while (numleft) - { - num = PED_MIN(numleft, MAXCONT); - while (num != 1) - { - if (ptr[0].num + num-1 == ptr[num-1].num && - ptr[0].dest + num-1 == ptr[num-1].dest) - break; - - num >>= 1; - } - - if (!ext2_bcache_flush_range(fs, ptr[0].num, num)) - goto error_free_buf; - if (!ext2_bcache_flush_range(fs, ptr[0].dest, num)) - goto error_free_buf; - - if (!ext2_read_blocks(fs, buf, ptr[0].num, num)) - goto error_free_buf; - if (!ext2_write_blocks(fs, buf, ptr[0].dest, num)) - goto error_free_buf; - - ptr += num; - numleft -= num; - - if (fs->opt_verbose) - { - fprintf(stderr, "copied %i/%i blocks\r", - state->usedentries - numleft, - state->usedentries); - fflush(stderr); - } - } - - ped_free(buf); - - if (fs->opt_safe) - ext2_sync(fs); - - if (fs->opt_verbose) - fputc('\n', stderr); - } - else - { - blk_t i; - - ped_exception_catch(); - ped_exception_leave_all(); - - for (i=0;iusedentries;i++) - { - struct ext2_block_entry *block; - - block = &state->block[i]; - if (!ext2_copy_block(fs, block->num, block->dest)) - goto error; - } - } - - return 1; - -error_free_buf: - ped_free(buf); -error: - return 0; -} - -static int ext2_block_relocator_ref(struct ext2_fs *fs, struct ext2_block_relocator_state *state, struct ext2_block_entry *block) -{ - struct ext2_buffer_head *bh; - static int numerrors = 0; - - if (!(block->refblock || block->refoffset)) - { - ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, - _("Block %i has no reference? Weird."), - block->num); - return 0; - } - - bh = ext2_bread(fs, block->refblock); - if (!bh) - return 0; - - if (fs->opt_debug) - { - if (PED_LE32_TO_CPU(*((uint32_t *)(bh->data + block->refoffset))) - != block->num) { - fprintf(stderr, - "block %i ref error! (->%i {%i, %i})\n", - block->num, - block->dest, - block->refblock, - block->refoffset); - ext2_brelse(bh, 0); - - if (numerrors++ < 4) - return 1; - - fputs("all is not well!\n", stderr); - return 0; - } - } - - *((uint32_t *)(bh->data + block->refoffset)) - = PED_LE32_TO_CPU(block->dest); - bh->dirty = 1; - ext2_brelse(bh, 0); - - ext2_set_block_state(fs, block->dest, 1, 1); - ext2_set_block_state(fs, block->num, 0, 1); - - if (block->isindirectblock) - { - struct ext2_block_entry *dst; - int i; - int num; - - dst = state->start[block->isindirectblock-1].dst; - num = state->start[block->isindirectblock-1].num; - - for (i=0;inum) - dst[i].refblock = block->dest; - } - - return 1; -} - -/* This function allocates new locations for blocks that are scheduled to move - * (inside state->blocks). - * - * FIXME: doesn't seem to handle sparse block groups. That is, there might be - * some free space that could be exploited in resizing that currently isn't... - * - * FIXME: should throw an exception if it fails to allocate blocks. - */ -static int ext2_block_relocator_grab_blocks(struct ext2_fs *fs, struct ext2_block_relocator_state *state) -{ - int i; - blk_t ptr; - - ptr = 0; - - for (i=0;inumgroups;i++) - if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i])) - { - struct ext2_buffer_head *bh; - unsigned int j; - int offset; - - bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])); - offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - - for (j=state->newallocoffset; - jsb); - j++) - if (!(bh->data[j>>3] & _bitmap[j&7])) - { - state->block[ptr++].dest = offset + j; - - if (ptr == state->usedentries) - { - ext2_brelse(bh, 0); - return 1; - } - } - - ext2_brelse(bh, 0); - } - - return 0; -} - -static int ext2_block_relocator_flush(struct ext2_fs *fs, struct ext2_block_relocator_state *state) -{ - int i; - - if (!state->usedentries) - return 1; - - if (fs->opt_verbose) - fputs("ext2_block_relocator_flush\n", stderr); - - if (fs->opt_debug) - { - again: - - for (i=0; (unsigned int) i < state->usedentries-1; i++) - if (state->block[i].num >= state->block[i+1].num) - { - fputs("ext2_block_relocator_flush: " - "blocks not in order!\n", stderr); - - qsort(state->block, - state->usedentries, - sizeof(struct ext2_block_entry), - compare_block_entries); - goto again; - } - } - - if (!doscan(fs, state)) - return 0; - - if (!ext2_block_relocator_grab_blocks(fs, state)) - return 0; - - if (!ext2_block_relocator_copy(fs, state)) - return 0; - - qsort(state->block, - state->usedentries, - sizeof(struct ext2_block_entry), - compare_block_entries_ind); - - for (i=3;i>=0;i--) - { - struct ext2_block_entry *dst; - int j; - int num; - - dst = state->start[i].dst; - num = state->start[i].num; - - if (!num) - continue; - - if (fs->opt_verbose) - { - /* FIXXXME gross hack */ - fprintf(stderr, "relocating %s blocks", - ((char *[4]){"direct", - "singly indirect", - "doubly indirect", - "triply indirect"})[i]); - fflush(stderr); - } - - qsort(dst, - num, - sizeof(struct ext2_block_entry), - compare_block_entries_ref); - - for (j=0;jopt_safe) { - if (!ext2_sync(fs)) - return 0; - } - - if (fs->opt_verbose) - fputc('\n', stderr); - } - - state->usedentries = 0; - state->resolvedentries = 0; - - return 1; -} - -static int ext2_block_relocator_mark(struct ext2_fs *fs, struct ext2_block_relocator_state *state, blk_t block) -{ - int i; - - if (fs->opt_debug) - { - if (!ext2_get_block_state(fs, block) || - !ext2_is_data_block(fs, block)) - { - ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("Block %i shouldn't have been marked " - "(%d, %d)!"), block, - ext2_get_block_state(fs, block), - ext2_is_data_block(fs, block)); - } - } - - if (state->usedentries == state->allocentries - 1) - if (!ext2_block_relocator_flush(fs, state)) - return 0; - - i = state->usedentries; - state->block[i].num = block; - state->block[i].dest = 0; - state->block[i].refblock = 0; - state->block[i].refoffset = 0; - - state->usedentries++; - return 1; -} - -static int ext2_block_relocate_grow(struct ext2_fs *fs, struct ext2_block_relocator_state *state, blk_t newsize) -{ - blk_t newgdblocks; - blk_t newitoffset; - int i; - - newgdblocks = ped_div_round_up (newsize - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), - EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - newgdblocks = ped_div_round_up (newgdblocks - * sizeof(struct ext2_group_desc), - fs->blocksize); - if (newgdblocks == fs->gdblocks) - return 1; - - newitoffset = newgdblocks + 3; - state->newallocoffset = newitoffset + fs->inodeblocks; - - for (i=0;inumgroups;i++) - { - struct ext2_buffer_head *bh; - blk_t diff; - blk_t j; - blk_t start; - int sparse; - - bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])); - start = (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - sparse = ext2_is_group_sparse(fs, i); - - if (EXT2_GROUP_INODE_TABLE(fs->gd[i]) < start + newitoffset - || (sparse && ((EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) - < start + newitoffset - 2) - || (EXT2_GROUP_INODE_BITMAP(fs->gd[i]) - < start + newitoffset - 1)))) - { - diff = newitoffset - (EXT2_GROUP_INODE_TABLE(fs->gd[i]) - - start); - - for (j=0;jgd[i]) - + fs->inodeblocks + j; - block = k % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - if (bh->data[block>>3] & _bitmap[block&7]) { - k += EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - if (!ext2_block_relocator_mark(fs, - state, k)) - { - ext2_brelse(bh, 0); - return 0; - } - } - } - } - - ext2_brelse(bh, 0); - } - - if (!ext2_block_relocator_flush(fs, state)) - return 0; - - return 1; -} - -static int ext2_block_relocate_shrink(struct ext2_fs *fs, struct ext2_block_relocator_state *state, blk_t newsize) -{ - int diff; - int i; - - diff = ped_div_round_up (newsize - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), - EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - diff = ped_div_round_up (diff * sizeof(struct ext2_group_desc), - fs->blocksize); - diff = fs->gdblocks - diff; - - state->newallocoffset = fs->itoffset + fs->inodeblocks; - - for (i=0;inumgroups;i++) - { - struct ext2_buffer_head *bh; - blk_t groupsize; - blk_t j; - blk_t offset; - int sparse; - blk_t start; - int type; - - offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - sparse = ext2_is_group_sparse(fs, i); - - if (newsize >= offset + EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - continue; /* group will survive */ - - bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])); - - if (newsize <= offset) - type = 2; /* group is fully chopped off */ - else - type = 1; /* group is partly chopped off */ - - if (!sparse && type == 2) - { - for (j=EXT2_GROUP_INODE_BITMAP(fs->gd[i])+1; - jgd[i]); - j++) - { - blk_t k; - - k = j - offset; - if (bh->data[k>>3] & _bitmap[k&7]) - if (!ext2_block_relocator_mark(fs, state, j)) - { - ext2_brelse(bh, 0); - return 0; - } - } - } - - start = newsize; - if (type == 2) - start = EXT2_GROUP_INODE_TABLE(fs->gd[i]) - + fs->inodeblocks; - - start -= offset; - - groupsize = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - if (offset + groupsize > EXT2_SUPER_BLOCKS_COUNT(fs->sb)) - groupsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - offset; - - for (j=start;jdata[j>>3] & _bitmap[j&7]) - if (!ext2_block_relocator_mark(fs, state, - offset + j)) - { - ext2_brelse(bh, 0); - return 0; - } - - ext2_brelse(bh, 0); - } - - return ext2_block_relocator_flush(fs, state); -} - -int ext2_block_relocate(struct ext2_fs *fs, blk_t newsize) -{ - struct ext2_block_relocator_state state; - - if (fs->opt_verbose) - fputs("relocating blocks....\n", stderr); - - state.newallocoffset = 0; - state.allocentries = (ext2_relocator_pool_size << 10) / - sizeof(struct ext2_block_entry); - state.usedentries = 0; - state.resolvedentries = 0; - state.block = (struct ext2_block_entry *)fs->relocator_pool; - - if (newsize < EXT2_SUPER_BLOCKS_COUNT(fs->sb)) - return ext2_block_relocate_shrink(fs, &state, newsize); - - return ext2_block_relocate_grow(fs, &state, newsize); -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_buffer.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_buffer.c deleted file mode 100644 index 3a5f29c991..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_buffer.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - ext2_buffer.c -- ext2 buffer cache - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include -#include "ext2.h" - -/* pseudo-header */ - -static __inline__ int ext2_block_hash(blk_t block) -{ - unsigned long x; - - x = block ^ (block >> 8) ^ (block >> 16) ^ (block >> 24); - return x & ((1 << ext2_hash_bits) - 1); -} - -static struct ext2_buffer_head *ext2_bh_alloc (struct ext2_buffer_cache *, blk_t); -static void ext2_bh_dealloc (struct ext2_buffer_head *); -static struct ext2_buffer_head *ext2_bh_find (struct ext2_buffer_cache *, blk_t); -static int ext2_bh_do_read (struct ext2_buffer_head *); -static int ext2_bh_do_write(struct ext2_buffer_head *); -static void ext2_bh_hash (struct ext2_buffer_head *); -static void ext2_bh_unhash (struct ext2_buffer_head *); - - - -static int try_to_flush(struct ext2_buffer_cache *bc) -{ - int i; - - for (i=0;isize;i++) - { - struct ext2_buffer_head *bh; - - bh = &bc->heads[i]; - - if (bh->alloc && !bh->usecount && !bh->dirty) - { - ext2_bh_dealloc(bh); - return 1; - } - } - - for (i=0;isize;i++) - { - struct ext2_buffer_head *bh; - - bh = &bc->heads[i]; - - if (bh->alloc && !bh->usecount && bh->dirty) - { - ext2_bh_do_write(bh); - ext2_bh_dealloc(bh); - return 1; - } - } - - if (ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Couldn't flush buffer cache!")) - != PED_EXCEPTION_IGNORE) - return 0; - return 1; -} - - - - - -static struct ext2_buffer_head *ext2_bh_alloc(struct ext2_buffer_cache *bc, blk_t block) -{ - struct ext2_buffer_head *bh; - int i; - - bh = NULL; - - tryagain: - for (i=0;isize;i++) - { - bh = &bc->heads[i]; - - if (!bh->alloc) - break; - } - - if (i == bc->size) - { - try_to_flush(bc); - goto tryagain; - } - - bh = &bc->heads[i]; - - bh->next = NULL; - bh->prev = NULL; - bh->block = block; - bh->usecount = 0; - bh->dirty = 0; - bh->alloc = 1; - bc->numalloc++; - - ext2_bh_hash(bh); - - return bh; -} - -static void ext2_bh_dealloc(struct ext2_buffer_head *bh) -{ - if (bh->dirty) - ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_IGNORE, - "deallocing() a dirty buffer! %i\n", bh->block); - - ext2_bh_unhash(bh); - bh->alloc = 0; - bh->bc->numalloc--; -} - -static struct ext2_buffer_head *ext2_bh_find(struct ext2_buffer_cache *bc, blk_t block) -{ - struct ext2_buffer_head *a; - struct ext2_buffer_head *b; - int hash; - - hash = ext2_block_hash(block); - a = bc->hash[hash]; - - if (a != NULL) - { - b = a; - do - { - if (a->block == block) - return a; - - a = a->next; - } while (a != b); - } - - return NULL; -} - -static int ext2_bh_do_read(struct ext2_buffer_head *bh) -{ - return ext2_read_blocks(bh->bc->fs, bh->data, bh->block, 1); -} - -static int ext2_bh_do_write(struct ext2_buffer_head *bh) -{ - if (!bh->alloc) { - ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, - "Attempt to write unallocated buffer."); - return 0; - } - - ext2_write_blocks(bh->bc->fs, bh->data, bh->block, 1); - bh->dirty = 0; - return 1; -} - -static void ext2_bh_hash(struct ext2_buffer_head *bh) -{ - int hash; - - hash = ext2_block_hash(bh->block); - if (bh->bc->hash[hash] != NULL) - { - bh->next = bh->bc->hash[hash]; - bh->prev = bh->next->prev; - bh->next->prev = bh; - bh->prev->next = bh; - return; - } - - bh->bc->hash[hash] = bh; - bh->next = bh->prev = bh; -} - -static void ext2_bh_unhash(struct ext2_buffer_head *bh) -{ - int hash; - - hash = ext2_block_hash(bh->block); - - bh->prev->next = bh->next; - bh->next->prev = bh->prev; - - if (bh->bc->hash[hash] == bh) - { - if (bh->next != bh) - bh->bc->hash[hash] = bh->next; - else - bh->bc->hash[hash] = NULL; - } - - bh->next = NULL; - bh->prev = NULL; -} - - - - - - - -static int breadimmhits = 0; -static int breadindhits = 0; -static int breadmisses = 0; - -void ext2_bcache_deinit(struct ext2_fs *fs) -{ - ext2_bcache_sync(fs); - ped_free(fs->bc->buffermem); - ped_free(fs->bc->hash); - ped_free(fs->bc->heads); - ped_free(fs->bc); - - if (fs->opt_verbose) - fprintf(stderr, - "direct hits: %i, indirect hits: %i, misses: %i\n", - breadimmhits, - breadindhits, - breadmisses); -} - -void ext2_bcache_dump(struct ext2_fs *fs) -{ - int i; - - fputs ("buffer cache dump:\n", stderr); - - for (i=0;i<(1<bc->hash[i] != NULL) - { - struct ext2_buffer_head *a; - struct ext2_buffer_head *b; - - fprintf(stderr, "%i: ", i); - - a = b = fs->bc->hash[i]; - do - { - fprintf(stderr, "%i ", a->block); - a = a->next; - } while (a != b); - - fputc ('\n', stderr); - } -} - -int ext2_bcache_flush(struct ext2_fs *fs, blk_t block) -{ - struct ext2_buffer_head *bh; - - if ((bh = ext2_bh_find(fs->bc, block)) == NULL) - return 1; - - if (bh->usecount) { - ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, - "Attempt to flush a buffer that's in use! [%i,%i]", - bh->block, bh->usecount); - return 0; - } - - if (bh->dirty) { - if (!ext2_bh_do_write(bh)) - return 0; - } - - ext2_bh_dealloc(bh); - return 1; -} - -int ext2_bcache_flush_range(struct ext2_fs *fs, blk_t block, blk_t num) -{ - blk_t end = block + num; - - for (; block < end; block++) { - if (!ext2_bcache_flush(fs, block)) - return 0; - } - return 1; -} - -int ext2_bcache_init(struct ext2_fs *fs) -{ - struct ext2_buffer_cache *bc; - int i; - int size; - - size = ext2_buffer_cache_pool_size >> (fs->logsize - 10); - - if ((bc = (struct ext2_buffer_cache *) ped_malloc(sizeof(struct ext2_buffer_cache))) == NULL) - return 0; - - if ((bc->heads = (struct ext2_buffer_head *) ped_malloc(size * sizeof(struct ext2_buffer_head))) == NULL) - return 0; - - if ((bc->hash = (struct ext2_buffer_head **) ped_malloc(sizeof(struct ext2_buffer_head *) << ext2_hash_bits)) == NULL) - { - ped_free(bc->heads); - ped_free(bc); - return 0; - } - - if ((bc->buffermem = (unsigned char *) ped_malloc(ext2_buffer_cache_pool_size << 10)) == NULL) - { - ped_free(bc->hash); - ped_free(bc->heads); - ped_free(bc); - return 0; - } - - bc->cache = &bc->heads[0]; - bc->fs = fs; - bc->size = size; - bc->numalloc = 0; - - for (i=0;iheads[i].data = bc->buffermem + (i << fs->logsize); - bc->heads[i].bc = bc; - bc->heads[i].alloc = 0; - } - - for (i=0;i<(1<hash[i] = NULL; - - fs->bc = bc; - - return 1; -} - -int ext2_bcache_sync(struct ext2_fs *fs) -{ - int i; - - for (i=0;ibc->size;i++) - { - struct ext2_buffer_head *bh; - - bh = &fs->bc->heads[i]; - - if (bh->alloc && bh->dirty) { - if (!ext2_bh_do_write(bh)) - return 0; - } - } - return 1; -} - - - - - - - - -struct ext2_buffer_head *ext2_bcreate(struct ext2_fs *fs, blk_t block) -{ - struct ext2_buffer_head *bh; - - if ((bh = ext2_bh_find(fs->bc, block)) != NULL) - { - bh->usecount++; - } - else - { - bh = ext2_bh_alloc(fs->bc, block); - bh->usecount = 1; - } - - memset(bh->data, 0, fs->blocksize); - bh->dirty = 1; - - return bh; -} - -struct ext2_buffer_head *ext2_bread(struct ext2_fs *fs, blk_t block) -{ - struct ext2_buffer_head *bh; - - if ((bh = fs->bc->cache)->block == block) - { - breadimmhits++; - bh->usecount++; - return bh; - } - - if ((bh = ext2_bh_find(fs->bc, block)) != NULL) - { - fs->bc->cache = bh; - breadindhits++; - bh->usecount++; - return bh; - } - - breadmisses++; - - bh = ext2_bh_alloc(fs->bc, block); - fs->bc->cache = bh; - bh->usecount = 1; - if (!ext2_bh_do_read(bh)) { - ext2_bh_dealloc(bh); - return NULL; - } - - return bh; -} - -int ext2_brelse(struct ext2_buffer_head *bh, int forget) -{ - if (bh->usecount-- == 1 && forget) - { - if (bh->dirty) { - if (!ext2_bh_do_write(bh)) - return 0; - } - - ext2_bh_dealloc(bh); - } - return 1; -} - -#endif /* !DISCOVER_ONLY */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_fs.h b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_fs.h deleted file mode 100644 index 713cc21af3..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_fs.h +++ /dev/null @@ -1,323 +0,0 @@ -/* - * 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 - */ - -/* - * EXT2_*_*() convienience macros added by Andrew Clausen - * Copyright (C) 2000 Free Software Foundation, Inc. - */ - -#ifndef _EXT2_FS_H -#define _EXT2_FS_H - -#include -#include - -/* - * The second extended file system constants/structures - */ - -#define EXT2_SUPER_MAGIC_CONST 0xEF53 -#define EXT2_MIN_BLOCK_SIZE 1024 -#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) -#define EXT2_VALID_FS 0x0001 -#define EXT2_ERROR_FS 0x0002 -#define EXT2_RESERVED_INODE_COUNT 11 - -/* - * Codes for operating systems - */ -#define EXT2_OS_LINUX 0 -#define EXT2_OS_HURD 1 -#define EXT2_OS_MASIX 2 -#define EXT2_OS_FREEBSD 3 -#define EXT2_OS_LITES 4 - -/* - * Feature set definitions - */ -#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004 -#define EXT2_FEATURE_COMPAT_HAS_DIR_INDEX 0x0020 - -#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001 -#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002 - -#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002 -#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004 - -/* - * Special inodes numbers - */ -#define EXT2_BAD_INO 1 /* Bad blocks inode */ -#define EXT2_ROOT_INO 2 /* Root inode */ -#define EXT2_ACL_IDX_INO 3 /* ACL inode */ -#define EXT2_ACL_DATA_INO 4 /* ACL inode */ -#define EXT2_BOOT_LOADER_INO 5 /* Boot loader inode */ -#define EXT2_UNDEL_DIR_INO 6 /* Undelete directory inode */ - -/* - * 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 - -/* - * 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 - -struct ext2_dir_entry_2 -{ - uint32_t inode; - uint16_t rec_len; - uint8_t name_len; - uint8_t file_type; - char name[255]; -}; - -struct ext2_group_desc -{ - uint32_t bg_block_bitmap; - uint32_t bg_inode_bitmap; - uint32_t bg_inode_table; - uint16_t bg_free_blocks_count; - uint16_t bg_free_inodes_count; - uint16_t bg_used_dirs_count; - uint16_t bg_pad; - uint32_t bg_reserved[3]; -}; - -struct ext2_inode -{ - uint16_t i_mode; /* File mode */ - uint16_t i_uid; /* Owner Uid */ - uint32_t i_size; /* Size in bytes */ - uint32_t i_atime; /* Access time */ - uint32_t i_ctime; /* Creation time */ - uint32_t i_mtime; /* Modification time */ - uint32_t i_dtime; /* Deletion Time */ - uint16_t i_gid; /* Group Id */ - uint16_t i_links_count; /* Links count */ - uint32_t i_blocks; /* Blocks count */ - uint32_t i_flags; /* File flags */ - union { - struct { - uint32_t l_i_reserved1; - } linux1; - struct { - uint32_t h_i_translator; - } hurd1; - struct { - uint32_t m_i_reserved1; - } masix1; - } osd1; /* OS dependent 1 */ - uint32_t i_block[EXT2_N_BLOCKS];/* Pointers to blocks */ - uint32_t i_generation; /* File version (for NFS) */ - uint32_t i_file_acl; /* File ACL */ - uint32_t i_dir_acl; /* Directory ACL */ - uint32_t i_faddr; /* Fragment address */ - union { - struct { - uint8_t l_i_frag; /* Fragment number */ - uint8_t l_i_fsize; /* Fragment size */ - uint16_t i_pad1; - uint32_t l_i_reserved2[2]; - } linux2; - struct { - uint8_t h_i_frag; /* Fragment number */ - uint8_t h_i_fsize; /* Fragment size */ - uint16_t h_i_mode_high; - uint16_t h_i_uid_high; - uint16_t h_i_gid_high; - uint32_t h_i_author; - } hurd2; - struct { - uint8_t m_i_frag; /* Fragment number */ - uint8_t m_i_fsize; /* Fragment size */ - uint16_t m_pad1; - uint32_t m_i_reserved2[2]; - } masix2; - } osd2; /* OS dependent 2 */ -}; - -#define i_size_high i_dir_acl - -struct ext2_super_block -{ - uint32_t s_inodes_count; /* Inodes count */ - uint32_t s_blocks_count; /* Blocks count */ - uint32_t s_r_blocks_count; /* Reserved blocks count */ - uint32_t s_free_blocks_count; /* Free blocks count */ - uint32_t s_free_inodes_count; /* Free inodes count */ - uint32_t s_first_data_block; /* First Data Block */ - uint32_t s_log_block_size; /* Block size */ - int32_t s_log_frag_size; /* Fragment size */ - uint32_t s_blocks_per_group; /* # Blocks per group */ - uint32_t s_frags_per_group; /* # Fragments per group */ - uint32_t s_inodes_per_group; /* # Inodes per group */ - uint32_t s_mtime; /* Mount time */ - uint32_t s_wtime; /* Write time */ - uint16_t s_mnt_count; /* Mount count */ - int16_t s_max_mnt_count; /* Maximal mount count */ - uint16_t s_magic; /* Magic signature */ - uint16_t s_state; /* File system state */ - uint16_t s_errors; /* Behaviour when detecting errors */ - uint16_t s_minor_rev_level; /* minor revision level */ - uint32_t s_lastcheck; /* time of last check */ - uint32_t s_checkinterval; /* max. time between checks */ - uint32_t s_creator_os; /* OS */ - uint32_t s_rev_level; /* Revision level */ - uint16_t s_def_resuid; /* Default uid for reserved blocks */ - uint16_t 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 file system. - * - * 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... - */ - uint32_t s_first_ino; /* First non-reserved inode */ - uint16_t s_inode_size; /* size of inode structure */ - uint16_t s_block_group_nr; /* block group # of this superblock */ - uint32_t s_feature_compat; /* compatible feature set */ - uint32_t s_feature_incompat; /* incompatible feature set */ - uint32_t s_feature_ro_compat; /* readonly-compatible feature set */ - uint8_t s_uuid[16]; /* 128-bit uuid for volume */ - char s_volume_name[16]; /* volume name */ - char s_last_mounted[64]; /* directory where last mounted */ - uint32_t s_algorithm_usage_bitmap; /* For compression */ - /* - * Performance hints. Directory preallocation should only - * happen if the EXT2_COMPAT_PREALLOC flag is on. - */ - uint8_t s_prealloc_blocks; /* Nr of blocks to try to preallocate*/ - uint8_t s_prealloc_dir_blocks; /* Nr to preallocate for dirs */ - uint16_t s_padding1; - /* - * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set. - */ - uint8_t s_journal_uuid[16]; /* uuid of journal superblock */ - uint32_t s_journal_inum; /* inode number of journal file */ - uint32_t s_journal_dev; /* device number of journal file */ - uint32_t s_last_orphan; /* start of list of inodes to delete */ - - uint32_t s_reserved[197]; /* Padding to the end of the block */ -}; - -#define EXT2_DIRENT_INODE(dir_ent) (PED_LE32_TO_CPU((dir_ent).inode)) -#define EXT2_DIRENT_REC_LEN(dir_ent) (PED_LE16_TO_CPU((dir_ent).rec_len)) -#define EXT2_DIRENT_NAME_LEN(dir_ent) ((dir_ent).name_len) -#define EXT2_DIRENT_FILE_TYPE(dir_ent) ((dir_ent).file_type) - -#define EXT2_GROUP_BLOCK_BITMAP(gd) (PED_LE32_TO_CPU((gd).bg_block_bitmap)) -#define EXT2_GROUP_INODE_BITMAP(gd) (PED_LE32_TO_CPU((gd).bg_inode_bitmap)) -#define EXT2_GROUP_INODE_TABLE(gd) (PED_LE32_TO_CPU((gd).bg_inode_table)) -#define EXT2_GROUP_FREE_BLOCKS_COUNT(gd) \ - (PED_LE16_TO_CPU((gd).bg_free_blocks_count)) -#define EXT2_GROUP_FREE_INODES_COUNT(gd) \ - (PED_LE16_TO_CPU((gd).bg_free_inodes_count)) -#define EXT2_GROUP_USED_DIRS_COUNT(gd) \ - (PED_LE16_TO_CPU((gd).bg_used_dirs_count)) - -#define EXT2_INODE_MODE(inode) (PED_LE16_TO_CPU((inode).i_mode)) -#define EXT2_INODE_UID(inode) (PED_LE16_TO_CPU((inode).i_uid)) -#define EXT2_INODE_SIZE(inode) \ - ((uint64_t) PED_LE32_TO_CPU((inode).i_size) \ - + ((uint64_t) PED_LE32_TO_CPU((inode).i_size_high) << 32)) -#define EXT2_INODE_ATIME(inode) (PED_LE32_TO_CPU((inode).i_atime)) -#define EXT2_INODE_CTIME(inode) (PED_LE32_TO_CPU((inode).i_ctime)) -#define EXT2_INODE_MTIME(inode) (PED_LE32_TO_CPU((inode).i_mtime)) -#define EXT2_INODE_DTIME(inode) (PED_LE32_TO_CPU((inode).i_dtime)) -#define EXT2_INODE_GID(inode) (PED_LE16_TO_CPU((inode).i_gid)) -#define EXT2_INODE_LINKS_COUNT(inode) (PED_LE16_TO_CPU((inode).i_links_count)) -#define EXT2_INODE_BLOCKS(inode) (PED_LE32_TO_CPU((inode).i_blocks)) -#define EXT2_INODE_FLAGS(inode) (PED_LE32_TO_CPU((inode).i_flags)) -#define EXT2_INODE_TRANSLATOR(inode) (PED_LE32_TO_CPU((inode).osd1.hurd1.h_i_translator)) -#define EXT2_INODE_BLOCK(inode, blk) (PED_LE32_TO_CPU((inode).i_block[blk])) - -#define EXT2_SUPER_INODES_COUNT(sb) (PED_LE32_TO_CPU((sb).s_inodes_count)) -#define EXT2_SUPER_BLOCKS_COUNT(sb) (PED_LE32_TO_CPU((sb).s_blocks_count)) -#define EXT2_SUPER_R_BLOCKS_COUNT(sb) (PED_LE32_TO_CPU((sb).s_r_blocks_count)) -#define EXT2_SUPER_FREE_BLOCKS_COUNT(sb) \ - (PED_LE32_TO_CPU((sb).s_free_blocks_count)) -#define EXT2_SUPER_FREE_INODES_COUNT(sb) \ - (PED_LE32_TO_CPU((sb).s_free_inodes_count)) -#define EXT2_SUPER_FIRST_DATA_BLOCK(sb) \ - (PED_LE32_TO_CPU((sb).s_first_data_block)) -#define EXT2_SUPER_LOG_BLOCK_SIZE(sb) (PED_LE32_TO_CPU((sb).s_log_block_size)) -#define EXT2_SUPER_LOG_FRAG_SIZE(sb) \ - ((int32_t) PED_LE32_TO_CPU((sb).s_log_frag_size)) -#define EXT2_SUPER_BLOCKS_PER_GROUP(sb) \ - (PED_LE32_TO_CPU((sb).s_blocks_per_group)) -#define EXT2_SUPER_FRAGS_PER_GROUP(sb) \ - (PED_LE32_TO_CPU((sb).s_frags_per_group)) -#define EXT2_SUPER_INODES_PER_GROUP(sb) \ - (PED_LE32_TO_CPU((sb).s_inodes_per_group)) -#define EXT2_SUPER_MTIME(sb) (PED_LE32_TO_CPU((sb).s_mtime)) -#define EXT2_SUPER_WTIME(sb) (PED_LE32_TO_CPU((sb).s_wtime)) -#define EXT2_SUPER_MNT_COUNT(sb) (PED_LE16_TO_CPU((sb).s_mnt_count)) -#define EXT2_SUPER_MAX_MNT_COUNT(sb) \ - ((int16_t) PED_LE16_TO_CPU((sb).s_max_mnt_count)) -#define EXT2_SUPER_MAGIC(sb) (PED_LE16_TO_CPU((sb).s_magic)) -#define EXT2_SUPER_STATE(sb) (PED_LE16_TO_CPU((sb).s_state)) -#define EXT2_SUPER_ERRORS(sb) (PED_LE16_TO_CPU((sb).s_errors)) -#define EXT2_SUPER_MINOR_REV_LEVEL(sb) \ - (PED_LE16_TO_CPU((sb).s_minor_rev_level)) -#define EXT2_SUPER_LASTCHECK(sb) (PED_LE32_TO_CPU((sb).s_lastcheck)) -#define EXT2_SUPER_CHECKINTERVAL(sb) (PED_LE32_TO_CPU((sb).s_checkinterval)) -#define EXT2_SUPER_CREATOR_OS(sb) (PED_LE32_TO_CPU((sb).s_creator_os)) -#define EXT2_SUPER_REV_LEVEL(sb) (PED_LE32_TO_CPU((sb).s_rev_level)) -#define EXT2_SUPER_DEF_RESUID(sb) (PED_LE16_TO_CPU((sb).s_def_resuid)) -#define EXT2_SUPER_DEF_RESGID(sb) (PED_LE16_TO_CPU((sb).s_def_resgid)) - -#define EXT2_SUPER_FIRST_INO(sb) (PED_LE32_TO_CPU((sb).s_first_ino)) -#define EXT2_SUPER_INODE_SIZE(sb) (PED_LE16_TO_CPU((sb).s_inode_size)) -#define EXT2_SUPER_BLOCK_GROUP_NR(sb) (PED_LE16_TO_CPU((sb).s_block_group_nr)) -#define EXT2_SUPER_FEATURE_COMPAT(sb) (PED_LE32_TO_CPU((sb).s_feature_compat)) -#define EXT2_SUPER_FEATURE_INCOMPAT(sb) \ - (PED_LE32_TO_CPU((sb).s_feature_incompat)) -#define EXT2_SUPER_FEATURE_RO_COMPAT(sb) \ - (PED_LE32_TO_CPU((sb).s_feature_ro_compat)) -#define EXT2_SUPER_UUID(sb) ((sb).s_uuid) -#define EXT2_SUPER_VOLUME_NAME(sb) ((sb).s_volume_name) -#define EXT2_SUPER_LAST_MOUNTED(sb) ((sb).s_last_mounted) -#define EXT2_SUPER_ALGORITHM_USAGE_BITMAP(sb) \ - (PED_LE32_TO_CPU((sb).s_algorithm_usage_bitmap)) - -#define EXT2_SUPER_JOURNAL_UUID(sb) ((sb).s_journal_uuid) -#define EXT2_SUPER_JOURNAL_INUM(sb) (PED_LE32_TO_CPU((sb).s_journal_inum)) -#define EXT2_SUPER_JOURNAL_DEV(sb) (PED_LE32_TO_CPU((sb).s_journal_dev)) -#define EXT2_SUPER_LAST_ORPHAN(sb) (PED_LE32_TO_CPU((sb).s_last_orphan)) - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_inode_relocator.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_inode_relocator.c deleted file mode 100644 index 45befbf9ce..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_inode_relocator.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - ext2_inode_relocator.c -- ext2 inode relocator - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include /* for S_ISDIR */ -#include "ext2.h" - - - - - - -struct ext2_reference -{ - blk_t block; - off_t offset; -}; - -struct ext2_inode_entry -{ - ino_t num; - ino_t dest; - unsigned numreferences:16; - unsigned isdir:1; - struct ext2_reference *ref; -}; - -struct ext2_inode_relocator_state -{ - int usedentries; - int resolvedentries; - struct ext2_inode_entry *inode; - struct ext2_reference *last; -}; - - - - - -static struct ext2_inode_entry *findit(struct ext2_inode_relocator_state *state, ino_t inode) -{ - int min; - int max; - struct ext2_inode_entry *retv; - int t; - blk_t tval; - - max = state->usedentries - 1; - min = 0; - retv = NULL; - - repeat: - if (min > max) - goto out; - - t = (min + max) >> 1; - tval = state->inode[t].num; - - t--; - if (tval > inode) - max = t; - - t += 2; - if (tval < inode) - min = t; - - t--; - - if (tval != inode) - goto repeat; - - retv = &state->inode[t]; - - out: - return retv; -} - -static int addref(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, ino_t inode, blk_t block, off_t offset) -{ - struct ext2_inode_entry *ent; - int i; - - if ((ent = findit(state, inode)) == NULL) - return 1; - - for (i=0;inumreferences;i++) - if (!ent->ref[i].block) - break; - - if (i == ent->numreferences) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Found an inode with a incorrect link count. " - "Better go run e2fsck first!")); - return 0; - } - - if (i == ent->numreferences - 1) - state->resolvedentries++; - - ent->ref[i].block = block; - ent->ref[i].offset = offset; - - return 1; -} - -static int doblock(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, blk_t blockno) -{ - struct ext2_buffer_head *bh; - off_t offset; - - bh = ext2_bread(fs, blockno); - if (!bh) - return 0; - - offset = 0; - do - { - struct ext2_dir_entry_2 *ptr; - - ptr = (struct ext2_dir_entry_2 *)(bh->data + offset); - - if (ptr->name_len) - if (!addref(fs, state, EXT2_DIRENT_INODE(*ptr), blockno, - offset)) - return 0; - - PED_ASSERT (ptr->rec_len > 0, return 0); - offset += EXT2_DIRENT_REC_LEN (*ptr); - } while (offset < fs->blocksize); - - ext2_brelse(bh, 0); - return 1; -} - -static int doindblock(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, blk_t blockno) -{ - struct ext2_buffer_head *bh; - blk_t blk; - int i; - - bh = ext2_bread(fs, blockno); - - for (i=0;i<(fs->blocksize>>2);i++) - if ((blk = PED_LE32_TO_CPU(((uint32_t *)bh->data)[i])) != 0) - if (!doblock(fs, state, blk)) - return 0; - - ext2_brelse(bh, 0); - return 1; -} - -static int dodindblock(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, blk_t blockno) -{ - struct ext2_buffer_head *bh; - blk_t blk; - int i; - - bh = ext2_bread(fs, blockno); - if (!bh) - return 0; - - for (i=0;i<(fs->blocksize>>2);i++) - if ((blk = PED_LE32_TO_CPU(((uint32_t *)bh->data)[i])) != 0) - if (!doindblock(fs, state, blk)) - return 0; - - ext2_brelse(bh, 0); - return 1; -} - -static int dotindblock(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, blk_t blockno) -{ - struct ext2_buffer_head *bh; - blk_t blk; - int i; - - bh = ext2_bread(fs, blockno); - if (!bh) - return 0; - - for (i=0;i<(fs->blocksize>>2);i++) - if ((blk = PED_LE32_TO_CPU(((uint32_t *)bh->data)[i])) != 0) - if (!dodindblock(fs, state, blk)) - return 0; - - ext2_brelse(bh, 0); - return 1; -} - -static int doinode(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, ino_t inode) -{ - struct ext2_inode buf; - int i; - - if (!ext2_read_inode(fs, inode, &buf)) - return 0; - if (S_ISDIR(EXT2_INODE_MODE(buf))) - { - blk_t blk; - - for (i=0;iopt_verbose) - fprintf(stderr, " scanning group %i.... ", group); - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group])); - offset = group * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; - - for (i=0;isb);i++) - if (bh->data[i>>3] & _bitmap[i&7]) - { - if (!doinode(fs, state, offset + i)) - { - ext2_brelse(bh, 0); - return 0; - } - - if (state->resolvedentries == state->usedentries) - break; - } - - ext2_brelse(bh, 0); - - if (fs->opt_verbose) - fprintf(stderr, - "%i/%i inodes resolved\r", - state->resolvedentries, - state->usedentries); - - return 1; -} - -/* basically: this builds a dependency graph of the inodes in the entire file - * system. inodes are only referenced by the directory tree (or the magic - * ones implicitly, like the bad blocks inode), so we just walk the directory - * tree adding references. - */ -static int doscan(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - int i; - - /* while the journal will usually be inode 8 (and therefore will never - * need to be moved), we don't have any guarantee (grrr). So, we - * need to be prepared to move it... (and update the reference in the - * super block) - */ - if (fs->has_internal_journal) - addref(fs, state, EXT2_SUPER_JOURNAL_INUM(fs->sb), - 1, offsetof(struct ext2_super_block, s_journal_inum)); - - if (!doscangroup(fs, state, 0)) - return 0; - - if (state->resolvedentries != state->usedentries) - for (i=fs->numgroups-1;i>0;i--) - { - if (!doscangroup(fs, state, i)) - return 0; - - if (state->resolvedentries == state->usedentries) - break; - } - - if (fs->opt_verbose) - fputc ('\n', stderr); - - return 1; -} - - - - - - - -static int ext2_inode_relocator_copy(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - int i; - - for (i=0;iusedentries;i++) - { - struct ext2_inode buf; - struct ext2_inode_entry *entry; - - entry = &state->inode[i]; - - if (fs->opt_debug) - if (!ext2_get_inode_state(fs, entry->num) || - ext2_get_inode_state(fs, entry->dest)) - fputs ("inodebitmaperror\n", stderr); - - if (!ext2_read_inode(fs, entry->num, &buf)) - return 0; - if (!ext2_write_inode(fs, entry->dest, &buf)) - return 0; - - entry->isdir = S_ISDIR(EXT2_INODE_MODE(buf))?1:0; - } - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - return 1; -} - -static int ext2_inode_relocator_finish(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - int i; - - for (i=0;iusedentries;i++) - { - struct ext2_inode_entry *entry; - - entry = &state->inode[i]; - ext2_set_inode_state(fs, entry->dest, 1, 1); - ext2_set_inode_state(fs, entry->num, 0, 1); - ext2_zero_inode(fs, entry->num); - } - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - return 1; -} - -static int ext2_inode_relocator_ref(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - int i; - static int numerrors = 0; - - for (i=0;iusedentries;i++) - { - struct ext2_inode_entry *entry; - int j; - uint32_t t; - - entry = &state->inode[i]; - t = entry->dest; - - for (j=0;jnumreferences;j++) - { - struct ext2_buffer_head *bh; - - bh = ext2_bread(fs, entry->ref[j].block); - if (!bh) - return 0; - - if (fs->opt_debug) - { - if (PED_LE32_TO_CPU((*((uint32_t *)(bh->data + entry->ref[j].offset)))) != entry->num) - { - fprintf(stderr, - "inode %li ref error! (->%li, [%i]={%i, %i})\n", - (long) entry->num, - (long) entry->dest, - j, - entry->ref[j].block, - (int) entry->ref[j].offset); - ext2_brelse(bh, 0); - - if (numerrors++ < 4) - continue; - - fputs ("all is not well!\n", stderr); - return 0; - } - } - - *((uint32_t *)(bh->data + entry->ref[j].offset)) - = PED_CPU_TO_LE32(t); - bh->dirty = 1; - - ext2_brelse(bh, 0); - } - - if (entry->isdir) - { - int oldgroup; - int newgroup; - - oldgroup = (entry->num - 1) - / EXT2_SUPER_INODES_PER_GROUP(fs->sb); - newgroup = (entry->dest - 1) - / EXT2_SUPER_INODES_PER_GROUP(fs->sb); - - fs->gd[oldgroup].bg_used_dirs_count = PED_CPU_TO_LE16 ( - EXT2_GROUP_USED_DIRS_COUNT(fs->gd[oldgroup]) - - 1); - fs->gd[newgroup].bg_used_dirs_count = PED_CPU_TO_LE16 ( - EXT2_GROUP_USED_DIRS_COUNT(fs->gd[newgroup]) - + 1); - - fs->metadirty = EXT2_META_GD; - } - } - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - return 1; -} - -static int ext2_inode_relocator_grab_inodes(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - int i; - int ptr; - - ptr = 0; - - for (i=0;inumgroups;i++) - if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i])) - { - struct ext2_buffer_head *bh; - unsigned int j; - int offset; - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[i])); - if (!bh) - return 0; - offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; - - j = i ? 0 : 13; - for (;jsb);j++) - if (!(bh->data[j>>3] & _bitmap[j&7])) - { - state->inode[ptr++].dest = offset + j; - - if (ptr == state->usedentries) - { - ext2_brelse(bh, 0); - return 1; - } - } - - ext2_brelse(bh, 0); - } - - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Not enough free inodes!")); - return 0; -} - -static int ext2_inode_relocator_flush(struct ext2_fs *fs, struct ext2_inode_relocator_state *state) -{ - if (!state->usedentries) - return 1; - - if (!doscan(fs, state)) - return 0; - - if (!ext2_inode_relocator_grab_inodes(fs, state)) - return 0; - - if (!ext2_inode_relocator_copy(fs, state)) - return 0; - - if (!ext2_inode_relocator_ref(fs, state)) - return 0; - - if (!ext2_inode_relocator_finish(fs, state)) - return 0; - - state->usedentries = 0; - state->resolvedentries = 0; - state->last = (struct ext2_reference *)fs->relocator_pool_end; - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - return 1; -} - -static int ext2_inode_relocator_mark(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, ino_t inode) -{ - struct ext2_inode buf; - struct ext2_inode_entry *ent; - int i; - - if (!ext2_read_inode(fs, inode, &buf)) - return 0; - - { - register void *adv; - register void *rec; - - adv = state->inode + state->usedentries + 1; - rec = state->last - EXT2_INODE_LINKS_COUNT(buf); - - if (adv >= rec) - ext2_inode_relocator_flush(fs, state); - } - - state->last -= EXT2_INODE_LINKS_COUNT(buf); - - ent = &state->inode[state->usedentries]; - ent->num = inode; - ent->dest = 0; - ent->numreferences = EXT2_INODE_LINKS_COUNT(buf); - ent->ref = state->last; - - for (i=0;inumreferences;i++) - { - ent->ref[i].block = 0; - ent->ref[i].offset = 0; - } - - state->usedentries++; - - return 1; -} - - -int ext2_inode_relocate(struct ext2_fs *fs, int newgroups) -{ - int i; - struct ext2_inode_relocator_state state; - - if (fs->opt_verbose) - fputs ("ext2_inode_relocate\n", stderr); - - state.usedentries = 0; - state.resolvedentries = 0; - state.inode = (struct ext2_inode_entry *)fs->relocator_pool; - state.last = (struct ext2_reference *)fs->relocator_pool_end; - - for (i=newgroups;inumgroups;i++) - { - struct ext2_buffer_head *bh; - unsigned int j; - int offset; - - bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[i])); - if (!bh) - return 0; - offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1; - - for (j=0;jsb);j++) - if (bh->data[j>>3] & _bitmap[j&7]) - ext2_inode_relocator_mark(fs, &state, - offset + j); - - ext2_brelse(bh, 0); - } - - if (!ext2_inode_relocator_flush(fs, &state)) - return 0; - - return 1; -} -#endif /* !DISCOVER_ONLY */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c deleted file mode 100644 index 09fb8ad5e1..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - ext2_meta.c -- ext2 metadata mover - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include "ext2.h" - -int ext2_metadata_push(struct ext2_fs *fs, blk_t newsize) -{ - int i; - int newgdblocks; - blk_t newitoffset; - - newgdblocks = ped_div_round_up (newsize - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), - EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - newgdblocks = ped_div_round_up (newgdblocks - * sizeof(struct ext2_group_desc), - fs->blocksize); - newitoffset = newgdblocks + 3; - - if (newitoffset <= fs->itoffset) - return 1; - - for (i=0;inumgroups;i++) - { - blk_t diff; - blk_t j; - blk_t fromblock; - blk_t start; - - start = (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - - if (EXT2_GROUP_INODE_TABLE(fs->gd[i]) >= start + newitoffset - && EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) >= start + newitoffset - 2 - && EXT2_GROUP_INODE_BITMAP(fs->gd[i]) >= start + newitoffset - 1) - continue; - - diff = newitoffset - (EXT2_GROUP_INODE_TABLE(fs->gd[i]) - start); - - /* inode table */ - fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]) + fs->inodeblocks; - - if (fs->opt_debug) - { - for (j=0;jgd[i]), - fs->inodeblocks, - EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff)) - return 0; - fs->gd[i].bg_inode_table = PED_CPU_TO_LE32 ( - EXT2_GROUP_INODE_TABLE(fs->gd[i]) + diff); - fs->metadirty |= EXT2_META_GD; - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - /* block bitmap and inode bitmap */ - fromblock = EXT2_GROUP_INODE_TABLE(fs->gd[i]); - if (ext2_is_group_sparse(fs, i)) - { - if (!ext2_copy_block(fs, - EXT2_GROUP_INODE_BITMAP(fs->gd[i]), - EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff)) - return 0; - fs->gd[i].bg_inode_bitmap = PED_CPU_TO_LE32 ( - EXT2_GROUP_INODE_BITMAP(fs->gd[i]) + diff); - fs->metadirty |= EXT2_META_GD; - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - if (!ext2_copy_block(fs, - EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]), - EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])+diff)) - return 0; - fs->gd[i].bg_block_bitmap = PED_CPU_TO_LE32 ( - EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) + diff); - fs->metadirty |= EXT2_META_GD; - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - fromblock = EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]); - } - - ext2_zero_blocks(fs, fromblock-diff, diff); - for (j=0;jopt_verbose) - fprintf(stderr, - "ext2_metadata_push: group %i/%i\r", - i+1, fs->numgroups); - } - - fs->itoffset = newitoffset; - - if (fs->opt_verbose) - fputc ('\n', stderr); - - return 1; -} -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_mkfs.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_mkfs.c deleted file mode 100644 index 19931dd0f3..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_mkfs.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - ext2_mkfs.c -- ext2 fs creator - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#define USE_EXT2_IS_DATA_BLOCK - -#include -#include -#include -#include -#include -#include -#include -#include "ext2.h" - -/* formula grabbed from linux ext2 kernel source - * - * returns 1 iff: - * x == y^N, N is some natural number - * OR x == 0 - */ -static __inline__ int is_root(int x, int y) -{ - if (!x) return 1; - - while (1) - { - if (x == 1) return 1; - - if (x % y) return 0; - - x /= y; - } -} - -static __inline__ int is_group_sparse(int sparsesbfs, int group) -{ - if (!sparsesbfs) - return 1; - - if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7)) - return 1; - - return 0; -} - -/* has implicit parameter 'sb' !! */ -#define is_sparse(group) is_group_sparse(EXT2_SUPER_FEATURE_RO_COMPAT(*sb) \ - & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER, (group)) - -static int ext2_mkfs_write_main(struct ext2_dev_handle *handle, - struct ext2_super_block *sb, - struct ext2_group_desc *gd) -{ - int freeit; - int i; - int numgroups; - int gdblocks; - unsigned char *sbbuf; - struct ext2_super_block *sb_for_io; - - freeit = 0; - sbbuf = (unsigned char *)sb; - sb_for_io = sb; - if (EXT2_SUPER_LOG_BLOCK_SIZE(*sb)) - { - sbbuf = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)); - if (!(handle->ops->read)(handle->cookie, sbbuf, 0, 1)) - return 0; - memcpy (sbbuf+1024, sb, 1024); - freeit = 1; - sb_for_io = (struct ext2_super_block*) (sbbuf + 1024); - } - - numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(*sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(*sb), - EXT2_SUPER_BLOCKS_PER_GROUP(*sb)); - gdblocks = ped_div_round_up (numgroups * sizeof(struct ext2_group_desc), - 1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)); - - for (i=0;is_block_group_nr = PED_CPU_TO_LE16 (i); - - if (!handle->ops->write(handle->cookie, sbbuf, - offset, 1)) - return 0; - if (!handle->ops->write(handle->cookie, gd, offset+1, - gdblocks)) - return 0; - } - } - - sb_for_io->s_block_group_nr = 0; - - if (freeit) - ped_free(sbbuf); - return 1; -} - -static int ext2_mkfs_write_meta(struct ext2_dev_handle *handle, - struct ext2_super_block *sb, - struct ext2_group_desc *gd, - PedTimer* timer) -{ - int blocksize; - int gdtsize; - int i; - int itsize; - int numgroups; - unsigned char *bb; - unsigned char *ib; - unsigned char *zero; - - blocksize = 1 << (EXT2_SUPER_LOG_BLOCK_SIZE(*sb) + 13); - - numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(*sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(*sb), - EXT2_SUPER_BLOCKS_PER_GROUP(*sb)); - itsize = ped_div_round_up (sizeof(struct ext2_inode) - * EXT2_SUPER_INODES_PER_GROUP(*sb), - (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb))); - gdtsize = ped_div_round_up (sizeof(struct ext2_group_desc) * numgroups, - (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb))); - - bb = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)); - if (!bb) goto error; - ib = ped_malloc(1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)); - if (!ib) goto error_free_bb; - zero = ped_malloc((1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)) * itsize); - if (!zero) goto error_free_zero; - - memset(zero, 0, (1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)) * itsize); - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("writing per-group metadata")); - - for (i=0;i>3] |= _bitmap[j&7]; - - j = bbblock - groupoffset; - bb[j>>3] |= _bitmap[j&7]; - - j = ibblock - groupoffset; - bb[j>>3] |= _bitmap[j&7]; - - for (j=0;j>3] |= _bitmap[k&7]; - } - - for (j=groupsize;j>3] |= _bitmap[j&7]; - - if (!handle->ops->write(handle->cookie, bb, bbblock, 1)) - goto error_free_zero; - } - - { - memset(ib, 0, 1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb)); - - for (j=EXT2_SUPER_INODES_PER_GROUP(*sb);j>3] |= _bitmap[j&7]; - - if (!handle->ops->write(handle->cookie, ib, ibblock, 1)) - goto error_free_zero; - } - - if (!handle->ops->write(handle->cookie, zero, - groupoffset + gdtsize + 3, itsize)) - goto error_free_zero; - - gd[i].bg_block_bitmap = PED_CPU_TO_LE32(bbblock); - gd[i].bg_inode_bitmap = PED_CPU_TO_LE32(ibblock); - gd[i].bg_inode_table = PED_CPU_TO_LE32(groupoffset + gdtsize - + 3); - gd[i].bg_free_blocks_count = PED_CPU_TO_LE16(groupsize - admin); - gd[i].bg_free_inodes_count = PED_CPU_TO_LE16( - EXT2_SUPER_INODES_PER_GROUP(*sb)); - gd[i].bg_used_dirs_count = 0; - gd[i].bg_used_dirs_count = 0; - gd[i].bg_pad = 0; - gd[i].bg_reserved[0] = 0; - gd[i].bg_reserved[1] = 0; - gd[i].bg_reserved[2] = 0; - - sb->s_free_blocks_count = PED_CPU_TO_LE32 ( - EXT2_SUPER_FREE_BLOCKS_COUNT(*sb) - + EXT2_GROUP_FREE_BLOCKS_COUNT(gd[i])); - } - - ped_timer_update (timer, 1.0); - - ped_free(zero); - ped_free(ib); - ped_free(bb); - return 1; - -error_free_zero: - ped_free(zero); - ped_free(ib); -error_free_bb: - ped_free(bb); -error: - return 0; -} - -/* returns the offset into the buffer of the start of the next dir entry */ -static int _set_dirent(void* buf, int offset, int block_size, int is_last, - uint32_t inode, char* name, int file_type) -{ - struct ext2_dir_entry_2 *dirent = (void*) (((char*)buf) + offset); - int name_len = strlen(name); - int rec_len; - - if (is_last) - rec_len = block_size - offset; - else - rec_len = ped_round_up_to(name_len + 1 + 8, 4); - - memset (dirent, 0, rec_len); - - dirent->inode = PED_CPU_TO_LE32(inode); - dirent->name_len = name_len; - dirent->rec_len = PED_CPU_TO_LE16(rec_len); - dirent->file_type = file_type; - strcpy(dirent->name, name); - - return offset + rec_len; -} - -static int ext2_mkfs_create_lost_and_found_inode(struct ext2_fs *fs) -{ - struct ext2_buffer_head *bh; - blk_t blocks[12]; - uint32_t* data = ped_malloc ((fs->blocksize / 4) * sizeof(uint32_t)); - int i; - struct ext2_inode inode; - int offset; - - for (i=0;i<12;i++) - { - if (!(blocks[i] = ext2_find_free_block(fs))) - return 0; - - if (!ext2_set_block_state(fs, blocks[i], 1, 1)) - return 0; - } - - /* create the directory entries, preallocating lots of blocks */ - /* first block contains . and .. */ - bh = ext2_bcreate(fs, blocks[0]); - if (!bh) - return 0; - memset(bh->data, 0, fs->blocksize); - offset = _set_dirent(bh->data, 0, fs->blocksize, 0, - 11, ".", EXT2_FT_DIR); - offset = _set_dirent(bh->data, offset, fs->blocksize, 1, - EXT2_ROOT_INO, "..", EXT2_FT_DIR); - bh->dirty = 1; - ext2_brelse(bh, 1); - - /* subsequent blocks are empty */ - memset(data, 0, fs->blocksize); - data[0] = 0; - data[1] = PED_CPU_TO_LE32(fs->blocksize); - for (i=1;i<12;i++) - { - bh = ext2_bcreate(fs, blocks[i]); - memcpy(bh->data, data, fs->blocksize); - bh->dirty = 1; - ext2_brelse(bh, 1); - } - - /* create inode */ - memset(&inode, 0, sizeof(struct ext2_inode)); - inode.i_mode = PED_CPU_TO_LE16(S_IFDIR | 0755); - inode.i_uid = 0; - inode.i_size = PED_CPU_TO_LE32(12 * fs->blocksize); - inode.i_atime = PED_CPU_TO_LE32(time(NULL)); - inode.i_ctime = PED_CPU_TO_LE32(time(NULL)); - inode.i_mtime = PED_CPU_TO_LE32(time(NULL)); - inode.i_dtime = 0; - inode.i_gid = 0; - inode.i_links_count = PED_CPU_TO_LE16(2); - inode.i_blocks = PED_CPU_TO_LE32((12 * fs->blocksize) >> 9); - inode.i_flags = 0; - for (i=0;i<12;i++) - inode.i_block[i] = PED_CPU_TO_LE32(blocks[i]); - - if (!ext2_write_inode(fs, 11, &inode)) - return 0; - fs->gd[0].bg_used_dirs_count = PED_CPU_TO_LE16( - EXT2_GROUP_USED_DIRS_COUNT(fs->gd[0]) + 1); - fs->metadirty |= EXT2_META_GD; - - return 1; -} - -static int ext2_mkfs_create_root_inode(struct ext2_fs *fs) -{ - struct ext2_buffer_head *bh; - blk_t block; - struct ext2_inode inode; - int offset; - - if (!(block = ext2_find_free_block(fs))) - return 0; - if (!ext2_set_block_state(fs, block, 1, 1)) - return 0; - - /* create directory entries */ - bh = ext2_bcreate(fs, block); - memset(bh->data, 0, fs->blocksize); - offset = _set_dirent(bh->data, 0, fs->blocksize, 0, - EXT2_ROOT_INO, ".", EXT2_FT_DIR); - offset = _set_dirent(bh->data, offset, fs->blocksize, 0, - EXT2_ROOT_INO, "..", EXT2_FT_DIR); - offset = _set_dirent(bh->data, offset, fs->blocksize, 1, - 11, "lost+found", EXT2_FT_DIR); - bh->dirty = 1; - if (!ext2_brelse(bh, 1)) - return 0; - - /* create inode */ - memset(&inode, 0, sizeof(struct ext2_inode)); - inode.i_mode = PED_CPU_TO_LE16(S_IFDIR | 0755); - inode.i_uid = 0; - inode.i_size = PED_CPU_TO_LE32(fs->blocksize); - inode.i_atime = PED_CPU_TO_LE32(time(NULL)); - inode.i_ctime = PED_CPU_TO_LE32(time(NULL)); - inode.i_mtime = PED_CPU_TO_LE32(time(NULL)); - inode.i_dtime = 0; - inode.i_gid = 0; - inode.i_links_count = PED_CPU_TO_LE16(3); - inode.i_blocks = PED_CPU_TO_LE32(fs->blocksize >> 9); - inode.i_flags = 0; - inode.i_block[0] = PED_CPU_TO_LE32(block); - - if (!ext2_write_inode(fs, 2, &inode)) - return 0; - fs->gd[0].bg_used_dirs_count = PED_CPU_TO_LE16 ( - EXT2_GROUP_USED_DIRS_COUNT(fs->gd[0]) + 1); - fs->metadirty |= EXT2_META_GD; - - return 1; -} - -static int ext2_reserve_inodes(struct ext2_fs *fs) -{ - int i; - - for (i=1;i<12;i++) - if (!ext2_set_inode_state(fs, i, 1, 1)) - return 0; - return 1; -} - -static int ext2_mkfs_init_sb (struct ext2_super_block *sb, blk_t numblocks, - int numgroups, int first_block, - int log_block_size, blk_t blocks_per_group, - int inodes_per_group, int sparse_sb, - int reserved_block_percentage) -{ - /* catch a bug in gcc 2.95.2 */ - PED_ASSERT(numgroups != 0, return 0); - - memset(sb, 0, 1024); - - sb->s_inodes_count = PED_CPU_TO_LE32(numgroups * inodes_per_group); - sb->s_blocks_count = PED_CPU_TO_LE32(numblocks); - sb->s_r_blocks_count = PED_CPU_TO_LE32(((uint64_t)numblocks - * reserved_block_percentage) / 100); - - /* hack: this get's inc'd as we go through each group in - * ext2_mkfs_write_meta() - */ - sb->s_free_blocks_count = 0; - sb->s_free_inodes_count = PED_CPU_TO_LE32 (numgroups - * inodes_per_group); - sb->s_first_data_block = PED_CPU_TO_LE32(first_block); - sb->s_log_block_size = PED_CPU_TO_LE32(log_block_size - 10); - sb->s_log_frag_size = sb->s_log_block_size; - sb->s_blocks_per_group = PED_CPU_TO_LE32(blocks_per_group); - sb->s_frags_per_group = PED_CPU_TO_LE32(blocks_per_group); - sb->s_inodes_per_group = PED_CPU_TO_LE32(inodes_per_group); - sb->s_mtime = 0; - sb->s_wtime = 0; - sb->s_mnt_count = 0; - sb->s_max_mnt_count = PED_CPU_TO_LE16(30); - sb->s_magic = PED_CPU_TO_LE16(0xEF53); - sb->s_state = PED_CPU_TO_LE16(EXT2_VALID_FS); - sb->s_errors = PED_CPU_TO_LE16(EXT2_ERRORS_DEFAULT); - sb->s_minor_rev_level = 0; - sb->s_lastcheck = 0; - sb->s_checkinterval = 0; - sb->s_creator_os = 0; - sb->s_rev_level = PED_CPU_TO_LE32(1); - sb->s_def_resuid = 0; - sb->s_def_resgid = 0; - sb->s_first_ino = PED_CPU_TO_LE32(11); - sb->s_inode_size = PED_CPU_TO_LE16(128); - sb->s_block_group_nr = 0; - sb->s_feature_compat = 0; - sb->s_feature_incompat = 0; - sb->s_feature_ro_compat = 0; - if (sparse_sb) - sb->s_feature_ro_compat - |= PED_CPU_TO_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER); - -/* FIXME: let the user decide? _set_dirent() assumes FILETYPE */ - sb->s_feature_incompat - |= PED_CPU_TO_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE); - - uuid_generate(sb->s_uuid); - memset(sb->s_volume_name, 0, 16); - memset(sb->s_last_mounted, 0, 64); - sb->s_algorithm_usage_bitmap = 0; - sb->s_prealloc_blocks = 0; - sb->s_prealloc_dir_blocks = 0; - sb->s_padding1 = 0; - - return 1; -} - -/* Given these five inputs, compute the three outputs. */ -static void -compute_block_counts (blk_t numblocks, int numgroups, int log_block_size, - int sparse_sb, blk_t blocks_per_group, - int *last_group_blocks, - int *last_group_admin, - int *inodes_per_group) -{ - int first_block = (log_block_size == 10) ? 1 : 0; - size_t block_size = 1 << log_block_size; - - *last_group_blocks = ((numblocks - first_block) % blocks_per_group); - if (!*last_group_blocks) - *last_group_blocks = blocks_per_group; - *inodes_per_group = ped_round_up_to (numblocks / numgroups / 2, - (block_size - / sizeof(struct ext2_inode))); - *last_group_admin = (2 + *inodes_per_group * sizeof(struct ext2_inode) - / block_size); - if (is_group_sparse(sparse_sb, numgroups - 1)) { - *last_group_admin += - (ped_div_round_up (numgroups * sizeof(struct ext2_group_desc), - block_size)); - } -} - -struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle, - blk_t numblocks, - int log_block_size, - blk_t blocks_per_group, - int inodes_per_group, - int sparse_sb, - int reserved_block_percentage, - PedTimer* timer) -{ - struct ext2_fs *fs; - struct ext2_super_block sb; - struct ext2_group_desc *gd; - int numgroups; - int first_block; - int last_group_blocks; - int last_group_admin; - - /* if the FS is > 512Mb, use 4k blocks, otherwise 1k blocks */ - if (log_block_size == 0) { - handle->ops->set_blocksize(handle->cookie, 12); - if (handle->ops->get_size(handle->cookie) > (512 * 1024)) - log_block_size = 12; - else - log_block_size = 10; - } - - /* FIXME: block size must be > MAX(logicalbs, physicalbs) - * to avoid modify-on-write. - * -- Leslie - */ - - - handle->ops->set_blocksize(handle->cookie, log_block_size); - - if (numblocks == 0) - numblocks = handle->ops->get_size(handle->cookie); - if (numblocks == 0) - goto diagnose_fs_too_small; - - if (blocks_per_group == (unsigned int) 0) - blocks_per_group = 8 << log_block_size; - - first_block = (log_block_size == 10) ? 1 : 0; - - numgroups = ped_div_round_up (numblocks - - first_block, blocks_per_group); - - if (sparse_sb == -1) - sparse_sb = 1; - - /* FIXME: 5% not appropriate for modern drive sizes */ - if (reserved_block_percentage == -1) - reserved_block_percentage = 5; - - compute_block_counts (numblocks, numgroups, log_block_size, sparse_sb, - blocks_per_group, &last_group_blocks, - &last_group_admin, &inodes_per_group); - - int fs_too_small = 0; - if (last_group_admin + 1 >= last_group_blocks) - { - numgroups--; - if (numgroups == 0) - fs_too_small = 1; - else - { - numblocks -= last_group_blocks; - compute_block_counts (numblocks, numgroups, log_block_size, - sparse_sb, blocks_per_group, - &last_group_blocks, &last_group_admin, - &inodes_per_group); - } - } - - if (numgroups == 1 - && (last_group_blocks - last_group_admin < 8 - || inodes_per_group < 16 - /* This final term ensures that we detect - mkpartfs primary ext2 10KB 27650B as invalid. */ - || (inodes_per_group == 16 - && last_group_blocks - last_group_admin < 14))) - fs_too_small = 1; - - if (fs_too_small) { - diagnose_fs_too_small: - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("File system too small for ext2.")); - goto error; - } - - gd = ped_malloc(numgroups * sizeof(struct ext2_group_desc) - + (1 << log_block_size)); - if (!gd) - goto error; - - if (!ext2_mkfs_init_sb(&sb, numblocks, numgroups, first_block, - log_block_size, blocks_per_group, - inodes_per_group, sparse_sb, - reserved_block_percentage)) - goto error_free_gd; - if (!ext2_mkfs_write_meta(handle, &sb, gd, timer)) - goto error_free_gd; - if (!ext2_mkfs_write_main(handle, &sb, gd)) - goto error_free_gd; - - fs = ext2_open(handle, 0); - if (!fs) goto error_close_fs; - if (!ext2_reserve_inodes(fs)) goto error_close_fs; - if (!ext2_mkfs_create_root_inode(fs)) goto error_close_fs; - if (!ext2_mkfs_create_lost_and_found_inode(fs)) - goto error_close_fs; - if (!ext2_sync(fs)) goto error_close_fs; - ped_free(gd); - return fs; - -error_close_fs: - ext2_close(fs); -error_free_gd: - ped_free (gd); -error: - return NULL; -} -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_resize.c b/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_resize.c deleted file mode 100644 index 580c46606e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/ext2_resize.c +++ /dev/null @@ -1,730 +0,0 @@ -/* - ext2_resize.c -- ext2 resizer - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include "ext2.h" - -static int ext2_add_group(struct ext2_fs *fs, blk_t groupsize) -{ - blk_t admin; - int group; - blk_t groupstart; - blk_t newgdblocks; - int sparse; - - if (fs->opt_verbose) - fputs ("ext2_add_group\n", stderr); - - if (!ped_realloc ((void*) &fs->gd, - (fs->numgroups+1) * sizeof(struct ext2_group_desc) - + fs->blocksize)) - return 0; - - if (fs->opt_debug) - { - if (EXT2_SUPER_BLOCKS_COUNT(fs->sb) != - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - + fs->numgroups * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - { - fputs ("ext2_add_group: last (existing) group " - "isn't complete!\n", stderr); - - return 0; - } - } - - group = fs->numgroups; - sparse = ext2_is_group_sparse(fs, group); - groupstart = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - + group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - admin = fs->adminblocks; - if (!sparse) - admin -= fs->gdblocks + 1; - - if (fs->opt_debug) - { - if (groupsize < fs->adminblocks || - groupsize > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - { - fprintf(stderr, - "ext2_add_group: groups of %i blocks are " - "impossible!\n", groupsize); - - return 0; - } - } - - newgdblocks = ped_div_round_up((fs->numgroups + 1) - * sizeof(struct ext2_group_desc), - fs->blocksize); - if (newgdblocks != fs->gdblocks) - { - int i; - - for (i=0;inumgroups;i++) - if (ext2_is_group_sparse(fs, i)) - { - blk_t start; - - start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - + i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - ext2_set_block_state(fs, - start + fs->gdblocks + 1, 1, 1); - } - - fs->gdblocks++; - fs->adminblocks++; - if (sparse) - admin++; - } - - fs->numgroups++; - - fs->sb.s_inodes_count = PED_CPU_TO_LE32( - EXT2_SUPER_INODES_COUNT(fs->sb) - + EXT2_SUPER_INODES_PER_GROUP(fs->sb)); - fs->sb.s_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_BLOCKS_COUNT(fs->sb) + groupsize); - fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + groupsize - admin); - fs->sb.s_free_inodes_count = PED_CPU_TO_LE32( - EXT2_SUPER_FREE_INODES_COUNT(fs->sb) - + EXT2_SUPER_INODES_PER_GROUP(fs->sb)); - fs->metadirty |= EXT2_META_SB; - - { - blk_t off; - blk_t sparseoff; - - off = groupstart; - sparseoff = off + fs->itoffset - 2; - - if (sparse) - { - fs->gd[group].bg_block_bitmap - = PED_CPU_TO_LE32(sparseoff); - fs->gd[group].bg_inode_bitmap - = PED_CPU_TO_LE32(sparseoff + 1); - } - else - { - fs->gd[group].bg_block_bitmap - = PED_CPU_TO_LE32(off); - fs->gd[group].bg_inode_bitmap - = PED_CPU_TO_LE32(off + 1); - } - - /* Hey, I don't know _why_ either */ - fs->gd[group].bg_inode_table = PED_CPU_TO_LE32(sparseoff + 2); - } - - fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16(groupsize - admin); - fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16( - EXT2_SUPER_INODES_PER_GROUP(fs->sb)); - fs->gd[group].bg_used_dirs_count = 0; - fs->metadirty |= EXT2_META_SB | EXT2_META_GD; - - { - struct ext2_buffer_head *bh; - blk_t i; - - bh = ext2_bcreate(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group])); - if (!bh) - return 0; - - if (sparse) - { - bh->data[0] |= _bitmap[0]; - for (i=1;i<=fs->gdblocks;i++) - bh->data[i>>3] |= _bitmap[i&7]; - } - - i = EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]) - groupstart; - bh->data[i>>3] |= _bitmap[i&7]; - - i = EXT2_GROUP_INODE_BITMAP(fs->gd[group]) - groupstart; - bh->data[i>>3] |= _bitmap[i&7]; - - for (i=0;iinodeblocks;i++) - { - blk_t j; - - j = EXT2_GROUP_INODE_TABLE(fs->gd[group]) - - groupstart + i; - bh->data[j>>3] |= _bitmap[j&7]; - } - - for (i=groupsize;isb);i++) - bh->data[i>>3] |= _bitmap[i&7]; - - ext2_brelse(bh, 0); /* this is a block bitmap */ - } - - if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]), 1)) - return 0; - if (!ext2_zero_blocks(fs, EXT2_GROUP_INODE_TABLE(fs->gd[group]), - fs->inodeblocks)) - return 0; - - if (fs->opt_safe) - if (!ext2_sync(fs)) - return 0; - - return 1; -} - -static int ext2_del_group(struct ext2_fs *fs) -{ - blk_t admin; - int group; - blk_t groupsize; - blk_t newgdblocks; - int sparse; - - if (fs->opt_verbose) - fputs ("ext2_del_group\n", stderr); - - group = fs->numgroups - 1; - sparse = ext2_is_group_sparse(fs, group); - - admin = fs->adminblocks; - if (!sparse) - admin -= fs->gdblocks + 1; - - groupsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - - group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - if (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) < groupsize - admin) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system is too full to remove a group!")); - - return 0; - } - - if (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) - < EXT2_SUPER_INODES_PER_GROUP(fs->sb)) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has too many allocated inodes to " - "remove a group!")); - return 0; - } - - if (fs->opt_debug) - { - if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) != - EXT2_SUPER_INODES_PER_GROUP(fs->sb)) - { - fputs ("ext2_del_group: this should not " - "happen anymore!\n", stderr); - - return 0; - } - } - - newgdblocks = ped_div_round_up((fs->numgroups - 1) * - sizeof(struct ext2_group_desc), fs->blocksize); - - if (newgdblocks != fs->gdblocks) - { - int i; - - for (i=0;inumgroups;i++) - if (ext2_is_group_sparse(fs, i)) - { - blk_t start; - - start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + - i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - ext2_set_block_state(fs, - start + fs->gdblocks, - 0, 1); - } - - fs->gdblocks--; - fs->adminblocks--; - if (sparse) - admin--; - } - - if (fs->opt_debug) - { - if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) - != groupsize - admin) - { - blk_t i; - blk_t num; - blk_t offset; - - offset = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + - group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - num = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - for (i=0;inumgroups--; - - fs->sb.s_inodes_count = PED_CPU_TO_LE32( - EXT2_SUPER_INODES_COUNT(fs->sb) - - EXT2_SUPER_INODES_PER_GROUP(fs->sb)); - fs->sb.s_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupsize); - fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - (groupsize - admin)); - fs->sb.s_free_inodes_count = PED_CPU_TO_LE32( - EXT2_SUPER_FREE_INODES_COUNT(fs->sb) - - EXT2_SUPER_INODES_PER_GROUP(fs->sb)); - fs->metadirty |= EXT2_META_SB; - - if (fs->opt_safe) - ext2_sync(fs); - - ped_realloc ((void*) &fs->gd, - fs->numgroups * sizeof(struct ext2_group_desc) - + fs->blocksize); - - return 1; -} - -static int ext2_grow_group(struct ext2_fs *fs, blk_t newsize) -{ - int group; - blk_t groupoff; - blk_t gblocks; - blk_t i; - - if (fs->opt_verbose) - fputs ("ext2_grow_group\n", stderr); - - group = fs->numgroups - 1; - groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff; - - if (fs->opt_debug) - { - if (newsize < gblocks) - { - fputs ("ext2_grow_group: called to shrink group!\n", - stderr); - - return 0; - } - - if (gblocks == newsize) - { - fputs ("ext2_grow_group: nothing to do!\n", stderr); - return 0; - } - } - - for (i=gblocks;isb.s_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_BLOCKS_COUNT(fs->sb) + newsize - gblocks); - fs->metadirty |= EXT2_META_SB; - - if (fs->opt_safe) - ext2_sync(fs); - - return 1; -} - -static int ext2_shrink_group(struct ext2_fs *fs, blk_t newsize) -{ - blk_t admin; - int group; - blk_t groupoff; - blk_t gblocks; - blk_t i; - - if (fs->opt_verbose) - fputs ("ext2_shrink_group\n", stderr); - - group = fs->numgroups - 1; - - admin = fs->adminblocks; - if (!ext2_is_group_sparse(fs, group)) - admin -= fs->gdblocks + 1; - - groupoff = group * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb) - + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - gblocks = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - groupoff; - - if (fs->opt_debug) - { - if (newsize < admin) - { - fprintf(stderr, - "ext2_shrink_group: cant shrink a group " - "to %i blocks\n", newsize); - - return 0; - } - - if (newsize > gblocks) - { - fputs ("ext2_shrink_group: called to grow group!\n", - stderr); - - return 0; - } - - if (gblocks == newsize) - { - fputs ("ext2_shrink_group: nothing to do!\n", - stderr); - - return 0; - } - } - - for (i=newsize;iopt_debug && ext2_get_block_state(fs, groupoff + i)) - { - fprintf(stderr, - "error: block relocator should have relocated " - "%i\n", - groupoff + i); - - return 0; - } - - ext2_set_block_state(fs, groupoff + i, 1, 0); - } - - i = gblocks - newsize; - fs->sb.s_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_BLOCKS_COUNT(fs->sb) - i); - fs->sb.s_free_blocks_count = PED_CPU_TO_LE32( - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) - i); - fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16( - EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) - i); - - fs->metadirty |= EXT2_META_SB | EXT2_META_GD; - - if (fs->opt_safe) - ext2_sync(fs); - - return 1; -} - - - - - - -static int ext2_grow_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer) -{ - blk_t diff; - blk_t sizelast; - blk_t origsize = EXT2_SUPER_BLOCKS_COUNT(fs->sb); - - if (fs->opt_verbose) - fputs ("ext2_grow_fs\n", stderr); - - if (!ext2_block_relocate(fs, newsize)) - return 0; - - if (!ext2_metadata_push(fs, newsize)) - return 0; - - diff = newsize - EXT2_SUPER_BLOCKS_COUNT(fs->sb); - sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - - (fs->numgroups-1) * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - if (sizelast != EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - { - blk_t growto; - - growto = sizelast + diff; - if (growto > EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)) - growto = EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - if (!ext2_grow_group(fs, growto)) - return 0; - - diff -= growto - sizelast; - } - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("adding groups")); - - while (diff) - { - ped_timer_update (timer, - 1.0 - 1.0 * diff / (newsize - origsize)); - - sizelast = PED_MIN(diff, EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - if (!ext2_add_group(fs, sizelast)) - return 0; - - diff -= sizelast; - } - - ped_timer_update (timer, 1.0); - - return 1; -} - -static int ext2_shrink_fs(struct ext2_fs *fs, blk_t newsize, - PedTimer* timer) -{ - blk_t origsize = EXT2_SUPER_BLOCKS_COUNT (fs->sb); - blk_t diff; - int newgroups; - blk_t sizelast; - - if (fs->opt_verbose) - fputs ("ext2_shrink_fs\n", stderr); - - newgroups = ped_div_round_up (newsize - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb), - EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - if (EXT2_SUPER_BLOCKS_COUNT(fs->sb) - - EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) > newsize) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Your file system is too full to resize it to %i " - "blocks. Sorry."), newsize); - return 0; - } - - if (EXT2_SUPER_INODES_COUNT(fs->sb) - - EXT2_SUPER_FREE_INODES_COUNT(fs->sb) - > newgroups * EXT2_SUPER_INODES_PER_GROUP(fs->sb)) - { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Your file system has too many occupied inodes to " - "resize it to %i blocks. Sorry."), newsize); - return 0; - } - - if (!ext2_inode_relocate(fs, newgroups)) - return 0; - - if (!ext2_block_relocate(fs, newsize)) - return 0; - - diff = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - newsize; - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("shrinking")); - - while (diff > 0) - { - ped_timer_update (timer, - 1.0 - 1.0 * diff / (origsize - newsize)); - - sizelast = EXT2_SUPER_BLOCKS_COUNT(fs->sb) - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - - (fs->numgroups - 1) - * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - - if (diff < sizelast) - { - if (!ext2_shrink_group(fs, sizelast - diff)) - return 0; - - diff = 0; - } - else - { - if (!ext2_del_group(fs)) - return 0; - - diff -= sizelast; - } - } - - ped_timer_update (timer, 1.0); - - return 1; -} - -int ext2_determine_itoffset(struct ext2_fs *fs) -{ - int i; - - fs->itoffset = EXT2_GROUP_INODE_TABLE(fs->gd[0]) - - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); - - /*PED_DEBUG (0x20, "itoffset is %d", fs->itoffset); - - PED_DEBUG (0x20, "walking %d groups", fs->numgroups);*/ - - for (i=0;inumgroups;i++) - { - blk_t start; - blk_t bb; - blk_t ib; - blk_t it; - - start = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) - + (i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)); - it = start + fs->itoffset; - - /*PED_DEBUG (0x21, "start = %d, it = %d", start, it);*/ - - if (ext2_is_group_sparse(fs, i)) - { - /*PED_DEBUG (0x21, "%d has a superblock copy", i);*/ - bb = it - 2; - ib = it - 1; - } - else - { - /*PED_DEBUG (0x21, "%d doesn't have a superblock copy", - i);*/ - bb = start; - ib = start + 1; - } - - if (EXT2_GROUP_BLOCK_BITMAP(fs->gd[i]) != bb || - EXT2_GROUP_INODE_BITMAP(fs->gd[i]) != ib || - EXT2_GROUP_INODE_TABLE(fs->gd[i]) != it) - { - /* ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("This ext2 file system has a rather strange layout! " - "Parted can't resize this (yet)."));*/ - - /* PED_DEBUG (0x21, "calculated block bitmap to be %d, " - "but fs says %d.", bb, - EXT2_GROUP_BLOCK_BITMAP(fs->gd[i])); - PED_DEBUG (0x21, "calculated inode bitmap to be %d, " - "but fs says %d.", ib, - EXT2_GROUP_INODE_BITMAP(fs->gd[i])); - PED_DEBUG (0x21, "calculated inode table to be %d, " - "but fs says %d.", it, - EXT2_GROUP_INODE_TABLE(fs->gd[i]));*/ - - return 0; - } - } - - return 1; -} - -int ext2_resize_fs(struct ext2_fs *fs, blk_t newsize, PedTimer* timer) -{ - blk_t residue; - int status; - - if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS) - { - ped_exception_throw ( - PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, - _("File system has errors! You should run e2fsck.")); - return 0; - } - - if (!(EXT2_SUPER_STATE(fs->sb) & EXT2_VALID_FS)) - { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system was not cleanly unmounted! " - "You should run e2fsck.")); - return 0; - } - - if (EXT2_SUPER_FEATURE_COMPAT(fs->sb) - & EXT2_FEATURE_COMPAT_HAS_DIR_INDEX) { - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL, - _("The file system has the 'dir_index' feature " - "enabled. Parted can only resize the file system " - "if it disables this feature. You can enable it " - "later by running 'tune2fs -O dir_index DEVICE' " - "and then 'e2fsck -fD DEVICE'.")) - != PED_EXCEPTION_IGNORE) - return 0; - fs->sb.s_feature_compat - = PED_CPU_TO_LE32(EXT2_SUPER_FEATURE_COMPAT(fs->sb) - & ~EXT2_FEATURE_COMPAT_HAS_DIR_INDEX); - fs->metadirty |= EXT2_META_SB; - } - - if (!ext2_determine_itoffset(fs) && ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK_CANCEL, - _("A resize operation on this file system will " - "use EXPERIMENTAL code\n" - "that MAY CORRUPT it (although no one has " - "reported any such damage yet).\n" - "You should at least backup your data first, " - "and run 'e2fsck -f' afterwards.")) - == PED_EXCEPTION_CANCEL) - { - return 0; - } - - if (fs->opt_verbose) - fputs ("ext2_resize_fs\n", stderr); - - residue = (newsize - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) - % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb); - if (residue && residue <= fs->adminblocks) - newsize -= residue; - - if (newsize == EXT2_SUPER_BLOCKS_COUNT(fs->sb)) - return 1; - - fs->relocator_pool - = (unsigned char *)ped_malloc(ext2_relocator_pool_size << 10); - if (!fs->relocator_pool) - return 0; - fs->relocator_pool_end - = fs->relocator_pool + (ext2_relocator_pool_size << 10); - - if (newsize < EXT2_SUPER_BLOCKS_COUNT(fs->sb)) - status = ext2_shrink_fs(fs, newsize, timer); - else - status = ext2_grow_fs(fs, newsize, timer); - - ped_free(fs->relocator_pool); - fs->relocator_pool = NULL; - fs->relocator_pool_end = NULL; - - return status; -} -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/interface.c b/usr/src/lib/libparted/common/libparted/fs/ext2/interface.c deleted file mode 100644 index 043f948de6..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/interface.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - interface.c -- parted binding glue to libext2resize - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* VERSION: libext2resize 1.1.6 (by Lennert) - * merged 1.1.11 changes (by Andrew) - */ - -#include - -#include -#include "ext2.h" -#include "parted_io.h" - -static PedFileSystemType _ext2_type; -static PedFileSystemType _ext3_type; - -struct ext2_dev_handle* ext2_make_dev_handle_from_parted_geometry(PedGeometry* geom); - -static PedGeometry* -_ext2_generic_probe (PedGeometry* geom, int expect_ext3) -{ - struct ext2_super_block sb; - - if (!ped_geometry_read(geom, &sb, 2, 2)) - return NULL; - - if (EXT2_SUPER_MAGIC(sb) == EXT2_SUPER_MAGIC_CONST) { - PedSector block_size = 1 << (EXT2_SUPER_LOG_BLOCK_SIZE(sb) + 1); - PedSector block_count = EXT2_SUPER_BLOCKS_COUNT(sb); - PedSector group_blocks = EXT2_SUPER_BLOCKS_PER_GROUP(sb); - PedSector group_nr = EXT2_SUPER_BLOCK_GROUP_NR(sb); - PedSector first_data_block = EXT2_SUPER_FIRST_DATA_BLOCK(sb); - int version = EXT2_SUPER_REV_LEVEL(sb); - int is_ext3 = (EXT2_SUPER_FEATURE_COMPAT(sb) - & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0; - - if (expect_ext3 != is_ext3) - return NULL; - - if (version > 0 && group_nr > 0) { - PedSector start; - PedGeometry probe_geom; - - start = geom->start - - group_blocks * group_nr - - first_data_block; - - if (start < 0) - return NULL; - ped_geometry_init (&probe_geom, geom->dev, - start, block_count * block_size); - return _ext2_generic_probe (&probe_geom, expect_ext3); - } else { - return ped_geometry_new (geom->dev, geom->start, - block_count * block_size); - } - } - return NULL; -} - -static PedGeometry* -_ext2_probe (PedGeometry* geom) -{ - return _ext2_generic_probe (geom, 0); -} - -static PedGeometry* -_ext3_probe (PedGeometry* geom) -{ - return _ext2_generic_probe (geom, 1); -} - -#ifndef DISCOVER_ONLY -static int -_ext2_clobber (PedGeometry* geom) -{ - struct ext2_super_block sb; - - if (!ped_geometry_read(geom, &sb, 2, 2)) - return 0; - if (EXT2_SUPER_MAGIC(sb) != EXT2_SUPER_MAGIC_CONST) - return 1; - - sb.s_magic = 0; - return ped_geometry_write(geom, &sb, 2, 2); -} - -static PedFileSystem* -_ext2_open (PedGeometry* geom) -{ - PedFileSystem* fs; - struct ext2_fs* fs_info; - struct ext2_dev_handle* handle; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto error; - - fs->type = &_ext2_type; - fs->geom = ped_geometry_duplicate (geom); - fs->checked = 1; - - handle = ext2_make_dev_handle_from_parted_geometry(fs->geom); - if (!handle) goto error_free_fs; - - fs_info = (struct ext2_fs*) ext2_open(handle, 0); - if (!fs_info) goto error_free_handle; - - fs->type_specific = (void*) fs_info; - fs_info->opt_verbose = 0; - - return fs; - -error_free_handle: - ext2_destroy_dev_handle(handle); -error_free_fs: - ped_free(fs); -error: - return NULL; -} - -static PedFileSystem* -_ext2_create (PedGeometry* geom, PedTimer* timer) -{ - PedFileSystem* fs; - struct ext2_fs* fs_info; - struct ext2_dev_handle* handle; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto error; - - fs->type = &_ext2_type; - fs->geom = ped_geometry_duplicate (geom); - - handle = ext2_make_dev_handle_from_parted_geometry(fs->geom); - if (!handle) goto error_free_fs; - - fs_info = ext2_mkfs (handle, 0, 0, 0, 0, -1, -1, timer); - if (!fs_info) goto error_free_handle; - - fs->type_specific = (void*) fs_info; - fs_info->opt_verbose = 0; - - return fs; - -error_free_handle: - ext2_destroy_dev_handle(handle); -error_free_fs: - ped_free(fs); -error: - return NULL; -} - -static int -_ext2_close (PedFileSystem *fs) -{ - struct ext2_dev_handle* handle; - - handle = ((struct ext2_fs*)fs->type_specific)->devhandle; - ext2_close(fs->type_specific); - ext2_destroy_dev_handle(handle); - - ped_free(fs); - return 1; -} - -static int -_ext2_check (PedFileSystem *fs, PedTimer* timer) -{ - ped_exception_throw (PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, - _("The ext2 file system passed a basic check. For a more " - "comprehensive check, use the e2fsck program.")); - return 1; -} - -static int -_ext2_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - struct ext2_fs* f; - PedSector old_length = fs->geom->length; - - PED_ASSERT (fs->geom->dev == geom->dev, return 0); - - if (fs->geom->start != geom->start) - { - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Sorry, can't move the start of ext2 partitions yet!")); - return 0; - } - - geom->dev->boot_dirty = 1; - - f = (struct ext2_fs *) fs->type_specific; - -/* ensure that the geometry contains the new and old geometry */ - if (old_length > geom->length) { - if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9), - timer)) - goto error; - - fs->geom->length = geom->length; - fs->geom->end = fs->geom->start + geom->length - 1; - } else { - fs->geom->length = geom->length; - fs->geom->end = fs->geom->start + geom->length - 1; - - if (!ext2_resize_fs(f, geom->length >> (f->logsize - 9), - timer)) - goto error; - } - return 1; - -error: - return 0; -} - -static PedConstraint* -_ext2_get_create_constraint (const PedDevice* dev) -{ - PedGeometry full_dev; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - 64, dev->length); -} - -static PedConstraint* -_ext2_get_resize_constraint (const PedFileSystem* fs) -{ - struct ext2_fs* f = (struct ext2_fs *) fs->type_specific; - PedDevice* dev = fs->geom->dev; - PedAlignment start_align; - PedGeometry start_sector; - PedGeometry full_dev; - PedSector min_size; - - if (!ped_alignment_init (&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1)) - return NULL; - min_size = (EXT2_SUPER_BLOCKS_COUNT(f->sb) - - EXT2_SUPER_FREE_BLOCKS_COUNT(f->sb)) - * (f->blocksize / dev->sector_size); - - return ped_constraint_new (&start_align, ped_alignment_any, - &start_sector, &full_dev, min_size, - dev->length); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps _ext2_ops = { - .probe = _ext2_probe, -#ifndef DISCOVER_ONLY - .clobber = _ext2_clobber, - .open = _ext2_open, - .create = _ext2_create, - .close = _ext2_close, - .check = _ext2_check, - .resize = _ext2_resize, - .copy = NULL, - .get_create_constraint = _ext2_get_create_constraint, - .get_copy_constraint = NULL, - .get_resize_constraint = _ext2_get_resize_constraint -#else /* !DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -#endif /* !DISCOVER_ONLY */ -}; - -static PedFileSystemOps _ext3_ops = { - .probe = _ext3_probe, -#ifndef DISCOVER_ONLY - .clobber = _ext2_clobber, - .open = _ext2_open, - .create = NULL, - .close = _ext2_close, - .check = _ext2_check, - .resize = _ext2_resize, - .copy = NULL, - .get_create_constraint = _ext2_get_create_constraint, - .get_copy_constraint = NULL, - .get_resize_constraint = _ext2_get_resize_constraint -#else /* !DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_copy_constraint = NULL, - .get_resize_constraint = NULL -#endif /* !DISCOVER_ONLY */ -}; - -#define EXT23_BLOCK_SIZES ((int[6]){512, 1024, 2048, 4096, 8192, 0}) - -static PedFileSystemType _ext2_type = { - .next = NULL, - .ops = &_ext2_ops, - .name = "ext2", - .block_sizes = EXT23_BLOCK_SIZES -}; - -static PedFileSystemType _ext3_type = { - .next = NULL, - .ops = &_ext3_ops, - .name = "ext3", - .block_sizes = EXT23_BLOCK_SIZES -}; - -void ped_file_system_ext2_init () -{ - ped_file_system_type_register (&_ext2_type); - ped_file_system_type_register (&_ext3_type); -} - -void ped_file_system_ext2_done () -{ - ped_file_system_type_unregister (&_ext2_type); - ped_file_system_type_unregister (&_ext3_type); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.c b/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.c deleted file mode 100644 index 7018cde022..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - parted_io.c -- parted I/O code interface for libext2resize - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -#include -#include -#include -#include "ext2.h" - -/* pseudo-header.... */ - -loff_t llseek(unsigned int fd, loff_t offset, unsigned int whence); - -struct my_cookie -{ - int logsize; - PedGeometry* geom; -}; - -/* ...then this must be pseudo-code :-) */ - -static int do_close (void *cookie); -static int do_sync (void *cookie); -static blk_t do_get_size (void *cookie); -static int do_read (void *cookie, void *ptr, blk_t block, blk_t numblocks); -static int do_set_blocksize(void *cookie, int logsize); -static int do_write (void *cookie, void *ptr, blk_t block, blk_t numblocks); - -struct ext2_dev_ops ops = -{ - .close = do_close, - .get_size = do_get_size, - .read = do_read, - .set_blocksize = do_set_blocksize, - .sync = do_sync, - .write = do_write -}; - - - -static int do_close(void *cookie) -{ - struct my_cookie *monster = cookie; - - return ped_geometry_sync(monster->geom); -} - -static int do_sync(void *cookie) -{ - struct my_cookie *monster = cookie; - - return ped_geometry_sync(monster->geom); -} - -static blk_t do_get_size(void *cookie) -{ - struct my_cookie *monster = cookie; - - return monster->geom->length >> (monster->logsize - 9); -} - -static int do_read(void *cookie, void *ptr, blk_t block, blk_t num) -{ - struct my_cookie *monster = cookie; - - return ped_geometry_read(monster->geom, ptr, block << (monster->logsize - 9), num << (monster->logsize - 9)); -} - -static int do_set_blocksize(void *cookie, int logsize) -{ - struct my_cookie *monster = cookie; - - monster->logsize = logsize; - return 1; -} - -static int do_write(void *cookie, void *ptr, blk_t block, blk_t num) -{ - struct my_cookie *monster = cookie; - - return ped_geometry_write(monster->geom, ptr, - block << (monster->logsize - 9), - num << (monster->logsize - 9)); -} - - -struct ext2_dev_handle *ext2_make_dev_handle_from_parted_geometry(PedGeometry* geom) -{ - struct ext2_dev_handle *dh; - struct my_cookie *monster; - - if ((dh = ped_malloc(sizeof(struct ext2_dev_handle))) == NULL) - goto error; - - if ((monster = ped_malloc(sizeof(struct my_cookie))) == NULL) - goto error_free_dh; - - dh->ops = &ops; - dh->cookie = monster; - monster->logsize = 9; - monster->geom = geom; - - return dh; - -error_free_dh: - ped_free(dh); -error: - return NULL; -} - -void ext2_destroy_dev_handle(struct ext2_dev_handle *handle) -{ - ped_geometry_destroy(((struct my_cookie *)handle->cookie)->geom); - ped_free(handle->cookie); - ped_free(handle); -} -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.h b/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.h deleted file mode 100644 index a860b71d24..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - parted_io.h - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _PARTED_IO_H -#define _PARTED_IO_H - -#include "ext2.h" - -void ext2_destroy_dev_handle(struct ext2_dev_handle *handle); - -#endif - diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/tune.c b/usr/src/lib/libparted/common/libparted/fs/ext2/tune.c deleted file mode 100644 index 258d86ed07..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/tune.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - tune.c -- tuneable stuff - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#ifndef DISCOVER_ONLY - -/* - * maybe i'll make this all command-line configurable one day - */ - -/* The size of the buffer cache in kilobytes. Note that this is only - the actual buffer memory. On top of this amount additional memory - will be allocated for buffer cache bookkeeping. */ -int ext2_buffer_cache_pool_size = 512; - -/* The size of the buffer cache hash table (log2 of # of buckets). */ -int ext2_hash_bits = 8; - -/* The block/inode relocator pool size in kilobytes. Make this as big - as you can. The smaller this is, the more disk I/O is required for - doing relocations. */ -int ext2_relocator_pool_size = 4096; -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/ext2/tune.h b/usr/src/lib/libparted/common/libparted/fs/ext2/tune.h deleted file mode 100644 index 27c526fc17..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ext2/tune.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - tune.h -- ext2 tunables header - Copyright (C) 1998-2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _TUNE_H -#define _TUNE_H - -#define MAXCONT 256 - -extern int ext2_buffer_cache_pool_size; -extern int ext2_hash_bits; -extern int ext2_max_groups; -extern int ext2_relocator_pool_size; - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.c b/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.c deleted file mode 100644 index 2bed1fd970..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" - -#include -#include -#include -#include -#include -#include -#include - -/* Reads in the boot sector (superblock), and does a minimum of sanity - * checking. The goals are: - * - to detect fat file systems, even if they are damaged [i.e. not - * return an error / throw an exception] - * - to fail detection if there's not enough information for - * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero) - */ -int -fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom) -{ - PED_ASSERT (bs != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - - if (!ped_geometry_read (geom, bs, 0, 1)) - return 0; - - if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid signature for a FAT " - "file system.")); - return 0; - } - - if (!bs->system_id[0]) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid signature for a FAT " - "file system.")); - return 0; - } - - if (!bs->sector_size - || PED_LE16_TO_CPU (bs->sector_size) % PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid sector size for a FAT " - "file system.")); - return 0; - } - - if (!bs->cluster_size) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid cluster size for a FAT " - "file system.")); - return 0; - } - - if (!bs->reserved) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid number of reserved " - "sectors for a FAT file system.")); - return 0; - } - - if (bs->fats < 1 || bs->fats > 4) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("File system has an invalid number of FATs.")); - return 0; - } - - return 1; -} - -/* - Don't trust the FAT12, FAT16 or FAT32 label string. - */ -FatType -fat_boot_sector_probe_type (const FatBootSector* bs, const PedGeometry* geom) -{ - PedSector logical_sector_size; - PedSector first_cluster_sector; - FatCluster cluster_count; - - if (!PED_LE16_TO_CPU (bs->dir_entries)) - return FAT_TYPE_FAT32; - - logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512; - - first_cluster_sector - = PED_LE16_TO_CPU (bs->reserved) * logical_sector_size - + 2 * PED_LE16_TO_CPU (bs->fat_length) * logical_sector_size - + PED_LE16_TO_CPU (bs->dir_entries) - / (512 / sizeof (FatDirEntry)); - cluster_count = (geom->length - first_cluster_sector) - / bs->cluster_size / logical_sector_size; - if (cluster_count > MAX_FAT12_CLUSTERS) - return FAT_TYPE_FAT16; - else - return FAT_TYPE_FAT12; -} - -/* Analyses the boot sector, and sticks appropriate numbers in - fs->type_specific. - - Note: you need to subtract (2 * cluster_sectors) off cluster offset, - because the first cluster is number 2. (0 and 1 are not real clusters, - and referencing them is a bug) - */ -int -fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - int fat_entry_size; - - PED_ASSERT (bs != NULL, return 0); - - if (PED_LE16_TO_CPU (bs->sector_size) != 512) { - if (ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_IGNORE_CANCEL, - _("This file system has a logical sector size of %d. " - "GNU Parted is known not to work properly with sector " - "sizes other than 512 bytes."), - (int) PED_LE16_TO_CPU (bs->sector_size)) - != PED_EXCEPTION_IGNORE) - return 0; - } - - fs_info->logical_sector_size = PED_LE16_TO_CPU (bs->sector_size) / 512; - - fs_info->sectors_per_track = PED_LE16_TO_CPU (bs->secs_track); - fs_info->heads = PED_LE16_TO_CPU (bs->heads); - if (fs_info->sectors_per_track < 1 || fs_info->sectors_per_track > 63 - || fs_info->heads < 1 || fs_info->heads > 255) { - PedCHSGeometry* bios_geom = &fs->geom->dev->bios_geom; - int cyl_count = 0; - - if (fs_info->heads > 0 && fs_info->sectors_per_track > 0) - cyl_count = fs->geom->dev->length / fs_info->heads - / fs_info->sectors_per_track; - - switch (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX + PED_EXCEPTION_IGNORE - + PED_EXCEPTION_CANCEL, - _("The file system's CHS geometry is (%d, %d, %d), " - "which is invalid. The partition table's CHS " - "geometry is (%d, %d, %d). If you select Ignore, " - "the file system's CHS geometry will be left " - "unchanged. If you select Fix, the file system's " - "CHS geometry will be set to match the partition " - "table's CHS geometry."), - cyl_count, fs_info->heads, fs_info->sectors_per_track, - bios_geom->cylinders, bios_geom->heads, - bios_geom->sectors)) { - - case PED_EXCEPTION_FIX: - fs_info->sectors_per_track = bios_geom->sectors; - fs_info->heads = bios_geom->heads; - bs->secs_track - = PED_CPU_TO_LE16 (fs_info->sectors_per_track); - bs->heads = PED_CPU_TO_LE16 (fs_info->heads); - if (!fat_boot_sector_write (bs, fs)) - return 0; - break; - - case PED_EXCEPTION_CANCEL: - return 0; - - case PED_EXCEPTION_IGNORE: - break; - - default: - break; - } - } - - if (bs->sectors) - fs_info->sector_count = PED_LE16_TO_CPU (bs->sectors) - * fs_info->logical_sector_size; - else - fs_info->sector_count = PED_LE32_TO_CPU (bs->sector_count) - * fs_info->logical_sector_size; - - fs_info->fat_table_count = bs->fats; - fs_info->root_dir_entry_count = PED_LE16_TO_CPU (bs->dir_entries); - fs_info->fat_offset = PED_LE16_TO_CPU (bs->reserved) - * fs_info->logical_sector_size; - fs_info->cluster_sectors = bs->cluster_size - * fs_info->logical_sector_size; - fs_info->cluster_size = fs_info->cluster_sectors * 512; - - if (fs_info->logical_sector_size == 0) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("FAT boot sector says logical sector size is 0. " - "This is weird. ")); - return 0; - } - if (fs_info->fat_table_count == 0) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("FAT boot sector says there are no FAT tables. This " - "is weird. ")); - return 0; - } - if (fs_info->cluster_sectors == 0) { - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("FAT boot sector says clusters are 0 sectors. This " - "is weird. ")); - return 0; - } - - fs_info->fat_type = fat_boot_sector_probe_type (bs, fs->geom); - if (fs_info->fat_type == FAT_TYPE_FAT12) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("File system is FAT12, which is unsupported.")); - return 0; - } - if (fs_info->fat_type == FAT_TYPE_FAT16) { - fs_info->fat_sectors = PED_LE16_TO_CPU (bs->fat_length) - * fs_info->logical_sector_size; - fs_info->serial_number - = PED_LE32_TO_CPU (bs->u.fat16.serial_number); - fs_info->root_cluster = 0; - fs_info->root_dir_offset - = fs_info->fat_offset - + fs_info->fat_sectors * fs_info->fat_table_count; - fs_info->root_dir_sector_count - = fs_info->root_dir_entry_count * sizeof (FatDirEntry) - / (512 * fs_info->logical_sector_size); - fs_info->cluster_offset - = fs_info->root_dir_offset - + fs_info->root_dir_sector_count; - } - if (fs_info->fat_type == FAT_TYPE_FAT32) { - fs_info->fat_sectors = PED_LE32_TO_CPU (bs->u.fat32.fat_length) - * fs_info->logical_sector_size; - fs_info->serial_number - = PED_LE32_TO_CPU (bs->u.fat32.serial_number); - fs_info->info_sector_offset - = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.info_sector) - * fs_info->logical_sector_size; - fs_info->boot_sector_backup_offset - = PED_LE16_TO_CPU (fs_info->boot_sector.u.fat32.backup_sector) - * fs_info->logical_sector_size; - fs_info->root_cluster - = PED_LE32_TO_CPU (bs->u.fat32.root_dir_cluster); - fs_info->root_dir_offset = 0; - fs_info->root_dir_sector_count = 0; - fs_info->cluster_offset - = fs_info->fat_offset - + fs_info->fat_sectors * fs_info->fat_table_count; - } - - fs_info->cluster_count - = (fs_info->sector_count - fs_info->cluster_offset) - / fs_info->cluster_sectors; - - fat_entry_size = fat_table_entry_size (fs_info->fat_type); - if (fs_info->cluster_count + 2 - > fs_info->fat_sectors * 512 / fat_entry_size) - fs_info->cluster_count - = fs_info->fat_sectors * 512 / fat_entry_size - 2; - - fs_info->dir_entries_per_cluster - = fs_info->cluster_size / sizeof (FatDirEntry); - return 1; -} - -#ifndef DISCOVER_ONLY -int -fat_boot_sector_set_boot_code (FatBootSector* bs) -{ - PED_ASSERT (bs != NULL, return 0); - - memset (bs, 0, 512); - memcpy (bs->boot_jump, FAT_BOOT_JUMP, 3); - memcpy (bs->u.fat32.boot_code, FAT_BOOT_CODE, FAT_BOOT_CODE_LENGTH); - return 1; -} - -int -fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (bs != NULL, return 0); - - memcpy (bs->system_id, "MSWIN4.1", 8); - bs->sector_size = PED_CPU_TO_LE16 (fs_info->logical_sector_size * 512); - bs->cluster_size = fs_info->cluster_sectors - / fs_info->logical_sector_size; - bs->reserved = PED_CPU_TO_LE16 (fs_info->fat_offset - / fs_info->logical_sector_size); - bs->fats = fs_info->fat_table_count; - - bs->dir_entries = (fs_info->fat_type == FAT_TYPE_FAT16) - ? PED_CPU_TO_LE16 (fs_info->root_dir_entry_count) - : 0; - - if (fs_info->sector_count / fs_info->logical_sector_size > 0xffff - || fs_info->fat_type == FAT_TYPE_FAT32) { - bs->sectors = 0; - bs->sector_count = PED_CPU_TO_LE32 (fs_info->sector_count - / fs_info->logical_sector_size); - } else { - bs->sectors = PED_CPU_TO_LE16 (fs_info->sector_count - / fs_info->logical_sector_size); - bs->sector_count = 0; - } - - bs->media = 0xf8; - - bs->secs_track = PED_CPU_TO_LE16 (fs_info->sectors_per_track); - bs->heads = PED_CPU_TO_LE16 (fs_info->heads); - bs->hidden = PED_CPU_TO_LE32 (fs->geom->start); - - if (fs_info->fat_type == FAT_TYPE_FAT32) { - bs->fat_length = 0; - bs->u.fat32.fat_length = PED_CPU_TO_LE32 (fs_info->fat_sectors - / fs_info->logical_sector_size); - bs->u.fat32.flags = 0; /* FIXME: what the hell are these? */ - bs->u.fat32.version = 0; /* must be 0, for Win98 bootstrap */ - bs->u.fat32.root_dir_cluster - = PED_CPU_TO_LE32 (fs_info->root_cluster); - bs->u.fat32.info_sector - = PED_CPU_TO_LE16 (fs_info->info_sector_offset - / fs_info->logical_sector_size); - bs->u.fat32.backup_sector - = PED_CPU_TO_LE16 (fs_info->boot_sector_backup_offset - / fs_info->logical_sector_size); - - bs->u.fat32.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */ - - memset (bs->u.fat32.empty_1, 0, 12); - - bs->u.fat32.ext_signature = 0x29; - bs->u.fat32.serial_number - = PED_CPU_TO_LE32 (fs_info->serial_number); - memcpy (bs->u.fat32.volume_name, "NO NAME ", 11); - memcpy (bs->u.fat32.fat_name, "FAT32 ", 8); - } else { - bs->fat_length - = PED_CPU_TO_LE16 (fs_info->fat_sectors - / fs_info->logical_sector_size); - - bs->u.fat16.drive_num = 0x80; /* _ALWAYS_ 0x80. silly DOS */ - - bs->u.fat16.ext_signature = 0x29; - bs->u.fat16.serial_number - = PED_CPU_TO_LE32 (fs_info->serial_number); - memcpy (bs->u.fat16.volume_name, "NO NAME ", 11); - memcpy (bs->u.fat16.fat_name, "FAT16 ", 8); - } - - bs->boot_sign = PED_CPU_TO_LE16 (0xaa55); - - return 1; -} - -int -fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (bs != NULL, return 0); - - if (!ped_geometry_write (fs->geom, bs, 0, 1)) - return 0; - if (fs_info->fat_type == FAT_TYPE_FAT32) { - if (!ped_geometry_write (fs->geom, bs, - fs_info->boot_sector_backup_offset, 1)) - return 0; - } - return ped_geometry_sync (fs->geom); -} - -int -fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - int status; - - PED_ASSERT (is != NULL, return 0); - - if (!ped_geometry_read (fs->geom, is, fs_info->info_sector_offset, 1)) - return 0; - - if (PED_LE32_TO_CPU (is->signature_2) != FAT32_INFO_MAGIC2) { - status = ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The information sector has the wrong " - "signature (%x). Select cancel for now, " - "and send in a bug report. If you're " - "desperate, it's probably safe to ignore."), - PED_LE32_TO_CPU (is->signature_2)); - if (status == PED_EXCEPTION_CANCEL) return 0; - } - return 1; -} - -int -fat_info_sector_generate (FatInfoSector* is, const PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (is != NULL, return 0); - - fat_table_count_stats (fs_info->fat); - - memset (is, 0, 512); - - is->signature_1 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC1); - is->signature_2 = PED_CPU_TO_LE32 (FAT32_INFO_MAGIC2); - is->free_clusters = PED_CPU_TO_LE32 (fs_info->fat->free_cluster_count); - is->next_cluster = PED_CPU_TO_LE32 (fs_info->fat->last_alloc); - is->signature_3 = PED_CPU_TO_LE16 (FAT32_INFO_MAGIC3); - - return 1; -} - -int -fat_info_sector_write (const FatInfoSector* is, PedFileSystem *fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (is != NULL, return 0); - - if (!ped_geometry_write (fs->geom, is, fs_info->info_sector_offset, 1)) - return 0; - return ped_geometry_sync (fs->geom); -} -#endif /* !DISCOVER_ONLY */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.h b/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.h deleted file mode 100644 index 38fc3129e9..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/bootsector.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_FAT_BOOTSECTOR_H -#define PED_FAT_BOOTSECTOR_H - -typedef struct _FatBootSector FatBootSector; -typedef struct _FatInfoSector FatInfoSector; - -#include "fat.h" - -#define FAT32_INFO_MAGIC1 0x41615252 -#define FAT32_INFO_MAGIC2 0x61417272 -#define FAT32_INFO_MAGIC3 0xaa55 - -/* stolen from mkdosfs, by Dave Hudson */ - -#define FAT_BOOT_MESSAGE \ -"This partition does not have an operating system loader installed on it.\n\r"\ -"Press a key to reboot..." - -#define FAT_BOOT_JUMP "\xeb\x58\x90" /* jmp +5a */ - -#define FAT_BOOT_CODE "\x0e" /* push cs */ \ - "\x1f" /* pop ds */ \ - "\xbe\x74\x7e" /* mov si, offset message */ \ - /* write_msg_loop: */ \ - "\xac" /* lodsb */ \ - "\x22\xc0" /* and al, al */ \ - "\x74\x06" /* jz done (+8) */ \ - "\xb4\x0e" /* mov ah, 0x0e */ \ - "\xcd\x10" /* int 0x10 */ \ - "\xeb\xf5" /* jmp write_msg_loop */ \ - /* done: */ \ - "\xb4\x00" /* mov ah, 0x00 */ \ - "\xcd\x16" /* int 0x16 */ \ - "\xb4\x00" /* mov ah, 0x00 */ \ - "\xcd\x19" /* int 0x19 */ \ - "\xeb\xfe" /* jmp +0 - in case int 0x19 */ \ - /* doesn't work */ \ - /* message: */ \ - FAT_BOOT_MESSAGE - -#define FAT_BOOT_CODE_LENGTH 128 - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _FatBootSector { - uint8_t boot_jump[3]; /* 00: Boot strap short or near jump */ - uint8_t system_id[8]; /* 03: system name */ - uint16_t sector_size; /* 0b: bytes per logical sector */ - uint8_t cluster_size; /* 0d: sectors/cluster */ - uint16_t reserved; /* 0e: reserved sectors */ - uint8_t fats; /* 10: number of FATs */ - uint16_t dir_entries; /* 11: number of root directory entries */ - uint16_t sectors; /* 13: if 0, total_sect supersedes */ - uint8_t media; /* 15: media code */ - uint16_t fat_length; /* 16: sectors/FAT for FAT12/16 */ - uint16_t secs_track; /* 18: sectors per track */ - uint16_t heads; /* 1a: number of heads */ - uint32_t hidden; /* 1c: hidden sectors (partition start) */ - uint32_t sector_count; /* 20: no. of sectors (if sectors == 0) */ - - union __attribute__ ((packed)) { - /* FAT16 fields */ - struct __attribute__ ((packed)) { - uint8_t drive_num; /* 24: */ - uint8_t empty_1; /* 25: */ - uint8_t ext_signature; /* 26: always 0x29 */ - uint32_t serial_number; /* 27: */ - uint8_t volume_name [11]; /* 2b: */ - uint8_t fat_name [8]; /* 36: */ - uint8_t boot_code[448]; /* 3f: Boot code (or message) */ - } fat16; - /* FAT32 fields */ - struct __attribute__ ((packed)) { - uint32_t fat_length; /* 24: size of FAT in sectors */ - uint16_t flags; /* 28: bit8: fat mirroring, low4: active fat */ - uint16_t version; /* 2a: minor * 256 + major */ - uint32_t root_dir_cluster; /* 2c: */ - uint16_t info_sector; /* 30: */ - uint16_t backup_sector; /* 32: */ - uint8_t empty_1 [12]; /* 34: */ - uint16_t drive_num; /* 40: */ - uint8_t ext_signature; /* 42: always 0x29 */ - uint32_t serial_number; /* 43: */ - uint8_t volume_name [11]; /* 47: */ - uint8_t fat_name [8]; /* 52: */ - uint8_t boot_code[420]; /* 5a: Boot code (or message) */ - } fat32; - } u; - - uint16_t boot_sign; /* 1fe: always 0xAA55 */ -}; - -struct __attribute__ ((packed)) _FatInfoSector { - uint32_t signature_1; /* should be 0x41615252 */ - uint8_t unused [480]; - uint32_t signature_2; /* should be 0x61417272 */ - uint32_t free_clusters; - uint32_t next_cluster; /* most recently allocated cluster */ - uint8_t unused2 [0xe]; - uint16_t signature_3; /* should be 0xaa55 */ -}; -#ifdef __sun -#pragma pack() -#endif - -int fat_boot_sector_read (FatBootSector* bs, const PedGeometry* geom); -FatType fat_boot_sector_probe_type (const FatBootSector* bs, - const PedGeometry* geom); -int fat_boot_sector_analyse (FatBootSector* bs, PedFileSystem* fs); -int fat_boot_sector_set_boot_code (FatBootSector* bs); -int fat_boot_sector_generate (FatBootSector* bs, const PedFileSystem* fs); -int fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs); - -int fat_info_sector_read (FatInfoSector* is, const PedFileSystem* fs); -int fat_info_sector_generate (FatInfoSector* is, const PedFileSystem* fs); -int fat_info_sector_write (const FatInfoSector* is, PedFileSystem* fs); - -#endif /* PED_FAT_BOOTSECTOR_H */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/calc.c b/usr/src/lib/libparted/common/libparted/fs/fat/calc.c deleted file mode 100644 index e7c2862a8c..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/calc.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" - -#ifndef DISCOVER_ONLY - -/* returns the minimum size of clusters for a given file system type */ -PedSector -fat_min_cluster_size (FatType fat_type) { - switch (fat_type) { - case FAT_TYPE_FAT12: return 1; - case FAT_TYPE_FAT16: return 1024/512; - case FAT_TYPE_FAT32: return 4096/512; - } - return 0; -} - -static PedSector -_smallest_power2_over (PedSector ceiling) -{ - PedSector result = 1; - - while (result < ceiling) - result *= 2; - - return result; -} - -/* returns the minimum size of clusters for a given file system type */ -PedSector -fat_recommend_min_cluster_size (FatType fat_type, PedSector size) { - switch (fat_type) { - case FAT_TYPE_FAT12: return 1; - case FAT_TYPE_FAT16: return fat_min_cluster_size(fat_type); - case FAT_TYPE_FAT32: - return PED_MAX(_smallest_power2_over(size - / MAX_FAT32_CLUSTERS), - fat_min_cluster_size (fat_type)); - } - return 0; -} - -/* returns the maxmimum size of clusters for a given file system type */ -PedSector -fat_max_cluster_size (FatType fat_type) { - switch (fat_type) { - case FAT_TYPE_FAT12: return 1; /* dunno... who cares? */ - case FAT_TYPE_FAT16: return 32768/512; - case FAT_TYPE_FAT32: return 65536/512; - } - return 0; -} - -/* returns the minimum number of clusters for a given file system type */ -FatCluster -fat_min_cluster_count (FatType fat_type) { - switch (fat_type) { - case FAT_TYPE_FAT12: - case FAT_TYPE_FAT16: - return fat_max_cluster_count (fat_type) / 2; - - case FAT_TYPE_FAT32: return 0xfff0; - } - return 0; -} - -/* returns the maximum number of clusters for a given file system type */ -FatCluster -fat_max_cluster_count (FatType fat_type) { - switch (fat_type) { - case FAT_TYPE_FAT12: return 0xff0; - case FAT_TYPE_FAT16: return 0xfff0; - case FAT_TYPE_FAT32: return 0x0ffffff0; - } - return 0; -} - -/* what is this supposed to be? What drugs are M$ on? (Can I have some? :-) */ -PedSector -fat_min_reserved_sector_count (FatType fat_type) -{ - return (fat_type == FAT_TYPE_FAT32) ? 32 : 1; -} - -int -fat_check_resize_geometry (const PedFileSystem* fs, - const PedGeometry* geom, - PedSector new_cluster_sectors, - FatCluster new_cluster_count) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector free_space; - PedSector min_free_space; - PedSector total_space; - PedSector new_total_space; - PedSector dir_space; - - PED_ASSERT (geom != NULL, return 0); - - dir_space = fs_info->total_dir_clusters * fs_info->cluster_sectors; - free_space = fs_info->fat->free_cluster_count - * fs_info->cluster_sectors; - total_space = fs_info->fat->cluster_count * fs_info->cluster_sectors; - new_total_space = new_cluster_count * new_cluster_sectors; - min_free_space = total_space - new_total_space + dir_space; - - PED_ASSERT (new_cluster_count - <= fat_max_cluster_count (FAT_TYPE_FAT32), - return 0); - - if (free_space < min_free_space) { - char* needed = ped_unit_format (geom->dev, min_free_space); - char* have = ped_unit_format (geom->dev, free_space); - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("You need %s of free disk space to shrink this " - "partition to this size. Currently, only %s is " - "free."), - needed, have); - ped_free (needed); - ped_free (have); - return 0; - } - - return 1; -} - - -/******************************************************************************/ - -/* DO NOT EDIT THIS ALGORITHM! - * As far as I can tell, this is the same algorithm used by Microsoft to - * calculate the size of the file allocaion tables, and the number of clusters. - * I have not verified this by dissassembling Microsoft code - I came to this - * conclusion by empirical analysis (i.e. trial and error - this was HORRIBLE). - * - * If you think this code makes no sense, then you are right. I will restrain - * the urge to inflict serious bodily harm on Microsoft people. - */ - -static int -entries_per_sector (FatType fat_type) -{ - switch (fat_type) { - case FAT_TYPE_FAT12: - return 512 * 3 / 2; - case FAT_TYPE_FAT16: - return 512 / 2; - case FAT_TYPE_FAT32: - return 512 / 4; - } - return 0; -} - -static int -calc_sizes (PedSector size, PedSector align, FatType fat_type, - PedSector root_dir_sectors, PedSector cluster_sectors, - FatCluster* out_cluster_count, PedSector* out_fat_size) -{ - PedSector data_fat_space; /* space available to clusters + FAT */ - PedSector fat_space; /* space taken by each FAT */ - PedSector cluster_space; /* space taken by clusters */ - FatCluster cluster_count; - int i; - - PED_ASSERT (out_cluster_count != NULL, return 0); - PED_ASSERT (out_fat_size != NULL, return 0); - - data_fat_space = size - fat_min_reserved_sector_count (fat_type) - - align; - if (fat_type == FAT_TYPE_FAT16) - data_fat_space -= root_dir_sectors; - - fat_space = 0; - for (i = 0; i < 2; i++) { - if (fat_type == FAT_TYPE_FAT32) - cluster_space = data_fat_space - fat_space; - else - cluster_space = data_fat_space - 2 * fat_space; - - cluster_count = cluster_space / cluster_sectors; - fat_space = ped_div_round_up (cluster_count + 2, - entries_per_sector (fat_type)); - } - - cluster_space = data_fat_space - 2 * fat_space; - cluster_count = cluster_space / cluster_sectors; - - /* looks like this should be part of the loop condition? - * Need to build the Big Table TM again to check - */ - if (fat_space < ped_div_round_up (cluster_count + 2, - entries_per_sector (fat_type))) { - fat_space = ped_div_round_up (cluster_count + 2, - entries_per_sector (fat_type)); - } - - if (cluster_count > fat_max_cluster_count (fat_type) - || cluster_count < fat_min_cluster_count (fat_type)) - return 0; - - *out_cluster_count = cluster_count; - *out_fat_size = fat_space; - - return 1; -} - -/****************************************************************************/ - -int -fat_calc_sizes (PedSector size, PedSector align, FatType fat_type, - PedSector root_dir_sectors, - PedSector* out_cluster_sectors, FatCluster* out_cluster_count, - PedSector* out_fat_size) -{ - PedSector cluster_sectors; - - PED_ASSERT (out_cluster_sectors != NULL, return 0); - PED_ASSERT (out_cluster_count != NULL, return 0); - PED_ASSERT (out_fat_size != NULL, return 0); - - for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size); - cluster_sectors <= fat_max_cluster_size (fat_type); - cluster_sectors *= 2) { - if (calc_sizes (size, align, fat_type, root_dir_sectors, - cluster_sectors, - out_cluster_count, out_fat_size)) { - *out_cluster_sectors = cluster_sectors; - return 1; - } - } - - for (cluster_sectors = fat_recommend_min_cluster_size (fat_type, size); - cluster_sectors >= fat_min_cluster_size (fat_type); - cluster_sectors /= 2) { - if (calc_sizes (size, align, fat_type, root_dir_sectors, - cluster_sectors, - out_cluster_count, out_fat_size)) { - *out_cluster_sectors = cluster_sectors; - return 1; - } - } - - /* only make the cluster size really small (<4k) if a bigger one is - * isn't possible. Windows never makes FS's like this, but it - * seems to work... (do more tests!) - */ - for (cluster_sectors = 4; cluster_sectors > 0; cluster_sectors /= 2) { - if (calc_sizes (size, align, fat_type, root_dir_sectors, - cluster_sectors, - out_cluster_count, out_fat_size)) { - *out_cluster_sectors = cluster_sectors; - return 1; - } - } - - return 0; -} - -/* Same as fat_calc_sizes, except it only attempts to match a particular - * cluster size. This is useful, because the FAT resizer can only shrink the - * cluster size. - */ -int -fat_calc_resize_sizes ( - const PedGeometry* geom, - PedSector align, - FatType fat_type, - PedSector root_dir_sectors, - PedSector cluster_sectors, - PedSector* out_cluster_sectors, - FatCluster* out_cluster_count, - PedSector* out_fat_size) -{ - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (out_cluster_sectors != NULL, return 0); - PED_ASSERT (out_cluster_count != NULL, return 0); - PED_ASSERT (out_fat_size != NULL, return 0); - -/* libparted can only reduce the cluster size at this point */ - for (*out_cluster_sectors = cluster_sectors; - *out_cluster_sectors >= fat_min_cluster_size (fat_type); - *out_cluster_sectors /= 2) { - if (calc_sizes (geom->length, align, fat_type, root_dir_sectors, - *out_cluster_sectors, - out_cluster_count, out_fat_size)) - return 1; - } - return 0; -} - -/* Calculates the number of sectors needed to be added to cluster_offset, - to make the cluster on the new file system match up with the ones - on the old file system. - However, some space is reserved by fat_calc_resize_sizes() and - friends, to allow room for this space. If too much of this space is left - over, everyone will complain, so we have to be greedy, and use it all up... - */ -PedSector -fat_calc_align_sectors (const PedFileSystem* new_fs, - const PedFileSystem* old_fs) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs); - PedSector raw_old_meta_data_end; - PedSector new_meta_data_size; - PedSector min_new_meta_data_end; - PedSector new_data_size; - PedSector new_clusters_size; - PedSector align; - - new_meta_data_size - = fat_min_reserved_sector_count (new_fs_info->fat_type) - + new_fs_info->fat_sectors * 2; - - if (new_fs_info->fat_type == FAT_TYPE_FAT16) - new_meta_data_size += new_fs_info->root_dir_sector_count; - - raw_old_meta_data_end = old_fs->geom->start - + old_fs_info->cluster_offset; - - min_new_meta_data_end = new_fs->geom->start + new_meta_data_size; - - if (raw_old_meta_data_end > min_new_meta_data_end) - align = (raw_old_meta_data_end - min_new_meta_data_end) - % new_fs_info->cluster_sectors; - else - align = (new_fs_info->cluster_sectors - - ( (min_new_meta_data_end - raw_old_meta_data_end) - % new_fs_info->cluster_sectors )) - % new_fs_info->cluster_sectors; - - new_data_size = new_fs->geom->length - new_meta_data_size; - new_clusters_size = new_fs_info->cluster_count - * new_fs_info->cluster_sectors; - - while (new_clusters_size + align + new_fs_info->cluster_sectors - <= new_data_size) - align += new_fs_info->cluster_sectors; - - return align; -} - -int -fat_is_sector_in_clusters (const PedFileSystem* fs, PedSector sector) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - return sector >= fs_info->cluster_offset - && sector < fs_info->cluster_offset - + fs_info->cluster_sectors * fs_info->cluster_count; -} - -FatFragment -fat_cluster_to_frag (const PedFileSystem* fs, FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2, - return 0); - - return (cluster - 2) * fs_info->cluster_frags; -} - -FatCluster -fat_frag_to_cluster (const PedFileSystem* fs, FatFragment frag) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (frag >= 0 && frag < fs_info->frag_count, return 0); - - return frag / fs_info->cluster_frags + 2; -} - -PedSector -fat_frag_to_sector (const PedFileSystem* fs, FatFragment frag) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (frag >= 0 && frag < fs_info->frag_count, return 0); - - return frag * fs_info->frag_sectors + fs_info->cluster_offset; -} - -FatFragment -fat_sector_to_frag (const PedFileSystem* fs, PedSector sector) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (sector >= fs_info->cluster_offset, return 0); - - return (sector - fs_info->cluster_offset) / fs_info->frag_sectors; -} - -PedSector -fat_cluster_to_sector (const PedFileSystem* fs, FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2, - return 0); - - return (cluster - 2) * fs_info->cluster_sectors - + fs_info->cluster_offset; -} - -FatCluster -fat_sector_to_cluster (const PedFileSystem* fs, PedSector sector) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (sector >= fs_info->cluster_offset, return 0); - - return (sector - fs_info->cluster_offset) / fs_info->cluster_sectors - + 2; -} -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/calc.h b/usr/src/lib/libparted/common/libparted/fs/fat/calc.h deleted file mode 100644 index 9af08ebc83..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/calc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_FAT_CALC_H -#define PED_FAT_CALC_H - -extern PedSector fat_min_cluster_size (FatType fat_type); -extern PedSector fat_max_cluster_size (FatType fat_type); -extern FatCluster fat_min_cluster_count (FatType fat_type); -extern FatCluster fat_max_cluster_count (FatType fat_type); - -extern PedSector fat_min_reserved_sector_count (FatType fat_type); - -extern int fat_check_resize_geometry (const PedFileSystem* fs, - const PedGeometry* geom, - PedSector new_cluster_sectors, - FatCluster new_cluster_count); - -extern int fat_calc_sizes (PedSector size, - PedSector align, - FatType fat_type, - PedSector root_dir_sectors, - PedSector* out_cluster_sectors, - FatCluster* out_cluster_count, - PedSector* out_fat_size); - -extern int fat_calc_resize_sizes (const PedGeometry* geom, - PedSector align, - FatType fat_type, - PedSector root_dir_sectors, - PedSector cluster_sectors, - PedSector* out_cluster_sectors, - FatCluster* out_cluster_count, - PedSector* out_fat_size); - -extern PedSector -fat_calc_align_sectors (const PedFileSystem* new_fs, - const PedFileSystem* old_fs); - -extern int -fat_is_sector_in_clusters (const PedFileSystem* fs, PedSector sector); - -extern FatFragment -fat_cluster_to_frag (const PedFileSystem* fs, FatCluster cluster); - -extern FatCluster -fat_frag_to_cluster (const PedFileSystem* fs, FatFragment frag); - -extern PedSector -fat_frag_to_sector (const PedFileSystem* fs, FatFragment frag); - -extern FatFragment -fat_sector_to_frag (const PedFileSystem* fs, PedSector sector); - -extern PedSector -fat_cluster_to_sector (const PedFileSystem* fs, FatCluster cluster); - -extern FatCluster -fat_sector_to_cluster (const PedFileSystem* fs, PedSector sector); - -#endif /* PED_FAT_CALC_H */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.c b/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.c deleted file mode 100644 index f3151fee5e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.c +++ /dev/null @@ -1,424 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include - -#include "fat.h" - -#ifndef DISCOVER_ONLY - -static int -needs_duplicating (const FatOpContext* ctx, FatFragment frag) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatCluster cluster = fat_frag_to_cluster (ctx->old_fs, frag); - FatClusterFlag flag; - - PED_ASSERT (cluster >= 2 && cluster < old_fs_info->cluster_count + 2, - return 0); - - flag = fat_get_fragment_flag (ctx->old_fs, frag); - switch (flag) { - case FAT_FLAG_FREE: - return 0; - - case FAT_FLAG_DIRECTORY: - return 1; - - case FAT_FLAG_FILE: - return fat_op_context_map_static_fragment (ctx, frag) == -1; - - case FAT_FLAG_BAD: - return 0; - } - - return 0; -} - -static int -search_next_fragment (FatOpContext* ctx) -{ - FatSpecific* fs_info = FAT_SPECIFIC (ctx->old_fs); - - for (; ctx->buffer_offset < fs_info->frag_count; ctx->buffer_offset++) { - if (needs_duplicating (ctx, ctx->buffer_offset)) - return 1; - } - return 0; /* all done! */ -} - -static int -read_marked_fragments (FatOpContext* ctx, FatFragment length) -{ - FatSpecific* fs_info = FAT_SPECIFIC (ctx->old_fs); - int status; - FatFragment i; - - ped_exception_fetch_all (); - status = fat_read_fragments (ctx->old_fs, fs_info->buffer, - ctx->buffer_offset, length); - ped_exception_leave_all (); - if (status) - return 1; - - ped_exception_catch (); - -/* something bad happened, so read fragments one by one. (The error may - have occurred on an unused fragment: who cares) */ - for (i = 0; i < length; i++) { - if (ctx->buffer_map [i]) { - if (!fat_read_fragment (ctx->old_fs, - fs_info->buffer + i * fs_info->frag_size, - ctx->buffer_offset + i)) - return 0; - } - } - - return 1; -} - -static int -fetch_fragments (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatFragment fetch_length = 0; - FatFragment frag; - - for (frag = 0; frag < ctx->buffer_frags; frag++) - ctx->buffer_map [frag] = -1; - - for (frag = 0; - frag < ctx->buffer_frags - && ctx->buffer_offset + frag < old_fs_info->frag_count; - frag++) { - if (needs_duplicating (ctx, ctx->buffer_offset + frag)) { - ctx->buffer_map [frag] = 1; - fetch_length = frag + 1; - } - } - - if (!read_marked_fragments (ctx, fetch_length)) - return 0; - - return 1; -} - -/***************************************************************************** - * here starts the write code. All assumes that ctx->buffer_map [first] and - * ctx->buffer_map [last] are occupied by fragments that need to be duplicated. - *****************************************************************************/ - -/* finds the first fragment that is not going to get overwritten (that needs to - get read in) */ -static FatFragment -get_first_underlay (const FatOpContext* ctx, int first, int last) -{ - int old; - FatFragment new; - - PED_ASSERT (first <= last, return 0); - - new = ctx->buffer_map [first]; - for (old = first + 1; old <= last; old++) { - if (ctx->buffer_map [old] == -1) - continue; - new++; - if (ctx->buffer_map [old] != new) - return new; - } - return -1; -} - -/* finds the last fragment that is not going to get overwritten (that needs to - get read in) */ -static FatFragment -get_last_underlay (const FatOpContext* ctx, int first, int last) -{ - int old; - FatFragment new; - - PED_ASSERT (first <= last, return 0); - - new = ctx->buffer_map [last]; - for (old = last - 1; old >= first; old--) { - if (ctx->buffer_map [old] == -1) - continue; - new--; - if (ctx->buffer_map [old] != new) - return new; - } - return -1; -} - -/* "underlay" refers to the "static" fragments, that remain unchanged. - * when writing large chunks at a time, we don't want to clobber these, - * so we read them in, and write them back again. MUCH quicker that way. - */ -static int -quick_group_write_read_underlay (FatOpContext* ctx, int first, int last) -{ - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatFragment first_underlay; - FatFragment last_underlay; - FatFragment underlay_length; - - PED_ASSERT (first <= last, return 0); - - first_underlay = get_first_underlay (ctx, first, last); - if (first_underlay == -1) - return 1; - last_underlay = get_last_underlay (ctx, first, last); - - PED_ASSERT (first_underlay <= last_underlay, return 0); - - underlay_length = last_underlay - first_underlay + 1; - if (!fat_read_fragments (ctx->new_fs, - new_fs_info->buffer - + (first_underlay - ctx->buffer_map [first]) - * new_fs_info->frag_size, - first_underlay, - underlay_length)) - return 0; - return 1; -} - -/* quick_group_write() makes no attempt to recover from errors - just - * does things fast. If there is an error, slow_group_write() is - * called. - * Note: we do syncing writes, to make sure there isn't any - * error writing out. It's rather difficult recovering from errors - * further on. - */ -static int -quick_group_write (FatOpContext* ctx, int first, int last) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - int active_length; - int i; - int offset; - - PED_ASSERT (first <= last, return 0); - - ped_exception_fetch_all (); - if (!quick_group_write_read_underlay (ctx, first, last)) - goto error; - - for (i = first; i <= last; i++) { - if (ctx->buffer_map [i] == -1) - continue; - - offset = ctx->buffer_map [i] - ctx->buffer_map [first]; - memcpy (new_fs_info->buffer + offset * new_fs_info->frag_size, - old_fs_info->buffer + i * new_fs_info->frag_size, - new_fs_info->frag_size); - } - - active_length = ctx->buffer_map [last] - ctx->buffer_map [first] + 1; - if (!fat_write_sync_fragments (ctx->new_fs, new_fs_info->buffer, - ctx->buffer_map [first], active_length)) - goto error; - - ped_exception_leave_all (); - return 1; - -error: - ped_exception_catch (); - ped_exception_leave_all (); - return 0; -} - -/* Writes fragments out, one at a time, avoiding errors on redundant writes - * on damaged parts of the disk we already know about. If there's an error - * on one of the required fragments, it gets marked as bad, and a replacement - * is found. - */ -static int -slow_group_write (FatOpContext* ctx, int first, int last) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - int i; - - PED_ASSERT (first <= last, return 0); - - for (i = first; i <= last; i++) { - if (ctx->buffer_map [i] == -1) - continue; - - while (!fat_write_sync_fragment (ctx->new_fs, - old_fs_info->buffer + i * old_fs_info->frag_size, - ctx->buffer_map [i])) { - fat_table_set_bad (new_fs_info->fat, - ctx->buffer_map [i]); - ctx->buffer_map [i] = fat_table_alloc_cluster - (new_fs_info->fat); - if (ctx->buffer_map [i] == 0) - return 0; - } - } - return 1; -} - -static int -update_remap (FatOpContext* ctx, int first, int last) -{ - int i; - - PED_ASSERT (first <= last, return 0); - - for (i = first; i <= last; i++) { - if (ctx->buffer_map [i] == -1) - continue; - ctx->remap [ctx->buffer_offset + i] = ctx->buffer_map [i]; - } - - return 1; -} - -static int -group_write (FatOpContext* ctx, int first, int last) -{ - PED_ASSERT (first <= last, return 0); - - if (!quick_group_write (ctx, first, last)) { - if (!slow_group_write (ctx, first, last)) - return 0; - } - if (!update_remap (ctx, first, last)) - return 0; - return 1; -} - -/* assumes fragment size and new_fs's cluster size are equal */ -static int -write_fragments (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - int group_start; - int group_end = -1; /* shut gcc up! */ - FatFragment mapped_length; - FatFragment i; - FatCluster new_cluster; - - PED_ASSERT (ctx->buffer_offset < old_fs_info->frag_count, return 0); - - group_start = -1; - for (i = 0; i < ctx->buffer_frags; i++) { - if (ctx->buffer_map [i] == -1) - continue; - - ctx->frags_duped++; - - new_cluster = fat_table_alloc_cluster (new_fs_info->fat); - if (!new_cluster) - return 0; - fat_table_set_eof (new_fs_info->fat, new_cluster); - ctx->buffer_map [i] = fat_cluster_to_frag (ctx->new_fs, - new_cluster); - - if (group_start == -1) - group_start = group_end = i; - - PED_ASSERT (ctx->buffer_map [i] - >= ctx->buffer_map [group_start], - return 0); - - mapped_length = ctx->buffer_map [i] - - ctx->buffer_map [group_start] + 1; - if (mapped_length <= ctx->buffer_frags) { - group_end = i; - } else { - /* ran out of room in the buffer, so write this group, - * and start a new one... - */ - if (!group_write (ctx, group_start, group_end)) - return 0; - group_start = group_end = i; - } - } - - PED_ASSERT (group_start != -1, return 0); - - if (!group_write (ctx, group_start, group_end)) - return 0; - return 1; -} - -/* default all fragments to unmoved - */ -static void -init_remap (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatFragment i; - - for (i = 0; i < old_fs_info->frag_count; i++) - ctx->remap[i] = fat_op_context_map_static_fragment (ctx, i); -} - -static FatFragment -count_frags_to_dup (FatOpContext* ctx) -{ - FatSpecific* fs_info = FAT_SPECIFIC (ctx->old_fs); - FatFragment i; - FatFragment total; - - total = 0; - - for (i = 0; i < fs_info->frag_count; i++) { - if (needs_duplicating (ctx, i)) - total++; - } - - return total; -} - -/* duplicates unreachable file clusters, and all directory clusters - */ -int -fat_duplicate_clusters (FatOpContext* ctx, PedTimer* timer) -{ - FatFragment total_frags_to_dup; - - init_remap (ctx); - total_frags_to_dup = count_frags_to_dup (ctx); - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, "moving data"); - - ctx->buffer_offset = 0; - ctx->frags_duped = 0; - while (search_next_fragment (ctx)) { - ped_timer_update ( - timer, 1.0 * ctx->frags_duped / total_frags_to_dup); - - if (!fetch_fragments (ctx)) - return 0; - if (!write_fragments (ctx)) - return 0; - ctx->buffer_offset += ctx->buffer_frags; - } - - ped_timer_update (timer, 1.0); - return 1; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.h b/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.h deleted file mode 100644 index 88316b7675..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/clstdup.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - libparted - Copyright (C) 1999, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_FAT_CLSTDUP_H_INCLUDED -#define PED_FAT_CLSTDUP_H_INCLUDED - -#include "context.h" - -/* the big important one :-) */ -extern int fat_duplicate_clusters (FatOpContext* ctx, PedTimer* timer); - -#endif /* PED_FAT_CLSTDUP_H_INCLUDED */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/context.c b/usr/src/lib/libparted/common/libparted/fs/fat/context.c deleted file mode 100644 index 8b04ad2536..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/context.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include - -#include "fat.h" - -#ifndef DISCOVER_ONLY - -/* Note: this deals with file system start and end sectors, even if the physical - * devices are different (eg for fat_copy()) Perhaps this is a hack, but it - * works ;-) - */ -static int -calc_deltas (FatOpContext* ctx) -{ - PedFileSystem* old_fs = ctx->old_fs; - PedFileSystem* new_fs = ctx->new_fs; - FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs); - PedSector old_cluster_ofs; - PedSector new_cluster_ofs; - PedSector sector_delta; - - old_cluster_ofs = old_fs->geom->start + old_fs_info->cluster_offset; - new_cluster_ofs = new_fs->geom->start + new_fs_info->cluster_offset; - - if (new_cluster_ofs > old_cluster_ofs) { - ctx->start_move_dir = FAT_DIR_FORWARD; - sector_delta = new_cluster_ofs - old_cluster_ofs; - } else { - ctx->start_move_dir = FAT_DIR_BACKWARD; - sector_delta = old_cluster_ofs - new_cluster_ofs; - } - - if (sector_delta % new_fs_info->cluster_sectors) { - ped_exception_throw ( - PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, - _("Cluster start delta = %d, which is not a multiple " - "of the cluster size %d."), - (int) sector_delta, - (int) new_fs_info->cluster_sectors); - return 0; - } - - ctx->start_move_delta = sector_delta / ctx->frag_sectors; - -#ifdef PED_VERBOSE - printf ("Start move delta is: %d %s.\n", - (int) ctx->start_move_delta, - (ctx->start_move_dir == FAT_DIR_FORWARD)? - "forwards" : "backwards"); -#endif - - return 1; -} - -FatOpContext* -fat_op_context_new (PedFileSystem* new_fs, PedFileSystem* old_fs) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (new_fs); - FatOpContext* ctx; - - ctx = (FatOpContext*) ped_malloc (sizeof (FatOpContext)); - if (!ctx) - goto error; - - ctx->frag_sectors = PED_MIN (old_fs_info->cluster_sectors, - new_fs_info->cluster_sectors); - if (!fat_set_frag_sectors (new_fs, ctx->frag_sectors)) - goto error; - if (!fat_set_frag_sectors (old_fs, ctx->frag_sectors)) - goto error; - - ctx->buffer_frags = old_fs_info->buffer_sectors / ctx->frag_sectors; - ctx->buffer_map = (FatFragment*) ped_malloc (sizeof (FatFragment) - * ctx->buffer_frags); - if (!ctx->buffer_map) - goto error_free_ctx; - - ctx->remap = (FatFragment*) ped_malloc (sizeof (FatFragment) - * old_fs_info->frag_count); - if (!ctx->remap) - goto error_free_buffer_map; - - ctx->new_fs = new_fs; - ctx->old_fs = old_fs; - if (!calc_deltas (ctx)) - goto error_free_buffer_map; - - return ctx; - -error_free_buffer_map: - ped_free (ctx->buffer_map); -error_free_ctx: - ped_free (ctx); -error: - return NULL; -} - -void -fat_op_context_destroy (FatOpContext* ctx) -{ - ped_free (ctx->buffer_map); - ped_free (ctx->remap); - ped_free (ctx); -} - -FatFragment -fat_op_context_map_static_fragment (const FatOpContext* ctx, FatFragment frag) -{ - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatFragment result; - - if (ctx->new_fs->geom->dev != ctx->old_fs->geom->dev) - return -1; - - if (ctx->start_move_dir == FAT_DIR_FORWARD) { - if (frag < ctx->start_move_delta) - return -1; - result = frag - ctx->start_move_delta; - } else { - result = frag + ctx->start_move_delta; - } - - if (result >= new_fs_info->frag_count) - return -1; - - return result; -} - -FatCluster -fat_op_context_map_static_cluster (const FatOpContext* ctx, FatCluster clst) -{ - FatFragment mapped_frag; - - mapped_frag = fat_op_context_map_static_fragment (ctx, - fat_cluster_to_frag (ctx->old_fs, clst)); - if (mapped_frag != -1) - return fat_frag_to_cluster (ctx->new_fs, mapped_frag); - else - return 0; -} - -FatFragment -fat_op_context_map_fragment (const FatOpContext* ctx, FatFragment frag) -{ - return ctx->remap [frag]; -} - -FatCluster -fat_op_context_map_cluster (const FatOpContext* ctx, FatCluster clst) -{ - FatFragment mapped_frag; - - mapped_frag = fat_op_context_map_fragment (ctx, - fat_cluster_to_frag (ctx->old_fs, clst)); - if (mapped_frag != -1) - return fat_frag_to_cluster (ctx->new_fs, mapped_frag); - else - return 0; -} - -/* This function sets the initial fat for the new resized file system. - This is in *NO WAY* a proper FAT table - all it does is: - a) mark bad clusters as bad. - b) mark used clusters (that is, clusters from the original FS that are - reachable from the resized one). Marks as EOF (i.e. used, end of - file chain). - c) mark original file system metadata as EOF (i.e. used), to prevent - it from being clobbered. This will leave the original file system - intact, until the partition table is modified, if the start of - the partition is moved. - - The FATs are rebuilt *properly* after cluster relocation. This here is - only to mark clusters as used, so when cluster relocation occurs, clusters - aren't relocated on top of ones marked in a, b or c. -*/ -int -fat_op_context_create_initial_fat (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatCluster clst; - FatCluster new_clst; - PedSector sect; - PedSector new_sect; - FatFragment frag; - FatFragment new_frag; - FatClusterFlag frag_flag; - - new_fs_info->fat = fat_table_new ( - new_fs_info->fat_type, - new_fs_info->fat_sectors * 512 - / fat_table_entry_size (new_fs_info->fat_type)); - if (!new_fs_info->fat) - return 0; - - if (!fat_table_set_cluster_count (new_fs_info->fat, - new_fs_info->cluster_count)) - return 0; - -/* mark bad and used clusters */ - for (frag = 0; frag < old_fs_info->frag_count; frag++) { - frag_flag = fat_get_fragment_flag (ctx->old_fs, frag); - if (frag_flag == FAT_FLAG_FREE) - continue; - - new_frag = fat_op_context_map_static_fragment (ctx, frag); - if (new_frag == -1) - continue; - - new_clst = fat_frag_to_cluster (ctx->new_fs, new_frag); - PED_ASSERT (new_clst != 0, return 0); - - if (frag_flag == FAT_FLAG_BAD) { - if (!fat_table_set_bad (new_fs_info->fat, new_clst)) - return 0; - } else { - if (!fat_table_set_eof (new_fs_info->fat, new_clst)) - return 0; - } - } - -/* mark metadata regions that map to clusters on the new FS */ - for (sect = 0; sect < old_fs_info->cluster_offset; sect++) { - new_sect = ped_geometry_map (ctx->new_fs->geom, - ctx->old_fs->geom, sect); - if (new_sect == -1 - || !fat_is_sector_in_clusters (ctx->new_fs, new_sect)) - continue; - - clst = fat_sector_to_cluster (ctx->new_fs, new_sect); - PED_ASSERT (clst != 0, return 0); - - if (!fat_table_set_eof (new_fs_info->fat, clst)) - return 0; - } - - return 1; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/context.h b/usr/src/lib/libparted/common/libparted/fs/fat/context.h deleted file mode 100644 index 39119a18d0..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/context.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - libparted - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_FAT_CONTEXT_H_INCLUDED -#define PED_FAT_CONTEXT_H_INCLUDED - -#include "count.h" - -enum _FatDirection { - FAT_DIR_FORWARD, - FAT_DIR_BACKWARD -}; -typedef enum _FatDirection FatDirection; - -struct _FatOpContext { - PedFileSystem* old_fs; - PedFileSystem* new_fs; - - PedSector frag_sectors; /* should equal old_fs and - new_fs's frag_sectors */ - - FatDirection start_move_dir; - FatFragment start_move_delta; - - FatFragment buffer_offset; - FatFragment buffer_frags; - FatFragment* buffer_map; - - FatFragment frags_duped; - - FatFragment* remap; - - FatCluster new_root_dir [32]; -}; -typedef struct _FatOpContext FatOpContext; - -extern FatOpContext* fat_op_context_new (PedFileSystem* new_fs, - PedFileSystem* old_fs); - -extern void fat_op_context_destroy (FatOpContext* ctx); - -extern FatFragment fat_op_context_map_static_fragment (const FatOpContext* ctx, - FatFragment frag); -extern FatCluster fat_op_context_map_static_cluster (const FatOpContext* ctx, - FatCluster clst); - -extern FatFragment fat_op_context_map_fragment (const FatOpContext* ctx, - FatFragment frag); -extern FatCluster fat_op_context_map_cluster (const FatOpContext* ctx, - FatCluster clst); - -extern int fat_op_context_create_initial_fat (FatOpContext* ctx); - -#endif /* PED_FAT_CONTEXT_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/count.c b/usr/src/lib/libparted/common/libparted/fs/fat/count.c deleted file mode 100644 index 10328d1b3e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/count.c +++ /dev/null @@ -1,403 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" -#include "traverse.h" - -#include -#include -#include - -#ifndef DISCOVER_ONLY - -#if 0 -/* extremely ugly hack: stick everything that obviously isn't an unmovable file - * in here. Note: DAT is a bit dubious. Unfortunately, it's used by the - * registry, so it'll be all over the place :-( - */ -static char* movable_extensions[] = { - "", - "1ST", - "AVI", - "BAK", "BAT", "BMP", - "CFG", "COM", "CSS", - "DAT", "DLL", "DOC", "DRV", - "EXE", - "FAQ", "FLT", "FON", - "GID", "GIF", - "HLP", "HTT", "HTM", - "ICO", "INI", - "JPG", - "LNK", "LOG", - "KBD", - "ME", "MID", "MSG", - "OCX", "OLD", - "PIF", "PNG", "PRV", - "RTF", - "SCR", "SYS", - "TMP", "TTF", "TXT", - "URL", - "WAV", - "VBX", "VOC", "VXD", - NULL -}; - -static char* -get_extension (char* file_name) -{ - char* ext; - - ext = strrchr (file_name, '.'); - if (!ext) - return ""; - if (strchr (ext, '\\')) - return ""; - return ext + 1; -} - -static int -is_movable_system_file (char* file_name) -{ - char* ext = get_extension (file_name); - int i; - - for (i = 0; movable_extensions [i]; i++) { - if (strcasecmp (ext, movable_extensions [i]) == 0) - return 1; - } - - return 0; -} -#endif /* 0 */ - -/* - prints out the sequence of clusters for a given file chain, beginning - at start_cluster. -*/ -#ifdef PED_VERBOSE -static void -print_chain (PedFileSystem* fs, FatCluster start) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster clst; - int this_row; - - this_row = 0; - for (clst = start; !fat_table_is_eof (fs_info->fat, clst); - clst = fat_table_get (fs_info->fat, clst)) { - printf (" %d", (int) clst); - if (++this_row == 7) { - putchar ('\n'); - this_row = 0; - } - } - putchar ('\n'); -} -#endif /* PED_VERBOSE */ - -static PedSector -remainder_round_up (PedSector a, PedSector b) -{ - PedSector result; - - result = a % b; - if (!result) - result = b; - return result; -} - -/* - traverse the FAT for a file/directory, marking each entry's flag - to "flag". -*/ -static int -flag_traverse_fat (PedFileSystem* fs, const char* chain_name, FatCluster start, - FatClusterFlag flag, PedSector size) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster clst; - FatCluster prev_clst; - int last_cluster_usage; - FatCluster chain_length = 0; - - if (fat_table_is_eof (fs_info->fat, start)) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Bad directory entry for %s: first cluster is the " - "end of file marker."), - chain_name) - != PED_EXCEPTION_IGNORE) - return 0; - } - - for (prev_clst = clst = start; !fat_table_is_eof (fs_info->fat, clst); - prev_clst = clst, clst = fat_table_get (fs_info->fat, clst)) { - chain_length++; - if (!clst) { - ped_exception_throw (PED_EXCEPTION_FATAL, - PED_EXCEPTION_CANCEL, - _("Bad FAT: unterminated chain for %s. You " - "should run dosfsck or scandisk."), - chain_name); - return 0; - } - - if (clst >= fs_info->fat->cluster_count + 2) { - ped_exception_throw (PED_EXCEPTION_FATAL, - PED_EXCEPTION_CANCEL, - _("Bad FAT: cluster %d outside file system " - "in chain for %s. You should run dosfsck " - "or scandisk."), - (int) clst, chain_name); - return 0; - } - - if (fs_info->cluster_info [clst].flag != FAT_FLAG_FREE ) { - ped_exception_throw (PED_EXCEPTION_FATAL, - PED_EXCEPTION_CANCEL, - _("Bad FAT: cluster %d is cross-linked for " - "%s. You should run dosfsck or scandisk."), - (int) clst, chain_name); - return 0; - } - - if (flag == FAT_FLAG_DIRECTORY) - fs_info->total_dir_clusters++; - - fs_info->cluster_info [clst].flag = flag; - fs_info->cluster_info [clst].units_used = 0; /* 0 == 64 */ - } - - if (size - && chain_length - != ped_div_round_up (size, fs_info->cluster_sectors)) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("%s is %dk, but it has %d clusters (%dk)."), - chain_name, - (int) size / 2, - (int) chain_length, - (int) chain_length * fs_info->cluster_sectors / 2) - != PED_EXCEPTION_IGNORE) - return 0; - } - - last_cluster_usage - = ped_div_round_up (64 * remainder_round_up (size, - fs_info->cluster_sectors), - fs_info->cluster_sectors); - - fs_info->cluster_info [prev_clst].units_used = last_cluster_usage; - - return 1; -} - -/* - recursively traverses a directory, flagging all clusters in the process. - It frees the traverse_info structure before returning. -*/ -static int -flag_traverse_dir (FatTraverseInfo* trav_info) { - PedFileSystem* fs = trav_info->fs; - FatDirEntry* this_entry; - FatTraverseInfo* subdir_trav_info; - char file_name [512]; - char* file_name_start; - FatCluster first_cluster; - PedSector size; - - PED_ASSERT (trav_info != NULL, return 0); - - strcpy (file_name, trav_info->dir_name); - file_name_start = file_name + strlen (file_name); - - while ( (this_entry = fat_traverse_next_dir_entry (trav_info)) ) { - if (fat_dir_entry_is_null_term (this_entry)) - break; - if (!fat_dir_entry_has_first_cluster (this_entry, fs)) - continue; - if (this_entry->name [0] == '.') - continue; /* skip . and .. entries */ - - fat_dir_entry_get_name (this_entry, file_name_start); - first_cluster = fat_dir_entry_get_first_cluster(this_entry, fs); - size = ped_div_round_up (fat_dir_entry_get_length (this_entry), - 512); - -#ifdef PED_VERBOSE - printf ("%s: ", file_name); - print_chain (fs, first_cluster); -#endif - -#if 0 - if (fat_dir_entry_is_system_file (this_entry) - && !is_movable_system_file (file_name)) { - PedExceptionOption ex_status; - ex_status = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The file %s is marked as a system file. " - "This means moving it could cause some " - "programs to stop working."), - file_name); - - switch (ex_status) { - case PED_EXCEPTION_CANCEL: - return 0; - - case PED_EXCEPTION_UNHANDLED: - ped_exception_catch (); - case PED_EXCEPTION_IGNORE: - } - } -#endif /* 0 */ - - if (fat_dir_entry_is_directory (this_entry)) { - if (!flag_traverse_fat (fs, file_name, first_cluster, - FAT_FLAG_DIRECTORY, size)) - return 0; - - subdir_trav_info = fat_traverse_directory (trav_info, - this_entry); - if (!subdir_trav_info) - return 0; - if (!flag_traverse_dir (subdir_trav_info)) - return 0; - } else if (fat_dir_entry_is_file (this_entry)) { - if (!flag_traverse_fat (fs, file_name, first_cluster, - FAT_FLAG_FILE, size)) - return 0; - } - } - - fat_traverse_complete (trav_info); - return 1; -} - -static void -_mark_bad_clusters (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster cluster; - - for (cluster = 2; cluster < fs_info->cluster_count + 2; cluster++) { - if (fat_table_is_bad (fs_info->fat, cluster)) - fs_info->cluster_info [cluster].flag = FAT_FLAG_BAD; - } -} - -/* - fills in cluster_info. Each FAT entry (= cluster) is flagged as either - FAT_FLAG_FREE, FAT_FLAG_FILE or FAT_FLAG_DIRECTORY. - - Also, the fraction of each cluster (x/64) is recorded -*/ -int -fat_collect_cluster_info (PedFileSystem* fs) { - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatTraverseInfo* trav_info; - - /* set all clusters to unused as a default */ - memset (fs_info->cluster_info, 0, fs_info->fat->cluster_count + 2); - fs_info->total_dir_clusters = 0; - - if (fs_info->fat_type == FAT_TYPE_FAT32) { - trav_info = fat_traverse_begin (fs, fs_info->root_cluster, - "\\"); - if (!flag_traverse_dir (trav_info)) - return 0; - if (!flag_traverse_fat (fs, "\\", fs_info->root_cluster, - FAT_FLAG_DIRECTORY, 0)) - return 0; - } else { - trav_info = fat_traverse_begin (fs, FAT_ROOT, "\\"); - if (!flag_traverse_dir (trav_info)) - return 0; - } - - _mark_bad_clusters (fs); - return 1; -} - -FatClusterFlag -fat_get_cluster_flag (PedFileSystem* fs, FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - return fs_info->cluster_info [cluster].flag; -} - -PedSector -fat_get_cluster_usage (PedFileSystem* fs, FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - int fraction; - - if (fs_info->cluster_info [cluster].flag == FAT_FLAG_FREE) - return 0; - - fraction = fs_info->cluster_info [cluster].units_used; - if (fraction == 0) - fraction = 64; - - return fraction * fs_info->cluster_sectors / 64; -} - -FatClusterFlag -fat_get_fragment_flag (PedFileSystem* fs, FatFragment frag) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster cluster = fat_frag_to_cluster (fs, frag); - FatFragment offset = frag % fs_info->cluster_frags; - FatFragment last_frag_used; - FatClusterFlag flag; - - PED_ASSERT (cluster >= 2 && cluster < fs_info->cluster_count + 2, - return 0); - - flag = fat_get_cluster_flag (fs, cluster); - if (flag != FAT_FLAG_FILE && flag != FAT_FLAG_DIRECTORY) - return flag; - last_frag_used = (fat_get_cluster_usage (fs, cluster) - 1) - / fs_info->frag_sectors; - if (offset > last_frag_used) - return FAT_FLAG_FREE; - else - return flag; -} - -int -fat_is_fragment_active (PedFileSystem* fs, FatFragment frag) -{ - switch (fat_get_fragment_flag (fs, frag)) { - case FAT_FLAG_FREE: - case FAT_FLAG_BAD: - return 0; - - case FAT_FLAG_FILE: - case FAT_FLAG_DIRECTORY: - return 1; - } - return 0; -} - -#endif /* !DISCOVER_ONLY */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/count.h b/usr/src/lib/libparted/common/libparted/fs/fat/count.h deleted file mode 100644 index 2b68de69c1..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/count.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - libparted - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef COUNT_H_INCLUDED -#define COUNT_H_INCLUDED - -typedef enum _FatClusterFlag FatClusterFlag; -typedef struct _FatClusterInfo FatClusterInfo; - -enum _FatClusterFlag { - FAT_FLAG_FREE=0, - FAT_FLAG_FILE=1, - FAT_FLAG_DIRECTORY=2, - FAT_FLAG_BAD=3 -}; - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _FatClusterInfo { - unsigned int units_used:6; /* 1 unit = cluster_size / 64 */ - FatClusterFlag flag:2; -} fat16; -#ifdef __sun -#pragma pack() -#endif - -extern int fat_collect_cluster_info (PedFileSystem *fs); -extern FatClusterFlag fat_get_cluster_flag (PedFileSystem* fs, - FatCluster cluster); -extern PedSector fat_get_cluster_usage (PedFileSystem* fs, FatCluster cluster); -extern FatClusterFlag fat_get_fragment_flag (PedFileSystem* fs, - FatFragment frag); -extern int fat_is_fragment_active (PedFileSystem* fs, FatFragment frag); - -#endif /* COUNT_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/fat.c b/usr/src/lib/libparted/common/libparted/fs/fat/fat.c deleted file mode 100644 index fa91a33a3d..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/fat.c +++ /dev/null @@ -1,887 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include - -#include "fat.h" -#include "calc.h" - -PedFileSystem* -fat_alloc (const PedGeometry* geom) -{ - PedFileSystem* fs; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) - goto error; - - fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific)); - if (!fs->type_specific) - goto error_free_fs; - - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) - goto error_free_type_specific; - - fs->checked = 0; - return fs; - -error_free_type_specific: - ped_free (fs->type_specific); -error_free_fs: - ped_free (fs); -error: - return NULL; -} - -/* Requires the boot sector to be analysed */ -int -fat_alloc_buffers (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - fs_info->buffer_sectors = BUFFER_SIZE; - fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512); - if (!fs_info->buffer) - goto error; - - fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2); - if (!fs_info->cluster_info) - goto error_free_buffer; - - return 1; - -error_free_buffer: - ped_free (fs_info->buffer); -error: - return 0; -} - -void -fat_free_buffers (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - ped_free (fs_info->cluster_info); - ped_free (fs_info->buffer); -} - -void -fat_free (PedFileSystem* fs) -{ - ped_geometry_destroy (fs->geom); - ped_free (fs->type_specific); - ped_free (fs); -} - -int -fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0 - && frag_sectors <= fs_info->cluster_sectors, - return 0); - - fs_info->frag_size = frag_sectors * 512; - fs_info->frag_sectors = frag_sectors; - fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors; - fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors; - fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags; - - return 1; -} - -PedGeometry* -fat_probe (PedGeometry* geom, FatType* fat_type) -{ - PedFileSystem* fs; - FatSpecific* fs_info; - PedGeometry* result; - - fs = fat_alloc (geom); - if (!fs) - goto error; - fs_info = (FatSpecific*) fs->type_specific; - - if (!fat_boot_sector_read (&fs_info->boot_sector, geom)) - goto error_free_fs; - if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs)) - goto error_free_fs; - - *fat_type = fs_info->fat_type; - result = ped_geometry_new (geom->dev, geom->start, - fs_info->sector_count); - - fat_free (fs); - return result; - -error_free_fs: - fat_free (fs); -error: - return NULL; -} - -PedGeometry* -fat_probe_fat16 (PedGeometry* geom) -{ - FatType fat_type; - PedGeometry* probed_geom = fat_probe (geom, &fat_type); - - if (probed_geom) { - if (fat_type == FAT_TYPE_FAT16) - return probed_geom; - ped_geometry_destroy (probed_geom); - } - return NULL; -} - -PedGeometry* -fat_probe_fat32 (PedGeometry* geom) -{ - FatType fat_type; - PedGeometry* probed_geom = fat_probe (geom, &fat_type); - - if (probed_geom) { - if (fat_type == FAT_TYPE_FAT32) - return probed_geom; - ped_geometry_destroy (probed_geom); - } - return NULL; -} - -#ifndef DISCOVER_ONLY -int -fat_clobber (PedGeometry* geom) -{ - FatBootSector boot_sector; - - if (!fat_boot_sector_read (&boot_sector, geom)) - return 1; - - boot_sector.system_id[0] = 0; - boot_sector.boot_sign = 0; - if (boot_sector.u.fat16.fat_name[0] == 'F') - boot_sector.u.fat16.fat_name[0] = 0; - if (boot_sector.u.fat32.fat_name[0] == 'F') - boot_sector.u.fat32.fat_name[0] = 0; - - return ped_geometry_write (geom, &boot_sector, 0, 1); -} - -static int -_init_fats (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster table_size; - - table_size = fs_info->fat_sectors * 512 - / fat_table_entry_size (fs_info->fat_type); - fs_info->fat = fat_table_new (fs_info->fat_type, table_size); - if (!fs_info->fat) - goto error; - - if (!fat_table_read (fs_info->fat, fs, 0)) - goto error_free_fat; - - return 1; - -error_free_fat: - fat_table_destroy (fs_info->fat); -error: - return 0; -} - -PedFileSystem* -fat_open (PedGeometry* geom) -{ - PedFileSystem* fs; - FatSpecific* fs_info; - - fs = fat_alloc (geom); - if (!fs) - goto error; - fs_info = (FatSpecific*) fs->type_specific; - - if (!fat_boot_sector_read (&fs_info->boot_sector, geom)) - goto error_free_fs; - if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs)) - goto error_free_fs; - fs->type = (fs_info->fat_type == FAT_TYPE_FAT16) - ? &fat16_type - : &fat32_type; - if (fs_info->fat_type == FAT_TYPE_FAT32) { - if (!fat_info_sector_read (&fs_info->info_sector, fs)) - goto error_free_fs; - } - - if (!_init_fats (fs)) - goto error_free_fs; - if (!fat_alloc_buffers (fs)) - goto error_free_fat_table; - if (!fat_collect_cluster_info (fs)) - goto error_free_buffers; - - return fs; - -error_free_buffers: - fat_free_buffers (fs); -error_free_fat_table: - fat_table_destroy (fs_info->fat); -error_free_fs: - fat_free (fs); -error: - return NULL; -} - -static int -fat_root_dir_clear (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count); - return ped_geometry_write (fs->geom, fs_info->buffer, - fs_info->root_dir_offset, - fs_info->root_dir_sector_count); -} - -/* hack: use the ext2 uuid library to generate a reasonably random (hopefully - * with /dev/random) number. Unfortunately, we can only use 4 bytes of it - */ -static uint32_t -_gen_new_serial_number () -{ - uuid_t uuid; - - uuid_generate (uuid); - return * (uint32_t*) &uuid [0]; -} - -PedFileSystem* -fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer) -{ - PedFileSystem* fs; - FatSpecific* fs_info; - FatCluster table_size; - - fs = fat_alloc (geom); - if (!fs) - goto error; - fs_info = (FatSpecific*) fs->type_specific; - - fs_info->logical_sector_size = 1; - fs_info->sectors_per_track = geom->dev->bios_geom.sectors; - fs_info->heads = geom->dev->bios_geom.heads; - fs_info->sector_count = fs->geom->length; - fs_info->fat_table_count = 2; -/* some initial values, to be changed later */ - fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT - / (512 / sizeof (FatDirEntry)); - fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT; - - fs_info->fat_type = fat_type; - if (!fat_calc_sizes (fs->geom->length, 0, - fs_info->fat_type, - fs_info->root_dir_sector_count, - &fs_info->cluster_sectors, - &fs_info->cluster_count, - &fs_info->fat_sectors)) { - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Partition too big/small for a %s file system."), - (fat_type == FAT_TYPE_FAT16) - ? fat16_type.name - : fat32_type.name); - goto error_free_fs; - } - - fs_info->cluster_size = fs_info->cluster_sectors * 512; - - fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type); - fs_info->dir_entries_per_cluster - = fs_info->cluster_size / sizeof (FatDirEntry); - - if (fs_info->fat_type == FAT_TYPE_FAT16) { - /* FAT16 */ - fs->type = &fat16_type; - - if (fs_info->cluster_count - > fat_max_cluster_count (fs_info->fat_type)) { - fs_info->cluster_count - = fat_max_cluster_count (fs_info->fat_type); - } - - fs_info->root_dir_sector_count - = FAT_ROOT_DIR_ENTRY_COUNT - / (512 / sizeof (FatDirEntry)); - fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT; - fs_info->root_dir_offset - = fs_info->fat_offset - + fs_info->fat_sectors * fs_info->fat_table_count; - fs_info->cluster_offset - = fs_info->root_dir_offset - + fs_info->root_dir_sector_count; - } else { - /* FAT32 */ - fs->type = &fat32_type; - - fs_info->info_sector_offset = 1; - fs_info->boot_sector_backup_offset = 6; - - fs_info->root_dir_sector_count = 0; - fs_info->root_dir_entry_count = 0; - fs_info->root_dir_offset = 0; - - fs_info->cluster_offset - = fs_info->fat_offset - + fs_info->fat_sectors * fs_info->fat_table_count; - } - - table_size = fs_info->fat_sectors * 512 - / fat_table_entry_size (fs_info->fat_type); - fs_info->fat = fat_table_new (fs_info->fat_type, table_size); - if (!fs_info->fat) - goto error_free_fs; - fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count); - if (!fat_alloc_buffers (fs)) - goto error_free_fat_table; - - if (fs_info->fat_type == FAT_TYPE_FAT32) { - fs_info->root_cluster - = fat_table_alloc_cluster (fs_info->fat); - fat_table_set_eof (fs_info->fat, fs_info->root_cluster); - memset (fs_info->buffer, 0, fs_info->cluster_size); - if (!fat_write_cluster (fs, fs_info->buffer, - fs_info->root_cluster)) - return 0; - } - - fs_info->serial_number = _gen_new_serial_number (); - - if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector)) - goto error_free_buffers; - if (!fat_boot_sector_generate (&fs_info->boot_sector, fs)) - goto error_free_buffers; - if (!fat_boot_sector_write (&fs_info->boot_sector, fs)) - goto error_free_buffers; - if (fs_info->fat_type == FAT_TYPE_FAT32) { - if (!fat_info_sector_generate (&fs_info->info_sector, fs)) - goto error_free_buffers; - if (!fat_info_sector_write (&fs_info->info_sector, fs)) - goto error_free_buffers; - } - - if (!fat_table_write_all (fs_info->fat, fs)) - goto error_free_buffers; - - if (fs_info->fat_type == FAT_TYPE_FAT16) { - if (!fat_root_dir_clear (fs)) - goto error_free_buffers; - } - - return fs; - -error_free_buffers: - fat_free_buffers (fs); -error_free_fat_table: - fat_table_destroy (fs_info->fat); -error_free_fs: - fat_free (fs); -error: - return NULL; -} - -PedFileSystem* -fat_create_fat16 (PedGeometry* geom, PedTimer* timer) -{ - return fat_create (geom, FAT_TYPE_FAT16, timer); -} - -PedFileSystem* -fat_create_fat32 (PedGeometry* geom, PedTimer* timer) -{ - return fat_create (geom, FAT_TYPE_FAT32, timer); -} - -int -fat_close (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - fat_free_buffers (fs); - fat_table_destroy (fs_info->fat); - fat_free (fs); - return 1; -} - -/* Hack: just resize the file system outside of its boundaries! */ -PedFileSystem* -fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - PedFileSystem* new_fs; - - new_fs = ped_file_system_open (fs->geom); - if (!new_fs) - goto error; - if (!ped_file_system_resize (new_fs, geom, timer)) - goto error_close_new_fs; - return new_fs; - -error_close_new_fs: - ped_file_system_close (new_fs); -error: - return 0; -} - -static int -_compare_fats (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatTable* table_copy; - FatCluster table_size; - int i; - - table_size = fs_info->fat_sectors * 512 - / fat_table_entry_size (fs_info->fat_type); - - table_copy = fat_table_new (fs_info->fat_type, table_size); - if (!table_copy) - goto error; - - for (i = 1; i < fs_info->fat_table_count; i++) { - if (!fat_table_read (table_copy, fs, i)) - goto error_free_table_copy; - if (!fat_table_compare (fs_info->fat, table_copy)) { - if (ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("The FATs don't match. If you don't know " - "what this means, then select cancel, run " - "scandisk on the file system, and then come " - "back.")) - != PED_EXCEPTION_IGNORE) - goto error_free_table_copy; - } - } - - fat_table_destroy (table_copy); - return 1; - -error_free_table_copy: - fat_table_destroy (table_copy); -error: - return 0; -} - -int -fat_check (PedFileSystem* fs, PedTimer* timer) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector cluster_sectors; - FatCluster cluster_count; - PedSector fat_sectors; - PedSector align_sectors; - FatCluster info_free_clusters; - - align_sectors = fs_info->fat_offset - - fat_min_reserved_sector_count (fs_info->fat_type); - - if (!fat_calc_sizes (fs->geom->length, - align_sectors, - fs_info->fat_type, - fs_info->root_dir_sector_count, - &cluster_sectors, - &cluster_count, - &fat_sectors)) { - if (ped_exception_throw (PED_EXCEPTION_BUG, - PED_EXCEPTION_IGNORE_CANCEL, - _("There are no possible configurations for this FAT " - "type.")) - != PED_EXCEPTION_IGNORE) - goto error; - } - - if (fs_info->fat_type == FAT_TYPE_FAT16) { - if (cluster_sectors != fs_info->cluster_sectors - || cluster_count != fs_info->cluster_count - || fat_sectors != fs_info->fat_sectors) { - if (ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("File system doesn't have expected sizes for " - "Windows to like it. " - "Cluster size is %dk (%dk expected); " - "number of clusters is %d (%d expected); " - "size of FATs is %d sectors (%d expected)."), - (int) fs_info->cluster_sectors / 2, - (int) cluster_sectors / 2, - (int) fs_info->cluster_count, - (int) cluster_count, - (int) fs_info->fat_sectors, - (int) fat_sectors) - != PED_EXCEPTION_IGNORE) - goto error; - } - } - - if (fs_info->fat_type == FAT_TYPE_FAT32) { - info_free_clusters - = PED_LE32_TO_CPU (fs_info->info_sector.free_clusters); - if (info_free_clusters != (FatCluster) -1 - && info_free_clusters != fs_info->fat->free_cluster_count) { - if (ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("File system is reporting the free space as " - "%d clusters, not %d clusters."), - info_free_clusters, - fs_info->fat->free_cluster_count) - != PED_EXCEPTION_IGNORE) - goto error; - } - } - - if (!_compare_fats (fs)) - goto error; - - fs->checked = 1; - return 1; /* existence of fs implies consistency ;-) */ - -error: - return 0; -} - -/* Calculates how much space there will be in clusters in: - * old_fs intersect the-new-fs - */ -static PedSector -_calc_resize_data_size ( - const PedFileSystem* old_fs, - PedSector new_cluster_sectors, - FatCluster new_cluster_count, - PedSector new_fat_size) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs); - PedSector fat_size_delta; - - fat_size_delta = old_fs_info->fat_sectors - new_fat_size; - return new_cluster_sectors * new_cluster_count - fat_size_delta * 2; -} - -static int -_test_resize_size (const PedFileSystem* fs, - PedSector length, PedSector min_data_size) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedGeometry geom; - PedSector _cluster_sectors; - FatCluster _cluster_count; - PedSector _fat_size; - - ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length); - - if (fat_calc_resize_sizes ( - &geom, - fs_info->cluster_sectors, - FAT_TYPE_FAT16, - fs_info->root_dir_sector_count, - fs_info->cluster_sectors, - &_cluster_sectors, - &_cluster_count, - &_fat_size) - && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count, - _fat_size) - >= min_data_size) - return 1; - - if (fat_calc_resize_sizes ( - &geom, - fs_info->cluster_sectors, - FAT_TYPE_FAT32, - 0, - fs_info->cluster_sectors, - &_cluster_sectors, - &_cluster_count, - &_fat_size) - && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count, - _fat_size) - >= min_data_size) - return 1; - - return 0; -} - -/* does a binary search (!) for the mininum size. Too hard to compute directly - * (see calc_sizes() for why!) - */ -static PedSector -_get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size) -{ - PedSector min_length = 0; - PedSector max_length = fs->geom->length; - PedSector length; - - while (min_length < max_length - 1) { - length = (min_length + max_length) / 2; - if (_test_resize_size (fs, length, min_data_size)) - max_length = length; - else - min_length = length; - } - -/* adds a bit of leeway (64 sectors), for resolving extra issues, like root - * directory allocation, that aren't covered here. - */ - return max_length + 64; -} - -PedConstraint* -fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedGeometry full_dev; - PedSector min_cluster_count; - FatCluster used_clusters; - PedSector min_data_size; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - used_clusters = fs_info->fat->cluster_count - - fs_info->fat->free_cluster_count; - min_cluster_count = used_clusters + fs_info->total_dir_clusters; - min_data_size = min_cluster_count * fs_info->cluster_sectors; - - return ped_constraint_new (ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - _get_min_resize_size (fs, min_data_size), - dev->length); -} - -PedConstraint* -fat_get_resize_constraint (const PedFileSystem* fs) -{ - return fat_get_copy_constraint (fs, fs->geom->dev); -} - -/* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or - * something. This is a really difficult (maths) problem to do - * nicely... - * So, this algorithm works if dev->length / 2 is a valid fat_type - * size. (Which is how I got the magic numbers below) - */ -#if 0 -/* returns: -1 too small, 0 ok, 1 too big */ -static int -_test_create_size (PedSector length, FatType fat_type, - PedSector cluster_sectors, PedSector cluster_count) -{ - PedSector rootdir_sectors; - PedSector _cluster_sectors; - FatCluster _cluster_count; - PedSector _fat_size; - - rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0; - - if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors, - &_cluster_sectors, &_cluster_count, &_fat_size)) - return -1; // XXX: doesn't work... can't see a better way! - - if (_cluster_sectors < cluster_sectors) - return -1; - if (_cluster_sectors > cluster_sectors) - return 1; - - if (_cluster_count < cluster_count) - return -1; - if (_cluster_count > cluster_count) - return 1; - - return 0; -} - -static PedSector -_get_create_size (PedSector upper_bound, FatType fat_type, - PedSector cluster_sectors, FatCluster cluster_count) -{ - PedSector min_length = 0; - PedSector max_length = upper_bound; - PedSector length; - - while (1) { - length = (min_length + max_length) / 2; - switch (_test_create_size (length, fat_type, cluster_sectors, - cluster_count)) { - case -1: min_length = length; break; - case 0: return length; - case 1: max_length = length; break; - } - /* hack... won't always be able to get max cluster count - * with max cluster size, etc. */ - if (max_length - min_length == 1) - return min_length; - } - - return 0; /* shut gcc up */ -} -#endif - -PedConstraint* -fat_get_create_constraint_fat16 (const PedDevice* dev) -{ - PedGeometry full_dev; - PedSector min_size; - PedSector max_size; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - -#if 0 - min_size = _get_create_size (dev->length, FAT_TYPE_FAT16, - fat_min_cluster_size (FAT_TYPE_FAT16), - fat_min_cluster_count (FAT_TYPE_FAT16)); - max_size = _get_create_size (dev->length, FAT_TYPE_FAT16, - fat_max_cluster_size (FAT_TYPE_FAT16), - fat_max_cluster_count (FAT_TYPE_FAT16)); - if (!min_size) - return NULL; -#else - min_size = 65794; - max_size = 2097153; -#endif - - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - min_size, max_size); -} - -PedConstraint* -fat_get_create_constraint_fat32 (const PedDevice* dev) -{ - PedGeometry full_dev; - PedSector min_size; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - -#if 0 - min_size = _get_create_size (dev->length, FAT_TYPE_FAT32, - fat_min_cluster_size (FAT_TYPE_FAT32), - fat_min_cluster_count (FAT_TYPE_FAT32)); - if (!min_size) - return NULL; -#else - min_size = 525224; -#endif - - return ped_constraint_new ( - ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - min_size, dev->length); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps fat16_ops = { - .probe = fat_probe_fat16, -#ifndef DISCOVER_ONLY - .clobber = fat_clobber, - .open = fat_open, - .create = fat_create_fat16, - .close = fat_close, - .check = fat_check, - .resize = fat_resize, - .copy = fat_copy, - .get_create_constraint = fat_get_create_constraint_fat16, - .get_resize_constraint = fat_get_resize_constraint, - .get_copy_constraint = fat_get_copy_constraint, -#else /* !DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL, -#endif /* !DISCOVER_ONLY */ -}; - -static PedFileSystemOps fat32_ops = { - .probe = fat_probe_fat32, -#ifndef DISCOVER_ONLY - .clobber = fat_clobber, - .open = fat_open, - .create = fat_create_fat32, - .close = fat_close, - .check = fat_check, - .resize = fat_resize, - .copy = fat_copy, - .get_create_constraint = fat_get_create_constraint_fat32, - .get_resize_constraint = fat_get_resize_constraint, - .get_copy_constraint = fat_get_copy_constraint, -#else /* !DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .resize = NULL, - .copy = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL, -#endif /* !DISCOVER_ONLY */ -}; - -#define FAT_BLOCK_SIZES ((int[2]){512, 0}) - -PedFileSystemType fat16_type = { - .next = NULL, - .ops = &fat16_ops, - .name = "fat16", - .block_sizes = FAT_BLOCK_SIZES -}; - -PedFileSystemType fat32_type = { - .next = NULL, - .ops = &fat32_ops, - .name = "fat32", - .block_sizes = FAT_BLOCK_SIZES -}; - -void -ped_file_system_fat_init () -{ - if (sizeof (FatBootSector) != 512) { - ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL, - _("GNU Parted was miscompiled: the FAT boot sector " - "should be 512 bytes. FAT support will be disabled.")); - } else { - ped_file_system_type_register (&fat16_type); - ped_file_system_type_register (&fat32_type); - } -} - -void -ped_file_system_fat_done () -{ - ped_file_system_type_unregister (&fat16_type); - ped_file_system_type_unregister (&fat32_type); -} - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/fat.h b/usr/src/lib/libparted/common/libparted/fs/fat/fat.h deleted file mode 100644 index 82232fbfb5..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/fat.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - libparted - Copyright (C) 1998-2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef FAT_H_INCLUDED -#define FAT_H_INCLUDED - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include -#include -#include - -#define BUFFER_SIZE 1024 /* buffer size in sectors (512 bytes) */ - -typedef uint32_t FatCluster; -typedef int32_t FatFragment; - -enum _FatType { - FAT_TYPE_FAT12, - FAT_TYPE_FAT16, - FAT_TYPE_FAT32 -}; -typedef enum _FatType FatType; - -typedef struct _FatSpecific FatSpecific; -typedef struct _FatDirEntry FatDirEntry; - -/* FIXME: YUCKY */ -#include "table.h" -#include "bootsector.h" -#include "context.h" -#include "fatio.h" -#include "traverse.h" -#include "calc.h" -#include "count.h" -#include "clstdup.h" - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _FatDirEntry { - char name[8]; - uint8_t extension[3]; - uint8_t attributes; - uint8_t is_upper_case_name; - uint8_t creation_time_low; /* milliseconds */ - uint16_t creation_time_high; - uint16_t creation_date; - uint16_t access_date; - uint16_t first_cluster_high; /* for FAT32 */ - uint16_t time; - uint16_t date; - uint16_t first_cluster; - uint32_t length; -}; -#ifdef __sun -#pragma pack() -#endif - -struct _FatSpecific { - FatBootSector boot_sector; /* structure of boot sector */ - FatInfoSector info_sector; /* fat32-only information sector */ - - int logical_sector_size; /* illogical sector size :-) */ - PedSector sector_count; - - int sectors_per_track; /* BIOS CHS stuff (S) */ - int heads; /* BIOS CHS stuff (H) */ - - int cluster_size; - PedSector cluster_sectors; - FatCluster cluster_count; - int dir_entries_per_cluster; - - FatType fat_type; - int fat_table_count; - PedSector fat_sectors; - - uint32_t serial_number; - - PedSector info_sector_offset; /* FAT32 only */ - PedSector fat_offset; - PedSector root_dir_offset; /* non-FAT32 */ - PedSector cluster_offset; - PedSector boot_sector_backup_offset; - - FatCluster root_cluster; /* FAT32 only */ - int root_dir_entry_count; /* non-FAT32 */ - PedSector root_dir_sector_count; /* non-FAT32 */ - FatCluster total_dir_clusters; - - FatTable* fat; - FatClusterInfo* cluster_info; - - PedSector buffer_sectors; - char* buffer; - - int frag_size; - PedSector frag_sectors; - FatFragment frag_count; - FatFragment buffer_frags; - FatFragment cluster_frags; -}; - -#define FAT_SPECIFIC(fs) ((FatSpecific*) fs->type_specific) - -#define FAT_ROOT 0 - -#define DELETED_FLAG 0xe5 - -#define READONLY_ATTR 0x01 -#define HIDDEN_ATTR 0x02 -#define SYSTEM_ATTR 0x04 -#define VOLUME_LABEL_ATTR 0x08 -#define VFAT_ATTR 0x0f -#define DIRECTORY_ATTR 0x10 -#define ARCH_ATTR 0x20 - -#define MAX_FAT12_CLUSTERS 4086 -#define MAX_FAT16_CLUSTERS 65526 -#define MAX_FAT32_CLUSTERS 2000000 - -#define FAT_ROOT_DIR_ENTRY_COUNT 512 - -extern PedFileSystemType fat16_type; -extern PedFileSystemType fat32_type; - -extern void fat_print (const PedFileSystem* fs); - -extern PedFileSystem* fat_alloc (const PedGeometry* geom); -extern void fat_free (PedFileSystem* fs); -extern int fat_alloc_buffers (PedFileSystem* fs); -extern void fat_free_buffers (PedFileSystem* fs); - -extern int fat_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer); - -extern int fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors); - -#endif /* FAT_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/fatio.c b/usr/src/lib/libparted/common/libparted/fs/fat/fatio.c deleted file mode 100644 index c12ebc6e8c..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/fatio.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" -#include "fatio.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifndef DISCOVER_ONLY - -int -fat_read_fragments (PedFileSystem* fs, char* buf, FatFragment frag, - FatFragment count) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector sector = fat_frag_to_sector (fs, frag); - PedSector sector_count = count * fs_info->frag_sectors; - - PED_ASSERT (frag >= 0 && frag < fs_info->frag_count, return 0); - - return ped_geometry_read (fs->geom, buf, sector, sector_count); -} - -int -fat_read_fragment (PedFileSystem* fs, char* buf, FatFragment frag) -{ - return fat_read_fragments (fs, buf, frag, 1); -} - -int -fat_write_fragments (PedFileSystem* fs, char* buf, FatFragment frag, - FatFragment count) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector sector = fat_frag_to_sector (fs, frag); - PedSector sector_count = count * fs_info->frag_sectors; - - PED_ASSERT (frag >= 0 && frag < fs_info->frag_count, return 0); - - return ped_geometry_write (fs->geom, buf, sector, sector_count); -} - -int -fat_write_fragment (PedFileSystem* fs, char* buf, FatFragment frag) -{ - return fat_write_fragments (fs, buf, frag, 1); -} - -int -fat_write_sync_fragments (PedFileSystem* fs, char* buf, FatFragment frag, - FatFragment count) -{ - if (!fat_write_fragments (fs, buf, frag, count)) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - return 1; -} - -int -fat_write_sync_fragment (PedFileSystem* fs, char* buf, FatFragment frag) -{ - return fat_write_sync_fragments (fs, buf, frag, 1); -} - -int -fat_read_clusters (PedFileSystem* fs, char *buf, FatCluster cluster, - FatCluster count) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector sector = fat_cluster_to_sector (fs, cluster); - PedSector sector_count = count * fs_info->cluster_sectors; - - PED_ASSERT (cluster >= 2 - && cluster + count - 1 < fs_info->cluster_count + 2, - return 0); - - return ped_geometry_read (fs->geom, buf, sector, sector_count); -} - -int -fat_read_cluster (PedFileSystem* fs, char *buf, FatCluster cluster) -{ - return fat_read_clusters (fs, buf, cluster, 1); -} - -int -fat_write_clusters (PedFileSystem* fs, char *buf, FatCluster cluster, - FatCluster count) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector sector = fat_cluster_to_sector (fs, cluster); - PedSector sector_count = count * fs_info->cluster_sectors; - - PED_ASSERT (cluster >= 2 - && cluster + count - 1 < fs_info->cluster_count + 2, - return 0); - - return ped_geometry_write (fs->geom, buf, sector, sector_count); -} - -int -fat_write_cluster (PedFileSystem* fs, char *buf, FatCluster cluster) -{ - return fat_write_clusters (fs, buf, cluster, 1); -} - -int -fat_write_sync_clusters (PedFileSystem* fs, char *buf, FatCluster cluster, - FatCluster count) -{ - if (!fat_write_clusters (fs, buf, cluster, count)) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - return 1; -} - -int -fat_write_sync_cluster (PedFileSystem* fs, char *buf, FatCluster cluster) -{ - if (!fat_write_cluster (fs, buf, cluster)) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - return 1; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/fatio.h b/usr/src/lib/libparted/common/libparted/fs/fat/fatio.h deleted file mode 100644 index 319b2262bd..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/fatio.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef FATIO_H_INCLUDED -#define FATIO_H_INCLUDED - -#include "fat.h" - -extern int fat_read_fragments (PedFileSystem* fs, char* buf, FatFragment frag, - FatFragment count); -extern int fat_write_fragments (PedFileSystem* fs, char* buf, FatFragment frag, - FatFragment count); -extern int fat_write_sync_fragments (PedFileSystem* fs, char* buf, - FatFragment frag, FatFragment count); - -extern int fat_read_fragment (PedFileSystem* fs, char* buf, FatFragment frag); -extern int fat_write_fragment (PedFileSystem* fs, char* buf, FatFragment frag); -extern int fat_write_sync_fragment (PedFileSystem* fs, char* buf, - FatFragment frag); - -extern int fat_read_clusters (PedFileSystem* fs, char* buf, FatCluster cluster, - FatCluster count); -extern int fat_write_clusters (PedFileSystem* fs, char* buf, FatCluster cluster, - FatCluster count); -extern int fat_write_sync_clusters (PedFileSystem* fs, char* buf, - FatCluster cluster, FatCluster count); - -extern int fat_read_cluster (PedFileSystem* fs, char *buf, FatCluster cluster); -extern int fat_write_cluster (PedFileSystem* fs, char *buf, FatCluster cluster); -extern int fat_write_sync_cluster (PedFileSystem* fs, char *buf, - FatCluster cluster); - -#endif /* FATIO_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/resize.c b/usr/src/lib/libparted/common/libparted/fs/fat/resize.c deleted file mode 100644 index 7386948de1..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/resize.c +++ /dev/null @@ -1,877 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" -#include "traverse.h" -#include "count.h" -#include "fatio.h" -#include "calc.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef DISCOVER_ONLY - -/* Recursively builds (i.e. makes consistent) the duplicated directory tree - * (leaving the original directory tree in tact) - */ -static int -fat_construct_directory (FatOpContext* ctx, FatTraverseInfo* trav_info) -{ - FatTraverseInfo* sub_dir_info; - FatDirEntry* dir_entry; - FatCluster old_first_cluster; - - while ( (dir_entry = fat_traverse_next_dir_entry (trav_info)) ) { - if (fat_dir_entry_is_null_term (dir_entry)) - break; - if (!fat_dir_entry_has_first_cluster (dir_entry, ctx->old_fs)) - continue; - - fat_traverse_mark_dirty (trav_info); - - old_first_cluster = fat_dir_entry_get_first_cluster (dir_entry, - ctx->old_fs); - fat_dir_entry_set_first_cluster (dir_entry, ctx->new_fs, - fat_op_context_map_cluster (ctx, old_first_cluster)); - - if (fat_dir_entry_is_directory (dir_entry) - && dir_entry->name [0] != '.') { - sub_dir_info - = fat_traverse_directory (trav_info, dir_entry); - if (!sub_dir_info) - return 0; - if (!fat_construct_directory (ctx, sub_dir_info)) - return 0; - } - } - /* remove "stale" entries at the end */ - while ((dir_entry = fat_traverse_next_dir_entry (trav_info))) { - memset (dir_entry, 0, sizeof (FatDirEntry)); - fat_traverse_mark_dirty (trav_info); - } - fat_traverse_complete (trav_info); - return 1; -} - -static int -duplicate_legacy_root_dir (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - - PED_ASSERT (old_fs_info->root_dir_sector_count - == new_fs_info->root_dir_sector_count, return 0); - - if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer, - old_fs_info->root_dir_offset, - old_fs_info->root_dir_sector_count)) - return 0; - - if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer, - new_fs_info->root_dir_offset, - new_fs_info->root_dir_sector_count)) - return 0; - - return 1; -} - -/* - Constructs the new directory tree for legacy (FAT16) file systems. -*/ -static int -fat_construct_legacy_root (FatOpContext* ctx) -{ - FatTraverseInfo* trav_info; - - if (!duplicate_legacy_root_dir (ctx)) - return 0; - trav_info = fat_traverse_begin (ctx->new_fs, FAT_ROOT, "\\"); - return fat_construct_directory (ctx, trav_info); -} - -/* - Constructs the new directory tree for new (FAT32) file systems. -*/ -static int -fat_construct_root (FatOpContext* ctx) -{ - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatTraverseInfo* trav_info; - - trav_info = fat_traverse_begin (ctx->new_fs, new_fs_info->root_cluster, - "\\"); - fat_construct_directory (ctx, trav_info); - return 1; -} - -/* Converts the root directory between FAT16 and FAT32. NOTE: this code - * can also do no conversion. I'm leaving fat_construct_directory(), because - * it's really pretty :-) It also leaves a higher chance of deleted file - * recovery, because it doesn't remove redundant entries. (We do this here, - * because brain-damaged FAT16 has an arbitary limit on root directory entries, - * so we save room) - */ -static int -fat_convert_directory (FatOpContext* ctx, FatTraverseInfo* old_trav, - FatTraverseInfo* new_trav) -{ - FatTraverseInfo* sub_old_dir_trav; - FatTraverseInfo* sub_new_dir_trav; - FatDirEntry* new_dir_entry; - FatDirEntry* old_dir_entry; - FatCluster old_first_cluster; - - while ( (old_dir_entry = fat_traverse_next_dir_entry (old_trav)) ) { - if (fat_dir_entry_is_null_term (old_dir_entry)) - break; - if (!fat_dir_entry_is_active (old_dir_entry)) - continue; - - new_dir_entry = fat_traverse_next_dir_entry (new_trav); - if (!new_dir_entry) { - return ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("There's not enough room in the root " - "directory for all of the files. Either " - "cancel, or ignore to lose the files.")) - == PED_EXCEPTION_IGNORE; - } - - *new_dir_entry = *old_dir_entry; - fat_traverse_mark_dirty (new_trav); - - if (!fat_dir_entry_has_first_cluster (old_dir_entry, - ctx->old_fs)) - continue; - - old_first_cluster = fat_dir_entry_get_first_cluster ( - old_dir_entry, ctx->old_fs); - fat_dir_entry_set_first_cluster (new_dir_entry, ctx->new_fs, - fat_op_context_map_cluster (ctx, old_first_cluster)); - - if (fat_dir_entry_is_directory (old_dir_entry) - && old_dir_entry->name [0] != '.') { - sub_old_dir_trav - = fat_traverse_directory (old_trav, old_dir_entry); - sub_new_dir_trav - = fat_traverse_directory (new_trav, new_dir_entry); - if (!sub_old_dir_trav || !sub_new_dir_trav) - return 0; - - if (!fat_convert_directory (ctx, sub_old_dir_trav, - sub_new_dir_trav)) - return 0; - } - } - - /* remove "stale" entries at the end, just in case there is some - * overlap - */ - while ((new_dir_entry = fat_traverse_next_dir_entry (new_trav))) { - memset (new_dir_entry, 0, sizeof (FatDirEntry)); - fat_traverse_mark_dirty (new_trav); - } - - fat_traverse_complete (old_trav); - fat_traverse_complete (new_trav); - return 1; -} - -static void -clear_cluster (PedFileSystem* fs, FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - memset (fs_info->buffer, 0, fs_info->cluster_size); - fat_write_cluster (fs, fs_info->buffer, cluster); -} - -/* This MUST be called BEFORE the fat_construct_new_fat(), because cluster - * allocation depend on the old FAT. The reason is, old clusters may - * still be needed during the resize, (particularly clusters in the directory - * tree) even if they will be discarded later. - */ -static int -alloc_root_dir (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatCluster i; - FatCluster cluster; - FatCluster cluster_count; - - PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT32, return 0); - - cluster_count = ped_div_round_up ( - PED_MAX (16, old_fs_info->root_dir_sector_count), - new_fs_info->cluster_sectors); - - for (i = 0; i < cluster_count; i++) { - cluster = fat_table_alloc_check_cluster (new_fs_info->fat, - ctx->new_fs); - if (!cluster) - return 0; - ctx->new_root_dir [i] = cluster; - clear_cluster (ctx->new_fs, cluster); - } - ctx->new_root_dir [i] = 0; - new_fs_info->root_cluster = ctx->new_root_dir [0]; - return 1; -} - -/* when converting FAT32 -> FAT16 - * fat_duplicate clusters() duplicated the root directory unnecessarily. - * Let's free it. - * - * This must be called AFTER fat_construct_new_fat(). (otherwise, our - * changes just get overwritten) - */ -static int -free_root_dir (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatCluster old_cluster; - FatFragment i; - - PED_ASSERT (old_fs_info->fat_type == FAT_TYPE_FAT32, return 0); - PED_ASSERT (new_fs_info->fat_type == FAT_TYPE_FAT16, return 0); - - for (old_cluster = old_fs_info->root_cluster; - !fat_table_is_eof (old_fs_info->fat, old_cluster); - old_cluster = fat_table_get (old_fs_info->fat, old_cluster)) { - FatFragment old_frag; - old_frag = fat_cluster_to_frag (ctx->old_fs, old_cluster); - for (i = 0; i < new_fs_info->cluster_frags; i++) { - FatFragment new_frag; - FatCluster new_clst; - new_frag = fat_op_context_map_fragment (ctx, - old_frag + i); - new_clst = fat_frag_to_cluster (ctx->old_fs, new_frag); - if (!fat_table_set_avail (new_fs_info->fat, new_clst)) - return 0; - } - } - - return 1; -} - -static int -fat_clear_root_dir (PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - int i; - - PED_ASSERT (fs_info->fat_type == FAT_TYPE_FAT16, return 0); - PED_ASSERT (fs_info->root_dir_sector_count, return 0); - - memset (fs_info->buffer, 0, 512); - - for (i = 0; i < fs_info->root_dir_sector_count; i++) { - if (!ped_geometry_write (fs->geom, fs_info->buffer, - fs_info->root_dir_offset + i, 1)) { - if (ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Error writing to the root directory.")) - == PED_EXCEPTION_CANCEL) - return 0; - } - } - return 1; -} - -static int -fat_construct_converted_tree (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatTraverseInfo* old_trav_info; - FatTraverseInfo* new_trav_info; - - if (new_fs_info->fat_type == FAT_TYPE_FAT32) { - new_trav_info = fat_traverse_begin (ctx->new_fs, - new_fs_info->root_cluster, "\\"); - old_trav_info = fat_traverse_begin (ctx->old_fs, FAT_ROOT, - "\\"); - } else { - fat_clear_root_dir (ctx->new_fs); - new_trav_info = fat_traverse_begin (ctx->new_fs, FAT_ROOT, - "\\"); - old_trav_info = fat_traverse_begin (ctx->old_fs, - old_fs_info->root_cluster, "\\"); - } - if (!new_trav_info || !old_trav_info) - return 0; - if (!fat_convert_directory (ctx, old_trav_info, new_trav_info)) - return 0; - return 1; -} - -/* - Constructs the new directory tree to match the new file locations. -*/ -static int -fat_construct_dir_tree (FatOpContext* ctx) -{ - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - - if (new_fs_info->fat_type == old_fs_info->fat_type) { - switch (old_fs_info->fat_type) { - case FAT_TYPE_FAT12: - PED_ASSERT (0, (void) 0); - break; - - case FAT_TYPE_FAT16: - return fat_construct_legacy_root (ctx); - - case FAT_TYPE_FAT32: - return fat_construct_root (ctx); - } - } else { - return fat_construct_converted_tree (ctx); - } - - return 0; -} - -static FatFragment -_get_next_old_frag (FatOpContext* ctx, FatFragment frag) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatCluster cluster; - FatCluster next_cluster; - - if ((frag + 1) % old_fs_info->cluster_frags != 0) { - if (fat_is_fragment_active (ctx->old_fs, frag + 1)) - return frag + 1; - else - return -1; - } else { - cluster = fat_frag_to_cluster (ctx->old_fs, frag); - next_cluster = fat_table_get (old_fs_info->fat, cluster); - - if (fat_table_is_eof (old_fs_info->fat, next_cluster)) - return -1; - else - return fat_cluster_to_frag (ctx->old_fs, next_cluster); - } -} - -/* - Constructs the new fat for the resized file system. -*/ -static int -fat_construct_new_fat (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - FatFragment old_frag; - FatCluster new_cluster; - FatFragment new_frag; - FatFragment old_next_frag; - FatFragment new_next_frag; - FatCluster new_next_cluster; - FatClusterFlag flag; - int i; - - fat_table_clear (new_fs_info->fat); - if (!fat_table_set_cluster_count (new_fs_info->fat, - new_fs_info->cluster_count)) - return 0; - - for (old_frag = 0; old_frag < old_fs_info->frag_count; old_frag++) { - flag = fat_get_fragment_flag (ctx->old_fs, old_frag); - if (flag == FAT_FLAG_FREE) - continue; - if (flag == FAT_FLAG_BAD) { - new_frag = fat_op_context_map_static_fragment ( - ctx, old_frag); - if (new_frag == -1) - continue; - new_cluster = fat_frag_to_cluster (ctx->new_fs, - new_frag); - fat_table_set_bad (new_fs_info->fat, new_cluster); - continue; - } - - new_frag = fat_op_context_map_fragment (ctx, old_frag); - new_cluster = fat_frag_to_cluster (ctx->new_fs, new_frag); - - old_next_frag = _get_next_old_frag (ctx, old_frag); - if (old_next_frag == -1) { - fat_table_set_eof (new_fs_info->fat, new_cluster); - continue; - } - - new_next_frag = fat_op_context_map_fragment (ctx, - old_next_frag); - PED_ASSERT (new_next_frag != -1, return 0); - - new_next_cluster = fat_frag_to_cluster (ctx->new_fs, - new_next_frag); - PED_ASSERT (new_next_cluster != new_cluster, return 0); - - fat_table_set (new_fs_info->fat, new_cluster, new_next_cluster); - } - -#if 0 -#ifdef PED_VERBOSE - for (old_cluster=2; old_cluster < old_fs_info->cluster_count+2; - old_cluster++) { - if (fat_table_is_available (old_fs_info->fat, old_cluster)) - continue; - - printf ("%d->%d\t(next: %d->%d)\n", - old_cluster, - ctx->remap [old_cluster], - fat_table_get (old_fs_info->fat, old_cluster), - fat_table_get (new_fs_info->fat, - ctx->remap [old_cluster])); - } -#endif /* PED_VERBOSE */ -#endif - - if (old_fs_info->fat_type == FAT_TYPE_FAT32 - && new_fs_info->fat_type == FAT_TYPE_FAT32) { - new_fs_info->root_cluster - = fat_op_context_map_cluster (ctx, - old_fs_info->root_cluster); - } - - if (old_fs_info->fat_type == FAT_TYPE_FAT16 - && new_fs_info->fat_type == FAT_TYPE_FAT32) { - for (i=0; ctx->new_root_dir[i+1]; i++) { - fat_table_set (new_fs_info->fat, - ctx->new_root_dir[i], - ctx->new_root_dir[i+1]); - } - fat_table_set_eof (new_fs_info->fat, ctx->new_root_dir[i]); - } - - return 1; -} - -static int -ask_type (PedFileSystem* fs, int fat16_ok, int fat32_ok, FatType* out_fat_type) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedExceptionOption status; - char* fat16_msg; - char* fat32_msg; - - if (fs_info->fat_type == FAT_TYPE_FAT16) - fat16_msg = _("If you leave your file system as FAT16, " - "then you will have no problems."); - else - fat16_msg = _("If you convert to FAT16, and MS Windows " - "is installed on this partition, then " - "you must re-install the MS Windows boot " - "loader. If you want to do this, you " - "should consult the Parted manual (or " - "your distribution's manual)."); - - if (fs_info->fat_type == FAT_TYPE_FAT32) - fat32_msg = _("If you leave your file system as FAT32, " - "then you will not introduce any new " - "problems."); - else - fat32_msg = _("If you convert to FAT32, and MS Windows " - "is installed on this partition, then " - "you must re-install the MS Windows boot " - "loader. If you want to do this, you " - "should consult the Parted manual (or " - "your distribution's manual). Also, " - "converting to FAT32 will make the file " - "system unreadable by MS DOS, MS Windows " - "95a, and MS Windows NT."); - - if (fat16_ok && fat32_ok) { - status = ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_YES_NO_CANCEL, - _("%s %s %s"), - _("Would you like to use FAT32?"), - fat16_msg, - fat32_msg); - - switch (status) { - case PED_EXCEPTION_YES: - *out_fat_type = FAT_TYPE_FAT32; - return 1; - - case PED_EXCEPTION_NO: - *out_fat_type = FAT_TYPE_FAT16; - return 1; - - case PED_EXCEPTION_UNHANDLED: - *out_fat_type = fs_info->fat_type; - return 1; - - case PED_EXCEPTION_CANCEL: - return 0; - - default: - PED_ASSERT (0, (void) 0); - break; - } - } - - if (fat16_ok) { - if (fs_info->fat_type != FAT_TYPE_FAT16) { - status = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK_CANCEL, - _("%s %s"), - _("The file system can only be resized to this " - "size by converting to FAT16."), - fat16_msg); - if (status == PED_EXCEPTION_CANCEL) - return 0; - } - *out_fat_type = FAT_TYPE_FAT16; - return 1; - } - - if (fat32_ok) { - if (fs_info->fat_type != FAT_TYPE_FAT32) { - status = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK_CANCEL, - _("%s %s"), - _("The file system can only be resized to this " - "size by converting to FAT32."), - fat32_msg); - if (status == PED_EXCEPTION_CANCEL) - return 0; - } - *out_fat_type = FAT_TYPE_FAT32; - return 1; - } - - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("GNU Parted cannot resize this partition to this size. " - "We're working on it!")); - - return 0; -} - -/* For resize operations: determine if the file system must be FAT16 or FAT32, - * or either. If the new file system must be FAT32, then query for - * confirmation. If either file system can be used, query for which one. - */ -static int -get_fat_type (PedFileSystem* fs, const PedGeometry* new_geom, - FatType* out_fat_type) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - PedSector fat16_cluster_sectors; - PedSector fat32_cluster_sectors; - FatCluster dummy_cluster_count; - PedSector dummy_fat_sectors; - int fat16_ok; - int fat32_ok; - - fat16_ok = fat_calc_resize_sizes ( - new_geom, - fs_info->cluster_sectors, - FAT_TYPE_FAT16, - fs_info->root_dir_sector_count, - fs_info->cluster_sectors, - &fat16_cluster_sectors, - &dummy_cluster_count, - &dummy_fat_sectors); - - fat32_ok = fat_calc_resize_sizes ( - new_geom, - fs_info->cluster_sectors, - FAT_TYPE_FAT32, - fs_info->root_dir_sector_count, - fs_info->cluster_sectors, - &fat32_cluster_sectors, - &dummy_cluster_count, - &dummy_fat_sectors); - - return ask_type (fs, fat16_ok, fat32_ok, out_fat_type); -} - -/* Creates the PedFileSystem struct for the new resized file system, and - sticks it in a FatOpContext. At the end of the process, the original - (ctx->old_fs) is destroyed, and replaced with the new one (ctx->new_fs). - */ -static FatOpContext* -create_resize_context (PedFileSystem* fs, const PedGeometry* new_geom) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatSpecific* new_fs_info; - PedFileSystem* new_fs; - PedSector new_cluster_sectors; - FatCluster new_cluster_count; - PedSector new_fat_sectors; - FatType new_fat_type; - PedSector root_dir_sector_count; - FatOpContext* context; - - /* hypothetical number of root dir sectors, if we end up using - * FAT16 - */ - if (fs_info->root_dir_sector_count) - root_dir_sector_count = fs_info->root_dir_sector_count; - else - root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT - * sizeof (FatDirEntry) / 512; - - if (!get_fat_type (fs, new_geom, &new_fat_type)) - return 0; - - fat_calc_resize_sizes (new_geom, fs_info->cluster_sectors, new_fat_type, - root_dir_sector_count, fs_info->cluster_sectors, - &new_cluster_sectors, &new_cluster_count, &new_fat_sectors); - - if (!fat_check_resize_geometry (fs, new_geom, new_cluster_sectors, - new_cluster_count)) - goto error; - - new_fs = fat_alloc (new_geom); - if (!new_fs) - goto error; - - new_fs_info = FAT_SPECIFIC (new_fs); - if (!new_fs_info) - goto error_free_new_fs; - -/* preserve boot code, etc. */ - memcpy (&new_fs_info->boot_sector, &fs_info->boot_sector, - sizeof (FatBootSector)); - memcpy (&new_fs_info->info_sector, &fs_info->info_sector, - sizeof (FatInfoSector)); - - new_fs_info->logical_sector_size = fs_info->logical_sector_size; - new_fs_info->sector_count = new_geom->length; - - new_fs_info->sectors_per_track = fs_info->sectors_per_track; - new_fs_info->heads = fs_info->heads; - - new_fs_info->cluster_size = new_cluster_sectors * 512; - new_fs_info->cluster_sectors = new_cluster_sectors; - new_fs_info->cluster_count = new_cluster_count; - new_fs_info->dir_entries_per_cluster = fs_info->dir_entries_per_cluster; - - new_fs_info->fat_type = new_fat_type; - new_fs_info->fat_table_count = 2; - new_fs_info->fat_sectors = new_fat_sectors; - - /* what about copying? */ - new_fs_info->serial_number = fs_info->serial_number; - - if (new_fs_info->fat_type == FAT_TYPE_FAT32) { - new_fs_info->info_sector_offset = 1; - new_fs_info->boot_sector_backup_offset = 6; - - new_fs_info->root_dir_offset = 0; - new_fs_info->root_dir_entry_count = 0; - new_fs_info->root_dir_sector_count = 0; - - /* we add calc_align_sectors to push the cluster_offset - forward, to keep the clusters aligned between the new - and old file systems - */ - new_fs_info->fat_offset - = fat_min_reserved_sector_count (FAT_TYPE_FAT32) - + fat_calc_align_sectors (new_fs, fs); - - new_fs_info->cluster_offset - = new_fs_info->fat_offset - + 2 * new_fs_info->fat_sectors; - } else { - new_fs_info->root_dir_sector_count = root_dir_sector_count; - new_fs_info->root_dir_entry_count - = root_dir_sector_count * 512 / sizeof (FatDirEntry); - - new_fs_info->fat_offset - = fat_min_reserved_sector_count (FAT_TYPE_FAT16) - + fat_calc_align_sectors (new_fs, fs); - - new_fs_info->root_dir_offset = new_fs_info->fat_offset - + 2 * new_fs_info->fat_sectors; - - new_fs_info->cluster_offset = new_fs_info->root_dir_offset - + new_fs_info->root_dir_sector_count; - } - - new_fs_info->total_dir_clusters = fs_info->total_dir_clusters; - - context = fat_op_context_new (new_fs, fs); - if (!context) - goto error_free_new_fs_info; - - if (!fat_op_context_create_initial_fat (context)) - goto error_free_context; - - if (!fat_alloc_buffers (new_fs)) - goto error_free_fat; - - return context; - -error_free_fat: - fat_table_destroy (new_fs_info->fat); -error_free_context: - ped_free (context); -error_free_new_fs_info: - ped_free (new_fs_info); -error_free_new_fs: - ped_free (new_fs); -error: - return NULL; -} - -static int -resize_context_assimilate (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - - fat_free_buffers (ctx->old_fs); - fat_table_destroy (old_fs_info->fat); - ped_free (old_fs_info); - ped_geometry_destroy (ctx->old_fs->geom); - - ctx->old_fs->type_specific = ctx->new_fs->type_specific; - ctx->old_fs->geom = ctx->new_fs->geom; - ctx->old_fs->type = (new_fs_info->fat_type == FAT_TYPE_FAT16) - ? &fat16_type - : &fat32_type; - - ped_free (ctx->new_fs); - - fat_op_context_destroy (ctx); - - return 1; -} - -static int -resize_context_abort (FatOpContext* ctx) -{ - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - - fat_free_buffers (ctx->new_fs); - fat_table_destroy (new_fs_info->fat); - ped_free (new_fs_info); - ped_geometry_destroy (ctx->new_fs->geom); - ped_free (ctx->new_fs); - - fat_op_context_destroy (ctx); - - return 1; -} - -/* copies the "hidden" sectors, between the boot sector and the FAT. Required, - * for the Windows 98 FAT32 boot loader - */ -int -_copy_hidden_sectors (FatOpContext* ctx) -{ - FatSpecific* old_fs_info = FAT_SPECIFIC (ctx->old_fs); - FatSpecific* new_fs_info = FAT_SPECIFIC (ctx->new_fs); - PedSector first = 1; - PedSector last; - PedSector count; - - /* nothing to copy for FAT16 */ - if (old_fs_info->fat_type == FAT_TYPE_FAT16 - || new_fs_info->fat_type == FAT_TYPE_FAT16) - return 1; - - last = PED_MIN (old_fs_info->fat_offset, new_fs_info->fat_offset) - 1; - count = last - first + 1; - - PED_ASSERT (count < BUFFER_SIZE, return 0); - - if (!ped_geometry_read (ctx->old_fs->geom, old_fs_info->buffer, - first, count)) - return 0; - if (!ped_geometry_write (ctx->new_fs->geom, old_fs_info->buffer, - first, count)) - return 0; - return 1; -} - -int -fat_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatSpecific* new_fs_info; - FatOpContext* ctx; - PedFileSystem* new_fs; - - ctx = create_resize_context (fs, geom); - if (!ctx) - goto error; - new_fs = ctx->new_fs; - new_fs_info = FAT_SPECIFIC (new_fs); - - if (!fat_duplicate_clusters (ctx, timer)) - goto error_abort_ctx; - if (fs_info->fat_type == FAT_TYPE_FAT16 - && new_fs_info->fat_type == FAT_TYPE_FAT32) { - if (!alloc_root_dir (ctx)) - goto error_abort_ctx; - } - if (!fat_construct_new_fat (ctx)) - goto error_abort_ctx; - if (fs_info->fat_type == FAT_TYPE_FAT32 - && new_fs_info->fat_type == FAT_TYPE_FAT16) { - if (!free_root_dir (ctx)) - goto error_abort_ctx; - } - if (!fat_construct_dir_tree (ctx)) - goto error_abort_ctx; - if (!fat_table_write_all (new_fs_info->fat, new_fs)) - goto error_abort_ctx; - - _copy_hidden_sectors (ctx); - fat_boot_sector_generate (&new_fs_info->boot_sector, new_fs); - fat_boot_sector_write (&new_fs_info->boot_sector, new_fs); - if (new_fs_info->fat_type == FAT_TYPE_FAT32) { - fat_info_sector_generate (&new_fs_info->info_sector, new_fs); - fat_info_sector_write (&new_fs_info->info_sector, new_fs); - } - - if (!resize_context_assimilate (ctx)) - goto error; - - return 1; - -error_abort_ctx: - resize_context_abort (ctx); -error: - return 0; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/table.c b/usr/src/lib/libparted/common/libparted/fs/fat/table.c deleted file mode 100644 index e4a95944bc..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/table.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include "fat.h" - -#ifndef DISCOVER_ONLY - -FatTable* -fat_table_new (FatType fat_type, FatCluster size) -{ - FatTable* ft; - int entry_size = fat_table_entry_size (fat_type); - - ft = (FatTable*) ped_malloc (sizeof (FatTable)); - if (!ft) return NULL; - - ft->cluster_count = ft->free_cluster_count = size - 2; - -/* ensure there's some free room on the end, to finish off the sector */ - ft->size = ped_div_round_up (size * entry_size, 512) * 512 / entry_size; - ft->fat_type = fat_type; - ft->raw_size = ft->size * entry_size; - - ft->table = ped_malloc (ft->raw_size); - if (!ft->table) { - ped_free (ft); - return NULL; - } - - fat_table_clear (ft); - return ft; -} - -void -fat_table_destroy (FatTable* ft) -{ - ped_free (ft->table); - ped_free (ft); -} - -FatTable* -fat_table_duplicate (const FatTable* ft) -{ - FatTable* dup; - - dup = fat_table_new (ft->fat_type, ft->size); - if (!dup) return NULL; - - dup->cluster_count = ft->cluster_count; - dup->free_cluster_count = ft->free_cluster_count; - dup->bad_cluster_count = ft->bad_cluster_count; - dup->last_alloc = ft->last_alloc; - - memcpy (dup->table, ft->table, ft->raw_size); - - return dup; -} - -void -fat_table_clear (FatTable* ft) -{ - memset (ft->table, 0, ft->raw_size); - - fat_table_set (ft, 0, 0x0ffffff8); - fat_table_set (ft, 1, 0x0fffffff); - - ft->free_cluster_count = ft->cluster_count; - ft->bad_cluster_count = 0; - ft->last_alloc = 1; -} - -int -fat_table_set_cluster_count (FatTable* ft, FatCluster new_cluster_count) -{ - PED_ASSERT (new_cluster_count + 2 <= ft->size, return 0); - - ft->cluster_count = new_cluster_count; - return fat_table_count_stats (ft); -} - -int -fat_table_count_stats (FatTable* ft) -{ - FatCluster i; - - PED_ASSERT (ft->cluster_count + 2 <= ft->size, return 0); - - ft->free_cluster_count = 0; - ft->bad_cluster_count = 0; - - for (i=2; i < ft->cluster_count + 2; i++) { - if (fat_table_is_available (ft, i)) - ft->free_cluster_count++; - if (fat_table_is_bad (ft, i)) - ft->bad_cluster_count++; - } - return 1; -} - -int -fat_table_read (FatTable* ft, const PedFileSystem* fs, int table_num) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (ft->raw_size >= fs_info->fat_sectors * 512, return 0); - - memset (ft->table, 0, ft->raw_size); - - if (!ped_geometry_read (fs->geom, (void *) ft->table, - fs_info->fat_offset - + table_num * fs_info->fat_sectors, - fs_info->fat_sectors)) - return 0; - - if ( *((unsigned char*) ft->table) != fs_info->boot_sector.media) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("FAT %d media %x doesn't match the boot sector's " - "media %x. You should probably run scandisk."), - (int) table_num + 1, - (int) *((unsigned char*) ft->table), - (int) fs_info->boot_sector.media) - != PED_EXCEPTION_IGNORE) - return 0; - } - - ft->cluster_count = fs_info->cluster_count; - - fat_table_count_stats (ft); - - return 1; -} - -int -fat_table_write (const FatTable* ft, PedFileSystem* fs, int table_num) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - PED_ASSERT (ft->raw_size >= fs_info->fat_sectors * 512, return 0); - - if (!ped_geometry_write (fs->geom, (void *) ft->table, - fs_info->fat_offset - + table_num * fs_info->fat_sectors, - fs_info->fat_sectors)) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - - return 1; -} - -int -fat_table_write_all (const FatTable* ft, PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - int i; - - for (i = 0; i < fs_info->fat_table_count; i++) { - if (!fat_table_write (ft, fs, i)) - return 0; - } - - return 1; -} - -int -fat_table_compare (const FatTable* a, const FatTable* b) -{ - FatCluster i; - - if (a->cluster_count != b->cluster_count) - return 0; - - for (i = 0; i < a->cluster_count + 2; i++) { - if (fat_table_get (a, i) != fat_table_get (b, i)) - return 0; - } - - return 1; -} - -static int -_test_code_available (const FatTable* ft, FatCluster code) -{ - return code == 0; -} - -static int -_test_code_bad (const FatTable* ft, FatCluster code) -{ - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - if (code == 0xff7) return 1; - break; - - case FAT_TYPE_FAT16: - if (code == 0xfff7) return 1; - break; - - case FAT_TYPE_FAT32: - if (code == 0x0ffffff7) return 1; - break; - } - return 0; -} - -static int -_test_code_eof (const FatTable* ft, FatCluster code) -{ - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - if (code >= 0xff7) return 1; - break; - - case FAT_TYPE_FAT16: - if (code >= 0xfff7) return 1; - break; - - case FAT_TYPE_FAT32: - if (code >= 0x0ffffff7) return 1; - break; - } - return 0; -} - -void -_update_stats (FatTable* ft, FatCluster cluster, FatCluster value) -{ - if (_test_code_available (ft, value) - && !fat_table_is_available (ft, cluster)) { - ft->free_cluster_count++; - if (fat_table_is_bad (ft, cluster)) - ft->bad_cluster_count--; - } - - if (!_test_code_available (ft, value) - && fat_table_is_available (ft, cluster)) { - ft->free_cluster_count--; - if (_test_code_bad (ft, cluster)) - ft->bad_cluster_count--; - } -} - -int -fat_table_set (FatTable* ft, FatCluster cluster, FatCluster value) -{ - if (cluster >= ft->cluster_count + 2) { - ped_exception_throw (PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("fat_table_set: cluster %ld outside " - "file system"), - (long) cluster); - return 0; - } - - _update_stats (ft, cluster, value); - - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - PED_ASSERT (0, (void) 0); - break; - - case FAT_TYPE_FAT16: - ((unsigned short *) ft->table) [cluster] - = PED_CPU_TO_LE16 (value); - break; - - case FAT_TYPE_FAT32: - ((unsigned int *) ft->table) [cluster] - = PED_CPU_TO_LE32 (value); - break; - } - return 1; -} - -FatCluster -fat_table_get (const FatTable* ft, FatCluster cluster) -{ - if (cluster >= ft->cluster_count + 2) { - ped_exception_throw (PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("fat_table_get: cluster %ld outside " - "file system"), - (long) cluster); - exit (1); /* FIXME */ - } - - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - PED_ASSERT (0, (void) 0); - break; - - case FAT_TYPE_FAT16: - return PED_LE16_TO_CPU - (((unsigned short *) ft->table) [cluster]); - - case FAT_TYPE_FAT32: - return PED_LE32_TO_CPU - (((unsigned int *) ft->table) [cluster]); - } - - return 0; -} - -FatCluster -fat_table_alloc_cluster (FatTable* ft) -{ - FatCluster i; - FatCluster cluster; - -/* hack: assumes the first two FAT entries are marked as used (which they - * always should be) - */ - for (i=1; i < ft->cluster_count + 1; i++) { - cluster = (i + ft->last_alloc) % ft->cluster_count; - if (fat_table_is_available (ft, cluster)) { - ft->last_alloc = cluster; - return cluster; - } - } - - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("fat_table_alloc_cluster: no free clusters")); - return 0; -} - -FatCluster -fat_table_alloc_check_cluster (FatTable* ft, PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster result; - - while (1) { - result = fat_table_alloc_cluster (ft); - if (!result) - return 0; - if (fat_read_cluster (fs, fs_info->buffer, result)) - return result; - fat_table_set_bad (ft, result); - } -} - -/* - returns true if is marked as bad -*/ -int -fat_table_is_bad (const FatTable* ft, FatCluster cluster) -{ - return _test_code_bad (ft, fat_table_get (ft, cluster)); -} - -/* - returns true if represents an EOF marker -*/ -int -fat_table_is_eof (const FatTable* ft, FatCluster cluster) -{ - return _test_code_eof (ft, cluster); -} - -/* - returns true if is available. -*/ -int -fat_table_is_available (const FatTable* ft, FatCluster cluster) -{ - return _test_code_available (ft, fat_table_get (ft, cluster)); -} - -/* - returns true if is empty. Note that this includes bad clusters. -*/ -int -fat_table_is_empty (const FatTable* ft, FatCluster cluster) -{ - return fat_table_is_available (ft, cluster) - || fat_table_is_bad (ft, cluster); -} - -/* - returns true if is being used for something constructive. -*/ -int -fat_table_is_active (const FatTable* ft, FatCluster cluster) -{ - return !fat_table_is_bad (ft, cluster) - && !fat_table_is_available (ft, cluster); -} - -/* - marks as the last cluster in the chain -*/ -int -fat_table_set_eof (FatTable* ft, FatCluster cluster) -{ - - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - PED_ASSERT (0, (void) 0); - break; - - case FAT_TYPE_FAT16: - return fat_table_set (ft, cluster, 0xfff8); - - case FAT_TYPE_FAT32: - return fat_table_set (ft, cluster, 0x0fffffff); - } - - return 0; -} - -/* - Marks a clusters as unusable, due to physical disk damage. -*/ -int -fat_table_set_bad (FatTable* ft, FatCluster cluster) -{ - if (!fat_table_is_bad (ft, cluster)) - ft->bad_cluster_count++; - - switch (ft->fat_type) { - case FAT_TYPE_FAT12: - return fat_table_set (ft, cluster, 0xff7); - - case FAT_TYPE_FAT16: - return fat_table_set (ft, cluster, 0xfff7); - - case FAT_TYPE_FAT32: - return fat_table_set (ft, cluster, 0x0ffffff7); - } - - return 0; -} - -/* - marks as unused/free/available -*/ -int -fat_table_set_avail (FatTable* ft, FatCluster cluster) -{ - return fat_table_set (ft, cluster, 0); -} - -#endif /* !DISCOVER_ONLY */ - -int -fat_table_entry_size (FatType fat_type) -{ - switch (fat_type) { - case FAT_TYPE_FAT12: - return 2; /* FIXME: how? */ - - case FAT_TYPE_FAT16: - return 2; - - case FAT_TYPE_FAT32: - return 4; - } - - return 0; -} - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/table.h b/usr/src/lib/libparted/common/libparted/fs/fat/table.h deleted file mode 100644 index b30a4d54c3..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/table.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef PED_FAT_TABLE_H_INCLUDED -#define PED_FAT_TABLE_H_INCLUDED - -typedef struct _FatTable FatTable; - -#include "fat.h" - -struct _FatTable { - void* table; - FatCluster size; - int raw_size; - - FatType fat_type; - FatCluster cluster_count; - FatCluster free_cluster_count; - FatCluster bad_cluster_count; - - FatCluster last_alloc; -}; - -extern FatTable* fat_table_new (FatType fat_type, FatCluster size); -extern FatTable* fat_table_duplicate (const FatTable* ft); -extern void fat_table_destroy (FatTable* ft); -extern void fat_table_clear (FatTable* ft); -extern int fat_table_set_cluster_count (FatTable* ft, - FatCluster new_cluster_count); - -extern int fat_table_read (FatTable* ft, const PedFileSystem* fs, - int table_num); -extern int fat_table_write (const FatTable* ft, PedFileSystem* fs, - int table_num); -extern int fat_table_write_all (const FatTable* ft, PedFileSystem* fs); -extern int fat_table_compare (const FatTable* a, const FatTable* b); -extern int fat_table_count_stats (FatTable* ft); - -extern FatCluster fat_table_get (const FatTable* ft, FatCluster cluster); -extern int fat_table_set (FatTable* ft, FatCluster cluster, FatCluster value); - -extern FatCluster fat_table_alloc_cluster (FatTable* ft); -extern FatCluster fat_table_alloc_check_cluster (FatTable* ft, - PedFileSystem* fs); - -extern int fat_table_is_bad (const FatTable* ft, FatCluster cluster); -extern int fat_table_is_eof (const FatTable* ft, FatCluster cluster); -extern int fat_table_is_empty (const FatTable* ft, FatCluster cluster); -extern int fat_table_is_available (const FatTable* ft, FatCluster cluster); -extern int fat_table_is_active (const FatTable* ft, FatCluster cluster); - -extern int fat_table_set_eof (FatTable* ft, FatCluster cluster); -extern int fat_table_set_avail (FatTable* ft, FatCluster cluster); -extern int fat_table_set_bad (FatTable* ft, FatCluster cluster); - -extern int fat_table_entry_size (FatType fat_type); - -#endif /* PED_FAT_TABLE_H_INCLUDED */ - diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/traverse.c b/usr/src/lib/libparted/common/libparted/fs/fat/traverse.c deleted file mode 100644 index 3d2e2b5e80..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/traverse.c +++ /dev/null @@ -1,365 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "fat.h" -#include "traverse.h" - -#include -#include -#include - -#ifndef DISCOVER_ONLY - -#define NO_CLUSTER -1 - -static char tmp_buffer [4096]; - -int -fat_traverse_entries_per_buffer (FatTraverseInfo* trav_info) -{ - return trav_info->buffer_size / sizeof (FatDirEntry); -} - -/* returns 1 if there are no more directory entries in the directory being - * traversed, 0 otherwise. - */ -static int -is_last_buffer (FatTraverseInfo* trav_info) { - FatSpecific* fs_info = FAT_SPECIFIC (trav_info->fs); - - if (trav_info->is_legacy_root_dir) - return 1; - else - return fat_table_is_eof (fs_info->fat, trav_info->next_buffer); -} - -static int -write_root_dir (FatTraverseInfo* trav_info) -{ - FatSpecific* fs_info = FAT_SPECIFIC (trav_info->fs); - - if (!ped_geometry_write (trav_info->fs->geom, trav_info->dir_entries, - fs_info->root_dir_offset, - fs_info->root_dir_sector_count)) - return 0; - if (!ped_geometry_sync (trav_info->fs->geom)) - return 0; - trav_info->dirty = 0; - return 1; -} - -static int -write_dir_cluster (FatTraverseInfo* trav_info) -{ - if (!fat_write_sync_cluster (trav_info->fs, - (void*) trav_info->dir_entries, - trav_info->this_buffer)) - return 0; - trav_info->dirty = 0; - return 1; -} - -static int -write_dir_buffer (FatTraverseInfo* trav_info) -{ - if (trav_info->is_legacy_root_dir) - return write_root_dir (trav_info); - else - return write_dir_cluster (trav_info); -} - -static int -read_next_dir_buffer (FatTraverseInfo* trav_info) -{ - FatSpecific* fs_info = FAT_SPECIFIC (trav_info->fs); - - PED_ASSERT (!trav_info->is_legacy_root_dir, return 0); - - trav_info->this_buffer = trav_info->next_buffer; - - if (trav_info->this_buffer < 2 - || trav_info->this_buffer >= fs_info->cluster_count + 2) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - "Cluster %ld in directory %s is outside file system!", - (long) trav_info->this_buffer, - trav_info->dir_name); - return 0; - } - - trav_info->next_buffer - = fat_table_get (fs_info->fat, trav_info->this_buffer); - - return fat_read_cluster (trav_info->fs, (void *) trav_info->dir_entries, - trav_info->this_buffer); -} - -/* FIXME: put into fat_dir_entry_* operations */ -void -fat_traverse_mark_dirty (FatTraverseInfo* trav_info) -{ - trav_info->dirty = 1; -} - -FatTraverseInfo* -fat_traverse_begin (PedFileSystem* fs, FatCluster start_cluster, - char* dir_name) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatTraverseInfo* trav_info; - - trav_info = (FatTraverseInfo*) ped_malloc (sizeof (FatTraverseInfo)); - if (!trav_info) - goto error; - - trav_info->dir_name = strdup (dir_name); - if (!trav_info->dir_name) - goto error_free_trav_info; - - trav_info->fs = fs; - trav_info->is_legacy_root_dir - = (fs_info->fat_type == FAT_TYPE_FAT16) && (start_cluster == 0); - trav_info->dirty = 0; - trav_info->eof = 0; - trav_info->current_entry = -1; - - if (trav_info->is_legacy_root_dir) { - trav_info->buffer_size = 512 * fs_info->root_dir_sector_count; - } else { - trav_info->next_buffer = start_cluster; - trav_info->buffer_size = fs_info->cluster_size; - } - - trav_info->dir_entries - = (FatDirEntry*) ped_malloc (trav_info->buffer_size); - if (!trav_info->dir_entries) - goto error_free_dir_name; - - if (trav_info->is_legacy_root_dir) { - if (!ped_geometry_read (fs->geom, trav_info->dir_entries, - fs_info->root_dir_offset, - fs_info->root_dir_sector_count)) - goto error_free_dir_entries; - } else { - if (!read_next_dir_buffer (trav_info)) - goto error_free_dir_entries; - } - - return trav_info; - -error_free_dir_entries: - ped_free (trav_info->dir_entries); -error_free_dir_name: - ped_free (trav_info->dir_name); -error_free_trav_info: - ped_free (trav_info); -error: - return NULL; -} - -int -fat_traverse_complete (FatTraverseInfo* trav_info) -{ - if (trav_info->dirty) { - if (!write_dir_buffer (trav_info)) - return 0; - } - ped_free (trav_info->dir_entries); - ped_free (trav_info->dir_name); - ped_free (trav_info); - return 1; -} - -FatTraverseInfo* -fat_traverse_directory (FatTraverseInfo *trav_info, FatDirEntry* parent) -{ - strcpy (tmp_buffer, trav_info->dir_name); - fat_dir_entry_get_name (parent, - tmp_buffer + strlen (trav_info->dir_name)); - strcat (tmp_buffer, "\\"); - - return fat_traverse_begin (trav_info->fs, - fat_dir_entry_get_first_cluster (parent, trav_info->fs), - tmp_buffer); -} - -FatDirEntry* -fat_traverse_next_dir_entry (FatTraverseInfo *trav_info) -{ - if (trav_info->eof) - return NULL; - - trav_info->current_entry++; - if (trav_info->current_entry - >= fat_traverse_entries_per_buffer (trav_info)) { - if (trav_info->dirty) { - if (!write_dir_buffer (trav_info)) - return NULL; - } - - trav_info->current_entry = 0; - if (is_last_buffer (trav_info)) { - trav_info->eof = 1; - return NULL; - } - if (!read_next_dir_buffer (trav_info)) - return NULL; - } - return trav_info->dir_entries + trav_info->current_entry; -} - -FatCluster -fat_dir_entry_get_first_cluster (FatDirEntry* dir_entry, PedFileSystem *fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - switch (fs_info->fat_type) { - case FAT_TYPE_FAT12: - case FAT_TYPE_FAT16: - return PED_LE16_TO_CPU (dir_entry->first_cluster); - - case FAT_TYPE_FAT32: - return PED_LE16_TO_CPU (dir_entry->first_cluster_high) - * 65536L - + PED_LE16_TO_CPU (dir_entry->first_cluster); - } - - return 0; -} - -void -fat_dir_entry_set_first_cluster (FatDirEntry* dir_entry, PedFileSystem* fs, - FatCluster cluster) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - - switch (fs_info->fat_type) { - case FAT_TYPE_FAT12: - PED_ASSERT (0, (void) 0); - break; - - case FAT_TYPE_FAT16: - dir_entry->first_cluster = PED_CPU_TO_LE16 (cluster); - break; - - case FAT_TYPE_FAT32: - dir_entry->first_cluster - = PED_CPU_TO_LE16 (cluster & 0xffff); - dir_entry->first_cluster_high - = PED_CPU_TO_LE16 (cluster / 0x10000); - break; - } -} - -uint32_t -fat_dir_entry_get_length (FatDirEntry* dir_entry) -{ - return PED_LE32_TO_CPU (dir_entry->length); -} - -int -fat_dir_entry_is_null_term (const FatDirEntry* dir_entry) -{ - FatDirEntry null_entry; - - memset (&null_entry, 0, sizeof (null_entry)); - return memcmp (&null_entry, dir_entry, sizeof (null_entry)) == 0; -} - -int -fat_dir_entry_is_active (FatDirEntry* dir_entry) -{ - if ((unsigned char) dir_entry->name[0] == DELETED_FLAG) return 0; - if ((unsigned char) dir_entry->name[0] == 0) return 0; - if ((unsigned char) dir_entry->name[0] == 0xF6) return 0; - return 1; -} - -int -fat_dir_entry_is_file (FatDirEntry* dir_entry) { - if (dir_entry->attributes == VFAT_ATTR) return 0; - if (dir_entry->attributes & VOLUME_LABEL_ATTR) return 0; - if (!fat_dir_entry_is_active (dir_entry)) return 0; - if ((dir_entry->attributes & DIRECTORY_ATTR) == DIRECTORY_ATTR) return 0; - return 1; -} - -int -fat_dir_entry_is_system_file (FatDirEntry* dir_entry) -{ - if (!fat_dir_entry_is_file (dir_entry)) return 0; - return (dir_entry->attributes & SYSTEM_ATTR) - || (dir_entry->attributes & HIDDEN_ATTR); -} - -int -fat_dir_entry_is_directory (FatDirEntry* dir_entry) -{ - if (dir_entry->attributes == VFAT_ATTR) return 0; - if (dir_entry->attributes & VOLUME_LABEL_ATTR) return 0; - if (!fat_dir_entry_is_active (dir_entry)) return 0; - return (dir_entry->attributes & DIRECTORY_ATTR) == DIRECTORY_ATTR; -} - -int -fat_dir_entry_has_first_cluster (FatDirEntry* dir_entry, PedFileSystem* fs) -{ - FatSpecific* fs_info = FAT_SPECIFIC (fs); - FatCluster first_cluster; - - if (!fat_dir_entry_is_file (dir_entry) - && !fat_dir_entry_is_directory (dir_entry)) - return 0; - - first_cluster = fat_dir_entry_get_first_cluster (dir_entry, fs); - if (first_cluster == 0 - || fat_table_is_eof (fs_info->fat, first_cluster)) - return 0; - - return 1; -} - -/* - decrypts silly DOS names to FILENAME.EXT -*/ -void -fat_dir_entry_get_name (FatDirEntry*dir_entry, char *result) { - int i; - char *src; - - src = dir_entry->name; - - for (i=0; i<8; i++) { - if (src[i] == ' ' || src[i] == 0) break; - *result++ = src[i]; - } - - if (src[8] != ' ' && src[8] != 0) { - *result++ = '.'; - for (i=8; i<11; i++) { - if (src[i] == ' ' || src[i] == 0) break; - *result++ = src[i]; - } - } - - *result = 0; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/fat/traverse.h b/usr/src/lib/libparted/common/libparted/fs/fat/traverse.h deleted file mode 100644 index 21e4c27d6e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/fat/traverse.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - libparted - Copyright (C) 1998, 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef TRAVERSE_H_INCLUDED -#define TRAVERSE_H_INCLUDED - -#include "fatio.h" - -typedef struct _FatTraverseInfo FatTraverseInfo; - -struct _FatTraverseInfo { - PedFileSystem* fs; - char* dir_name; - - int is_legacy_root_dir; - int dirty; - int eof; - - FatDirEntry* dir_entries; - int current_entry; - FatCluster this_buffer, next_buffer; - int buffer_size; -}; - -extern int fat_traverse_entries_per_buffer (FatTraverseInfo* trav_info); - -/* starts traversal at an arbitary cluster. if start_cluster==0, then uses - root directory */ -extern FatTraverseInfo* fat_traverse_begin (PedFileSystem* fs, - FatCluster start_cluster, char* dir_name); - -extern int fat_traverse_complete (FatTraverseInfo* trav_info); - -extern FatTraverseInfo* fat_traverse_directory (FatTraverseInfo* trav_info, - FatDirEntry* parent); - -extern void fat_traverse_mark_dirty (FatTraverseInfo* trav_info); - -extern FatDirEntry* fat_traverse_next_dir_entry (FatTraverseInfo* trav_info); - -extern FatCluster fat_dir_entry_get_first_cluster (FatDirEntry* dir_entry, - PedFileSystem* fs); - -extern void fat_dir_entry_set_first_cluster (FatDirEntry* dir_entry, - PedFileSystem* fs, FatCluster cluster); - -extern uint32_t fat_dir_entry_get_length (FatDirEntry* dir_entry); - -extern int fat_dir_entry_is_null_term (const FatDirEntry* dir_entry); -extern int fat_dir_entry_is_file (FatDirEntry* dir_entry); -extern int fat_dir_entry_is_system_file (FatDirEntry* dir_entry); -extern int fat_dir_entry_is_directory (FatDirEntry* dir_entry); -extern void fat_dir_entry_get_name (FatDirEntry* dir_entry, char* result); -extern int fat_dir_entry_is_active (FatDirEntry* dir_entry); -extern int fat_dir_entry_has_first_cluster (FatDirEntry* dir_entry, - PedFileSystem* fs); - -#endif /* TRAVERSE_H_INCLUDED */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.c b/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.c deleted file mode 100644 index b3438bd56e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file.h" - -#include "advfs.h" - -/* - if a < b, 0 if a == b, + if a > b */ -/* Comparaison is done in the following order : */ -/* CNID, then fork type, then start block */ -/* Note that HFS implementation in linux has a bug */ -/* in this function */ -static int -hfs_extent_key_cmp(HfsPrivateGenericKey* a, HfsPrivateGenericKey* b) -{ - HfsExtentKey* key1 = (HfsExtentKey*) a; - HfsExtentKey* key2 = (HfsExtentKey*) b; - - /* do NOT use a substraction, because */ - /* 0xFFFFFFFF - 1 = 0xFFFFFFFE so this */ - /* would return -2, despite the fact */ - /* 0xFFFFFFFF > 1 !!! (this is the 2.4 bug) */ - if (key1->file_ID != key2->file_ID) - return PED_BE32_TO_CPU(key1->file_ID) < - PED_BE32_TO_CPU(key2->file_ID) ? - -1 : +1; - - if (key1->type != key2->type) - return (int)(key1->type - key2->type); - - if (key1->start == key2->start) - return 0; - /* the whole thing wont work with 16 bits ints */ - /* anyway */ - return (int)( PED_BE16_TO_CPU(key1->start) - - PED_BE16_TO_CPU(key2->start) ); -} - -/* do a B-Tree lookup */ -/* read the first record immediatly inferior or egal to the given key */ -/* return 0 on error */ -/* record_out _must_ be large enough to receive record_size bytes */ -/* WARNING : the compare function called only handle Extents BTree */ -/* so modify this function if you want to do lookup in */ -/* other BTrees has well */ -int -hfs_btree_search (HfsPrivateFile* b_tree_file, HfsPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsPrivateGenericKey* record_key = NULL; - unsigned int node_number, record_number; - int i; - - /* Read the header node */ - if (!hfs_file_read_sector(b_tree_file, node, 0)) - return 0; - header = ((HfsHeaderRecord*) (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT-2)))))); - - /* Get the node number of the root */ - node_number = PED_BE32_TO_CPU(header->root_node); - if (!node_number) - return 0; - - /* Read the root node */ - if (!hfs_file_read_sector(b_tree_file, node, node_number)) - return 0; - - /* Follow the white rabbit */ - while (1) { - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = record_number; i; i--) { - record_key = (HfsPrivateGenericKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - /* check for obvious error in FS */ - if (((uint8_t*)record_key - node < HFS_FIRST_REC) - || ((uint8_t*)record_key - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - if (hfs_extent_key_cmp(record_key, key) <= 0) - break; - } - if (!i) return 0; - if (desc->type == HFS_IDX_NODE) { - unsigned int skip; - - skip = (1 + record_key->key_length + 1) & ~1; - node_number = PED_BE32_TO_CPU (*((uint32_t *) - (((uint8_t *) record_key) + skip))); - if (!hfs_file_read_sector(b_tree_file, node, - node_number)) - return 0; - } else - break; - } - - /* copy the result if needed */ - if (record_size) - memcpy (record_out, record_key, record_size); - - /* send record reference if needed */ - if (record_ref) { - record_ref->node_size = 1; /* in sectors */ - record_ref->node_number = node_number; - record_ref->record_pos = (uint8_t*)record_key - node; - record_ref->record_number = i; - } - - /* success */ - return 1; -} - -/* free the bad blocks linked list */ -void -hfs_free_bad_blocks_list(HfsPrivateLinkExtent* first) -{ - HfsPrivateLinkExtent* next; - - while (first) { - next = first->next; - ped_free (first); - first = next; - } -} - -/* This function reads bad blocks extents in the extents file - and store it in f.s. specific data of fs */ -int -hfs_read_bad_blocks (const PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - return 1; - - { - uint8_t record[sizeof (HfsExtentKey) - + sizeof (HfsExtDataRec)]; - HfsExtentKey search; - HfsExtentKey* ret_key = (HfsExtentKey*) record; - HfsExtDescriptor* ret_cache = (HfsExtDescriptor*) - (record + sizeof (HfsExtentKey)); - unsigned int block, last_start, first_pass = 1; - - search.key_length = sizeof (HfsExtentKey) - 1; - search.type = HFS_DATA_FORK; - search.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - - last_start = -1; block = 0; - while (1) { - int i; - - search.start = PED_CPU_TO_BE16 (block); - if (!hfs_btree_search (priv_data->extent_file, - (HfsPrivateGenericKey*) &search, - record, sizeof (record), NULL) - || ret_key->file_ID != search.file_ID - || ret_key->type != search.type) { - if (first_pass) - break; - else - goto errbb; - } - if (PED_BE16_TO_CPU (ret_key->start) == last_start) - break; - - last_start = PED_BE16_TO_CPU (ret_key->start); - for (i = 0; i < HFS_EXT_NB; i++) { - if (ret_cache[i].block_count) { - HfsPrivateLinkExtent* new_xt = - (HfsPrivateLinkExtent*) ped_malloc ( - sizeof (HfsPrivateLinkExtent)); - if (!new_xt) - goto errbb; - new_xt->next = priv_data->bad_blocks_xtent_list; - memcpy(&(new_xt->extent), ret_cache+i, - sizeof (HfsExtDescriptor)); - priv_data->bad_blocks_xtent_list = new_xt; - priv_data->bad_blocks_xtent_nb++; - block += PED_BE16_TO_CPU ( - ret_cache[i].block_count); - } - } - first_pass = 0; - } - - priv_data->bad_blocks_loaded = 1; - return 1;} - -errbb: hfs_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - priv_data->bad_blocks_xtent_list=NULL; - priv_data->bad_blocks_xtent_nb=0; - return 0; -} - -/* This function check if fblock is a bad block */ -int -hfs_is_bad_block (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsPrivateLinkExtent* walk; - - for (walk = priv_data->bad_blocks_xtent_list; walk; walk = walk->next) { - /* Won't compile without the strange cast ! gcc bug ? */ - /* or maybe C subtilties... */ - if ((fblock >= PED_BE16_TO_CPU (walk->extent.start_block)) && - (fblock < (unsigned int) (PED_BE16_TO_CPU ( - walk->extent.start_block) - + PED_BE16_TO_CPU ( - walk->extent.block_count)))) - return 1; - } - - return 0; -} - -/* This function returns the first sector of the last free block of an - HFS volume we can get after a hfs_pack_free_space_from_block call */ -/* On error this function returns 0 */ -PedSector -hfs_get_empty_end (const PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - HfsPrivateLinkExtent* link; - unsigned int block, last_bad, end_free_blocks; - - /* find the next block to the last bad block of the volume */ - if (!hfs_read_bad_blocks (fs)) - return 0; - - last_bad = 0; - for (link = priv_data->bad_blocks_xtent_list; link; link = link->next) { - if ((unsigned int) PED_BE16_TO_CPU (link->extent.start_block) - + PED_BE16_TO_CPU (link->extent.block_count) > last_bad) - last_bad = PED_BE16_TO_CPU (link->extent.start_block) - + PED_BE16_TO_CPU (link->extent.block_count); - } - - /* Count the free blocks from last_bad to the end of the volume */ - end_free_blocks = 0; - for (block = last_bad; - block < PED_BE16_TO_CPU (mdb->total_blocks); - block++) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - end_free_blocks++; - } - - /* Calculate the block that will by the first free at the - end of the volume */ - block = PED_BE16_TO_CPU (mdb->total_blocks) - end_free_blocks; - - return (PedSector) PED_BE16_TO_CPU (mdb->start_block) - + (PedSector) block * (PED_BE32_TO_CPU (mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT); -} - -/* return the block which should be used to pack data to have at - least free fblock blocks at the end of the volume */ -unsigned int -hfs_find_start_pack (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int block; - - for (block = PED_BE16_TO_CPU (priv_data->mdb->total_blocks) - 1; - block && fblock; - block--) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - fblock--; - } - - while (block && !TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block--; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block++; - - return block; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.h b/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.h deleted file mode 100644 index 18a2661e35..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _ADVFS_H -#define _ADVFS_H - -#include -#include -#include - -#include "hfs.h" - -int -hfs_btree_search (HfsPrivateFile* b_tree_file, HfsPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref); - -void -hfs_free_bad_blocks_list(HfsPrivateLinkExtent* first); - -int -hfs_read_bad_blocks (const PedFileSystem *fs); - -int -hfs_is_bad_block (const PedFileSystem *fs, unsigned int fblock); - -PedSector -hfs_get_empty_end (const PedFileSystem *fs); - -unsigned int -hfs_find_start_pack (const PedFileSystem *fs, unsigned int fblock); - -#endif /* _ADVFS_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.c b/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.c deleted file mode 100644 index b810c8b089..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.c +++ /dev/null @@ -1,383 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs.h" -#include "file_plus.h" - -#include "advfs_plus.h" - -/* - if a < b, 0 if a == b, + if a > b */ -/* Comparaison is done in the following order : */ -/* CNID, then fork type, then start block */ -static int -hfsplus_extent_key_cmp(HfsPPrivateGenericKey* a, HfsPPrivateGenericKey* b) -{ - HfsPExtentKey* key1 = (HfsPExtentKey*) a; - HfsPExtentKey* key2 = (HfsPExtentKey*) b; - - if (key1->file_ID != key2->file_ID) - return PED_BE32_TO_CPU(key1->file_ID) < - PED_BE32_TO_CPU(key2->file_ID) ? - -1 : +1; - - if (key1->type != key2->type) - return (int)(key1->type - key2->type); - - if (key1->start == key2->start) - return 0; - return PED_BE32_TO_CPU(key1->start) < - PED_BE32_TO_CPU(key2->start) ? - -1 : +1; -} - -/* do a B-Tree lookup */ -/* read the first record immediatly inferior or egal to the given key */ -/* return 0 on error */ -/* record_out _must_ be large enough to receive the whole record (key + data) */ -/* WARNING : the search function called only handle Extents BTree */ -/* so modify this function if you want to do lookup in */ -/* other BTrees has well */ -int -hfsplus_btree_search (HfsPPrivateFile* b_tree_file, HfsPPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref) -{ - uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; - uint8_t* node; - HfsPHeaderRecord* header; - HfsPNodeDescriptor* desc = (HfsPNodeDescriptor*) node_1; - HfsPPrivateGenericKey* record_key = NULL; - unsigned int node_number, record_number, size, bsize; - int i; - - /* Read the header node */ - if (!hfsplus_file_read_sector(b_tree_file, node_1, 0)) - return 0; - header = (HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC); - - /* Get the node number of the root */ - node_number = PED_BE32_TO_CPU (header->root_node); - if (!node_number) - return 0; - - /* Get the size of a node in sectors and allocate buffer */ - size = (bsize = PED_BE16_TO_CPU (header->node_size)) / PED_SECTOR_SIZE_DEFAULT; - node = (uint8_t*) ped_malloc (bsize); - if (!node) - return 0; - desc = (HfsPNodeDescriptor*) node; - - /* Read the root node */ - if (!hfsplus_file_read (b_tree_file, node, - (PedSector) node_number * size, size)) - return 0; - - /* Follow the white rabbit */ - while (1) { - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = record_number; i; i--) { - record_key = (HfsPPrivateGenericKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(bsize - 2*i))))); - /* check for obvious error in FS */ - if (((uint8_t*)record_key - node < HFS_FIRST_REC) - || ((uint8_t*)record_key - node - >= (signed)bsize - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - ped_free (node); - return 0; - } - if (hfsplus_extent_key_cmp(record_key, key) <= 0) - break; - } - if (!i) { ped_free (node); return 0; } - if (desc->type == HFS_IDX_NODE) { - unsigned int skip; - - skip = ( 2 + PED_BE16_TO_CPU (record_key->key_length) - + 1 ) & ~1; - node_number = PED_BE32_TO_CPU (*((uint32_t *) - (((uint8_t *) record_key) + skip))); - if (!hfsplus_file_read(b_tree_file, node, - (PedSector) node_number * size, - size)) { - ped_free (node); - return 0; - } - } else - break; - } - - /* copy the result if needed */ - if (record_size) - memcpy (record_out, record_key, record_size); - - /* send record reference if needed */ - if (record_ref) { - record_ref->node_size = size; /* in sectors */ - record_ref->node_number = node_number; - record_ref->record_pos = (uint8_t*)record_key - node; - record_ref->record_number = i; - } - - /* success */ - ped_free (node); - return 1; -} - -/* free the bad blocks linked list */ -void -hfsplus_free_bad_blocks_list(HfsPPrivateLinkExtent* first) -{ - HfsPPrivateLinkExtent* next; - - while (first) { - next = first->next; - ped_free (first); - first = next; - } -} - -/* This function reads bad blocks extents in the extents file - and store it in f.s. specific data of fs */ -int -hfsplus_read_bad_blocks (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - return 1; - - { - uint8_t record[sizeof (HfsPExtentKey) - + sizeof (HfsPExtDataRec)]; - HfsPExtentKey search; - HfsPExtentKey* ret_key = (HfsPExtentKey*) record; - HfsPExtDescriptor* ret_cache = (HfsPExtDescriptor*) - (record + sizeof (HfsPExtentKey)); - int block, first_pass = 1; - unsigned int last_start; - - search.key_length = sizeof (HfsExtentKey) - 2; - search.type = HFS_DATA_FORK; - search.pad = 0; - search.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - - last_start = -1; block = 0; - while (1) { - int i; - - search.start = PED_CPU_TO_BE32 (block); - if (!hfsplus_btree_search (priv_data->extents_file, - (HfsPPrivateGenericKey*) &search, - record, sizeof (record), NULL) - || ret_key->file_ID != search.file_ID - || ret_key->type != search.type) { - if (first_pass) - break; - else - goto errbbp; - } - if (PED_BE32_TO_CPU (ret_key->start) == last_start) - break; - - last_start = PED_BE32_TO_CPU (ret_key->start); - for (i = 0; i < HFSP_EXT_NB; i++) { - if (ret_cache[i].block_count) { - HfsPPrivateLinkExtent* new_xt = - (HfsPPrivateLinkExtent*) ped_malloc ( - sizeof (HfsPPrivateLinkExtent)); - if (!new_xt) - goto errbbp; - new_xt->next = priv_data->bad_blocks_xtent_list; - memcpy (&(new_xt->extent), ret_cache+i, - sizeof (HfsPExtDescriptor)); - priv_data->bad_blocks_xtent_list = new_xt; - priv_data->bad_blocks_xtent_nb++; - block += PED_BE32_TO_CPU ( - ret_cache[i].block_count); - } - } - first_pass = 0; - } - - priv_data->bad_blocks_loaded = 1; - return 1;} - -errbbp: hfsplus_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - priv_data->bad_blocks_xtent_list=NULL; - priv_data->bad_blocks_xtent_nb=0; - return 0; -} - -/* This function check if fblock is a bad block */ -int -hfsplus_is_bad_block (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPPrivateLinkExtent* walk; - - for (walk = priv_data->bad_blocks_xtent_list; walk; walk = walk->next) { - /* Won't compile without the strange cast ! gcc bug ? */ - /* or maybe C subtilties... */ - if ((fblock >= PED_BE32_TO_CPU (walk->extent.start_block)) && - (fblock < (unsigned int)(PED_BE32_TO_CPU ( - walk->extent.start_block) - + PED_BE32_TO_CPU (walk->extent.block_count)))) - return 1; - } - - return 0; -} - -/* This function returns the first sector of the last free block of - an HFS+ volume we can get after a hfsplus_pack_free_space_from_block call */ -PedSector -hfsplus_get_empty_end (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - HfsPPrivateLinkExtent* link; - unsigned int block, last_bad, end_free_blocks; - - /* find the next block to the last bad block of the volume */ - if (!hfsplus_read_bad_blocks (fs)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad blocks could not be read.")); - return 0; - } - - last_bad = 0; - for (link = priv_data->bad_blocks_xtent_list; link; link = link->next) { - if ((unsigned int) PED_BE32_TO_CPU (link->extent.start_block) - + PED_BE32_TO_CPU (link->extent.block_count) > last_bad) - last_bad = PED_BE32_TO_CPU (link->extent.start_block) - + PED_BE32_TO_CPU (link->extent.block_count); - } - - /* Count the free blocks from last_bad to the end of the volume */ - end_free_blocks = 0; - for (block = last_bad; - block < PED_BE32_TO_CPU (vh->total_blocks); - block++) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - end_free_blocks++; - } - - /* Calculate the block that will by the first free at - the end of the volume */ - block = PED_BE32_TO_CPU (vh->total_blocks) - end_free_blocks; - - return (PedSector) block * ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); -} - -/* On error, returns 0 */ -PedSector -hfsplus_get_min_size (const PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - PedSector min_size; - - /* don't need to add anything because every sector - can be part of allocation blocks in HFS+, and - the last block _must_ be reserved */ - min_size = hfsplus_get_empty_end(fs); - if (!min_size) return 0; - - if (priv_data->wrapper) { - HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - unsigned int hfs_sect_block; - PedSector hgee; - hfs_sect_block = - PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - /* - * if hfs+ is embedded in an hfs wrapper then the new size is : - * the new size of the hfs+ volume rounded up to the size - * of hfs blocks - * + the minimum size of the hfs wrapper without any hfs+ - * modification - * - the current size of the hfs+ volume in the hfs wrapper - */ - hgee = hfs_get_empty_end(priv_data->wrapper); - if (!hgee) return 0; - min_size = ((min_size + hfs_sect_block - 1) / hfs_sect_block) - * hfs_sect_block - + hgee + 2 - - (PedSector) PED_BE16_TO_CPU ( hfs_priv_data->mdb - ->old_new.embedded - .location.block_count ) - * hfs_sect_block; - } - - return min_size; -} - -/* return the block which should be used to pack data to have - at least free fblock blocks at the end of the volume */ -unsigned int -hfsplus_find_start_pack (const PedFileSystem *fs, unsigned int fblock) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - unsigned int block; - - for (block = PED_BE32_TO_CPU (priv_data->vh->total_blocks) - 1; - block && fblock; - block--) { - if (!TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - fblock--; - } - - while (block && !TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block--; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) - block++; - - return block; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.h b/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.h deleted file mode 100644 index 75bd3b7bcb..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _ADVFS_PLUS_H -#define _ADVFS_PLUS_H - -#include -#include -#include - -#include "hfs.h" - -int -hfsplus_btree_search (HfsPPrivateFile* b_tree_file, HfsPPrivateGenericKey* key, - void *record_out, unsigned int record_size, - HfsCPrivateLeafRec* record_ref); - -void -hfsplus_free_bad_blocks_list(HfsPPrivateLinkExtent* first); - -int -hfsplus_read_bad_blocks (const PedFileSystem *fs); - -int -hfsplus_is_bad_block (const PedFileSystem *fs, unsigned int fblock); - -PedSector -hfsplus_get_empty_end (const PedFileSystem *fs); - -PedSector -hfsplus_get_min_size (const PedFileSystem *fs); - -unsigned int -hfsplus_find_start_pack (const PedFileSystem *fs, unsigned int fblock); - -#endif /* _ADVFS_PLUS_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/cache.c b/usr/src/lib/libparted/common/libparted/fs/hfs/cache.c deleted file mode 100644 index de34e72a45..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/cache.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" - -#include "cache.h" - -static HfsCPrivateCacheTable* -hfsc_new_cachetable(unsigned int size) -{ - HfsCPrivateCacheTable* ret; - - ret = (HfsCPrivateCacheTable*) ped_malloc(sizeof(*ret)); - if (!ret) return NULL; - - ret->next_cache = NULL; - ret->table_size = size; - ret->table_first_free = 0; - - ret->table = ped_malloc(sizeof(*ret->table)*size); - if (!ret->table) { ped_free(ret); return NULL; } - memset(ret->table, 0, sizeof(*ret->table)*size); - - return ret; -} - -HfsCPrivateCache* -hfsc_new_cache(unsigned int block_number, unsigned int file_number) -{ - unsigned int cachetable_size, i; - HfsCPrivateCache* ret; - - ret = (HfsCPrivateCache*) ped_malloc(sizeof(*ret)); - if (!ret) return NULL; - ret->block_number = block_number; - /* following code avoid integer overflow */ - ret->linked_ref_size = block_number > block_number + ((1<> CR_SHIFT ) + 1 : - ( block_number + ((1<> CR_SHIFT - ; - - ret->linked_ref = (HfsCPrivateExtent**) - ped_malloc( sizeof(*ret->linked_ref) - * ret->linked_ref_size ); - if (!ret->linked_ref) { ped_free(ret); return NULL; } - - cachetable_size = file_number + file_number / CR_OVER_DIV + CR_ADD_CST; - if (cachetable_size < file_number) cachetable_size = (unsigned) -1; - ret->first_cachetable_size = cachetable_size; - ret->table_list = hfsc_new_cachetable(cachetable_size); - if (!ret->table_list) { - ped_free(ret->linked_ref); - ped_free(ret); - return NULL; - } - ret->last_table = ret->table_list; - - for (i = 0; i < ret->linked_ref_size; ++i) - ret->linked_ref[i] = NULL; - - ret->needed_alloc_size = 0; - - return ret; -} - -static void -hfsc_delete_cachetable(HfsCPrivateCacheTable* list) -{ - HfsCPrivateCacheTable* next; - - while (list) { - ped_free (list->table); - next = list->next_cache; - ped_free (list); - list = next; - } -} - -void -hfsc_delete_cache(HfsCPrivateCache* cache) -{ - hfsc_delete_cachetable(cache->table_list); - ped_free(cache->linked_ref); - ped_free(cache); -} - -HfsCPrivateExtent* -hfsc_cache_add_extent(HfsCPrivateCache* cache, uint32_t start, uint32_t length, - uint32_t block, uint16_t offset, uint8_t sbb, - uint8_t where, uint8_t ref_index) -{ - HfsCPrivateExtent* ext; - unsigned int idx = start >> CR_SHIFT; - - PED_ASSERT(idx < cache->linked_ref_size, return NULL); - - for (ext = cache->linked_ref[idx]; - ext && start != ext->ext_start; - ext = ext->next); - - if (ext) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to register an extent starting at block " - "0x%X, but another one already exists at this " - "position. You should check the file system!"), - start); - return NULL; - } - - if ( cache->last_table->table_first_free - == cache->last_table->table_size ) { - cache->last_table->next_cache = - hfsc_new_cachetable( ( cache->first_cachetable_size - / CR_NEW_ALLOC_DIV ) - + CR_ADD_CST ); - if (!cache->last_table->next_cache) - return NULL; - cache->last_table = cache->last_table->next_cache; - } - - ext = cache->last_table->table+(cache->last_table->table_first_free++); - - ext->ext_start = start; - ext->ext_length = length; - ext->ref_block = block; - ext->ref_offset = offset; - ext->sect_by_block = sbb; - ext->where = where; - ext->ref_index = ref_index; - - ext->next = cache->linked_ref[idx]; - cache->linked_ref[idx] = ext; - - cache->needed_alloc_size = cache->needed_alloc_size > - (unsigned) PED_SECTOR_SIZE_DEFAULT * sbb ? - cache->needed_alloc_size : - (unsigned) PED_SECTOR_SIZE_DEFAULT * sbb; - - return ext; -} - -HfsCPrivateExtent* -hfsc_cache_search_extent(HfsCPrivateCache* cache, uint32_t start) -{ - HfsCPrivateExtent* ret; - unsigned int idx = start >> CR_SHIFT; - - PED_ASSERT(idx < cache->linked_ref_size, return NULL); - - for (ret = cache->linked_ref[idx]; - ret && start != ret->ext_start; - ret = ret->next); - - return ret; -} - -/* Can't fail if extent begining at old_start exists */ -/* Returns 0 if no such extent, or on error */ -HfsCPrivateExtent* -hfsc_cache_move_extent(HfsCPrivateCache* cache, uint32_t old_start, - uint32_t new_start) -{ - HfsCPrivateExtent** ppext; - HfsCPrivateExtent* pext; - - unsigned int idx1 = old_start >> CR_SHIFT; - unsigned int idx2 = new_start >> CR_SHIFT; - - PED_ASSERT(idx1 < cache->linked_ref_size, return NULL); - PED_ASSERT(idx2 < cache->linked_ref_size, return NULL); - - for (pext = cache->linked_ref[idx2]; - pext && new_start != pext->ext_start; - pext = pext->next); - - if (pext) { - ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("Trying to move an extent from block Ox%X to block " - "Ox%X, but another one already exists at this " - "position. This should not happen!"), - old_start, new_start); - return NULL; - } - - for (ppext = &(cache->linked_ref[idx1]); - (*ppext) && old_start != (*ppext)->ext_start; - ppext = &((*ppext)->next)); - - if (!(*ppext)) return NULL; - - /* removing the extent from the cache */ - pext = *ppext; - (*ppext) = pext->next; - - /* change ext_start and insert the extent again */ - pext->ext_start = new_start; - pext->next = cache->linked_ref[idx2]; - cache->linked_ref[idx2] = pext; - - return pext; -} - -#endif /* DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/cache.h b/usr/src/lib/libparted/common/libparted/fs/hfs/cache.h deleted file mode 100644 index 8e1b921e0e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/cache.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _CACHE_H -#define _CACHE_H - -#include -#include -#include - -#include "hfs.h" - -/* CR => CACHE REF */ -#define CR_NULL 0 /* reserved */ -#define CR_PRIM_CAT 1 -#define CR_PRIM_EXT 2 -#define CR_PRIM_ATTR 3 -#define CR_PRIM_ALLOC 4 -#define CR_PRIM_START 5 -#define CR_BTREE_CAT 6 -#define CR_BTREE_ATTR 7 -#define CR_BTREE_EXT_0 8 -#define CR_BTREE_EXT_CAT 9 -#define CR_BTREE_EXT_EXT 10 /* should not happen ! */ -#define CR_BTREE_EXT_ATTR 11 -#define CR_BTREE_EXT_ALLOC 12 -#define CR_BTREE_EXT_START 13 /* unneeded in current code */ -#define CR_BTREE_CAT_JIB 14 /* journal info block */ -#define CR_BTREE_CAT_JL 15 /* journal */ -/* 16 -> 31 || high order bit */ /* reserved */ - -/* tuning */ -#define CR_SHIFT 8 /* number of bits to shift start_block by */ - /* to get the index of the linked list */ -#define CR_OVER_DIV 16 /* alloc a table for (1+1/CR_OVER_DIV) * - file_number + CR_ADD_CST */ -#define CR_ADD_CST 16 -#define CR_NEW_ALLOC_DIV 4 /* divide the size of the first alloc table - by this value to allocate next tables */ - -/* See DOC for an explaination of this structure */ -/* Access read only from outside cache.c */ -struct _HfsCPrivateExtent { - struct _HfsCPrivateExtent* next; - uint32_t ext_start; - uint32_t ext_length; - uint32_t ref_block; - uint16_t ref_offset; - uint8_t sect_by_block; - unsigned where : 5; - unsigned ref_index : 3; /* 0 -> 7 */ -}; -typedef struct _HfsCPrivateExtent HfsCPrivateExtent; - -/* Internaly used by cache.c for custom memory managment only */ -struct _HfsCPrivateCacheTable { - struct _HfsCPrivateCacheTable* next_cache; - HfsCPrivateExtent* table; - unsigned int table_size; - unsigned int table_first_free; - /* first_elemt ? */ -}; -typedef struct _HfsCPrivateCacheTable HfsCPrivateCacheTable; - -/* Internaly used by cache.c for custom memory managment - and cache handling only */ -struct _HfsCPrivateCache { - HfsCPrivateCacheTable* table_list; - HfsCPrivateCacheTable* last_table; - HfsCPrivateExtent** linked_ref; - unsigned int linked_ref_size; - unsigned int block_number; - unsigned int first_cachetable_size; - unsigned int needed_alloc_size; -}; -typedef struct _HfsCPrivateCache HfsCPrivateCache; - -HfsCPrivateCache* -hfsc_new_cache(unsigned int block_number, unsigned int file_number); - -void -hfsc_delete_cache(HfsCPrivateCache* cache); - -HfsCPrivateExtent* -hfsc_cache_add_extent(HfsCPrivateCache* cache, uint32_t start, uint32_t length, - uint32_t block, uint16_t offset, uint8_t sbb, - uint8_t where, uint8_t index); - -HfsCPrivateExtent* -hfsc_cache_search_extent(HfsCPrivateCache* cache, uint32_t start); - -HfsCPrivateExtent* -hfsc_cache_move_extent(HfsCPrivateCache* cache, uint32_t old_start, - uint32_t new_start); - -static __inline__ unsigned int -hfsc_cache_needed_buffer(HfsCPrivateCache* cache) -{ - return cache->needed_alloc_size; -} - -#endif /* _CACHE_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/file.c b/usr/src/lib/libparted/common/libparted/fs/hfs/file.c deleted file mode 100644 index f440749359..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/file.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs.h" - -#include "file.h" - -/* Open the data fork of a file with its first three extents and its CNID */ -HfsPrivateFile* -hfs_file_open (PedFileSystem *fs, uint32_t CNID, - HfsExtDataRec ext_desc, PedSector sect_nb) -{ - HfsPrivateFile* file; - - file = (HfsPrivateFile*) ped_malloc (sizeof (HfsPrivateFile)); - if (!file) return NULL; - - file->fs = fs; - file->sect_nb = sect_nb; - file->CNID = CNID; - memcpy(file->first, ext_desc, sizeof (HfsExtDataRec)); - file->start_cache = 0; - - return file; -} - -/* Close an HFS file */ -void -hfs_file_close (HfsPrivateFile* file) -{ - ped_free (file); -} - -/* warning : only works on data forks */ -static int -hfs_get_extent_containing (HfsPrivateFile* file, unsigned int block, - HfsExtDataRec cache, uint16_t* ptr_start_cache) -{ - uint8_t record[sizeof (HfsExtentKey) - + sizeof (HfsExtDataRec)]; - HfsExtentKey search; - HfsExtentKey* ret_key = (HfsExtentKey*) record; - HfsExtDescriptor* ret_cache = (HfsExtDescriptor*) - (record + sizeof (HfsExtentKey)); - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - file->fs->type_specific; - - search.key_length = sizeof (HfsExtentKey) - 1; - search.type = HFS_DATA_FORK; - search.file_ID = file->CNID; - search.start = PED_CPU_TO_BE16 (block); - - if (!hfs_btree_search (priv_data->extent_file, - (HfsPrivateGenericKey*) &search, - record, sizeof (record), NULL)) - return 0; - - if (ret_key->file_ID != search.file_ID || ret_key->type != search.type) - return 0; - - memcpy (cache, ret_cache, sizeof(HfsExtDataRec)); - *ptr_start_cache = PED_BE16_TO_CPU (ret_key->start); - - return 1; -} - -/* find and return the nth sector of a file */ -/* return 0 on error */ -static PedSector -hfs_file_find_sector (HfsPrivateFile* file, PedSector sector) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - file->fs->type_specific; - unsigned int sect_by_block = PED_BE32_TO_CPU ( - priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - unsigned int i, s, vol_block; - unsigned int block = sector / sect_by_block; - unsigned int offset = sector % sect_by_block; - - /* in the three first extent */ - for (s = 0, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && ( block < s + PED_BE16_TO_CPU ( - file->first[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->first[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->first[i].block_count); - } - - /* in the three cached extent */ - if (file->start_cache && block >= file->start_cache) - for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE16_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->cache[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->cache[i].block_count); - } - - /* update cache */ - if (!hfs_get_extent_containing (file, block, file->cache, - &(file->start_cache))) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_CANCEL, - _("Could not update the extent cache for HFS file with " - "CNID %X."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - /* in the three cached extent */ - PED_ASSERT(file->start_cache && block >= file->start_cache, return 0); - for (s = file->start_cache, i = 0; i < HFS_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE16_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) + PED_BE16_TO_CPU ( - file->cache[i].start_block); - goto sector_found; - } - s += PED_BE16_TO_CPU (file->cache[i].block_count); - } - - return 0; - - sector_found: - return (PedSector) PED_BE16_TO_CPU (priv_data->mdb->start_block) - + (PedSector) vol_block * sect_by_block - + offset; -} - -/* Read the nth sector of a file */ -/* return 0 on error */ -int -hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector) -{ - PedSector abs_sector; - - if (sector >= file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to read HFS file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - abs_sector = hfs_file_find_sector (file, sector); - if (!abs_sector) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS file with " - "CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - return ped_geometry_read (file->fs->geom, buf, abs_sector, 1); -} - -/* Write the nth sector of a file */ -/* return 0 on error */ -int -hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector) -{ - PedSector abs_sector; - - if (sector >= file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to write HFS file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - abs_sector = hfs_file_find_sector (file, sector); - if (!abs_sector) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS file with " - "CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - return ped_geometry_write (file->fs->geom, buf, abs_sector, 1); -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/file.h b/usr/src/lib/libparted/common/libparted/fs/hfs/file.h deleted file mode 100644 index de21c1f698..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/file.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _FILE_H -#define _FILE_H - -#include -#include -#include - -#include "hfs.h" - -HfsPrivateFile* -hfs_file_open (PedFileSystem *fs, uint32_t CNID, - HfsExtDataRec ext_desc, PedSector sect_nb); - -void -hfs_file_close (HfsPrivateFile* file); - -int -hfs_file_read_sector (HfsPrivateFile* file, void *buf, PedSector sector); - -int -hfs_file_write_sector (HfsPrivateFile* file, void *buf, PedSector sector); - -#endif /* _FILE_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.c b/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.c deleted file mode 100644 index 753997f203..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "advfs_plus.h" - -#include "file_plus.h" - -/* Open the data fork of a file with its first eight extents and its CNID */ -/* CNID and ext_desc must be in disc order, sect_nb in CPU order */ -/* return null on failure */ -HfsPPrivateFile* -hfsplus_file_open (PedFileSystem *fs, HfsPNodeID CNID, - HfsPExtDataRec ext_desc, PedSector sect_nb) -{ - HfsPPrivateFile* file; - - file = (HfsPPrivateFile*) ped_malloc (sizeof (HfsPPrivateFile)); - if (!file) return NULL; - - file->fs = fs; - file->sect_nb = sect_nb; - file->CNID = CNID; - memcpy(file->first, ext_desc, sizeof (HfsPExtDataRec)); - file->start_cache = 0; - - return file; -} - -/* Close an HFS+ file */ -void -hfsplus_file_close (HfsPPrivateFile* file) -{ - ped_free (file); -} - -/* warning : only works on data forks */ -static int -hfsplus_get_extent_containing (HfsPPrivateFile* file, unsigned int block, - HfsPExtDataRec cache, uint32_t* ptr_start_cache) -{ - uint8_t record[sizeof (HfsPExtentKey) - + sizeof (HfsPExtDataRec)]; - HfsPExtentKey search; - HfsPExtentKey* ret_key = (HfsPExtentKey*) record; - HfsPExtDescriptor* ret_cache = (HfsPExtDescriptor*) - (record + sizeof (HfsPExtentKey)); - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - - search.key_length = PED_CPU_TO_BE16 (sizeof (HfsPExtentKey) - 2); - search.type = HFS_DATA_FORK; - search.pad = 0; - search.file_ID = file->CNID; - search.start = PED_CPU_TO_BE32 (block); - - if (!hfsplus_btree_search (priv_data->extents_file, - (HfsPPrivateGenericKey*) &search, - record, sizeof (record), NULL)) - return 0; - - if (ret_key->file_ID != search.file_ID || ret_key->type != search.type) - return 0; - - memcpy (cache, ret_cache, sizeof(HfsPExtDataRec)); - *ptr_start_cache = PED_BE32_TO_CPU (ret_key->start); - - return 1; -} - -/* find a sub extent contained in the desired area */ -/* and with the same starting point */ -/* return 0 in sector_count on error, or the physical area */ -/* on the volume corresponding to the logical area in the file */ -static HfsPPrivateExtent -hfsplus_file_find_extent (HfsPPrivateFile* file, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent ret = {0,0}; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - unsigned int sect_by_block = PED_BE32_TO_CPU ( - priv_data->vh->block_size) - / PED_SECTOR_SIZE_DEFAULT; - unsigned int i, s, vol_block, size; - PedSector sect_size; - unsigned int block = sector / sect_by_block; - unsigned int offset = sector % sect_by_block; - - /* in the 8 first extent */ - for (s = 0, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->first[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->first[i] - .start_block); - size = PED_BE32_TO_CPU (file->first[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->first[i].block_count); - } - - /* in the 8 cached extent */ - if (file->start_cache && block >= file->start_cache) - for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->cache[i] - .start_block); - size = PED_BE32_TO_CPU (file->cache[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->cache[i].block_count); - } - - /* update cache */ - if (!hfsplus_get_extent_containing (file, block, file->cache, - &(file->start_cache))) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_CANCEL, - _("Could not update the extent cache for HFS+ file " - "with CNID %X."), - PED_BE32_TO_CPU(file->CNID)); - return ret; /* ret == {0,0} */ - } - - /* ret == {0,0} */ - PED_ASSERT(file->start_cache && block >= file->start_cache, return ret); - - for (s = file->start_cache, i = 0; i < HFSP_EXT_NB; i++) { - if ((block >= s) && (block < s + PED_BE32_TO_CPU ( - file->cache[i].block_count))) { - vol_block = (block - s) - + PED_BE32_TO_CPU (file->cache[i] - .start_block); - size = PED_BE32_TO_CPU (file->cache[i].block_count) - + s - block; - goto plus_sector_found; - } - s += PED_BE32_TO_CPU (file->cache[i].block_count); - } - - return ret; - -plus_sector_found: - sect_size = (PedSector) size * sect_by_block - offset; - ret.start_sector = vol_block * sect_by_block + offset; - ret.sector_count = (sect_size < nb) ? sect_size : nb; - return ret; -} - -int -hfsplus_file_read(HfsPPrivateFile* file, void *buf, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent phy_area; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - char *b = buf; - - if (sector+nb < sector /* detect overflow */ - || sector+nb > file->sect_nb) /* out of file */ { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to read HFS+ file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - while (nb) { - phy_area = hfsplus_file_find_extent(file, sector, nb); - if (phy_area.sector_count == 0) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS+ file " - "with CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - if (!ped_geometry_read(priv_data->plus_geom, b, - phy_area.start_sector, - phy_area.sector_count)) - return 0; - - nb -= phy_area.sector_count; /* < nb anyway ... */ - sector += phy_area.sector_count; - b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT; - } - - return 1; -} - -int -hfsplus_file_write(HfsPPrivateFile* file, void *buf, PedSector sector, - unsigned int nb) -{ - HfsPPrivateExtent phy_area; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - file->fs->type_specific; - char *b = buf; - - if (sector+nb < sector /* detect overflow */ - || sector+nb > file->sect_nb) /* out of file */ { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Trying to write HFS+ file with CNID %X behind EOF."), - PED_BE32_TO_CPU(file->CNID)); - return 0; - } - - while (nb) { - phy_area = hfsplus_file_find_extent(file, sector, nb); - if (phy_area.sector_count == 0) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not find sector %lli of HFS+ file " - "with CNID %X."), - sector, PED_BE32_TO_CPU(file->CNID)); - return 0; - } - if (!ped_geometry_write(priv_data->plus_geom, b, - phy_area.start_sector, - phy_area.sector_count)) - return 0; - - nb -= phy_area.sector_count; /* < nb anyway ... */ - sector += phy_area.sector_count; - b += phy_area.sector_count * PED_SECTOR_SIZE_DEFAULT; - } - - return 1; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.h b/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.h deleted file mode 100644 index 0c875d13ae..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _FILE_PLUS_H -#define _FILE_PLUS_H - -#include -#include -#include - -#include "hfs.h" - -HfsPPrivateFile* -hfsplus_file_open (PedFileSystem *fs, HfsPNodeID CNID, - HfsPExtDataRec ext_desc, PedSector sect_nb); - -void -hfsplus_file_close (HfsPPrivateFile* file); - -int -hfsplus_file_read(HfsPPrivateFile* file, void *buf, - PedSector sector, unsigned int nb); - -int -hfsplus_file_write(HfsPPrivateFile* file, void *buf, - PedSector sector, unsigned int nb); - -/* Read the nth sector of a file */ -/* return 0 on error */ -static __inline__ int -hfsplus_file_read_sector (HfsPPrivateFile* file, void *buf, PedSector sector) -{ - return hfsplus_file_read(file, buf, sector, 1); -} - -/* Write the nth sector of a file */ -/* return 0 on error */ -static __inline__ int -hfsplus_file_write_sector (HfsPPrivateFile* file, void *buf, PedSector sector) -{ - return hfsplus_file_write(file, buf, sector, 1); -} - - -#endif /* _FILE_PLUS_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.c b/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.c deleted file mode 100644 index 2a3936d6f1..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.c +++ /dev/null @@ -1,1353 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - Author : Guillaume Knispel - Report bug to -*/ - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "probe.h" - -uint8_t* hfs_block = NULL; -uint8_t* hfsp_block = NULL; -unsigned hfs_block_count; -unsigned hfsp_block_count; - -#define HFS_BLOCK_SIZES ((int[2]){512, 0}) -#define HFSP_BLOCK_SIZES ((int[2]){512, 0}) -#define HFSX_BLOCK_SIZES ((int[2]){512, 0}) - -#ifndef DISCOVER_ONLY -#include "file.h" -#include "reloc.h" -#include "advfs.h" - -static PedFileSystemType hfs_type; -static PedFileSystemType hfsplus_type; - - -/* ----- HFS ----- */ - -/* This is a very unundoable operation */ -/* Maybe I shouldn't touch the alternate MDB ? */ -/* Anyway clobber is call before other fs creation */ -/* So this is a non-issue */ -static int -hfs_clobber (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - - memset (buf, 0, PED_SECTOR_SIZE_DEFAULT); - - /* destroy boot blocks, mdb, alternate mdb ... */ - return (!!ped_geometry_write (geom, buf, 0, 1)) & - (!!ped_geometry_write (geom, buf, 1, 1)) & - (!!ped_geometry_write (geom, buf, 2, 1)) & - (!!ped_geometry_write (geom, buf, geom->length - 2, 1)) & - (!!ped_geometry_write (geom, buf, geom->length - 1, 1)) & - (!!ped_geometry_sync (geom)); -} - -static PedFileSystem* -hfs_open (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedFileSystem* fs; - HfsMasterDirectoryBlock* mdb; - HfsPrivateFSData* priv_data; - - if (!hfsc_can_use_geom (geom)) - return NULL; - - /* Read MDB */ - if (!ped_geometry_read (geom, buf, 2, 1)) - return NULL; - - /* Allocate memory */ - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto ho; - mdb = (HfsMasterDirectoryBlock*) - ped_malloc (sizeof (HfsMasterDirectoryBlock)); - if (!mdb) goto ho_fs; - priv_data = (HfsPrivateFSData*) - ped_malloc (sizeof (HfsPrivateFSData)); - if (!priv_data) goto ho_mdb; - - memcpy (mdb, buf, sizeof (HfsMasterDirectoryBlock)); - - /* init structures */ - priv_data->mdb = mdb; - priv_data->bad_blocks_loaded = 0; - priv_data->bad_blocks_xtent_nb = 0; - priv_data->bad_blocks_xtent_list = NULL; - priv_data->extent_file = - hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), - mdb->extents_file_rec, - PED_CPU_TO_BE32 (mdb->extents_file_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->extent_file) goto ho_pd; - priv_data->catalog_file = - hfs_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), - mdb->catalog_file_rec, - PED_CPU_TO_BE32 (mdb->catalog_file_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->catalog_file) goto ho_ce; - /* Read allocation blocks */ - if (!ped_geometry_read(geom, priv_data->alloc_map, - PED_BE16_TO_CPU (mdb->volume_bitmap_block), - ( PED_BE16_TO_CPU (mdb->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8) ) ) - goto ho_cf; - - fs->type = &hfs_type; - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) goto ho_cf; - fs->type_specific = (void*) priv_data; - fs->checked = ( PED_BE16_TO_CPU (mdb->volume_attributes) - >> HFS_UNMOUNTED ) & 1; - - return fs; - -/*--- clean error handling ---*/ -ho_cf: hfs_file_close(priv_data->catalog_file); -ho_ce: hfs_file_close(priv_data->extent_file); -ho_pd: ped_free(priv_data); -ho_mdb: ped_free(mdb); -ho_fs: ped_free(fs); -ho: return NULL; -} - -static int -hfs_close (PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific; - - hfs_file_close (priv_data->extent_file); - hfs_file_close (priv_data->catalog_file); - if (priv_data->bad_blocks_loaded) - hfs_free_bad_blocks_list (priv_data->bad_blocks_xtent_list); - ped_free (priv_data->mdb); - ped_free (priv_data); - ped_geometry_destroy (fs->geom); - ped_free (fs); - - return 1; -} - -static PedConstraint* -hfs_get_resize_constraint (const PedFileSystem *fs) -{ - PedDevice* dev = fs->geom->dev; - PedAlignment start_align; - PedGeometry start_sector; - PedGeometry full_dev; - PedSector min_size; - - if (!ped_alignment_init (&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1)) - return NULL; - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - /* 2 = last two sectors (alternate MDB and unused sector) */ - min_size = hfs_get_empty_end(fs) + 2; - if (min_size == 2) return NULL; - - return ped_constraint_new (&start_align, ped_alignment_any, - &start_sector, &full_dev, min_size, - fs->geom->length); -} - -static int -hfs_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - unsigned int nblock, nfree; - unsigned int block, to_free; - HfsPrivateFSData* priv_data; - HfsMasterDirectoryBlock* mdb; - int resize = 1; - unsigned int hfs_sect_block; - PedSector hgee; - - /* check preconditions */ - PED_ASSERT (fs != NULL, return 0); - PED_ASSERT (fs->geom != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); -#ifdef DEBUG - PED_ASSERT ((hgee = hfs_get_empty_end(fs)) != 0, return 0); -#else - if ((hgee = hfs_get_empty_end(fs)) == 0) - return 0; -#endif - - PED_ASSERT ((hgee = hfs_get_empty_end(fs)) != 0, return 0); - - if (ped_geometry_test_equal(fs->geom, geom)) - return 1; - - priv_data = (HfsPrivateFSData*) fs->type_specific; - mdb = priv_data->mdb; - hfs_sect_block = PED_BE32_TO_CPU (mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - - if (fs->geom->start != geom->start - || geom->length > fs->geom->length - || geom->length < hgee + 2) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Sorry, HFS cannot be resized that way yet.")); - return 0; - } - - /* Flush caches */ - if (!ped_geometry_sync(fs->geom)) - return 0; - - /* Clear the unmounted bit */ - mdb->volume_attributes &= PED_CPU_TO_BE16 (~( 1 << HFS_UNMOUNTED )); - if (!ped_geometry_read (fs->geom, buf, 2, 1)) - return 0; - memcpy (buf, mdb, sizeof (HfsMasterDirectoryBlock)); - if ( !ped_geometry_write (fs->geom, buf, 2, 1) - || !ped_geometry_sync (fs->geom)) - return 0; - - ped_timer_reset (timer); - ped_timer_set_state_name(timer, _("shrinking")); - ped_timer_update(timer, 0.0); - /* relocate data */ - to_free = ( fs->geom->length - geom->length - + hfs_sect_block - 1 ) - / hfs_sect_block ; - block = hfs_find_start_pack (fs, to_free); - if (!hfs_pack_free_space_from_block (fs, block, timer, to_free)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Data relocation has failed.")); - goto write_MDB; - } - - /* Calculate new block number and other MDB field */ - nblock = ( geom->length - (PED_BE16_TO_CPU (mdb->start_block) + 2) ) - / hfs_sect_block; - nfree = PED_BE16_TO_CPU (mdb->free_blocks) - - ( PED_BE16_TO_CPU (mdb->total_blocks) - nblock ); - - /* Check that all block after future end are really free */ - for (block = nblock; - block < PED_BE16_TO_CPU (mdb->total_blocks); - block++) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Data relocation left some data in the end " - "of the volume.")); - goto write_MDB; - } - } - - /* Mark out of volume blocks as used - (broken implementations compatibility) */ - for ( block = nblock; block < (1 << 16); ++block) - SET_BLOC_OCCUPATION(priv_data->alloc_map,block); - - /* save the allocation map - I do not write until start of allocation blocks - but only until pre-resize end of bitmap blocks - because the specifications do _not_ assert that everything - until allocation blocks is boot, mdb and alloc */ - ped_geometry_write(fs->geom, priv_data->alloc_map, - PED_BE16_TO_CPU (priv_data->mdb->volume_bitmap_block), - ( PED_BE16_TO_CPU (priv_data->mdb->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1) - / (PED_SECTOR_SIZE_DEFAULT * 8)); - - /* Update geometry */ - if (resize) { - /* update in fs structure */ - if (PED_BE16_TO_CPU (mdb->next_allocation) >= nblock) - mdb->next_allocation = PED_CPU_TO_BE16 (0); - mdb->total_blocks = PED_CPU_TO_BE16 (nblock); - mdb->free_blocks = PED_CPU_TO_BE16 (nfree); - /* update parted structure */ - fs->geom->length = geom->length; - fs->geom->end = fs->geom->start + geom->length - 1; - } - - /* Set the unmounted bit */ - mdb->volume_attributes |= PED_CPU_TO_BE16 ( 1 << HFS_UNMOUNTED ); - - /* Effective write */ - write_MDB: - ped_timer_set_state_name(timer,_("writing HFS Master Directory Block")); - - if (!hfs_update_mdb(fs)) { - ped_geometry_sync(geom); - return 0; - } - - if (!ped_geometry_sync(geom)) - return 0; - - ped_timer_update(timer, 1.0); - - return (resize); -} - -/* ----- HFS+ ----- */ - -#include "file_plus.h" -#include "advfs_plus.h" -#include "reloc_plus.h" -#include "journal.h" - -static int -hfsplus_clobber (PedGeometry* geom) -{ - unsigned int i = 1; - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - HfsMasterDirectoryBlock *mdb; - - mdb = (HfsMasterDirectoryBlock *) buf; - - if (!ped_geometry_read (geom, buf, 2, 1)) - return 0; - - if (PED_BE16_TO_CPU (mdb->signature) == HFS_SIGNATURE) { - /* embedded hfs+ */ - PedGeometry *embedded; - - i = PED_BE32_TO_CPU(mdb->block_size) / PED_SECTOR_SIZE_DEFAULT; - embedded = ped_geometry_new ( - geom->dev, - (PedSector) geom->start - + PED_BE16_TO_CPU (mdb->start_block) - + (PedSector) PED_BE16_TO_CPU ( - mdb->old_new.embedded.location.start_block ) * i, - (PedSector) PED_BE16_TO_CPU ( - mdb->old_new.embedded.location.block_count ) * i ); - if (!embedded) i = 0; - else { - i = hfs_clobber (embedded); - ped_geometry_destroy (embedded); - } - } - - /* non-embedded or envelop destroy as hfs */ - return ( hfs_clobber (geom) && i ); -} - -static int -hfsplus_close (PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - if (priv_data->bad_blocks_loaded) - hfsplus_free_bad_blocks_list(priv_data->bad_blocks_xtent_list); - ped_free(priv_data->alloc_map); - ped_free(priv_data->dirty_alloc_map); - hfsplus_file_close (priv_data->allocation_file); - hfsplus_file_close (priv_data->attributes_file); - hfsplus_file_close (priv_data->catalog_file); - hfsplus_file_close (priv_data->extents_file); - if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); - if (priv_data->wrapper) hfs_close(priv_data->wrapper); - ped_geometry_destroy (fs->geom); - ped_free(priv_data->vh); - ped_free(priv_data); - ped_free(fs); - - return 1; -} - -static PedFileSystem* -hfsplus_open (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedFileSystem* fs; - HfsPVolumeHeader* vh; - HfsPPrivateFSData* priv_data; - PedGeometry* wrapper_geom; - unsigned int map_sectors; - - if (!hfsc_can_use_geom (geom)) - return NULL; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) goto hpo; - vh = (HfsPVolumeHeader*) ped_malloc (sizeof (HfsPVolumeHeader)); - if (!vh) goto hpo_fs; - priv_data = (HfsPPrivateFSData*)ped_malloc (sizeof (HfsPPrivateFSData)); - if (!priv_data) goto hpo_vh; - - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) goto hpo_pd; - fs->type_specific = (void*) priv_data; - - if ((wrapper_geom = hfs_and_wrapper_probe (geom))) { - HfsPrivateFSData* hfs_priv_data; - PedSector abs_sect, length; - unsigned int bs; - - ped_geometry_destroy (wrapper_geom); - priv_data->wrapper = hfs_open(geom); - if (!priv_data->wrapper) goto hpo_gm; - hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - bs = PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - abs_sect = (PedSector) geom->start - + (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->start_block) - + (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.start_block ) - * bs; - length = (PedSector) PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.block_count) - * bs; - priv_data->plus_geom = ped_geometry_new (geom->dev, abs_sect, - length); - if (!priv_data->plus_geom) goto hpo_wr; - priv_data->free_geom = 1; - } else { - priv_data->wrapper = NULL; - priv_data->plus_geom = fs->geom; - priv_data->free_geom = 0; - } - - if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) goto hpo_pg; - memcpy (vh, buf, sizeof (HfsPVolumeHeader)); - priv_data->vh = vh; - - if (vh->signature != PED_CPU_TO_BE16(HFSP_SIGNATURE) - && vh->signature != PED_CPU_TO_BE16(HFSX_SIGNATURE)) { - ped_exception_throw ( - PED_EXCEPTION_BUG, - PED_EXCEPTION_CANCEL, - _("No valid HFS[+X] signature has been found while " - "opening.")); - goto hpo_pg; - } - - if (vh->signature == PED_CPU_TO_BE16(HFSP_SIGNATURE) - && vh->version != PED_CPU_TO_BE16(HFSP_VERSION)) { - if (ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_IGNORE_CANCEL, - _("Version %d of HFS+ isn't supported."), - PED_BE16_TO_CPU(vh->version)) - != PED_EXCEPTION_IGNORE) - goto hpo_pg; - } - - if (vh->signature == PED_CPU_TO_BE16(HFSX_SIGNATURE) - && vh->version != PED_CPU_TO_BE16(HFSX_VERSION)) { - if (ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_IGNORE_CANCEL, - _("Version %d of HFSX isn't supported."), - PED_BE16_TO_CPU(vh->version)) - != PED_EXCEPTION_IGNORE) - goto hpo_pg; - } - - priv_data->jib_start_block = 0; - priv_data->jl_start_block = 0; - if (vh->attributes & PED_CPU_TO_BE32(1<bad_blocks_loaded = 0; - priv_data->bad_blocks_xtent_nb = 0; - priv_data->bad_blocks_xtent_list = NULL; - priv_data->extents_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_XTENT_ID), - vh->extents_file.extents, - PED_BE64_TO_CPU ( - vh->extents_file.logical_size ) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->extents_file) goto hpo_pg; - priv_data->catalog_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFS_CATALOG_ID), - vh->catalog_file.extents, - PED_BE64_TO_CPU ( - vh->catalog_file.logical_size ) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->catalog_file) goto hpo_ce; - priv_data->attributes_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ATTRIB_ID), - vh->attributes_file.extents, - PED_BE64_TO_CPU ( - vh->attributes_file.logical_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->attributes_file) goto hpo_cc; - - map_sectors = ( PED_BE32_TO_CPU (vh->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - priv_data->dirty_alloc_map = (uint8_t*) - ped_malloc ((map_sectors + 7) / 8); - if (!priv_data->dirty_alloc_map) goto hpo_cl; - memset(priv_data->dirty_alloc_map, 0, (map_sectors + 7) / 8); - priv_data->alloc_map = (uint8_t*) - ped_malloc (map_sectors * PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->alloc_map) goto hpo_dm; - - priv_data->allocation_file = - hfsplus_file_open (fs, PED_CPU_TO_BE32 (HFSP_ALLOC_ID), - vh->allocation_file.extents, - PED_BE64_TO_CPU ( - vh->allocation_file.logical_size) - / PED_SECTOR_SIZE_DEFAULT); - if (!priv_data->allocation_file) goto hpo_am; - if (!hfsplus_file_read (priv_data->allocation_file, - priv_data->alloc_map, 0, map_sectors)) { - hfsplus_close(fs); - return NULL; - } - - fs->type = &hfsplus_type; - fs->checked = ((PED_BE32_TO_CPU (vh->attributes) >> HFS_UNMOUNTED) & 1) - && !((PED_BE32_TO_CPU (vh->attributes) >> HFSP_INCONSISTENT) & 1); - - return fs; - -/*--- clean error handling ---*/ -hpo_am: ped_free(priv_data->alloc_map); -hpo_dm: ped_free(priv_data->dirty_alloc_map); -hpo_cl: hfsplus_file_close (priv_data->attributes_file); -hpo_cc: hfsplus_file_close (priv_data->catalog_file); -hpo_ce: hfsplus_file_close (priv_data->extents_file); -hpo_pg: if (priv_data->free_geom) ped_geometry_destroy (priv_data->plus_geom); -hpo_wr: if (priv_data->wrapper) hfs_close(priv_data->wrapper); -hpo_gm: ped_geometry_destroy (fs->geom); -hpo_pd: ped_free(priv_data); -hpo_vh: ped_free(vh); -hpo_fs: ped_free(fs); -hpo: return NULL; -} - -static PedConstraint* -hfsplus_get_resize_constraint (const PedFileSystem *fs) -{ - PedDevice* dev = fs->geom->dev; - PedAlignment start_align; - PedGeometry start_sector; - PedGeometry full_dev; - PedSector min_size; - - if (!ped_alignment_init (&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init (&start_sector, dev, fs->geom->start, 1)) - return NULL; - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - min_size = hfsplus_get_min_size (fs); - if (!min_size) return NULL; - - return ped_constraint_new (&start_align, ped_alignment_any, - &start_sector, &full_dev, min_size, - fs->geom->length); -} - -static int -hfsplus_volume_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - unsigned int nblock, nfree, mblock; - unsigned int block, to_free, old_blocks; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - int resize = 1; - unsigned int hfsp_sect_block = - ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); - unsigned int map_sectors; - - old_blocks = PED_BE32_TO_CPU (vh->total_blocks); - - /* Flush caches */ - if (!ped_geometry_sync(priv_data->plus_geom)) - return 0; - - /* Clear the unmounted bit */ - /* and set the implementation code (Apple Creator Code) */ - vh->attributes &= PED_CPU_TO_BE32 (~( 1 << HFS_UNMOUNTED )); - vh->last_mounted_version = PED_CPU_TO_BE32(HFSP_IMPL_Shnk); - if (!ped_geometry_read (priv_data->plus_geom, buf, 2, 1)) - return 0; - memcpy (buf, vh, sizeof (HfsPVolumeHeader)); - if ( !ped_geometry_write (priv_data->plus_geom, buf, 2, 1) - || !ped_geometry_sync (priv_data->plus_geom)) - return 0; - - ped_timer_reset (timer); - ped_timer_set_state_name(timer, _("shrinking")); - ped_timer_update(timer, 0.0); - /* relocate data */ - to_free = ( priv_data->plus_geom->length - - geom->length + hfsp_sect_block - - 1 ) / hfsp_sect_block; - block = hfsplus_find_start_pack (fs, to_free); - if (!hfsplus_pack_free_space_from_block (fs, block, timer, to_free)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Data relocation has failed.")); - goto write_VH; - } - - /* Calculate new block number and other VH field */ - /* nblock must be rounded _down_ */ - nblock = geom->length / hfsp_sect_block; - nfree = PED_BE32_TO_CPU (vh->free_blocks) - - (old_blocks - nblock); - /* free block readjustement is only needed when incorrect nblock - was used by my previous implementation, so detect the case */ - if (priv_data->plus_geom->length < old_blocks - * ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT) ) { - if (priv_data->plus_geom->length % hfsp_sect_block == 1) - nfree++; - } - - /* Check that all block after future end are really free */ - mblock = ( priv_data->plus_geom->length - 2 ) - / hfsp_sect_block; - if (mblock > old_blocks - 1) - mblock = old_blocks - 1; - for ( block = nblock; - block < mblock; - block++ ) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,block)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Data relocation left some data at the end " - "of the volume.")); - goto write_VH; - } - } - - /* Mark out of volume blocks as used */ - map_sectors = ( ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8) ) - * (PED_SECTOR_SIZE_DEFAULT * 8); - for ( block = nblock; block < map_sectors; ++block) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - - /* Update geometry */ - if (resize) { - /* update in fs structure */ - if (PED_BE32_TO_CPU (vh->next_allocation) >= nblock) - vh->next_allocation = PED_CPU_TO_BE32 (0); - vh->total_blocks = PED_CPU_TO_BE32 (nblock); - vh->free_blocks = PED_CPU_TO_BE32 (nfree); - /* update parted structure */ - priv_data->plus_geom->length = geom->length; - priv_data->plus_geom->end = priv_data->plus_geom->start - + geom->length - 1; - } - - /* Effective write */ - write_VH: - /* lasts two sectors are allocated by the alternate VH - and a reserved sector, and last block is always reserved */ - block = (priv_data->plus_geom->length - 1) / hfsp_sect_block; - if (block < PED_BE32_TO_CPU (vh->total_blocks)) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - block = (priv_data->plus_geom->length - 2) / hfsp_sect_block; - if (block < PED_BE32_TO_CPU (vh->total_blocks)) - SET_BLOC_OCCUPATION(priv_data->alloc_map, block); - SET_BLOC_OCCUPATION(priv_data->alloc_map, - PED_BE32_TO_CPU (vh->total_blocks) - 1); - - /* Write the _old_ area to set out of volume blocks as used */ - map_sectors = ( old_blocks + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - if (!hfsplus_file_write (priv_data->allocation_file, - priv_data->alloc_map, 0, map_sectors)) { - resize = 0; - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Error while writing the allocation file.")); - } else { - /* Write remaining part of allocation bitmap */ - /* This is necessary to handle pre patch-11 and third party */ - /* implementations */ - memset(buf, 0xFF, PED_SECTOR_SIZE_DEFAULT); - for (block = map_sectors; - block < priv_data->allocation_file->sect_nb; - ++block) { - if (!hfsplus_file_write_sector ( - priv_data->allocation_file, - buf, block)) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("Error while writing the " - "compatibility part of the " - "allocation file.")); - break; - } - } - } - ped_geometry_sync (priv_data->plus_geom); - - if (resize) { - /* Set the unmounted bit and clear the inconsistent bit */ - vh->attributes |= PED_CPU_TO_BE32 ( 1 << HFS_UNMOUNTED ); - vh->attributes &= ~ PED_CPU_TO_BE32 ( 1 << HFSP_INCONSISTENT ); - } - - ped_timer_set_state_name(timer, _("writing HFS+ Volume Header")); - if (!hfsplus_update_vh(fs)) { - ped_geometry_sync(priv_data->plus_geom); - return 0; - } - - if (!ped_geometry_sync(priv_data->plus_geom)) - return 0; - - ped_timer_update(timer, 1.0); - - return (resize); -} - -/* Update the HFS wrapper mdb and bad blocks file to reflect - the new geometry of the embedded HFS+ volume */ -static int -hfsplus_wrapper_update (PedFileSystem* fs) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsCPrivateLeafRec ref; - HfsExtentKey key; - HfsNodeDescriptor* node_desc = (HfsNodeDescriptor*) node; - HfsExtentKey* ret_key; - HfsExtDescriptor* ret_data; - unsigned int i; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - unsigned int hfs_sect_block = - PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT ; - PedSector hfsplus_sect = (PedSector) - PED_BE32_TO_CPU (priv_data->vh->total_blocks) - * ( PED_BE32_TO_CPU (priv_data->vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ); - unsigned int hfs_blocks_embedded = - (hfsplus_sect + hfs_sect_block - 1) - / hfs_sect_block; - unsigned int hfs_blocks_embedded_old; - - /* update HFS wrapper MDB */ - hfs_blocks_embedded_old = PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new - .embedded.location.block_count ); - hfs_priv_data->mdb->old_new.embedded.location.block_count = - PED_CPU_TO_BE16 (hfs_blocks_embedded); - /* maybe macOS will boot with this */ - /* update : yes it does \o/ :) */ - hfs_priv_data->mdb->free_blocks = - PED_CPU_TO_BE16 ( PED_BE16_TO_CPU (hfs_priv_data->mdb->free_blocks) - + hfs_blocks_embedded_old - - hfs_blocks_embedded ); - - if (!hfs_update_mdb(priv_data->wrapper)) - return 0; - - /* force reload bad block list */ - if (hfs_priv_data->bad_blocks_loaded) { - hfs_free_bad_blocks_list (hfs_priv_data->bad_blocks_xtent_list); - hfs_priv_data->bad_blocks_xtent_list = NULL; - hfs_priv_data->bad_blocks_xtent_nb = 0; - hfs_priv_data->bad_blocks_loaded = 0; - } - - /* clean HFS wrapper allocation map */ - for (i = PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new.embedded - .location.start_block ) - + hfs_blocks_embedded; - i < PED_BE16_TO_CPU ( - hfs_priv_data->mdb->old_new.embedded - .location.start_block ) - + hfs_blocks_embedded_old; - i++ ) { - CLR_BLOC_OCCUPATION(hfs_priv_data->alloc_map, i); - } - /* and save it */ - if (!ped_geometry_write (fs->geom, hfs_priv_data->alloc_map, - PED_BE16_TO_CPU ( - hfs_priv_data->mdb->volume_bitmap_block ), - ( PED_BE16_TO_CPU ( - hfs_priv_data->mdb->total_blocks ) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8))) - return 0; - if (!ped_geometry_sync (fs->geom)) - return 0; - - /* search and update the bad blocks file */ - key.key_length = sizeof(key) - 1; - key.type = HFS_DATA_FORK; - key.file_ID = PED_CPU_TO_BE32 (HFS_BAD_BLOCK_ID); - key.start = 0; - if (!hfs_btree_search (hfs_priv_data->extent_file, - (HfsPrivateGenericKey*) &key, NULL, 0, &ref)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("An error occurred while looking for the mandatory " - "bad blocks file.")); - return 0; - } - if (!hfs_file_read_sector (hfs_priv_data->extent_file, node, - ref.node_number)) - return 0; - ret_key = (HfsExtentKey*) (node + ref.record_pos); - ret_data = (HfsExtDescriptor*) ( node + ref.record_pos - + sizeof (HfsExtentKey) ); - - while (ret_key->type == key.type && ret_key->file_ID == key.file_ID) { - for (i = 0; i < HFS_EXT_NB; i++) { - if ( ret_data[i].start_block - == hfs_priv_data->mdb->old_new - .embedded.location.start_block) { - ret_data[i].block_count = - hfs_priv_data->mdb->old_new - .embedded.location.block_count; - /* found ! : update */ - if (!hfs_file_write_sector ( - hfs_priv_data->extent_file, - node, ref.node_number) - || !ped_geometry_sync(fs->geom)) - return 0; - return 1; - } - } - - if (ref.record_number < PED_BE16_TO_CPU (node_desc->rec_nb)) { - ref.record_number++; - } else { - ref.node_number = PED_BE32_TO_CPU (node_desc->next); - if (!ref.node_number - || !hfs_file_read_sector(hfs_priv_data->extent_file, - node, ref.node_number)) - goto bb_not_found; - ref.record_number = 1; - } - - ref.record_pos = - PED_BE16_TO_CPU (*((uint16_t *) - (node + (PED_SECTOR_SIZE_DEFAULT - - 2*ref.record_number)))); - ret_key = (HfsExtentKey*) (node + ref.record_pos); - ret_data = (HfsExtDescriptor*) ( node + ref.record_pos - + sizeof (HfsExtentKey) ); - } - -bb_not_found: - /* not found : not a valid hfs+ wrapper : failure */ - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("It seems there is an error in the HFS wrapper: the bad " - "blocks file doesn't contain the embedded HFS+ volume.")); - return 0; -} - -static int -hfsplus_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - HfsPPrivateFSData* priv_data; - PedTimer* timer_plus; - PedGeometry* embedded_geom; - PedSector hgms; - - /* check preconditions */ - PED_ASSERT (fs != NULL, return 0); - PED_ASSERT (fs->geom != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (fs->geom->dev == geom->dev, return 0); -#ifdef DEBUG - PED_ASSERT ((hgms = hfsplus_get_min_size (fs)) != 0, return 0); -#else - if ((hgms = hfsplus_get_min_size (fs)) == 0) - return 0; -#endif - - if (ped_geometry_test_equal(fs->geom, geom)) - return 1; - - priv_data = (HfsPPrivateFSData*) fs->type_specific; - - if (fs->geom->start != geom->start - || geom->length > fs->geom->length - || geom->length < hgms) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Sorry, HFS+ cannot be resized that way yet.")); - return 0; - } - - if (priv_data->wrapper) { - PedSector red, hgee; - HfsPrivateFSData* hfs_priv_data = (HfsPrivateFSData*) - priv_data->wrapper->type_specific; - unsigned int hfs_sect_block = - PED_BE32_TO_CPU (hfs_priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT; - - /* There is a wrapper so we must calculate the new geometry - of the embedded HFS+ volume */ - red = ( (fs->geom->length - geom->length + hfs_sect_block - 1) - / hfs_sect_block ) * hfs_sect_block; - /* Can't we shrink the hfs+ volume by the desired size ? */ - hgee = hfsplus_get_empty_end (fs); - if (!hgee) return 0; - if (red > priv_data->plus_geom->length - hgee) { - /* No, shrink hfs+ by the greatest possible value */ - hgee = ((hgee + hfs_sect_block - 1) / hfs_sect_block) - * hfs_sect_block; - red = priv_data->plus_geom->length - hgee; - } - embedded_geom = ped_geometry_new (geom->dev, - priv_data->plus_geom->start, - priv_data->plus_geom->length - - red); - - /* There is a wrapper so the resize process is a two stages - process (embedded resizing then wrapper resizing) : - we create a sub timer */ - ped_timer_reset (timer); - ped_timer_set_state_name (timer, - _("shrinking embedded HFS+ volume")); - ped_timer_update(timer, 0.0); - timer_plus = ped_timer_new_nested (timer, 0.98); - } else { - /* No wrapper : the desired geometry is the desired - HFS+ volume geometry */ - embedded_geom = geom; - timer_plus = timer; - } - - /* Resize the HFS+ volume */ - if (!hfsplus_volume_resize (fs, embedded_geom, timer_plus)) { - if (timer_plus != timer) ped_timer_destroy_nested (timer_plus); - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Resizing the HFS+ volume has failed.")); - return 0; - } - - if (priv_data->wrapper) { - ped_geometry_destroy (embedded_geom); - ped_timer_destroy_nested (timer_plus); - ped_timer_set_state_name(timer, _("shrinking HFS wrapper")); - timer_plus = ped_timer_new_nested (timer, 0.02); - /* There's a wrapper : second stage = resizing it */ - if (!hfsplus_wrapper_update (fs) - || !hfs_resize (priv_data->wrapper, geom, timer_plus)) { - ped_timer_destroy_nested (timer_plus); - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Updating the HFS wrapper has failed.")); - return 0; - } - ped_timer_destroy_nested (timer_plus); - } - ped_timer_update(timer, 1.0); - - return 1; -} - -#ifdef HFS_EXTRACT_FS -/* The following is for debugging purpose only, NOT for packaging */ - -#include - -uint8_t* extract_buffer = NULL; - -static int -hfs_extract_file(const char* filename, HfsPrivateFile* hfs_file) -{ - FILE* fout; - PedSector sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (sect = 0; sect < hfs_file->sect_nb; ++sect) { - if (!hfs_file_read_sector(hfs_file, extract_buffer, sect)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfs_extract_bitmap(const char* filename, PedFileSystem* fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - unsigned int count; - FILE* fout; - PedSector sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (sect = PED_BE16_TO_CPU(mdb->volume_bitmap_block); - sect < PED_BE16_TO_CPU(mdb->start_block); - sect += count) { - uint16_t st_block = PED_BE16_TO_CPU(mdb->start_block); - count = (st_block-sect) < BLOCK_MAX_BUFF ? - (st_block-sect) : BLOCK_MAX_BUFF; - if (!ped_geometry_read(fs->geom, extract_buffer, sect, count)) - goto err_close; - if (!fwrite (extract_buffer, count * PED_SECTOR_SIZE_DEFAULT, - 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfs_extract_mdb (const char* filename, PedFileSystem* fs) -{ - FILE* fout; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - if (!ped_geometry_read(fs->geom, extract_buffer, 2, 1)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfs_extract (PedFileSystem* fs, PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This is not a real %s check. This is going to extract " - "special low level files for debugging purposes."), - "HFS"); - - extract_buffer = ped_malloc(BLOCK_MAX_BUFF * PED_SECTOR_SIZE_DEFAULT); - if (!extract_buffer) return 0; - - hfs_extract_mdb(HFS_MDB_FILENAME, fs); - hfs_extract_file(HFS_CATALOG_FILENAME, priv_data->catalog_file); - hfs_extract_file(HFS_EXTENTS_FILENAME, priv_data->extent_file); - hfs_extract_bitmap(HFS_BITMAP_FILENAME, fs); - - ped_free(extract_buffer); extract_buffer = NULL; - return 0; /* nothing has been fixed by us ! */ -} - -static int -hfsplus_extract_file(const char* filename, HfsPPrivateFile* hfsp_file) -{ - FILE* fout; - unsigned int cp_sect; - PedSector rem_sect; - - fout = fopen(filename, "w"); - if (!fout) return 0; - - for (rem_sect = hfsp_file->sect_nb; rem_sect; rem_sect -= cp_sect) { - cp_sect = rem_sect < BLOCK_MAX_BUFF ? rem_sect : BLOCK_MAX_BUFF; - if (!hfsplus_file_read(hfsp_file, extract_buffer, - hfsp_file->sect_nb - rem_sect, cp_sect)) - goto err_close; - if (!fwrite (extract_buffer, cp_sect * PED_SECTOR_SIZE_DEFAULT, - 1, fout)) - goto err_close; - } - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -static int -hfsplus_extract_vh (const char* filename, PedFileSystem* fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - FILE* fout; - PedGeometry* geom = priv_data->plus_geom; - - - fout = fopen(filename, "w"); - if (!fout) return 0; - - if (!ped_geometry_read(geom, extract_buffer, 2, 1)) - goto err_close; - if (!fwrite(extract_buffer, PED_SECTOR_SIZE_DEFAULT, 1, fout)) - goto err_close; - - return (fclose(fout) == 0 ? 1 : 0); - -err_close: - fclose(fout); - return 0; -} - -/* TODO : use the timer to report what is happening */ -/* TODO : use exceptions to report errors */ -static int -hfsplus_extract (PedFileSystem* fs, PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - HfsPPrivateFile* startup_file; - - if (priv_data->wrapper) { - /* TODO : create nested timer */ - hfs_extract (priv_data->wrapper, timer); - } - - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This is not a real %s check. This is going to extract " - "special low level files for debugging purposes."), - "HFS+"); - - extract_buffer = ped_malloc(BLOCK_MAX_BUFF * PED_SECTOR_SIZE_DEFAULT); - if (!extract_buffer) return 0; - - hfsplus_extract_vh(HFSP_VH_FILENAME, fs); - hfsplus_extract_file(HFSP_CATALOG_FILENAME, priv_data->catalog_file); - hfsplus_extract_file(HFSP_EXTENTS_FILENAME, priv_data->extents_file); - hfsplus_extract_file(HFSP_ATTRIB_FILENAME, priv_data->attributes_file); - hfsplus_extract_file(HFSP_BITMAP_FILENAME, priv_data->allocation_file); - - startup_file = hfsplus_file_open(fs, PED_CPU_TO_BE32(HFSP_STARTUP_ID), - vh->startup_file.extents, - PED_BE64_TO_CPU ( - vh->startup_file.logical_size) - / PED_SECTOR_SIZE_DEFAULT); - if (startup_file) { - hfsplus_extract_file(HFSP_STARTUP_FILENAME, startup_file); - hfsplus_file_close(startup_file); startup_file = NULL; - } - - ped_free(extract_buffer); extract_buffer = NULL; - return 0; /* nothing has been fixed by us ! */ -} -#endif /* HFS_EXTRACT_FS */ - -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps hfs_ops = { - .probe = hfs_probe, -#ifndef DISCOVER_ONLY - .clobber = hfs_clobber, - .open = hfs_open, - .create = NULL, - .close = hfs_close, -#ifndef HFS_EXTRACT_FS - .check = NULL, -#else - .check = hfs_extract, -#endif - .copy = NULL, - .resize = hfs_resize, - .get_create_constraint = NULL, - .get_resize_constraint = hfs_get_resize_constraint, - .get_copy_constraint = NULL, -#else /* DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL, -#endif /* DISCOVER_ONLY */ -}; - -static PedFileSystemOps hfsplus_ops = { - .probe = hfsplus_probe, -#ifndef DISCOVER_ONLY - .clobber = hfsplus_clobber, - .open = hfsplus_open, - .create = NULL, - .close = hfsplus_close, -#ifndef HFS_EXTRACT_FS - .check = NULL, -#else - .check = hfsplus_extract, -#endif - .copy = NULL, - .resize = hfsplus_resize, - .get_create_constraint = NULL, - .get_resize_constraint = hfsplus_get_resize_constraint, - .get_copy_constraint = NULL, -#else /* DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL, -#endif /* DISCOVER_ONLY */ -}; - -static PedFileSystemOps hfsx_ops = { - .probe = hfsx_probe, -#ifndef DISCOVER_ONLY - .clobber = hfs_clobber, /* NOT hfsplus_clobber ! - HFSX can't be embedded */ - .open = hfsplus_open, - .create = NULL, - .close = hfsplus_close, -#ifndef HFS_EXTRACT_FS - .check = NULL, -#else - .check = hfsplus_extract, -#endif - .copy = NULL, - .resize = hfsplus_resize, - .get_create_constraint = NULL, - .get_resize_constraint = hfsplus_get_resize_constraint, - .get_copy_constraint = NULL, -#else /* DISCOVER_ONLY */ - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL, -#endif /* DISCOVER_ONLY */ -}; - - -static PedFileSystemType hfs_type = { - .next = NULL, - .ops = &hfs_ops, - .name = "hfs", - .block_sizes = HFS_BLOCK_SIZES -}; - -static PedFileSystemType hfsplus_type = { - .next = NULL, - .ops = &hfsplus_ops, - .name = "hfs+", - .block_sizes = HFSP_BLOCK_SIZES -}; - -static PedFileSystemType hfsx_type = { - .next = NULL, - .ops = &hfsx_ops, - .name = "hfsx", - .block_sizes = HFSX_BLOCK_SIZES -}; - -void -ped_file_system_hfs_init () -{ - ped_file_system_type_register (&hfs_type); - ped_file_system_type_register (&hfsplus_type); - ped_file_system_type_register (&hfsx_type); -} - -void -ped_file_system_hfs_done () -{ - ped_file_system_type_unregister (&hfs_type); - ped_file_system_type_unregister (&hfsplus_type); - ped_file_system_type_unregister (&hfsx_type); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.h b/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.h deleted file mode 100644 index 076d355f96..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/hfs.h +++ /dev/null @@ -1,830 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _HFS_H -#define _HFS_H - -/* WARNING : bn is used 2 times in theses macro */ -/* so _never_ use side effect operators when using them */ -#define TST_BLOC_OCCUPATION(tab,bn) \ - (((tab)[(bn)/8]) & (1<<(7-((bn)&7)))) -#define SET_BLOC_OCCUPATION(tab,bn) \ - (((tab)[(bn)/8]) |= (1<<(7-((bn)&7)))) -#define CLR_BLOC_OCCUPATION(tab,bn) \ - (((tab)[(bn)/8]) &= ~(1<<(7-((bn)&7)))) - -/* Maximum number of blocks for the copy buffers */ -#define BLOCK_MAX_BUFF 256 -/* Maximum size of the copy buffers, in bytes */ -#define BYTES_MAX_BUFF 8388608 - -/* Apple Creator Codes follow */ -#define HFSP_IMPL_Shnk 0x53686e6b /* in use */ -#define HFSP_IMPL_Xpnd 0x58706e64 /* reserved */ -#define HFSP_IMPL_Resz 0x5265737a /* reserved */ -#define HFSP_IMPL_PHpx 0x50482b78 /* reserved */ -#define HFSP_IMPL_traP 0x74726150 /* reserved */ -#define HFSP_IMPL_GnuP 0x476e7550 /* reserved */ - -#define HFS_SIGNATURE 0x4244 /* 'BD' */ -#define HFSP_SIGNATURE 0x482B /* 'H+' */ -#define HFSX_SIGNATURE 0x4858 /* 'HX' */ - -#define HFSP_VERSION 4 -#define HFSX_VERSION 5 - -#define HFS_HARD_LOCK 7 -#define HFS_UNMOUNTED 8 -#define HFS_BAD_SPARED 9 -#define HFS_SOFT_LOCK 15 -#define HFSP_NO_CACHE 10 -#define HFSP_INCONSISTENT 11 -#define HFSP_REUSE_CNID 12 -#define HFSP_JOURNALED 13 - -#define HFS_IDX_NODE 0x00 -#define HFS_HDR_NODE 0x01 -#define HFS_MAP_NODE 0x02 -#define HFS_LEAF_NODE 0xFF - -#define HFS_FIRST_REC 0x0E -#define HFS_NSD_HD_REC 0x78 -#define HFS_MAP_REC 0xF8 - -#define HFS_DATA_FORK 0x00 -#define HFS_RES_FORK 0xFF - -#define HFS_CAT_DIR 0x01 -#define HFS_CAT_FILE 0x02 -#define HFS_CAT_DIR_TH 0x03 -#define HFS_CAT_FILE_TH 0x04 - -#define HFSP_ATTR_INLINE 0x10 -#define HFSP_ATTR_FORK 0x20 -#define HFSP_ATTR_EXTENTS 0x30 - -#define HFS_ROOT_PAR_ID 0x01 -#define HFS_ROOT_DIR_ID 0x02 -#define HFS_XTENT_ID 0x03 -#define HFS_CATALOG_ID 0x04 -#define HFS_BAD_BLOCK_ID 0x05 -#define HFSP_ALLOC_ID 0x06 -#define HFSP_STARTUP_ID 0x07 -#define HFSP_ATTRIB_ID 0x08 -#define HFSP_BOGUS_ID 0x0F -#define HFSP_FIRST_AV_ID 0x10 - -#define HFSJ_JOURN_IN_FS 0x00 -#define HFSJ_JOURN_OTHER_DEV 0x01 -#define HFSJ_JOURN_NEED_INIT 0x02 - -#define HFSJ_HEADER_MAGIC 0x4a4e4c78 -#define HFSJ_ENDIAN_MAGIC 0x12345678 - -#define HFSX_CASE_FOLDING 0xCF /* case insensitive HFSX */ -#define HFSX_BINARY_COMPARE 0xBC /* case sensitive HFSX */ - -#define HFS_EXT_NB 3 -#define HFSP_EXT_NB 8 - -/* Define the filenames used by the FS extractor */ -#ifdef HFS_EXTRACT_FS - -#define HFS_MDB_FILENAME "mdb.hfs" -#define HFS_CATALOG_FILENAME "catalog.hfs" -#define HFS_EXTENTS_FILENAME "extents.hfs" -#define HFS_BITMAP_FILENAME "bitmap.hfs" - -#define HFSP_VH_FILENAME "vh.hfsplus" -#define HFSP_CATALOG_FILENAME "catalog.hfsplus" -#define HFSP_EXTENTS_FILENAME "extents.hfsplus" -#define HFSP_BITMAP_FILENAME "bitmap.hfsplus" -#define HFSP_ATTRIB_FILENAME "attributes.hfsplus" -#define HFSP_STARTUP_FILENAME "startup.hfsplus" - -#endif /* HFS_EXTRACT_FS */ - - - -/* ----------------------------------- */ -/* -- HFS DATA STRUCTURES -- */ -/* ----------------------------------- */ - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -/* Extent descriptor */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsExtDescriptor { - uint16_t start_block; - uint16_t block_count; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsExtDescriptor HfsExtDescriptor; -typedef HfsExtDescriptor HfsExtDataRec[HFS_EXT_NB]; - -/* Volume header */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsMasterDirectoryBlock { - uint16_t signature; - uint32_t create_date; - uint32_t modify_date; - uint16_t volume_attributes; - uint16_t files_in_root; - uint16_t volume_bitmap_block; /* in sectors */ - uint16_t next_allocation; - uint16_t total_blocks; - uint32_t block_size; /* in bytes */ - uint32_t def_clump_size; /* in bytes */ - uint16_t start_block; /* in sectors */ - uint32_t next_free_node; - uint16_t free_blocks; - uint8_t name_length; - char name[27]; - uint32_t backup_date; - uint16_t backup_number; - uint32_t write_count; - uint32_t extents_clump; - uint32_t catalog_clump; - uint16_t dirs_in_root; - uint32_t file_count; - uint32_t dir_count; - uint32_t finder_info[8]; - union __attribute__ ((packed)) { - struct __attribute__ ((packed)) { - uint16_t volume_cache_size; /* in blocks */ - uint16_t bitmap_cache_size; /* in blocks */ - uint16_t common_cache_size; /* in blocks */ - } legacy; - struct __attribute__ ((packed)) { - uint16_t signature; - HfsExtDescriptor location; - } embedded; - } old_new; - uint32_t extents_file_size; /* in bytes, block size multiple */ - HfsExtDataRec extents_file_rec; - uint32_t catalog_file_size; /* in bytes, block size multiple */ - HfsExtDataRec catalog_file_rec; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsMasterDirectoryBlock HfsMasterDirectoryBlock; - -/* B*-Tree Node Descriptor */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsNodeDescriptor { - uint32_t next; - uint32_t previous; - int8_t type; - uint8_t height; - uint16_t rec_nb; - uint16_t reserved; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsNodeDescriptor HfsNodeDescriptor; - -/* Header record of a whole B*-Tree */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsHeaderRecord { - uint16_t depth; - uint32_t root_node; - uint32_t leaf_records; - uint32_t first_leaf_node; - uint32_t last_leaf_node; - uint16_t node_size; - uint16_t max_key_len; - uint32_t total_nodes; - uint32_t free_nodes; - int8_t reserved[76]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsHeaderRecord HfsHeaderRecord; - -/* Catalog key for B*-Tree lookup in the catalog file */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsCatalogKey { - uint8_t key_length; /* length of the key without key_length */ - uint8_t reserved; - uint32_t parent_ID; - uint8_t name_length; - char name[31]; /* in fact physicaly 1 upto 31 */ -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsCatalogKey HfsCatalogKey; - -/* Extents overflow key for B*-Tree lookup */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsExtentKey { - uint8_t key_length; /* length of the key without key_length */ - uint8_t type; /* data or ressource fork */ - uint32_t file_ID; - uint16_t start; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsExtentKey HfsExtentKey; - -/* Catalog subdata case directory */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsDir { - uint16_t flags; - uint16_t valence; /* number of files in this directory */ - uint32_t dir_ID; - uint32_t create_date; - uint32_t modify_date; - uint32_t backup_date; - int8_t DInfo[16]; /* used by Finder, handle as reserved */ - int8_t DXInfo[16]; /* used by Finder, handle as reserved */ - uint32_t reserved[4]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsDir HfsDir; - -/* Catalog subdata case file */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsFile { - int8_t flags; - int8_t type; /* should be 0 */ - int8_t FInfo[16]; /* used by Finder, handle as reserved */ - uint32_t file_ID; - uint16_t data_start_block; - uint32_t data_sz_byte; - uint32_t data_sz_block; - uint16_t res_start_block; - uint32_t res_sz_byte; - uint32_t res_sz_block; - uint32_t create_date; - uint32_t modify_date; - uint32_t backup_date; - int8_t FXInfo[16]; /* used by Finder, handle as reserved */ - uint16_t clump_size; - HfsExtDataRec extents_data; - HfsExtDataRec extents_res; - uint32_t reserved; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsFile HfsFile; - -/* Catalog subdata case directory thread */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsDirTh { - uint32_t reserved[2]; - uint32_t parent_ID; - int8_t name_length; - char name[31]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsDirTh HfsDirTh; - -/* Catalog subdata case file thread */ -typedef struct _HfsDirTh HfsFileTh; /* same as directory thread */ - -/* Catalog data */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsCatalog { - int8_t type; - int8_t reserved; - union { - HfsDir dir; - HfsFile file; - HfsDirTh dir_th; - HfsFileTh file_th; - } sel; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsCatalog HfsCatalog; - - - -/* ------------------------------------ */ -/* -- HFS+ DATA STRUCTURES -- */ -/* ------------------------------------ */ - -/* documented since 2004 in tn1150 */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPPerms { - uint32_t owner_ID; - uint32_t group_ID; - uint32_t permissions; - uint32_t special_devices; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPPerms HfsPPerms; - -/* HFS+ extent descriptor*/ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPExtDescriptor { - uint32_t start_block; - uint32_t block_count; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPExtDescriptor HfsPExtDescriptor; -typedef HfsPExtDescriptor HfsPExtDataRec[HFSP_EXT_NB]; - -/* HFS+ fork data structure */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPForkData { - uint64_t logical_size; - uint32_t clump_size; - uint32_t total_blocks; - HfsPExtDataRec extents; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPForkData HfsPForkData; - -/* HFS+ catalog node ID */ -typedef uint32_t HfsPNodeID; - -/* HFS+ file names */ -typedef uint16_t unichar; -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPUniStr255 { - uint16_t length; - unichar unicode[255]; /* 1 upto 255 */ -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPUniStr255 HfsPUniStr255; - -/* HFS+ volume header */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPVolumeHeader { - uint16_t signature; - uint16_t version; - uint32_t attributes; - uint32_t last_mounted_version; - uint32_t journal_info_block; - - uint32_t create_date; - uint32_t modify_date; - uint32_t backup_date; - uint32_t checked_date; - - uint32_t file_count; - uint32_t dir_count; - - uint32_t block_size; - uint32_t total_blocks; - uint32_t free_blocks; - - uint32_t next_allocation; - uint32_t res_clump_size; - uint32_t data_clump_size; - HfsPNodeID next_catalog_ID; - - uint32_t write_count; - uint64_t encodings_bitmap; - - uint8_t finder_info[32]; - - HfsPForkData allocation_file; - HfsPForkData extents_file; - HfsPForkData catalog_file; - HfsPForkData attributes_file; - HfsPForkData startup_file; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPVolumeHeader HfsPVolumeHeader; - -/* HFS+ B-Tree Node Descriptor. Same as HFS btree. */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPNodeDescriptor { - uint32_t next; - uint32_t previous; - int8_t type; - uint8_t height; - uint16_t rec_nb; - uint16_t reserved; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPNodeDescriptor HfsPNodeDescriptor; - -/* Header record of a whole HFS+ B-Tree. */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPHeaderRecord { - uint16_t depth; - uint32_t root_node; - uint32_t leaf_records; - uint32_t first_leaf_node; - uint32_t last_leaf_node; - uint16_t node_size; - uint16_t max_key_len; - uint32_t total_nodes; - uint32_t free_nodes; /* same as hfs btree until here */ - uint16_t reserved1; - - uint32_t clump_size; - uint8_t btree_type; /* must be 0 for HFS+ B-Tree */ - uint8_t key_compare_type; /* hfsx => 0xCF = case folding */ - /* 0xBC = binary compare */ - /* otherwise, reserved */ - uint32_t attributes; - uint32_t reserved3[16]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPHeaderRecord HfsPHeaderRecord; - -/* Catalog key for B-Tree lookup in the HFS+ catalog file */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPCatalogKey { - uint16_t key_length; - HfsPNodeID parent_ID; - HfsPUniStr255 node_name; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPCatalogKey HfsPCatalogKey; - -/* HFS+ catalog subdata case dir */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPDir { - uint16_t flags; - uint32_t valence; - HfsPNodeID dir_ID; - uint32_t create_date; - uint32_t modify_date; - uint32_t attrib_mod_date; - uint32_t access_date; - uint32_t backup_date; - HfsPPerms permissions; - int8_t DInfo[16]; /* used by Finder, handle as reserved */ - int8_t DXInfo[16]; /* used by Finder, handle as reserved */ - uint32_t text_encoding; - uint32_t reserved; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPDir HfsPDir; - -/* HFS+ catalog subdata case file */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPFile { - uint16_t flags; - uint32_t reserved1; - HfsPNodeID file_ID; - uint32_t create_date; - uint32_t modify_date; - uint32_t attrib_mod_date; - uint32_t access_date; - uint32_t backup_date; - HfsPPerms permissions; - int8_t FInfo[16]; /* used by Finder, handle as reserved */ - int8_t FXInfo[16]; /* used by Finder, handle as reserved */ - uint32_t text_encoding; - uint32_t reserved2; - - HfsPForkData data_fork; - HfsPForkData res_fork; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPFile HfsPFile; - -/* HFS+ catalog subdata case thread */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPThread { - int16_t reserved; - HfsPNodeID parent_ID; - HfsPUniStr255 node_name; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPThread HfsPDirTh; -typedef struct _HfsPThread HfsPFileTh; - -/* HFS+ Catalog leaf data */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPCatalog { - int16_t type; - union { - HfsPDir dir; - HfsPFile file; - HfsPDirTh dir_th; - HfsPFileTh file_th; - } sel; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPCatalog HfsPCatalog; - -/* HFS+ extents file key */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPExtentKey { - uint16_t key_length; - uint8_t type; - uint8_t pad; - HfsPNodeID file_ID; - uint32_t start; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPExtentKey HfsPExtentKey; - -/* extent file data is HfsPExtDataRec */ - -/* Fork data attribute file */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPForkDataAttr { - uint32_t record_type; - uint32_t reserved; - union __attribute__ ((packed)) { - HfsPForkData fork; - HfsPExtDataRec extents; - } fork_res; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPForkDataAttr HfsPForkDataAttr; - - -/* ----------- Journal data structures ----------- */ - -/* Info block : stored in a block # defined in the VH */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsJJournalInfoBlock { - uint32_t flags; - uint32_t device_signature[8]; - uint64_t offset; - uint64_t size; - uint32_t reserved[32]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsJJournalInfoBlock HfsJJournalInfoBlock; - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsJJournalHeader { - uint32_t magic; - uint32_t endian; - uint64_t start; - uint64_t end; - uint64_t size; - uint32_t blhdr_size; - uint32_t checksum; - uint32_t jhdr_size; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsJJournalHeader HfsJJournalHeader; - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsJBlockInfo { - uint64_t bnum; /* sector number */ - uint32_t bsize; /* size in bytes */ - uint32_t next; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsJBlockInfo HfsJBlockInfo; - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsJBlockListHeader { - uint16_t max_blocks; /* reserved */ - uint16_t num_blocks; - uint32_t bytes_used; - uint32_t checksum; - uint32_t pad; - HfsJBlockInfo binfo[1]; -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsJBlockListHeader HfsJBlockListHeader; - - -/* ---------------------------------------- */ -/* -- INTERNAL DATA STRUCTURES -- */ -/* ---------------------------------------- */ - -/* Data of an opened HFS file */ -struct _HfsPrivateFile { - PedSector sect_nb; - PedFileSystem* fs; - uint32_t CNID; /* disk order (BE) */ - HfsExtDataRec first; /* disk order (BE) */ - HfsExtDataRec cache; /* disk order (BE) */ - uint16_t start_cache; /* CPU order */ -}; -typedef struct _HfsPrivateFile HfsPrivateFile; - -/* To store bad block list */ -struct _HfsPrivateLinkExtent { - HfsExtDescriptor extent; - struct _HfsPrivateLinkExtent* next; -}; -typedef struct _HfsPrivateLinkExtent HfsPrivateLinkExtent; - -/* HFS Filesystem specific data */ -struct _HfsPrivateFSData { - uint8_t alloc_map[(1<<16) / 8]; - HfsMasterDirectoryBlock* mdb; - HfsPrivateFile* extent_file; - HfsPrivateFile* catalog_file; - HfsPrivateLinkExtent* bad_blocks_xtent_list; - unsigned int bad_blocks_xtent_nb; - char bad_blocks_loaded; -}; -typedef struct _HfsPrivateFSData HfsPrivateFSData; - -/* Generic btree key */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPrivateGenericKey { - uint8_t key_length; - uint8_t key_content[1]; /* we use 1 as a minimum size */ -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPrivateGenericKey HfsPrivateGenericKey; - -/* ----- HFS+ ----- */ - -/* Data of an opened HFS file */ -struct _HfsPPrivateFile { - PedSector sect_nb; - PedFileSystem* fs; - HfsPNodeID CNID; /* disk order (BE) */ - HfsPExtDataRec first; /* disk order (BE) */ - HfsPExtDataRec cache; /* disk order (BE) */ - uint32_t start_cache; /* CPU order */ -}; -typedef struct _HfsPPrivateFile HfsPPrivateFile; - -struct _HfsPPrivateExtent { - PedSector start_sector; - PedSector sector_count; -}; -typedef struct _HfsPPrivateExtent HfsPPrivateExtent; - -/* To store bad block list */ -struct _HfsPPrivateLinkExtent { - HfsPExtDescriptor extent; - struct _HfsPPrivateLinkExtent* next; -}; -typedef struct _HfsPPrivateLinkExtent HfsPPrivateLinkExtent; - -/* HFS+ file system specific data */ -struct _HfsPPrivateFSData { - PedFileSystem* wrapper; /* NULL if hfs+ is not embedded */ - PedGeometry* plus_geom; /* Geometry of HFS+ _volume_ */ - uint8_t* alloc_map; - uint8_t* dirty_alloc_map; - HfsPVolumeHeader* vh; - HfsPPrivateFile* extents_file; - HfsPPrivateFile* catalog_file; - HfsPPrivateFile* attributes_file; - HfsPPrivateFile* allocation_file; - HfsPPrivateLinkExtent* bad_blocks_xtent_list; - uint32_t jib_start_block; - uint32_t jl_start_block; - unsigned int bad_blocks_xtent_nb; - char bad_blocks_loaded; - char free_geom; /* 1 = plus_geom must be freed */ -}; -typedef struct _HfsPPrivateFSData HfsPPrivateFSData; - -/* Generic + btree key */ -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _HfsPPrivateGenericKey { - uint16_t key_length; - uint8_t key_content[1]; /* we use 1 as a minimum size */ -}; -#ifdef __sun -#pragma pack() -#endif -typedef struct _HfsPPrivateGenericKey HfsPPrivateGenericKey; - -/* ---- common ---- */ - -/* node and lead record reference for a BTree search */ -struct _HfsCPrivateLeafRec { - unsigned int node_size; /* in sectors */ - unsigned int node_number; - unsigned int record_pos; - unsigned int record_number; -}; -typedef struct _HfsCPrivateLeafRec HfsCPrivateLeafRec; - -extern uint8_t* hfs_block; -extern uint8_t* hfsp_block; -extern unsigned hfs_block_count; -extern unsigned hfsp_block_count; - -#endif /* _HFS_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/journal.c b/usr/src/lib/libparted/common/libparted/fs/hfs/journal.c deleted file mode 100644 index 083cb598e5..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/journal.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "reloc_plus.h" - -#include "journal.h" - -static int hfsj_vh_replayed = 0; -static int is_le = 0; - -static uint32_t -hfsj_calc_checksum(uint8_t *ptr, int len) -{ - int i; - uint32_t cksum=0; - - for (i=0; i < len; i++, ptr++) { - cksum = (cksum << 8) ^ (cksum + *ptr); - } - - return (~cksum); -} - -int -hfsj_update_jib(PedFileSystem* fs, uint32_t block) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - - priv_data->vh->journal_info_block = PED_CPU_TO_BE32(block); - - if (!hfsplus_update_vh (fs)) - return 0; - - priv_data->jib_start_block = block; - return 1; -} - -int -hfsj_update_jl(PedFileSystem* fs, uint32_t block) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedSector sector; - uint64_t offset; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsJJournalInfoBlock* jib; - int binsect; - - binsect = HFS_32_TO_CPU(priv_data->vh->block_size, is_le) / PED_SECTOR_SIZE_DEFAULT; - sector = (PedSector) priv_data->jib_start_block * binsect; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jib = (HfsJJournalInfoBlock*) buf; - - offset = (uint64_t)block * PED_SECTOR_SIZE_DEFAULT * binsect; - jib->offset = HFS_CPU_TO_64(offset, is_le); - - if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) - || !ped_geometry_sync(priv_data->plus_geom)) - return 0; - - priv_data->jl_start_block = block; - return 1; -} - -/* Return the sector in the journal that is after the area read */ -/* or 0 on error */ -static PedSector -hfsj_journal_read(PedGeometry* geom, HfsJJournalHeader* jh, - PedSector journ_sect, PedSector journ_length, - PedSector read_sect, unsigned int nb_sect, - void* buf) -{ - int r; - - while (nb_sect--) { - r = ped_geometry_read(geom, buf, journ_sect + read_sect, 1); - if (!r) return 0; - - buf = ((uint8_t*)buf) + PED_SECTOR_SIZE_DEFAULT; - read_sect++; - if (read_sect == journ_length) - read_sect = 1; /* skip journal header - which is asserted to be - 1 sector long */ - } - - return read_sect; -} - -static int -hfsj_replay_transaction(PedFileSystem* fs, HfsJJournalHeader* jh, - PedSector jsector, PedSector jlength) -{ - PedSector start, sector; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsJBlockListHeader* blhdr; - uint8_t* block; - unsigned int blhdr_nbsect; - int i, r; - uint32_t cksum, size; - - blhdr_nbsect = HFS_32_TO_CPU(jh->blhdr_size, is_le) / PED_SECTOR_SIZE_DEFAULT; - blhdr = (HfsJBlockListHeader*) - ped_malloc (blhdr_nbsect * PED_SECTOR_SIZE_DEFAULT); - if (!blhdr) return 0; - - start = HFS_64_TO_CPU(jh->start, is_le) / PED_SECTOR_SIZE_DEFAULT; - do { - start = hfsj_journal_read(priv_data->plus_geom, jh, jsector, - jlength, start, blhdr_nbsect, blhdr); - if (!start) goto err_replay; - - cksum = HFS_32_TO_CPU(blhdr->checksum, is_le); - blhdr->checksum = 0; - if (cksum!=hfsj_calc_checksum((uint8_t*)blhdr, sizeof(*blhdr))){ - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad block list header checksum.")); - goto err_replay; - } - blhdr->checksum = HFS_CPU_TO_32(cksum, is_le); - - for (i=1; i < HFS_16_TO_CPU(blhdr->num_blocks, is_le); ++i) { - size = HFS_32_TO_CPU(blhdr->binfo[i].bsize, is_le); - sector = HFS_64_TO_CPU(blhdr->binfo[i].bnum, is_le); - if (!size) continue; - if (size % PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Invalid size of a transaction " - "block while replaying the journal " - "(%i bytes)."), - size); - goto err_replay; - } - block = (uint8_t*) ped_malloc(size); - if (!block) goto err_replay; - start = hfsj_journal_read(priv_data->plus_geom, jh, - jsector, jlength, start, - size / PED_SECTOR_SIZE_DEFAULT, - block); - if (!start) { - ped_free (block); - goto err_replay; - } - /* the sector stored in the journal seems to be - relative to the begin of the block device which - contains the hfs+ journaled volume */ - if (sector != ~0LL) - r = ped_geometry_write (fs->geom, block, sector, - size / PED_SECTOR_SIZE_DEFAULT); - else - r = 1; - ped_free (block); - /* check if wrapper mdb or vh with no wrapper has - changed */ - if ( (sector != ~0LL) - && (2 >= sector) - && (2 < sector + size / PED_SECTOR_SIZE_DEFAULT) ) - hfsj_vh_replayed = 1; - /* check if vh of embedded hfs+ has changed */ - if ( (sector != ~0LL) - && (priv_data->plus_geom != fs->geom) - && (sector - + fs->geom->start - - priv_data->plus_geom->start <= 2) - && (sector - + size / PED_SECTOR_SIZE_DEFAULT - + fs->geom->start - - priv_data->plus_geom->start > 2) ) - hfsj_vh_replayed = 1; - if (!r) goto err_replay; - } - } while (blhdr->binfo[0].next); - - jh->start = HFS_CPU_TO_64(start * PED_SECTOR_SIZE_DEFAULT, is_le); - - ped_free (blhdr); - return (ped_geometry_sync (fs->geom)); - -err_replay: - ped_free (blhdr); - return 0; -} - -/* 0 => Failure, don't continue to open ! */ -/* 1 => Success, the journal has been completly replayed, or don't need to */ -int -hfsj_replay_journal(PedFileSystem* fs) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedSector sector, length; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsJJournalInfoBlock* jib; - HfsJJournalHeader* jh; - int binsect; - uint32_t cksum; - - binsect = PED_BE32_TO_CPU(priv_data->vh->block_size) / PED_SECTOR_SIZE_DEFAULT; - priv_data->jib_start_block = - PED_BE32_TO_CPU(priv_data->vh->journal_info_block); - sector = (PedSector) priv_data->jib_start_block * binsect; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jib = (HfsJJournalInfoBlock*) buf; - - if ( (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) - && !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { - priv_data->jl_start_block = HFS_64_TO_CPU(jib->offset, is_le) - / ( PED_SECTOR_SIZE_DEFAULT * binsect ); - } - - if (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_NEED_INIT)) - return 1; - - if ( !(jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_IN_FS)) - || (jib->flags & PED_CPU_TO_BE32(1 << HFSJ_JOURN_OTHER_DEV)) ) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Journal stored outside of the volume are " - "not supported. Try to desactivate the " - "journal and run Parted again.")); - return 0; - } - - if ( (PED_BE64_TO_CPU(jib->offset) % PED_SECTOR_SIZE_DEFAULT) - || (PED_BE64_TO_CPU(jib->size) % PED_SECTOR_SIZE_DEFAULT) ) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Journal offset or size is not multiple of " - "the sector size.")); - return 0; - } - - sector = PED_BE64_TO_CPU(jib->offset) / PED_SECTOR_SIZE_DEFAULT; - length = PED_BE64_TO_CPU(jib->size) / PED_SECTOR_SIZE_DEFAULT; - - jib = NULL; - if (!ped_geometry_read(priv_data->plus_geom, buf, sector, 1)) - return 0; - jh = (HfsJJournalHeader*) buf; - - if (jh->endian == PED_LE32_TO_CPU(HFSJ_ENDIAN_MAGIC)) - is_le = 1; - - if ( (jh->magic != HFS_32_TO_CPU(HFSJ_HEADER_MAGIC, is_le)) - || (jh->endian != HFS_32_TO_CPU(HFSJ_ENDIAN_MAGIC, is_le)) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Incorrect magic values in the journal header.")); - return 0; - } - - if ( (HFS_64_TO_CPU(jh->size, is_le)%PED_SECTOR_SIZE_DEFAULT) - || (HFS_64_TO_CPU(jh->size, is_le)/PED_SECTOR_SIZE_DEFAULT - != (uint64_t)length) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Journal size mismatch between journal info block " - "and journal header.")); - return 0; - } - - if ( (HFS_64_TO_CPU(jh->start, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_64_TO_CPU(jh->end, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_32_TO_CPU(jh->blhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) - || (HFS_32_TO_CPU(jh->jhdr_size, is_le) % PED_SECTOR_SIZE_DEFAULT) ) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Some header fields are not multiple of the sector " - "size.")); - return 0; - } - - if (HFS_32_TO_CPU(jh->jhdr_size, is_le) != PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The sector size stored in the journal is not 512 " - "bytes. Parted only supports 512 bytes length " - "sectors.")); - return 0; - } - - cksum = HFS_32_TO_CPU(jh->checksum, is_le); - jh->checksum = 0; - if (cksum != hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad journal checksum.")); - return 0; - } - jh->checksum = HFS_CPU_TO_32(cksum, is_le); - - /* The 2 following test are in the XNU Darwin source code */ - /* so I assume they're needed */ - if (jh->start == jh->size) - jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); - if (jh->end == jh->size) - jh->start = HFS_CPU_TO_64(PED_SECTOR_SIZE_DEFAULT, is_le); - - if (jh->start == jh->end) - return 1; - - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, - _("The journal is not empty. Parted must replay the " - "transactions before opening the file system. This will " - "modify the file system.")) - != PED_EXCEPTION_FIX) - return 0; - - while (jh->start != jh->end) { - /* Replay one complete transaction */ - if (!hfsj_replay_transaction(fs, jh, sector, length)) - return 0; - - /* Recalculate cksum of the journal header */ - jh->checksum = 0; /* need to be 0 while calculating the cksum */ - cksum = hfsj_calc_checksum((uint8_t*)jh, sizeof(*jh)); - jh->checksum = HFS_CPU_TO_32(cksum, is_le); - - /* Update the Journal Header */ - if (!ped_geometry_write(priv_data->plus_geom, buf, sector, 1) - || !ped_geometry_sync(priv_data->plus_geom)) - return 0; - } - - if (hfsj_vh_replayed) { - /* probe could have reported incorrect info ! */ - /* is there a way to ask parted to quit ? */ - ped_exception_throw( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_OK, - _("The volume header or the master directory block has " - "changed while replaying the journal. You should " - "restart Parted.")); - return 0; - } - - return 1; -} - -#endif /* DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/journal.h b/usr/src/lib/libparted/common/libparted/fs/hfs/journal.h deleted file mode 100644 index 6bab396a2b..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/journal.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _JOURNAL_H -#define _JOURNAL_H - -#include -#include -#include - -#include "hfs.h" - -int -hfsj_replay_journal(PedFileSystem* fs); - -int -hfsj_update_jib(PedFileSystem* fs, uint32_t block); - -int -hfsj_update_jl(PedFileSystem* fs, uint32_t block); - -#define HFS_16_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint16_t)PED_LE16_TO_CPU(x) : (uint16_t)PED_BE16_TO_CPU(x)) -#define HFS_32_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint32_t)PED_LE32_TO_CPU(x) : (uint32_t)PED_BE32_TO_CPU(x)) -#define HFS_64_TO_CPU(x, is_little_endian) ((is_little_endian) ? (uint64_t)PED_LE64_TO_CPU(x) : (uint64_t)PED_BE64_TO_CPU(x)) -#define HFS_CPU_TO_16(x, is_little_endian) ((is_little_endian) ? (uint16_t)PED_CPU_TO_LE16(x) : (uint16_t)PED_CPU_TO_BE16(x)) -#define HFS_CPU_TO_32(x, is_little_endian) ((is_little_endian) ? (uint32_t)PED_CPU_TO_LE32(x) : (uint32_t)PED_CPU_TO_BE32(x)) -#define HFS_CPU_TO_64(x, is_little_endian) ((is_little_endian) ? (uint64_t)PED_CPU_TO_LE64(x) : (uint64_t)PED_CPU_TO_BE64(x)) - -#endif /* _JOURNAL_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/probe.c b/usr/src/lib/libparted/common/libparted/fs/hfs/probe.c deleted file mode 100644 index 4da4594f69..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/probe.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" - -#include "probe.h" - -int -hfsc_can_use_geom (PedGeometry* geom) -{ - PedDevice* dev; - - dev = geom->dev; - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size != PED_SECTOR_SIZE_DEFAULT) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Parted can't use HFS file systems on disks " - "with a sector size not equal to %d bytes."), - (int)PED_SECTOR_SIZE_DEFAULT ); - return 0; - } - - return 1; -} - -/* Probe an HFS volume, detecting it even if -it is in fact a wrapper to an HFS+ volume */ -/* Used by hfsplus_probe and hfs_probe */ -PedGeometry* -hfs_and_wrapper_probe (PedGeometry* geom) -{ - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - HfsMasterDirectoryBlock *mdb; - PedGeometry* geom_ret; - PedSector search, max; - - PED_ASSERT (geom != NULL, return NULL); - PED_ASSERT (hfsc_can_use_geom (geom), return NULL); - - mdb = (HfsMasterDirectoryBlock *) buf; - - /* is 5 an intelligent value ? */ - if ((geom->length < 5) - || (!ped_geometry_read (geom, buf, 2, 1)) - || (mdb->signature != PED_CPU_TO_BE16 (HFS_SIGNATURE)) ) - return NULL; - - search = ((PedSector) PED_BE16_TO_CPU (mdb->start_block) - + ((PedSector) PED_BE16_TO_CPU (mdb->total_blocks) - * (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT ))); - max = search + (PED_BE32_TO_CPU (mdb->block_size) / PED_SECTOR_SIZE_DEFAULT); - if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, search + 2))) - return NULL; - - for (; search < max; search++) { - if (!ped_geometry_set (geom_ret, geom_ret->start, search + 2) - || !ped_geometry_read (geom_ret, buf, search, 1)) - break; - if (mdb->signature == PED_CPU_TO_BE16 (HFS_SIGNATURE)) - return geom_ret; - } - - ped_geometry_destroy (geom_ret); - return NULL; -} - -PedGeometry* -hfsplus_probe (PedGeometry* geom) -{ - PedGeometry* geom_ret; - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - - PED_ASSERT (geom != NULL, return NULL); - - if (!hfsc_can_use_geom (geom)) - return NULL; - - if ((geom_ret = hfs_and_wrapper_probe(geom))) { - /* HFS+ is embedded in an HFS volume ? */ - HfsMasterDirectoryBlock *mdb; - mdb = (HfsMasterDirectoryBlock *) buf; - - if (!ped_geometry_read (geom, buf, 2, 1) - || (mdb->old_new.embedded.signature - != PED_CPU_TO_BE16 (HFSP_SIGNATURE))) { - ped_geometry_destroy (geom_ret); - return NULL; - } else - return geom_ret; - } else { - /* This is a standalone HFS+ volume ? */ - PedSector search, max; - HfsPVolumeHeader *vh; - vh = (HfsPVolumeHeader *) buf; - - if ((geom->length < 5) - || !ped_geometry_read (geom, buf, 2, 1) - || (vh->signature != PED_CPU_TO_BE16 (HFSP_SIGNATURE))) - return NULL; - - /* Correct range is indeed [ blocks*sz-2;(blocs+1)*sz-2 ( */ - /* But previous versions of my implementation used to */ - /* assume range is [(blocks-1)*sz-1;(blocks*sz) ( */ - /* (blocks-1)*sz-1 has to be scanned last, because */ - /* it can belong to a regular file */ - max = ((PedSector) PED_BE32_TO_CPU (vh->total_blocks) + 1) - * ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ) - - 2; - search = max - 2 * ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ) + 2; - if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, - search + 2))) - return NULL; - - for (; search < max; search++) { - if (!ped_geometry_set (geom_ret, geom_ret->start, - search + 2) - || !ped_geometry_read (geom_ret, buf, search, 1)) - break; - if (vh->signature == PED_CPU_TO_BE16 (HFSP_SIGNATURE)) - return geom_ret; - } - search = ((PedSector) PED_BE32_TO_CPU (vh->total_blocks) - 1) - * ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ) - - 1; - if (!ped_geometry_set (geom_ret, geom_ret->start, - search + 2) - || !ped_geometry_read (geom_ret, buf, search, 1) - || vh->signature != PED_CPU_TO_BE16 (HFSP_SIGNATURE)) { - ped_geometry_destroy (geom_ret); - return NULL; - } else - return geom_ret; - } -} - -PedGeometry* -hfs_probe (PedGeometry* geom) -{ - PedGeometry* geom_base; - PedGeometry* geom_plus = NULL; - - PED_ASSERT (geom != NULL, return NULL); - - if (!hfsc_can_use_geom (geom)) - return NULL; - - if ((geom_base = hfs_and_wrapper_probe(geom)) - && (!(geom_plus = hfsplus_probe(geom_base)))) - return geom_base; - else { - if (geom_base) ped_geometry_destroy (geom_base); - if (geom_plus) ped_geometry_destroy (geom_plus); - return NULL; - } -} - -PedGeometry* -hfsx_probe (PedGeometry* geom) -{ - PedGeometry* geom_ret; - uint8_t buf[PED_SECTOR_SIZE_DEFAULT]; - PedSector search, max; - HfsPVolumeHeader *vh = (HfsPVolumeHeader *) buf; - - PED_ASSERT (geom != NULL, return NULL); - - if (!hfsc_can_use_geom (geom)) - return NULL; - - if ((geom->length < 5) - || !ped_geometry_read (geom, buf, 2, 1) - || (vh->signature != PED_CPU_TO_BE16 (HFSX_SIGNATURE))) - return NULL; - - /* unlike the hfs+ code, which should be kept compatible - with my old previous implementations, we only care here - about legal alternate VH positions, like TN1150 describes them */ - max = ((PedSector) PED_BE32_TO_CPU (vh->total_blocks) + 1) - * ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ) - - 2; - search = max - ( PED_BE32_TO_CPU (vh->block_size) / PED_SECTOR_SIZE_DEFAULT ); - if (!(geom_ret = ped_geometry_new (geom->dev, geom->start, - search + 2))) - return NULL; - for (; search < max; search++) { - if (!ped_geometry_set (geom_ret, geom_ret->start, - search + 2) - || !ped_geometry_read (geom_ret, buf, search, 1)) - break; - if (vh->signature == PED_CPU_TO_BE16 (HFSX_SIGNATURE)) - return geom_ret; - } - - ped_geometry_destroy (geom_ret); - return NULL; -} diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/probe.h b/usr/src/lib/libparted/common/libparted/fs/hfs/probe.h deleted file mode 100644 index f508de356e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/probe.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _PROBE_H -#define _PROBE_H - -#include -#include -#include - -#include "hfs.h" - -int -hfsc_can_use_geom (PedGeometry* geom); - -PedGeometry* -hfs_and_wrapper_probe (PedGeometry* geom); - -PedGeometry* -hfsplus_probe (PedGeometry* geom); - -PedGeometry* -hfs_probe (PedGeometry* geom); - -PedGeometry* -hfsx_probe (PedGeometry* geom); - -#endif /* _PROBE_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.c b/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.c deleted file mode 100644 index 3c8911563f..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.c +++ /dev/null @@ -1,670 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file.h" -#include "advfs.h" -#include "cache.h" - -#include "reloc.h" - -/* This function moves data of size blocks starting - at block *ptr_fblock to block *ptr_to_fblock */ -/* return new start or -1 on failure */ -static int -hfs_effect_move_extent (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, unsigned int size) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int i, ok = 0; - unsigned int next_to_fblock; - unsigned int start, stop; - - PED_ASSERT (hfs_block != NULL, return -1); - PED_ASSERT (*ptr_to_fblock <= *ptr_fblock, return -1); - /* quiet gcc */ - next_to_fblock = start = stop = 0; - -/* - Try to fit the extent AT or _BEFORE_ the wanted place, - or then in the gap between dest and source. - If failed try to fit the extent after source, for 2 pass relocation - The extent is always copied in a non overlapping way -*/ - - /* Backward search */ - /* 1 pass relocation AT or BEFORE *ptr_to_fblock */ - if (*ptr_to_fblock != *ptr_fblock) { - start = stop = *ptr_fblock < *ptr_to_fblock+size ? - *ptr_fblock : *ptr_to_fblock+size; - while (start && stop-start != size) { - --start; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,start)) - stop = start; - } - ok = (stop-start == size); - } - - /* Forward search */ - /* 1 pass relocation in the gap merged with 2 pass reloc after source */ - if (!ok && *ptr_to_fblock != *ptr_fblock) { - start = stop = *ptr_to_fblock+1; - while (stop < PED_BE16_TO_CPU(priv_data->mdb->total_blocks) - && stop-start != size) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,stop)) - start = stop + 1; - ++stop; - } - ok = (stop-start == size); - } - - /* new non overlapping room has been found ? */ - if (ok) { - /* enough room */ - unsigned int j; - unsigned int start_block = - PED_BE16_TO_CPU (priv_data->mdb->start_block ); - unsigned int block_sz = - (PED_BE32_TO_CPU (priv_data->mdb->block_size) - / PED_SECTOR_SIZE_DEFAULT); - - if (stop > *ptr_to_fblock && stop <= *ptr_fblock) - /* Fit in the gap */ - next_to_fblock = stop; - else - /* Before or after the gap */ - next_to_fblock = *ptr_to_fblock; - - /* move blocks */ - for (i = 0; i < size; /*i+=j*/) { - PedSector abs_sector; - unsigned int ai; - - j = size - i; j = (j < hfs_block_count) ? - j : hfs_block_count ; - - abs_sector = start_block - + (PedSector) (*ptr_fblock + i) * block_sz; - if (!ped_geometry_read (fs->geom, hfs_block, abs_sector, - block_sz * j)) - return -1; - - abs_sector = start_block - + (PedSector) (start + i) * block_sz; - if (!ped_geometry_write (fs->geom,hfs_block,abs_sector, - block_sz * j)) - return -1; - - for (ai = i+j; i < ai; i++) { - /* free source block */ - CLR_BLOC_OCCUPATION(priv_data->alloc_map, - *ptr_fblock + i); - - /* set dest block */ - SET_BLOC_OCCUPATION(priv_data->alloc_map, - start + i); - } - } - if (!ped_geometry_sync_fast (fs->geom)) - return -1; - - *ptr_fblock += size; - *ptr_to_fblock = next_to_fblock; - } else { - if (*ptr_fblock != *ptr_to_fblock) - /* not enough room, but try to continue */ - ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("An extent has not been relocated.")); - start = *ptr_fblock; - *ptr_fblock = *ptr_to_fblock = start + size; - } - - return start; -} - -/* Update MDB */ -/* Return 0 if an error occurred */ -/* Return 1 if everything ok */ -int -hfs_update_mdb (PedFileSystem *fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - - if (!ped_geometry_read (fs->geom, node, 2, 1)) - return 0; - memcpy (node, priv_data->mdb, sizeof (HfsMasterDirectoryBlock)); - if ( !ped_geometry_write (fs->geom, node, 2, 1) - || !ped_geometry_write (fs->geom, node, fs->geom->length - 2, 1) - || !ped_geometry_sync_fast (fs->geom)) - return 0; - return 1; -} - -/* Generic relocator */ -/* replace previous hfs_do_move_* */ -static int -hfs_do_move (PedFileSystem* fs, unsigned int *ptr_src, - unsigned int *ptr_dest, HfsCPrivateCache* cache, - HfsCPrivateExtent* ref) -{ - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsPrivateFile* file; - HfsExtDescriptor* extent; - HfsCPrivateExtent* move; - int new_start; - - new_start = hfs_effect_move_extent (fs, ptr_src, ptr_dest, - ref->ext_length); - if (new_start == -1) return -1; - - if (ref->ext_start != (unsigned) new_start) { - /* Load, modify & save */ - switch (ref->where) { - /******** MDB *********/ - case CR_PRIM_CAT : - priv_data->catalog_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - goto CR_PRIM; - case CR_PRIM_EXT : - priv_data->extent_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - CR_PRIM : - extent = ( HfsExtDescriptor* ) - ( (uint8_t*)priv_data->mdb + ref->ref_offset ); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - if (!hfs_update_mdb(fs)) return -1; - break; - - /********* BTREE *******/ - case CR_BTREE_EXT_CAT : - if (priv_data->catalog_file - ->cache[ref->ref_index].start_block - == PED_CPU_TO_BE16(ref->ext_start)) - priv_data->catalog_file - ->cache[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - case CR_BTREE_EXT_0 : - file = priv_data->extent_file; - goto CR_BTREE; - case CR_BTREE_CAT : - file = priv_data->catalog_file; - CR_BTREE: - PED_ASSERT(ref->sect_by_block == 1 - && ref->ref_offset < PED_SECTOR_SIZE_DEFAULT, - return -1); - if (!hfs_file_read_sector(file, node, ref->ref_block)) - return -1; - extent = ( HfsExtDescriptor* ) (node + ref->ref_offset); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE16(new_start); - if (!hfs_file_write_sector(file, node, ref->ref_block) - || !ped_geometry_sync_fast (fs->geom)) - return -1; - break; - - /********** BUG ********/ - default : - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("A reference to an extent comes from a place " - "it should not. You should check the file " - "system!")); - return -1; - break; - } - - /* Update the cache */ - move = hfsc_cache_move_extent(cache, ref->ext_start, new_start); - if (!move) return -1; /* "cleanly" fail */ - PED_ASSERT(move == ref, return -1); /* generate a bug */ - } - - return new_start; -} - -/* 0 error, 1 ok */ -static int -hfs_save_allocation(PedFileSystem* fs) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - unsigned int map_sectors; - - map_sectors = ( PED_BE16_TO_CPU (priv_data->mdb->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) - / (PED_SECTOR_SIZE_DEFAULT * 8); - return ( ped_geometry_write (fs->geom, priv_data->alloc_map, - PED_BE16_TO_CPU (priv_data->mdb->volume_bitmap_block), - map_sectors) ); -} - -/* This function moves an extent starting at block fblock to block to_fblock - if there's enough room */ -/* Return 1 if everything was fine */ -/* Return -1 if an error occurred */ -/* Return 0 if no extent was found */ -/* Generic search thanks to the file system cache */ -static int -hfs_move_extent_starting_at (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, - HfsCPrivateCache* cache) -{ - HfsCPrivateExtent* ref; - unsigned int old_start, new_start; - - /* Reference search powered by the cache... */ - /* This is the optimisation secret :) */ - ref = hfsc_cache_search_extent(cache, *ptr_fblock); - if (!ref) return 0; /* not found */ - - old_start = *ptr_fblock; - new_start = hfs_do_move(fs, ptr_fblock, ptr_to_fblock, cache, ref); - if (new_start == (unsigned int) -1) return -1; - if (new_start > old_start) { /* detect 2 pass reloc */ - new_start = hfs_do_move(fs,&new_start,ptr_to_fblock,cache,ref); - if (new_start == (unsigned int) -1 || new_start > old_start) - return -1; - } - - /* allocation bitmap save is not atomic with data relocation */ - /* so we only do it a few times, and without syncing */ - /* The unmounted bit protect us anyway */ - hfs_save_allocation(fs); - return 1; -} - -static int -hfs_cache_from_mdb(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsExtDescriptor* extent; - unsigned int j; - - extent = priv_data->mdb->extents_file_rec; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - 0, /* unused for mdb */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->mdb), - 1, /* load/save only 1 sector */ - CR_PRIM_EXT, - j ) - ) - return 0; - } - - extent = priv_data->mdb->catalog_file_rec; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - 0, - ((uint8_t*)extent) - ((uint8_t*)priv_data->mdb), - 1, - CR_PRIM_CAT, - j ) - ) - return 0; - } - - return 1; -} - -static int -hfs_cache_from_catalog(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsCatalogKey* catalog_key; - HfsCatalog* catalog_data; - HfsExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j; - - if (!priv_data->catalog_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS volume has no catalog file. " - "This is very unusual!")); - return 1; - } - - if (!hfs_file_read_sector (priv_data->catalog_file, node, 0)) - return 0; - header = (HfsHeaderRecord*)(node + PED_BE16_TO_CPU(*((uint16_t*) - (node+(PED_SECTOR_SIZE_DEFAULT-2))))); - - for (leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - leaf_node; - leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfs_file_read_sector (priv_data->catalog_file, - node, leaf_node)) - return 0; - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; ++i) { - /* undocumented alignement */ - unsigned int skip; - catalog_key = (HfsCatalogKey*) (node + PED_BE16_TO_CPU( - *((uint16_t*)(node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - skip = (1 + catalog_key->key_length + 1) & ~1; - catalog_data = (HfsCatalog*)( ((uint8_t*)catalog_key) - + skip ); - /* check for obvious error in FS */ - if (((uint8_t*)catalog_key - node < HFS_FIRST_REC) - || ((uint8_t*)catalog_data - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - - if (catalog_data->type != HFS_CAT_FILE) continue; - - extent = catalog_data->sel.file.extents_data; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - CR_BTREE_CAT, - j ) - ) - return 0; - } - - extent = catalog_data->sel.file.extents_res; - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - CR_BTREE_CAT, - j ) - ) - return 0; - } - } - } - - return 1; -} - -static int -hfs_cache_from_extent(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - HfsHeaderRecord* header; - HfsNodeDescriptor* desc = (HfsNodeDescriptor*) node; - HfsExtentKey* extent_key; - HfsExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j; - - if (!priv_data->extent_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS volume has no extents overflow " - "file. This is quite unusual!")); - return 1; - } - - if (!hfs_file_read_sector (priv_data->extent_file, node, 0)) - return 0; - header = ((HfsHeaderRecord*) (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT-2)))))); - - for (leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - leaf_node; - leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfs_file_read_sector (priv_data->extent_file, node, - leaf_node)) - return 0; - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; i++) { - uint8_t where; - extent_key = (HfsExtentKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(PED_SECTOR_SIZE_DEFAULT - 2*i))))); - /* size is cst */ - extent = (HfsExtDescriptor*)(((uint8_t*)extent_key) - + sizeof (HfsExtentKey)); - /* check for obvious error in FS */ - if (((uint8_t*)extent_key - node < HFS_FIRST_REC) - || ((uint8_t*)extent - node - >= PED_SECTOR_SIZE_DEFAULT - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - return 0; - } - - switch (extent_key->file_ID) { - case PED_CPU_TO_BE32 (HFS_XTENT_ID) : - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The extents overflow file should not" - " contain its own extents! You " - "should check the file system.")) - != PED_EXCEPTION_IGNORE) - return 0; - where = CR_BTREE_EXT_EXT; - break; - case PED_CPU_TO_BE32 (HFS_CATALOG_ID) : - where = CR_BTREE_EXT_CAT; - break; - default : - where = CR_BTREE_EXT_0; - break; - } - - for (j = 0; j < HFS_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE16_TO_CPU(extent[j].start_block), - PED_BE16_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - 1, /* hfs => btree block = 512 b */ - where, - j ) - ) - return 0; - } - } - } - - return 1; -} - -/* This function cache every extents start and length stored in any - fs structure into the adt defined in cache.[ch] - Returns NULL on failure */ -static HfsCPrivateCache* -hfs_cache_extents(PedFileSystem *fs, PedTimer* timer) -{ - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsCPrivateCache* ret; - unsigned int file_number, block_number; - - file_number = PED_BE32_TO_CPU(priv_data->mdb->file_count); - block_number = PED_BE16_TO_CPU(priv_data->mdb->total_blocks); - ret = hfsc_new_cache(block_number, file_number); - if (!ret) return NULL; - - if (!hfs_cache_from_mdb(ret, fs, timer) || - !hfs_cache_from_catalog(ret, fs, timer) || - !hfs_cache_from_extent(ret, fs, timer)) { - ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not cache the file system in memory.")); - hfsc_delete_cache(ret); - return NULL; - } - - return ret; -} - -/* This function moves file's data to compact used and free space, - starting at fblock block */ -/* return 0 on error */ -int -hfs_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free) -{ - PedSector bytes_buff; - HfsPrivateFSData* priv_data = (HfsPrivateFSData*) - fs->type_specific; - HfsMasterDirectoryBlock* mdb = priv_data->mdb; - HfsCPrivateCache* cache; - unsigned int to_fblock = fblock; - unsigned int start = fblock; - unsigned int divisor = PED_BE16_TO_CPU (mdb->total_blocks) - + 1 - start - to_free; - int ret; - - PED_ASSERT (!hfs_block, return 0); - - cache = hfs_cache_extents (fs, timer); - if (!cache) - return 0; - - /* Calculate the size of the copy buffer : - * Takes BLOCK_MAX_BUFF HFS blocks, but if > BYTES_MAX_BUFF - * takes the maximum number of HFS blocks so that the buffer - * will remain smaller than or equal to BYTES_MAX_BUFF, with - * a minimum of 1 HFS block */ - bytes_buff = PED_BE32_TO_CPU (priv_data->mdb->block_size) - * (PedSector) BLOCK_MAX_BUFF; - if (bytes_buff > BYTES_MAX_BUFF) { - hfs_block_count = BYTES_MAX_BUFF - / PED_BE32_TO_CPU (priv_data->mdb->block_size); - if (!hfs_block_count) - hfs_block_count = 1; - bytes_buff = (PedSector) hfs_block_count - * PED_BE32_TO_CPU (priv_data->mdb->block_size); - } else - hfs_block_count = BLOCK_MAX_BUFF; - - /* If the cache code requests more space, give it to him */ - if (bytes_buff < hfsc_cache_needed_buffer (cache)) - bytes_buff = hfsc_cache_needed_buffer (cache); - - hfs_block = (uint8_t*) ped_malloc (bytes_buff); - if (!hfs_block) - goto error_cache; - - if (!hfs_read_bad_blocks (fs)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad blocks list could not be loaded.")); - goto error_alloc; - } - - while (fblock < PED_BE16_TO_CPU (mdb->total_blocks)) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,fblock) - && (!hfs_is_bad_block (fs, fblock))) { - if (!(ret = hfs_move_extent_starting_at (fs, &fblock, - &to_fblock, cache))) - to_fblock = ++fblock; - else if (ret == -1) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("An error occurred during extent " - "relocation.")); - goto error_alloc; - } - } else { - fblock++; - } - - ped_timer_update(timer, (float)(to_fblock - start)/divisor); - } - - ped_free (hfs_block); hfs_block = NULL; hfs_block_count = 0; - hfsc_delete_cache (cache); - return 1; - -error_alloc: - ped_free (hfs_block); hfs_block = NULL; hfs_block_count = 0; -error_cache: - hfsc_delete_cache (cache); - return 0; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.h b/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.h deleted file mode 100644 index 1d7add2a05..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _RELOC_H -#define _RELOC_H - -#include -#include -#include - -#include "hfs.h" - -int -hfs_update_mdb (PedFileSystem *fs); - -int -hfs_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free); - -#endif /* _RELOC_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.c b/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.c deleted file mode 100644 index ca2a59a1e1..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.c +++ /dev/null @@ -1,945 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef DISCOVER_ONLY - -#include - -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include "hfs.h" -#include "file_plus.h" -#include "advfs_plus.h" -#include "cache.h" -#include "journal.h" - -#include "reloc_plus.h" - -/* This function moves data of size blocks starting at block *ptr_fblock - to block *ptr_to_fblock */ -/* return new start or -1 on failure */ -/* -1 is ok because there can only be 2^32-1 blocks, so the max possible - last one is 2^32-2 (and anyway it contains Alternate VH), so - -1 (== 2^32-1[2^32]) never represent a valid block */ -static int -hfsplus_effect_move_extent (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, unsigned int size) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - unsigned int i, ok = 0; - unsigned int next_to_fblock; - unsigned int start, stop; - - PED_ASSERT (hfsp_block != NULL, return -1); - PED_ASSERT (*ptr_to_fblock <= *ptr_fblock, return -1); - /* quiet GCC */ - next_to_fblock = start = stop = 0; - -/* - Try to fit the extent AT or _BEFORE_ the wanted place, - or then in the gap between dest and source. - If failed try to fit the extent after source, for 2 pass relocation - The extent is always copied in a non overlapping way -*/ - - /* Backward search */ - /* 1 pass relocation AT or BEFORE *ptr_to_fblock */ - if (*ptr_to_fblock != *ptr_fblock) { - start = stop = *ptr_fblock < *ptr_to_fblock+size ? - *ptr_fblock : *ptr_to_fblock+size; - while (start && stop-start != size) { - --start; - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,start)) - stop = start; - } - ok = (stop-start == size); - } - - /* Forward search */ - /* 1 pass relocation in the gap merged with 2 pass reloc after source */ - if (!ok && *ptr_to_fblock != *ptr_fblock) { - start = stop = *ptr_to_fblock+1; - while (stop < PED_BE32_TO_CPU(priv_data->vh->total_blocks) - && stop-start != size) { - if (TST_BLOC_OCCUPATION(priv_data->alloc_map,stop)) - start = stop + 1; - ++stop; - } - ok = (stop-start == size); - } - - /* new non overlapping room has been found ? */ - if (ok) { - /* enough room */ - PedSector abs_sector; - unsigned int ai, j, block; - unsigned int block_sz = (PED_BE32_TO_CPU ( - priv_data->vh->block_size) - / PED_SECTOR_SIZE_DEFAULT); - - if (stop > *ptr_to_fblock && stop <= *ptr_fblock) - /* Fit in the gap */ - next_to_fblock = stop; - else - /* Before or after the gap */ - next_to_fblock = *ptr_to_fblock; - - /* move blocks */ - for (i = 0; i < size; /*i++*/) { - j = size - i; j = (j < hfsp_block_count) ? - j : hfsp_block_count ; - - abs_sector = (PedSector) (*ptr_fblock + i) * block_sz; - if (!ped_geometry_read (priv_data->plus_geom, - hfsp_block, abs_sector, - block_sz * j)) - return -1; - - abs_sector = (PedSector) (start + i) * block_sz; - if (!ped_geometry_write (priv_data->plus_geom, - hfsp_block, abs_sector, - block_sz * j)) - return -1; - - for (ai = i+j; i < ai; i++) { - /* free source block */ - block = *ptr_fblock + i; - CLR_BLOC_OCCUPATION(priv_data->alloc_map,block); - SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map, - block/(PED_SECTOR_SIZE_DEFAULT*8)); - - /* set dest block */ - block = start + i; - SET_BLOC_OCCUPATION(priv_data->alloc_map,block); - SET_BLOC_OCCUPATION(priv_data->dirty_alloc_map, - block/(PED_SECTOR_SIZE_DEFAULT*8)); - } - } - if (!ped_geometry_sync_fast (priv_data->plus_geom)) - return -1; - - *ptr_fblock += size; - *ptr_to_fblock = next_to_fblock; - } else { - if (*ptr_fblock != *ptr_to_fblock) - /* not enough room */ - ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("An extent has not been relocated.")); - start = *ptr_fblock; - *ptr_fblock = *ptr_to_fblock = start + size; - } - - return start; -} - -/* Returns 0 on error */ -/* 1 on succes */ -int -hfsplus_update_vh (PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - uint8_t node[PED_SECTOR_SIZE_DEFAULT]; - - if (!ped_geometry_read (priv_data->plus_geom, node, 2, 1)) - return 0; - memcpy (node, priv_data->vh, sizeof (HfsPVolumeHeader)); - if (!ped_geometry_write (priv_data->plus_geom, node, 2, 1) - || !ped_geometry_write (priv_data->plus_geom, node, - priv_data->plus_geom->length - 2, 1) - || !ped_geometry_sync_fast (priv_data->plus_geom)) - return 0; - return 1; -} - -static int -hfsplus_do_move (PedFileSystem* fs, unsigned int *ptr_src, - unsigned int *ptr_dest, HfsCPrivateCache* cache, - HfsCPrivateExtent* ref) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPPrivateFile* file; - HfsPExtDescriptor* extent; - HfsCPrivateExtent* move; - int new_start; - - new_start = hfsplus_effect_move_extent (fs, ptr_src, ptr_dest, - ref->ext_length); - - if (new_start == -1) return -1; - - if (ref->ext_start != (unsigned) new_start) { - switch (ref->where) { - /************ VH ************/ - case CR_PRIM_CAT : - priv_data->catalog_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_PRIM; - case CR_PRIM_EXT : - priv_data->extents_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_PRIM; - case CR_PRIM_ATTR : - priv_data->attributes_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_PRIM; - case CR_PRIM_ALLOC : - priv_data->allocation_file - ->first[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_PRIM; - case CR_PRIM_START : - /* No startup file opened */ - CR_PRIM : - extent = ( HfsPExtDescriptor* ) - ( (uint8_t*)priv_data->vh + ref->ref_offset ); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - if (!hfsplus_update_vh(fs)) - return -1; - break; - - /************** BTREE *************/ - case CR_BTREE_CAT_JIB : - if (!hfsj_update_jib(fs, new_start)) - return -1; - goto BTREE_CAT; - - case CR_BTREE_CAT_JL : - if (!hfsj_update_jl(fs, new_start)) - return -1; - goto BTREE_CAT; - - BTREE_CAT: - case CR_BTREE_CAT : - file = priv_data->catalog_file; - goto CR_BTREE; - - case CR_BTREE_ATTR : - file = priv_data->attributes_file; - goto CR_BTREE; - - case CR_BTREE_EXT_ATTR : - if (priv_data->attributes_file - ->cache[ref->ref_index].start_block - == PED_CPU_TO_BE32(ref->ext_start)) - priv_data->attributes_file - ->cache[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_BTREE_EXT; - case CR_BTREE_EXT_CAT : - if (priv_data->catalog_file - ->cache[ref->ref_index].start_block - == PED_CPU_TO_BE32(ref->ext_start)) - priv_data->catalog_file - ->cache[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_BTREE_EXT; - case CR_BTREE_EXT_ALLOC : - if (priv_data->allocation_file - ->cache[ref->ref_index].start_block - == PED_CPU_TO_BE32(ref->ext_start)) - priv_data->allocation_file - ->cache[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - goto CR_BTREE_EXT; - case CR_BTREE_EXT_START : - /* No startup file opened */ - CR_BTREE_EXT : - case CR_BTREE_EXT_0 : - file = priv_data->extents_file; - - CR_BTREE : - PED_ASSERT(PED_SECTOR_SIZE_DEFAULT * ref->sect_by_block - > ref->ref_offset, return -1 ); - if (!hfsplus_file_read(file, hfsp_block, - (PedSector)ref->ref_block * ref->sect_by_block, - ref->sect_by_block)) - return -1; - extent = ( HfsPExtDescriptor* ) - ( hfsp_block + ref->ref_offset ); - extent[ref->ref_index].start_block = - PED_CPU_TO_BE32(new_start); - if (!hfsplus_file_write(file, hfsp_block, - (PedSector)ref->ref_block * ref->sect_by_block, - ref->sect_by_block) - || !ped_geometry_sync_fast (priv_data->plus_geom)) - return -1; - break; - - /********** BUG *********/ - default : - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("A reference to an extent comes from a place " - "it should not. You should check the file " - "system!")); - return -1; - break; - } - - move = hfsc_cache_move_extent(cache, ref->ext_start, new_start); - if (!move) return -1; - PED_ASSERT(move == ref, return -1); - } - - return new_start; -} - -/* save any dirty sector of the allocation bitmap file */ -static int -hfsplus_save_allocation(PedFileSystem *fs) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - unsigned int map_sectors, i, j; - int ret = 1; - - map_sectors = ( PED_BE32_TO_CPU (priv_data->vh->total_blocks) - + PED_SECTOR_SIZE_DEFAULT * 8 - 1 ) / (PED_SECTOR_SIZE_DEFAULT * 8); - - for (i = 0; i < map_sectors;) { - for (j = i; - (TST_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j)); - ++j) - CLR_BLOC_OCCUPATION(priv_data->dirty_alloc_map,j); - if (j-i) { - ret = hfsplus_file_write(priv_data->allocation_file, - priv_data->alloc_map + i * PED_SECTOR_SIZE_DEFAULT, - i, j-i) && ret; - i = j; - } else - ++i; - } - - return ret; -} - -/* This function moves an extent starting at block fblock - to block to_fblock if there's enough room */ -/* Return 1 if everything was fine */ -/* Return -1 if an error occurred */ -/* Return 0 if no extent was found */ -static int -hfsplus_move_extent_starting_at (PedFileSystem *fs, unsigned int *ptr_fblock, - unsigned int *ptr_to_fblock, - HfsCPrivateCache* cache) -{ - HfsCPrivateExtent* ref; - unsigned int old_start, new_start; - - ref = hfsc_cache_search_extent(cache, *ptr_fblock); - if (!ref) return 0; - - old_start = *ptr_fblock; - new_start = hfsplus_do_move(fs, ptr_fblock, ptr_to_fblock, cache, ref); - if (new_start == (unsigned)-1) return -1; - if (new_start > old_start) { - new_start = hfsplus_do_move(fs, &new_start, ptr_to_fblock, - cache, ref); - if (new_start == (unsigned)-1 || new_start > old_start) - return -1; - } - - hfsplus_save_allocation(fs); - return 1; -} - -static int -hfsplus_cache_from_vh(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPExtDescriptor* extent; - unsigned int j; - - extent = priv_data->vh->allocation_file.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_ALLOC, - j ) - ) - return 0; - } - - extent = priv_data->vh->extents_file.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_EXT, - j ) - ) - return 0; - } - - extent = priv_data->vh->catalog_file.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_CAT, - j ) - ) - return 0; - } - - extent = priv_data->vh->attributes_file.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_ATTR, - j ) - ) - return 0; - } - - extent = priv_data->vh->startup_file.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - 0, /* unused for vh */ - ((uint8_t*)extent) - ((uint8_t*)priv_data->vh), - 1, /* load / save 1 sector */ - CR_PRIM_START, - j ) - ) - return 0; - } - - return 1; -} - -static int -hfsplus_cache_from_catalog(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; - uint8_t* node; - HfsPHeaderRecord* header; - HfsPNodeDescriptor* desc = (HfsPNodeDescriptor*) node_1; - HfsPCatalogKey* catalog_key; - HfsPCatalog* catalog_data; - HfsPExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j, size, bsize; - uint32_t jib = priv_data->jib_start_block, - jl = priv_data->jl_start_block; - - if (!priv_data->catalog_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS+ volume has no catalog file. " - "This is very unusual!")); - return 1; - } - - /* Search the extent starting at *ptr_block in the catalog file */ - if (!hfsplus_file_read_sector (priv_data->catalog_file, node_1, 0)) - return 0; - header = (HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC); - leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - bsize = PED_BE16_TO_CPU (header->node_size); - size = bsize / PED_SECTOR_SIZE_DEFAULT; - PED_ASSERT(size < 256, return 0); - - node = (uint8_t*) ped_malloc(bsize); - if (!node) return 0; - desc = (HfsPNodeDescriptor*) node; - - for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfsplus_file_read (priv_data->catalog_file, node, - (PedSector) leaf_node * size, size)) { - ped_free (node); - return 0; - } - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; i++) { - unsigned int skip; - uint8_t where; - - catalog_key = (HfsPCatalogKey*) - ( node + PED_BE16_TO_CPU (*((uint16_t *) - (node+(bsize - 2*i)))) ); - skip = ( 2 + PED_BE16_TO_CPU (catalog_key->key_length) - + 1) & ~1; - catalog_data = (HfsPCatalog*) - (((uint8_t*)catalog_key) + skip); - /* check for obvious error in FS */ - if (((uint8_t*)catalog_key - node < HFS_FIRST_REC) - || ((uint8_t*)catalog_data - node - >= (signed) bsize - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - ped_free (node); - return 0; - } - - if (PED_BE16_TO_CPU(catalog_data->type)!=HFS_CAT_FILE) - continue; - - extent = catalog_data->sel.file.data_fork.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - where = CR_BTREE_CAT; - if ( PED_BE32_TO_CPU(extent[j].start_block) - == jib ) { - jib = 0; - where = CR_BTREE_CAT_JIB; - } else - if ( PED_BE32_TO_CPU(extent[j].start_block) - == jl ) { - jl = 0; - where = CR_BTREE_CAT_JL; - } - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - size, - where, - j ) - ) { - ped_free (node); - return 0; - } - } - - extent = catalog_data->sel.file.res_fork.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - size, - CR_BTREE_CAT, - j ) - ) { - ped_free (node); - return 0; - } - } - } - } - - ped_free (node); - return 1; -} - -static int -hfsplus_cache_from_extent(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; - uint8_t* node; - HfsPHeaderRecord* header; - HfsPNodeDescriptor* desc = (HfsPNodeDescriptor*) node_1; - HfsPExtentKey* extent_key; - HfsPExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j, size, bsize; - - if (!priv_data->extents_file->sect_nb) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - _("This HFS+ volume has no extents overflow " - "file. This is quite unusual!")); - return 1; - } - - if (!hfsplus_file_read_sector (priv_data->extents_file, node_1, 0)) - return 0; - header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC)); - leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - bsize = PED_BE16_TO_CPU (header->node_size); - size = bsize / PED_SECTOR_SIZE_DEFAULT; - PED_ASSERT(size < 256, return 0); - - node = (uint8_t*) ped_malloc (bsize); - if (!node) return -1; - desc = (HfsPNodeDescriptor*) node; - - for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfsplus_file_read (priv_data->extents_file, node, - (PedSector) leaf_node * size, size)) { - ped_free (node); - return 0; - } - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; i++) { - uint8_t where; - extent_key = (HfsPExtentKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(bsize - 2*i))))); - extent = (HfsPExtDescriptor*) - (((uint8_t*)extent_key) + sizeof (HfsPExtentKey)); - /* check for obvious error in FS */ - if (((uint8_t*)extent_key - node < HFS_FIRST_REC) - || ((uint8_t*)extent - node - >= (signed)bsize - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - ped_free (node); - return -1; - } - - switch (extent_key->file_ID) { - case PED_CPU_TO_BE32 (HFS_XTENT_ID) : - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The extents overflow file should not" - " contain its own extents! You should " - "check the file system.")) - != PED_EXCEPTION_IGNORE) - return 0; - where = CR_BTREE_EXT_EXT; - break; - case PED_CPU_TO_BE32 (HFS_CATALOG_ID) : - where = CR_BTREE_EXT_CAT; - break; - case PED_CPU_TO_BE32 (HFSP_ALLOC_ID) : - where = CR_BTREE_EXT_ALLOC; - break; - case PED_CPU_TO_BE32 (HFSP_STARTUP_ID) : - where = CR_BTREE_EXT_START; - break; - case PED_CPU_TO_BE32 (HFSP_ATTRIB_ID) : - where = CR_BTREE_EXT_ATTR; - break; - default : - where = CR_BTREE_EXT_0; - break; - } - - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU(extent[j].start_block), - PED_BE32_TO_CPU(extent[j].block_count), - leaf_node, - (uint8_t*)extent - node, - size, - where, - j ) - ) { - ped_free (node); - return 0; - } - } - } - } - - ped_free (node); - return 1; -} - -static int -hfsplus_cache_from_attributes(HfsCPrivateCache* cache, PedFileSystem* fs, - PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - uint8_t node_1[PED_SECTOR_SIZE_DEFAULT]; - uint8_t* node; - HfsPHeaderRecord* header; - HfsPNodeDescriptor* desc = (HfsPNodeDescriptor*) node_1; - HfsPPrivateGenericKey* generic_key; - HfsPForkDataAttr* fork_ext_data; - HfsPExtDescriptor* extent; - unsigned int leaf_node, record_number; - unsigned int i, j, size, bsize; - - /* attributes file is facultative */ - if (!priv_data->attributes_file->sect_nb) - return 1; - - /* Search the extent starting at *ptr_block in the catalog file */ - if (!hfsplus_file_read_sector (priv_data->attributes_file, node_1, 0)) - return 0; - header = ((HfsPHeaderRecord*) (node_1 + HFS_FIRST_REC)); - leaf_node = PED_BE32_TO_CPU (header->first_leaf_node); - bsize = PED_BE16_TO_CPU (header->node_size); - size = bsize / PED_SECTOR_SIZE_DEFAULT; - PED_ASSERT(size < 256, return 0); - - node = (uint8_t*) ped_malloc(bsize); - if (!node) return 0; - desc = (HfsPNodeDescriptor*) node; - - for (; leaf_node; leaf_node = PED_BE32_TO_CPU (desc->next)) { - if (!hfsplus_file_read (priv_data->attributes_file, node, - (PedSector) leaf_node * size, size)) { - ped_free (node); - return 0; - } - record_number = PED_BE16_TO_CPU (desc->rec_nb); - for (i = 1; i <= record_number; i++) { - unsigned int skip; - generic_key = (HfsPPrivateGenericKey*) - (node + PED_BE16_TO_CPU(*((uint16_t *) - (node+(bsize - 2*i))))); - skip = ( 2 + PED_BE16_TO_CPU (generic_key->key_length) - + 1 ) & ~1; - fork_ext_data = (HfsPForkDataAttr*) - (((uint8_t*)generic_key) + skip); - /* check for obvious error in FS */ - if (((uint8_t*)generic_key - node < HFS_FIRST_REC) - || ((uint8_t*)fork_ext_data - node - >= (signed) bsize - - 2 * (signed)(record_number+1))) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system contains errors.")); - ped_free (node); - return 0; - } - - if (fork_ext_data->record_type - == PED_CPU_TO_BE32 ( HFSP_ATTR_FORK ) ) { - extent = fork_ext_data->fork_res.fork.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU ( - extent[j].start_block ), - PED_BE32_TO_CPU ( - extent[j].block_count ), - leaf_node, - (uint8_t*)extent-node, - size, - CR_BTREE_ATTR, - j ) - ) { - ped_free(node); - return 0; - } - } - } else if (fork_ext_data->record_type - == PED_CPU_TO_BE32 ( HFSP_ATTR_EXTENTS ) ) { - extent = fork_ext_data->fork_res.extents; - for (j = 0; j < HFSP_EXT_NB; ++j) { - if (!extent[j].block_count) break; - if (!hfsc_cache_add_extent( - cache, - PED_BE32_TO_CPU ( - extent[j].start_block ), - PED_BE32_TO_CPU ( - extent[j].block_count ), - leaf_node, - (uint8_t*)extent-node, - size, - CR_BTREE_ATTR, - j ) - ) { - ped_free(node); - return 0; - } - } - } else continue; - } - } - - ped_free (node); - return 1; -} - -static HfsCPrivateCache* -hfsplus_cache_extents(PedFileSystem* fs, PedTimer* timer) -{ - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsCPrivateCache* ret; - unsigned int file_number, block_number; - - file_number = PED_BE32_TO_CPU(priv_data->vh->file_count); - block_number = PED_BE32_TO_CPU(priv_data->vh->total_blocks); - ret = hfsc_new_cache(block_number, file_number); - if (!ret) return NULL; - - if (!hfsplus_cache_from_vh(ret, fs, timer) || - !hfsplus_cache_from_catalog(ret, fs, timer) || - !hfsplus_cache_from_extent(ret, fs, timer) || - !hfsplus_cache_from_attributes(ret, fs, timer)) { - ped_exception_throw( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Could not cache the file system in memory.")); - hfsc_delete_cache(ret); - return NULL; - } - - return ret; -} - -/* This function moves file's data to compact used and free space, - starting at fblock block */ -/* return 0 on error */ -int -hfsplus_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free) -{ - PedSector bytes_buff; - HfsPPrivateFSData* priv_data = (HfsPPrivateFSData*) - fs->type_specific; - HfsPVolumeHeader* vh = priv_data->vh; - HfsCPrivateCache* cache; - unsigned int to_fblock = fblock; - unsigned int start = fblock; - unsigned int divisor = PED_BE32_TO_CPU (vh->total_blocks) - + 1 - start - to_free; - int ret; - - PED_ASSERT (!hfsp_block, return 0); - - cache = hfsplus_cache_extents (fs, timer); - if (!cache) - return 0; - - /* Calculate the size of the copy buffer : - * Takes BLOCK_MAX_BUFF HFS blocks, but if > BYTES_MAX_BUFF - * takes the maximum number of HFS blocks so that the buffer - * will remain smaller than or equal to BYTES_MAX_BUFF, with - * a minimum of 1 HFS block */ - bytes_buff = PED_BE32_TO_CPU (priv_data->vh->block_size) - * (PedSector) BLOCK_MAX_BUFF; - if (bytes_buff > BYTES_MAX_BUFF) { - hfsp_block_count = BYTES_MAX_BUFF - / PED_BE32_TO_CPU (priv_data->vh->block_size); - if (!hfsp_block_count) - hfsp_block_count = 1; - bytes_buff = (PedSector) hfsp_block_count - * PED_BE32_TO_CPU (priv_data->vh->block_size); - } else - hfsp_block_count = BLOCK_MAX_BUFF; - - /* If the cache code requests more space, give it to him */ - if (bytes_buff < hfsc_cache_needed_buffer (cache)) - bytes_buff = hfsc_cache_needed_buffer (cache); - - hfsp_block = (uint8_t*) ped_malloc (bytes_buff); - if (!hfsp_block) - goto error_cache; - - if (!hfsplus_read_bad_blocks (fs)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Bad blocks list could not be loaded.")); - goto error_alloc; - } - - while ( fblock < ( priv_data->plus_geom->length - 2 ) - / ( PED_BE32_TO_CPU (vh->block_size) - / PED_SECTOR_SIZE_DEFAULT ) ) { - if (TST_BLOC_OCCUPATION (priv_data->alloc_map, fblock) - && (!hfsplus_is_bad_block (fs, fblock))) { - if (!(ret = hfsplus_move_extent_starting_at (fs, - &fblock, &to_fblock, cache))) - to_fblock = ++fblock; - else if (ret == -1) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("An error occurred during extent " - "relocation.")); - goto error_alloc; - } - } else { - fblock++; - } - - ped_timer_update(timer, (float)(to_fblock - start) / divisor); - } - - ped_free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0; - hfsc_delete_cache (cache); - return 1; - -error_alloc: - ped_free (hfsp_block); hfsp_block = NULL; hfsp_block_count = 0; -error_cache: - hfsc_delete_cache (cache); - return 0; -} - -#endif /* !DISCOVER_ONLY */ diff --git a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.h b/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.h deleted file mode 100644 index b764bab943..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _RELOC_PLUS_H -#define _RELOC_PLUS_H - -#include -#include -#include - -#include "hfs.h" - -int -hfsplus_update_vh (PedFileSystem *fs); - -int -hfsplus_pack_free_space_from_block (PedFileSystem *fs, unsigned int fblock, - PedTimer* timer, unsigned int to_free); - - -#endif /* _RELOC_PLUS_H */ diff --git a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs.c b/usr/src/lib/libparted/common/libparted/fs/jfs/jfs.c deleted file mode 100644 index b01d18a6d3..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include - -#define _JFS_UTILITY -#include "jfs_types.h" -#include "jfs_superblock.h" - -#define JFS_SUPER_SECTOR 64 - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define JFS_BLOCK_SIZES ((int[2]){512, 0}) - -static PedGeometry* -jfs_probe (PedGeometry* geom) -{ - union { - struct superblock sb; - char bytes[512]; - } buf; - - if (geom->length < JFS_SUPER_SECTOR + 1) - return NULL; - if (!ped_geometry_read (geom, &buf, JFS_SUPER_SECTOR, 1)) - return NULL; - - if (strncmp (buf.sb.s_magic, JFS_MAGIC, 4) == 0) { - PedSector block_size = PED_LE32_TO_CPU (buf.sb.s_pbsize) / 512; - PedSector block_count = PED_LE64_TO_CPU (buf.sb.s_size); - - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } else { - return NULL; - } -} - -#ifndef DISCOVER_ONLY -static int -jfs_clobber (PedGeometry* geom) -{ - char buf[512]; - - memset (buf, 0, 512); - return ped_geometry_write (geom, buf, JFS_SUPER_SECTOR, 1); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps jfs_ops = { - .probe = jfs_probe, -#ifndef DISCOVER_ONLY - .clobber = jfs_clobber, -#else - .clobber = NULL, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemType jfs_type = { - .next = NULL, - .ops = &jfs_ops, - .name = "jfs", - .block_sizes = JFS_BLOCK_SIZES -}; - -void -ped_file_system_jfs_init () -{ - ped_file_system_type_register (&jfs_type); -} - -void -ped_file_system_jfs_done () -{ - ped_file_system_type_unregister (&jfs_type); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_superblock.h b/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_superblock.h deleted file mode 100644 index 71fe3f10ac..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_superblock.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ -#ifndef _H_JFS_SUPERBLOCK -#define _H_JFS_SUPERBLOCK -/* - * jfs_superblock.h - */ - -/* - * make the magic number something a human could read - */ -#define JFS_MAGIC "JFS1" /* Magic word: Version 1 */ - -#define JFS_VERSION 1 /* Version number: Version 1 */ - -#define LV_NAME_SIZE 11 /* MUST BE 11 for OS/2 boot sector */ - -/* - * aggregate superblock - * - * The name superblock is too close to super_block, so the name has been - * changed to jfs_superblock. The utilities are still using the old name. - */ -#ifdef _JFS_UTILITY -struct superblock -#else -struct jfs_superblock -#endif -{ - char s_magic[4]; /* 4: magic number */ - u32 s_version; /* 4: version number */ - - s64 s_size; /* 8: aggregate size in hardware/LVM blocks; - * VFS: number of blocks - */ - s32 s_bsize; /* 4: aggregate block size in bytes; - * VFS: fragment size - */ - s16 s_l2bsize; /* 2: log2 of s_bsize */ - s16 s_l2bfactor; /* 2: log2(s_bsize/hardware block size) */ - s32 s_pbsize; /* 4: hardware/LVM block size in bytes */ - s16 s_l2pbsize; /* 2: log2 of s_pbsize */ - s16 pad; /* 2: padding necessary for alignment */ - - u32 s_agsize; /* 4: allocation group size in aggr. blocks */ - - u32 s_flag; /* 4: aggregate attributes: - * see jfs_filsys.h - */ - u32 s_state; /* 4: mount/unmount/recovery state: - * see jfs_filsys.h - */ - s32 s_compress; /* 4: > 0 if data compression */ - - pxd_t s_ait2; /* 8: first extent of secondary - * aggregate inode table - */ - - pxd_t s_aim2; /* 8: first extent of secondary - * aggregate inode map - */ - u32 s_logdev; /* 4: device address of log */ - s32 s_logserial; /* 4: log serial number at aggregate mount */ - pxd_t s_logpxd; /* 8: inline log extent */ - - pxd_t s_fsckpxd; /* 8: inline fsck work space extent */ - - struct timestruc_t s_time; /* 8: time last updated */ - - s32 s_fsckloglen; /* 4: Number of file system blocks reserved for - * the fsck service log. - * N.B. These blocks are divided among the - * versions kept. This is not a per - * version size. - * N.B. These blocks are included in the - * length field of s_fsckpxd. - */ - s8 s_fscklog; /* 1: which fsck service log is most recent - * 0 => no service log data yet - * 1 => the first one - * 2 => the 2nd one - */ - char s_fpack[11]; /* 11: file system volume name - * N.B. This must be 11 bytes to - * conform with the OS/2 BootSector - * requirements - */ - - /* extendfs() parameter under s_state & FM_EXTENDFS */ - s64 s_xsize; /* 8: extendfs s_size */ - pxd_t s_xfsckpxd; /* 8: extendfs fsckpxd */ - pxd_t s_xlogpxd; /* 8: extendfs logpxd */ - /* - 128 byte boundary - */ - - /* - * DFS VFS support (preliminary) - */ - char s_attach; /* 1: VFS: flag: set when aggregate is attached - */ - u8 rsrvd4[7]; /* 7: reserved - set to 0 */ - - u64 totalUsable; /* 8: VFS: total of 1K blocks which are - * available to "normal" (non-root) users. - */ - u64 minFree; /* 8: VFS: # of 1K blocks held in reserve for - * exclusive use of root. This value can be 0, - * and if it is then totalUsable will be equal - * to # of blocks in aggregate. I believe this - * means that minFree + totalUsable = # blocks. - * In that case, we don't need to store both - * totalUsable and minFree since we can compute - * one from the other. I would guess minFree - * would be the one we should store, and - * totalUsable would be the one we should - * compute. (Just a guess...) - */ - - u64 realFree; /* 8: VFS: # of free 1K blocks can be used by - * "normal" users. It may be this is something - * we should compute when asked for instead of - * storing in the superblock. I don't know how - * often this information is needed. - */ - /* - * graffiti area - */ -}; - -#endif /*_H_JFS_SUPERBLOCK */ diff --git a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_types.h b/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_types.h deleted file mode 100644 index ca865bb3e8..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/jfs/jfs_types.h +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2000 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef _H_JFS_TYPES -#define _H_JFS_TYPES - -/* - * jfs_types.h: - * - * basic type/utility definitions - * - * note: this header file must be the 1st include file - * of JFS include list in all JFS .c file. - */ - -#ifdef _JFS_UTILITY -/* this is defined in asm/byteorder.h for i386, but - * is NOT defined in asm/byteorder.h for ppc (non-kernel). - * Until that is changed, we'll define it here. */ -#define __BYTEORDER_HAS_U64__ - -#include -//#include -typedef unsigned short UniChar; -#else -#include -#include -#include - -#ifndef _ULS_UNICHAR_DEFINED -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)) -typedef wchar_t UniChar; -#else -typedef unsigned short UniChar; -#endif -#define _ULS_UNICHAR_DEFINED -#endif -#endif -/* #include "endian24.h" */ - -/* - * primitive types - */ -#ifdef _JFS_UTILITY -typedef int8_t s8; -typedef uint8_t u8; -typedef int16_t s16; -typedef uint16_t u16; -typedef int32_t s32; -typedef uint32_t u32; -typedef int64_t s64; -typedef uint64_t u64; - -#ifndef _UINT_TYPES - /* unicode includes also define these */ -typedef u16 uint16; -typedef u32 uint32; -#define _UINT_TYPES -#endif - -typedef s8 int8; -typedef u8 uint8; -typedef s16 int16; -typedef s32 int32; -typedef s64 int64; -typedef u64 uint64; - -#endif /* _JFS_UTILITY */ -/* - * Holdovers from OS/2. Try to get away from using these altogether. - */ -typedef unsigned long ULONG; -typedef unsigned short USHORT; -typedef unsigned char UCHAR; -typedef void *PVOID; -#define MAXPATHLEN 255 - - -/* - * Almost identical to Linux's timespec, but not quite - */ -struct timestruc_t { - u32 tv_sec; - u32 tv_nsec; -}; - -/* - * handy - */ -#undef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#undef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#undef ROUNDUP -#define ROUNDUP(x, y) ( ((x) + ((y) - 1)) & ~((y) - 1) ) - -#define LEFTMOSTONE 0x80000000 -#define HIGHORDER 0x80000000u /* high order bit on */ -#define ONES 0xffffffffu /* all bit on */ - -#if !defined(__sun) -typedef int boolean_t; -#endif - -#define TRUE 1 -#define FALSE 0 - -/* - * logical xd (lxd) - */ -typedef struct { - unsigned len:24; - unsigned off1:8; - u32 off2; -} lxd_t; - -/* lxd_t field construction */ -#define LXDlength(lxd, length32) ( (lxd)->len = length32 ) -#define LXDoffset(lxd, offset64)\ -{\ - (lxd)->off1 = ((s64)offset64) >> 32;\ - (lxd)->off2 = (offset64) & 0xffffffff;\ -} - -/* lxd_t field extraction */ -#define lengthLXD(lxd) ( (lxd)->len ) -#define offsetLXD(lxd)\ - ( ((s64)((lxd)->off1)) << 32 | (lxd)->off2 ) - -/* lxd list */ -typedef struct { - s16 maxnlxd; - s16 nlxd; - lxd_t *lxd; -} lxdlist_t; - -/* - * physical xd (pxd) - */ -typedef struct { - unsigned len:24; - unsigned addr1:8; - u32 addr2; -} pxd_t; - -/* xd_t field construction */ - -#define PXDlength(pxd, length32) ((pxd)->len = __cpu_to_le24(length32)) -#define PXDaddress(pxd, address64)\ -{\ - (pxd)->addr1 = ((s64)address64) >> 32;\ - (pxd)->addr2 = __cpu_to_le32((address64) & 0xffffffff);\ -} - -/* xd_t field extraction */ -#define lengthPXD(pxd) __le24_to_cpu((pxd)->len) -#define addressPXD(pxd)\ - ( ((s64)((pxd)->addr1)) << 32 | __le32_to_cpu((pxd)->addr2)) - -/* pxd list */ -typedef struct { - s16 maxnpxd; - s16 npxd; - pxd_t pxd[8]; -} pxdlist_t; - - -/* - * data extent descriptor (dxd) - */ -typedef struct { - unsigned flag:8; /* 1: flags */ - unsigned rsrvd:24; /* 3: */ - u32 size; /* 4: size in byte */ - unsigned len:24; /* 3: length in unit of fsblksize */ - unsigned addr1:8; /* 1: address in unit of fsblksize */ - u32 addr2; /* 4: address in unit of fsblksize */ -} dxd_t; /* - 16 - */ - -/* dxd_t flags */ -#define DXD_INDEX 0x80 /* B+-tree index */ -#define DXD_INLINE 0x40 /* in-line data extent */ -#define DXD_EXTENT 0x20 /* out-of-line single extent */ -#define DXD_FILE 0x10 /* out-of-line file (inode) */ -#define DXD_CORRUPT 0x08 /* Inconsistency detected */ - -/* dxd_t field construction - * Conveniently, the PXD macros work for DXD - */ -#define DXDlength PXDlength -#define DXDaddress PXDaddress -#define lengthDXD lengthPXD -#define addressDXD addressPXD - -/* - * directory entry argument - */ -typedef struct component_name { - int namlen; - UniChar *name; -} component_t; - - -/* - * DASD limit information - stored in directory inode - */ -typedef struct dasd { - u8 thresh; /* Alert Threshold (in percent) */ - u8 delta; /* Alert Threshold delta (in percent) */ - u8 rsrvd1; - u8 limit_hi; /* DASD limit (in logical blocks) */ - u32 limit_lo; /* DASD limit (in logical blocks) */ - u8 rsrvd2[3]; - u8 used_hi; /* DASD usage (in logical blocks) */ - u32 used_lo; /* DASD usage (in logical blocks) */ -} dasd_t; - -#define DASDLIMIT(dasdp) \ - (((u64)((dasdp)->limit_hi) << 32) + __le32_to_cpu((dasdp)->limit_lo)) -#define setDASDLIMIT(dasdp, limit)\ -{\ - (dasdp)->limit_hi = ((u64)limit) >> 32;\ - (dasdp)->limit_lo = __cpu_to_le32(limit);\ -} -#define DASDUSED(dasdp) \ - (((u64)((dasdp)->used_hi) << 32) + __le32_to_cpu((dasdp)->used_lo)) -#define setDASDUSED(dasdp, used)\ -{\ - (dasdp)->used_hi = ((u64)used) >> 32;\ - (dasdp)->used_lo = __cpu_to_le32(used);\ -} - -/* - * circular doubly-linked list (cdll) - * - * A circular doubly-linked list (cdll) is anchored by a pair of pointers, - * one to the head of the list and the other to the tail of the list. - * The elements are doubly linked so that an arbitrary element can be - * removed without a need to traverse the list. - * New elements can be added to the list before or after an existing element, - * at the head of the list, or at the tail of the list. - * A circle queue may be traversed in either direction. - * - * +----------+ +-------------------------------------+ - * | | | | - * +->+-----+ | +->+-----+ +->+-----+ +->+-----+ | - * | | h +-+ | | h +--+ | n +----+ | n +--+ - * | +-----+ | +-----+ | +-----+ | +-----+ - * | | t +-+ +-----+ t | | | p +--+ | | p +--+ - * | +-----+ | | | +-----+ | +-----+ | | +-----+ | - * +----------+ | +-----------------------+ | | - * | | | | - * | +-------------------------+ - * | | - * +----------------------------+ - */ -/* - * define header - * - * list header field definition in header element: - * - * type - type of list element struct embedding the link field - */ -#define CDLL_HEADER(type)\ -struct {\ - struct type *head;\ - struct type *tail;\ -} - -struct cdll_header { - struct cdll_header *head; - struct cdll_header *tail; -}; - -/* - * define link - * - * list link field definition in list element: - * - * type - type of parent list element struct embedding the link field - */ -#define CDLL_ENTRY(type)\ -struct {\ - struct type *next;\ - struct type *prev;\ -} - -struct cdll_entry { - struct cdll_entry *next; - struct cdll_entry *prev; -}; - -/* - * initialize header - * - * header - ptr to the header field in the header element - */ -#define CDLL_INIT(header) {\ - (header)->head = (void *)(header);\ - (header)->tail = (void *)(header);\ -} - -/* - * scan list - * - * header - ptr to the header field in the header element - * elm - ptr to the element to be inserted - * field - name of the link field in the list element - * - * struct header_container *container; - * struct header_type *header; - * struct element_type *elm; - * - * header = &container->header_field; - * for (elm = header->head; elm != (void *)header; elm = elm->field.next) - */ - -/* - * insert at head of list anchored at
- * - * header - ptr to the header field in the header element - * elm - ptr to the list element to be inserted - * field - name of the link field in the list element - */ -#define CDLL_INSERT_HEAD(header, elm, field) {\ - (elm)->field.next = (header)->head;\ - (elm)->field.prev = (void *)(header);\ - if ((header)->tail == (void *)(header))\ - (header)->tail = (elm);\ - else\ - (header)->head->field.prev = (elm);\ - (header)->head = (elm);\ -} - -/* - * insert at tail of list anchored at
- * - * header - ptr to the header field in the header element - * elm - ptr to the list element to be inserted - * field - name of the link field in the list element - */ -#define CDLL_INSERT_TAIL(header, elm, field) {\ - (elm)->field.next = (void *)(header);\ - (elm)->field.prev = (header)->tail;\ - if ((header)->head == (void *)(header))\ - (header)->head = (elm);\ - else\ - (header)->tail->field.next = (elm);\ - (header)->tail = (elm);\ -} - -/* - * insert after of list anchored at
- * - * header - ptr to the header field in the header element - * listelm - ptr to the list element at insertion point - * elm - ptr to the list element to be inserted - * field - name of the link field in the list element - */ -#define CDLL_INSERT_AFTER(header, listelm, elm, field) {\ - (elm)->field.next = (listelm)->field.next;\ - (elm)->field.prev = (listelm);\ - if ((listelm)->field.next == (void *)(header))\ - (header)->tail = (elm);\ - else\ - (listelm)->field.next->field.prev = (elm);\ - (listelm)->field.next = (elm);\ -} - -/* - * insert before of list anchored at
- * - * header - ptr to the header field in the header element - * listelm - ptr to list element at insertion point - * elm - ptr to the element to be inserted - * field - name of the link field in the list element - */ -#define CDLL_INSERT_BEFORE(header, listelm, elm, field) {\ - (elm)->field.next = (listelm);\ - (elm)->field.prev = (listelm)->field.prev;\ - if ((listelm)->field.prev == (void *)(header))\ - (header)->head = (elm);\ - else\ - (listelm)->field.prev->field.next = (elm);\ - (listelm)->field.prev = (elm);\ -} - -/* - * remove from list anchored at
- * - * header - ptr to the header field in the header element - * elm - ptr to the list element to be removed - * field - name of the link field in the list element - */ -#define CDLL_REMOVE(header, elm, field) {\ - if ((elm)->field.next == (void *)(header))\ - (header)->tail = (elm)->field.prev;\ - else\ - (elm)->field.next->field.prev = (elm)->field.prev;\ - if ((elm)->field.prev == (void *)(header))\ - (header)->head = (elm)->field.next;\ - else\ - (elm)->field.prev->field.next = (elm)->field.next;\ -} - -#define CDLL_MOVE_TO_HEAD(header, elm, field) {\ - if ((elm)->field.prev != (void *)(header))\ - {\ - if ((elm)->field.next == (void *)(header))\ - (header)->tail = (elm)->field.prev;\ - else\ - (elm)->field.next->field.prev = (elm)->field.prev;\ - (elm)->field.prev->field.next = (elm)->field.next;\ - (elm)->field.next = (header)->head;\ - (elm)->field.prev = (void *)(header);\ - (header)->head->field.prev = (elm);\ - (header)->head = (elm);\ - }\ -} - -#define CDLL_MOVE_TO_TAIL(header, elm, field) {\ - if ((elm)->field.next != (void *)(header))\ - {\ - (elm)->field.next->field.prev = (elm)->field.prev;\ - if ((elm)->field.prev == (void *)(header))\ - (header)->head = (elm)->field.next;\ - else\ - (elm)->field.prev->field.next = (elm)->field.next;\ - (elm)->field.next = (void *)(header);\ - (elm)->field.prev = (header)->tail;\ - (header)->tail->field.next = (elm);\ - (header)->tail = (elm);\ - }\ -} - -/* - * orphan list element - */ -#define CDLL_SELF(elm, field)\ - (elm)->field.next = (elm)->field.prev = (elm); - - -/* - * single head doubly-linked list - * - * A list is headed by a single head pointer. - * The elements are doubly linked so that an arbitrary element can be - * removed without a need to traverse the list. - * New elements can be added to the list at the head of the list, or - * after an existing element (NO insert at tail). - * A list may only be traversed in the forward direction. - * (note: the list is NULL terminated in next field.) - * - * +-----+ +->+-----+ +->+-----+ +->+-----+ - * | NULL| | | h +--+ | n +----+ | NULL| - * +-----+ | +-----+ | +-----+ +-----+ - * | | | p +--+ | p +--+ - * | | +-----+ | +-----+ | - * +-----------------------+ | - * | | - * +-------------------------+ - */ -#define LIST_HEADER(type)\ -struct {\ - struct type *head;\ -} - -#define LIST_ENTRY(type)\ -struct {\ - struct type *next;\ - struct type **prev;\ -} - -#define LIST_INIT(header) { (header)->head = NULL; } - -/* - * scan list - * - * header - ptr to the header (field in header element) - * elm - ptr to the element to be inserted - * field - name of the link field in list element - * - * struct header_container *container; - * struct header_type *header; - * struct element_type *elm; - * - * header = &container->header_field; - * for (elm = header->head; elm; elm = elm->field.next) - */ - -#define LIST_INSERT_HEAD(header, elm, field) {\ - if (((elm)->field.next = (header)->head) != NULL)\ - (header)->head->field.prev = &(elm)->field.next;\ - (header)->head = (elm);\ - (elm)->field.prev = &(header)->head;\ -} - -#define LIST_INSERT_AFTER(listelm, elm, field) {\ - if (((elm)->field.next = (listelm)->field.next) != NULL)\ - (listelm)->field.next->field.prev = &(elm)->field.next;\ - (listelm)->field.next = (elm);\ - (elm)->field.prev = &(listelm)->field.next;\ -} - -#define LIST_REMOVE(elm, field) {\ - if ((elm)->field.next != NULL)\ - (elm)->field.next->field.prev = (elm)->field.prev;\ - *(elm)->field.prev = (elm)->field.next;\ -} - -#define LIST_SELF(elm, field) {\ - (elm)->field.next = NULL;\ - (elm)->field.prev = &(elm)->field.next;\ -} - -#endif /* !_H_JFS_TYPES */ diff --git a/usr/src/lib/libparted/common/libparted/fs/linux_swap/linux_swap.c b/usr/src/lib/libparted/common/libparted/fs/linux_swap/linux_swap.c deleted file mode 100644 index 5aa81e6c47..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/linux_swap/linux_swap.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* It's a bit silly calling a swap partition a file system. Oh well... */ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include - -#define SWAP_SPECIFIC(fs) ((SwapSpecific*) (fs->type_specific)) -#define BUFFER_SIZE 128 - -#define LINUXSWAP_BLOCK_SIZES ((int[2]){512, 0}) - -typedef struct { - char page_map[1]; -} SwapOldHeader; - -/* ripped from mkswap */ -typedef struct { - char bootbits[1024]; /* Space for disklabel etc. */ - uint32_t version; - uint32_t last_page; - uint32_t nr_badpages; - unsigned char sws_uuid[16]; - unsigned char sws_volume[16]; - uint32_t padding[117]; - uint32_t badpages[1]; -} SwapNewHeader; - -typedef struct { - union { - SwapNewHeader new; - SwapOldHeader old; - }* header; - - void* buffer; - int buffer_size; - - PedSector page_sectors; - unsigned int page_count; - unsigned int version; - unsigned int max_bad_pages; -} SwapSpecific; - -static PedFileSystemType swap_type; - -static PedFileSystem* swap_open (PedGeometry* geom); -static int swap_close (PedFileSystem* fs); - -static PedGeometry* -swap_probe (PedGeometry* geom) -{ - PedFileSystem* fs; - SwapSpecific* fs_info; - PedGeometry* probed_geom; - PedSector length; - - fs = swap_open (geom); - if (!fs) - goto error; - fs_info = SWAP_SPECIFIC (fs); - - if (fs_info->version) - length = fs_info->page_sectors * fs_info->page_count; - else - length = geom->length; - probed_geom = ped_geometry_new (geom->dev, geom->start, length); - if (!probed_geom) - goto error_close_fs; - swap_close (fs); - return probed_geom; - -error_close_fs: - swap_close (fs); -error: - return NULL; -} - -#ifndef DISCOVER_ONLY -static int -swap_clobber (PedGeometry* geom) -{ - PedFileSystem* fs; - char buf[512]; - - fs = swap_open (geom); - if (!fs) - return 1; - - memset (buf, 0, 512); - if (!ped_geometry_write (geom, buf, getpagesize() / 512 - 1, 1)) - goto error_close_fs; - - swap_close (fs); - return 1; - -error_close_fs: - swap_close (fs); - - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static void -swap_init (PedFileSystem* fs, int fresh) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - - fs_info->page_sectors = getpagesize () / 512; - fs_info->page_count = fs->geom->length / fs_info->page_sectors; - fs_info->version = 1; - fs_info->max_bad_pages = (getpagesize() - - sizeof (SwapNewHeader)) / 4; - - if (fresh) - memset (fs_info->header, 0, getpagesize()); - else - ped_geometry_read (fs->geom, fs_info->header, - 0, fs_info->page_sectors); -} - -static PedFileSystem* -swap_alloc (PedGeometry* geom) -{ - PedFileSystem* fs; - SwapSpecific* fs_info; - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) - goto error; - - fs->type_specific = (SwapSpecific*) ped_malloc (sizeof (SwapSpecific)); - if (!fs->type_specific) - goto error_free_fs; - - fs_info = SWAP_SPECIFIC (fs); - fs_info->header = ped_malloc (getpagesize()); - if (!fs_info->header) - goto error_free_type_specific; - - fs_info = SWAP_SPECIFIC (fs); - fs_info->buffer_size = getpagesize() * BUFFER_SIZE; - fs_info->buffer = ped_malloc (fs_info->buffer_size); - if (!fs_info->buffer) - goto error_free_header; - - fs->geom = ped_geometry_duplicate (geom); - if (!fs->geom) - goto error_free_buffer; - fs->type = &swap_type; - return fs; - -error_free_buffer: - ped_free (fs_info->buffer); -error_free_header: - ped_free (fs_info->header); -error_free_type_specific: - ped_free (fs->type_specific); -error_free_fs: - ped_free (fs); -error: - return NULL; -} - -static void -swap_free (PedFileSystem* fs) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - - ped_free (fs_info->buffer); - ped_free (fs_info->header); - ped_free (fs->type_specific); - - ped_geometry_destroy (fs->geom); - ped_free (fs); -} - -static PedFileSystem* -swap_open (PedGeometry* geom) -{ - PedFileSystem* fs; - SwapSpecific* fs_info; - const char* sig; - - fs = swap_alloc (geom); - if (!fs) - goto error; - swap_init (fs, 0); - - fs_info = SWAP_SPECIFIC (fs); - if (!ped_geometry_read (fs->geom, fs_info->header, 0, - fs_info->page_sectors)) - goto error_free_fs; - - sig = ((char*) fs_info->header) + getpagesize() - 10; - if (strncmp (sig, "SWAP-SPACE", 10) == 0) { - fs_info->version = 0; - fs_info->page_count - = PED_MIN (fs->geom->length / fs_info->page_sectors, - 8 * (getpagesize() - 10)); - } else if (strncmp (sig, "SWAPSPACE2", 10) == 0) { - fs_info->version = 1; - fs_info->page_count = fs_info->header->new.last_page; - } else if (strncmp (sig, "S1SUSPEND", 9) == 0) { - fs_info->version = -1; - } else { - char _sig [11]; - - memcpy (_sig, sig, 10); - _sig [10] = 0; - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Unrecognised linux swap signature '%10s'."), _sig); - goto error_free_fs; - } - - fs->checked = 1; - return fs; - -error_free_fs: - swap_free (fs); -error: - return NULL; -} - -static int -swap_close (PedFileSystem* fs) -{ - swap_free (fs); - return 1; -} - -#ifndef DISCOVER_ONLY -static int -swap_new_find_bad_page (PedFileSystem* fs, unsigned int page) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - unsigned int i; - - for (i=0; i < fs_info->header->new.nr_badpages; i++) { - if (fs_info->header->new.badpages [i] == page) - return i; - } - - return 0; -} - -static int -swap_new_remove_bad_page (PedFileSystem* fs, unsigned int page) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - unsigned int pos; - - pos = swap_new_find_bad_page (fs, page); - if (!pos) - return 0; - - for (; pos < fs_info->header->new.nr_badpages; pos++) { - fs_info->header->new.badpages [pos - 1] - = fs_info->header->new.badpages [pos]; - } - - return 1; -} - -static int -swap_mark_page (PedFileSystem* fs, unsigned int page, int ok) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - char* ptr; - unsigned int mask; - - if (fs_info->version == 0) { - ptr = &fs_info->header->old.page_map [page/8]; - mask = 1 << (page%8); - *ptr = (*ptr & ~mask) + ok * mask; - } else { - if (ok) { - if (swap_new_remove_bad_page (fs, page)) - fs_info->header->new.nr_badpages--; - } else { - if (swap_new_find_bad_page (fs, page)) - return 1; - - if (fs_info->header->new.nr_badpages - > fs_info->max_bad_pages) { - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Too many bad pages.")); - return 0; - } - - fs_info->header->new.badpages - [fs_info->header->new.nr_badpages] = page; - fs_info->header->new.nr_badpages++; - } - } - - return 1; -} - -static void -swap_clear_pages (PedFileSystem* fs) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - unsigned int i; - - for (i = 1; i < fs_info->page_count; i++) { - swap_mark_page (fs, i, 1); - } - - if (fs_info->version == 0) { - for (; i < 1024; i++) { - swap_mark_page (fs, i, 0); - } - } -} - -static int -swap_check_pages (PedFileSystem* fs, PedTimer* timer) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - PedSector result; - int first_page = 1; - int stop_page = 0; - int last_page = fs_info->page_count - 1; - PedTimer* nested_timer; - - ped_timer_reset (timer); - ped_timer_set_state_name (timer, _("checking for bad blocks")); - - swap_clear_pages (fs); - while (first_page <= last_page) { - nested_timer = ped_timer_new_nested ( - timer, - 1.0 * (last_page - first_page) / last_page); - result = ped_geometry_check ( - fs->geom, - fs_info->buffer, - fs_info->buffer_size / 512, - first_page * fs_info->page_sectors, - fs_info->page_sectors, - (last_page - first_page + 1) - * fs_info->page_sectors, - nested_timer); - ped_timer_destroy_nested (nested_timer); - if (!result) - return 1; - stop_page = result / fs_info->page_sectors; - if (!swap_mark_page (fs, stop_page, 0)) - return 0; - first_page = stop_page + 1; - } - return 1; -} - -static int -swap_write (PedFileSystem* fs) -{ - SwapSpecific* fs_info = SWAP_SPECIFIC (fs); - char* sig = ((char*) fs_info->header) + getpagesize() - 10; - - if (fs_info->version == 0) { - memcpy (sig, "SWAP-SPACE", 10); - } else { - fs_info->header->new.version = 1; - fs_info->header->new.last_page = fs_info->page_count - 1; - fs_info->header->new.nr_badpages = 0; - memcpy (sig, "SWAPSPACE2", 10); - } - - return ped_geometry_write (fs->geom, fs_info->header, 0, - fs_info->page_sectors); -} - -static PedFileSystem* -swap_create (PedGeometry* geom, PedTimer* timer) -{ - PedFileSystem* fs; - - fs = swap_alloc (geom); - if (!fs) - goto error; - swap_init (fs, 1); - if (!swap_write (fs)) - goto error_free_fs; - return fs; - -error_free_fs: - swap_free (fs); -error: - return NULL; -} - -static int -swap_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - PedGeometry* old_geom = fs->geom; - - fs->geom = ped_geometry_duplicate (geom); - swap_init (fs, old_geom->start != geom->start); - if (!swap_write (fs)) - goto error; - ped_geometry_destroy (old_geom); - return 1; - -error: - ped_geometry_destroy (fs->geom); - fs->geom = old_geom; - return 0; -} - -static PedFileSystem* -swap_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - return ped_file_system_create (geom, &swap_type, timer); -} - -static int -swap_check (PedFileSystem* fs, PedTimer* timer) -{ - return swap_check_pages (fs, timer) - && swap_write (fs); -} - -static PedConstraint* -swap_get_create_constraint (const PedDevice* dev) -{ - PedGeometry full_dev; - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - return ped_constraint_new (ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - getpagesize() / 512, dev->length); -} - -static PedConstraint* -swap_get_resize_constraint (const PedFileSystem* fs) -{ - return swap_get_create_constraint (fs->geom->dev); -} - -static PedConstraint* -swap_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev) -{ - return swap_get_create_constraint (dev); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps swap_ops = { - .probe = swap_probe, -#ifndef DISCOVER_ONLY - .clobber = swap_clobber, - .open = swap_open, - .create = swap_create, - .close = swap_close, - .check = swap_check, - .copy = swap_copy, - .resize = swap_resize, - .get_create_constraint = swap_get_create_constraint, - .get_resize_constraint = swap_get_resize_constraint, - .get_copy_constraint = swap_get_copy_constraint -#else - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -#endif /* !DISCOVER_ONLY */ -}; - -static PedFileSystemType swap_type = { - .next = NULL, - .ops = &swap_ops, - .name = "linux-swap", - .block_sizes = LINUXSWAP_BLOCK_SIZES -}; - -void -ped_file_system_linux_swap_init () -{ - ped_file_system_type_register (&swap_type); -} - -void -ped_file_system_linux_swap_done () -{ - ped_file_system_type_unregister (&swap_type); -} - diff --git a/usr/src/lib/libparted/common/libparted/fs/ntfs/ntfs.c b/usr/src/lib/libparted/common/libparted/fs/ntfs/ntfs.c deleted file mode 100644 index 963be7c9c8..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ntfs/ntfs.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include -#include /* for PATH_MAX */ - -#define NTFS_BLOCK_SIZES ((int[2]){512, 0}) - -#define NTFS_SIGNATURE "NTFS" - -#define NTFSRESIZE_CMD_PATH "ntfsresize" -#define NTFSCREATE_CMD_PATH "mkntfs" -#define NTFSFIX_CMD_PATH "ntfsfix" -#define NTFSCLONE_CMD_PATH "ntfsclone" - -static PedFileSystemType ntfs_type; - -static char bigbuf[128*1024]; /* for command output storage */ - -static PedGeometry* -ntfs_probe (PedGeometry* geom) -{ - char buf[512]; - - PED_ASSERT(geom != NULL, return 0); - - if (!ped_geometry_read (geom, buf, 0, 1)) - return 0; - - if (strncmp (NTFS_SIGNATURE, buf + 3, strlen (NTFS_SIGNATURE)) == 0) - return ped_geometry_new (geom->dev, geom->start, - PED_LE64_TO_CPU (*(uint64_t*) - (buf + 0x28))); - else - return NULL; -} - -#ifndef DISCOVER_ONLY -static int -ntfs_clobber (PedGeometry* geom) -{ - char buf[512]; - - PED_ASSERT(geom != NULL, return 0); - - memset (buf, 0, sizeof(buf)); - return ped_geometry_write (geom, buf, 0, 1); -} - -static PedFileSystem* -ntfs_open (PedGeometry* geom) -{ - PedFileSystem* fs; - - PED_ASSERT(geom != NULL, return 0); - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) - return NULL; - - fs->type = &ntfs_type; - fs->geom = ped_geometry_duplicate (geom); - fs->checked = 1; /* XXX */ - fs->type_specific = NULL; - - return fs; -} - -/* - * Returns partition number (1..4) that contains geom, 0 otherwise. - */ -static int -_get_partition_num_by_geom(const PedGeometry* geom) -{ - PedDisk *disk; - PedPartition *part; - int partnum = 0; - - PED_ASSERT(geom != NULL, return 0); - - disk = ped_disk_new (geom->dev); - if (!disk) { - printf("_get_partition_num_by_geom: ped_disk_new failed!\n"); - } - else { - part = ped_disk_get_partition_by_sector (disk, geom->start); - if (part == NULL) { - printf("_get_partition_num_by_geom: " - "ped_disk_get_partition_by_sector failed!\n"); - } - else { - if (part->num > 0) - partnum = part->num; - } - ped_disk_destroy (disk); - } - return partnum; -} - -/* - * return the partition device name for geom in partpath. - * return 1 on success, 0 on failure. - */ -static int -_get_part_device_path(const PedGeometry* geom, char *partpath, const int len) -{ - int partnum; - - PED_ASSERT(geom != NULL, return 0); - PED_ASSERT(partpath != NULL, return 0); - - partnum = _get_partition_num_by_geom(geom); - if (!partnum) - return 0; - - strncpy(partpath, geom->dev->path, len); - /* - * XXX Solaris specific - * Create the path name to the *pn device, where n is the partition # - * geom->dev->path looks like this: "/devices/.../cmdk@0,0:q" - * or like this: "/dev/dsk/...p0" - * ":q" is the "/dev/dsk/...p0" device - * :r is p1, :s is p2, :t is p3, :u is p4 - * 'q' + 1 == 'r' - * '0' + 1 == '1' - */ - partpath[strlen(partpath) -1] += partnum; - - return 1; -} - -/* - * Executes cmd in a pipe. - * Returns -1 on popen failure or the return value from pclose. - * Saves the output from cmd in bigbuf for later display. - */ -static int -_execute(const char *cmd) -{ - FILE *fp; - char buf[512]; - int szbigbuf; - - PED_ASSERT(cmd != NULL, return 0); - - fp = popen(cmd, "r"); - if (fp == NULL) - return -1; - - strcpy(bigbuf, ""); - szbigbuf = sizeof(bigbuf) -1; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (szbigbuf > 0) { - strncat(bigbuf, buf, szbigbuf); - szbigbuf -= strlen(buf); - } - } - - return pclose(fp); -} - -/* - * ./mkntfs -f -s 512 -S 63 -H 255 -p 0 /dev/dsk/c0d0p1 - * Returns new fs on success, NULL on failure. - */ -PedFileSystem* -ntfs_create (PedGeometry* geom, PedTimer* timer) -{ - int x; - PedFileSystem* fs = NULL; - char partpath[PATH_MAX]; - char cmd[PATH_MAX]; - - PED_ASSERT(geom != NULL, return 0); - PED_ASSERT(timer != NULL, return 0); - - ped_timer_reset (timer); - ped_timer_update (timer, 0.0); - ped_timer_set_state_name(timer, _("creating")); - - if (_get_part_device_path(geom, partpath, sizeof(partpath)) == 0) - goto error; - - snprintf(cmd, sizeof(cmd), "%s -f -s %lld -S %d -H %d -p %lld %s", - NTFSCREATE_CMD_PATH, - geom->dev->sector_size, - geom->dev->hw_geom.sectors, - geom->dev->hw_geom.heads, - (PedSector) 0, /* partition start sector */ - partpath); - printf("%s\n", cmd); - - /* - * Use system() so the output that shows progress is displayed. - */ - ped_device_begin_external_access(geom->dev); - x = system(cmd); - ped_device_end_external_access(geom->dev); - - if (x != 0) { - goto error; - } - - fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem)); - if (!fs) - goto error; - fs->type = &ntfs_type; - fs->geom = ped_geometry_duplicate (geom); - fs->checked = 1; /* XXX */ - fs->type_specific = NULL; - -error: - ped_timer_update (timer, 1.0); - return fs; -} - -/* - * Returns 1 on success, 0 on failure. - */ -static int -ntfs_close (PedFileSystem *fs) -{ - PED_ASSERT(fs != NULL, return 0); - - ped_geometry_destroy (fs->geom); - ped_free (fs); - - return 1; -} - -/* - * ntfsfix /dev/dsk/c0d0p1 - * Returns 1 on success, 0 on failure. - */ -static int -ntfs_check(PedFileSystem *fs, PedTimer *timer) -{ - int x; - int ret = 0; - char partpath[PATH_MAX]; - char cmd[PATH_MAX]; - - PED_ASSERT(fs != NULL, return 0); - PED_ASSERT(timer != NULL, return 0); - - ped_timer_reset(timer); - ped_timer_set_state_name(timer, _("checking")); - ped_timer_update(timer, 0.0); - - if (_get_part_device_path(fs->geom, partpath, sizeof(partpath)) == 0) - goto error; - - snprintf(cmd, sizeof(cmd), "%s %s", - NTFSFIX_CMD_PATH, partpath); - printf("%s\n", cmd); - - /* - * Use system() so the output that shows progress is displayed. - */ - ped_device_begin_external_access(fs->geom->dev); - x = system(cmd); - ped_device_end_external_access(fs->geom->dev); - - if (x == 0) { - ret = 1; /* return success to the upper layer */ - } - else { - goto error; - } - -error: - ped_timer_update(timer, 1.0); - return ret; -} - -/* - * Copy from source fs to destination geom. - * The destination partition must alreay exist. - * ntfsclone --overwrite destination-device source-device - * Returns new fs on success, NULL on failure. - */ -static PedFileSystem* -ntfs_copy(const PedFileSystem *fs, PedGeometry *geom, PedTimer *timer) -{ - int x; - char spartpath[PATH_MAX]; - char dpartpath[PATH_MAX]; - char cmd[PATH_MAX]; - PedFileSystem *new_fs = NULL; - - PED_ASSERT(fs != NULL, return 0); - PED_ASSERT(geom != NULL, return 0); - PED_ASSERT(timer != NULL, return 0); - - ped_timer_reset(timer); - ped_timer_set_state_name(timer, _("copying")); - ped_timer_update(timer, 0.0); - - if (_get_part_device_path(fs->geom, spartpath, sizeof(spartpath)) == 0) - goto error; - - if (_get_part_device_path(geom, dpartpath, sizeof(dpartpath)) == 0) - goto error; - - snprintf(cmd, sizeof(cmd), "%s --overwrite %s %s", - NTFSCLONE_CMD_PATH, dpartpath, spartpath); - printf("%s\n", cmd); - - /* - * Use system() so the output that shows progress is displayed. - */ - ped_device_begin_external_access(geom->dev); - x = system(cmd); - ped_device_end_external_access(geom->dev); - - if (x != 0) { - goto error; - } - - if (!(new_fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) - goto error; - - new_fs->type = &ntfs_type; - new_fs->geom = ped_geometry_duplicate(geom); - new_fs->checked = 0; - new_fs->type_specific = NULL; - -error: - ped_timer_update(timer, 1.0); - return new_fs; -} - -/* - * fs->geom has the current filesystem size in sectors. - * geom has the new, requested filesystem size in sectors. - * - * fs->geom->dev is the same object as geom->dev. - * geom->dev->path looks like this: - * /dev/dsk/...p0 - * or this: - * /devices/.../cmdk@0,0:q - * - * The ntfsresize cmd wants the block disk device, not the raw one. - * It also wants the partition device, not the whole disk. - * - * Returns 1 on success, 0 on failure. - */ -static int -ntfs_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer) -{ - int x; - int ret = 0; /* this tells the upper layer NOT to resize partition */ - char partpath[PATH_MAX]; - char cmd[PATH_MAX]; - - PED_ASSERT(fs != NULL, return 0); - PED_ASSERT(geom != NULL, return 0); - PED_ASSERT(timer != NULL, return 0); - - if (fs->geom->start != geom->start) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Sorry, can't move the start of " - "ntfs partitions yet.")); - return 0; - } - - ped_timer_reset (timer); - ped_timer_update (timer, 0.0); - - if (fs->geom->length > geom->length) { - ped_timer_set_state_name(timer, _("shrinking")); - } - else if (fs->geom->length < geom->length) { - ped_timer_set_state_name(timer, _("enlarging")); - } - else { - ped_timer_set_state_name(timer, _("no change")); - } - - if (_get_part_device_path(fs->geom, partpath, sizeof(partpath)) == 0) - goto error1; - - ped_device_begin_external_access(geom->dev); - - /* - * ntfsresize -f says don't worry about consistency flag - */ - snprintf(cmd, sizeof(cmd), "%s -f -i %s", - NTFSRESIZE_CMD_PATH, partpath); - printf("%s\n", cmd); - x = _execute(cmd); - if (x != 0) { - printf("ntfsresize had this message:\n%s\n", bigbuf); - goto error2; - } - - snprintf(cmd, sizeof(cmd), "%s -f -n -s %lld %s", - NTFSRESIZE_CMD_PATH, - geom->length * geom->dev->sector_size, partpath); - printf("%s\n", cmd); - x = _execute(cmd); - if (x != 0) { - printf("ntfsresize had this message:\n%s\n", bigbuf); - goto error2; - } - - /* - * ntfsresize -f -f means don't ask "Are you sure?" - * Use system() so the output that shows progress is displayed. - */ - snprintf(cmd, sizeof(cmd), "%s -f -f -s %lld %s", - NTFSRESIZE_CMD_PATH, - geom->length * geom->dev->sector_size, partpath); - printf("%s\n", cmd); - x = system(cmd); - if (x == 0) { - ret = 1; /* this tells upper layer to resize the partition */ - } - else { - goto error2; - } - -error2: - ped_device_end_external_access(geom->dev); -error1: - ped_timer_update (timer, 1.0); - return ret; -} - -/* - * return the minimum resize size from the ntfsresize external cmd - * in blocks, 0 on error. - * Saves the output from cmd in bigbuf for later display. - */ -static PedSector -_get_min_from_ntfsresize(const char *cmd) -{ - FILE *fp; - char buf[512]; - PedSector size = 0; - int x; - int szbigbuf; - - PED_ASSERT(cmd != NULL, return 0); - - fp = popen(cmd, "r"); - if (fp == NULL) - return 0; - - strcpy(bigbuf, ""); - szbigbuf = sizeof(bigbuf) -1; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (szbigbuf > 0) { - strncat(bigbuf, buf, szbigbuf); - szbigbuf -= strlen(buf); - } - x = sscanf(buf, "You might resize at %lld", &size); - if (x > 0) - break; - } - - pclose(fp); - return size; -} - -/* - * return the minimum resize size in blocks, fs->geom->length on error. - */ -static PedSector -_get_min_resize_size (const PedFileSystem* fs) -{ - PedSector max_length = fs->geom->length; - PedSector length; - char partpath[PATH_MAX]; - char cmd[PATH_MAX]; - - PED_ASSERT(fs != NULL, return 0); - - if (_get_part_device_path(fs->geom, partpath, sizeof(partpath)) == 0) - return max_length; - - snprintf(cmd, sizeof(cmd), "%s -f -i %s", - NTFSRESIZE_CMD_PATH, partpath); - - length = _get_min_from_ntfsresize(cmd); - if (length == 0) { - printf("ntfsresize had this message:\n%s\n", bigbuf); - return max_length; - } - - return (length / fs->geom->dev->sector_size); -} - -PedConstraint* -ntfs_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev) -{ - PedGeometry full_dev; - - PED_ASSERT(fs != NULL, return 0); - PED_ASSERT(dev != NULL, return 0); - - if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1)) - return NULL; - - return ped_constraint_new (ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - _get_min_resize_size (fs), - dev->length); -} - -PedConstraint* -ntfs_get_resize_constraint (const PedFileSystem* fs) -{ - PED_ASSERT(fs != NULL, return 0); - - return ntfs_get_copy_constraint (fs, fs->geom->dev); -} - -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps ntfs_ops = { - .probe = ntfs_probe, -#ifndef DISCOVER_ONLY - .clobber = ntfs_clobber, - .open = ntfs_open, - .create = ntfs_create, - .close = ntfs_close, - .check = ntfs_check, - .copy = ntfs_copy, - .resize = ntfs_resize, - .get_create_constraint = NULL, - .get_resize_constraint = ntfs_get_resize_constraint, - .get_copy_constraint = ntfs_get_copy_constraint -#else - .clobber = NULL, - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -#endif -}; - -static PedFileSystemType ntfs_type = { - .next = NULL, - .ops = &ntfs_ops, - .name = "ntfs", - .block_sizes = NTFS_BLOCK_SIZES -}; - -void -ped_file_system_ntfs_init () -{ - ped_file_system_type_register (&ntfs_type); -} - -void -ped_file_system_ntfs_done () -{ - ped_file_system_type_unregister (&ntfs_type); -} - - diff --git a/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.c b/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.c deleted file mode 100644 index 0e52e6a3c5..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - geom_dal.c -- parted device abstraction layer - Copyright (C) 2001, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#if (DYNAMIC_LOADING || HAVE_LIBREISERFS) && !DISCOVER_ONLY - -#include "geom_dal.h" - -#include -#include - -static blk_t __len(dal_t *dal) { - PED_ASSERT(dal != NULL, return 0); - - return ((PedGeometry *)dal->dev)->length / - (dal->block_size / PED_SECTOR_SIZE_DEFAULT); -} - -static int __read(dal_t *dal, void *buff, blk_t block, blk_t count) { - blk_t k; - PedSector block_pos; - PedSector block_count; - - PED_ASSERT(dal != NULL, return 0); - - k = dal->block_size / PED_SECTOR_SIZE_DEFAULT; - block_pos = (PedSector)(block * k); - block_count = (PedSector)(count * k); - - return ped_geometry_read((PedGeometry *)dal->dev, buff, block_pos, block_count); -} - -static int __write(dal_t *dal, void *buff, blk_t block, blk_t count) { - blk_t k; - PedSector block_pos; - PedSector block_count; - - PED_ASSERT(dal != NULL, return 0); - - k = dal->block_size / PED_SECTOR_SIZE_DEFAULT; - block_pos = (PedSector)(block * k); - block_count = (PedSector)(count * k); - - return ped_geometry_write((PedGeometry *)dal->dev, buff, block_pos, - block_count); -} - -static int __sync(dal_t *dal) { - PED_ASSERT(dal != NULL, return 0); - return ped_geometry_sync((PedGeometry *)dal->dev); -} - -static int __flags(dal_t *dal) { - PED_ASSERT(dal != NULL, return 0); - return dal->flags; -} - -static int __equals(dal_t *dal1, dal_t *dal2) { - PED_ASSERT(dal1 != NULL, return 0); - PED_ASSERT(dal2 != NULL, return 0); - - return ped_geometry_test_equal((PedGeometry *)dal1->dev, - (PedGeometry *)dal2->dev); -} - -static int __stat(dal_t *dal, struct stat *st) { - - PED_ASSERT(dal != NULL, return 0); - PED_ASSERT(st != NULL, return 0); - - if (stat(((PedGeometry *)dal->dev)->dev->path, st)) - return 0; - - return 1; -} - -static dev_t __dev(dal_t *dal) { - struct stat st; - - if (!__stat(dal, &st)) - return (dev_t)0; - - return st.st_dev; -} - -static struct dal_ops ops = { - __len, __read, __write, __sync, - __flags, __equals, __stat, __dev -}; - -dal_t *geom_dal_create(PedGeometry *geom, size_t block_size, int flags) { - dal_t *dal; - - if (!geom) - return NULL; - - if (!(dal = ped_malloc(sizeof(dal_t)))) - return NULL; - - dal->ops = &ops; - dal->dev = geom; - dal->block_size = block_size; - dal->flags = flags; - dal->len = 0; - - return dal; -} - -int geom_dal_reopen(dal_t *dal, int flags) { - - if (!dal) return 0; - dal->flags = flags; - - return 1; -} - -void geom_dal_free(dal_t *dal) { - PED_ASSERT(dal != NULL, return); - ped_free(dal); -} - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.h b/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.h deleted file mode 100644 index f79cb8c01d..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - geom_dal.h -- parted device abstraction layer - Copyright (C) 2001, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef GEOM_DAL_H -#define GEOM_DAL_H - -#include - -#if DYNAMIC_LOADING || !DISCOVER_ONLY - -#include - -typedef unsigned long blk_t; - -struct dal_ops; - -struct _dal { - struct dal_ops *ops; - const void *dev; - size_t block_size; - int flags; - void *data; - blk_t len; -}; - -typedef struct _dal dal_t; - -struct dal_ops { - blk_t (*len)(dal_t *); - int (*read)(dal_t *, void *, blk_t, blk_t); - int (*write)(dal_t *, void *, blk_t, blk_t); - int (*sync)(dal_t *); - int (*flags)(dal_t *); - int (*equals)(dal_t *, dal_t *); - int (*stat)(dal_t *, struct stat *); - dev_t (*dev)(dal_t *); -}; - -extern dal_t *geom_dal_create(PedGeometry *geom, size_t block_size, int flags); -extern int geom_dal_reopen(dal_t *dal, int flags); -extern void geom_dal_free(dal_t *dal); - -#endif - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.c b/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.c deleted file mode 100644 index e624193372..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.c +++ /dev/null @@ -1,866 +0,0 @@ -/* - reiserfs.c -- libparted / libreiserfs glue - Copyright (C) 2001, 2002, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - This is all rather complicated. There are a few combinations: - * shared libraries full support - * dynamic libraries present full support (via dlopen) - * dynamic libraries absent (full support disabled) (via dlopen) - * discover only - - We'd love to hear comments... - - So far, we've opted for maximum flexibility for the user. Is it - all worth it? -*/ - -#include - -#if (HAVE_LIBREISERFS || DYNAMIC_LOADING) && !DISCOVER_ONLY -# define REISER_FULL_SUPPORT -#endif - -#include -#include -#include - -#ifdef DYNAMIC_LOADING -# include -#endif - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif - -#include "reiserfs.h" -#include "geom_dal.h" - -#define REISERFS_BLOCK_SIZES ((int[2]){512, 0}) - -static PedSector reiserfs_super_offset[] = { 128, 16, -1 }; -static PedFileSystemType* reiserfs_type; - -#ifdef DYNAMIC_LOADING -# define FPTR * -# define FCLASS static -#else -# define FPTR -# define FCLASS extern -#endif - -#ifdef DYNAMIC_LOADING - -static int libreiserfs_present; - -static void *libdal_handle; -static void *libreiserfs_handle; - -#endif /* DYNAMIC_LOADING */ - -#ifdef REISER_FULL_SUPPORT - -FCLASS blk_t (FPTR reiserfs_fs_probe) (dal_t *); - -FCLASS int (FPTR libreiserfs_exception_type) (reiserfs_exception_t *); -FCLASS int (FPTR libreiserfs_exception_option) (reiserfs_exception_t *); -FCLASS char *(FPTR libreiserfs_exception_message) (reiserfs_exception_t *); -FCLASS void (FPTR libreiserfs_exception_set_handler) - (int(FPTR)(reiserfs_exception_t *)); - -FCLASS void (FPTR dal_realize) (dal_t *); -FCLASS size_t (FPTR dal_block_size) (dal_t *); -FCLASS blk_t (FPTR dal_len) (dal_t *); -FCLASS int (FPTR dal_flags) (dal_t *); - -FCLASS reiserfs_fs_t* (FPTR reiserfs_fs_open) (dal_t *, dal_t *); -FCLASS reiserfs_fs_t* (FPTR reiserfs_fs_create) (dal_t *, dal_t *, - blk_t, blk_t, blk_t, size_t, - int, int, const char *, - const char *, blk_t, - reiserfs_gauge_t *); - -FCLASS int (FPTR reiserfs_fs_resize) (reiserfs_fs_t *, blk_t, reiserfs_gauge_t *); -#ifdef HAVE_REISERFS_FS_CHECK -FCLASS int (FPTR reiserfs_fs_check) (reiserfs_fs_t *, reiserfs_gauge_t *); -#endif - -FCLASS reiserfs_fs_t *(FPTR reiserfs_fs_copy) (reiserfs_fs_t *, dal_t *, - reiserfs_gauge_t *); - -FCLASS int (FPTR reiserfs_fs_clobber) (dal_t *); -FCLASS void (FPTR reiserfs_fs_close) (reiserfs_fs_t *); - -FCLASS int (FPTR reiserfs_fs_is_resizeable) (reiserfs_fs_t *); -FCLASS int (FPTR reiserfs_fs_is_consistent) (reiserfs_fs_t *); - -FCLASS blk_t (FPTR reiserfs_fs_min_size) (reiserfs_fs_t *); -FCLASS blk_t (FPTR reiserfs_fs_block_size) (reiserfs_fs_t *); -FCLASS dal_t* (FPTR reiserfs_fs_host_dal) (reiserfs_fs_t *); - -FCLASS blk_t (FPTR reiserfs_fs_bitmap_used) (reiserfs_fs_t *); -FCLASS int (FPTR reiserfs_fs_bitmap_check) (reiserfs_fs_t *); - -FCLASS reiserfs_gauge_t *(FPTR libreiserfs_gauge_create) ( - char *, reiserfs_gauge_handler_t, void *); - -FCLASS void (FPTR libreiserfs_gauge_free) (reiserfs_gauge_t *); - -static void gauge_handler(const char *name, unsigned int value, void *data, - int determined, int update_header, - int update_footer) -{ - PedTimer *timer = (PedTimer *) data; - ped_timer_set_state_name(timer, name); - ped_timer_update(timer, 1.0 * value / 100); -} - -static PedExceptionOption -exopt_libreiserfs_to_parted(reiserfs_exception_option_t option) -{ - switch (option) { - case EXCEPTION_UNHANDLED: - return PED_EXCEPTION_UNHANDLED; - case EXCEPTION_FIX: - return PED_EXCEPTION_FIX; - case EXCEPTION_YES: - return PED_EXCEPTION_YES; - case EXCEPTION_NO: - return PED_EXCEPTION_NO; - case EXCEPTION_OK: - return PED_EXCEPTION_OK; - case EXCEPTION_RETRY: - return PED_EXCEPTION_RETRY; - case EXCEPTION_IGNORE: - return PED_EXCEPTION_IGNORE; - case EXCEPTION_CANCEL: - return PED_EXCEPTION_CANCEL; - - default: - return PED_EXCEPTION_UNHANDLED; - } -} - -static PedExceptionType -extype_libreiserfs_to_parted(reiserfs_exception_type_t type) -{ - switch (type) { - case EXCEPTION_INFORMATION: - return PED_EXCEPTION_INFORMATION; - case EXCEPTION_WARNING: - return PED_EXCEPTION_WARNING; - case EXCEPTION_ERROR: - return PED_EXCEPTION_ERROR; - case EXCEPTION_FATAL: - return PED_EXCEPTION_FATAL; - case EXCEPTION_BUG: - return PED_EXCEPTION_BUG; - case EXCEPTION_NO_FEATURE: - return PED_EXCEPTION_NO_FEATURE; - - default: - return PED_EXCEPTION_NO_FEATURE; - } -} - -static int exception_handler(reiserfs_exception_t *exception) -{ - int ex_type = libreiserfs_exception_type(exception); - int ex_option = libreiserfs_exception_option(exception); - char *ex_message = libreiserfs_exception_message(exception); - - return ped_exception_throw (extype_libreiserfs_to_parted (ex_type), - exopt_libreiserfs_to_parted (ex_option), - ex_message); -} -#endif /* REISER_FULL_SUPPORT */ - -static PedGeometry *reiserfs_probe(PedGeometry *geom) -{ - int i; - reiserfs_super_block_t sb; - - PED_ASSERT(geom != NULL, return NULL); - - for (i = 0; reiserfs_super_offset[i] != -1; i++) { - if (reiserfs_super_offset[i] >= geom->length) - continue; - if (!ped_geometry_read (geom, &sb, reiserfs_super_offset[i], 1)) - continue; - - if (strncmp(REISERFS_SIGNATURE, sb.s_magic, - strlen(REISERFS_SIGNATURE)) == 0 - || strncmp(REISER2FS_SIGNATURE, sb.s_magic, - strlen(REISER2FS_SIGNATURE)) == 0 - || strncmp(REISER3FS_SIGNATURE, sb.s_magic, - strlen(REISER3FS_SIGNATURE)) == 0) { - PedSector block_size; - PedSector block_count; - - block_size = PED_LE16_TO_CPU(sb.s_blocksize) - / PED_SECTOR_SIZE_DEFAULT; - block_count = PED_LE32_TO_CPU(sb.s_block_count); - - return ped_geometry_new(geom->dev, geom->start, - block_size * block_count); - } - } - return NULL; -} - -#ifndef DISCOVER_ONLY -static int reiserfs_clobber(PedGeometry *geom) -{ - int i; - char buf[512]; - - PED_ASSERT(geom != NULL, return 0); - - memset(buf, 0, 512); - for (i = 0; reiserfs_super_offset[i] != -1; i++) { - if (reiserfs_super_offset[i] >= geom->length) - continue; - if (!ped_geometry_write - (geom, buf, reiserfs_super_offset[i], 1)) - return 0; - } - return 1; -} -#endif /* !DISCOVER_ONLY */ - -#ifdef REISER_FULL_SUPPORT - -static PedFileSystem *reiserfs_open(PedGeometry *geom) -{ - PedFileSystem *fs; - PedGeometry *fs_geom; - dal_t *dal; - reiserfs_fs_t *fs_info; - - PED_ASSERT(geom != NULL, return NULL); - - if (!(fs_geom = ped_geometry_duplicate(geom))) - goto error; - - if (! (dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDONLY))) - goto error_fs_geom_free; - - /* - We are passing NULL as DAL for journal. Therefore we let libreiserfs know, - that journal not available and parted will be working fine for reiserfs - with relocated journal too. - */ - if (!(fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) - goto error_free_dal; - - if (!(fs_info = reiserfs_fs_open(dal, NULL))) - goto error_free_fs; - - fs->type = reiserfs_type; - fs->geom = fs_geom; - fs->type_specific = (void *) fs_info; - - return fs; - -error_free_fs: - ped_free(fs); -error_free_dal: - geom_dal_free(dal); -error_fs_geom_free: - ped_geometry_destroy(fs_geom); -error: - return NULL; -} - -static PedFileSystem *reiserfs_create(PedGeometry *geom, PedTimer *timer) -{ - dal_t *dal; - uuid_t uuid; - PedFileSystem *fs; - PedGeometry *fs_geom; - reiserfs_fs_t *fs_info; - reiserfs_gauge_t *gauge = NULL; - - PED_ASSERT(geom != NULL, return NULL); - - fs_geom = ped_geometry_duplicate(geom); - - if (!(dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDWR))) - goto error_fs_geom_free; - - memset(uuid, 0, sizeof(uuid)); - uuid_generate(uuid); - - ped_timer_reset(timer); - ped_timer_set_state_name(timer, _("creating")); - - if (libreiserfs_gauge_create && libreiserfs_gauge_free) { - if (! (gauge = - libreiserfs_gauge_create(NULL, gauge_handler, timer))) - goto error_free_dal; - } - - if (!(fs_info = reiserfs_fs_create(dal, dal, 0, JOURNAL_MAX_TRANS, - DEFAULT_JOURNAL_SIZE, - DEFAULT_BLOCK_SIZE, - FS_FORMAT_3_6, R5_HASH, NULL, - (char *) uuid, dal_len(dal), - gauge))) - goto error_free_gauge; - - ped_timer_update(timer, 1.0); - - if (gauge) - libreiserfs_gauge_free(gauge); - - if (!(fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) - goto error_free_fs_info; - - fs->type = reiserfs_type; - fs->geom = fs_geom; - fs->type_specific = (void *) fs_info; - - return fs; - -error_free_fs_info: - ped_free(fs_info); -error_free_gauge: - if (gauge) - libreiserfs_gauge_free(gauge); -error_free_dal: - geom_dal_free(dal); -error_fs_geom_free: - ped_geometry_destroy(fs_geom); - return NULL; -} - -static int reiserfs_close(PedFileSystem *fs) -{ - dal_t *dal; - - PED_ASSERT(fs != NULL, return 0); - - dal = reiserfs_fs_host_dal(fs->type_specific); - reiserfs_fs_close(fs->type_specific); - - geom_dal_free(dal); - ped_geometry_sync(fs->geom); - - ped_free(fs); - return 1; -} - -static PedConstraint *reiserfs_get_create_constraint(const PedDevice *dev) -{ - PedGeometry full_dev; - PedSector min_blks = (SUPER_OFFSET_IN_BYTES / DEFAULT_BLOCK_SIZE) - + 2 + DEFAULT_JOURNAL_SIZE + 1 + 100 + 1; - - if (!ped_geometry_init(&full_dev, dev, 0, dev->length - 1)) - return NULL; - - return ped_constraint_new(ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - min_blks * (DEFAULT_BLOCK_SIZE / 512), - dev->length); -} - -static int reiserfs_check(PedFileSystem *fs, PedTimer *timer) -{ - reiserfs_fs_t *fs_info; -#ifdef HAVE_REISERFS_FS_CHECK - reiserfs_gauge_t *gauge = NULL; -#endif - - PED_ASSERT(fs != NULL, return 0); - - fs_info = fs->type_specific; - - if (!reiserfs_fs_is_consistent(fs_info)) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The file system is in an invalid " - "state. Perhaps it is mounted?")); - return 0; - } - - if (!reiserfs_fs_is_resizeable(fs_info)) - ped_exception_throw(PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("The file system is in old " - "(unresizeable) format.")); - - if (!reiserfs_fs_bitmap_check(fs_info)) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Invalid free blocks count. Run " - "reiserfsck --check first.")); - return 0; - } - -#ifdef HAVE_REISERFS_FS_CHECK - ped_timer_reset(timer); - - if (libreiserfs_gauge_create && libreiserfs_gauge_free) { - if (! - (gauge = - libreiserfs_gauge_create(NULL, gauge_handler, timer))) - return 0; - } - - ped_timer_set_state_name(timer, _("checking")); - ped_timer_update(timer, 0.0); - - if (!reiserfs_fs_check(fs_info, gauge)) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Reiserfs tree seems to be corrupted. " - "Run reiserfsck --check first.")); - return 0; - } - - ped_timer_update(timer, 1.0); - - if (gauge) - libreiserfs_gauge_free(gauge); -#endif - - ped_exception_throw(PED_EXCEPTION_INFORMATION, PED_EXCEPTION_OK, - _("The reiserfs file system passed a basic check. " - "For a more comprehensive check, run " - "reiserfsck --check.")); - - return 1; -} - -static int reiserfs_resize(PedFileSystem *fs, PedGeometry *geom, - PedTimer *timer) -{ - dal_t *dal; - blk_t fs_len; - PedSector old_length; - reiserfs_fs_t *fs_info; - reiserfs_gauge_t *gauge = NULL; - - PED_ASSERT(fs != NULL, return 0); - - old_length = fs->geom->length; - - PED_ASSERT (fs->geom->dev == geom->dev, return 0); - - if (fs->geom->start != geom->start) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Sorry, can't move the start of " - "reiserfs partitions yet.")); - return 0; - } - - fs_info = fs->type_specific; - - fs_len = (blk_t) (geom->length / (reiserfs_fs_block_size(fs_info) / - PED_SECTOR_SIZE_DEFAULT)); - - dal = reiserfs_fs_host_dal(fs_info); - - if (dal_flags(dal) && O_RDONLY) { - if (!geom_dal_reopen(dal, O_RDWR)) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Couldn't reopen device " - "abstraction layer for " - "read/write.")); - return 0; - } - } - - ped_timer_reset(timer); - - if (libreiserfs_gauge_create && libreiserfs_gauge_free) { - if (! - (gauge = - libreiserfs_gauge_create(NULL, gauge_handler, timer))) - return 0; - } - - if (old_length > geom->length) { - - ped_timer_set_state_name(timer, _("shrinking")); - ped_timer_update(timer, 0.0); - - if (!reiserfs_fs_resize(fs_info, fs_len, gauge)) - goto error_free_gauge; - - ped_geometry_set_end (fs->geom, geom->end); - dal_realize(dal); - } else { - ped_geometry_set_end (fs->geom, geom->end); - dal_realize(dal); - - ped_timer_set_state_name(timer, _("expanding")); - ped_timer_update(timer, 0.0); - - if (!reiserfs_fs_resize(fs_info, fs_len, gauge)) - goto error_free_gauge; - } - - ped_timer_update(timer, 1.0); - - if (gauge) - libreiserfs_gauge_free(gauge); - - return 1; - -error_free_gauge: - if (gauge) - libreiserfs_gauge_free(gauge); - ped_geometry_set_end (fs->geom, fs->geom->start + old_length - 1); - return 0; -} - -static PedConstraint *reiserfs_get_resize_constraint(const PedFileSystem * - fs) -{ - PedDevice *dev; - PedSector min_size; - PedGeometry full_disk; - reiserfs_fs_t *fs_info; - PedAlignment start_align; - PedGeometry start_sector; - - PED_ASSERT(fs != NULL, return NULL); - - fs_info = fs->type_specific; - dev = fs->geom->dev; - - if (!ped_alignment_init(&start_align, fs->geom->start, 0)) - return NULL; - if (!ped_geometry_init(&full_disk, dev, 0, dev->length - 1)) - return NULL; - if (!ped_geometry_init(&start_sector, dev, fs->geom->start, 1)) - return NULL; - - /* - Minsize for reiserfs is area occupied by data blocks and - metadata blocks minus free space blocks and minus bitmap - blocks which describes free space blocks. - */ - min_size = reiserfs_fs_min_size(fs_info) * - (reiserfs_fs_block_size(fs_info) / PED_SECTOR_SIZE_DEFAULT); - - return ped_constraint_new(&start_align, ped_alignment_any, - &start_sector, &full_disk, min_size, - dev->length); -} - -static PedFileSystem *reiserfs_copy(const PedFileSystem *fs, - PedGeometry *geom, PedTimer *timer) -{ - dal_t *dal; - PedGeometry *fs_geom; - PedFileSystem *new_fs; - blk_t fs_len, min_needed_blk; - - reiserfs_fs_t *dest_fs, *src_fs; - reiserfs_gauge_t *gauge = NULL; - - fs_geom = ped_geometry_duplicate(geom); - - if (!(dal = geom_dal_create(fs_geom, DEFAULT_BLOCK_SIZE, O_RDWR))) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Couldn't create reiserfs device " - "abstraction handler.")); - goto error_free_fs_geom; - } - - src_fs = fs->type_specific; - - fs_len = - (geom->length / (reiserfs_fs_block_size(src_fs) / PED_SECTOR_SIZE_DEFAULT)); - min_needed_blk = reiserfs_fs_bitmap_used(src_fs); - - if (fs_len <= min_needed_blk) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Device is too small for %lu blocks."), - min_needed_blk); - goto error_free_dal; - } - - if (! (new_fs = (PedFileSystem *) ped_malloc(sizeof(PedFileSystem)))) - goto error_free_dal; - - ped_timer_reset(timer); - ped_timer_set_state_name(timer, _("copying")); - ped_timer_update(timer, 0.0); - - if (libreiserfs_gauge_create && libreiserfs_gauge_free) { - if (! (gauge = - libreiserfs_gauge_create(NULL, gauge_handler, timer))) - goto error_free_new_fs; - } - - if (!(dest_fs = reiserfs_fs_copy(src_fs, dal, gauge))) - goto error_free_gauge; - - ped_timer_update(timer, 1.0); - - if (gauge) - libreiserfs_gauge_free(gauge); - - new_fs->type = reiserfs_type; - new_fs->geom = fs_geom; - new_fs->type_specific = (void *) dest_fs; - - return new_fs; - -error_free_gauge: - if (gauge) - libreiserfs_gauge_free(gauge); -error_free_new_fs: - ped_free(new_fs); -error_free_dal: - geom_dal_free(dal); -error_free_fs_geom: - ped_geometry_destroy(fs_geom); - return NULL; -} - -static PedConstraint *reiserfs_get_copy_constraint(const PedFileSystem *fs, - const PedDevice *dev) -{ - PedGeometry full_dev; - - PED_ASSERT(fs != NULL, return NULL); - PED_ASSERT(dev != NULL, return NULL); - - if (!ped_geometry_init(&full_dev, dev, 0, dev->length - 1)) - return NULL; - - return ped_constraint_new(ped_alignment_any, ped_alignment_any, - &full_dev, &full_dev, - reiserfs_fs_bitmap_used(fs->type_specific), - dev->length); -} - -#endif /* !REISER_FULL_SUPPORT */ - -#ifdef DYNAMIC_LOADING - -#define INIT_SYM(SYM) SYM = getsym (libreiserfs_handle, #SYM) - -static void *getsym(void *handle, const char *symbol) -{ - void *entry; - char *error; - - entry = dlsym(handle, symbol); - if ((error = dlerror()) != NULL) { - ped_exception_throw(PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("Couldn't resolve symbol %s. " - "Error: %s."), - symbol, error); - return NULL; - } - - return entry; -} - -static int reiserfs_ops_interface_version_check(void) -{ - int min_interface_version, max_interface_version; - int (*libreiserfs_get_max_interface_version) (void); - int (*libreiserfs_get_min_interface_version) (void); - - INIT_SYM(libreiserfs_get_max_interface_version); - INIT_SYM(libreiserfs_get_min_interface_version); - - if (!libreiserfs_get_min_interface_version || - !libreiserfs_get_max_interface_version) { - ped_exception_throw( - PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, - _("GNU Parted found an invalid libreiserfs library.")); - return 0; - } - - min_interface_version = libreiserfs_get_min_interface_version(); - max_interface_version = libreiserfs_get_max_interface_version(); - - if (REISERFS_API_VERSION < min_interface_version || - REISERFS_API_VERSION > max_interface_version) { - ped_exception_throw( - PED_EXCEPTION_WARNING, PED_EXCEPTION_CANCEL, - _("GNU Parted has detected libreiserfs interface " - "version mismatch. Found %d-%d, required %d. " - "ReiserFS support will be disabled."), - min_interface_version, - max_interface_version, - REISERFS_API_VERSION); - return 0; - } - - return 1; -} - -static int reiserfs_ops_init(void) -{ - if (!(libreiserfs_handle = dlopen("libreiserfs.so", RTLD_NOW))) - goto error; - - if (!reiserfs_ops_interface_version_check()) - goto error_free_libreiserfs_handle; - - if (!(libdal_handle = dlopen("libdal.so", RTLD_NOW))) - goto error_free_libreiserfs_handle; - - INIT_SYM(reiserfs_fs_probe); - INIT_SYM(libreiserfs_exception_type); - - INIT_SYM(libreiserfs_exception_option); - INIT_SYM(libreiserfs_exception_message); - INIT_SYM(libreiserfs_exception_set_handler); - - INIT_SYM(reiserfs_fs_clobber); - INIT_SYM(reiserfs_fs_open); - INIT_SYM(reiserfs_fs_create); - INIT_SYM(reiserfs_fs_resize); - INIT_SYM(reiserfs_fs_copy); - - INIT_SYM(reiserfs_fs_is_resizeable); - INIT_SYM(reiserfs_fs_is_consistent); - - INIT_SYM(reiserfs_fs_bitmap_check); - INIT_SYM(reiserfs_fs_bitmap_used); - - INIT_SYM(reiserfs_fs_min_size); - INIT_SYM(reiserfs_fs_block_size); - - INIT_SYM(reiserfs_fs_host_dal); - INIT_SYM(reiserfs_fs_close); - - INIT_SYM(libreiserfs_gauge_create); - INIT_SYM(libreiserfs_gauge_free); - - INIT_SYM(dal_realize); - INIT_SYM(dal_flags); - - INIT_SYM(dal_block_size); - INIT_SYM(dal_len); - - return 1; - -error_free_libreiserfs_handle: - dlclose(libreiserfs_handle); - libreiserfs_handle = NULL; -error: - return 0; -} - -static void reiserfs_ops_done() -{ - if (libdal_handle) - dlclose(libdal_handle); - if (libreiserfs_handle) - dlclose(libreiserfs_handle); -} -#endif /* DYNAMIC_LOADING */ - -#define REISER_BLOCK_SIZES ((int[]){512, 1024, 2048, 4096, 8192, 0}) - -#ifdef REISER_FULL_SUPPORT -static PedFileSystemOps reiserfs_full_ops = { - .probe = reiserfs_probe, - .clobber = reiserfs_clobber, - .open = reiserfs_open, - .create = reiserfs_create, - .close = reiserfs_close, - .check = reiserfs_check, - .copy = reiserfs_copy, - .resize = reiserfs_resize, - .get_create_constraint = reiserfs_get_create_constraint, - .get_resize_constraint = reiserfs_get_resize_constraint, - .get_copy_constraint = reiserfs_get_copy_constraint -}; - -static PedFileSystemType reiserfs_full_type = { - .next = NULL, - .ops = &reiserfs_full_ops, - .name = "reiserfs", - .block_sizes = REISER_BLOCK_SIZES -}; -#endif /* REISER_FULL_SUPPORT */ - -static PedFileSystemOps reiserfs_simple_ops = { - .probe = reiserfs_probe, -#ifdef DISCOVER_ONLY - .clobber = NULL, -#else - .clobber = reiserfs_clobber, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemType reiserfs_simple_type = { - .next = NULL, - .ops = &reiserfs_simple_ops, - .name = "reiserfs", - .block_sizes = REISER_BLOCK_SIZES -}; - -void ped_file_system_reiserfs_init() -{ -#ifdef DYNAMIC_LOADING - libreiserfs_present = reiserfs_ops_init(); - if (libreiserfs_present) { - reiserfs_type = &reiserfs_full_type; - libreiserfs_exception_set_handler(exception_handler); - } else { - reiserfs_type = &reiserfs_simple_type; - } -#else /* !DYNAMIC_LOADING */ -#ifdef REISER_FULL_SUPPORT - libreiserfs_exception_set_handler(exception_handler); - reiserfs_type = &reiserfs_full_type; -#else - reiserfs_type = &reiserfs_simple_type; -#endif -#endif /* !DYNAMIC_LOADING */ - ped_file_system_type_register(reiserfs_type); -} - -void ped_file_system_reiserfs_done() -{ - ped_file_system_type_unregister(reiserfs_type); -#ifdef DYNAMIC_LOADING - reiserfs_ops_done(); -#endif /* DYNAMIC_LOADING */ -} diff --git a/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.h b/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.h deleted file mode 100644 index 3cd68c0398..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef REISERFS_H -#define REISERFS_H - -#define REISERFS_API_VERSION 0 - -#define REISERFS_SIGNATURE "ReIsErFs" -#define REISER2FS_SIGNATURE "ReIsEr2Fs" -#define REISER3FS_SIGNATURE "ReIsEr3Fs" - -#define DEFAULT_BLOCK_SIZE 4096 - -struct reiserfs_super_block { - uint32_t s_block_count; - uint32_t s_free_blocks; - uint32_t s_root_block; - uint32_t s_journal_block; - uint32_t s_journal_dev; - uint32_t s_orig_journal_size; - uint32_t s_journal_trans_max; - uint32_t s_journal_block_count; - uint32_t s_journal_max_batch; - uint32_t s_journal_max_commit_age; - uint32_t s_journal_max_trans_age; - uint16_t s_blocksize; - uint16_t s_oid_maxsize; - uint16_t s_oid_cursize; - uint16_t s_state; - char s_magic[10]; - uint16_t s_fsck_state; - uint32_t s_hash_function_code; - uint16_t s_tree_height; - uint16_t s_bmap_nr; - uint16_t s_version; - char padding[438]; -}; - -typedef struct reiserfs_super_block reiserfs_super_block_t; - -enum reiserfs_exception_type { - EXCEPTION_INFORMATION = 1, - EXCEPTION_WARNING = 2, - EXCEPTION_ERROR = 3, - EXCEPTION_FATAL = 4, - EXCEPTION_BUG = 5, - EXCEPTION_NO_FEATURE = 6 -}; - -typedef enum reiserfs_exception_type reiserfs_exception_type_t; - -enum reiserfs_exception_option { - EXCEPTION_UNHANDLED = 1 << 0, - EXCEPTION_FIX = 1 << 1, - EXCEPTION_YES = 1 << 2, - EXCEPTION_NO = 1 << 3, - EXCEPTION_OK = 1 << 4, - EXCEPTION_RETRY = 1 << 5, - EXCEPTION_IGNORE = 1 << 6, - EXCEPTION_CANCEL = 1 << 7 -}; - -typedef enum reiserfs_exception_option reiserfs_exception_option_t; - -typedef void (reiserfs_gauge_handler_t)(const char *, unsigned int, void *, int, int, int); - -typedef void * reiserfs_exception_t; -typedef void * reiserfs_gauge_t; -typedef void * reiserfs_fs_t; - -#define FS_FORMAT_3_5 0 -#define FS_FORMAT_3_6 2 - -#define SUPER_OFFSET_IN_BYTES 64*1024 - -#define DEFAULT_JOURNAL_SIZE 8192 - -#define JOURNAL_MIN_SIZE 512 -#define JOURNAL_MIN_TRANS 256 -#define JOURNAL_MAX_TRANS 1024 - -#define JOURNAL_DEF_RATIO 8 -#define JOURNAL_MIN_RATIO 2 -#define JOURNAL_MAX_BATCH 900 -#define JOURNAL_MAX_COMMIT_AGE 30 -#define JOURNAL_MAX_TRANS_AGE 30 - -#define TEA_HASH 1 -#define YURA_HASH 2 -#define R5_HASH 3 - -#endif diff --git a/usr/src/lib/libparted/common/libparted/fs/solaris_x86/solaris_x86.c b/usr/src/lib/libparted/common/libparted/fs/solaris_x86/solaris_x86.c deleted file mode 100644 index 29d5e935d6..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/solaris_x86/solaris_x86.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * libparted - a library for manipulating disk partitions - * - * This module recognizes the Solaris x86 VTOC so that the - * partition can be identified as "solaris". - * - * Mark Logan - */ - -#include - -#include -#include -#include - -#if ENABLE_NLS -#include -#define _(String) dgettext(PACKAGE, String) -#else -#define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include - -#define BLOCK_SIZES ((int[2]) {512, 0}) - -#define VTOC_SANE 0x600DDEEE -#define LEN_DKL_VVOL 8 -#define V_NUMPAR 16 /* # of logical partitions */ -#define LEN_DKL_ASCII 128 /* length of dkl_asciilabel */ - -#define LEN_DKL_PAD \ - (512 - \ - ((5 * sizeof (uint32_t)) + \ - LEN_DKL_VVOL + \ - (2 * sizeof (uint16_t)) + \ - (10 * sizeof (uint32_t)) + \ - (V_NUMPAR * sizeof (struct partition)) + \ - (V_NUMPAR * sizeof (uint32_t)) + \ - LEN_DKL_ASCII + \ - (2 * (sizeof (uint16_t))))) - -#define DKL_MAGIC 0xDABE /* magic number */ - -struct partition { - unsigned short p_tag; /* ID tag of partition */ - unsigned short p_flag; /* permission flags */ - long p_start; /* start sector no of partition */ - long p_size; /* # of blocks in partition */ -}; - -struct vtoc { - unsigned long v_bootinfo[3]; /* info for mboot (unsupported) */ - unsigned long v_sanity; /* to verify vtoc sanity */ - unsigned long v_version; /* layout version */ - char v_volume[LEN_DKL_VVOL]; /* volume name */ - unsigned short v_sectorsz; /* sector size in bytes */ - unsigned short v_nparts; /* number of partitions */ - unsigned long v_reserved[10]; /* free space */ - struct partition v_part[V_NUMPAR]; /* partition headers */ - int32_t timestamp[V_NUMPAR]; /* partition timestamp (unsupported) */ - char v_asciilabel[LEN_DKL_ASCII]; /* for compatibility */ - char dkl_pad[LEN_DKL_PAD]; /* unused part of 512 bytes */ - uint16_t dkl_magic; /* identifies this label format */ - uint16_t dkl_cksum; /* xor checksum of sector */ -}; - -static PedGeometry* -solaris_x86_probe(PedGeometry* geom) -{ - int8_t buf[512 * 3]; - struct vtoc *pvtoc; - uint16_t *dkl_magic; - - if (geom->length < 5) - return (0); - if (!ped_geometry_read(geom, buf, 1, 1)) - return (0); - - pvtoc = (struct vtoc *)buf; - - if (pvtoc->v_sanity == VTOC_SANE && pvtoc->dkl_magic == DKL_MAGIC) { - PedSector block_size = pvtoc->v_sectorsz / 512; - /* - * Use the size of the backup slice: - */ - PedSector block_count = pvtoc->v_part[2].p_size; - return ped_geometry_new(geom->dev, geom->start, - block_size * block_count); - } - - return (NULL); -} - -#ifndef DISCOVER_ONLY -static int -solaris_x86_clobber(PedGeometry* geom) -{ - char buf[512*3]; - - if (!ped_geometry_read(geom, buf, 1, 1)) - return (0); - - memset(buf, 0, sizeof (struct vtoc)); - - return (ped_geometry_write(geom, buf, 1, 1)); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps solaris_x86_ops = { - .probe = solaris_x86_probe, -#ifndef DISCOVER_ONLY - .clobber = solaris_x86_clobber, -#else - .clobber = NULL, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemType solaris_x86_type = { - .next = NULL, - .ops = &solaris_x86_ops, - .name = "solaris", - .block_sizes = BLOCK_SIZES -}; - -void -ped_file_system_solaris_x86_init() -{ - ped_file_system_type_register(&solaris_x86_type); -} - -void -ped_file_system_solaris_x86_done() -{ - ped_file_system_type_unregister(&solaris_x86_type); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/ufs/ufs.c b/usr/src/lib/libparted/common/libparted/fs/ufs/ufs.c deleted file mode 100644 index 060c6bebc4..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/ufs/ufs.c +++ /dev/null @@ -1,324 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - Contributor: Ben Collins -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include - -#define SUN_UFS_BLOCK_SIZES ((int[2]){512, 0}) -#define HP_UFS_BLOCK_SIZES ((int[2]){512, 0}) - - -/* taken from ufs_fs.h in Linux */ -#define UFS_MAXNAMLEN 255 -#define UFS_MAXMNTLEN 512 -#define UFS_MAXCSBUFS 31 -#define UFS_LINK_MAX 32000 - -#define UFS_MAGIC 0x00011954 -#define UFS_MAGIC_LFN 0x00095014 -#define UFS_MAGIC_FEA 0x00195612 -#define UFS_MAGIC_4GB 0x05231994 - -struct ufs_csum { - uint32_t cs_ndir; /* number of directories */ - uint32_t cs_nbfree; /* number of free blocks */ - uint32_t cs_nifree; /* number of free inodes */ - uint32_t cs_nffree; /* number of free frags */ -}; - -struct ufs_super_block { - uint32_t fs_link; /* UNUSED */ - uint32_t fs_rlink; /* UNUSED */ - uint32_t fs_sblkno; /* addr of super-block in filesys */ - uint32_t fs_cblkno; /* offset of cyl-block in filesys */ - uint32_t fs_iblkno; /* offset of inode-blocks in filesys */ - uint32_t fs_dblkno; /* offset of first data after cg */ - uint32_t fs_cgoffset; /* cylinder group offset in cylinder */ - uint32_t fs_cgmask; /* used to calc mod fs_ntrak */ - uint32_t fs_time; /* last time written -- time_t */ - uint32_t fs_size; /* number of blocks in fs */ - uint32_t fs_dsize; /* number of data blocks in fs */ - uint32_t fs_ncg; /* number of cylinder groups */ - uint32_t fs_bsize; /* size of basic blocks in fs */ - uint32_t fs_fsize; /* size of frag blocks in fs */ - uint32_t fs_frag; /* number of frags in a block in fs */ -/* these are configuration parameters */ - uint32_t fs_minfree; /* minimum percentage of free blocks */ - uint32_t fs_rotdelay; /* num of ms for optimal next block */ - uint32_t fs_rps; /* disk revolutions per second */ -/* these fields can be computed from the others */ - uint32_t fs_bmask; /* ``blkoff'' calc of blk offsets */ - uint32_t fs_fmask; /* ``fragoff'' calc of frag offsets */ - uint32_t fs_bshift; /* ``lblkno'' calc of logical blkno */ - uint32_t fs_fshift; /* ``numfrags'' calc number of frags */ -/* these are configuration parameters */ - uint32_t fs_maxcontig; /* max number of contiguous blks */ - uint32_t fs_maxbpg; /* max number of blks per cyl group */ -/* these fields can be computed from the others */ - uint32_t fs_fragshift; /* block to frag shift */ - uint32_t fs_fsbtodb; /* fsbtodb and dbtofsb shift constant */ - uint32_t fs_sbsize; /* actual size of super block */ - uint32_t fs_csmask; /* csum block offset */ - uint32_t fs_csshift; /* csum block number */ - uint32_t fs_nindir; /* value of NINDIR */ - uint32_t fs_inopb; /* value of INOPB */ - uint32_t fs_nspf; /* value of NSPF */ -/* yet another configuration parameter */ - uint32_t fs_optim; /* optimization preference, see below */ -/* these fields are derived from the hardware */ - union { - struct { - uint32_t fs_npsect; /* # sectors/track including spares */ - } fs_sun; - struct { - int32_t fs_state; /* file system state time stamp */ - } fs_sunx86; - } fs_u1; - uint32_t fs_interleave; /* hardware sector interleave */ - uint32_t fs_trackskew; /* sector 0 skew, per track */ -/* a unique id for this file system (currently unused and unmaintained) */ -/* In 4.3 Tahoe this space is used by fs_headswitch and fs_trkseek */ -/* Neither of those fields is used in the Tahoe code right now but */ -/* there could be problems if they are. */ - uint32_t fs_id[2]; /* file system id */ -/* sizes determined by number of cylinder groups and their sizes */ - uint32_t fs_csaddr; /* blk addr of cyl grp summary area */ - uint32_t fs_cssize; /* size of cyl grp summary area */ - uint32_t fs_cgsize; /* cylinder group size */ -/* these fields are derived from the hardware */ - uint32_t fs_ntrak; /* tracks per cylinder */ - uint32_t fs_nsect; /* sectors per track */ - uint32_t fs_spc; /* sectors per cylinder */ -/* this comes from the disk driver partitioning */ - uint32_t fs_ncyl; /* cylinders in file system */ -/* these fields can be computed from the others */ - uint32_t fs_cpg; /* cylinders per group */ - uint32_t fs_ipg; /* inodes per group */ - uint32_t fs_fpg; /* blocks per group * fs_frag */ -/* this data must be re-computed after crashes */ - struct ufs_csum fs_cstotal; /* cylinder summary information */ -/* these fields are cleared at mount time */ - int8_t fs_fmod; /* super block modified flag */ - int8_t fs_clean; /* file system is clean flag */ - int8_t fs_ronly; /* mounted read-only flag */ - int8_t fs_flags; /* currently unused flag */ - int8_t fs_fsmnt[UFS_MAXMNTLEN]; /* name mounted on */ -/* these fields retain the current block allocation info */ - uint32_t fs_cgrotor; /* last cg searched */ - uint32_t fs_csp[UFS_MAXCSBUFS]; /* list of fs_cs info buffers */ - uint32_t fs_maxcluster; - uint32_t fs_cpc; /* cyl per cycle in postbl */ - uint16_t fs_opostbl[16][8]; /* old rotation block list head */ - union { - struct { - int32_t fs_sparecon[53];/* reserved for future constants */ - int32_t fs_reclaim; - int32_t fs_sparecon2[1]; - int32_t fs_state; /* file system state time stamp */ - uint32_t fs_qbmask[2]; /* ~usb_bmask */ - uint32_t fs_qfmask[2]; /* ~usb_fmask */ - } fs_sun; - struct { - int32_t fs_sparecon[53];/* reserved for future constants */ - int32_t fs_reclaim; - int32_t fs_sparecon2[1]; - uint32_t fs_npsect; /* # sectors/track including spares */ - uint32_t fs_qbmask[2]; /* ~usb_bmask */ - uint32_t fs_qfmask[2]; /* ~usb_fmask */ - } fs_sunx86; - struct { - int32_t fs_sparecon[50];/* reserved for future constants */ - int32_t fs_contigsumsize;/* size of cluster summary array */ - int32_t fs_maxsymlinklen;/* max length of an internal symlink */ - int32_t fs_inodefmt; /* format of on-disk inodes */ - uint32_t fs_maxfilesize[2]; /* max representable file size */ - uint32_t fs_qbmask[2]; /* ~usb_bmask */ - uint32_t fs_qfmask[2]; /* ~usb_fmask */ - int32_t fs_state; /* file system state time stamp */ - } fs_44; - } fs_u2; - int32_t fs_postblformat; /* format of positional layout tables */ - int32_t fs_nrpos; /* number of rotational positions */ - int32_t fs_postbloff; /* (__s16) rotation block list head */ - int32_t fs_rotbloff; /* (uint8_t) blocks for each rotation */ - int32_t fs_magic; /* magic number */ - uint8_t fs_space[4]; /* list of blocks for each rotation */ -}; - -static PedGeometry* -ufs_probe_sun (PedGeometry* geom) -{ - int8_t buf[512 * 3]; - struct ufs_super_block *sb; - - if (geom->length < 5) - return 0; - if (!ped_geometry_read (geom, buf, 16, 3)) - return 0; - - sb = (struct ufs_super_block *)buf; - - if (PED_BE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { - PedSector block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; - PedSector block_count = PED_BE32_TO_CPU(sb->fs_size); - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - if (PED_LE32_TO_CPU(sb->fs_magic) == UFS_MAGIC) { - PedSector block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; - PedSector block_count = PED_LE32_TO_CPU(sb->fs_size); - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - return NULL; -} - -static PedGeometry* -ufs_probe_hp (PedGeometry* geom) -{ - int8_t buf[1536]; - struct ufs_super_block *sb; - PedSector block_size; - PedSector block_count; - - if (geom->length < 5) - return 0; - if (!ped_geometry_read (geom, buf, 16, 3)) - return 0; - - sb = (struct ufs_super_block *)buf; - - /* Try sane bytesex */ - switch (PED_BE32_TO_CPU(sb->fs_magic)) { - case UFS_MAGIC_LFN: - case UFS_MAGIC_FEA: - case UFS_MAGIC_4GB: - block_size = PED_BE32_TO_CPU(sb->fs_bsize) / 512; - block_count = PED_BE32_TO_CPU(sb->fs_size); - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - - /* Try perverted bytesex */ - switch (PED_LE32_TO_CPU(sb->fs_magic)) { - case UFS_MAGIC_LFN: - case UFS_MAGIC_FEA: - case UFS_MAGIC_4GB: - block_size = PED_LE32_TO_CPU(sb->fs_bsize) / 512; - block_count = PED_LE32_TO_CPU(sb->fs_size); - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - return NULL; -} - -#ifndef DISCOVER_ONLY -static int -ufs_clobber (PedGeometry* geom) -{ - char buf[1536]; - - if (!ped_geometry_read (geom, buf, 16, 3)) - return 0; - - memset (buf, 0, sizeof(struct ufs_super_block)); - - return ped_geometry_write (geom, buf, 16, 3); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps ufs_ops_sun = { - .probe = ufs_probe_sun, -#ifndef DISCOVER_ONLY - .clobber = ufs_clobber, -#else - .clobber = NULL, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemOps ufs_ops_hp = { - .probe = ufs_probe_hp, -#ifndef DISCOVER_ONLY - .clobber = ufs_clobber, -#else - .clobber = NULL, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemType ufs_type_sun = { - .next = NULL, - .ops = &ufs_ops_sun, - .name = "sun-ufs", - .block_sizes = SUN_UFS_BLOCK_SIZES -}; - -static PedFileSystemType ufs_type_hp = { - .next = NULL, - .ops = &ufs_ops_hp, - .name = "hp-ufs", - .block_sizes = HP_UFS_BLOCK_SIZES -}; - -void -ped_file_system_ufs_init () -{ - PED_ASSERT (sizeof (struct ufs_super_block) == 1380, return); - - ped_file_system_type_register (&ufs_type_sun); - ped_file_system_type_register (&ufs_type_hp); -} - -void -ped_file_system_ufs_done () -{ - ped_file_system_type_unregister (&ufs_type_hp); - ped_file_system_type_unregister (&ufs_type_sun); -} diff --git a/usr/src/lib/libparted/common/libparted/fs/xfs/platform_defs.h b/usr/src/lib/libparted/common/libparted/fs/xfs/platform_defs.h deleted file mode 100644 index 8696273b11..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/xfs/platform_defs.h +++ /dev/null @@ -1,117 +0,0 @@ -/* include/platform_defs.h. Generated automatically by configure. */ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 3 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. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - * - * @configure_input@ - */ -#ifndef __XFS_PLATFORM_DEFS_H__ -#define __XFS_PLATFORM_DEFS_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1) -# define constpp const char * const * -#else -# define constpp char * const * -#endif - -#ifdef __sparc__ -# ifndef O_DIRECT -# define O_DIRECT 0x100000 -# endif -#endif - -#if defined(__sun) -typedef off_t loff_t; -#endif - -typedef loff_t xfs_off_t; -typedef uint64_t xfs_ino_t; -typedef uint32_t xfs_dev_t; -typedef int64_t xfs_daddr_t; -typedef char* xfs_caddr_t; - -/* long and pointer must be either 32 bit or 64 bit */ -/* #undef HAVE_64BIT_LONG */ -#define HAVE_32BIT_LONG 1 -#define HAVE_32BIT_PTR 1 -/* #undef HAVE_64BIT_PTR */ - -/* Check if __psint_t is set to something meaningful */ -/* #undef HAVE___PSINT_T */ -#ifndef HAVE___PSINT_T -# ifdef HAVE_32BIT_PTR -typedef int __psint_t; -# elif defined HAVE_64BIT_PTR -# ifdef HAVE_64BIT_LONG -typedef long __psint_t; -# else -/* This is a very strange architecture, which has 64 bit pointers but - * not 64 bit longs. So, I'd just punt here and assume long long is Ok */ -typedef long long __psint_t; -# endif -# else -# error Unknown pointer size -# endif -#endif - -/* Check if __psunsigned_t is set to something meaningful */ -/* #undef HAVE___PSUNSIGNED_T */ -#ifndef HAVE___PSUNSIGNED_T -# ifdef HAVE_32BIT_PTR -typedef unsigned int __psunsigned_t; -# elif defined HAVE_64BIT_PTR -# ifdef HAVE_64BIT_LONG -typedef long __psunsigned_t; -# else -/* This is a very strange architecture, which has 64 bit pointers but - * not 64 bit longs. So, I'd just punt here and assume long long is Ok */ -typedef unsigned long long __psunsigned_t; -# endif -# else -# error Unknown pointer size -# endif -#endif - -#ifdef DEBUG -# define ASSERT assert -#else -# define ASSERT(EX) ((void) 0) -#endif - -#endif /* __XFS_PLATFORM_DEFS_H__ */ diff --git a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs.c b/usr/src/lib/libparted/common/libparted/fs/xfs/xfs.c deleted file mode 100644 index 2ca51a88a9..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#include -#include "platform_defs.h" -#include "xfs_types.h" -#include "xfs_sb.h" - -#define XFS_BLOCK_SIZES ((int[2]){512, 0}) - -static PedGeometry* -xfs_probe (PedGeometry* geom) -{ - PedSector block_size; - PedSector block_count; - union { - struct xfs_sb sb; - char bytes [512]; - } buf; - - if (geom->length < XFS_SB_DADDR + 1) - return NULL; - if (!ped_geometry_read (geom, &buf, XFS_SB_DADDR, 1)) - return NULL; - - if (PED_LE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { - block_size = PED_LE32_TO_CPU (buf.sb.sb_blocksize) / 512; - block_count = PED_LE64_TO_CPU (buf.sb.sb_dblocks); - - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - - if (PED_BE32_TO_CPU (buf.sb.sb_magicnum) == XFS_SB_MAGIC) { - block_size = PED_BE32_TO_CPU (buf.sb.sb_blocksize) / 512; - block_count = PED_BE64_TO_CPU (buf.sb.sb_dblocks); - - return ped_geometry_new (geom->dev, geom->start, - block_size * block_count); - } - - return NULL; -} - -#ifndef DISCOVER_ONLY -static int -xfs_clobber (PedGeometry* geom) -{ - char buf[512]; - - memset (buf, 0, 512); - return ped_geometry_write (geom, buf, XFS_SB_DADDR, 1); -} -#endif /* !DISCOVER_ONLY */ - -static PedFileSystemOps xfs_ops = { - .probe = xfs_probe, -#ifndef DISCOVER_ONLY - .clobber = xfs_clobber, -#else - .clobber = NULL, -#endif - .open = NULL, - .create = NULL, - .close = NULL, - .check = NULL, - .copy = NULL, - .resize = NULL, - .get_create_constraint = NULL, - .get_resize_constraint = NULL, - .get_copy_constraint = NULL -}; - -static PedFileSystemType xfs_type = { - .next = NULL, - .ops = &xfs_ops, - .name = "xfs", - .block_sizes = XFS_BLOCK_SIZES -}; - -void -ped_file_system_xfs_init () -{ - ped_file_system_type_register (&xfs_type); -} - -void -ped_file_system_xfs_done () -{ - ped_file_system_type_unregister (&xfs_type); -} - diff --git a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_sb.h b/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_sb.h deleted file mode 100644 index 139cd07c0f..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_sb.h +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 3 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. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_SB_H__ -#define __XFS_SB_H__ - -/* - * Super block - * Fits into a 512-byte buffer at daddr_t 0 of each allocation group. - * Only the first of these is ever updated except during growfs. - */ - -struct xfs_buf; -struct xfs_mount; - -#define XFS_SB_MAGIC 0x58465342 /* 'XFSB' */ -#define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ -#define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ -#define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ -#define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ -#define XFS_SB_VERSION_NUMBITS 0x000f -#define XFS_SB_VERSION_ALLFBITS 0xfff0 -#define XFS_SB_VERSION_SASHFBITS 0xf000 -#define XFS_SB_VERSION_REALFBITS 0x0ff0 -#define XFS_SB_VERSION_ATTRBIT 0x0010 -#define XFS_SB_VERSION_NLINKBIT 0x0020 -#define XFS_SB_VERSION_QUOTABIT 0x0040 -#define XFS_SB_VERSION_ALIGNBIT 0x0080 -#define XFS_SB_VERSION_DALIGNBIT 0x0100 -#define XFS_SB_VERSION_SHAREDBIT 0x0200 -#define XFS_SB_VERSION_EXTFLGBIT 0x1000 -#define XFS_SB_VERSION_DIRV2BIT 0x2000 -#define XFS_SB_VERSION_OKSASHFBITS \ - (XFS_SB_VERSION_EXTFLGBIT | \ - XFS_SB_VERSION_DIRV2BIT) -#define XFS_SB_VERSION_OKREALFBITS \ - (XFS_SB_VERSION_ATTRBIT | \ - XFS_SB_VERSION_NLINKBIT | \ - XFS_SB_VERSION_QUOTABIT | \ - XFS_SB_VERSION_ALIGNBIT | \ - XFS_SB_VERSION_DALIGNBIT | \ - XFS_SB_VERSION_SHAREDBIT) -#define XFS_SB_VERSION_OKSASHBITS \ - (XFS_SB_VERSION_NUMBITS | \ - XFS_SB_VERSION_REALFBITS | \ - XFS_SB_VERSION_OKSASHFBITS) -#define XFS_SB_VERSION_OKREALBITS \ - (XFS_SB_VERSION_NUMBITS | \ - XFS_SB_VERSION_OKREALFBITS | \ - XFS_SB_VERSION_OKSASHFBITS) -#define XFS_SB_VERSION_MKFS(ia,dia,extflag,dirv2) \ - (((ia) || (dia) || (extflag) || (dirv2)) ? \ - (XFS_SB_VERSION_4 | \ - ((ia) ? XFS_SB_VERSION_ALIGNBIT : 0) | \ - ((dia) ? XFS_SB_VERSION_DALIGNBIT : 0) | \ - ((extflag) ? XFS_SB_VERSION_EXTFLGBIT : 0) | \ - ((dirv2) ? XFS_SB_VERSION_DIRV2BIT : 0)) : \ - XFS_SB_VERSION_1) - -typedef struct xfs_sb -{ - uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ - uint32_t sb_blocksize; /* logical block size, bytes */ - xfs_drfsbno_t sb_dblocks; /* number of data blocks */ - xfs_drfsbno_t sb_rblocks; /* number of realtime blocks */ - xfs_drtbno_t sb_rextents; /* number of realtime extents */ - uuid_t sb_uuid; /* file system unique id */ - xfs_dfsbno_t sb_logstart; /* starting block of log if internal */ - xfs_ino_t sb_rootino; /* root inode number */ - xfs_ino_t sb_rbmino; /* bitmap inode for realtime extents */ - xfs_ino_t sb_rsumino; /* summary inode for rt bitmap */ - xfs_agblock_t sb_rextsize; /* realtime extent size, blocks */ - xfs_agblock_t sb_agblocks; /* size of an allocation group */ - xfs_agnumber_t sb_agcount; /* number of allocation groups */ - xfs_extlen_t sb_rbmblocks; /* number of rt bitmap blocks */ - xfs_extlen_t sb_logblocks; /* number of log blocks */ - uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ - uint16_t sb_sectsize; /* volume sector size, bytes */ - uint16_t sb_inodesize; /* inode size, bytes */ - uint16_t sb_inopblock; /* inodes per block */ - char sb_fname[12]; /* file system name */ - uint8_t sb_blocklog; /* log2 of sb_blocksize */ - uint8_t sb_sectlog; /* log2 of sb_sectsize */ - uint8_t sb_inodelog; /* log2 of sb_inodesize */ - uint8_t sb_inopblog; /* log2 of sb_inopblock */ - uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ - uint8_t sb_rextslog; /* log2 of sb_rextents */ - uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ - uint8_t sb_imax_pct; /* max % of fs for inode space */ - /* statistics */ - /* - * These fields must remain contiguous. If you really - * want to change their layout, make sure you fix the - * code in xfs_trans_apply_sb_deltas(). - */ - uint64_t sb_icount; /* allocated inodes */ - uint64_t sb_ifree; /* free inodes */ - uint64_t sb_fdblocks; /* free data blocks */ - uint64_t sb_frextents; /* free realtime extents */ - /* - * End contiguous fields. - */ - xfs_ino_t sb_uquotino; /* user quota inode */ - xfs_ino_t sb_gquotino; /* group quota inode */ - uint16_t sb_qflags; /* quota flags */ - uint8_t sb_flags; /* misc. flags */ - uint8_t sb_shared_vn; /* shared version number */ - xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ - uint32_t sb_unit; /* stripe or raid unit */ - uint32_t sb_width; /* stripe or raid width */ - uint8_t sb_dirblklog; /* log2 of dir block size (fsbs) */ - uint8_t sb_dummy[7]; /* padding */ -} xfs_sb_t; - -/* - * Sequence number values for the fields. - */ -typedef enum { - XFS_SBS_MAGICNUM, XFS_SBS_BLOCKSIZE, XFS_SBS_DBLOCKS, XFS_SBS_RBLOCKS, - XFS_SBS_REXTENTS, XFS_SBS_UUID, XFS_SBS_LOGSTART, XFS_SBS_ROOTINO, - XFS_SBS_RBMINO, XFS_SBS_RSUMINO, XFS_SBS_REXTSIZE, XFS_SBS_AGBLOCKS, - XFS_SBS_AGCOUNT, XFS_SBS_RBMBLOCKS, XFS_SBS_LOGBLOCKS, - XFS_SBS_VERSIONNUM, XFS_SBS_SECTSIZE, XFS_SBS_INODESIZE, - XFS_SBS_INOPBLOCK, XFS_SBS_FNAME, XFS_SBS_BLOCKLOG, - XFS_SBS_SECTLOG, XFS_SBS_INODELOG, XFS_SBS_INOPBLOG, XFS_SBS_AGBLKLOG, - XFS_SBS_REXTSLOG, XFS_SBS_INPROGRESS, XFS_SBS_IMAX_PCT, XFS_SBS_ICOUNT, - XFS_SBS_IFREE, XFS_SBS_FDBLOCKS, XFS_SBS_FREXTENTS, XFS_SBS_UQUOTINO, - XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN, - XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG, - XFS_SBS_DUMMY, - XFS_SBS_FIELDCOUNT -} xfs_sb_field_t; - -/* - * Mask values, defined based on the xfs_sb_field_t values. - * Only define the ones we're using. - */ -#define XFS_SB_MVAL(x) (1LL << XFS_SBS_ ## x) -#define XFS_SB_UUID XFS_SB_MVAL(UUID) -#define XFS_SB_FNAME XFS_SB_MVAL(FNAME) -#define XFS_SB_ROOTINO XFS_SB_MVAL(ROOTINO) -#define XFS_SB_RBMINO XFS_SB_MVAL(RBMINO) -#define XFS_SB_RSUMINO XFS_SB_MVAL(RSUMINO) -#define XFS_SB_VERSIONNUM XFS_SB_MVAL(VERSIONNUM) -#define XFS_SB_UQUOTINO XFS_SB_MVAL(UQUOTINO) -#define XFS_SB_GQUOTINO XFS_SB_MVAL(GQUOTINO) -#define XFS_SB_QFLAGS XFS_SB_MVAL(QFLAGS) -#define XFS_SB_SHARED_VN XFS_SB_MVAL(SHARED_VN) -#define XFS_SB_UNIT XFS_SB_MVAL(UNIT) -#define XFS_SB_WIDTH XFS_SB_MVAL(WIDTH) -#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT) -#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1) -#define XFS_SB_MOD_BITS \ - (XFS_SB_UUID | XFS_SB_ROOTINO | XFS_SB_RBMINO | XFS_SB_RSUMINO | \ - XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ - XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH) - -/* - * Misc. Flags - warning - these will be cleared by xfs_repair unless - * a feature bit is set when the flag is used. - */ -#define XFS_SBF_NOFLAGS 0x00 /* no flags set */ -#define XFS_SBF_READONLY 0x01 /* only read-only mounts allowed */ - -/* - * define max. shared version we can interoperate with - */ -#define XFS_SB_MAX_SHARED_VN 0 - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_NUM) -int xfs_sb_version_num(xfs_sb_t *sbp); -#define XFS_SB_VERSION_NUM(sbp) xfs_sb_version_num(sbp) -#else -#define XFS_SB_VERSION_NUM(sbp) ((sbp)->sb_versionnum & XFS_SB_VERSION_NUMBITS) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_GOOD_VERSION) -int xfs_sb_good_version(xfs_sb_t *sbp); -#define XFS_SB_GOOD_VERSION(sbp) xfs_sb_good_version(sbp) -#else -#define XFS_SB_GOOD_VERSION_INT(sbp) \ - ((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \ - ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - !((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKREALBITS) -#ifdef __KERNEL__ -#define XFS_SB_GOOD_VERSION(sbp) \ - (XFS_SB_GOOD_VERSION_INT(sbp) && \ - (sbp)->sb_shared_vn <= XFS_SB_MAX_SHARED_VN) )) -#else -/* - * extra 2 paren's here (( to unconfuse paren-matching editors - * like vi because XFS_SB_GOOD_VERSION_INT is a partial expression - * and the two XFS_SB_GOOD_VERSION's each 2 more close paren's to - * complete the expression. - */ -#define XFS_SB_GOOD_VERSION(sbp) \ - (XFS_SB_GOOD_VERSION_INT(sbp) && \ - (!((sbp)->sb_versionnum & XFS_SB_VERSION_SHAREDBIT) || \ - (sbp)->sb_shared_vn <= XFS_SB_MAX_SHARED_VN)) )) -#endif /* __KERNEL__ */ -#endif - -#define XFS_SB_GOOD_SASH_VERSION(sbp) \ - ((((sbp)->sb_versionnum >= XFS_SB_VERSION_1) && \ - ((sbp)->sb_versionnum <= XFS_SB_VERSION_3)) || \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - !((sbp)->sb_versionnum & ~XFS_SB_VERSION_OKSASHBITS))) - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_TONEW) -unsigned xfs_sb_version_tonew(unsigned v); -#define XFS_SB_VERSION_TONEW(v) xfs_sb_version_tonew(v) -#else -#define XFS_SB_VERSION_TONEW(v) \ - ((((v) == XFS_SB_VERSION_1) ? \ - 0 : \ - (((v) == XFS_SB_VERSION_2) ? \ - XFS_SB_VERSION_ATTRBIT : \ - (XFS_SB_VERSION_ATTRBIT | XFS_SB_VERSION_NLINKBIT))) | \ - XFS_SB_VERSION_4) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_TOOLD) -unsigned xfs_sb_version_toold(unsigned v); -#define XFS_SB_VERSION_TOOLD(v) xfs_sb_version_toold(v) -#else -#define XFS_SB_VERSION_TOOLD(v) \ - (((v) & (XFS_SB_VERSION_QUOTABIT | XFS_SB_VERSION_ALIGNBIT)) ? \ - 0 : \ - (((v) & XFS_SB_VERSION_NLINKBIT) ? \ - XFS_SB_VERSION_3 : \ - (((v) & XFS_SB_VERSION_ATTRBIT) ? \ - XFS_SB_VERSION_2 : \ - XFS_SB_VERSION_1))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASATTR) -int xfs_sb_version_hasattr(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASATTR(sbp) xfs_sb_version_hasattr(sbp) -#else -#define XFS_SB_VERSION_HASATTR(sbp) \ - (((sbp)->sb_versionnum == XFS_SB_VERSION_2) || \ - ((sbp)->sb_versionnum == XFS_SB_VERSION_3) || \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_ATTRBIT))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDATTR) -void xfs_sb_version_addattr(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDATTR(sbp) xfs_sb_version_addattr(sbp) -#else -#define XFS_SB_VERSION_ADDATTR(sbp) \ - ((sbp)->sb_versionnum = \ - (((sbp)->sb_versionnum == XFS_SB_VERSION_1) ? \ - XFS_SB_VERSION_2 : \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) ? \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_ATTRBIT) : \ - (XFS_SB_VERSION_4 | XFS_SB_VERSION_ATTRBIT)))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASNLINK) -int xfs_sb_version_hasnlink(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASNLINK(sbp) xfs_sb_version_hasnlink(sbp) -#else -#define XFS_SB_VERSION_HASNLINK(sbp) \ - (((sbp)->sb_versionnum == XFS_SB_VERSION_3) || \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_NLINKBIT))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDNLINK) -void xfs_sb_version_addnlink(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDNLINK(sbp) xfs_sb_version_addnlink(sbp) -#else -#define XFS_SB_VERSION_ADDNLINK(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum <= XFS_SB_VERSION_2 ? \ - XFS_SB_VERSION_3 : \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_NLINKBIT))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASQUOTA) -int xfs_sb_version_hasquota(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASQUOTA(sbp) xfs_sb_version_hasquota(sbp) -#else -#define XFS_SB_VERSION_HASQUOTA(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_QUOTABIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDQUOTA) -void xfs_sb_version_addquota(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDQUOTA(sbp) xfs_sb_version_addquota(sbp) -#else -#define XFS_SB_VERSION_ADDQUOTA(sbp) \ - ((sbp)->sb_versionnum = \ - (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4 ? \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_QUOTABIT) : \ - (XFS_SB_VERSION_TONEW((sbp)->sb_versionnum) | \ - XFS_SB_VERSION_QUOTABIT))) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASALIGN) -int xfs_sb_version_hasalign(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASALIGN(sbp) xfs_sb_version_hasalign(sbp) -#else -#define XFS_SB_VERSION_HASALIGN(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_ALIGNBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_SUBALIGN) -void xfs_sb_version_subalign(xfs_sb_t *sbp); -#define XFS_SB_VERSION_SUBALIGN(sbp) xfs_sb_version_subalign(sbp) -#else -#define XFS_SB_VERSION_SUBALIGN(sbp) \ - ((sbp)->sb_versionnum = \ - XFS_SB_VERSION_TOOLD((sbp)->sb_versionnum & ~XFS_SB_VERSION_ALIGNBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASDALIGN) -int xfs_sb_version_hasdalign(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASDALIGN(sbp) xfs_sb_version_hasdalign(sbp) -#else -#define XFS_SB_VERSION_HASDALIGN(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_DALIGNBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDDALIGN) -int xfs_sb_version_adddalign(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDDALIGN(sbp) xfs_sb_version_adddalign(sbp) -#else -#define XFS_SB_VERSION_ADDDALIGN(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_DALIGNBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASSHARED) -int xfs_sb_version_hasshared(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASSHARED(sbp) xfs_sb_version_hasshared(sbp) -#else -#define XFS_SB_VERSION_HASSHARED(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_SHAREDBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDSHARED) -int xfs_sb_version_addshared(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDSHARED(sbp) xfs_sb_version_addshared(sbp) -#else -#define XFS_SB_VERSION_ADDSHARED(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_SHAREDBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_SUBSHARED) -int xfs_sb_version_subshared(xfs_sb_t *sbp); -#define XFS_SB_VERSION_SUBSHARED(sbp) xfs_sb_version_subshared(sbp) -#else -#define XFS_SB_VERSION_SUBSHARED(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum & ~XFS_SB_VERSION_SHAREDBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASDIRV2) -int xfs_sb_version_hasdirv2(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASDIRV2(sbp) xfs_sb_version_hasdirv2(sbp) -#else -#define XFS_SB_VERSION_HASDIRV2(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_HASEXTFLGBIT) -int xfs_sb_version_hasextflgbit(xfs_sb_t *sbp); -#define XFS_SB_VERSION_HASEXTFLGBIT(sbp) xfs_sb_version_hasextflgbit(sbp) -#else -#define XFS_SB_VERSION_HASEXTFLGBIT(sbp) \ - ((XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4) && \ - ((sbp)->sb_versionnum & XFS_SB_VERSION_EXTFLGBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_ADDEXTFLGBIT) -int xfs_sb_version_addextflgbit(xfs_sb_t *sbp); -#define XFS_SB_VERSION_ADDEXTFLGBIT(sbp) xfs_sb_version_addextflgbit(sbp) -#else -#define XFS_SB_VERSION_ADDEXTFLGBIT(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum | XFS_SB_VERSION_EXTFLGBIT)) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_VERSION_SUBEXTFLGBIT) -int xfs_sb_version_subextflgbit(xfs_sb_t *sbp); -#define XFS_SB_VERSION_SUBEXTFLGBIT(sbp) xfs_sb_version_subextflgbit(sbp) -#else -#define XFS_SB_VERSION_SUBEXTFLGBIT(sbp) \ - ((sbp)->sb_versionnum = \ - ((sbp)->sb_versionnum & ~XFS_SB_VERSION_EXTFLGBIT)) -#endif - -/* - * end of superblock version macros - */ - -#define XFS_SB_DADDR ((xfs_daddr_t)0) /* daddr in file system/ag */ -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_SB_BLOCK) -xfs_agblock_t xfs_sb_block(struct xfs_mount *mp); -#define XFS_SB_BLOCK(mp) xfs_sb_block(mp) -#else -#define XFS_SB_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_SB_DADDR) -#endif - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_HDR_BLOCK) -xfs_agblock_t xfs_hdr_block(struct xfs_mount *mp, xfs_daddr_t d); -#define XFS_HDR_BLOCK(mp,d) xfs_hdr_block(mp,d) -#else -#define XFS_HDR_BLOCK(mp,d) ((xfs_agblock_t)(XFS_BB_TO_FSBT(mp,d))) -#endif -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_DADDR_TO_FSB) -xfs_fsblock_t xfs_daddr_to_fsb(struct xfs_mount *mp, xfs_daddr_t d); -#define XFS_DADDR_TO_FSB(mp,d) xfs_daddr_to_fsb(mp,d) -#else -#define XFS_DADDR_TO_FSB(mp,d) \ - XFS_AGB_TO_FSB(mp, XFS_DADDR_TO_AGNO(mp,d), XFS_DADDR_TO_AGBNO(mp,d)) -#endif -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_FSB_TO_DADDR) -xfs_daddr_t xfs_fsb_to_daddr(struct xfs_mount *mp, xfs_fsblock_t fsbno); -#define XFS_FSB_TO_DADDR(mp,fsbno) xfs_fsb_to_daddr(mp,fsbno) -#else -#define XFS_FSB_TO_DADDR(mp,fsbno) \ - XFS_AGB_TO_DADDR(mp, XFS_FSB_TO_AGNO(mp,fsbno), \ - XFS_FSB_TO_AGBNO(mp,fsbno)) -#endif - -/* - * File system block to basic block conversions. - */ -#define XFS_FSB_TO_BB(mp,fsbno) ((fsbno) << (mp)->m_blkbb_log) -#define XFS_BB_TO_FSB(mp,bb) \ - (((bb) + (XFS_FSB_TO_BB(mp,1) - 1)) >> (mp)->m_blkbb_log) -#define XFS_BB_TO_FSBT(mp,bb) ((bb) >> (mp)->m_blkbb_log) -#define XFS_BB_FSB_OFFSET(mp,bb) ((bb) & ((mp)->m_bsize - 1)) - -/* - * File system block to byte conversions. - */ -#define XFS_FSB_TO_B(mp,fsbno) ((xfs_fsize_t)(fsbno) << \ - (mp)->m_sb.sb_blocklog) -#define XFS_B_TO_FSB(mp,b) \ - ((((uint64_t)(b)) + (mp)->m_blockmask) >> (mp)->m_sb.sb_blocklog) -#define XFS_B_TO_FSBT(mp,b) (((uint64_t)(b)) >> (mp)->m_sb.sb_blocklog) -#define XFS_B_FSB_OFFSET(mp,b) ((b) & (mp)->m_blockmask) - -#if XFS_WANT_FUNCS || (XFS_WANT_SPACE && XFSSO_XFS_BUF_TO_SBP) -xfs_sb_t *xfs_buf_to_sbp(struct xfs_buf *bp); -#define XFS_BUF_TO_SBP(bp) xfs_buf_to_sbp(bp) -#else -#define XFS_BUF_TO_SBP(bp) ((xfs_sb_t *)XFS_BUF_PTR(bp)) -#endif - -#endif /* __XFS_SB_H__ */ diff --git a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_types.h b/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_types.h deleted file mode 100644 index 643a19b95e..0000000000 --- a/usr/src/lib/libparted/common/libparted/fs/xfs/xfs_types.h +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 3 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. - * - * Further, this software is distributed without any warranty that it is - * free of the rightful claim of any third person regarding infringement - * or the like. Any license provided herein, whether implied or - * otherwise, applies only to this software file. Patent licenses, if - * any, provided herein do not apply to combinations of this program with - * other software, or any other product whatsoever. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, - * Mountain View, CA 94043, or: - * - * http://www.sgi.com - * - * For further information regarding this notice, see: - * - * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ - */ -#ifndef __XFS_TYPES_H__ -#define __XFS_TYPES_H__ - -/* - * Some types are conditional based on the selected configuration. - * Set XFS_BIG_FILES=1 or 0 and XFS_BIG_FILESYSTEMS=1 or 0 depending - * on the desired configuration. - * XFS_BIG_FILES needs pgno_t to be 64 bits (64-bit kernels). - * XFS_BIG_FILESYSTEMS needs daddr_t to be 64 bits (N32 and 64-bit kernels). - * - * Expect these to be set from klocaldefs, or from the machine-type - * defs files for the normal case. - */ - -#define XFS_BIG_FILES 1 -#define XFS_BIG_FILESYSTEMS 1 - -typedef uint32_t xfs_agblock_t; /* blockno in alloc. group */ -typedef uint32_t xfs_extlen_t; /* extent length in blocks */ -typedef uint32_t xfs_agnumber_t; /* allocation group number */ -typedef int32_t xfs_extnum_t; /* # of extents in a file */ -typedef int16_t xfs_aextnum_t; /* # extents in an attribute fork */ -typedef int64_t xfs_fsize_t; /* bytes in a file */ -typedef uint64_t xfs_ufsize_t; /* unsigned bytes in a file */ - -typedef int32_t xfs_suminfo_t; /* type of bitmap summary info */ -typedef int32_t xfs_rtword_t; /* word type for bitmap manipulations */ - -typedef int64_t xfs_lsn_t; /* log sequence number */ -typedef int32_t xfs_tid_t; /* transaction identifier */ - -typedef uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ -typedef uint32_t xfs_dahash_t; /* dir/attr hash value */ - -typedef uint16_t xfs_prid_t; /* prid_t truncated to 16bits in XFS */ - -/* - * These types are 64 bits on disk but are either 32 or 64 bits in memory. - * Disk based types: - */ -typedef uint64_t xfs_dfsbno_t; /* blockno in filesystem (agno|agbno) */ -typedef uint64_t xfs_drfsbno_t; /* blockno in filesystem (raw) */ -typedef uint64_t xfs_drtbno_t; /* extent (block) in realtime area */ -typedef uint64_t xfs_dfiloff_t; /* block number in a file */ -typedef uint64_t xfs_dfilblks_t; /* number of blocks in a file */ - -/* - * Memory based types are conditional. - */ -#if XFS_BIG_FILESYSTEMS -typedef uint64_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ -typedef uint64_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ -typedef uint64_t xfs_rtblock_t; /* extent (block) in realtime area */ -typedef int64_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */ -#else -typedef uint32_t xfs_fsblock_t; /* blockno in filesystem (agno|agbno) */ -typedef uint32_t xfs_rfsblock_t; /* blockno in filesystem (raw) */ -typedef uint32_t xfs_rtblock_t; /* extent (block) in realtime area */ -typedef int32_t xfs_srtblock_t; /* signed version of xfs_rtblock_t */ -#endif -#if XFS_BIG_FILES -typedef uint64_t xfs_fileoff_t; /* block number in a file */ -typedef int64_t xfs_sfiloff_t; /* signed block number in a file */ -typedef uint64_t xfs_filblks_t; /* number of blocks in a file */ -#else -typedef uint32_t xfs_fileoff_t; /* block number in a file */ -typedef int32_t xfs_sfiloff_t; /* signed block number in a file */ -typedef uint32_t xfs_filblks_t; /* number of blocks in a file */ -#endif - -typedef uint8_t xfs_arch_t; /* architecutre of an xfs fs */ - -/* - * Null values for the types. - */ -#define NULLDFSBNO ((xfs_dfsbno_t)-1) -#define NULLDRFSBNO ((xfs_drfsbno_t)-1) -#define NULLDRTBNO ((xfs_drtbno_t)-1) -#define NULLDFILOFF ((xfs_dfiloff_t)-1) - -#define NULLFSBLOCK ((xfs_fsblock_t)-1) -#define NULLRFSBLOCK ((xfs_rfsblock_t)-1) -#define NULLRTBLOCK ((xfs_rtblock_t)-1) -#define NULLFILEOFF ((xfs_fileoff_t)-1) - -#define NULLAGBLOCK ((xfs_agblock_t)-1) -#define NULLAGNUMBER ((xfs_agnumber_t)-1) -#define NULLEXTNUM ((xfs_extnum_t)-1) - -#define NULLCOMMITLSN ((xfs_lsn_t)-1) - -/* - * Max values for extlen, extnum, aextnum. - */ -#define MAXEXTLEN ((xfs_extlen_t)0x001fffff) /* 21 bits */ -#define MAXEXTNUM ((xfs_extnum_t)0x7fffffff) /* signed int */ -#define MAXAEXTNUM ((xfs_aextnum_t)0x7fff) /* signed short */ - -/* - * MAXNAMELEN is the length (including the terminating null) of - * the longest permissible file (component) name. - */ -#define MAXNAMELEN 256 - -typedef enum { - XFS_LOOKUP_EQi, XFS_LOOKUP_LEi, XFS_LOOKUP_GEi -} xfs_lookup_t; - -typedef enum { - XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, - XFS_BTNUM_MAX -} xfs_btnum_t; - - -#ifdef CONFIG_PROC_FS -/* - * XFS global statistics - */ -struct xfsstats { -# define XFSSTAT_END_EXTENT_ALLOC 4 - uint32_t xs_allocx; - uint32_t xs_allocb; - uint32_t xs_freex; - uint32_t xs_freeb; -# define XFSSTAT_END_ALLOC_BTREE (XFSSTAT_END_EXTENT_ALLOC+4) - uint32_t xs_abt_lookup; - uint32_t xs_abt_compare; - uint32_t xs_abt_insrec; - uint32_t xs_abt_delrec; -# define XFSSTAT_END_BLOCK_MAPPING (XFSSTAT_END_ALLOC_BTREE+7) - uint32_t xs_blk_mapr; - uint32_t xs_blk_mapw; - uint32_t xs_blk_unmap; - uint32_t xs_add_exlist; - uint32_t xs_del_exlist; - uint32_t xs_look_exlist; - uint32_t xs_cmp_exlist; -# define XFSSTAT_END_BLOCK_MAP_BTREE (XFSSTAT_END_BLOCK_MAPPING+4) - uint32_t xs_bmbt_lookup; - uint32_t xs_bmbt_compare; - uint32_t xs_bmbt_insrec; - uint32_t xs_bmbt_delrec; -# define XFSSTAT_END_DIRECTORY_OPS (XFSSTAT_END_BLOCK_MAP_BTREE+4) - uint32_t xs_dir_lookup; - uint32_t xs_dir_create; - uint32_t xs_dir_remove; - uint32_t xs_dir_getdents; -# define XFSSTAT_END_TRANSACTIONS (XFSSTAT_END_DIRECTORY_OPS+3) - uint32_t xs_trans_sync; - uint32_t xs_trans_async; - uint32_t xs_trans_empty; -# define XFSSTAT_END_INODE_OPS (XFSSTAT_END_TRANSACTIONS+7) - uint32_t xs_ig_attempts; - uint32_t xs_ig_found; - uint32_t xs_ig_frecycle; - uint32_t xs_ig_missed; - uint32_t xs_ig_dup; - uint32_t xs_ig_reclaims; - uint32_t xs_ig_attrchg; -# define XFSSTAT_END_LOG_OPS (XFSSTAT_END_INODE_OPS+5) - uint32_t xs_log_writes; - uint32_t xs_log_blocks; - uint32_t xs_log_noiclogs; - uint32_t xs_log_force; - uint32_t xs_log_force_sleep; -# define XFSSTAT_END_TAIL_PUSHING (XFSSTAT_END_LOG_OPS+10) - uint32_t xs_try_logspace; - uint32_t xs_sleep_logspace; - uint32_t xs_push_ail; - uint32_t xs_push_ail_success; - uint32_t xs_push_ail_pushbuf; - uint32_t xs_push_ail_pinned; - uint32_t xs_push_ail_locked; - uint32_t xs_push_ail_flushing; - uint32_t xs_push_ail_restarts; - uint32_t xs_push_ail_flush; -# define XFSSTAT_END_WRITE_CONVERT (XFSSTAT_END_TAIL_PUSHING+2) - uint32_t xs_xstrat_quick; - uint32_t xs_xstrat_split; -# define XFSSTAT_END_READ_WRITE_OPS (XFSSTAT_END_WRITE_CONVERT+2) - uint32_t xs_write_calls; - uint32_t xs_read_calls; -# define XFSSTAT_END_ATTRIBUTE_OPS (XFSSTAT_END_READ_WRITE_OPS+4) - uint32_t xs_attr_get; - uint32_t xs_attr_set; - uint32_t xs_attr_remove; - uint32_t xs_attr_list; -# define XFSSTAT_END_QUOTA_OPS (XFSSTAT_END_ATTRIBUTE_OPS+8) - uint32_t xs_qm_dqreclaims; - uint32_t xs_qm_dqreclaim_misses; - uint32_t xs_qm_dquot_dups; - uint32_t xs_qm_dqcachemisses; - uint32_t xs_qm_dqcachehits; - uint32_t xs_qm_dqwants; - uint32_t xs_qm_dqshake_reclaims; - uint32_t xs_qm_dqinact_reclaims; -# define XFSSTAT_END_INODE_CLUSTER (XFSSTAT_END_QUOTA_OPS+3) - uint32_t xs_iflush_count; - uint32_t xs_icluster_flushcnt; - uint32_t xs_icluster_flushinode; -# define XFSSTAT_END_VNODE_OPS (XFSSTAT_END_INODE_CLUSTER+8) - uint32_t vn_active; /* # vnodes not on free lists */ - uint32_t vn_alloc; /* # times vn_alloc called */ - uint32_t vn_get; /* # times vn_get called */ - uint32_t vn_hold; /* # times vn_hold called */ - uint32_t vn_rele; /* # times vn_rele called */ - uint32_t vn_reclaim; /* # times vn_reclaim called */ - uint32_t vn_remove; /* # times vn_remove called */ - uint32_t vn_free; /* # times vn_free called */ - struct xfsstats_xpc { - uint64_t xs_xstrat_bytes; - uint64_t xs_write_bytes; - uint64_t xs_read_bytes; - } xpc; -} xfsstats; - -# define XFS_STATS_INC(count) ( xfsstats.##count ++ ) -# define XFS_STATS_DEC(count) ( xfsstats.##count -- ) -# define XFS_STATS_ADD(count, inc) ( xfsstats.##count += (inc) ) -# define XFS_STATS64_INC(count) ( xfsstats.xpc.##count ++ ) -# define XFS_STATS64_ADD(count, inc) ( xfsstats.xpc.##count += (inc) ) -#else /* !CONFIG_PROC_FS */ -# define XFS_STATS_INC(count) -# define XFS_STATS_DEC(count) -# define XFS_STATS_ADD(count, inc) -# define XFS_STATS64_INC(count) -# define XFS_STATS64_ADD(count, inc) -#endif /* !CONFIG_PROC_FS */ - - -#ifdef __KERNEL__ - -/* juggle IRIX device numbers - still used in ondisk structures */ - -#define IRIX_DEV_BITSMAJOR 14 -#define IRIX_DEV_BITSMINOR 18 -#define IRIX_DEV_MAXMAJ 0x1ff -#define IRIX_DEV_MAXMIN 0x3ffff -#define IRIX_DEV_MAJOR(dev) ((int)(((unsigned)(dev)>>IRIX_DEV_BITSMINOR) \ - & IRIX_DEV_MAXMAJ)) -#define IRIX_DEV_MINOR(dev) ((int)((dev)&IRIX_DEV_MAXMIN)) -#define IRIX_MKDEV(major,minor) ((xfs_dev_t)(((major)<. - - Contributor: Matt Wilson -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define AIX_LABEL_MAGIC 0xc9c2d4c1 - -static PedDiskType aix_disk_type; - -static inline int -aix_label_magic_get (const char *label) -{ - return *(unsigned int *)label; -} - -static inline void -aix_label_magic_set (char *label, int magic_val) -{ - *(unsigned int *)label = magic_val; -} - -/* Read a single sector, of length DEV->sector_size, into malloc'd storage. - If the read fails, free the memory and return zero without modifying *BUF. - Otherwise, set *BUF to the new buffer and return 1. */ -static int -read_sector (const PedDevice *dev, char **buf) -{ - char *b = ped_malloc (dev->sector_size); - PED_ASSERT (b != NULL, return 0); - if (!ped_device_read (dev, b, 0, 1)) { - ped_free (b); - return 0; - } - *buf = b; - return 1; -} - -static int -aix_probe (const PedDevice *dev) -{ - PED_ASSERT (dev != NULL, return 0); - - char *label; - if (!read_sector (dev, &label)) - return 0; - unsigned int magic = aix_label_magic_get (label); - ped_free (label); - return magic == AIX_LABEL_MAGIC; -} - -#ifndef DISCOVER_ONLY -static int -aix_clobber (PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - - if (!aix_probe (dev)) - return 0; - - char *label; - if (!read_sector (dev, &label)) - return 0; - - aix_label_magic_set (label, 0); - int result = ped_device_write (dev, label, 0, 1); - ped_free (label); - return result; -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk* -aix_alloc (const PedDevice* dev) -{ - PedDisk* disk; - - disk = _ped_disk_alloc (dev, &aix_disk_type); - if (!disk) - return NULL; - - return disk; -} - -static PedDisk* -aix_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - - new_disk = ped_disk_new_fresh (disk->dev, &aix_disk_type); - if (!new_disk) - return NULL; - - return new_disk; -} - -static void -aix_free (PedDisk *disk) -{ - _ped_disk_free (disk); -} - -static int -aix_read (PedDisk* disk) -{ - ped_disk_delete_all (disk); - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for reading AIX disk labels is " - "is not implemented yet.")); - return 0; -} - -#ifndef DISCOVER_ONLY -static int -aix_write (const PedDisk* disk) -{ - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for writing AIX disk labels is " - "is not implemented yet.")); - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -aix_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for adding partitions to AIX disk " - "labels is not implemented yet.")); - return NULL; -} - -static PedPartition* -aix_partition_duplicate (const PedPartition* part) -{ - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for duplicating partitions in AIX " - "disk labels is not implemented yet.")); - return NULL; -} - -static void -aix_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - _ped_partition_free (part); -} - -static int -aix_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for setting system type of partitions " - "in AIX disk labels is not implemented yet.")); - return 0; -} - -static int -aix_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - ped_exception_throw (PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Support for setting flags " - "in AIX disk labels is not implemented yet.")); - return 0; -} - -static int -aix_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - return 0; -} - - -static int -aix_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - return 0; -} - - -static int -aix_get_max_primary_partition_count (const PedDisk* disk) -{ - return 4; -} - -static int -aix_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - return 1; -} - -static int -aix_partition_enumerate (PedPartition* part) -{ - return 1; -} - -static int -aix_alloc_metadata (PedDisk* disk) -{ - return 1; -} - -static PedDiskOps aix_disk_ops = { - .probe = aix_probe, -#ifndef DISCOVER_ONLY - .clobber = aix_clobber, -#else - .clobber = NULL, -#endif - .alloc = aix_alloc, - .duplicate = aix_duplicate, - .free = aix_free, - .read = aix_read, -#ifndef DISCOVER_ONLY - .write = aix_write, -#else - .write = NULL, -#endif - - .partition_new = aix_partition_new, - .partition_duplicate = aix_partition_duplicate, - .partition_destroy = aix_partition_destroy, - .partition_set_system = aix_partition_set_system, - .partition_set_flag = aix_partition_set_flag, - .partition_get_flag = aix_partition_get_flag, - .partition_is_flag_available = aix_partition_is_flag_available, - .partition_align = aix_partition_align, - .partition_enumerate = aix_partition_enumerate, - .alloc_metadata = aix_alloc_metadata, - .get_max_primary_partition_count = - aix_get_max_primary_partition_count, - - .partition_set_name = NULL, - .partition_get_name = NULL, -}; - -static PedDiskType aix_disk_type = { - .next = NULL, - .name = "aix", - .ops = &aix_disk_ops, - .features = 0 -}; - -void -ped_disk_aix_init () -{ - ped_disk_type_register (&aix_disk_type); -} - -void -ped_disk_aix_done () -{ - ped_disk_type_unregister (&aix_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/bsd.c b/usr/src/lib/libparted/common/libparted/labels/bsd.c deleted file mode 100644 index c570d2a1e1..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/bsd.c +++ /dev/null @@ -1,633 +0,0 @@ -/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - Contributor: Matt Wilson -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* struct's & #define's stolen from libfdisk, which probably came from - * Linux... - */ - -#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */ -#define BSD_MAXPARTITIONS 8 -#define BSD_FS_UNUSED 0 /* disklabel unused partition entry ID */ -#define BSD_LABEL_OFFSET 64 - -#define BSD_DTYPE_SMD 1 /* SMD, XSMD; VAX hp/up */ -#define BSD_DTYPE_MSCP 2 /* MSCP */ -#define BSD_DTYPE_DEC 3 /* other DEC (rk, rl) */ -#define BSD_DTYPE_SCSI 4 /* SCSI */ -#define BSD_DTYPE_ESDI 5 /* ESDI interface */ -#define BSD_DTYPE_ST506 6 /* ST506 etc. */ -#define BSD_DTYPE_HPIB 7 /* CS/80 on HP-IB */ -#define BSD_DTYPE_HPFL 8 /* HP Fiber-link */ -#define BSD_DTYPE_FLOPPY 10 /* floppy */ - -#define BSD_BBSIZE 8192 /* size of boot area, with label */ -#define BSD_SBSIZE 8192 /* max size of fs superblock */ - -typedef struct _BSDRawPartition BSDRawPartition; -typedef struct _BSDRawLabel BSDRawLabel; - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct _BSDRawPartition { /* the partition table */ - uint32_t p_size; /* number of sectors in partition */ - uint32_t p_offset; /* starting sector */ - uint32_t p_fsize; /* file system basic fragment size */ - uint8_t p_fstype; /* file system type, see below */ - uint8_t p_frag; /* file system fragments per block */ - uint16_t p_cpg; /* file system cylinders per group */ -} __attribute__((packed)); -#ifdef __sun -#pragma pack() -#endif - -#ifdef __sun -#pragma pack(1) -#endif -struct _BSDRawLabel { - uint32_t d_magic; /* the magic number */ - int16_t d_type; /* drive type */ - int16_t d_subtype; /* controller/d_type specific */ - int8_t d_typename[16]; /* type name, e.g. "eagle" */ - int8_t d_packname[16]; /* pack identifier */ - uint32_t d_secsize; /* # of bytes per sector */ - uint32_t d_nsectors; /* # of data sectors per track */ - uint32_t d_ntracks; /* # of tracks per cylinder */ - uint32_t d_ncylinders; /* # of data cylinders per unit */ - uint32_t d_secpercyl; /* # of data sectors per cylinder */ - uint32_t d_secperunit; /* # of data sectors per unit */ - uint16_t d_sparespertrack; /* # of spare sectors per track */ - uint16_t d_sparespercyl; /* # of spare sectors per cylinder */ - uint32_t d_acylinders; /* # of alt. cylinders per unit */ - uint16_t d_rpm; /* rotational speed */ - uint16_t d_interleave; /* hardware sector interleave */ - uint16_t d_trackskew; /* sector 0 skew, per track */ - uint16_t d_cylskew; /* sector 0 skew, per cylinder */ - uint32_t d_headswitch; /* head switch time, usec */ - uint32_t d_trkseek; /* track-to-track seek, usec */ - uint32_t d_flags; /* generic flags */ -#define NDDATA 5 - uint32_t d_drivedata[NDDATA]; /* drive-type specific information */ -#define NSPARE 5 - uint32_t d_spare[NSPARE]; /* reserved for future use */ - uint32_t d_magic2; /* the magic number (again) */ - uint16_t d_checksum; /* xor of data incl. partitions */ - - /* file system and partition information: */ - uint16_t d_npartitions; /* number of partitions in following */ - uint32_t d_bbsize; /* size of boot area at sn0, bytes */ - uint32_t d_sbsize; /* max size of fs superblock, bytes */ - BSDRawPartition d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ -} __attribute__((packed)); -#ifdef __sun -#pragma pack() -#endif - -typedef struct { - char boot_code [512]; -} BSDDiskData; - -typedef struct { - uint8_t type; -} BSDPartitionData; - -static PedDiskType bsd_disk_type; - -/* XXX fixme: endian? */ -static unsigned short -xbsd_dkcksum (BSDRawLabel *lp) { - unsigned short *start, *end; - unsigned short sum = 0; - - lp->d_checksum = 0; - start = (u_short*) lp; - end = (u_short*) &lp->d_partitions [ - PED_LE16_TO_CPU (lp->d_npartitions)]; - while (start < end) - sum ^= *start++; - return sum; -} - -/* XXX fixme: endian? */ -static void -alpha_bootblock_checksum (char *boot) { - uint64_t *dp, sum; - int i; - - dp = (uint64_t *)boot; - sum = 0; - for (i = 0; i < 63; i++) - sum += dp[i]; - dp[63] = sum; -} - - -static int -bsd_probe (const PedDevice *dev) -{ - char boot[512]; - BSDRawLabel *label; - - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size != 512) - return 0; - - if (!ped_device_read (dev, boot, 0, 1)) - return 0; - - label = (BSDRawLabel *) (boot + BSD_LABEL_OFFSET); - - alpha_bootblock_checksum(boot); - - /* check magic */ - if (PED_LE32_TO_CPU (label->d_magic) != BSD_DISKMAGIC) - return 0; - - return 1; -} - -static PedDisk* -bsd_alloc (const PedDevice* dev) -{ - PedDisk* disk; - BSDDiskData* bsd_specific; - BSDRawLabel* label; - - PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0); - - disk = _ped_disk_alloc ((PedDevice*)dev, &bsd_disk_type); - if (!disk) - goto error; - disk->disk_specific = bsd_specific = ped_malloc (sizeof (BSDDiskData)); - if (!bsd_specific) - goto error_free_disk; - /* Initialize the first byte to zero, so that the code in bsd_write - knows to call _probe_and_add_boot_code. Initializing all of the - remaining buffer is a little wasteful, but the alternative is to - figure out why a block at offset 340 would otherwise be used - uninitialized. */ - memset(bsd_specific->boot_code, 0, sizeof (bsd_specific->boot_code)); - - label = (BSDRawLabel*) (bsd_specific->boot_code + BSD_LABEL_OFFSET); - - label->d_magic = PED_CPU_TO_LE32 (BSD_DISKMAGIC); - label->d_type = PED_CPU_TO_LE16 (BSD_DTYPE_SCSI); - label->d_flags = 0; - label->d_secsize = PED_CPU_TO_LE16 (dev->sector_size); - label->d_nsectors = PED_CPU_TO_LE32 (dev->bios_geom.sectors); - label->d_ntracks = PED_CPU_TO_LE32 (dev->bios_geom.heads); - label->d_ncylinders = PED_CPU_TO_LE32 (dev->bios_geom.cylinders); - label->d_secpercyl = PED_CPU_TO_LE32 (dev->bios_geom.sectors - * dev->bios_geom.heads); - label->d_secperunit - = PED_CPU_TO_LE32 (dev->bios_geom.sectors - * dev->bios_geom.heads - * dev->bios_geom.cylinders); - - label->d_rpm = PED_CPU_TO_LE16 (3600); - label->d_interleave = PED_CPU_TO_LE16 (1);; - label->d_trackskew = 0; - label->d_cylskew = 0; - label->d_headswitch = 0; - label->d_trkseek = 0; - - label->d_magic2 = PED_CPU_TO_LE32 (BSD_DISKMAGIC); - label->d_bbsize = PED_CPU_TO_LE32 (BSD_BBSIZE); - label->d_sbsize = PED_CPU_TO_LE32 (BSD_SBSIZE); - - label->d_npartitions = 0; - label->d_checksum = xbsd_dkcksum (label); - return disk; - -error_free_disk: - ped_free (disk); -error: - return NULL; -} - -static PedDisk* -bsd_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - BSDDiskData* new_bsd_data; - BSDDiskData* old_bsd_data = (BSDDiskData*) disk->disk_specific; - - new_disk = ped_disk_new_fresh (disk->dev, &bsd_disk_type); - if (!new_disk) - return NULL; - - new_bsd_data = (BSDDiskData*) new_disk->disk_specific; - memcpy (new_bsd_data->boot_code, old_bsd_data->boot_code, 512); - return new_disk; -} - -static void -bsd_free (PedDisk* disk) -{ - ped_free (disk->disk_specific); - _ped_disk_free (disk); -} - -#ifndef DISCOVER_ONLY -static int -bsd_clobber (PedDevice* dev) -{ - char boot [512]; - BSDRawLabel* label = (BSDRawLabel *) (boot + BSD_LABEL_OFFSET); - - if (!ped_device_read (dev, boot, 0, 1)) - return 0; - label->d_magic = 0; - return ped_device_write (dev, (void*) boot, 0, 1); -} -#endif /* !DISCOVER_ONLY */ - -static int -bsd_read (PedDisk* disk) -{ - BSDDiskData* bsd_specific = (BSDDiskData*) disk->disk_specific; - BSDRawLabel* label; - int i; - - ped_disk_delete_all (disk); - - if (!ped_device_read (disk->dev, bsd_specific->boot_code, 0, 1)) - goto error; - label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET); - - for (i = 1; i <= BSD_MAXPARTITIONS; i++) { - PedPartition* part; - BSDPartitionData* bsd_part_data; - PedSector start; - PedSector end; - PedConstraint* constraint_exact; - - if (!label->d_partitions[i - 1].p_size - || !label->d_partitions[i - 1].p_fstype) - continue; - start = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset); - end = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset) - + PED_LE32_TO_CPU(label->d_partitions[i - 1].p_size) - 1; - part = ped_partition_new (disk, 0, NULL, start, end); - if (!part) - goto error; - bsd_part_data = part->disk_specific; - bsd_part_data->type = label->d_partitions[i - 1].p_fstype; - part->num = i; - part->fs_type = ped_file_system_probe (&part->geom); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error; - ped_constraint_destroy (constraint_exact); - } - - return 1; - -error: - return 0; -} - -static void -_probe_and_add_boot_code (const PedDisk* disk) -{ - BSDDiskData* bsd_specific; - BSDRawLabel* old_label; - char old_boot_code [512]; - - bsd_specific = (BSDDiskData*) disk->disk_specific; - old_label = (BSDRawLabel*) (old_boot_code + BSD_LABEL_OFFSET); - - if (!ped_device_read (disk->dev, old_boot_code, 0, 1)) - return; - if (old_boot_code [0] - && old_label->d_magic == PED_CPU_TO_LE32 (BSD_DISKMAGIC)) - memcpy (bsd_specific->boot_code, old_boot_code, 512); -} - -#ifndef DISCOVER_ONLY -static int -bsd_write (const PedDisk* disk) -{ - BSDDiskData* bsd_specific; - BSDRawLabel* label; - BSDPartitionData* bsd_data; - PedPartition* part; - int i; - int max_part = 0; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - bsd_specific = (BSDDiskData*) disk->disk_specific; - label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET); - - if (!bsd_specific->boot_code [0]) - _probe_and_add_boot_code (disk); - - memset (label->d_partitions, 0, - sizeof (BSDRawPartition) * BSD_MAXPARTITIONS); - - for (i = 1; i <= BSD_MAXPARTITIONS; i++) { - part = ped_disk_get_partition (disk, i); - if (!part) - continue; - bsd_data = part->disk_specific; - label->d_partitions[i - 1].p_fstype = bsd_data->type; - label->d_partitions[i - 1].p_offset - = PED_CPU_TO_LE32 (part->geom.start); - label->d_partitions[i - 1].p_size - = PED_CPU_TO_LE32 (part->geom.length); - max_part = i; - } - - label->d_npartitions = PED_CPU_TO_LE16 (max_part) + 1; - label->d_checksum = xbsd_dkcksum (label); - - alpha_bootblock_checksum (bsd_specific->boot_code); - - if (!ped_device_write (disk->dev, (void*) bsd_specific->boot_code, - 0, 1)) - goto error; - return ped_device_sync (disk->dev); - -error: - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -bsd_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - BSDPartitionData* bsd_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (ped_partition_is_active (part)) { - part->disk_specific - = bsd_data = ped_malloc (sizeof (BSDPartitionData)); - if (!bsd_data) - goto error_free_part; - bsd_data->type = 0; - } else { - part->disk_specific = NULL; - } - return part; - - ped_free (bsd_data); -error_free_part: - ped_free (part); -error: - return 0; -} - -static PedPartition* -bsd_partition_duplicate (const PedPartition* part) -{ - PedPartition* new_part; - BSDPartitionData* new_bsd_data; - BSDPartitionData* old_bsd_data; - - new_part = ped_partition_new (part->disk, part->type, - part->fs_type, part->geom.start, - part->geom.end); - if (!new_part) - return NULL; - new_part->num = part->num; - - old_bsd_data = (BSDPartitionData*) part->disk_specific; - new_bsd_data = (BSDPartitionData*) new_part->disk_specific; - new_bsd_data->type = old_bsd_data->type; - return new_part; -} - -static void -bsd_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) - ped_free (part->disk_specific); - _ped_partition_free (part); -} - -static int -bsd_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - BSDPartitionData* bsd_data = part->disk_specific; - - part->fs_type = fs_type; - - if (!fs_type) - bsd_data->type = 0x8; - else if (!strcmp (fs_type->name, "linux-swap")) - bsd_data->type = 0x1; - else - bsd_data->type = 0x8; - - return 1; -} - -static int -bsd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - /* no flags for bsd */ - return 0; -} - -static int -bsd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - /* no flags for bsd */ - return 0; -} - -static int -bsd_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - /* no flags for bsd */ - return 0; -} - - -static int -bsd_get_max_primary_partition_count (const PedDisk* disk) -{ - return BSD_MAXPARTITIONS; -} - -static PedConstraint* -_get_constraint (const PedDevice* dev) -{ - PedGeometry max; - - ped_geometry_init (&max, dev, 1, dev->length - 1); - return ped_constraint_new_from_max (&max); -} - -static int -bsd_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - if (_ped_partition_attempt_align (part, constraint, - _get_constraint (part->disk->dev))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -bsd_partition_enumerate (PedPartition* part) -{ - int i; - PedPartition* p; - - /* never change the partition numbers */ - if (part->num != -1) - return 1; - for (i = 1; i <= BSD_MAXPARTITIONS; i++) { - p = ped_disk_get_partition (part->disk, i); - if (!p) { - part->num = i; - return 1; - } - } - - /* failed to allocate a number */ -#ifndef DISCOVER_ONLY - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Unable to allocate a bsd disklabel slot.")); -#endif - return 0; -} - -static int -bsd_alloc_metadata (PedDisk* disk) -{ - PedPartition* new_part; - PedConstraint* constraint_any = NULL; - - PED_ASSERT (disk != NULL, goto error); - PED_ASSERT (disk->dev != NULL, goto error); - - constraint_any = ped_constraint_any (disk->dev); - - /* allocate 1 sector for the disk label at the start */ - new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, 0); - if (!new_part) - goto error; - - if (!ped_disk_add_partition (disk, new_part, constraint_any)) { - ped_partition_destroy (new_part); - goto error; - } - - ped_constraint_destroy (constraint_any); - return 1; -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static PedDiskOps bsd_disk_ops = { - .probe = bsd_probe, -#ifndef DISCOVER_ONLY - .clobber = bsd_clobber, -#else - .clobber = NULL, -#endif - .alloc = bsd_alloc, - .duplicate = bsd_duplicate, - .free = bsd_free, - .read = bsd_read, -#ifndef DISCOVER_ONLY - .write = bsd_write, -#else - .write = NULL, -#endif - - .partition_new = bsd_partition_new, - .partition_duplicate = bsd_partition_duplicate, - .partition_destroy = bsd_partition_destroy, - .partition_set_system = bsd_partition_set_system, - .partition_set_flag = bsd_partition_set_flag, - .partition_get_flag = bsd_partition_get_flag, - .partition_is_flag_available = bsd_partition_is_flag_available, - .partition_set_name = NULL, - .partition_get_name = NULL, - .partition_align = bsd_partition_align, - .partition_enumerate = bsd_partition_enumerate, - - .alloc_metadata = bsd_alloc_metadata, - .get_max_primary_partition_count = - bsd_get_max_primary_partition_count -}; - -static PedDiskType bsd_disk_type = { - .next = NULL, - .name = "bsd", - .ops = &bsd_disk_ops, - .features = 0 -}; - -void -ped_disk_bsd_init () -{ - PED_ASSERT (sizeof (BSDRawPartition) == 16, return); - PED_ASSERT (sizeof (BSDRawLabel) == 276, return); - - ped_disk_type_register (&bsd_disk_type); -} - -void -ped_disk_bsd_done () -{ - ped_disk_type_unregister (&bsd_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/dos.c b/usr/src/lib/libparted/common/libparted/labels/dos.c deleted file mode 100644 index 7b4b63c6bc..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/dos.c +++ /dev/null @@ -1,2280 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007 - Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* this MBR boot code is loaded into 0000:7c00 by the BIOS. See mbr.s for - * the source, and how to build it - */ - -static const unsigned char MBR_BOOT_CODE[] = { - 0xfa, 0xb8, 0x00, 0x10, 0x8e, 0xd0, 0xbc, 0x00, - 0xb0, 0xb8, 0x00, 0x00, 0x8e, 0xd8, 0x8e, 0xc0, - 0xfb, 0xbe, 0x00, 0x7c, 0xbf, 0x00, 0x06, 0xb9, - 0x00, 0x02, 0xf3, 0xa4, 0xea, 0x21, 0x06, 0x00, - 0x00, 0xbe, 0xbe, 0x07, 0x38, 0x04, 0x75, 0x0b, - 0x83, 0xc6, 0x10, 0x81, 0xfe, 0xfe, 0x07, 0x75, - 0xf3, 0xeb, 0x16, 0xb4, 0x02, 0xb0, 0x01, 0xbb, - 0x00, 0x7c, 0xb2, 0x80, 0x8a, 0x74, 0x01, 0x8b, - 0x4c, 0x02, 0xcd, 0x13, 0xea, 0x00, 0x7c, 0x00, - 0x00, 0xeb, 0xfe -}; - -#define MSDOS_MAGIC 0xAA55 -#define PARTITION_MAGIC_MAGIC 0xf6f6 - -#define PARTITION_EMPTY 0x00 -#define PARTITION_FAT12 0x01 -#define PARTITION_FAT16_SM 0x04 -#define PARTITION_DOS_EXT 0x05 -#define PARTITION_FAT16 0x06 -#define PARTITION_NTFS 0x07 -#define PARTITION_HPFS 0x07 -#define PARTITION_FAT32 0x0b -#define PARTITION_FAT32_LBA 0x0c -#define PARTITION_FAT16_LBA 0x0e -#define PARTITION_EXT_LBA 0x0f - -#define PART_FLAG_HIDDEN 0x10 /* Valid for FAT/NTFS only */ -#define PARTITION_FAT12_H (PARTITION_FAT12 | PART_FLAG_HIDDEN) -#define PARTITION_FAT16_SM_H (PARTITION_FAT16_SM | PART_FLAG_HIDDEN) -#define PARTITION_DOS_EXT_H (PARTITION_DOS_EXT | PART_FLAG_HIDDEN) -#define PARTITION_FAT16_H (PARTITION_FAT16 | PART_FLAG_HIDDEN) -#define PARTITION_NTFS_H (PARTITION_NTFS | PART_FLAG_HIDDEN) -#define PARTITION_FAT32_H (PARTITION_FAT32 | PART_FLAG_HIDDEN) -#define PARTITION_FAT32_LBA_H (PARTITION_FAT32_LBA | PART_FLAG_HIDDEN) -#define PARTITION_FAT16_LBA_H (PARTITION_FAT16_LBA | PART_FLAG_HIDDEN) - -#define PARTITION_COMPAQ_DIAG 0x12 -#define PARTITION_LDM 0x42 -#define PARTITION_LINUX_SWAP 0x82 -#define PARTITION_LINUX 0x83 -#define PARTITION_LINUX_EXT 0x85 -#define PARTITION_LINUX_LVM 0x8e -#define PARTITION_SUN_UFS 0xbf -#define PARTITION_DELL_DIAG 0xde -#define PARTITION_GPT 0xee -#define PARTITION_PALO 0xf0 -#define PARTITION_PREP 0x41 -#define PARTITION_LINUX_RAID 0xfd -#define PARTITION_LINUX_LVM_OLD 0xfe - -/* This constant contains the maximum cylinder number that can be represented - * in (C,H,S) notation. Higher cylinder numbers are reserved for - * "too big" indicators (in which case only LBA addressing can be used). - * Some partition tables in the wild indicate this number is 1021. - * (i.e. 1022 is sometimes used to indicate "use LBA"). - */ -#define MAX_CHS_CYLINDER 1021 - -typedef struct _DosRawPartition DosRawPartition; -typedef struct _DosRawTable DosRawTable; - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -/* note: lots of bit-bashing here, thus, you shouldn't look inside it. - * Use chs_to_sector() and sector_to_chs() instead. - */ -#ifdef __sun -#pragma pack(1) -#endif -typedef struct { - uint8_t head; - uint8_t sector; - uint8_t cylinder; -} __attribute__((packed)) RawCHS; - -/* ripped from Linux source */ -struct _DosRawPartition { - uint8_t boot_ind; /* 00: 0x80 - active */ - RawCHS chs_start; /* 01: */ - uint8_t type; /* 04: partition type */ - RawCHS chs_end; /* 05: */ - uint32_t start; /* 08: starting sector counting from 0 */ - uint32_t length; /* 0c: nr of sectors in partition */ -} __attribute__((packed)); - -struct _DosRawTable { - char boot_code [440]; - uint32_t mbr_signature; /* really a unique ID */ - uint16_t Unknown; - DosRawPartition partitions [4]; - uint16_t magic; -} __attribute__((packed)); -#ifdef __sun -#pragma pack() -#endif - - -/* OrigState is information we want to preserve about the partition for - * dealing with CHS issues - */ -typedef struct { - PedGeometry geom; - DosRawPartition raw_part; - PedSector lba_offset; /* needed for computing start/end for - * logical partitions */ -} OrigState; - -typedef struct { - unsigned char system; - int boot; - int hidden; - int raid; - int lvm; - int lba; - int palo; - int prep; - OrigState* orig; /* used for CHS stuff */ -} DosPartitionData; - -static PedDiskType msdos_disk_type; - -/* FIXME: factor out this function: copied from aix.c, with changes to - the description, and an added sector number argument. - Read sector, SECTOR_NUM (which has length DEV->sector_size) into malloc'd - storage. If the read fails, free the memory and return zero without - modifying *BUF. Otherwise, set *BUF to the new buffer and return 1. */ -static int -read_sector (const PedDevice *dev, PedSector sector_num, char **buf) -{ - char *b = ped_malloc (dev->sector_size); - PED_ASSERT (b != NULL, return 0); - if (!ped_device_read (dev, b, sector_num, 1)) { - ped_free (b); - return 0; - } - *buf = b; - return 1; -} - -static int -msdos_probe (const PedDevice *dev) -{ - PedDiskType* disk_type; - DosRawTable* part_table; - int i; - - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size < sizeof *part_table) - return 0; - - char *label; - if (!read_sector (dev, 0, &label)) - return 0; - - part_table = (DosRawTable *) label; - - /* check magic */ - if (PED_LE16_TO_CPU (part_table->magic) != MSDOS_MAGIC) - goto probe_fail; - - /* if this is a FAT fs, fail here. Note that the Smart Boot Manager - * Loader (SBML) signature indicates a partition table, not a file - * system. - */ - if ((!strncmp (part_table->boot_code + 0x36, "FAT", 3) - && strncmp (part_table->boot_code + 0x40, "SBML", 4) != 0) - || !strncmp (part_table->boot_code + 0x52, "FAT", 3)) - goto probe_fail; - - /* If this is a GPT disk, fail here */ - for (i = 0; i < 4; i++) { - if (part_table->partitions[i].type == PARTITION_GPT) - goto probe_fail; - } - - /* If this is an AIX Physical Volume, fail here. IBMA in EBCDIC */ - if (part_table->boot_code[0] == (char) 0xc9 && - part_table->boot_code[1] == (char) 0xc2 && - part_table->boot_code[2] == (char) 0xd4 && - part_table->boot_code[3] == (char) 0xc1) - goto probe_fail; - -#ifdef ENABLE_PC98 - /* HACK: it's impossible to tell PC98 and msdos disk labels apart. - * Someone made the signatures the same (very clever). Since - * PC98 has some idiosyncracies with it's boot-loader, it's detection - * is more reliable */ - disk_type = ped_disk_type_get ("pc98"); - if (disk_type && disk_type->ops->probe (dev)) - goto probe_fail; -#endif /* ENABLE_PC98 */ - - free (label); - return 1; - - probe_fail: - free (label); - return 0; -} - -static PedDisk* -msdos_alloc (const PedDevice* dev) -{ - PedDisk* disk; - PED_ASSERT (dev != NULL, return NULL); - - disk = _ped_disk_alloc ((PedDevice*)dev, &msdos_disk_type); - if (disk) - disk->disk_specific = NULL; - return disk; -} - -static PedDisk* -msdos_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - - new_disk = ped_disk_new_fresh (disk->dev, &msdos_disk_type); - if (!new_disk) - return NULL; - new_disk->disk_specific = NULL; - return new_disk; -} - -static void -msdos_free (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return); - - _ped_disk_free (disk); -} - -#ifndef DISCOVER_ONLY -static int -msdos_clobber (PedDevice* dev) -{ - DosRawTable table; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (msdos_probe (dev), return 0); - - if (!ped_device_read (dev, &table, 0, 1)) - return 0; - table.magic = 0; - return ped_device_write (dev, (void*) &table, 0, 1); -} -#endif /* !DISCOVER_ONLY */ - -static int -chs_get_cylinder (const RawCHS* chs) -{ - return chs->cylinder + ((chs->sector >> 6) << 8); -} - -static int -chs_get_head (const RawCHS* chs) -{ - return chs->head; -} - -/* counts from 0 */ -static int -chs_get_sector (const RawCHS* chs) -{ - return (chs->sector & 0x3f) - 1; -} - -static PedSector -chs_to_sector (const PedDevice* dev, const PedCHSGeometry *bios_geom, - const RawCHS* chs) -{ - PedSector c; /* not measured in sectors, but need */ - PedSector h; /* lots of bits */ - PedSector s; - - PED_ASSERT (bios_geom != NULL, return 0); - PED_ASSERT (chs != NULL, return 0); - - c = chs_get_cylinder (chs); - h = chs_get_head (chs); - s = chs_get_sector (chs); - - if (c > MAX_CHS_CYLINDER) /* MAGIC: C/H/S is irrelevant */ - return 0; - if (s < 0) - return 0; - return ((c * bios_geom->heads + h) * bios_geom->sectors + s) - * (dev->sector_size / 512); -} - -static void -sector_to_chs (const PedDevice* dev, const PedCHSGeometry* bios_geom, - PedSector sector, RawCHS* chs) -{ - PedSector real_c, real_h, real_s; - - PED_ASSERT (dev != NULL, return); - PED_ASSERT (chs != NULL, return); - - if (!bios_geom) - bios_geom = &dev->bios_geom; - - sector /= (dev->sector_size / 512); - - real_c = sector / (bios_geom->heads * bios_geom->sectors); - real_h = (sector / bios_geom->sectors) % bios_geom->heads; - real_s = sector % bios_geom->sectors; - - if (real_c > MAX_CHS_CYLINDER) { - real_c = 1023; - real_h = bios_geom->heads - 1; - real_s = bios_geom->sectors - 1; - } - - chs->cylinder = real_c % 0x100; - chs->head = real_h; - chs->sector = real_s + 1 + (real_c >> 8 << 6); -} - -static PedSector -legacy_start (const PedDisk* disk, const PedCHSGeometry* bios_geom, - const DosRawPartition* raw_part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - return chs_to_sector (disk->dev, bios_geom, &raw_part->chs_start); -} - -static PedSector -legacy_end (const PedDisk* disk, const PedCHSGeometry* bios_geom, - const DosRawPartition* raw_part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - return chs_to_sector (disk->dev, bios_geom, &raw_part->chs_end); -} - -static PedSector -linear_start (const PedDisk* disk, const DosRawPartition* raw_part, - PedSector offset) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - return offset - + PED_LE32_TO_CPU (raw_part->start) - * (disk->dev->sector_size / 512); -} - -static PedSector -linear_end (const PedDisk* disk, const DosRawPartition* raw_part, - PedSector offset) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - return linear_start (disk, raw_part, offset) - + (PED_LE32_TO_CPU (raw_part->length) - 1) - * (disk->dev->sector_size / 512); -} - -#ifndef DISCOVER_ONLY -static int -partition_check_bios_geometry (PedPartition* part, PedCHSGeometry* bios_geom) -{ - PedSector leg_start, leg_end; - DosPartitionData* dos_data; - PedDisk* disk; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - dos_data = part->disk_specific; - - if (!dos_data->orig) - return 1; - - disk = part->disk; - leg_start = legacy_start (disk, bios_geom, &dos_data->orig->raw_part); - leg_end = legacy_end (disk, bios_geom, &dos_data->orig->raw_part); - - if (leg_start && leg_start != dos_data->orig->geom.start) - return 0; - if (leg_end && leg_end != dos_data->orig->geom.end) - return 0; - return 1; -} - -static int -disk_check_bios_geometry (const PedDisk* disk, PedCHSGeometry* bios_geom) -{ - PedPartition* part = NULL; - - PED_ASSERT (disk != NULL, return 0); - - while ((part = ped_disk_next_partition (disk, part))) { - if (ped_partition_is_active (part)) { - if (!partition_check_bios_geometry (part, bios_geom)) - return 0; - } - } - - return 1; -} - -static int -probe_filesystem_for_geom (const PedPartition* part, PedCHSGeometry* bios_geom) -{ - const char* ms_types[] = {"ntfs", "fat16", "fat32", NULL}; - int i; - int found; - unsigned char* buf; - int sectors; - int heads; - int res = 0; - - PED_ASSERT (bios_geom != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - PED_ASSERT (part->disk->dev != NULL, return 0); - PED_ASSERT (part->disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, - return 0); - - buf = ped_malloc (part->disk->dev->sector_size); - - if (!buf) - return 0; - - if (!part->fs_type) - goto end; - - found = 0; - for (i = 0; ms_types[i]; i++) { - if (!strcmp(ms_types[i], part->fs_type->name)) - found = 1; - } - if (!found) - goto end; - - if (!ped_geometry_read(&part->geom, buf, 0, 1)) - goto end; - - /* shared by the start of all Microsoft file systems */ - sectors = buf[0x18] + (buf[0x19] << 8); - heads = buf[0x1a] + (buf[0x1b] << 8); - - if (sectors < 1 || sectors > 63) - goto end; - if (heads > 255 || heads < 1) - goto end; - - bios_geom->sectors = sectors; - bios_geom->heads = heads; - bios_geom->cylinders = part->disk->dev->length / (sectors * heads); - res = 1; -end: - ped_free(buf); - return res; -} - -/* This function attempts to infer the BIOS CHS geometry of the hard disk - * from the CHS + LBA information contained in the partition table from - * a single partition's entry. - * - * This involves some maths. Let (c,h,s,a) be the starting cylinder, - * starting head, starting sector and LBA start address of the partition. - * Likewise, (C,H,S,A) the end addresses. Using both of these pieces - * of information, we want to deduce cyl_sectors and head_sectors which - * are the sizes of a single cylinder and a single head, respectively. - * - * The relationships are: - * c*cyl_sectors + h * head_sectors + s = a - * C*cyl_sectors + H * head_sectors + S = A - * - * We can rewrite this in matrix form: - * - * [ c h ] [ cyl_sectors ] = [ s - a ] = [ a_ ] - * [ C H ] [ head_sectors ] [ S - A ] [ A_ ]. - * - * (s - a is abbreviated to a_to simplify the notation.) - * - * This can be abbreviated into augmented matrix form: - * - * [ c h | a_ ] - * [ C H | A_ ]. - * - * Solving these equations requires following the row reduction algorithm. We - * need to be careful about a few things though: - * - the equations might be linearly dependent, in which case there - * are many solutions. - * - the equations might be inconsistent, in which case there - * are no solutions. (Inconsistent partition table entry!) - * - there might be zeros, so we need to be careful about applying - * the algorithm. We know, however, that C > 0. - */ -static int -probe_partition_for_geom (const PedPartition* part, PedCHSGeometry* bios_geom) -{ - DosPartitionData* dos_data; - RawCHS* start_chs; - RawCHS* end_chs; - PedSector c, h, s, a, a_; /* start */ - PedSector C, H, S, A, A_; /* end */ - PedSector dont_overflow, denum; - PedSector cyl_size, head_size; - PedSector cylinders, heads, sectors; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - PED_ASSERT (bios_geom != NULL, return 0); - - dos_data = part->disk_specific; - - if (!dos_data->orig) - return 0; - - start_chs = &dos_data->orig->raw_part.chs_start; - c = chs_get_cylinder (start_chs); - h = chs_get_head (start_chs); - s = chs_get_sector (start_chs); - a = dos_data->orig->geom.start; - a_ = a - s; - - end_chs = &dos_data->orig->raw_part.chs_end; - C = chs_get_cylinder (end_chs); - H = chs_get_head (end_chs); - S = chs_get_sector (end_chs); - A = dos_data->orig->geom.end; - A_ = A - S; - - if (h < 0 || H < 0 || h > 254 || H > 254) - return 0; - if (c > C) - return 0; - - /* If no geometry is feasible, then don't even bother. - * Useful for eliminating assertions for broken partition - * tables generated by Norton Ghost et al. - */ - if (A > (C+1) * 255 * 63) - return 0; - - /* Not enough information. In theory, we can do better. Should we? */ - if (C > MAX_CHS_CYLINDER) - return 0; - if (C == 0) - return 0; - - /* Calculate the maximum number that can be multiplied by - * any head count without overflowing a PedSector - * 2^8 = 256, 8 bits + 1(sign bit) = 9 - */ - dont_overflow = 1; - dont_overflow <<= (8*sizeof(dont_overflow)) - 9; - dont_overflow--; - - if (a_ > dont_overflow || A_ > dont_overflow) - return 0; - - /* The matrix is solved by : - * - * [ c h | a_] R1 - * [ C H | A_] R2 - * - * (cH - Ch) cyl_size = a_H - A_h H R1 - h R2 - * => (if cH - Ch != 0) cyl_size = (a_H - A_h) / (cH - Ch) - * - * (Hc - hC) head_size = A_c - a_C c R2 - C R1 - * => (if cH - Ch != 0) head_size = (A_c - a_C) / (cH - Ch) - * - * But this calculation of head_size would need - * not overflowing A_c or a_C - * So substitution is use instead, to minimize dimension - * of temporary results : - * - * If h != 0 : head_size = ( a_ - c cyl_size ) / h - * If H != 0 : head_size = ( A_ - C cyl_size ) / H - * - */ - denum = c * H - C * h; - if (denum == 0) - return 0; - - cyl_size = (a_*H - A_*h) / denum; - /* Check for non integer result */ - if (cyl_size * denum != a_*H - A_*h) - return 0; - - PED_ASSERT (cyl_size > 0, return 0); - PED_ASSERT (cyl_size <= 255 * 63, return 0); - - if (h > 0) - head_size = ( a_ - c * cyl_size ) / h; - else if (H > 0) - head_size = ( A_ - C * cyl_size ) / H; - else { - /* should not happen because denum != 0 */ - head_size = 0; - PED_ASSERT (0, return 0); - } - - PED_ASSERT (head_size > 0, return 0); - PED_ASSERT (head_size <= 63, return 0); - - cylinders = part->disk->dev->length / cyl_size; - heads = cyl_size / head_size; - sectors = head_size; - - PED_ASSERT (heads > 0, return 0); - PED_ASSERT (heads < 256, return 0); - - PED_ASSERT (sectors > 0, return 0); - PED_ASSERT (sectors <= 63, return 0); - - /* Some broken OEM partitioning program(s) seem to have an out-by-one - * error on the end of partitions. We should offer to fix the - * partition table... - */ - if (((C + 1) * heads + H) * sectors + S == A) - C++; - - PED_ASSERT ((c * heads + h) * sectors + s == a, return 0); - PED_ASSERT ((C * heads + H) * sectors + S == A, return 0); - - bios_geom->cylinders = cylinders; - bios_geom->heads = heads; - bios_geom->sectors = sectors; - - return 1; -} - -static void -partition_probe_bios_geometry (const PedPartition* part, - PedCHSGeometry* bios_geom) -{ - PED_ASSERT (part != NULL, return); - PED_ASSERT (part->disk != NULL, return); - PED_ASSERT (bios_geom != NULL, return); - - if (ped_partition_is_active (part)) { - if (probe_partition_for_geom (part, bios_geom)) - return; - if (part->type & PED_PARTITION_EXTENDED) { - if (probe_filesystem_for_geom (part, bios_geom)) - return; - } - } - if (part->type & PED_PARTITION_LOGICAL) { - PedPartition* ext_part; - ext_part = ped_disk_extended_partition (part->disk); - PED_ASSERT (ext_part != NULL, return); - partition_probe_bios_geometry (ext_part, bios_geom); - } else { - *bios_geom = part->disk->dev->bios_geom; - } -} - -static void -disk_probe_bios_geometry (const PedDisk* disk, PedCHSGeometry* bios_geom) -{ - PedPartition* part; - - /* first look at the boot partition */ - part = NULL; - while ((part = ped_disk_next_partition (disk, part))) { - if (!ped_partition_is_active (part)) - continue; - if (ped_partition_get_flag (part, PED_PARTITION_BOOT)) { - if (probe_filesystem_for_geom (part, bios_geom)) - return; - if (probe_partition_for_geom (part, bios_geom)) - return; - } - } - - /* that didn't work... try all partition table entries */ - part = NULL; - while ((part = ped_disk_next_partition (disk, part))) { - if (ped_partition_is_active (part)) { - if (probe_partition_for_geom (part, bios_geom)) - return; - } - } - - /* that didn't work... look at all file systems */ - part = NULL; - while ((part = ped_disk_next_partition (disk, part))) { - if (ped_partition_is_active (part)) { - if (probe_filesystem_for_geom (part, bios_geom)) - return; - } - } -} -#endif /* !DISCOVER_ONLY */ - -static int -raw_part_is_extended (const DosRawPartition* raw_part) -{ - PED_ASSERT (raw_part != NULL, return 0); - - switch (raw_part->type) { - case PARTITION_DOS_EXT: - case PARTITION_EXT_LBA: - case PARTITION_LINUX_EXT: - return 1; - - default: - return 0; - } - - return 0; -} - -static int -raw_part_is_hidden (const DosRawPartition* raw_part) -{ - PED_ASSERT (raw_part != NULL, return 0); - - switch (raw_part->type) { - case PARTITION_FAT12_H: - case PARTITION_FAT16_SM_H: - case PARTITION_FAT16_H: - case PARTITION_FAT32_H: - case PARTITION_NTFS_H: - case PARTITION_FAT32_LBA_H: - case PARTITION_FAT16_LBA_H: - return 1; - - default: - return 0; - } - - return 0; -} - -static int -raw_part_is_lba (const DosRawPartition* raw_part) -{ - PED_ASSERT (raw_part != NULL, return 0); - - switch (raw_part->type) { - case PARTITION_FAT32_LBA: - case PARTITION_FAT16_LBA: - case PARTITION_EXT_LBA: - case PARTITION_FAT32_LBA_H: - case PARTITION_FAT16_LBA_H: - return 1; - - default: - return 0; - } - - return 0; -} - -static PedPartition* -raw_part_parse (const PedDisk* disk, const DosRawPartition* raw_part, - PedSector lba_offset, PedPartitionType type) -{ - PedPartition* part; - DosPartitionData* dos_data; - - PED_ASSERT (disk != NULL, return NULL); - PED_ASSERT (raw_part != NULL, return NULL); - - part = ped_partition_new ( - disk, type, NULL, - linear_start (disk, raw_part, lba_offset), - linear_end (disk, raw_part, lba_offset)); - if (!part) - return NULL; - dos_data = part->disk_specific; - dos_data->system = raw_part->type; - dos_data->boot = raw_part->boot_ind != 0; - dos_data->hidden = raw_part_is_hidden (raw_part); - dos_data->raid = raw_part->type == PARTITION_LINUX_RAID; - dos_data->lvm = raw_part->type == PARTITION_LINUX_LVM_OLD - || raw_part->type == PARTITION_LINUX_LVM; - dos_data->lba = raw_part_is_lba (raw_part); - dos_data->palo = raw_part->type == PARTITION_PALO; - dos_data->prep = raw_part->type == PARTITION_PREP; - dos_data->orig = ped_malloc (sizeof (OrigState)); - if (!dos_data->orig) { - ped_partition_destroy (part); - return NULL; - } - dos_data->orig->geom = part->geom; - dos_data->orig->raw_part = *raw_part; - dos_data->orig->lba_offset = lba_offset; - return part; -} - -static int -read_table (PedDisk* disk, PedSector sector, int is_extended_table) -{ - int i; - DosRawTable* table; - DosRawPartition* raw_part; - PedPartition* part; - PedPartitionType type; - PedSector lba_offset; - PedConstraint* constraint_exact; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - char *label = NULL; - if (!read_sector (disk->dev, sector, &label)) - goto error; - - table = (DosRawTable *) label; - - /* weird: empty extended partitions are filled with 0xf6 by PM */ - if (is_extended_table - && PED_LE16_TO_CPU (table->magic) == PARTITION_MAGIC_MAGIC) - goto read_ok; - -#ifndef DISCOVER_ONLY - if (PED_LE16_TO_CPU (table->magic) != MSDOS_MAGIC) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, - _("Invalid partition table on %s " - "-- wrong signature %x."), - disk->dev->path, - PED_LE16_TO_CPU (table->magic)) - != PED_EXCEPTION_IGNORE) - goto error; - goto read_ok; - } -#endif - - /* parse the partitions from this table */ - for (i = 0; i < 4; i++) { - raw_part = &table->partitions [i]; - if (raw_part->type == PARTITION_EMPTY || !raw_part->length) - continue; - - /* process nested extended partitions after normal logical - * partitions, to make sure we get the order right. - */ - if (is_extended_table && raw_part_is_extended (raw_part)) - continue; - - lba_offset = is_extended_table ? sector : 0; - - if (linear_start (disk, raw_part, lba_offset) == sector) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Invalid partition table - recursive " - "partition on %s."), - disk->dev->path) - != PED_EXCEPTION_IGNORE) - goto error; - continue; /* avoid infinite recursion */ - } - - if (is_extended_table) - type = PED_PARTITION_LOGICAL; - else if (raw_part_is_extended (raw_part)) - type = PED_PARTITION_EXTENDED; - else - type = PED_PARTITION_NORMAL; - - part = raw_part_parse (disk, raw_part, lba_offset, type); - if (!part) - goto error; - if (!is_extended_table) - part->num = i + 1; - if (type != PED_PARTITION_EXTENDED) - part->fs_type = ped_file_system_probe (&part->geom); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error; - ped_constraint_destroy (constraint_exact); - - /* non-nested extended partition */ - if (part->type == PED_PARTITION_EXTENDED) { - if (!read_table (disk, part->geom.start, 1)) - goto error; - } - } - - if (is_extended_table) { - /* process the nested extended partitions */ - for (i = 0; i < 4; i++) { - PedSector part_start; - - raw_part = &table->partitions [i]; - if (!raw_part_is_extended (raw_part)) - continue; - - lba_offset = ped_disk_extended_partition - (disk)->geom.start; - part_start = linear_start (disk, raw_part, lba_offset); - if (part_start == sector) { - /* recursive table - already threw an - * exception above. - */ - continue; - } - if (!read_table (disk, part_start, 1)) - goto error; - } - } - -read_ok: - free (label); - return 1; - -error: - free (label); - ped_disk_delete_all (disk); - return 0; -} - -static int -msdos_read (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - ped_disk_delete_all (disk); - if (!read_table (disk, 0, 0)) - return 0; - -#ifndef DISCOVER_ONLY - /* try to figure out the correct BIOS CHS values */ - if (!disk_check_bios_geometry (disk, &disk->dev->bios_geom)) { - PedCHSGeometry bios_geom = disk->dev->bios_geom; - disk_probe_bios_geometry (disk, &bios_geom); - - /* if the geometry was wrong, then we should reread, to - * make sure the metadata is allocated in the right places. - */ - if (disk->dev->bios_geom.cylinders != bios_geom.cylinders - || disk->dev->bios_geom.heads != bios_geom.heads - || disk->dev->bios_geom.sectors != bios_geom.sectors) { - disk->dev->bios_geom = bios_geom; - return msdos_read (disk); - } - } -#endif - - return 1; -} - -#ifndef DISCOVER_ONLY -static int -fill_raw_part (DosRawPartition* raw_part, - const PedPartition* part, PedSector offset) -{ - DosPartitionData* dos_data; - PedCHSGeometry bios_geom; - - PED_ASSERT (raw_part != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - - partition_probe_bios_geometry (part, &bios_geom); - - dos_data = part->disk_specific; - - raw_part->boot_ind = 0x80 * dos_data->boot; - raw_part->type = dos_data->system; - raw_part->start = PED_CPU_TO_LE32 ((part->geom.start - offset) - / (part->disk->dev->sector_size / 512)); - raw_part->length = PED_CPU_TO_LE32 (part->geom.length - / (part->disk->dev->sector_size / 512)); - - sector_to_chs (part->disk->dev, &bios_geom, part->geom.start, - &raw_part->chs_start); - sector_to_chs (part->disk->dev, &bios_geom, part->geom.end, - &raw_part->chs_end); - - if (dos_data->orig) { - DosRawPartition* orig_raw_part = &dos_data->orig->raw_part; - if (dos_data->orig->geom.start == part->geom.start) - raw_part->chs_start = orig_raw_part->chs_start; - if (dos_data->orig->geom.end == part->geom.end) - raw_part->chs_end = orig_raw_part->chs_end; - } - - return 1; -} - -static int -fill_ext_raw_part_geom (DosRawPartition* raw_part, - const PedCHSGeometry* bios_geom, - const PedGeometry* geom, PedSector offset) -{ - PED_ASSERT (raw_part != NULL, return 0); - PED_ASSERT (geom != NULL, return 0); - PED_ASSERT (geom->dev != NULL, return 0); - - raw_part->boot_ind = 0; - raw_part->type = PARTITION_DOS_EXT; - raw_part->start = PED_CPU_TO_LE32 ((geom->start - offset) - / (geom->dev->sector_size / 512)); - raw_part->length = PED_CPU_TO_LE32 (geom->length - / (geom->dev->sector_size / 512)); - - sector_to_chs (geom->dev, bios_geom, geom->start, &raw_part->chs_start); - sector_to_chs (geom->dev, bios_geom, geom->start + geom->length - 1, - &raw_part->chs_end); - - return 1; -} - -static int -write_ext_table (const PedDisk* disk, - PedSector sector, const PedPartition* logical) -{ - DosRawTable table; - PedPartition* part; - PedSector lba_offset; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (ped_disk_extended_partition (disk) != NULL, return 0); - PED_ASSERT (logical != NULL, return 0); - - lba_offset = ped_disk_extended_partition (disk)->geom.start; - - memset (&table, 0, sizeof (DosRawTable)); - table.magic = PED_CPU_TO_LE16 (MSDOS_MAGIC); - - if (!fill_raw_part (&table.partitions[0], logical, sector)) - return 0; - - part = ped_disk_get_partition (disk, logical->num + 1); - if (part) { - PedGeometry* geom; - PedCHSGeometry bios_geom; - - geom = ped_geometry_new (disk->dev, part->prev->geom.start, - part->geom.end - part->prev->geom.start + 1); - if (!geom) - return 0; - partition_probe_bios_geometry (part, &bios_geom); - fill_ext_raw_part_geom (&table.partitions[1], &bios_geom, - geom, lba_offset); - ped_geometry_destroy (geom); - - if (!write_ext_table (disk, part->prev->geom.start, part)) - return 0; - } - - return ped_device_write (disk->dev, (void*) &table, sector, 1); -} - -static int -write_empty_table (const PedDisk* disk, PedSector sector) -{ - DosRawTable table; - - PED_ASSERT (disk != NULL, return 0); - - memset (&table, 0, sizeof (DosRawTable)); - table.magic = PED_CPU_TO_LE16 (MSDOS_MAGIC); - - return ped_device_write (disk->dev, (void*) &table, sector, 1); -} - -/* Find the first logical partition, and write the partition table for it. - */ -static int -write_extended_partitions (const PedDisk* disk) -{ - PedPartition* ext_part; - PedPartition* part; - PedCHSGeometry bios_geom; - - PED_ASSERT (disk != NULL, return 0); - - ext_part = ped_disk_extended_partition (disk); - partition_probe_bios_geometry (ext_part, &bios_geom); - part = ped_disk_get_partition (disk, 5); - if (part) - return write_ext_table (disk, ext_part->geom.start, part); - else - return write_empty_table (disk, ext_part->geom.start); -} - -static inline uint32_t generate_random_id (void) -{ - struct timeval tv; - int rc; - rc = gettimeofday(&tv, NULL); - if (rc == -1) - return 0; - return (uint32_t)(tv.tv_usec & 0xFFFFFFFFUL); -} - -static int -msdos_write (const PedDisk* disk) -{ - DosRawTable table; - PedPartition* part; - int i; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - ped_device_read (disk->dev, &table, 0, 1); - - if (!table.boot_code[0]) { - memset (table.boot_code, 0, 512); - memcpy (table.boot_code, MBR_BOOT_CODE, sizeof (MBR_BOOT_CODE)); - } - - /* If there is no unique identifier, generate a random one */ - if (!table.mbr_signature) - table.mbr_signature = generate_random_id(); - - memset (table.partitions, 0, sizeof (DosRawPartition) * 4); - table.magic = PED_CPU_TO_LE16 (MSDOS_MAGIC); - - for (i=1; i<=4; i++) { - part = ped_disk_get_partition (disk, i); - if (!part) - continue; - - if (!fill_raw_part (&table.partitions [i - 1], part, 0)) - return 0; - - if (part->type == PED_PARTITION_EXTENDED) { - if (!write_extended_partitions (disk)) - return 0; - } - } - - if (!ped_device_write (disk->dev, (void*) &table, 0, 1)) - return 0; - return ped_device_sync (disk->dev); -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -msdos_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - DosPartitionData* dos_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (ped_partition_is_active (part)) { - part->disk_specific - = dos_data = ped_malloc (sizeof (DosPartitionData)); - if (!dos_data) - goto error_free_part; - dos_data->orig = NULL; - dos_data->system = PARTITION_LINUX; - dos_data->hidden = 0; - dos_data->boot = 0; - dos_data->raid = 0; - dos_data->lvm = 0; - dos_data->lba = 0; - dos_data->palo = 0; - dos_data->prep = 0; - } else { - part->disk_specific = NULL; - } - return part; - - ped_free (dos_data); -error_free_part: - ped_free (part); -error: - return 0; -} - -static PedPartition* -msdos_partition_duplicate (const PedPartition* part) -{ - PedPartition* new_part; - DosPartitionData* new_dos_data; - DosPartitionData* old_dos_data; - - new_part = ped_partition_new (part->disk, part->type, part->fs_type, - part->geom.start, part->geom.end); - if (!new_part) - return NULL; - new_part->num = part->num; - - old_dos_data = (DosPartitionData*) part->disk_specific; - new_dos_data = (DosPartitionData*) new_part->disk_specific; - new_dos_data->system = old_dos_data->system; - new_dos_data->boot = old_dos_data->boot; - new_dos_data->hidden = old_dos_data->hidden; - new_dos_data->raid = old_dos_data->raid; - new_dos_data->lvm = old_dos_data->lvm; - new_dos_data->lba = old_dos_data->lba; - new_dos_data->palo = old_dos_data->palo; - new_dos_data->prep = old_dos_data->prep; - - if (old_dos_data->orig) { - new_dos_data->orig = ped_malloc (sizeof (OrigState)); - if (!new_dos_data->orig) { - ped_partition_destroy (new_part); - return NULL; - } - new_dos_data->orig->geom = old_dos_data->orig->geom; - new_dos_data->orig->raw_part = old_dos_data->orig->raw_part; - new_dos_data->orig->lba_offset = old_dos_data->orig->lba_offset; - } - return new_part; -} - -static void -msdos_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) { - DosPartitionData* dos_data; - dos_data = (DosPartitionData*) part->disk_specific; - if (dos_data->orig) - ped_free (dos_data->orig); - ped_free (part->disk_specific); - } - ped_free (part); -} - -static int -msdos_partition_set_system (PedPartition* part, - const PedFileSystemType* fs_type) -{ - DosPartitionData* dos_data = part->disk_specific; - - part->fs_type = fs_type; - - if (dos_data->hidden - && fs_type - && strncmp (fs_type->name, "fat", 3) != 0 - && strcmp (fs_type->name, "ntfs") != 0) - dos_data->hidden = 0; - - if (part->type & PED_PARTITION_EXTENDED) { - dos_data->raid = 0; - dos_data->lvm = 0; - dos_data->palo = 0; - dos_data->prep = 0; - if (dos_data->lba) - dos_data->system = PARTITION_EXT_LBA; - else - dos_data->system = PARTITION_DOS_EXT; - return 1; - } - - if (dos_data->lvm) { - dos_data->system = PARTITION_LINUX_LVM; - return 1; - } - if (dos_data->raid) { - dos_data->system = PARTITION_LINUX_RAID; - return 1; - } - if (dos_data->palo) { - dos_data->system = PARTITION_PALO; - return 1; - } - if (dos_data->prep) { - dos_data->system = PARTITION_PREP; - return 1; - } - - if (!fs_type) - dos_data->system = PARTITION_LINUX; - else if (!strcmp (fs_type->name, "fat16")) { - dos_data->system = dos_data->lba - ? PARTITION_FAT16_LBA : PARTITION_FAT16; - dos_data->system |= dos_data->hidden ? PART_FLAG_HIDDEN : 0; - } else if (!strcmp (fs_type->name, "fat32")) { - dos_data->system = dos_data->lba - ? PARTITION_FAT32_LBA : PARTITION_FAT32; - dos_data->system |= dos_data->hidden ? PART_FLAG_HIDDEN : 0; - } else if (!strcmp (fs_type->name, "ntfs") - || !strcmp (fs_type->name, "hpfs")) { - dos_data->system = PARTITION_NTFS; - dos_data->system |= dos_data->hidden ? PART_FLAG_HIDDEN : 0; - } else if (!strcmp (fs_type->name, "sun-ufs")) - dos_data->system = PARTITION_SUN_UFS; - else if (!strcmp (fs_type->name, "solaris")) - dos_data->system = PARTITION_SUN_UFS; - else if (!strcmp (fs_type->name, "linux-swap")) - dos_data->system = PARTITION_LINUX_SWAP; - else - dos_data->system = PARTITION_LINUX; - - return 1; -} - -static int -msdos_partition_set_flag (PedPartition* part, - PedPartitionFlag flag, int state) -{ - PedDisk* disk; - PedPartition* walk; - DosPartitionData* dos_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - dos_data = part->disk_specific; - disk = part->disk; - - switch (flag) { - case PED_PARTITION_HIDDEN: - if (part->type == PED_PARTITION_EXTENDED) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Extended partitions cannot be hidden on " - "msdos disk labels.")); - return 0; - } - dos_data->hidden = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_BOOT: - dos_data->boot = state; - if (!state) - return 1; - - walk = ped_disk_next_partition (disk, NULL); - for (; walk; walk = ped_disk_next_partition (disk, walk)) { - if (walk == part || !ped_partition_is_active (walk)) - continue; - msdos_partition_set_flag (walk, PED_PARTITION_BOOT, 0); - } - return 1; - - case PED_PARTITION_RAID: - if (state) { - dos_data->hidden = 0; - dos_data->lvm = 0; - dos_data->palo = 0; - dos_data->prep = 0; - } - dos_data->raid = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_LVM: - if (state) { - dos_data->hidden = 0; - dos_data->raid = 0; - dos_data->palo = 0; - dos_data->prep = 0; - } - dos_data->lvm = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_LBA: - dos_data->lba = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_PALO: - if (state) { - dos_data->hidden = 0; - dos_data->raid = 0; - dos_data->lvm = 0; - } - dos_data->palo = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_PREP: - if (state) { - dos_data->hidden = 0; - dos_data->raid = 0; - dos_data->lvm = 0; - } - dos_data->prep = state; - return ped_partition_set_system (part, part->fs_type); - - default: - return 0; - } -} - -static int -msdos_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - DosPartitionData* dos_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - dos_data = part->disk_specific; - switch (flag) { - case PED_PARTITION_HIDDEN: - return dos_data->hidden; - - case PED_PARTITION_BOOT: - return dos_data->boot; - - case PED_PARTITION_RAID: - return dos_data->raid; - - case PED_PARTITION_LVM: - return dos_data->lvm; - - case PED_PARTITION_LBA: - return dos_data->lba; - - case PED_PARTITION_PALO: - return dos_data->palo; - - case PED_PARTITION_PREP: - return dos_data->prep; - - default: - return 0; - } -} - -static int -msdos_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_HIDDEN: - case PED_PARTITION_BOOT: - case PED_PARTITION_RAID: - case PED_PARTITION_LVM: - case PED_PARTITION_LBA: - case PED_PARTITION_PALO: - case PED_PARTITION_PREP: - return 1; - - default: - return 0; - } -} - -static PedGeometry* -_try_constraint (const PedPartition* part, const PedConstraint* external, - PedConstraint* internal) -{ - PedConstraint* intersection; - PedGeometry* solution; - - intersection = ped_constraint_intersect (external, internal); - ped_constraint_destroy (internal); - if (!intersection) - return NULL; - - solution = ped_constraint_solve_nearest (intersection, &part->geom); - ped_constraint_destroy (intersection); - return solution; -} - -static PedGeometry* -_best_solution (const PedPartition* part, const PedCHSGeometry* bios_geom, - PedGeometry* a, PedGeometry* b) -{ - PedSector cyl_size = bios_geom->heads * bios_geom->sectors; - int a_cylinder; - int b_cylinder; - - if (!a) - return b; - if (!b) - return a; - - a_cylinder = a->start / cyl_size; - b_cylinder = b->start / cyl_size; - - if (a_cylinder == b_cylinder) { - if ( (a->start / bios_geom->sectors) % bios_geom->heads - < (b->start / bios_geom->sectors) % bios_geom->heads) - goto choose_a; - else - goto choose_b; - } else { - PedSector a_delta; - PedSector b_delta; - - a_delta = abs (part->geom.start - a->start); - b_delta = abs (part->geom.start - b->start); - - if (a_delta < b_delta) - goto choose_a; - else - goto choose_b; - } - - return NULL; /* never get here! */ - -choose_a: - ped_geometry_destroy (b); - return a; - -choose_b: - ped_geometry_destroy (a); - return b; -} - -/* This constraint is for "normal" primary partitions, that start at the - * beginning of a cylinder, and end at the end of a cylinder. - * Note: you can't start a partition at the beginning of the 1st - * cylinder, because that's where the partition table is! There are different - * rules for that - see the _primary_start_constraint. - */ -static PedConstraint* -_primary_constraint (const PedDisk* disk, const PedCHSGeometry* bios_geom, - PedGeometry* min_geom) -{ - PedDevice* dev = disk->dev; - PedSector cylinder_size = bios_geom->sectors * bios_geom->heads; - PedAlignment start_align; - PedAlignment end_align; - PedGeometry start_geom; - PedGeometry end_geom; - - if (!ped_alignment_init (&start_align, 0, cylinder_size)) - return NULL; - if (!ped_alignment_init (&end_align, -1, cylinder_size)) - return NULL; - - if (min_geom) { - if (min_geom->start < cylinder_size) - return NULL; - if (!ped_geometry_init (&start_geom, dev, cylinder_size, - min_geom->start + 1 - cylinder_size)) - return NULL; - if (!ped_geometry_init (&end_geom, dev, min_geom->end, - dev->length - min_geom->end)) - return NULL; - } else { - if (!ped_geometry_init (&start_geom, dev, cylinder_size, - dev->length - cylinder_size)) - return NULL; - if (!ped_geometry_init (&end_geom, dev, 0, dev->length)) - return NULL; - } - - return ped_constraint_new (&start_align, &end_align, &start_geom, - &end_geom, 1, dev->length); -} - -/* This constraint is for partitions starting on the first cylinder. They - * must start on the 2nd head of the 1st cylinder. - * - * NOTE: We don't always start on the 2nd head of the 1st cylinder. Windows - * Vista aligns starting partitions at sector 2048 (0x800) by default. See: - * http://support.microsoft.com/kb/923332 - */ -static PedConstraint* -_primary_start_constraint (const PedDisk* disk, - const PedPartition *part, - const PedCHSGeometry* bios_geom, - const PedGeometry* min_geom) -{ - PedDevice* dev = disk->dev; - PedSector cylinder_size = bios_geom->sectors * bios_geom->heads; - PedAlignment start_align; - PedAlignment end_align; - PedGeometry start_geom; - PedGeometry end_geom; - PedSector start_pos; - - if (part->geom.start == 2048) - /* check for known Windows Vista (NTFS >= 3.1) alignments */ - /* sector 0x800 == 2048 */ - start_pos = 2048; - else - /* all other primary partitions on a DOS label align to */ - /* the 2nd head of the first cylinder (0x3F == 63) */ - start_pos = bios_geom->sectors; - - if (!ped_alignment_init (&start_align, start_pos, 0)) - return NULL; - if (!ped_alignment_init (&end_align, -1, cylinder_size)) - return NULL; - if (min_geom) { - if (!ped_geometry_init (&start_geom, dev, start_pos, 1)) - return NULL; - if (!ped_geometry_init (&end_geom, dev, min_geom->end, - dev->length - min_geom->end)) - return NULL; - } else { - if (!ped_geometry_init (&start_geom, dev, start_pos, - dev->length - start_pos)) - return NULL; - if (!ped_geometry_init (&end_geom, dev, 0, dev->length)) - return NULL; - } - - return ped_constraint_new (&start_align, &end_align, &start_geom, - &end_geom, 1, dev->length); -} - -/* constraints for logical partitions: - * - start_offset is the offset in the start alignment. "normally", - * this is bios_geom->sectors. exceptions: MINOR > 5 at the beginning of the - * extended partition, or MINOR == 5 in the middle of the extended partition - * - is_start_part == 1 if the constraint is for the first cylinder of - * the extended partition, or == 0 if the constraint is for the second cylinder - * onwards of the extended partition. - */ -static PedConstraint* -_logical_constraint (const PedDisk* disk, const PedCHSGeometry* bios_geom, - PedSector start_offset, int is_start_part) -{ - PedPartition* ext_part = ped_disk_extended_partition (disk); - PedDevice* dev = disk->dev; - PedSector cylinder_size = bios_geom->sectors * bios_geom->heads; - PedAlignment start_align; - PedAlignment end_align; - PedGeometry max_geom; - - PED_ASSERT (ext_part != NULL, return NULL); - - if (!ped_alignment_init (&start_align, start_offset, cylinder_size)) - return NULL; - if (!ped_alignment_init (&end_align, -1, cylinder_size)) - return NULL; - if (is_start_part) { - if (!ped_geometry_init (&max_geom, dev, - ext_part->geom.start, - ext_part->geom.length)) - return NULL; - } else { - PedSector min_start; - PedSector max_length; - - min_start = ped_round_up_to (ext_part->geom.start + 1, - cylinder_size); - max_length = ext_part->geom.end - min_start + 1; - if (min_start >= ext_part->geom.end) - return NULL; - - if (!ped_geometry_init (&max_geom, dev, min_start, max_length)) - return NULL; - } - - return ped_constraint_new (&start_align, &end_align, &max_geom, - &max_geom, 1, dev->length); -} - -/* returns the minimum geometry for the extended partition, given that the - * extended partition must contain: - * * all logical partitions - * * all partition tables for all logical partitions (except the first) - * * the extended partition table - */ -static PedGeometry* -_get_min_extended_part_geom (const PedPartition* ext_part, - const PedCHSGeometry* bios_geom) -{ - PedDisk* disk = ext_part->disk; - PedSector head_size = bios_geom ? bios_geom->sectors : 1; - PedPartition* walk; - PedGeometry* min_geom; - - walk = ped_disk_get_partition (disk, 5); - if (!walk) - return NULL; - - min_geom = ped_geometry_duplicate (&walk->geom); - if (!min_geom) - return NULL; - ped_geometry_set_start (min_geom, walk->geom.start - 1 * head_size); - - for (walk = ext_part->part_list; walk; walk = walk->next) { - if (!ped_partition_is_active (walk) || walk->num == 5) - continue; - if (walk->geom.start < min_geom->start) - ped_geometry_set_start (min_geom, - walk->geom.start - 2 * head_size); - if (walk->geom.end > min_geom->end) - ped_geometry_set_end (min_geom, walk->geom.end); - } - - return min_geom; -} - -static int -_align_primary (PedPartition* part, const PedCHSGeometry* bios_geom, - const PedConstraint* constraint) -{ - PedDisk* disk = part->disk; - PedGeometry* min_geom = NULL; - PedGeometry* solution = NULL; - - if (part->type == PED_PARTITION_EXTENDED) - min_geom = _get_min_extended_part_geom (part, bios_geom); - - solution = _best_solution (part, bios_geom, solution, - _try_constraint (part, constraint, - _primary_start_constraint (disk, part, - bios_geom, min_geom))); - - solution = _best_solution (part, bios_geom, solution, - _try_constraint (part, constraint, - _primary_constraint (disk, bios_geom, - min_geom))); - - if (min_geom) - ped_geometry_destroy (min_geom); - - if (solution) { - ped_geometry_set (&part->geom, solution->start, - solution->length); - ped_geometry_destroy (solution); - return 1; - } - - return 0; -} - -static int -_logical_min_start_head (const PedPartition* part, - const PedCHSGeometry* bios_geom, - const PedPartition* ext_part, - int is_start_ext_part) -{ - PedSector cylinder_size = bios_geom->sectors * bios_geom->heads; - PedSector base_head; - - if (is_start_ext_part) - base_head = 1 + (ext_part->geom.start % cylinder_size) - / bios_geom->sectors; - else - base_head = 0; - - if (part->num == 5) - return base_head + 0; - else - return base_head + 1; -} - -/* Shamelessly copied and adapted from _partition_get_overlap_constraint - * (in disk.c) - * This should get ride of the infamous Assertion (metadata_length > 0) failed - * bug for extended msdos disklabels generated by Parted. - * 1) There always is a partition table at the start of ext_part, so we leave - * a one sector gap there. - * 2)*The partition table of part5 is always at the beginning of the ext_part - * so there is no need to leave a one sector gap before part5. - * *There always is a partition table at the beginning of each partition != 5. - * We don't need to worry to much about consistency with - * _partition_get_overlap_constraint because missing it means we are in edge - * cases anyway, and we don't lose anything by just refusing to do the job in - * those cases. - */ -static PedConstraint* -_log_meta_overlap_constraint (PedPartition* part, const PedGeometry* geom) -{ - PedGeometry safe_space; - PedSector min_start; - PedSector max_end; - PedPartition* ext_part = ped_disk_extended_partition (part->disk); - PedPartition* walk; - int not_5 = (part->num != 5); - - PED_ASSERT (ext_part != NULL, return NULL); - - walk = ext_part->part_list; - - /* 1) 2) */ - min_start = ext_part->geom.start + 1 + not_5; - max_end = ext_part->geom.end; - - while (walk != NULL /* 2) 2) */ - && ( walk->geom.start - (walk->num != 5) < geom->start - not_5 - || walk->geom.start - (walk->num != 5) <= min_start )) { - if (walk != part && ped_partition_is_active (walk)) - min_start = walk->geom.end + 1 + not_5; /* 2) */ - walk = walk->next; - } - - while (walk && (walk == part || !ped_partition_is_active (walk))) - walk = walk->next; - - if (walk) - max_end = walk->geom.start - 1 - (walk->num != 5); /* 2) */ - - if (min_start >= max_end) - return NULL; - - ped_geometry_init (&safe_space, part->disk->dev, - min_start, max_end - min_start + 1); - return ped_constraint_new_from_max (&safe_space); -} - -static int -_align_logical (PedPartition* part, const PedCHSGeometry* bios_geom, - const PedConstraint* constraint) -{ - PedDisk* disk = part->disk; - PedPartition* ext_part = ped_disk_extended_partition (disk); - PedSector cyl_size = bios_geom->sectors * bios_geom->heads; - PedSector start_base; - int head; - PedGeometry* solution = NULL; - PedConstraint *intersect, *log_meta_overlap; - - PED_ASSERT (ext_part != NULL, return 0); - - log_meta_overlap = _log_meta_overlap_constraint(part, &part->geom); - intersect = ped_constraint_intersect (constraint, log_meta_overlap); - ped_constraint_destroy (log_meta_overlap); - if (!intersect) - return 0; - - start_base = ped_round_down_to (part->geom.start, cyl_size); - - for (head = _logical_min_start_head (part, bios_geom, ext_part, 0); - head < PED_MIN (5, bios_geom->heads); head++) { - PedConstraint* disk_constraint; - PedSector start = start_base + head * bios_geom->sectors; - - if (head >= _logical_min_start_head (part, bios_geom, - ext_part, 1)) - disk_constraint = - _logical_constraint (disk, bios_geom, start, 1); - else - disk_constraint = - _logical_constraint (disk, bios_geom, start, 0); - - solution = _best_solution (part, bios_geom, solution, - _try_constraint (part, intersect, - disk_constraint)); - } - - ped_constraint_destroy (intersect); - - if (solution) { - ped_geometry_set (&part->geom, solution->start, - solution->length); - ped_geometry_destroy (solution); - return 1; - } - - return 0; -} - -static int -_align (PedPartition* part, const PedCHSGeometry* bios_geom, - const PedConstraint* constraint) -{ - if (part->type == PED_PARTITION_LOGICAL) - return _align_logical (part, bios_geom, constraint); - else - return _align_primary (part, bios_geom, constraint); -} - -static PedConstraint* -_no_geom_constraint (const PedDisk* disk, PedSector start, PedSector end) -{ - PedGeometry max; - - ped_geometry_init (&max, disk->dev, start, end - start + 1); - return ped_constraint_new_from_max (&max); -} - -static PedConstraint* -_no_geom_extended_constraint (const PedPartition* part) -{ - PedDevice* dev = part->disk->dev; - PedGeometry* min = _get_min_extended_part_geom (part, NULL); - PedGeometry start_range; - PedGeometry end_range; - PedConstraint* constraint; - - if (min) { - ped_geometry_init (&start_range, dev, 1, min->start); - ped_geometry_init (&end_range, dev, min->end, - dev->length - min->end); - ped_geometry_destroy (min); - } else { - ped_geometry_init (&start_range, dev, 1, dev->length - 1); - ped_geometry_init (&end_range, dev, 1, dev->length - 1); - } - constraint = ped_constraint_new (ped_alignment_any, ped_alignment_any, - &start_range, &end_range, 1, dev->length); - return constraint; -} - -static int -_align_primary_no_geom (PedPartition* part, const PedConstraint* constraint) -{ - PedDisk* disk = part->disk; - PedGeometry* solution; - - if (part->type == PED_PARTITION_EXTENDED) { - solution = _try_constraint (part, constraint, - _no_geom_extended_constraint (part)); - } else { - solution = _try_constraint (part, constraint, - _no_geom_constraint (disk, 1, - disk->dev->length - 1)); - } - - if (solution) { - ped_geometry_set (&part->geom, solution->start, - solution->length); - ped_geometry_destroy (solution); - return 1; - } - return 0; -} - -static int -_align_logical_no_geom (PedPartition* part, const PedConstraint* constraint) -{ - PedGeometry* solution; - - solution = _try_constraint (part, constraint, - _log_meta_overlap_constraint (part, &part->geom)); - - if (solution) { - ped_geometry_set (&part->geom, solution->start, - solution->length); - ped_geometry_destroy (solution); - return 1; - } - return 0; -} - -static int -_align_no_geom (PedPartition* part, const PedConstraint* constraint) -{ - if (part->type == PED_PARTITION_LOGICAL) - return _align_logical_no_geom (part, constraint); - else - return _align_primary_no_geom (part, constraint); -} - -static int -msdos_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PedCHSGeometry bios_geom; - DosPartitionData* dos_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - dos_data = part->disk_specific; - if (dos_data->system == PARTITION_LDM && dos_data->orig) { - PedGeometry *orig_geom = &dos_data->orig->geom; - - if (ped_geometry_test_equal (&part->geom, orig_geom) - && ped_constraint_is_solution (constraint, &part->geom)) - return 1; - - ped_geometry_set (&part->geom, orig_geom->start, - orig_geom->length); - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Parted can't resize partitions managed by " - "Windows Dynamic Disk.")); - return 0; - } - - partition_probe_bios_geometry (part, &bios_geom); - - if (_align (part, &bios_geom, constraint)) - return 1; - if (_align_no_geom (part, constraint)) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -add_metadata_part (PedDisk* disk, PedPartitionType type, PedSector start, - PedSector end) -{ - PedPartition* new_part; - - PED_ASSERT (disk != NULL, return 0); - - new_part = ped_partition_new (disk, type | PED_PARTITION_METADATA, NULL, - start, end); - if (!new_part) - goto error; - if (!ped_disk_add_partition (disk, new_part, NULL)) - goto error_destroy_new_part; - - return 1; - -error_destroy_new_part: - ped_partition_destroy (new_part); -error: - return 0; -} - -/* There are a few objectives here: - * - avoid having lots of "free space" partitions lying around, to confuse - * the front end. - * - ensure that there's enough room to put in the extended partition - * tables, etc. - */ -static int -add_logical_part_metadata (PedDisk* disk, const PedPartition* log_part) -{ - PedPartition* ext_part = ped_disk_extended_partition (disk); - PedPartition* prev = log_part->prev; - PedCHSGeometry bios_geom; - PedSector cyl_size; - PedSector metadata_start; - PedSector metadata_end; - PedSector metadata_length; - - partition_probe_bios_geometry (ext_part, &bios_geom); - cyl_size = bios_geom.sectors * bios_geom.heads; - - /* if there's metadata shortly before the partition (on the same - * cylinder), then make this new metadata partition touch the end of - * the other. No point having 63 bytes (or whatever) of free space - * partition - just confuses front-ends, etc. - * Otherwise, start the metadata at the start of the cylinder - */ - - metadata_end = log_part->geom.start - 1; - metadata_start = ped_round_down_to (metadata_end, cyl_size); - if (prev) - metadata_start = PED_MAX (metadata_start, prev->geom.end + 1); - else - metadata_start = PED_MAX (metadata_start, - ext_part->geom.start + 1); - metadata_length = metadata_end - metadata_start + 1; - - /* partition 5 doesn't need to have any metadata */ - if (log_part->num == 5 && metadata_length < bios_geom.sectors) - return 1; - - PED_ASSERT (metadata_length > 0, return 0); - - return add_metadata_part (disk, PED_PARTITION_LOGICAL, - metadata_start, metadata_end); -} - -static PedPartition* -get_last_part (const PedDisk* disk) -{ - PedPartition* first_part = disk->part_list; - PedPartition* walk; - - if (!first_part) - return NULL; - for (walk = first_part; walk->next; walk = walk->next); - return walk; -} - -/* Adds metadata placeholder partitions to cover the partition table (and - * "free" space after it that often has bootloader stuff), and the last - * incomplete cylinder at the end of the disk. - * Parted has to be mindful of the uncertainty of dev->bios_geom. - * It therefore makes sure this metadata doesn't overlap with partitions. - */ -static int -add_startend_metadata (PedDisk* disk) -{ - PedDevice* dev = disk->dev; - PedSector cyl_size = dev->bios_geom.sectors * dev->bios_geom.heads; - PedPartition* first_part = disk->part_list; - PedPartition* last_part = get_last_part (disk); - PedSector start, end; - - if (!first_part) - return 1; - - start = 0; - end = PED_MIN (dev->bios_geom.sectors - 1, first_part->geom.start - 1); - if (!add_metadata_part (disk, PED_PARTITION_NORMAL, start, end)) - return 0; - - start = PED_MAX (last_part->geom.end + 1, - ped_round_down_to (dev->length, cyl_size)); - end = dev->length - 1; - if (start < end) { - if (!add_metadata_part (disk, PED_PARTITION_NORMAL, start, end)) - return 0; - } - - return 1; -} - -static int -msdos_alloc_metadata (PedDisk* disk) -{ - PedPartition* ext_part; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - if (!add_startend_metadata (disk)) - return 0; - - ext_part = ped_disk_extended_partition (disk); - if (ext_part) { - int i; - PedSector start, end; - PedCHSGeometry bios_geom; - - for (i=5; 1; i++) { - PedPartition* log_part; - log_part = ped_disk_get_partition (disk, i); - if (!log_part) - break; - if (!add_logical_part_metadata (disk, log_part)) - return 0; - } - - partition_probe_bios_geometry (ext_part, &bios_geom); - start = ext_part->geom.start; - end = start + bios_geom.sectors - 1; - if (ext_part->part_list) - end = PED_MIN (end, - ext_part->part_list->geom.start - 1); - if (!add_metadata_part (disk, PED_PARTITION_LOGICAL, - start, end)) - return 0; - } - - return 1; -} - -static int -next_primary (const PedDisk* disk) -{ - int i; - for (i=1; i<=4; i++) { - if (!ped_disk_get_partition (disk, i)) - return i; - } - return 0; -} - -static int -next_logical (const PedDisk* disk) -{ - int i; - for (i=5; 1; i++) { - if (!ped_disk_get_partition (disk, i)) - return i; - } -} - -static int -msdos_partition_enumerate (PedPartition* part) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - /* don't re-number a primary partition */ - if (part->num != -1 && part->num <= 4) - return 1; - - part->num = -1; - - if (part->type & PED_PARTITION_LOGICAL) - part->num = next_logical (part->disk); - else - part->num = next_primary (part->disk); - - return 1; -} - -static int -msdos_get_max_primary_partition_count (const PedDisk* disk) -{ - return 4; -} - -static PedDiskOps msdos_disk_ops = { - .probe = msdos_probe, -#ifndef DISCOVER_ONLY - .clobber = msdos_clobber, -#else - .clobber = NULL, -#endif - .alloc = msdos_alloc, - .duplicate = msdos_duplicate, - .free = msdos_free, - .read = msdos_read, -#ifndef DISCOVER_ONLY - .write = msdos_write, -#else - .write = NULL, -#endif - - .partition_new = msdos_partition_new, - .partition_duplicate = msdos_partition_duplicate, - .partition_destroy = msdos_partition_destroy, - .partition_set_system = msdos_partition_set_system, - .partition_set_flag = msdos_partition_set_flag, - .partition_get_flag = msdos_partition_get_flag, - .partition_is_flag_available = msdos_partition_is_flag_available, - .partition_set_name = NULL, - .partition_get_name = NULL, - .partition_align = msdos_partition_align, - .partition_enumerate = msdos_partition_enumerate, - - .alloc_metadata = msdos_alloc_metadata, - .get_max_primary_partition_count = - msdos_get_max_primary_partition_count -}; - -static PedDiskType msdos_disk_type = { - .next = NULL, - .name = "msdos", - .ops = &msdos_disk_ops, - .features = PED_DISK_TYPE_EXTENDED -}; - -void -ped_disk_msdos_init () -{ - PED_ASSERT (sizeof (DosRawPartition) == 16, return); - PED_ASSERT (sizeof (DosRawTable) == 512, return); - - ped_disk_type_register (&msdos_disk_type); -} - -void -ped_disk_msdos_done () -{ - ped_disk_type_unregister (&msdos_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/dvh.c b/usr/src/lib/libparted/common/libparted/labels/dvh.c deleted file mode 100644 index c6275c7127..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/dvh.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001, 2002, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "dvh.h" - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* Default size for volhdr part, same val as IRIX's fx uses */ -#define PTYPE_VOLHDR_DFLTSZ 4096 - -/* Partition numbers that seem to be strongly held convention */ -#define PNUM_VOLHDR 8 -#define PNUM_VOLUME 10 - -/* Other notes of interest: - * PED_PARTITION_EXTENDED is used for volume headers - * PED_PARTITION_LOGICAL is used for bootfiles - * PED_PARTITION_NORMAL is used for all else - */ - -typedef struct _DVHDiskData { - struct device_parameters dev_params; - int swap; /* part num of swap, 0=none */ - int root; /* part num of root, 0=none */ - int boot; /* part num of boot, 0=none */ -} DVHDiskData; - -typedef struct _DVHPartData { - int type; - char name[VDNAMESIZE + 1]; /* boot volumes only */ - int real_file_size; /* boot volumes only */ -} DVHPartData; - -static PedDiskType dvh_disk_type; - -static int -dvh_probe (const PedDevice *dev) -{ - struct volume_header vh; - - if (dev->sector_size != 512) - return 0; - - if (!ped_device_read (dev, &vh, 0, 1)) - return 0; - - return PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC; -} - -#ifndef DISCOVER_ONLY -static int -dvh_clobber (PedDevice* dev) -{ - char zeros[512]; - - memset (zeros, 0, 512); - return ped_device_write (dev, zeros, 0, 1); -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk* -dvh_alloc (const PedDevice* dev) -{ - PedDisk* disk; - DVHDiskData* dvh_disk_data; - PedPartition* volume_part; - PedConstraint* constraint_any; - - disk = _ped_disk_alloc (dev, &dvh_disk_type); - if (!disk) - goto error; - - disk->disk_specific = dvh_disk_data - = ped_malloc (sizeof (DVHDiskData)); - if (!dvh_disk_data) - goto error_free_disk; - - memset (&dvh_disk_data->dev_params, 0, - sizeof (struct device_parameters)); - dvh_disk_data->swap = 0; - dvh_disk_data->root = 0; - dvh_disk_data->boot = 0; - - volume_part = ped_partition_new (disk, PED_PARTITION_EXTENDED, NULL, - 0, PTYPE_VOLHDR_DFLTSZ - 1); - if (!volume_part) - goto error_free_disk_specific; - volume_part->num = PNUM_VOLHDR + 1; - constraint_any = ped_constraint_any (dev); - if (!ped_disk_add_partition (disk, volume_part, constraint_any)) - goto error_destroy_constraint_any; - ped_constraint_destroy (constraint_any); - return disk; - -error_destroy_constraint_any: - ped_constraint_destroy (constraint_any); - ped_partition_destroy (volume_part); -error_free_disk_specific: - ped_free (disk->disk_specific); -error_free_disk: - ped_free (disk); -error: - return NULL; -} - -static PedDisk* -dvh_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - DVHDiskData* new_dvh_disk_data; - DVHDiskData* old_dvh_disk_data = disk->disk_specific; - - PED_ASSERT (old_dvh_disk_data != NULL, goto error); - - new_disk = _ped_disk_alloc (disk->dev, &dvh_disk_type); - if (!new_disk) - goto error; - - new_disk->disk_specific = new_dvh_disk_data - = ped_malloc (sizeof (DVHDiskData)); - if (!new_dvh_disk_data) - goto error_free_new_disk; - - new_dvh_disk_data->dev_params = old_dvh_disk_data->dev_params; - return new_disk; - -error_free_new_disk: - ped_free (new_disk); -error: - return NULL; -} - -static void -dvh_free (PedDisk* disk) -{ - ped_free (disk->disk_specific); - _ped_disk_free (disk); -} - -/* two's complement 32-bit checksum */ -static uint32_t -_checksum (const uint32_t* base, size_t size) -{ - uint32_t sum = 0; - size_t i; - - for (i = 0; i < size / sizeof (uint32_t); i++) - sum = sum - PED_BE32_TO_CPU (base[i]); - - return sum; -} - -/* try to make a reasonable volume header partition... */ -static PedExceptionOption -_handle_no_volume_header (PedDisk* disk) -{ - PedExceptionOption ret; - PedPartition* part; - PedConstraint* constraint; - - switch (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_FIX + PED_EXCEPTION_CANCEL, - _("%s has no extended partition (volume header partition)."), - disk->dev->path)) { - case PED_EXCEPTION_UNHANDLED: - case PED_EXCEPTION_FIX: - default: - part = ped_partition_new ( - disk, PED_PARTITION_EXTENDED, NULL, - 0, PTYPE_VOLHDR_DFLTSZ - 1); - if (!part) - goto error; - part->num = PNUM_VOLHDR + 1; - constraint = ped_constraint_any (part->disk->dev); - if (!constraint) - goto error_destroy_part; - if (!ped_disk_add_partition (disk, part, constraint)) - goto error_destroy_constraint; - ped_constraint_destroy (constraint); - ret = PED_EXCEPTION_FIX; - break; - - case PED_EXCEPTION_CANCEL: - goto error; - } - return ret; - -error_destroy_constraint: - ped_constraint_destroy (constraint); -error_destroy_part: - ped_partition_destroy (part); -error: - return PED_EXCEPTION_CANCEL; -} - -static PedPartition* -_parse_partition (PedDisk* disk, struct partition_table* pt) -{ - PedPartition* part; - DVHPartData* dvh_part_data; - PedSector start = PED_BE32_TO_CPU (pt->pt_firstlbn); - PedSector length = PED_BE32_TO_CPU (pt->pt_nblks); - - part = ped_partition_new (disk, - pt->pt_type ? 0 : PED_PARTITION_EXTENDED, - NULL, - start, start + length - 1); - if (!part) - return NULL; - - dvh_part_data = part->disk_specific; - dvh_part_data->type = PED_BE32_TO_CPU (pt->pt_type); - strcpy (dvh_part_data->name, ""); - - return part; -} - -static PedPartition* -_parse_boot_file (PedDisk* disk, struct volume_directory* vd) -{ - PedPartition* part; - DVHPartData* dvh_part_data; - PedSector start = PED_BE32_TO_CPU (vd->vd_lbn); - int length = PED_BE32_TO_CPU (vd->vd_nbytes); - - part = ped_partition_new (disk, PED_PARTITION_LOGICAL, NULL, - start, start + length/512 - 1); - if (!part) - return NULL; - - dvh_part_data = part->disk_specific; - dvh_part_data->real_file_size = length; - - strncpy (dvh_part_data->name, vd->vd_name, VDNAMESIZE); - dvh_part_data->name[VDNAMESIZE] = 0; - return part; -} - -static int dvh_write (const PedDisk* disk); - -/* YUCK - * - * If you remove a boot/root/swap partition, the disk->disk_specific - * thing isn't updated. (Probably reflects a design bug somewhere...) - * Anyway, the workaround is: flush stale flags whenever we allocate - * new partition numbers, and before we write to disk. - */ -static void -_flush_stale_flags (const PedDisk* disk) -{ - DVHDiskData* dvh_disk_data = disk->disk_specific; - - if (dvh_disk_data->root - && !ped_disk_get_partition (disk, dvh_disk_data->root)) - dvh_disk_data->root = 0; - if (dvh_disk_data->swap - && !ped_disk_get_partition (disk, dvh_disk_data->swap)) - dvh_disk_data->swap = 0; - if (dvh_disk_data->boot - && !ped_disk_get_partition (disk, dvh_disk_data->boot)) - dvh_disk_data->boot = 0; -} - -static int -dvh_read (PedDisk* disk) -{ - DVHDiskData* dvh_disk_data = disk->disk_specific; - int i; - struct volume_header vh; - char boot_name [BFNAMESIZE + 1]; -#ifndef DISCOVER_ONLY - int write_back = 0; -#endif - - PED_ASSERT (dvh_disk_data != NULL, return 0); - - ped_disk_delete_all (disk); - - if (!ped_device_read (disk->dev, &vh, 0, 1)) - return 0; - - if (_checksum ((uint32_t*) &vh, sizeof (struct volume_header))) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Checksum is wrong, indicating the partition " - "table is corrupt.")) - == PED_EXCEPTION_CANCEL) - return 0; - } - - PED_ASSERT (PED_BE32_TO_CPU (vh.vh_magic) == VHMAGIC, return 0); - - dvh_disk_data->dev_params = vh.vh_dp; - strncpy (boot_name, vh.vh_bootfile, BFNAMESIZE); - boot_name[BFNAMESIZE] = 0; - - /* normal partitions */ - for (i = 0; i < NPARTAB; i++) { - PedPartition* part; - PedConstraint* constraint_exact; - - if (!vh.vh_pt[i].pt_nblks) - continue; - /* Skip the whole-disk partition, parted disklikes overlap */ - if (PED_BE32_TO_CPU (vh.vh_pt[i].pt_type) == PTYPE_VOLUME) - continue; - - part = _parse_partition (disk, &vh.vh_pt[i]); - if (!part) - goto error_delete_all; - - part->fs_type = ped_file_system_probe (&part->geom); - part->num = i + 1; - - if (PED_BE16_TO_CPU (vh.vh_rootpt) == i) - ped_partition_set_flag (part, PED_PARTITION_ROOT, 1); - if (PED_BE16_TO_CPU (vh.vh_swappt) == i) - ped_partition_set_flag (part, PED_PARTITION_SWAP, 1); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition(disk, part, constraint_exact)) { - ped_partition_destroy (part); - goto error_delete_all; - } - ped_constraint_destroy (constraint_exact); - } - - if (!ped_disk_extended_partition (disk)) { -#ifdef DISCOVER_ONLY - return 1; -#else - switch (_handle_no_volume_header (disk)) { - case PED_EXCEPTION_CANCEL: - return 0; - case PED_EXCEPTION_IGNORE: - return 1; - case PED_EXCEPTION_FIX: - write_back = 1; - break; - default: - break; - } -#endif - } - - /* boot partitions */ - for (i = 0; i < NVDIR; i++) { - PedPartition* part; - PedConstraint* constraint_exact; - - if (!vh.vh_vd[i].vd_nbytes) - continue; - - part = _parse_boot_file (disk, &vh.vh_vd[i]); - if (!part) - goto error_delete_all; - - part->fs_type = ped_file_system_probe (&part->geom); - part->num = NPARTAB + i + 1; - - if (!strcmp (boot_name, ped_partition_get_name (part))) - ped_partition_set_flag (part, PED_PARTITION_BOOT, 1); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition(disk, part, constraint_exact)) { - ped_partition_destroy (part); - goto error_delete_all; - } - ped_constraint_destroy (constraint_exact); - } -#ifndef DISCOVER_ONLY - if (write_back) - dvh_write (disk); -#endif - return 1; - -error_delete_all: - ped_disk_delete_all (disk); - return 0; -} - -#ifndef DISCOVER_ONLY -static void -_generate_partition (PedPartition* part, struct partition_table* pt) -{ - DVHPartData* dvh_part_data = part->disk_specific; - - /* Assert not a bootfile */ - PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) == 0, return); - - pt->pt_nblks = PED_CPU_TO_BE32 (part->geom.length); - pt->pt_firstlbn = PED_CPU_TO_BE32 (part->geom.start); - pt->pt_type = PED_CPU_TO_BE32 (dvh_part_data->type); -} - -static void -_generate_boot_file (PedPartition* part, struct volume_directory* vd) -{ - DVHPartData* dvh_part_data = part->disk_specific; - - /* Assert it's a bootfile */ - PED_ASSERT ((part->type & PED_PARTITION_LOGICAL) != 0, return); - - vd->vd_nbytes = PED_CPU_TO_BE32 (dvh_part_data->real_file_size); - vd->vd_lbn = PED_CPU_TO_BE32 (part->geom.start); - - memset (vd->vd_name, 0, VDNAMESIZE); - strncpy (vd->vd_name, dvh_part_data->name, VDNAMESIZE); -} - -static int -dvh_write (const PedDisk* disk) -{ - DVHDiskData* dvh_disk_data = disk->disk_specific; - struct volume_header vh; - int i; - - PED_ASSERT (dvh_disk_data != NULL, return 0); - - _flush_stale_flags (disk); - - memset (&vh, 0, sizeof (struct volume_header)); - - vh.vh_magic = PED_CPU_TO_BE32 (VHMAGIC); - vh.vh_rootpt = PED_CPU_TO_BE16 (dvh_disk_data->root - 1); - vh.vh_swappt = PED_CPU_TO_BE16 (dvh_disk_data->swap - 1); - - if (dvh_disk_data->boot) { - PedPartition* boot_part; - boot_part = ped_disk_get_partition (disk, dvh_disk_data->boot); - strcpy (vh.vh_bootfile, ped_partition_get_name (boot_part)); - } - - vh.vh_dp = dvh_disk_data->dev_params; - /* Set up rudimentary device geometry */ - vh.vh_dp.dp_cyls - = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.cylinders); - vh.vh_dp.dp_trks0 = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.heads); - vh.vh_dp.dp_secs - = PED_CPU_TO_BE16 ((short)disk->dev->bios_geom.sectors); - vh.vh_dp.dp_secbytes = PED_CPU_TO_BE16 ((short)disk->dev->sector_size); - - for (i = 0; i < NPARTAB; i++) { - PedPartition* part = ped_disk_get_partition (disk, i + 1); - if (part) - _generate_partition (part, &vh.vh_pt[i]); - } - - /* whole disk partition - * This is only ever written here, and never modified - * (or even shown) as it must contain the entire disk, - * and parted does not like overlapping partitions - */ - vh.vh_pt[PNUM_VOLUME].pt_nblks = PED_CPU_TO_BE32 (disk->dev->length); - vh.vh_pt[PNUM_VOLUME].pt_firstlbn = PED_CPU_TO_BE32 (0); - vh.vh_pt[PNUM_VOLUME].pt_type = PED_CPU_TO_BE32 (PTYPE_VOLUME); - - for (i = 0; i < NVDIR; i++) { - PedPartition* part = ped_disk_get_partition (disk, - i + 1 + NPARTAB); - if (part) - _generate_boot_file (part, &vh.vh_vd[i]); - } - - vh.vh_csum = 0; - vh.vh_csum = PED_CPU_TO_BE32 (_checksum ((uint32_t*) &vh, - sizeof (struct volume_header))); - - return ped_device_write (disk->dev, &vh, 0, 1) - && ped_device_sync (disk->dev); -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -dvh_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - DVHPartData* dvh_part_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (!ped_partition_is_active (part)) { - part->disk_specific = NULL; - return part; - } - - dvh_part_data = part->disk_specific = - ped_malloc (sizeof (DVHPartData)); - if (!dvh_part_data) - goto error_free_part; - - dvh_part_data->type = (part_type == PED_PARTITION_EXTENDED) - ? PTYPE_VOLHDR - : PTYPE_RAW; - strcpy (dvh_part_data->name, ""); - dvh_part_data->real_file_size = part->geom.length * 512; - return part; - -error_free_part: - _ped_partition_free (part); -error: - return NULL; -} - -static PedPartition* -dvh_partition_duplicate (const PedPartition* part) -{ - PedPartition* result; - DVHPartData* part_data = part->disk_specific; - DVHPartData* result_data; - - result = _ped_partition_alloc (part->disk, part->type, part->fs_type, - part->geom.start, part->geom.end); - if (!result) - goto error; - result->num = part->num; - - if (!ped_partition_is_active (part)) { - result->disk_specific = NULL; - return result; - } - - result_data = result->disk_specific = - ped_malloc (sizeof (DVHPartData)); - if (!result_data) - goto error_free_part; - - result_data->type = part_data->type; - strcpy (result_data->name, part_data->name); - result_data->real_file_size = part_data->real_file_size; - return result; - -error_free_part: - _ped_partition_free (result); -error: - return NULL; -} - -static void -dvh_partition_destroy (PedPartition* part) -{ - if (ped_partition_is_active (part)) { - PED_ASSERT (part->disk_specific != NULL, return); - ped_free (part->disk_specific); - } - _ped_partition_free (part); -} - -static int -dvh_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - DVHPartData* dvh_part_data = part->disk_specific; - - part->fs_type = fs_type; - - if (part->type == PED_PARTITION_EXTENDED) { - dvh_part_data->type = PTYPE_VOLHDR; - return 1; - } - - /* Is this a bootfile? */ - if (part->type == PED_PARTITION_LOGICAL) - return 1; - - if (fs_type && !strcmp (fs_type->name, "xfs")) - dvh_part_data->type = PTYPE_XFS; - else - dvh_part_data->type = PTYPE_RAW; - return 1; -} - -static int -dvh_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - DVHDiskData* dvh_disk_data = part->disk->disk_specific; - - switch (flag) { - case PED_PARTITION_ROOT: - if (part->type != 0 && state) { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Only primary partitions can be root " - "partitions.")); -#endif - return 0; - } - dvh_disk_data->root = state ? part->num : 0; - break; - - case PED_PARTITION_SWAP: - if (part->type != 0 && state) { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Only primary partitions can be swap " - "partitions.")); - return 0; -#endif - } - dvh_disk_data->swap = state ? part->num : 0; - break; - - case PED_PARTITION_BOOT: - if (part->type != PED_PARTITION_LOGICAL && state) { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Only logical partitions can be a boot " - "file.")); -#endif - return 0; - } - dvh_disk_data->boot = state ? part->num : 0; - break; - - case PED_PARTITION_LVM: - case PED_PARTITION_LBA: - case PED_PARTITION_HIDDEN: - case PED_PARTITION_RAID: - default: - return 0; - } - return 1; -} - -static int -dvh_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - DVHDiskData* dvh_disk_data = part->disk->disk_specific; - - switch (flag) { - case PED_PARTITION_ROOT: - return dvh_disk_data->root == part->num; - - case PED_PARTITION_SWAP: - return dvh_disk_data->swap == part->num; - - case PED_PARTITION_BOOT: - return dvh_disk_data->boot == part->num; - - case PED_PARTITION_LVM: - case PED_PARTITION_LBA: - case PED_PARTITION_HIDDEN: - case PED_PARTITION_RAID: - default: - return 0; - } - return 1; -} - -static int -dvh_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_ROOT: - case PED_PARTITION_SWAP: - case PED_PARTITION_BOOT: - return 1; - - case PED_PARTITION_LVM: - case PED_PARTITION_LBA: - case PED_PARTITION_HIDDEN: - case PED_PARTITION_RAID: - default: - return 0; - } - return 1; -} - -static void -dvh_partition_set_name (PedPartition* part, const char* name) -{ - DVHPartData* dvh_part_data = part->disk_specific; - - if (part->type == PED_PARTITION_LOGICAL) { - /* Bootfile */ - strncpy (dvh_part_data->name, name, VDNAMESIZE); - dvh_part_data->name[VDNAMESIZE] = 0; - } else { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Only logical partitions (boot files) have a name.")); -#endif - } -} - -static const char* -dvh_partition_get_name (const PedPartition* part) -{ - DVHPartData* dvh_part_data = part->disk_specific; - return dvh_part_data->name; -} - -/* The constraint for the volume header partition is different, because it must - * contain the first sector of the disk. - */ -static PedConstraint* -_get_extended_constraint (PedDisk* disk) -{ - PedGeometry min_geom; - if (!ped_geometry_init (&min_geom, disk->dev, 0, 1)) - return NULL; - return ped_constraint_new_from_min (&min_geom); -} - -static PedConstraint* -_get_primary_constraint (PedDisk* disk) -{ - PedGeometry max_geom; - if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1)) - return NULL; - return ped_constraint_new_from_max (&max_geom); -} - -static int -dvh_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - if (_ped_partition_attempt_align ( - part, constraint, - (part->type == PED_PARTITION_EXTENDED) - ? _get_extended_constraint (part->disk) - : _get_primary_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -dvh_partition_enumerate (PedPartition* part) -{ - int i; - - /* never change the partition numbers */ - if (part->num != -1) - return 1; - - _flush_stale_flags (part->disk); - - if (part->type & PED_PARTITION_LOGICAL) { - /* Bootfile */ - for (i = 1 + NPARTAB; i <= NPARTAB + NVDIR; i++) { - if (!ped_disk_get_partition (part->disk, i)) { - part->num = i; - return 1; - } - } - PED_ASSERT (0, return 0); - } else if (part->type & PED_PARTITION_EXTENDED) { - /* Volheader */ - part->num = PNUM_VOLHDR + 1; - } else { - for (i = 1; i <= NPARTAB; i++) { - /* reserved for full volume partition */ - if (i == PNUM_VOLUME + 1) - continue; - - if (!ped_disk_get_partition (part->disk, i)) { - part->num = i; - return 1; - } - } - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Too many primary partitions")); - } - - return 0; -} - -static int -dvh_get_max_primary_partition_count (const PedDisk* disk) -{ - return NPARTAB; -} - -static int -dvh_alloc_metadata (PedDisk* disk) -{ - PedPartition* part; - PedPartition* extended_part; - PedConstraint* constraint_exact; - PedPartitionType metadata_type; - PED_ASSERT(disk != NULL, return 0); - - /* We don't need to "protect" the start of the disk from the volume - * header. - */ - extended_part = ped_disk_extended_partition (disk); - if (extended_part && extended_part->geom.start == 0) - metadata_type = PED_PARTITION_METADATA | PED_PARTITION_LOGICAL; - else - metadata_type = PED_PARTITION_METADATA; - - part = ped_partition_new (disk, metadata_type, NULL, 0, 0); - if (!part) - goto error; - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error_destroy_part; - ped_constraint_destroy (constraint_exact); - return 1; - - ped_constraint_destroy (constraint_exact); -error_destroy_part: - ped_partition_destroy (part); -error: - return 0; -} - -static PedDiskOps dvh_disk_ops = { - .probe = dvh_probe, -#ifndef DISCOVER_ONLY - .clobber = dvh_clobber, -#else - .clobber = NULL, -#endif - .alloc = dvh_alloc, - .duplicate = dvh_duplicate, - .free = dvh_free, - .read = dvh_read, -#ifndef DISCOVER_ONLY - .write = dvh_write, -#else - .write = NULL, -#endif - - .partition_new = dvh_partition_new, - .partition_duplicate = dvh_partition_duplicate, - .partition_destroy = dvh_partition_destroy, - .partition_set_system = dvh_partition_set_system, - .partition_set_flag = dvh_partition_set_flag, - .partition_get_flag = dvh_partition_get_flag, - .partition_is_flag_available = dvh_partition_is_flag_available, - .partition_set_name = dvh_partition_set_name, - .partition_get_name = dvh_partition_get_name, - .partition_align = dvh_partition_align, - .partition_enumerate = dvh_partition_enumerate, - - .alloc_metadata = dvh_alloc_metadata, - .get_max_primary_partition_count = - dvh_get_max_primary_partition_count -}; - -static PedDiskType dvh_disk_type = { - .next = NULL, - .name = "dvh", - .ops = &dvh_disk_ops, - .features = PED_DISK_TYPE_PARTITION_NAME | PED_DISK_TYPE_EXTENDED -}; - -void -ped_disk_dvh_init () -{ - PED_ASSERT (sizeof (struct volume_header) == 512, return); - - ped_disk_type_register (&dvh_disk_type); -} - -void -ped_disk_dvh_done () -{ - ped_disk_type_unregister (&dvh_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/dvh.h b/usr/src/lib/libparted/common/libparted/labels/dvh.h deleted file mode 100644 index 992f3ee87b..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/dvh.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - Copyright (C) 1985 MIPS Computer Systems, Inc. - Copyright (C) 2000 Silicon Graphics Computer Systems, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef _SYS_DVH_H -#define _SYS_DVH_H - -/* - * Format for volume header information - * - * The volume header is a block located at the beginning of all disk - * media (sector 0). It contains information pertaining to physical - * device parameters and logical partition information. - * - * The volume header is manipulated by disk formatters/verifiers, - * partition builders (e.g. fx, dvhtool, and mkfs), and disk drivers. - * - * Previous versions of IRIX wrote a copy of the volume header is - * located at sector 0 of each track of cylinder 0. These copies were - * never used, and reduced the capacity of the volume header to hold large - * files, so this practice was discontinued. - * The volume header is constrained to be less than or equal to 512 - * bytes long. A particular copy is assumed valid if no drive errors - * are detected, the magic number is correct, and the 32 bit 2's complement - * of the volume header is correct. The checksum is calculated by initially - * zeroing vh_csum, summing the entire structure and then storing the - * 2's complement of the sum. Thus a checksum to verify the volume header - * should be 0. - * - * The error summary table, bad sector replacement table, and boot blocks are - * located by searching the volume directory within the volume header. - * - * Tables are sized simply by the integral number of table records that - * will fit in the space indicated by the directory entry. - * - * The amount of space allocated to the volume header, replacement blocks, - * and other tables is user defined when the device is formatted. - */ - -/* - * device parameters are in the volume header to determine mapping - * from logical block numbers to physical device addresses - * - * Linux doesn't care ... - */ -struct device_parameters { - unsigned char dp_skew; /* spiral addressing skew */ - unsigned char dp_gap1; /* words of 0 before header */ - unsigned char dp_gap2; /* words of 0 between hdr and data */ - unsigned char dp_spares_cyl; /* This is for drives (such as SCSI - that support zone oriented sparing, where the zone is larger - than one track. It gets subracteded from the cylinder size - ( dp_trks0 * dp_sec) when doing partition size calculations */ - unsigned short dp_cyls; /* number of usable cylinders (i.e., - doesn't include cylinders reserved by the drive for badblocks, - etc.). For drives with variable geometry, this number may be - decreased so that: - dp_cyls * ((dp_heads * dp_trks0) - dp_spares_cyl) <= actualcapacity - This happens on SCSI drives such as the Wren IV and Toshiba 156 - Also see dp_cylshi below */ - unsigned short dp_shd0; /* starting head vol 0 */ - unsigned short dp_trks0; /* number of tracks / cylinder vol 0*/ - unsigned char dp_ctq_depth; /* Depth of CTQ queue */ - unsigned char dp_cylshi; /* high byte of 24 bits of cylinder count */ - unsigned short dp_unused; /* not used */ - unsigned short dp_secs; /* number of sectors/track */ - unsigned short dp_secbytes; /* length of sector in bytes */ - unsigned short dp_interleave; /* sector interleave */ - int dp_flags; /* controller characteristics */ - int dp_datarate; /* bytes/sec for kernel stats */ - int dp_nretries; /* max num retries on data error */ - int dp_mspw; /* ms per word to xfer, for iostat */ - unsigned short dp_xgap1; /* Gap 1 for xylogics controllers */ - unsigned short dp_xsync; /* sync delay for xylogics controllers */ - unsigned short dp_xrdly; /* read delay for xylogics controllers */ - unsigned short dp_xgap2; /* gap 2 for xylogics controllers */ - unsigned short dp_xrgate; /* read gate for xylogics controllers */ - unsigned short dp_xwcont; /* write continuation for xylogics */ -}; - -/* - * Device characterization flags - * (dp_flags) - */ -#define DP_SECTSLIP 0x00000001 /* sector slip to spare sector */ -#define DP_SECTFWD 0x00000002 /* forward to replacement sector */ -#define DP_TRKFWD 0x00000004 /* forward to replacement track */ -#define DP_MULTIVOL 0x00000008 /* multiple volumes per spindle */ -#define DP_IGNOREERRORS 0x00000010 /* transfer data regardless of errors */ -#define DP_RESEEK 0x00000020 /* recalibrate as last resort */ -#define DP_CTQ_EN 0x00000040 /* enable command tag queueing */ - -/* - * Boot blocks, bad sector tables, and the error summary table, are located - * via the volume_directory. - */ -#define VDNAMESIZE 8 - -struct volume_directory { - char vd_name[VDNAMESIZE]; /* name */ - int vd_lbn; /* logical block number */ - int vd_nbytes; /* file length in bytes */ -}; - -/* - * partition table describes logical device partitions - * (device drivers examine this to determine mapping from logical units - * to cylinder groups, device formatters/verifiers examine this to determine - * location of replacement tracks/sectors, etc) - * - * NOTE: pt_firstlbn SHOULD BE CYLINDER ALIGNED - */ -struct partition_table { /* one per logical partition */ - int pt_nblks; /* # of logical blks in partition */ - int pt_firstlbn; /* first lbn of partition */ - int pt_type; /* use of partition */ -}; - -#define PTYPE_VOLHDR 0 /* partition is volume header */ -#define PTYPE_TRKREPL 1 /* partition is used for repl trks */ -#define PTYPE_SECREPL 2 /* partition is used for repl secs */ -#define PTYPE_RAW 3 /* partition is used for data */ -#define PTYPE_BSD42 4 /* partition is 4.2BSD file system */ -#define PTYPE_BSD 4 /* partition is 4.2BSD file system */ -#define PTYPE_SYSV 5 /* partition is SysV file system */ -#define PTYPE_VOLUME 6 /* partition is entire volume */ -#define PTYPE_EFS 7 /* partition is sgi EFS */ -#define PTYPE_LVOL 8 /* partition is part of a logical vol */ -#define PTYPE_RLVOL 9 /* part of a "raw" logical vol */ -#define PTYPE_XFS 10 /* partition is sgi XFS */ -#define PTYPE_XFSLOG 11 /* partition is sgi XFS log */ -#define PTYPE_XLV 12 /* partition is part of an XLV vol */ -#define PTYPE_XVM 13 /* partition is sgi XVM */ -#define NPTYPES 16 - -#define VHMAGIC 0xbe5a941 /* randomly chosen value */ -#define NPARTAB 16 /* 16 unix partitions */ -#define NVDIR 15 /* max of 15 directory entries */ -#define BFNAMESIZE 16 /* max 16 chars in boot file name */ - -/* Partition types for ARCS */ -#define NOT_USED 0 /* Not used */ -#define FAT_SHORT 1 /* FAT file system, 12-bit FAT entries */ -#define FAT_LONG 4 /* FAT file system, 16-bit FAT entries */ -#define EXTENDED 5 /* extended partition */ -#define HUGE 6 /* huge partition- MS/DOS 4.0 and later */ - -/* Active flags for ARCS */ -#define BOOTABLE 0x00; -#define NOT_BOOTABLE 0x80; - -struct volume_header { - int vh_magic; /* identifies volume header */ - short vh_rootpt; /* root partition number */ - short vh_swappt; /* swap partition number */ - char vh_bootfile[BFNAMESIZE]; /* name of file to boot */ - struct device_parameters vh_dp; /* device parameters */ - struct volume_directory vh_vd[NVDIR]; /* other vol hdr contents */ - struct partition_table vh_pt[NPARTAB]; /* device partition layout */ - int vh_csum; /* volume header checksum */ - int vh_fill; /* fill out to 512 bytes */ -}; - -#endif /* _SYS_DVH_H */ diff --git a/usr/src/lib/libparted/common/libparted/labels/efi_crc32.c b/usr/src/lib/libparted/common/libparted/labels/efi_crc32.c deleted file mode 100644 index 327fb2dd4b..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/efi_crc32.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Dec 5, 2000 Matt Domsch - * - Copied crc32.c from the linux/drivers/net/cipe directory. - * - Now pass seed as an arg - * - changed unsigned long to uint32_t, added #include - * - changed len to be an unsigned long - * - changed crc32val to be a register - * - License remains unchanged! It's still GPL-compatable! - */ - - /* ============================================================= */ - /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ - /* code or tables extracted from it, as desired without restriction. */ - /* */ - /* First, the polynomial itself and its table of feedback terms. The */ - /* polynomial is */ - /* 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 */ - /* */ - /* Note that we take it "backwards" and put the highest-order term in */ - /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ - /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ - /* the MSB being 1. */ - /* */ - /* Note that the usual hardware shift register implementation, which */ - /* is what we're using (we're merely optimizing it by doing eight-bit */ - /* chunks at a time) shifts bits into the lowest-order term. In our */ - /* implementation, that means shifting towards the right. Why do we */ - /* do it this way? Because the calculated CRC must be transmitted in */ - /* order from highest-order term to lowest-order term. UARTs transmit */ - /* characters in order from LSB to MSB. By storing the CRC this way, */ - /* we hand it to the UART in the order low-byte to high-byte; the UART */ - /* sends each low-bit to hight-bit; and the result is transmission bit */ - /* by bit from highest- to lowest-order term without requiring any bit */ - /* shuffling on our part. Reception works similarly. */ - /* */ - /* The feedback terms table consists of 256, 32-bit entries. Notes: */ - /* */ - /* The table can be generated at runtime if desired; code to do so */ - /* is shown later. It might not be obvious, but the feedback */ - /* terms simply represent the results of eight shift/xor opera- */ - /* tions for all combinations of data and CRC register values. */ - /* */ - /* The values must be right-shifted by eight bits by the "updcrc" */ - /* logic; the shift must be unsigned (bring in zeroes). On some */ - /* hardware you could probably optimize the shift in assembler by */ - /* using byte-swap instructions. */ - /* polynomial $edb88320 */ - /* */ - /* -------------------------------------------------------------------- */ - -#include -#include - -static const uint32_t crc32_tab[] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL - }; - -/* Return a 32-bit CRC of the contents of the buffer. */ - -uint32_t -__efi_crc32(const void *buf, unsigned long len, uint32_t seed) -{ - unsigned long i; - register uint32_t crc32val; - const unsigned char *s = buf; - - crc32val = seed; - for (i = 0; i < len; i ++) - { - crc32val = - crc32_tab[(crc32val ^ s[i]) & 0xff] ^ - (crc32val >> 8); - } - return crc32val; -} diff --git a/usr/src/lib/libparted/common/libparted/labels/gpt.c b/usr/src/lib/libparted/common/libparted/labels/gpt.c deleted file mode 100644 index e7877dab45..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/gpt.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - - original version by Matt Domsch - Disclaimed into the Public Domain - - Portions Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007 - Free Software Foundation, Inc. - - EFI GUID Partition Table handling - Per Intel EFI Specification v1.02 - http://developer.intel.com/technology/efi/efi.htm - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) gettext (String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define EFI_PMBR_OSTYPE_EFI 0xEE -#define MSDOS_MBR_SIGNATURE 0xaa55 - -#define GPT_HEADER_SIGNATURE 0x5452415020494645LL - -/* NOTE: the document that describes revision 1.00 is labelled "version 1.02", - * so some implementors got confused... - */ -#define GPT_HEADER_REVISION_V1_02 0x00010200 -#define GPT_HEADER_REVISION_V1_00 0x00010000 -#define GPT_HEADER_REVISION_V0_99 0x00009900 - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -typedef uint16_t efi_char16_t; /* UNICODE character */ -typedef struct _GuidPartitionTableHeader_t GuidPartitionTableHeader_t; -typedef struct _GuidPartitionEntryAttributes_t GuidPartitionEntryAttributes_t; -typedef struct _GuidPartitionEntry_t GuidPartitionEntry_t; -typedef struct _PartitionRecord_t PartitionRecord_t; -typedef struct _LegacyMBR_t LegacyMBR_t; -typedef struct _GPTDiskData GPTDiskData; -typedef struct { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint8_t clock_seq_hi_and_reserved; - uint8_t clock_seq_low; - uint8_t node[6]; -} /* __attribute__ ((packed)) */ efi_guid_t; -/* commented out "__attribute__ ((packed))" to work around gcc bug (fixed - * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized - * data. It turns out we don't need it in this case, so it doesn't break - * anything :) - */ - -#define UNUSED_ENTRY_GUID \ - ((efi_guid_t) { 0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}) -#define PARTITION_SYSTEM_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xC12A7328), PED_CPU_TO_LE16 (0xF81F), \ - PED_CPU_TO_LE16 (0x11d2), 0xBA, 0x4B, \ - { 0x00, 0xA0, 0xC9, 0x3E, 0xC9, 0x3B }}) -#define LEGACY_MBR_PARTITION_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0x024DEE41), PED_CPU_TO_LE16 (0x33E7), \ - PED_CPU_TO_LE16 (0x11d3, 0x9D, 0x69, \ - { 0x00, 0x08, 0xC7, 0x81, 0xF3, 0x9F }}) -#define PARTITION_MSFT_RESERVED_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xE3C9E316), PED_CPU_TO_LE16 (0x0B5C), \ - PED_CPU_TO_LE16 (0x4DB8), 0x81, 0x7D, \ - { 0xF9, 0x2D, 0xF0, 0x02, 0x15, 0xAE }}) -#define PARTITION_BASIC_DATA_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xEBD0A0A2), PED_CPU_TO_LE16 (0xB9E5), \ - PED_CPU_TO_LE16 (0x4433), 0x87, 0xC0, \ - { 0x68, 0xB6, 0xB7, 0x26, 0x99, 0xC7 }}) -#define PARTITION_RAID_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xa19d880f), PED_CPU_TO_LE16 (0x05fc), \ - PED_CPU_TO_LE16 (0x4d3b), 0xa0, 0x06, \ - { 0x74, 0x3f, 0x0f, 0x84, 0x91, 0x1e }}) -#define PARTITION_SWAP_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0x0657fd6d), PED_CPU_TO_LE16 (0xa4ab), \ - PED_CPU_TO_LE16 (0x43c4), 0x84, 0xe5, \ - { 0x09, 0x33, 0xc8, 0x4b, 0x4f, 0x4f }}) -#define PARTITION_LVM_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xe6d6d379), PED_CPU_TO_LE16 (0xf507), \ - PED_CPU_TO_LE16 (0x44c2), 0xa2, 0x3c, \ - { 0x23, 0x8f, 0x2a, 0x3d, 0xf9, 0x28 }}) -#define PARTITION_RESERVED_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0x8da63339), PED_CPU_TO_LE16 (0x0007), \ - PED_CPU_TO_LE16 (0x60c0), 0xc4, 0x36, \ - { 0x08, 0x3a, 0xc8, 0x23, 0x09, 0x08 }}) -#define PARTITION_HPSERVICE_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0xe2a1e728), PED_CPU_TO_LE16 (0x32e3), \ - PED_CPU_TO_LE16 (0x11d6), 0xa6, 0x82, \ - { 0x7b, 0x03, 0xa0, 0x00, 0x00, 0x00 }}) -#define PARTITION_APPLE_HFS_GUID \ - ((efi_guid_t) { PED_CPU_TO_LE32 (0x48465300), PED_CPU_TO_LE16 (0x0000), \ - PED_CPU_TO_LE16 (0x11AA), 0xaa, 0x11, \ - { 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC }}) - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _GuidPartitionTableHeader_t { - uint64_t Signature; - uint32_t Revision; - uint32_t HeaderSize; - uint32_t HeaderCRC32; - uint32_t Reserved1; - uint64_t MyLBA; - uint64_t AlternateLBA; - uint64_t FirstUsableLBA; - uint64_t LastUsableLBA; - efi_guid_t DiskGUID; - uint64_t PartitionEntryLBA; - uint32_t NumberOfPartitionEntries; - uint32_t SizeOfPartitionEntry; - uint32_t PartitionEntryArrayCRC32; - uint8_t* Reserved2; -}; - -struct __attribute__ ((packed)) _GuidPartitionEntryAttributes_t { -#if defined(__GNUC__) || defined(__sun) /* XXX narrow this down to !TinyCC */ - uint64_t RequiredToFunction:1; - uint64_t Reserved:47; - uint64_t GuidSpecific:16; -#else - uint32_t RequiredToFunction:1; - uint32_t Reserved:32; - uint32_t LOST:5; - uint32_t GuidSpecific:16; -#endif -}; - -struct __attribute__ ((packed)) _GuidPartitionEntry_t { - efi_guid_t PartitionTypeGuid; - efi_guid_t UniquePartitionGuid; - uint64_t StartingLBA; - uint64_t EndingLBA; - GuidPartitionEntryAttributes_t Attributes; - efi_char16_t PartitionName[72 / sizeof(efi_char16_t)]; -}; -#ifdef __sun -#pragma pack() -#endif - -#define GPT_PMBR_LBA 0 -#define GPT_PMBR_SECTORS 1 -#define GPT_PRIMARY_HEADER_LBA 1 -#define GPT_HEADER_SECTORS 1 -#define GPT_PRIMARY_PART_TABLE_LBA 2 - -/* - These values are only defaults. The actual on-disk structures - may define different sizes, so use those unless creating a new GPT disk! -*/ - -#define GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE 16384 - -/* Number of actual partition entries should be calculated as: */ -#define GPT_DEFAULT_PARTITION_ENTRIES \ - (GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / \ - sizeof(GuidPartitionEntry_t)) - - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _PartitionRecord_t { - /* Not used by EFI firmware. Set to 0x80 to indicate that this - is the bootable legacy partition. */ - uint8_t BootIndicator; - - /* Start of partition in CHS address, not used by EFI firmware. */ - uint8_t StartHead; - - /* Start of partition in CHS address, not used by EFI firmware. */ - uint8_t StartSector; - - /* Start of partition in CHS address, not used by EFI firmware. */ - uint8_t StartTrack; - - /* OS type. A value of 0xEF defines an EFI system partition. - Other values are reserved for legacy operating systems, and - allocated independently of the EFI specification. */ - uint8_t OSType; - - /* End of partition in CHS address, not used by EFI firmware. */ - uint8_t EndHead; - - /* End of partition in CHS address, not used by EFI firmware. */ - uint8_t EndSector; - - /* End of partition in CHS address, not used by EFI firmware. */ - uint8_t EndTrack; - - /* Starting LBA address of the partition on the disk. Used by - EFI firmware to define the start of the partition. */ - uint32_t StartingLBA; - - /* Size of partition in LBA. Used by EFI firmware to determine - the size of the partition. */ - uint32_t SizeInLBA; -}; - -/* Protected Master Boot Record & Legacy MBR share same structure */ -/* Needs to be packed because the u16s force misalignment. */ -struct __attribute__ ((packed)) _LegacyMBR_t { - uint8_t BootCode[440]; - uint32_t UniqueMBRSignature; - uint16_t Unknown; - PartitionRecord_t PartitionRecord[4]; - uint16_t Signature; -}; - -/* uses libparted's disk_specific field in PedDisk, to store our info */ -struct __attribute__ ((packed)) _GPTDiskData { - PedGeometry data_area; - int entry_count; - efi_guid_t uuid; -}; -#ifdef __sun -#pragma pack() -#endif - -/* uses libparted's disk_specific field in PedPartition, to store our info */ -typedef struct _GPTPartitionData { - efi_guid_t type; - efi_guid_t uuid; - char name[37]; - int lvm; - int raid; - int boot; - int hp_service; - int hidden; - int msftres; -} GPTPartitionData; - -static PedDiskType gpt_disk_type; - - -static inline uint32_t -pth_get_size (const PedDevice* dev) -{ - return GPT_HEADER_SECTORS * dev->sector_size; -} - - -static inline uint32_t -pth_get_size_static (const PedDevice* dev) -{ - return sizeof (GuidPartitionTableHeader_t) - sizeof (uint8_t*); -} - - -static inline uint32_t -pth_get_size_rsv2 (const PedDevice* dev) -{ - return pth_get_size(dev) - pth_get_size_static(dev); -} - - -static GuidPartitionTableHeader_t* -pth_new (const PedDevice* dev) -{ - GuidPartitionTableHeader_t* pth = ped_malloc ( - sizeof (GuidPartitionTableHeader_t) - + sizeof (uint8_t)); - - pth->Reserved2 = ped_malloc ( pth_get_size_rsv2 (dev) ); - - return pth; -} - - -static GuidPartitionTableHeader_t* -pth_new_zeroed (const PedDevice* dev) -{ - GuidPartitionTableHeader_t* pth = pth_new (dev); - - memset (pth, 0, pth_get_size_static (dev)); - memset (pth->Reserved2, 0, pth_get_size_rsv2 (dev)); - - return (pth); -} - - -static GuidPartitionTableHeader_t* -pth_new_from_raw (const PedDevice* dev, const uint8_t* pth_raw) -{ - GuidPartitionTableHeader_t* pth = pth_new (dev); - - PED_ASSERT (pth_raw != NULL, return 0); - - memcpy (pth, pth_raw, pth_get_size_static (dev)); - memcpy (pth->Reserved2, pth_raw + pth_get_size_static (dev), - pth_get_size_rsv2 (dev)); - - return pth; -} - -static void -pth_free (GuidPartitionTableHeader_t* pth) -{ - PED_ASSERT (pth != NULL, return); - PED_ASSERT (pth->Reserved2 != NULL, return); - - ped_free (pth->Reserved2); - ped_free (pth); -} - -static uint8_t* -pth_get_raw (const PedDevice* dev, const GuidPartitionTableHeader_t* pth) -{ - uint8_t* pth_raw = ped_malloc (pth_get_size (dev)); - int size_static = pth_get_size_static (dev); - - PED_ASSERT (pth != NULL, return 0); - PED_ASSERT (pth->Reserved2 != NULL, return 0); - - memcpy (pth_raw, pth, size_static); - memcpy (pth_raw + size_static, pth->Reserved2, pth_get_size_rsv2 (dev)); - - return pth_raw; -} - - -/** - * swap_uuid_and_efi_guid() - converts between uuid formats - * @uuid - uuid_t in either format (converts it to the other) - * - * There are two different representations for Globally Unique Identifiers - * (GUIDs or UUIDs). - * - * The RFC specifies a UUID as a string of 16 bytes, essentially - * a big-endian array of char. - * Intel, in their EFI Specification, references the same RFC, but - * then defines a GUID as a structure of little-endian fields. - * Coincidentally, both structures have the same format when unparsed. - * - * When read from disk, EFI GUIDs are in struct of little endian format, - * and need to be converted to be treated as uuid_t in memory. - * - * When writing to disk, uuid_ts need to be converted into EFI GUIDs. - * - * Blame Intel. - */ -static void -swap_uuid_and_efi_guid(uuid_t uuid) -{ - efi_guid_t *guid = (efi_guid_t *)uuid; - - PED_ASSERT(uuid != NULL, return); - guid->time_low = PED_SWAP32(guid->time_low); - guid->time_mid = PED_SWAP16(guid->time_mid); - guid->time_hi_and_version = PED_SWAP16(guid->time_hi_and_version); -} - -/* returns the EFI-style CRC32 value for buf - * This function uses the crc32 function by Gary S. Brown, - * but seeds the function with ~0, and xor's with ~0 at the end. - */ -static inline uint32_t -efi_crc32(const void *buf, unsigned long len) -{ - return (__efi_crc32(buf, len, ~0L) ^ ~0L); -} - -static inline uint32_t -pth_crc32(const PedDevice* dev, const GuidPartitionTableHeader_t* pth) -{ - uint8_t* pth_raw = pth_get_raw (dev, pth); - uint32_t crc32 = 0; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (pth != NULL, return 0); - - crc32 = efi_crc32 (pth_raw, PED_LE32_TO_CPU (pth->HeaderSize)); - - ped_free (pth_raw); - - return crc32; -} - -static inline int -guid_cmp (efi_guid_t left, efi_guid_t right) -{ - return memcmp(&left, &right, sizeof(efi_guid_t)); -} - -/* checks if 'mbr' is a protective MBR partition table */ -static inline int -_pmbr_is_valid (const LegacyMBR_t* mbr) -{ - int i; - - PED_ASSERT(mbr != NULL, return 0); - - if (mbr->Signature != PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE)) - return 0; - for (i = 0; i < 4; i++) { - if (mbr->PartitionRecord[i].OSType == EFI_PMBR_OSTYPE_EFI) - return 1; - } - return 0; -} - -static int -gpt_probe (const PedDevice * dev) -{ - GuidPartitionTableHeader_t* gpt = NULL; - uint8_t* pth_raw = ped_malloc (pth_get_size (dev)); - LegacyMBR_t legacy_mbr; - int gpt_sig_found = 0; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (pth_raw != NULL, return 0); - - if (ped_device_read(dev, pth_raw, 1, GPT_HEADER_SECTORS) - || ped_device_read(dev, pth_raw, dev->length - 1, GPT_HEADER_SECTORS)) { - gpt = pth_new_from_raw (dev, pth_raw); - if (gpt->Signature == PED_CPU_TO_LE64(GPT_HEADER_SIGNATURE)) - gpt_sig_found = 1; - } - - ped_free (pth_raw); - - if (gpt) - pth_free (gpt); - - - if (!gpt_sig_found) - return 0; - - if (ped_device_read(dev, &legacy_mbr, 0, GPT_HEADER_SECTORS)) { - if (!_pmbr_is_valid (&legacy_mbr)) { - int ex_status = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_YES_NO, - _("%s contains GPT signatures, indicating that it has " - "a GPT table. However, it does not have a valid " - "fake msdos partition table, as it should. Perhaps " - "it was corrupted -- possibly by a program that " - "doesn't understand GPT partition tables. Or " - "perhaps you deleted the GPT table, and are now " - "using an msdos partition table. Is this a GPT " - "partition table?"), - dev->path); - if (ex_status == PED_EXCEPTION_NO) - return 0; - } - } - - return 1; -} - -#ifndef DISCOVER_ONLY -/* writes zeros to the PMBR and the primary and alternate GPTHs and PTEs */ -static int -gpt_clobber(PedDevice * dev) -{ - LegacyMBR_t pmbr; - uint8_t* zeroed_pth_raw = ped_malloc (pth_get_size (dev)); - uint8_t* pth_raw = ped_malloc (pth_get_size (dev)); - GuidPartitionTableHeader_t* gpt; - - PED_ASSERT (dev != NULL, return 0); - - memset(&pmbr, 0, sizeof(pmbr)); - memset(zeroed_pth_raw, 0, pth_get_size (dev)); - - /* - * TO DISCUSS: check whether checksum is correct? - * If not, we might get a wrong AlternateLBA field and destroy - * one sector of random data. - */ - if (!ped_device_read(dev, pth_raw, - GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS)) - goto error_free; - - gpt = pth_new_from_raw (dev, pth_raw); - - if (!ped_device_write(dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS)) - goto error_free_with_gpt; - if (!ped_device_write(dev, &zeroed_pth_raw, - GPT_PRIMARY_HEADER_LBA, GPT_HEADER_SECTORS)) - goto error_free_with_gpt; - if (!ped_device_write(dev, &zeroed_pth_raw, dev->length - GPT_HEADER_SECTORS, - GPT_HEADER_SECTORS)) - goto error_free_with_gpt; - - if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) < dev->length - 1) { - if (!ped_device_write(dev, gpt, - PED_LE64_TO_CPU (gpt->AlternateLBA), - GPT_HEADER_SECTORS)) - return 0; - } - - pth_free (gpt); - - return 1; - -error_free_with_gpt: - pth_free (gpt); -error_free: - ped_free (pth_raw); - ped_free (zeroed_pth_raw); - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk * -gpt_alloc (const PedDevice * dev) -{ - PedDisk* disk; - GPTDiskData *gpt_disk_data; - PedSector data_start, data_end; - - disk = _ped_disk_alloc ((PedDevice*)dev, &gpt_disk_type); - if (!disk) - goto error; - disk->disk_specific = gpt_disk_data = ped_malloc (sizeof (GPTDiskData)); - if (!disk->disk_specific) - goto error_free_disk; - - data_start = 2 + GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size; - data_end = dev->length - 2 - - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / dev->sector_size; - ped_geometry_init (&gpt_disk_data->data_area, dev, data_start, - data_end - data_start + 1); - gpt_disk_data->entry_count = GPT_DEFAULT_PARTITION_ENTRIES; - uuid_generate ((unsigned char*) &gpt_disk_data->uuid); - swap_uuid_and_efi_guid((unsigned char*)(&gpt_disk_data->uuid)); - return disk; - -error_free_disk: - ped_free (disk); -error: - return NULL; -} - -static PedDisk* -gpt_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - GPTDiskData* new_disk_data; - GPTDiskData* old_disk_data; - - new_disk = ped_disk_new_fresh (disk->dev, &gpt_disk_type); - if (!new_disk) - return NULL; - - old_disk_data = disk->disk_specific; - new_disk_data = new_disk->disk_specific; - - ped_geometry_init (&new_disk_data->data_area, disk->dev, - old_disk_data->data_area.start, - old_disk_data->data_area.length); - new_disk_data->entry_count = old_disk_data->entry_count; - new_disk_data->uuid = old_disk_data->uuid; - return new_disk; -} - -static void -gpt_free(PedDisk * disk) -{ - ped_disk_delete_all (disk); - ped_free (disk->disk_specific); - _ped_disk_free (disk); -} - -static int -_header_is_valid (const PedDevice* dev, GuidPartitionTableHeader_t* gpt) -{ - uint32_t crc, origcrc; - - if (PED_LE64_TO_CPU (gpt->Signature) != GPT_HEADER_SIGNATURE) - return 0; - /* - * "While the GUID Partition Table Header's size may increase - * in the future it cannot span more than one block on the - * device." EFI Specification, version 1.10, 11.2.2.1 - */ - if (PED_LE32_TO_CPU (gpt->HeaderSize) < pth_get_size_static (dev) - || PED_LE32_TO_CPU (gpt->HeaderSize) > dev->sector_size) - return 0; - - origcrc = gpt->HeaderCRC32; - gpt->HeaderCRC32 = 0; - crc = pth_crc32 (dev, gpt); - gpt->HeaderCRC32 = origcrc; - - return crc == PED_LE32_TO_CPU (origcrc); -} - -static int -_read_header (const PedDevice* dev, GuidPartitionTableHeader_t** gpt, - PedSector where) -{ - uint8_t* pth_raw = ped_malloc (pth_get_size (dev)); - - PED_ASSERT (dev != NULL, return 0); - - if (!ped_device_read (dev, pth_raw, where, GPT_HEADER_SECTORS)) { - ped_free (pth_raw); - return 0; - } - - *gpt = pth_new_from_raw (dev, pth_raw); - - ped_free (pth_raw); - - if (_header_is_valid (dev, *gpt)) - return 1; - - pth_free (*gpt); - return 0; -} - -static int -_parse_header (PedDisk* disk, GuidPartitionTableHeader_t* gpt, - int *update_needed) -{ - GPTDiskData* gpt_disk_data = disk->disk_specific; - PedSector first_usable; - PedSector last_usable; - PedSector last_usable_if_grown, last_usable_min_default; - static int asked_already; - - PED_ASSERT (_header_is_valid (disk->dev, gpt), return 0); - -#ifndef DISCOVER_ONLY - if (PED_LE32_TO_CPU (gpt->Revision) > GPT_HEADER_REVISION_V1_02) { - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The format of the GPT partition table is version " - "%x, which is newer than what Parted can " - "recognise. Please tell us! bug-parted@gnu.org"), - PED_LE32_TO_CPU (gpt->Revision)) - != PED_EXCEPTION_IGNORE) - return 0; - } -#endif - - first_usable = PED_LE64_TO_CPU (gpt->FirstUsableLBA); - last_usable = PED_LE64_TO_CPU (gpt->LastUsableLBA); - - -/* - Need to check whether the volume has grown, the LastUsableLBA is - normally set to disk->dev->length - 2 - ptes_size (at least for parted - created volumes), where ptes_size is the number of entries * - size of each entry / sector size or 16k / sector size, whatever the greater. - If the volume has grown, offer the user the chance to use the new - space or continue with the current usable area. Only ask once per - parted invocation. -*/ - - last_usable_if_grown - = PED_CPU_TO_LE64 (disk->dev->length - 2 - - ((PedSector)(PED_LE32_TO_CPU(gpt->NumberOfPartitionEntries)) * - (PedSector)(PED_LE32_TO_CPU(gpt->SizeOfPartitionEntry)) / - disk->dev->sector_size)); - - last_usable_min_default = disk->dev->length - 2 - - GPT_DEFAULT_PARTITION_ENTRY_ARRAY_SIZE / disk->dev->sector_size; - - if ( last_usable_if_grown > last_usable_min_default ) { - - last_usable_if_grown = last_usable_min_default; - } - - - PED_ASSERT (last_usable > first_usable, return 0); - PED_ASSERT (last_usable <= disk->dev->length, return 0); - - PED_ASSERT (last_usable_if_grown > first_usable, return 0); - PED_ASSERT (last_usable_if_grown <= disk->dev->length, return 0); - - if ( !asked_already && last_usable < last_usable_if_grown ) { - - PedExceptionOption q; - - q = ped_exception_throw (PED_EXCEPTION_WARNING, - PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE, - _("Not all of the space available to %s appears " - "to be used, you can fix the GPT to use all of the " - "space (an extra %llu blocks) or continue with the " - "current setting? "), disk->dev->path, - (uint64_t)(last_usable_if_grown - last_usable)); - - - if (q == PED_EXCEPTION_FIX) { - - last_usable = last_usable_if_grown; - *update_needed = 1; - - } - else if (q != PED_EXCEPTION_UNHANDLED ) { - - asked_already = 1; - } - } - - ped_geometry_init (&gpt_disk_data->data_area, disk->dev, - first_usable, last_usable - first_usable + 1); - - - gpt_disk_data->entry_count - = PED_LE32_TO_CPU (gpt->NumberOfPartitionEntries); - PED_ASSERT (gpt_disk_data->entry_count > 0, return 0); - PED_ASSERT (gpt_disk_data->entry_count <= 8192, return 0); - - gpt_disk_data->uuid = gpt->DiskGUID; - - return 1; -} - -static PedPartition* -_parse_part_entry (PedDisk* disk, GuidPartitionEntry_t* pte) -{ - PedPartition* part; - GPTPartitionData* gpt_part_data; - unsigned int i; - - part = ped_partition_new (disk, 0, NULL, - PED_LE64_TO_CPU(pte->StartingLBA), - PED_LE64_TO_CPU(pte->EndingLBA)); - if (!part) - return NULL; - - gpt_part_data = part->disk_specific; - gpt_part_data->type = pte->PartitionTypeGuid; - gpt_part_data->uuid = pte->UniquePartitionGuid; - for (i = 0; i < 72 / sizeof (efi_char16_t); i++) - gpt_part_data->name[i] = (efi_char16_t) PED_LE16_TO_CPU( - (uint16_t) pte->PartitionName[i]); - gpt_part_data->name[i] = 0; - - gpt_part_data->lvm = gpt_part_data->raid - = gpt_part_data->boot = gpt_part_data->hp_service - = gpt_part_data->hidden = gpt_part_data->msftres = 0; - - if (pte->Attributes.RequiredToFunction & 0x1) - gpt_part_data->hidden = 1; - - if (!guid_cmp (gpt_part_data->type, PARTITION_SYSTEM_GUID)) - gpt_part_data->boot = 1; - else if (!guid_cmp (gpt_part_data->type, PARTITION_RAID_GUID)) - gpt_part_data->raid = 1; - else if (!guid_cmp (gpt_part_data->type, PARTITION_LVM_GUID)) - gpt_part_data->lvm = 1; - else if (!guid_cmp (gpt_part_data->type, PARTITION_HPSERVICE_GUID)) - gpt_part_data->hp_service = 1; - else if (!guid_cmp (gpt_part_data->type, PARTITION_MSFT_RESERVED_GUID)) - gpt_part_data->msftres = 1; - - return part; -} - -/************************************************************ - * Intel is changing the EFI Spec. (after v1.02) to say that a - * disk is considered to have a GPT label only if the GPT - * structures are correct, and the MBR is actually a Protective - * MBR (has one 0xEE type partition). - * Problem occurs when a GPT-partitioned disk is then - * edited with a legacy (non-GPT-aware) application, such as - * fdisk (which doesn't generally erase the PGPT or AGPT). - * How should such a disk get handled? As a GPT disk (throwing - * away the fdisk changes), or as an MSDOS disk (throwing away - * the GPT information). Previously, I've taken the GPT-is-right, - * MBR is wrong, approach, to stay consistent with the EFI Spec. - * Intel disagrees, saying the disk should then be treated - * as having a msdos label, not a GPT label. If this is true, - * then what's the point of having an AGPT, since if the PGPT - * is screwed up, likely the PMBR is too, and the PMBR becomes - * a single point of failure. - * So, in the Linux kernel, I'm going to test for PMBR, and - * warn if it's not there, and treat the disk as MSDOS, with a note - * for users to use Parted to "fix up" their disk if they - * really want it to be considered GPT. - ************************************************************/ -static int -gpt_read (PedDisk * disk) -{ - GPTDiskData *gpt_disk_data = disk->disk_specific; - GuidPartitionTableHeader_t* gpt; - GuidPartitionEntry_t* ptes; - int ptes_size; - int i; -#ifndef DISCOVER_ONLY - int write_back = 0; -#endif - - ped_disk_delete_all (disk); - - /* - * motivation: let the user decide about the pmbr... during - * ped_disk_probe(), they probably didn't get a choice... - */ - if (!gpt_probe (disk->dev)) - goto error; - - if (_read_header (disk->dev, &gpt, 1)) { - PED_ASSERT ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) - <= disk->dev->length - 1, goto error_free_gpt); - if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) - < disk->dev->length - 1) { - char* zeros = ped_malloc (pth_get_size (disk->dev)); - -#ifndef DISCOVER_ONLY - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, - _("The backup GPT table is not at the end of the disk, as it " - "should be. This might mean that another operating system " - "believes the disk is smaller. Fix, by moving the backup " - "to the end (and removing the old backup)?")) - == PED_EXCEPTION_CANCEL) - goto error_free_gpt; - - write_back = 1; - memset (zeros, 0, disk->dev->sector_size); - ped_device_write (disk->dev, zeros, - PED_LE64_TO_CPU (gpt->AlternateLBA), - 1); -#endif /* !DISCOVER_ONLY */ - } - } else { /* primary GPT *not* ok */ - int alternate_ok = 0; - -#ifndef DISCOVER_ONLY - write_back = 1; -#endif - - if ((PedSector) PED_LE64_TO_CPU (gpt->AlternateLBA) - < disk->dev->length - 1) { - alternate_ok = _read_header (disk->dev, &gpt, - PED_LE64_TO_CPU(gpt->AlternateLBA)); - } - if (!alternate_ok) { - alternate_ok = _read_header (disk->dev, &gpt, - disk->dev->length - 1); - } - - if (alternate_ok) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_OK_CANCEL, - _("The primary GPT table is corrupt, but the " - "backup appears OK, so that will be used.")) - == PED_EXCEPTION_CANCEL) - goto error_free_gpt; - } else { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Both the primary and backup GPT tables " - "are corrupt. Try making a fresh table, " - "and using Parted's rescue feature to " - "recover partitions.")); - goto error; - } - } - - if (!_parse_header (disk, gpt, &write_back)) - goto error_free_gpt; - - /* - * ptes_size is in bytes and must be a multiple of sector_size. - */ - ptes_size = ped_round_up_to( - sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count, - disk->dev->sector_size); - ptes = (GuidPartitionEntry_t*) ped_malloc (ptes_size); - - if (!ped_device_read (disk->dev, ptes, - PED_LE64_TO_CPU(gpt->PartitionEntryLBA), - ptes_size / disk->dev->sector_size)) - goto error_free_ptes; - - for (i = 0; i < gpt_disk_data->entry_count; i++) { - PedPartition* part; - PedConstraint* constraint_exact; - - if (!guid_cmp (ptes[i].PartitionTypeGuid, UNUSED_ENTRY_GUID)) - continue; - - part = _parse_part_entry (disk, &ptes[i]); - if (!part) - goto error_delete_all; - - part->fs_type = ped_file_system_probe (&part->geom); - part->num = i + 1; - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition(disk, part, constraint_exact)) { - ped_partition_destroy (part); - goto error_delete_all; - } - ped_constraint_destroy (constraint_exact); - } - ped_free (ptes); - -#ifndef DISCOVER_ONLY - if (write_back) - ped_disk_commit_to_dev (disk); -#endif - - return 1; - -error_delete_all: - ped_disk_delete_all (disk); -error_free_ptes: - ped_free (ptes); -error_free_gpt: - pth_free (gpt); -error: - return 0; -} - -#ifndef DISCOVER_ONLY -/* Writes the protective MBR (to keep DOS happy) */ -static int -_write_pmbr (PedDevice * dev) -{ - LegacyMBR_t pmbr; - - memset(&pmbr, 0, sizeof(pmbr)); - pmbr.Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE); - pmbr.PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI; - pmbr.PartitionRecord[0].StartSector = 1; - pmbr.PartitionRecord[0].EndHead = 0xFE; - pmbr.PartitionRecord[0].EndSector = 0xFF; - pmbr.PartitionRecord[0].EndTrack = 0xFF; - pmbr.PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32(1); - if ((dev->length - 1ULL) > 0xFFFFFFFFULL) - pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(0xFFFFFFFF); - else - pmbr.PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32(dev->length - 1UL); - - return ped_device_write (dev, &pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS); -} - -static void -_generate_header (const PedDisk* disk, int alternate, uint32_t ptes_crc, - GuidPartitionTableHeader_t** gpt_p) -{ - GPTDiskData* gpt_disk_data = disk->disk_specific; - GuidPartitionTableHeader_t* gpt; - - *gpt_p = pth_new_zeroed (disk->dev); - - gpt = *gpt_p; - - gpt->Signature = PED_CPU_TO_LE64 (GPT_HEADER_SIGNATURE); - gpt->Revision = PED_CPU_TO_LE32 (GPT_HEADER_REVISION_V1_00); - - /* per 1.00 spec */ - gpt->HeaderSize = PED_CPU_TO_LE32 (pth_get_size_static (disk->dev)); - gpt->HeaderCRC32 = 0; - gpt->Reserved1 = 0; - - if (alternate) { - /* - * ptes_size is in sectors - */ - PedSector ptes_size = ped_div_round_up( - gpt_disk_data->entry_count * - sizeof (GuidPartitionEntry_t), - disk->dev->sector_size); - - gpt->MyLBA = PED_CPU_TO_LE64 (disk->dev->length - 1); - gpt->AlternateLBA = PED_CPU_TO_LE64 (1); - gpt->PartitionEntryLBA - = PED_CPU_TO_LE64 (disk->dev->length - 1 - ptes_size); - } else { - gpt->MyLBA = PED_CPU_TO_LE64 (1); - gpt->AlternateLBA = PED_CPU_TO_LE64 (disk->dev->length - 1); - gpt->PartitionEntryLBA = PED_CPU_TO_LE64 (2); - } - - gpt->FirstUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.start); - gpt->LastUsableLBA = PED_CPU_TO_LE64 (gpt_disk_data->data_area.end); - gpt->DiskGUID = gpt_disk_data->uuid; - gpt->NumberOfPartitionEntries - = PED_CPU_TO_LE32 (gpt_disk_data->entry_count); - gpt->SizeOfPartitionEntry - = PED_CPU_TO_LE32 (sizeof (GuidPartitionEntry_t)); - gpt->PartitionEntryArrayCRC32 = PED_CPU_TO_LE32 (ptes_crc); - gpt->HeaderCRC32 = PED_CPU_TO_LE32 (pth_crc32 (disk->dev, gpt)); -} - -static void -_partition_generate_part_entry (PedPartition* part, GuidPartitionEntry_t* pte) -{ - GPTPartitionData* gpt_part_data = part->disk_specific; - unsigned int i; - - PED_ASSERT (gpt_part_data != NULL, return); - - pte->PartitionTypeGuid = gpt_part_data->type; - pte->UniquePartitionGuid = gpt_part_data->uuid; - pte->StartingLBA = PED_CPU_TO_LE64(part->geom.start); - pte->EndingLBA = PED_CPU_TO_LE64(part->geom.end); - memset (&pte->Attributes, 0, sizeof (GuidPartitionEntryAttributes_t)); - - if (gpt_part_data->hidden) - pte->Attributes.RequiredToFunction = 1; - - for (i = 0; i < 72 / sizeof(efi_char16_t); i++) - pte->PartitionName[i] - = (efi_char16_t) PED_CPU_TO_LE16( - (uint16_t) gpt_part_data->name[i]); -} - -static int -gpt_write(const PedDisk * disk) -{ - GPTDiskData* gpt_disk_data; - GuidPartitionEntry_t* ptes; - uint32_t ptes_crc; - uint8_t* pth_raw = ped_malloc (pth_get_size (disk->dev)); - GuidPartitionTableHeader_t* gpt; - PedPartition* part; - int ptes_size; - - PED_ASSERT (disk != NULL, goto error); - PED_ASSERT (disk->dev != NULL, goto error); - PED_ASSERT (disk->disk_specific != NULL, goto error); - - gpt_disk_data = disk->disk_specific; - - /* - * ptes_size is in bytes and must be a multiple of sector_size. - */ - ptes_size = ped_round_up_to( - sizeof (GuidPartitionEntry_t) * gpt_disk_data->entry_count, - disk->dev->sector_size); - ptes = (GuidPartitionEntry_t*) ped_malloc (ptes_size); - if (!ptes) - goto error; - memset (ptes, 0, ptes_size); - for (part = ped_disk_next_partition (disk, NULL); part; - part = ped_disk_next_partition (disk, part)) { - if (part->type != 0) - continue; - _partition_generate_part_entry (part, &ptes[part->num - 1]); - } - - ptes_crc = efi_crc32 (ptes, ptes_size); - - /* Write protective MBR */ - if (!_write_pmbr (disk->dev)) - goto error_free_ptes; - - /* Write PTH and PTEs */ - _generate_header (disk, 0, ptes_crc, &gpt); - pth_raw = pth_get_raw (disk->dev, gpt); - if (!ped_device_write (disk->dev, pth_raw, 1, 1)) - goto error_free_ptes; - if (!ped_device_write (disk->dev, ptes, 2, ptes_size / disk->dev->sector_size)) - goto error_free_ptes; - - /* Write Alternate PTH & PTEs */ - _generate_header (disk, 1, ptes_crc, &gpt); - pth_raw = pth_get_raw (disk->dev, gpt); - if (!ped_device_write (disk->dev, pth_raw, disk->dev->length - 1, 1)) - goto error_free_ptes; - if (!ped_device_write (disk->dev, ptes, - disk->dev->length - 1 - ptes_size / disk->dev->sector_size, - ptes_size / disk->dev->sector_size)) - goto error_free_ptes; - - ped_free (ptes); - return ped_device_sync (disk->dev); - -error_free_ptes: - ped_free (ptes); -error: - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static int -add_metadata_part(PedDisk * disk, PedSector start, PedSector length) -{ - PedPartition* part; - PedConstraint* constraint_exact; - PED_ASSERT(disk != NULL, return 0); - - part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, - start, start + length - 1); - if (!part) - goto error; - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error_destroy_constraint; - ped_constraint_destroy (constraint_exact); - return 1; - -error_destroy_constraint: - ped_constraint_destroy (constraint_exact); - ped_partition_destroy (part); -error: - return 0; -} - -static PedPartition* -gpt_partition_new (const PedDisk* disk, - PedPartitionType part_type, const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - GPTPartitionData* gpt_part_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (part_type != 0) - return part; - - gpt_part_data = part->disk_specific = - ped_malloc (sizeof (GPTPartitionData)); - if (!gpt_part_data) - goto error_free_part; - - gpt_part_data->type = PARTITION_BASIC_DATA_GUID; - gpt_part_data->lvm = 0; - gpt_part_data->raid = 0; - gpt_part_data->boot = 0; - gpt_part_data->hp_service = 0; - gpt_part_data->hidden = 0; - gpt_part_data->msftres = 0; - uuid_generate ((unsigned char*) &gpt_part_data->uuid); - swap_uuid_and_efi_guid((unsigned char*)(&gpt_part_data->uuid)); - strcpy (gpt_part_data->name, ""); - return part; - -error_free_part: - _ped_partition_free (part); -error: - return NULL; -} - -static PedPartition* -gpt_partition_duplicate (const PedPartition* part) -{ - PedPartition* result; - GPTPartitionData* part_data = part->disk_specific; - GPTPartitionData* result_data; - - result = _ped_partition_alloc (part->disk, part->type, part->fs_type, - part->geom.start, part->geom.end); - if (!result) - goto error; - result->num = part->num; - - if (result->type != 0) - return result; - - result_data = result->disk_specific = - ped_malloc (sizeof (GPTPartitionData)); - if (!result_data) - goto error_free_part; - - result_data->type = part_data->type; - result_data->uuid = part_data->uuid; - strcpy (result_data->name, part_data->name); - return result; - -error_free_part: - _ped_partition_free (result); -error: - return NULL; -} - -static void -gpt_partition_destroy (PedPartition *part) -{ - if (part->type == 0) { - PED_ASSERT (part->disk_specific != NULL, return); - ped_free (part->disk_specific); - } - - _ped_partition_free (part); -} - -static int -gpt_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - GPTPartitionData* gpt_part_data = part->disk_specific; - - PED_ASSERT (gpt_part_data != NULL, return 0); - - part->fs_type = fs_type; - - if (gpt_part_data->lvm) { - gpt_part_data->type = PARTITION_LVM_GUID; - return 1; - } - if (gpt_part_data->raid) { - gpt_part_data->type = PARTITION_RAID_GUID; - return 1; - } - if (gpt_part_data->boot) { - gpt_part_data->type = PARTITION_SYSTEM_GUID; - return 1; - } - if (gpt_part_data->hp_service) { - gpt_part_data->type = PARTITION_HPSERVICE_GUID; - return 1; - } - if (gpt_part_data->msftres) { - gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID; - return 1; - } - - if (fs_type) { - if (strncmp (fs_type->name, "fat", 3) == 0 - || strcmp (fs_type->name, "ntfs") == 0) { - gpt_part_data->type = PARTITION_MSFT_RESERVED_GUID; - return 1; - } - if (strncmp (fs_type->name, "hfs", 3) == 0) { - gpt_part_data->type = PARTITION_APPLE_HFS_GUID; - return 1; - } - if (strstr (fs_type->name, "swap")) { - gpt_part_data->type = PARTITION_SWAP_GUID; - return 1; - } - } - - gpt_part_data->type = PARTITION_BASIC_DATA_GUID; - return 1; -} - -/* Allocate metadata partitions for the GPTH and PTES */ -static int -gpt_alloc_metadata (PedDisk * disk) -{ - PedSector gptlength, pteslength = 0; - GPTDiskData *gpt_disk_data; - - PED_ASSERT(disk != NULL, return 0); - PED_ASSERT(disk->dev != NULL, return 0); - PED_ASSERT(disk->disk_specific != NULL, return 0); - gpt_disk_data = disk->disk_specific; - - gptlength = ped_div_round_up (sizeof (GuidPartitionTableHeader_t), - disk->dev->sector_size); - pteslength = ped_div_round_up (gpt_disk_data->entry_count - * sizeof (GuidPartitionEntry_t), disk->dev->sector_size); - - /* metadata at the start of the disk includes the MBR */ - if (!add_metadata_part(disk, GPT_PMBR_LBA, - GPT_PMBR_SECTORS + gptlength + pteslength)) - return 0; - - /* metadata at the end of the disk */ - if (!add_metadata_part(disk, disk->dev->length - gptlength - pteslength, - gptlength + pteslength)) - return 0; - - return 1; -} - -/* Does nothing, as the read/new/destroy functions maintain part->num */ -static int -gpt_partition_enumerate (PedPartition* part) -{ - GPTDiskData* gpt_disk_data = part->disk->disk_specific; - int i; - - /* never change the partition numbers */ - if (part->num != -1) - return 1; - - for (i = 1; i <= gpt_disk_data->entry_count; i++) { - if (!ped_disk_get_partition (part->disk, i)) { - part->num = i; - return 1; - } - } - - PED_ASSERT (0, return 0); - - return 0; /* used if debug is disabled */ -} - -static int -gpt_partition_set_flag(PedPartition *part, - PedPartitionFlag flag, - int state) -{ - GPTPartitionData *gpt_part_data; - PED_ASSERT(part != NULL, return 0); - PED_ASSERT(part->disk_specific != NULL, return 0); - gpt_part_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_BOOT: - gpt_part_data->boot = state; - if (state) - gpt_part_data->raid - = gpt_part_data->lvm - = gpt_part_data->hp_service - = gpt_part_data->msftres = 0; - return gpt_partition_set_system (part, part->fs_type); - case PED_PARTITION_RAID: - gpt_part_data->raid = state; - if (state) - gpt_part_data->boot - = gpt_part_data->lvm - = gpt_part_data->hp_service - = gpt_part_data->msftres = 0; - return gpt_partition_set_system (part, part->fs_type); - case PED_PARTITION_LVM: - gpt_part_data->lvm = state; - if (state) - gpt_part_data->boot - = gpt_part_data->raid - = gpt_part_data->hp_service - = gpt_part_data->msftres = 0; - return gpt_partition_set_system (part, part->fs_type); - case PED_PARTITION_HPSERVICE: - gpt_part_data->hp_service = state; - if (state) - gpt_part_data->boot - = gpt_part_data->raid - = gpt_part_data->lvm - = gpt_part_data->msftres = 0; - return gpt_partition_set_system (part, part->fs_type); - case PED_PARTITION_MSFT_RESERVED: - gpt_part_data->msftres = state; - if (state) - gpt_part_data->boot - = gpt_part_data->raid - = gpt_part_data->lvm - = gpt_part_data->hp_service = 0; - return gpt_partition_set_system (part, part->fs_type); - case PED_PARTITION_HIDDEN: - gpt_part_data->hidden = state; - return 1; - case PED_PARTITION_SWAP: - case PED_PARTITION_ROOT: - case PED_PARTITION_LBA: - default: - return 0; - } - return 1; -} - -static int -gpt_partition_get_flag(const PedPartition *part, PedPartitionFlag flag) -{ - GPTPartitionData *gpt_part_data; - PED_ASSERT(part->disk_specific != NULL, return 0); - gpt_part_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_RAID: - return gpt_part_data->raid; - case PED_PARTITION_LVM: - return gpt_part_data->lvm; - case PED_PARTITION_BOOT: - return gpt_part_data->boot; - case PED_PARTITION_HPSERVICE: - return gpt_part_data->hp_service; - case PED_PARTITION_MSFT_RESERVED: - return gpt_part_data->msftres; - case PED_PARTITION_HIDDEN: - return gpt_part_data->hidden; - case PED_PARTITION_SWAP: - case PED_PARTITION_LBA: - case PED_PARTITION_ROOT: - default: - return 0; - } - return 0; -} - -static int -gpt_partition_is_flag_available(const PedPartition * part, - PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_RAID: - case PED_PARTITION_LVM: - case PED_PARTITION_BOOT: - case PED_PARTITION_HPSERVICE: - case PED_PARTITION_MSFT_RESERVED: - case PED_PARTITION_HIDDEN: - return 1; - case PED_PARTITION_SWAP: - case PED_PARTITION_ROOT: - case PED_PARTITION_LBA: - default: - return 0; - } - return 0; -} - -static void -gpt_partition_set_name (PedPartition *part, const char *name) -{ - GPTPartitionData *gpt_part_data = part->disk_specific; - - strncpy (gpt_part_data->name, name, 36); - gpt_part_data->name [36] = 0; -} - -static const char * -gpt_partition_get_name (const PedPartition * part) -{ - GPTPartitionData* gpt_part_data = part->disk_specific; - return gpt_part_data->name; -} - -static int -gpt_get_max_primary_partition_count (const PedDisk *disk) -{ - const GPTDiskData* gpt_disk_data = disk->disk_specific; - return gpt_disk_data->entry_count; -} - -static PedConstraint* -_non_metadata_constraint (const PedDisk* disk) -{ - GPTDiskData* gpt_disk_data = disk->disk_specific; - - return ped_constraint_new_from_max (&gpt_disk_data->data_area); -} - -static int -gpt_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - if (_ped_partition_attempt_align (part, constraint, - _non_metadata_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static PedDiskOps gpt_disk_ops = { - .probe = gpt_probe, -#ifndef DISCOVER_ONLY - .clobber = gpt_clobber, -#else - .clobber = NULL, -#endif - .alloc = gpt_alloc, - .duplicate = gpt_duplicate, - .free = gpt_free, - .read = gpt_read, -#ifndef DISCOVER_ONLY - .write = gpt_write, -#else - .write = NULL, -#endif - - .partition_new = gpt_partition_new, - .partition_duplicate = gpt_partition_duplicate, - .partition_destroy = gpt_partition_destroy, - .partition_set_system = gpt_partition_set_system, - .partition_set_flag = gpt_partition_set_flag, - .partition_get_flag = gpt_partition_get_flag, - .partition_is_flag_available = gpt_partition_is_flag_available, - .partition_set_name = gpt_partition_set_name, - .partition_get_name = gpt_partition_get_name, - .partition_align = gpt_partition_align, - .partition_enumerate = gpt_partition_enumerate, - .alloc_metadata = gpt_alloc_metadata, - .get_max_primary_partition_count = gpt_get_max_primary_partition_count -}; - -static PedDiskType gpt_disk_type = { - .next = NULL, - .name = "gpt", - .ops = &gpt_disk_ops, - .features = PED_DISK_TYPE_PARTITION_NAME -}; - -void -ped_disk_gpt_init() -{ - PED_ASSERT (sizeof (GuidPartitionEntryAttributes_t) == 8, return); - PED_ASSERT (sizeof (GuidPartitionEntry_t) == 128, return); - - ped_disk_type_register (&gpt_disk_type); -} - -void -ped_disk_gpt_done() -{ - ped_disk_type_unregister (&gpt_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/loop.c b/usr/src/lib/libparted/common/libparted/labels/loop.c deleted file mode 100644 index 36a00d5d19..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/loop.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -#define LOOP_SIGNATURE "GNU Parted Loopback 0" - -static PedDiskType loop_disk_type; - -static PedDisk* loop_alloc (const PedDevice* dev); -static void loop_free (PedDisk* disk); - -static int -loop_probe (const PedDevice* dev) -{ - PedDisk* disk; - char buf [512]; - int result; - - if (dev->sector_size != 512) - return 0; - - disk = loop_alloc (dev); - if (!disk) - goto error; - - if (!ped_device_read (dev, buf, 0, 1)) - goto error_destroy_disk; - if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) == 0) { - result = 1; - } else { - PedGeometry* geom; - - geom = ped_geometry_new (dev, 0, disk->dev->length); - if (!geom) - goto error_destroy_disk; - result = ped_file_system_probe (geom) != NULL; - ped_geometry_destroy (geom); - } - loop_free (disk); - return result; - -error_destroy_disk: - loop_free (disk); -error: - return 0; -} - -#ifndef DISCOVER_ONLY -static int -loop_clobber (PedDevice* dev) -{ - char buf [512]; - PedSector i = 0; - - PED_ASSERT (dev != NULL, return 0); - - memset (buf, 0, 512); - - while (loop_probe (dev)) { - if (!ped_device_write (dev, buf, i++, 1)) - return 0; - } - return 1; -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk* -loop_alloc (const PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - - if (dev->length < 256) - return NULL; - return _ped_disk_alloc ((PedDevice*)dev, &loop_disk_type); -} - -static PedDisk* -loop_duplicate (const PedDisk* disk) -{ - return ped_disk_new_fresh (disk->dev, &loop_disk_type); -} - -static void -loop_free (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return); - - _ped_disk_free (disk); -} - -static int -loop_read (PedDisk* disk) -{ - PedDevice* dev = NULL; - char buf [512]; - PedGeometry* geom; - PedFileSystemType* fs_type; - PedPartition* part; - PedConstraint* constraint_any; - - PED_ASSERT (disk != NULL, return 0); - dev = disk->dev; - constraint_any = ped_constraint_any (dev); - - ped_disk_delete_all (disk); - - if (!ped_device_read (dev, buf, 0, 1)) - goto error; - if (!strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE))) - return 1; - - geom = ped_geometry_new (dev, 0, dev->length); - if (!geom) - goto error; - - fs_type = ped_file_system_probe (geom); - if (!fs_type) - goto error_free_geom; - - part = ped_partition_new (disk, 0, fs_type, geom->start, geom->end); - ped_geometry_destroy (geom); - if (!part) - goto error; - part->fs_type = fs_type; - - if (!ped_disk_add_partition (disk, part, constraint_any)) - goto error; - ped_constraint_destroy (constraint_any); - return 1; - -error_free_geom: - ped_geometry_destroy (geom); -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -#ifndef DISCOVER_ONLY -static int -loop_write (const PedDisk* disk) -{ - char buf [512]; - - if (ped_disk_get_partition (disk, 1)) { - if (!ped_device_read (disk->dev, buf, 0, 1)) - return 0; - if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0) - return 1; - memset (buf, 0, strlen (LOOP_SIGNATURE)); - return ped_device_write (disk->dev, buf, 0, 1); - } - - memset (buf, 0, 512); - strcpy (buf, LOOP_SIGNATURE); - - return ped_device_write (disk->dev, buf, 0, 1); -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -loop_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - return NULL; - part->disk_specific = NULL; - return part; -} - -static PedPartition* -loop_partition_duplicate (const PedPartition* part) -{ - PedPartition* result; - - result = ped_partition_new (part->disk, part->type, part->fs_type, - part->geom.start, part->geom.end); - result->num = part->num; - return result; -} - -static void -loop_partition_destroy (PedPartition* part) -{ - ped_free (part); -} - -static int -loop_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - part->fs_type = fs_type; - return 1; -} - -static int -loop_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - return 0; -} - -static int -loop_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - return 0; -} - -static int -loop_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PedGeometry* new_geom; - - new_geom = ped_constraint_solve_nearest (constraint, &part->geom); - if (!new_geom) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the " - "partition.")); - return 0; - } - ped_geometry_set (&part->geom, new_geom->start, new_geom->length); - ped_geometry_destroy (new_geom); - return 1; -} - -static int -loop_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - return 0; -} - -static int -loop_partition_enumerate (PedPartition* part) -{ - part->num = 1; - return 1; -} - -static int -loop_alloc_metadata (PedDisk* disk) -{ - return 1; -} - -static int -loop_get_max_primary_partition_count (const PedDisk* disk) -{ - return 1; -} - -static PedDiskOps loop_disk_ops = { - .probe = loop_probe, -#ifndef DISCOVER_ONLY - .clobber = loop_clobber, -#else - .clobber = NULL, -#endif - .alloc = loop_alloc, - .duplicate = loop_duplicate, - .free = loop_free, - .read = loop_read, -#ifndef DISCOVER_ONLY - .write = loop_write, -#else - .write = NULL, -#endif - - .partition_new = loop_partition_new, - .partition_duplicate = loop_partition_duplicate, - .partition_destroy = loop_partition_destroy, - .partition_set_system = loop_partition_set_system, - .partition_set_flag = loop_partition_set_flag, - .partition_get_flag = loop_partition_get_flag, - .partition_is_flag_available = loop_partition_is_flag_available, - .partition_set_name = NULL, - .partition_get_name = NULL, - .partition_align = loop_partition_align, - .partition_enumerate = loop_partition_enumerate, - - .alloc_metadata = loop_alloc_metadata, - .get_max_primary_partition_count = - loop_get_max_primary_partition_count -}; - -static PedDiskType loop_disk_type = { - .next = NULL, - .name = "loop", - .ops = &loop_disk_ops, - .features = 0 -}; - -void -ped_disk_loop_init () -{ - ped_disk_type_register (&loop_disk_type); -} - -void -ped_disk_loop_done () -{ - ped_disk_type_unregister (&loop_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/mac.c b/usr/src/lib/libparted/common/libparted/labels/mac.c deleted file mode 100644 index 25ca6ab728..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/mac.c +++ /dev/null @@ -1,1629 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2002, 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* struct's hacked from Linux source: fs/partitions/mac.h - * I believe it was originally written by Paul Mackerras (from comments in - * Quik source) - * - * See also: - * http://developer.apple.com/documentation/mac/Devices/Devices-126.html - * http://developer.apple.com/documentation/mac/Devices/Devices-121.html - * http://devworld.apple.com/technotes/tn/tn1189.html - * - * Partition types: - * Apple_Bootstrap new-world (HFS) boot partition - * Apple_partition_map partition map (table) - * Apple_Driver device driver - * Apple_Driver43 SCSI Manager 4.3 device driver - * Apple_MFS original Macintosh File System - * Apple_HFS Hierarchical File System (and +) - * Apple_HFSX HFS+ with case sensitivity and more - * Apple_UNIX_SVR2 UNIX file system (UFS?) - * Apple_PRODOS ProDOS file system - * Apple_Free unused space - * Apple_Scratch empty - * Apple_Void padding for iso9660 - * Apple_Extra an unused partition map entry - * - * Quick explanation: - * ------------------ - * Terminology: - * - * Parted Apple - * ------ ----- - * device disk/device - * disk no equivalent. - * partition volume or partition - * sector block - * - * * All space must be accounted for, except block 0 (driver block) and - * block 1-X (the partition map: i.e. lots of MacRawPartitions) - * - * * It's really hard to grow/shrink the number of MacRawPartition - * entries in the partition map, because the first partition starts - * immediately after the partition map. When we can move the start of - * HFS and ext2 partitions, this problem will disappear ;-) - */ - -#define MAC_PARTITION_MAGIC_1 0x5453 /* old */ -#define MAC_PARTITION_MAGIC_2 0x504d -#define MAC_DISK_MAGIC 0x4552 - -#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ - -typedef struct _MacRawPartition MacRawPartition; -typedef struct _MacRawDisk MacRawDisk; -typedef struct _MacDeviceDriver MacDeviceDriver; -typedef struct _MacPartitionData MacPartitionData; -typedef struct _MacDiskData MacDiskData; - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _MacRawPartition { - uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */ - uint16_t res1; - uint32_t map_count; /* # blocks in partition map */ - uint32_t start_block; /* absolute starting block # of partition */ - uint32_t block_count; /* number of blocks in partition */ - char name[32]; /* partition name */ - char type[32]; /* string type description */ - uint32_t data_start; /* rel block # of first data block */ - uint32_t data_count; /* number of data blocks */ - uint32_t status; /* partition status bits */ - uint32_t boot_start; - uint32_t boot_count; - uint32_t boot_load; - uint32_t boot_load2; - uint32_t boot_entry; - uint32_t boot_entry2; - uint32_t boot_cksum; - char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */ - uint32_t driver_sig; - char _padding[372]; -}; - -/* Driver descriptor structure, in block 0 */ -struct __attribute__ ((packed)) _MacRawDisk { - uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */ - uint16_t block_size; /* physical sector size */ - uint32_t block_count; /* size of device in blocks */ - uint16_t dev_type; /* reserved */ - uint16_t dev_id; /* reserved */ - uint32_t data; /* reserved */ - uint16_t driver_count; /* # of driver descriptor entries */ - uint8_t driverlist[488];/* info about available drivers */ - uint16_t padding[3]; /* pad to 512 bytes */ -}; - -struct __attribute__ ((packed)) _MacDeviceDriver { - uint32_t block; /* startblock in MacRawDisk->block_size units */ - uint16_t size; /* size in 512 byte units */ - uint16_t type; /* operating system type (MacOS = 1) */ -}; -#ifdef __sun -#pragma pack() -#endif - -struct _MacPartitionData { - char volume_name[33]; /* eg: "Games" */ - char system_name[33]; /* eg: "Apple_Unix_SVR2" */ - char processor_name[17]; - - int is_boot; - int is_driver; - int has_driver; - int is_root; - int is_swap; - int is_lvm; - int is_raid; - - PedSector data_region_length; - PedSector boot_region_length; - - uint32_t boot_base_address; - uint32_t boot_entry_address; - uint32_t boot_checksum; - - uint32_t status; - uint32_t driver_sig; -}; - -struct _MacDiskData { - int ghost_size; /* sectors per "driver" block */ - int part_map_entry_count; /* # entries (incl. ghost) */ - int part_map_entry_num; /* partition map location */ - - int active_part_entry_count; /* # real partitions */ - int free_part_entry_count; /* # free space */ - int last_part_entry_num; /* last entry number */ - - uint16_t block_size; /* physical sector size */ - uint16_t driver_count; - MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */ -}; - -static PedDiskType mac_disk_type; - -static int -_check_signature (MacRawDisk* raw_disk) -{ - if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) { -#ifdef DISCOVER_ONLY - return 0; -#else - return ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Invalid signature %x for Mac disk labels."), - (int) PED_BE16_TO_CPU (raw_disk->signature)) - == PED_EXCEPTION_IGNORE; -#endif - } - - return 1; -} - -static int -_rawpart_check_signature (MacRawPartition* raw_part) -{ - int sig = (int) PED_BE16_TO_CPU (raw_part->signature); - return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2; -} - -static int -mac_probe (const PedDevice * dev) -{ - MacRawDisk buf; - - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size != 512) - return 0; - - if (!ped_device_read (dev, &buf, 0, 1)) - return 0; - - return _check_signature (&buf); -} - -static int -_disk_add_part_map_entry (PedDisk* disk, int warn) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - PedPartition* new_part; - MacPartitionData* mac_part_data; - PedSector part_map_size; - PedConstraint* constraint_any = ped_constraint_any (disk->dev); - -#ifndef DISCOVER_ONLY - if (warn && ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, - _("Partition map has no partition map entry!")) - != PED_EXCEPTION_FIX) - goto error; -#endif /* !DISCOVER_ONLY */ - - part_map_size - = ped_round_up_to (mac_disk_data->last_part_entry_num, 64); - if (part_map_size == 0) - part_map_size = 64; - - new_part = ped_partition_new (disk, 0, NULL, 1, part_map_size - 1); - if (!new_part) - goto error; - - mac_part_data = new_part->disk_specific; - strcpy (mac_part_data->volume_name, "Apple"); - strcpy (mac_part_data->system_name, "Apple_partition_map"); - - if (!ped_disk_add_partition (disk, new_part, constraint_any)) - goto error_destroy_new_part; - - mac_disk_data->part_map_entry_num = new_part->num; - mac_disk_data->part_map_entry_count - = new_part->geom.end - mac_disk_data->ghost_size; - ped_constraint_destroy (constraint_any); - return 1; - -error_destroy_new_part: - ped_partition_destroy (new_part); -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static PedDisk* -mac_alloc (const PedDevice* dev) -{ - PedDisk* disk; - MacDiskData* mac_disk_data; - - PED_ASSERT (dev != NULL, return NULL); - -#ifndef DISCOVER_ONLY - if (dev->length < 256) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s is too small for a Mac disk label!"), - dev->path); - goto error; - } -#endif - - disk = _ped_disk_alloc (dev, &mac_disk_type); - if (!disk) - goto error; - - mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData)); - if (!mac_disk_data) - goto error_free_disk; - disk->disk_specific = mac_disk_data; - mac_disk_data->ghost_size = disk->dev->sector_size / 512; - mac_disk_data->active_part_entry_count = 0; - mac_disk_data->free_part_entry_count = 1; - mac_disk_data->last_part_entry_num = 1; - mac_disk_data->block_size = 0; - mac_disk_data->driver_count = 0; - memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist)); - - if (!_disk_add_part_map_entry (disk, 0)) - goto error_free_disk; - return disk; - -error_free_disk: - _ped_disk_free (disk); -error: - return NULL; -} - -static PedDisk* -mac_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - MacDiskData* new_mac_data; - MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific; - PedPartition* partition_map; - - new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type); - if (!new_disk) - goto error; - - new_mac_data = (MacDiskData*) new_disk->disk_specific; - - /* remove the partition map partition - it will be duplicated - * later. - */ - partition_map = ped_disk_get_partition_by_sector (new_disk, 1); - PED_ASSERT (partition_map != NULL, return 0); - ped_disk_remove_partition (new_disk, partition_map); - - /* ugly, but C is ugly :p */ - memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData)); - return new_disk; - - _ped_disk_free (new_disk); -error: - return NULL; -} - -static void -mac_free (PedDisk* disk) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - - _ped_disk_free (disk); - ped_free (mac_disk_data); -} - -#ifndef DISCOVER_ONLY -static int -_clobber_part_map (PedDevice* dev) -{ - MacRawPartition raw_part; - PedSector sector; - - for (sector=1; 1; sector++) { - if (!ped_device_read (dev, &raw_part, sector, 1)) - return 0; - if (!_rawpart_check_signature (&raw_part)) - return 1; - memset (&raw_part, 0, 512); - if (!ped_device_write (dev, &raw_part, sector, 1)) - return 0; - } -} - -static int -mac_clobber (PedDevice* dev) -{ - MacRawDisk raw_disk; - - if (!ped_device_read (dev, &raw_disk, 0, 1)) - return 0; - if (!_check_signature (&raw_disk)) - return 0; - memset (&raw_disk, 0, 512); - if (!ped_device_write (dev, &raw_disk, 0, 1)) - return 0; - - return _clobber_part_map (dev); -} -#endif /* !DISCOVER_ONLY */ - -static int -_rawpart_cmp_type (MacRawPartition* raw_part, char* type) -{ - return strncasecmp (raw_part->type, type, 32) == 0; -} - -static int -_rawpart_cmp_name (MacRawPartition* raw_part, char* name) -{ - return strncasecmp (raw_part->name, name, 32) == 0; -} - -static int -_rawpart_is_partition_map (MacRawPartition* raw_part) -{ - return _rawpart_cmp_type (raw_part, "Apple_partition_map"); -} - -static int -strncasestr (const char* haystack, const char* needle, int n) -{ - int needle_size = strlen (needle); - int i; - - for (i = 0; haystack[i] && i < n - needle_size; i++) { - if (strncasecmp (haystack + i, needle, needle_size) == 0) - return 1; - } - - return 0; -} - -static int -_rawpart_is_boot (MacRawPartition* raw_part) -{ - if (!strcasecmp(raw_part->type, "Apple_Bootstrap")) - return 1; - - if (!strcasecmp(raw_part->type, "Apple_Boot")) - return 1; - - return 0; -} - -static int -_rawpart_is_driver (MacRawPartition* raw_part) -{ - if (strncmp (raw_part->type, "Apple_", 6) != 0) - return 0; - if (!strncasestr (raw_part->type, "driver", 32)) - return 0; - return 1; -} - -static int -_rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data) -{ - MacDeviceDriver *driverlist; - uint16_t i, bsz; - uint32_t driver_bs, driver_be, part_be; - - driverlist = &mac_disk_data->driverlist[0]; - bsz = mac_disk_data->block_size / 512; - for (i = 0; i < mac_disk_data->driver_count; i++) { - driver_bs = driverlist->block * bsz; - driver_be = driver_bs + driverlist->size; - part_be = raw_part->start_block + raw_part->block_count; - if (driver_bs >= raw_part->start_block && driver_be <= part_be) - return 1; - driverlist++; - } - return 0; -} - -static int -_rawpart_is_root (MacRawPartition* raw_part) -{ - if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2")) - return 0; - if (strcmp (raw_part->name, "root") != 0) - return 0; - return 1; -} - -static int -_rawpart_is_swap (MacRawPartition* raw_part) -{ - if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2")) - return 0; - if (strcmp (raw_part->name, "swap") != 0) - return 0; - return 1; -} - -static int -_rawpart_is_lvm (MacRawPartition* raw_part) -{ - if (strcmp (raw_part->type, "Linux_LVM") != 0) - return 0; - return 1; -} - -static int -_rawpart_is_raid (MacRawPartition* raw_part) -{ - if (strcmp (raw_part->type, "Linux_RAID") != 0) - return 0; - return 1; -} - -static int -_rawpart_is_void (MacRawPartition* raw_part) -{ - return _rawpart_cmp_type (raw_part, "Apple_Void"); -} - -/* returns 1 if the raw_part represents a partition that is "unused space", or - * doesn't represent a partition at all. NOTE: some people make Apple_Free - * partitions with MacOS, because they can't select another type. So, if the - * name is anything other than "Extra" or "", it is treated as a "real" - * partition. - */ -static int -_rawpart_is_active (MacRawPartition* raw_part) -{ - if (_rawpart_cmp_type (raw_part, "Apple_Free") - && (_rawpart_cmp_name (raw_part, "Extra") - || _rawpart_cmp_name (raw_part, ""))) - return 0; - if (_rawpart_cmp_type (raw_part, "Apple_Void")) - return 0; - if (_rawpart_cmp_type (raw_part, "Apple_Scratch")) - return 0; - if (_rawpart_cmp_type (raw_part, "Apple_Extra")) - return 0; - - return 1; -} - -static PedPartition* -_rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num) -{ - MacDiskData* mac_disk_data; - PedPartition* part; - MacPartitionData* mac_part_data; - PedSector block_size; - PedSector start, length; - - if (!_rawpart_check_signature (raw_part)) { -#ifndef DISCOVER_ONLY - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("Partition %d has an invalid signature %x."), - num, - (int) PED_BE16_TO_CPU (raw_part->signature)) - != PED_EXCEPTION_IGNORE) -#endif - goto error; - } - - mac_disk_data = (MacDiskData*) disk->disk_specific; - block_size = disk->dev->sector_size / 512; - - start = PED_BE32_TO_CPU (raw_part->start_block) * block_size; - length = PED_BE32_TO_CPU (raw_part->block_count) * block_size; - if (length == 0) { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Partition %d has an invalid length of 0 bytes!"), - num); -#endif - return NULL; - } - part = ped_partition_new (disk, 0, NULL, start, start + length - 1); - if (!part) - goto error; - - mac_part_data = part->disk_specific; - - strncpy (mac_part_data->volume_name, raw_part->name, 32); - strncpy (mac_part_data->system_name, raw_part->type, 32); - strncpy (mac_part_data->processor_name, raw_part->processor, 16); - - mac_part_data->is_boot = _rawpart_is_boot (raw_part); - mac_part_data->is_driver = _rawpart_is_driver (raw_part); - if (mac_part_data->is_driver) - mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data); - mac_part_data->is_root = _rawpart_is_root (raw_part); - mac_part_data->is_swap = _rawpart_is_swap (raw_part); - mac_part_data->is_lvm = _rawpart_is_lvm (raw_part); - mac_part_data->is_raid = _rawpart_is_raid (raw_part); - - /* "data" region */ -#ifndef DISCOVER_ONLY - if (raw_part->data_start) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The data region doesn't start at the start " - "of the partition.")); - goto error_destroy_part; - } -#endif /* !DISCOVER_ONLY */ - mac_part_data->data_region_length - = PED_BE32_TO_CPU (raw_part->data_count) * block_size; - - /* boot region - we have no idea what this is for, but Mac OSX - * seems to put garbage here, and doesn't pay any attention to - * it afterwards. [clausen, dan burcaw] - */ -#if 0 - if (raw_part->boot_start) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("The boot region doesn't start at the start " - "of the partition.")); - goto error_destroy_part; - } -#endif - mac_part_data->boot_region_length - = PED_BE32_TO_CPU (raw_part->boot_count) * block_size; - -#ifndef DISCOVER_ONLY - if (mac_part_data->has_driver) { - if (mac_part_data->boot_region_length < part->geom.length) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("The partition's boot region doesn't occupy " - "the entire partition.")) - != PED_EXCEPTION_IGNORE) - goto error_destroy_part; - } - } else { - if (mac_part_data->data_region_length < part->geom.length && - !mac_part_data->is_boot) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("The partition's data region doesn't occupy " - "the entire partition.")) - != PED_EXCEPTION_IGNORE) - goto error_destroy_part; - } - } -#endif /* !DISCOVER_ONLY */ - - mac_part_data->boot_base_address - = PED_BE32_TO_CPU (raw_part->boot_load); - mac_part_data->boot_entry_address - = PED_BE32_TO_CPU (raw_part->boot_entry); - mac_part_data->boot_checksum - = PED_BE32_TO_CPU (raw_part->boot_cksum); - - mac_part_data->status = PED_BE32_TO_CPU (raw_part->status); - mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig); - - return part; - -error_destroy_part: - ped_partition_destroy (part); -error: - return NULL; -} - -/* looks at the partition map size field in a mac raw partition, and calculates - * what the size of the partition map should be, from it - */ -static int -_rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - PedSector sector_size = disk->dev->sector_size / 512; - PedSector part_map_start; - PedSector part_map_end; - - part_map_start = mac_disk_data->ghost_size; - part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count); - - return part_map_end - part_map_start + 1; -} - -static int -_disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk) -{ - PedSector block_size; - - if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) { -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Weird block size on device descriptor: %d bytes is " - "not divisible by 512."), - (int) PED_BE16_TO_CPU (raw_disk->block_size)); -#endif - goto error; - } - - block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512; - if (block_size != disk->dev->sector_size / 512) { -#ifndef DISCOVER_ONLY - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The driver descriptor says the physical block size " - "is %d bytes, but Linux says it is %d bytes."), - (int) block_size * 512, - (int) disk->dev->sector_size) - != PED_EXCEPTION_IGNORE) - goto error; -#endif - disk->dev->sector_size = block_size * 512; - } - - return 1; - -error: - return 0; -} - -/* Tries to figure out the block size used by the drivers, for the ghost - * partitioning scheme. Ghost partitioning works like this: the OpenFirmware - * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and, - * perhaps, some other number?). To remain compatible, the partition map - * only has "real" partition map entries on ghost-aligned block numbers (and - * the others are padded with Apple_Void partitions). This function tries - * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not, - * doesn't always equal 2048!!!) - */ -static int -_disk_analyse_ghost_size (PedDisk* disk) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - MacRawPartition raw_part; - int i; - - for (i = 1; i < 64; i *= 2) { - if (!ped_device_read (disk->dev, &raw_part, i, 1)) - return 0; - if (_rawpart_check_signature (&raw_part) - && !_rawpart_is_void (&raw_part)) { - mac_disk_data->ghost_size = i; - PED_ASSERT (i <= disk->dev->sector_size / 512, - return 0); - return 1; - } - } - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("No valid partition map found.")); -#endif - return 0; -} - -static int -mac_read (PedDisk* disk) -{ - MacRawDisk raw_disk; - MacRawPartition raw_part; - MacDiskData* mac_disk_data; - PedPartition* part; - int num; - PedSector ghost_size; - PedConstraint* constraint_exact; - int last_part_entry_num = 0; - - PED_ASSERT (disk != NULL, return 0); - - mac_disk_data = disk->disk_specific; - mac_disk_data->part_map_entry_num = 0; /* 0 == none */ - - if (!ped_device_read (disk->dev, &raw_disk, 0, 1)) - goto error; - if (!_check_signature (&raw_disk)) - goto error; - - if (!_disk_analyse_block_size (disk, &raw_disk)) - goto error; - if (!_disk_analyse_ghost_size (disk)) - goto error; - ghost_size = mac_disk_data->ghost_size; - - if (!ped_disk_delete_all (disk)) - goto error; - - if (raw_disk.driver_count && raw_disk.driver_count < 62) { - memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0], - sizeof(mac_disk_data->driverlist)); - mac_disk_data->driver_count = raw_disk.driver_count; - mac_disk_data->block_size = raw_disk.block_size; - } - - for (num=1; num==1 || num <= last_part_entry_num; num++) { - if (!ped_device_read (disk->dev, &raw_part, - num * ghost_size, 1)) - goto error_delete_all; - - if (!_rawpart_check_signature (&raw_part)) - continue; - - if (num == 1) - last_part_entry_num - = _rawpart_get_partmap_size (&raw_part, disk); - if (_rawpart_get_partmap_size (&raw_part, disk) - != last_part_entry_num) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Conflicting partition map entry sizes! " - "Entry 1 says it is %d, but entry %d says " - "it is %d!"), - last_part_entry_num, - _rawpart_get_partmap_size (&raw_part, disk)) - != PED_EXCEPTION_IGNORE) - goto error_delete_all; - } - - if (!_rawpart_is_active (&raw_part)) - continue; - - part = _rawpart_analyse (&raw_part, disk, num); - if (!part) - goto error_delete_all; - part->num = num; - part->fs_type = ped_file_system_probe (&part->geom); - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error_delete_all; - ped_constraint_destroy (constraint_exact); - - if (_rawpart_is_partition_map (&raw_part)) { - if (mac_disk_data->part_map_entry_num - && ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_IGNORE_CANCEL, - _("Weird! There are 2 partitions " - "map entries!")) - != PED_EXCEPTION_IGNORE) - goto error_delete_all; - - mac_disk_data->part_map_entry_num = num; - mac_disk_data->part_map_entry_count - = part->geom.end - ghost_size + 1; - } - } - - if (!mac_disk_data->part_map_entry_num) { - if (!_disk_add_part_map_entry (disk, 1)) - goto error_delete_all; - ped_disk_commit_to_dev (disk); - } - return 1; - -error_delete_all: - ped_disk_delete_all (disk); -error: - return 0; -} - -#ifndef DISCOVER_ONLY -/* The Ghost partition: is a blank entry, used to pad out each block (where - * there physical block size > 512 bytes). This is because OpenFirmware uses - * 512 byte blocks, but device drivers Think Different TM, with a different - * lbock size, so we need to do this to avoid a clash (!) - */ -static int -_pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - MacRawPartition ghost_entry; - int i; - - memset (&ghost_entry, 0, sizeof (ghost_entry)); - ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); - strcpy (ghost_entry.type, "Apple_Void"); - ghost_entry.map_count - = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); - - for (i=0; i < mac_disk_data->ghost_size - 1; i++) - memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size], - &ghost_entry, sizeof (MacRawPartition)); - - return 1; -} - -static void -_update_driver_count (MacRawPartition* part_map_entry, - MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data) -{ - uint16_t i, count_orig, count_cur, bsz; - uint32_t driver_bs, driver_be, part_be; - - bsz = mac_disk_data->block_size / 512; - count_cur = mac_driverdata->driver_count; - count_orig = mac_disk_data->driver_count; - for (i = 0; i < count_orig; i++) { - driver_bs = mac_disk_data->driverlist[i].block * bsz; - driver_be = driver_bs + mac_disk_data->driverlist[i].size; - part_be = part_map_entry->start_block + part_map_entry->block_count; - if (driver_bs >= part_map_entry->start_block - && driver_be <= part_be) { - mac_driverdata->driverlist[count_cur].block - = mac_disk_data->driverlist[i].block; - mac_driverdata->driverlist[count_cur].size - = mac_disk_data->driverlist[i].size; - mac_driverdata->driverlist[count_cur].type - = mac_disk_data->driverlist[i].type; - mac_driverdata->driver_count++; - break; - } - } -} - -static int -_generate_raw_part (PedDisk* disk, PedPartition* part, - MacRawPartition* part_map, MacDiskData *mac_driverdata) -{ - MacDiskData* mac_disk_data; - MacPartitionData* mac_part_data; - MacRawPartition* part_map_entry; - PedSector block_size = disk->dev->sector_size / 512; - - PED_ASSERT (part->num > 0, goto error); - - mac_disk_data = disk->disk_specific; - mac_part_data = part->disk_specific; - - part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1]; - - part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); - part_map_entry->map_count - = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); - part_map_entry->start_block - = PED_CPU_TO_BE32 (part->geom.start / block_size); - part_map_entry->block_count - = PED_CPU_TO_BE32 (part->geom.length / block_size); - strcpy (part_map_entry->name, mac_part_data->volume_name); - strcpy (part_map_entry->type, mac_part_data->system_name); - - if (mac_part_data->is_driver) { - mac_part_data->boot_region_length = part->geom.length; - if (mac_part_data->has_driver) - _update_driver_count(part_map_entry, mac_driverdata, - mac_disk_data); - } else - mac_part_data->data_region_length = part->geom.length; - part_map_entry->data_count = PED_CPU_TO_BE32 ( - mac_part_data->data_region_length / block_size); - part_map_entry->boot_count = PED_CPU_TO_BE32 ( - mac_part_data->boot_region_length / block_size); - part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status); - part_map_entry->driver_sig - = PED_CPU_TO_BE32 (mac_part_data->driver_sig); - - part_map_entry->boot_load = - PED_CPU_TO_BE32 (mac_part_data->boot_base_address); - part_map_entry->boot_entry = - PED_CPU_TO_BE32 (mac_part_data->boot_entry_address); - part_map_entry->boot_cksum = - PED_CPU_TO_BE32 (mac_part_data->boot_checksum); - - strncpy (part_map_entry->processor, mac_part_data->processor_name, 16); - - if (!_pad_raw_part (disk, part->num, part_map)) - goto error; - - return 1; - -error: - return 0; -} - -static int -_generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num, - MacRawPartition* part_map) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - MacRawPartition* part_map_entry; - PedSector block_size = disk->dev->sector_size / 512; - - PED_ASSERT (num > 0, goto error); - - part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1]; - - part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); - part_map_entry->map_count - = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); - part_map_entry->start_block - = PED_CPU_TO_BE32 (geom->start / block_size); - part_map_entry->block_count - = PED_CPU_TO_BE32 (geom->length / block_size); - strcpy (part_map_entry->name, "Extra"); - strcpy (part_map_entry->type, "Apple_Free"); - - part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length); - part_map_entry->status = 0; - part_map_entry->driver_sig = 0; - - if (!_pad_raw_part (disk, num, part_map)) - goto error; - - return 1; - -error: - return 0; -} - -static int -_generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - MacRawPartition* part_map_entry; - - PED_ASSERT (num > 0, return 0); - - part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1]; - part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); - part_map_entry->map_count - = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); - strcpy (part_map_entry->type, "Apple_Void"); - - return _pad_raw_part (disk, num, part_map); -} - -/* returns the first empty entry in the partition map */ -static int -_get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - int i; - - for (i=1; i <= mac_disk_data->last_part_entry_num; i++) { - if (!part_map[i * mac_disk_data->ghost_size - 1].signature) - return i; - } - - return 0; -} - -static int -write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata) -{ - PedDevice* dev = disk->dev; - MacRawDisk raw_disk; - - if (!ped_device_read (dev, &raw_disk, 0, 1)) - return 0; - - raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC); - raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size); - raw_disk.block_count - = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512)); - - raw_disk.driver_count = mac_driverdata->driver_count; - memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0], - sizeof(raw_disk.driverlist)); - - return ped_device_write (dev, &raw_disk, 0, 1); -} - -static int -mac_write (PedDisk* disk) -{ - MacRawPartition* part_map; - MacDiskData* mac_disk_data; - MacDiskData* mac_driverdata; /* updated driver list */ - PedPartition* part; - int num; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->disk_specific != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - PED_ASSERT (!disk->update_mode, return 0); - - mac_disk_data = disk->disk_specific; - - if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) { - if (!_disk_add_part_map_entry (disk, 1)) - goto error; - } - - mac_driverdata = ped_malloc(sizeof(MacDiskData)); - if (!mac_driverdata) - goto error; - memset (mac_driverdata, 0, sizeof(MacDiskData)); - - part_map = (MacRawPartition*) - ped_malloc (mac_disk_data->part_map_entry_count * 512); - if (!part_map) - goto error_free_driverdata; - memset (part_map, 0, mac_disk_data->part_map_entry_count * 512); - -/* write (to memory) the "real" partitions */ - for (part = ped_disk_next_partition (disk, NULL); part; - part = ped_disk_next_partition (disk, part)) { - if (!ped_partition_is_active (part)) - continue; - if (!_generate_raw_part (disk, part, part_map, mac_driverdata)) - goto error_free_part_map; - } - -/* write the "free space" partitions */ - for (part = ped_disk_next_partition (disk, NULL); part; - part = ped_disk_next_partition (disk, part)) { - if (part->type != PED_PARTITION_FREESPACE) - continue; - num = _get_first_empty_part_entry (disk, part_map); - if (!_generate_raw_freespace_part (disk, &part->geom, num, - part_map)) - goto error_free_part_map; - } - -/* write the "void" (empty) partitions */ - for (num = _get_first_empty_part_entry (disk, part_map); num; - num = _get_first_empty_part_entry (disk, part_map)) - _generate_empty_part (disk, num, part_map); - -/* write to disk */ - if (!ped_device_write (disk->dev, part_map, 1, - mac_disk_data->part_map_entry_count)) - goto error_free_part_map; - ped_free (part_map); - return write_block_zero (disk, mac_driverdata); - -error_free_part_map: - ped_free (part_map); -error_free_driverdata: - ped_free (mac_driverdata); -error: - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -mac_partition_new ( - const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, PedSector start, PedSector end) -{ - PedPartition* part; - MacPartitionData* mac_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (ped_partition_is_active (part)) { - part->disk_specific - = mac_data = ped_malloc (sizeof (MacPartitionData)); - if (!mac_data) - goto error_free_part; - - memset (mac_data, 0, sizeof (MacPartitionData)); - strcpy (mac_data->volume_name, "untitled"); - } else { - part->disk_specific = NULL; - } - return part; - - ped_free (mac_data); -error_free_part: - ped_free (part); -error: - return 0; -} - -static PedPartition* -mac_partition_duplicate (const PedPartition* part) -{ - PedPartition* new_part; - MacPartitionData* new_mac_data; - MacPartitionData* old_mac_data; - - new_part = ped_partition_new (part->disk, part->type, - part->fs_type, part->geom.start, - part->geom.end); - if (!new_part) - return NULL; - new_part->num = part->num; - - old_mac_data = (MacPartitionData*) part->disk_specific; - new_mac_data = (MacPartitionData*) new_part->disk_specific; - - /* ugly, but C is ugly :p */ - memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData)); - return new_part; -} - -static void -mac_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) - ped_free (part->disk_specific); - ped_free (part); -} - -static int -mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - MacPartitionData* mac_data = part->disk_specific; - - part->fs_type = fs_type; - - if (fs_type && !strcmp (fs_type->name, "linux-swap")) - ped_partition_set_flag (part, PED_PARTITION_SWAP, 1); - - if (mac_data->is_boot) { - strcpy (mac_data->system_name, "Apple_Bootstrap"); - mac_data->status = 0x33; - return 1; - } - - if (fs_type && (!strcmp (fs_type->name, "hfs") - || !strcmp (fs_type->name, "hfs+"))) { - strcpy (mac_data->system_name, "Apple_HFS"); - mac_data->status |= 0x7f; - } else if (fs_type && !strcmp (fs_type->name, "hfsx")) { - strcpy (mac_data->system_name, "Apple_HFSX"); - mac_data->status |= 0x7f; - } else { - strcpy (mac_data->system_name, "Apple_UNIX_SVR2"); - mac_data->status = 0x33; - } - - return 1; -} - -static int -mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - MacPartitionData* mac_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - mac_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_BOOT: - mac_data->is_boot = state; - - if (part->fs_type) - return mac_partition_set_system (part, part->fs_type); - - if (state) { - strcpy (mac_data->system_name, "Apple_Bootstrap"); - mac_data->status = 0x33; - } - return 1; - - case PED_PARTITION_ROOT: - if (state) { - strcpy (mac_data->volume_name, "root"); - mac_data->is_swap = 0; - } else { - if (mac_data->is_root) - strcpy (mac_data->volume_name, "untitled"); - } - mac_data->is_root = state; - return 1; - - case PED_PARTITION_SWAP: - if (state) { - strcpy (mac_data->volume_name, "swap"); - mac_data->is_root = 0; - } else { - if (mac_data->is_swap) - strcpy (mac_data->volume_name, "untitled"); - } - mac_data->is_swap = state; - return 1; - - case PED_PARTITION_LVM: - if (state) { - strcpy (mac_data->system_name, "Linux_LVM"); - mac_data->is_lvm = state; - } else { - if (mac_data->is_lvm) - mac_partition_set_system (part, part->fs_type); - } - return 1; - - case PED_PARTITION_RAID: - if (state) { - strcpy (mac_data->system_name, "Linux_RAID"); - mac_data->is_raid = state; - } else { - if (mac_data->is_raid) - mac_partition_set_system (part, part->fs_type); - } - return 1; - - default: - return 0; - } -} - -static int -mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - MacPartitionData* mac_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - mac_data = part->disk_specific; - switch (flag) { - case PED_PARTITION_BOOT: - return mac_data->is_boot; - - case PED_PARTITION_ROOT: - return mac_data->is_root; - - case PED_PARTITION_SWAP: - return mac_data->is_swap; - - case PED_PARTITION_LVM: - return mac_data->is_lvm; - - case PED_PARTITION_RAID: - return mac_data->is_raid; - - default: - return 0; - } -} - -static int -mac_partition_is_flag_available ( - const PedPartition* part, PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_BOOT: - case PED_PARTITION_ROOT: - case PED_PARTITION_SWAP: - case PED_PARTITION_LVM: - case PED_PARTITION_RAID: - return 1; - - default: - return 0; - } -} - -static void -mac_partition_set_name (PedPartition* part, const char* name) -{ - MacPartitionData* mac_data; - int i; - - PED_ASSERT (part != NULL, return); - PED_ASSERT (part->disk_specific != NULL, return); - mac_data = part->disk_specific; - -#ifndef DISCOVER_ONLY - if (mac_data->is_root || mac_data->is_swap) { - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("Changing the name of a root or swap partition " - "will prevent Linux from recognising it as such.")) - != PED_EXCEPTION_IGNORE) - return; - mac_data->is_root = mac_data->is_swap = 0; - } -#endif - - strncpy (mac_data->volume_name, name, 32); - mac_data->volume_name [32] = 0; - for (i = strlen (mac_data->volume_name) - 1; - mac_data->volume_name[i] == ' '; i--) - mac_data->volume_name [i] = 0; -} - -static const char* -mac_partition_get_name (const PedPartition* part) -{ - MacPartitionData* mac_data; - - PED_ASSERT (part != NULL, return NULL); - PED_ASSERT (part->disk_specific != NULL, return NULL); - mac_data = part->disk_specific; - - return mac_data->volume_name; -} - -static PedConstraint* -_primary_constraint (PedDisk* disk) -{ - PedAlignment start_align; - PedAlignment end_align; - PedGeometry max_geom; - PedSector sector_size; - - sector_size = disk->dev->sector_size / 512; - - if (!ped_alignment_init (&start_align, 0, sector_size)) - return NULL; - if (!ped_alignment_init (&end_align, -1, sector_size)) - return NULL; - if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1)) - return NULL; - - return ped_constraint_new (&start_align, &end_align, &max_geom, - &max_geom, 1, disk->dev->length); -} - -static int -mac_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - if (_ped_partition_attempt_align (part, constraint, - _primary_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -mac_partition_enumerate (PedPartition* part) -{ - PedDisk* disk; - MacDiskData* mac_disk_data; - int i; - int max_part_count; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - disk = part->disk; - mac_disk_data = (MacDiskData*) disk->disk_specific; - - max_part_count = ped_disk_get_max_primary_partition_count (disk); - - if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count) - return 1; - - for (i = 1; i <= max_part_count; i++) { - if (!ped_disk_get_partition (disk, i)) { - part->num = i; - return 1; - } - } - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't add another partition -- the partition map is too " - "small!")); -#endif - - return 0; -} - -static int -_disk_count_partitions (PedDisk* disk) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - PedPartition* part = NULL; - PedPartition* last = NULL; - - PED_ASSERT (disk->update_mode, return 0); - - mac_disk_data->active_part_entry_count = 0; - mac_disk_data->free_part_entry_count = 0; - mac_disk_data->last_part_entry_num = 0; - - /* subtle: we only care about free space after the partition map. - * the partition map is an "active" partition, BTW... */ - for (part = ped_disk_next_partition (disk, part); part; - part = ped_disk_next_partition (disk, part)) { - if (!ped_partition_is_active (part)) - continue; - - mac_disk_data->active_part_entry_count++; - if (last && last->geom.end + 1 < part->geom.start) - mac_disk_data->free_part_entry_count++; - mac_disk_data->last_part_entry_num - = PED_MAX (mac_disk_data->last_part_entry_num, - part->num); - - last = part; - } - - if (last && last->geom.end < disk->dev->length - 1) - mac_disk_data->free_part_entry_count++; - - mac_disk_data->last_part_entry_num - = PED_MAX (mac_disk_data->last_part_entry_num, - mac_disk_data->active_part_entry_count - + mac_disk_data->free_part_entry_count); - return 1; -} - -static int -add_metadata_part (PedDisk* disk, PedSector start, PedSector end) -{ - PedPartition* new_part; - PedConstraint* constraint_any = ped_constraint_any (disk->dev); - - PED_ASSERT (disk != NULL, return 0); - - new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, - start, end); - if (!new_part) - goto error; - if (!ped_disk_add_partition (disk, new_part, constraint_any)) - goto error_destroy_new_part; - - ped_constraint_destroy (constraint_any); - return 1; - -error_destroy_new_part: - ped_partition_destroy (new_part); -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static int -mac_alloc_metadata (PedDisk* disk) -{ - MacDiskData* mac_disk_data; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->disk_specific != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - mac_disk_data = disk->disk_specific; - - if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1)) - return 0; - - /* hack: this seems to be a good place, to update the partition map - * entry count, since mac_alloc_metadata() gets called during - * _disk_pop_update_mode() - */ - return _disk_count_partitions (disk); -} - -static int -mac_get_max_primary_partition_count (const PedDisk* disk) -{ - MacDiskData* mac_disk_data = disk->disk_specific; - PedPartition* part_map_partition; - - part_map_partition = ped_disk_get_partition (disk, - mac_disk_data->part_map_entry_num); - - /* HACK: if we haven't found the partition map partition (yet), - * we return this. - */ - if (!part_map_partition) { - mac_disk_data->part_map_entry_num = 0; - return 65536; - } - - /* HACK: since Mac labels need an entry for free-space regions, we - * must allow half plus 1 entries for free-space partitions. I hate - * this, but things get REALLY complicated, otherwise. - * (I'm prepared to complicate things later, but I want to get - * everything working, first) - */ - return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size - - mac_disk_data->free_part_entry_count + 1; -} - -static PedDiskOps mac_disk_ops = { - .probe = mac_probe, -#ifndef DISCOVER_ONLY - .clobber = mac_clobber, -#else - .clobber = NULL, -#endif - .alloc = mac_alloc, - .duplicate = mac_duplicate, - .free = mac_free, - .read = mac_read, -#ifndef DISCOVER_ONLY - /* FIXME: remove this cast, once mac_write is fixed not to - modify its *DISK parameter. */ - .write = (int (*) (const PedDisk*)) mac_write, -#else - .write = NULL, -#endif - - .partition_new = mac_partition_new, - .partition_duplicate = mac_partition_duplicate, - .partition_destroy = mac_partition_destroy, - .partition_set_system = mac_partition_set_system, - .partition_set_flag = mac_partition_set_flag, - .partition_get_flag = mac_partition_get_flag, - .partition_is_flag_available = mac_partition_is_flag_available, - .partition_set_name = mac_partition_set_name, - .partition_get_name = mac_partition_get_name, - .partition_align = mac_partition_align, - .partition_enumerate = mac_partition_enumerate, - - .alloc_metadata = mac_alloc_metadata, - .get_max_primary_partition_count = - mac_get_max_primary_partition_count -}; - -static PedDiskType mac_disk_type = { - .next = NULL, - .name = "mac", - .ops = &mac_disk_ops, - .features = PED_DISK_TYPE_PARTITION_NAME -}; - -void -ped_disk_mac_init () -{ - PED_ASSERT (sizeof (MacRawPartition) == 512, return); - PED_ASSERT (sizeof (MacRawDisk) == 512, return); - - ped_disk_type_register (&mac_disk_type); -} - -void -ped_disk_mac_done () -{ - ped_disk_type_unregister (&mac_disk_type); -} - diff --git a/usr/src/lib/libparted/common/libparted/labels/pc98.c b/usr/src/lib/libparted/common/libparted/labels/pc98.c deleted file mode 100644 index dc7565760e..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/pc98.c +++ /dev/null @@ -1,896 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* hacked from Linux/98 source: fs/partitions/nec98.h - * - * See also: - * http://people.FreeBSD.org/~kato/pc98.html - * http://www.kmc.kyoto-u.ac.jp/proj/linux98/index-english.html - * - * Partition types: - * - * id0(mid): - * bit 7: 1=bootable, 0=not bootable - * # Linux uses this flag to make a distinction between ext2 and swap. - * bit 6--0: - * 00H : N88-BASIC(data)?, PC-UX(data)? - * 04H : PC-UX(data) - * 06H : N88-BASIC - * 10H : N88-BASIC - * 14H : *BSD, PC-UX - * 20H : DOS(data), Windows95/98/NT, Linux - * 21H..2FH : DOS(system#1 .. system#15) - * 40H : Minix - * - * id1(sid): - * bit 7: 1=active, 0=sleep(hidden) - * # PC-UX uses this flag to make a distinction between its file system - * # and its swap. - * bit 6--0: - * 01H: FAT12 - * 11H: FAT16, <32MB [accessible to DOS 3.3] - * 21H: FAT16, >=32MB [Large Partition] - * 31H: NTFS - * 28H: Windows NT (Volume/Stripe Set?) - * 41H: Windows NT (Volume/Stripe Set?) - * 48H: Windows NT (Volume/Stripe Set?) - * 61H: FAT32 - * 04H: PC-UX - * 06H: N88-BASIC - * 44H: *BSD - * 62H: ext2, linux-swap - */ - -#define MAX_PART_COUNT 16 -#define PC9800_EXTFMT_MAGIC 0xAA55 - -#define BIT(x) (1 << (x)) -#define GET_BIT(n,bit) (((n) & BIT(bit)) != 0) -#define SET_BIT(n,bit,val) n = (val)? (n | BIT(bit)) : (n & ~BIT(bit)) - -typedef struct _PC98RawPartition PC98RawPartition; -typedef struct _PC98RawTable PC98RawTable; - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -/* ripped from Linux/98 source */ -#ifdef __sun -#pragma pack(1) -#endif -struct _PC98RawPartition { - uint8_t mid; /* 0x80 - boot */ - uint8_t sid; /* 0x80 - active */ - uint8_t dum1; /* dummy for padding */ - uint8_t dum2; /* dummy for padding */ - uint8_t ipl_sect; /* IPL sector */ - uint8_t ipl_head; /* IPL head */ - uint16_t ipl_cyl; /* IPL cylinder */ - uint8_t sector; /* starting sector */ - uint8_t head; /* starting head */ - uint16_t cyl; /* starting cylinder */ - uint8_t end_sector; /* end sector */ - uint8_t end_head; /* end head */ - uint16_t end_cyl; /* end cylinder */ - char name[16]; -} __attribute__((packed)); - -struct _PC98RawTable { - uint8_t boot_code [510]; - uint16_t magic; - PC98RawPartition partitions [MAX_PART_COUNT]; -} __attribute__((packed)); -#ifdef __sun -#pragma pack() -#endif - -typedef struct { - PedSector ipl_sector; - int system; - int boot; - int hidden; - char name [17]; -} PC98PartitionData; - -/* this MBR boot code is dummy */ -static const unsigned char MBR_BOOT_CODE[] = { - 0xcb, /* retf */ - 0x00, 0x00, 0x00, /* */ - 0x49, 0x50, 0x4c, 0x31 /* "IPL1" */ -}; - -static PedDiskType pc98_disk_type; - -static PedSector chs_to_sector (const PedDevice* dev, int c, int h, int s); -static void sector_to_chs (const PedDevice* dev, PedSector sector, - int* c, int* h, int* s); - -/* magic(?) check */ -static int -pc98_check_magic (const PC98RawTable *part_table) -{ - /* check "extended-format" (have partition table?) */ - if (PED_LE16_TO_CPU(part_table->magic) != PC9800_EXTFMT_MAGIC) - return 0; - - return 1; -} - -static int -pc98_check_ipl_signature (const PC98RawTable *part_table) -{ - return !memcmp (part_table->boot_code + 4, "IPL1", 4); -} - -static int -check_partition_consistency (const PedDevice* dev, - const PC98RawPartition* raw_part) -{ - if (raw_part->ipl_sect >= dev->hw_geom.sectors - || raw_part->sector >= dev->hw_geom.sectors - || raw_part->end_sector >= dev->hw_geom.sectors - || raw_part->ipl_head >= dev->hw_geom.heads - || raw_part->head >= dev->hw_geom.heads - || raw_part->end_head >= dev->hw_geom.heads - || PED_LE16_TO_CPU(raw_part->ipl_cyl) >= dev->hw_geom.cylinders - || PED_LE16_TO_CPU(raw_part->cyl) >= dev->hw_geom.cylinders - || PED_LE16_TO_CPU(raw_part->end_cyl) >= dev->hw_geom.cylinders - || PED_LE16_TO_CPU(raw_part->cyl) - > PED_LE16_TO_CPU(raw_part->end_cyl) -#if 0 - || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->ipl_cyl), - raw_part->ipl_head, raw_part->ipl_sect) - || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->cyl), - raw_part->head, raw_part->sector) - || !chs_to_sector(dev, PED_LE16_TO_CPU(raw_part->end_cyl), - raw_part->end_head, raw_part->end_sector) -#endif - || PED_LE16_TO_CPU(raw_part->end_cyl) - < PED_LE16_TO_CPU(raw_part->cyl)) - return 0; - - return 1; -} - -static int -pc98_probe (const PedDevice *dev) -{ - PC98RawTable part_table; - int empty; - const PC98RawPartition* p; - - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size != 512) - return 0; - - if (!ped_device_read (dev, &part_table, 0, 2)) - return 0; - - /* check magic */ - if (!pc98_check_magic (&part_table)) - return 0; - - /* check consistency */ - empty = 1; - for (p = part_table.partitions; - p < part_table.partitions + MAX_PART_COUNT; - p++) - { - if (p->mid == 0 && p->sid == 0) - continue; - empty = 0; - if (!check_partition_consistency (dev, p)) - return 0; - } - - /* check boot loader */ - if (pc98_check_ipl_signature (&part_table)) - return 1; - else if (part_table.boot_code[0]) /* invalid boot loader */ - return 0; - - /* Not to mistake msdos disk map for PC-9800's empty disk map */ - if (empty) - return 0; - - return 1; -} - -#ifndef DISCOVER_ONLY -static int -pc98_clobber (PedDevice* dev) -{ - PC98RawTable table; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (pc98_probe (dev), return 0); - - if (!ped_device_read (dev, &table, 0, 1)) - return 0; - - memset (table.partitions, 0, sizeof (table.partitions)); - table.magic = PED_CPU_TO_LE16(0); - - if (pc98_check_ipl_signature (&table)) - memset (table.boot_code, 0, sizeof (table.boot_code)); - - if (!ped_device_write (dev, (void*) &table, 0, 1)) - return 0; - return ped_device_sync (dev); -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk* -pc98_alloc (const PedDevice* dev) -{ - PED_ASSERT (dev != NULL, return 0); - - return _ped_disk_alloc (dev, &pc98_disk_type); -} - -static PedDisk* -pc98_duplicate (const PedDisk* disk) -{ - return ped_disk_new_fresh (disk->dev, &pc98_disk_type); -} - -static void -pc98_free (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return); - - _ped_disk_free (disk); -} - -static PedSector -chs_to_sector (const PedDevice* dev, int c, int h, int s) -{ - PED_ASSERT (dev != NULL, return 0); - return (c * dev->hw_geom.heads + h) * dev->hw_geom.sectors + s; -} - -static void -sector_to_chs (const PedDevice* dev, PedSector sector, int* c, int* h, int* s) -{ - PedSector cyl_size; - - PED_ASSERT (dev != NULL, return); - PED_ASSERT (c != NULL, return); - PED_ASSERT (h != NULL, return); - PED_ASSERT (s != NULL, return); - - cyl_size = dev->hw_geom.heads * dev->hw_geom.sectors; - - *c = sector / cyl_size; - *h = (sector) % cyl_size / dev->hw_geom.sectors; - *s = (sector) % cyl_size % dev->hw_geom.sectors; -} - -static PedSector -legacy_start (const PedDisk* disk, const PC98RawPartition* raw_part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - return chs_to_sector (disk->dev, PED_LE16_TO_CPU(raw_part->cyl), - raw_part->head, raw_part->sector); -} - -static PedSector -legacy_end (const PedDisk* disk, const PC98RawPartition* raw_part) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (raw_part != NULL, return 0); - - if (raw_part->end_head == 0 && raw_part->end_sector == 0) { - return chs_to_sector (disk->dev, - PED_LE16_TO_CPU(raw_part->end_cyl), - disk->dev->hw_geom.heads - 1, - disk->dev->hw_geom.sectors - 1); - } else { - return chs_to_sector (disk->dev, - PED_LE16_TO_CPU(raw_part->end_cyl), - raw_part->end_head, - raw_part->end_sector); - } -} - -static int -is_unused_partition(const PC98RawPartition* raw_part) -{ - if (raw_part->mid || raw_part->sid - || raw_part->ipl_sect - || raw_part->ipl_head - || PED_LE16_TO_CPU(raw_part->ipl_cyl) - || raw_part->sector - || raw_part->head - || PED_LE16_TO_CPU(raw_part->cyl) - || raw_part->end_sector - || raw_part->end_head - || PED_LE16_TO_CPU(raw_part->end_cyl)) - return 0; - return 1; -} - -static int -read_table (PedDisk* disk) -{ - int i; - PC98RawTable table; - PedConstraint* constraint_any; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - constraint_any = ped_constraint_any (disk->dev); - - if (!ped_device_read (disk->dev, (void*) &table, 0, 2)) - goto error; - - if (!pc98_check_magic(&table)) { - if (ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL, - _("Invalid partition table on %s."), - disk->dev->path)) - goto error; - } - - for (i = 0; i < MAX_PART_COUNT; i++) { - PC98RawPartition* raw_part; - PedPartition* part; - PC98PartitionData* pc98_data; - PedSector part_start; - PedSector part_end; - - raw_part = &table.partitions [i]; - - if (is_unused_partition(raw_part)) - continue; - - part_start = legacy_start (disk, raw_part); - part_end = legacy_end (disk, raw_part); - - part = ped_partition_new (disk, 0, NULL, part_start, part_end); - if (!part) - goto error; - pc98_data = part->disk_specific; - PED_ASSERT (pc98_data != NULL, goto error); - - pc98_data->system = (raw_part->mid << 8) | raw_part->sid; - pc98_data->boot = GET_BIT(raw_part->mid, 7); - pc98_data->hidden = !GET_BIT(raw_part->sid, 7); - - ped_partition_set_name (part, raw_part->name); - - pc98_data->ipl_sector = chs_to_sector ( - disk->dev, - PED_LE16_TO_CPU(raw_part->ipl_cyl), - raw_part->ipl_head, - raw_part->ipl_sect); - - /* hack */ - if (pc98_data->ipl_sector == part->geom.start) - pc98_data->ipl_sector = 0; - - part->num = i + 1; - - if (!ped_disk_add_partition (disk, part, constraint_any)) - goto error; - - if (part->geom.start != part_start - || part->geom.end != part_end) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Partition %d isn't aligned to cylinder " - "boundaries. This is still unsupported."), - part->num); - goto error; - } - - part->fs_type = ped_file_system_probe (&part->geom); - } - - ped_constraint_destroy (constraint_any); - return 1; - -error: - ped_disk_delete_all (disk); - ped_constraint_destroy (constraint_any); - return 0; -} - -static int -pc98_read (PedDisk* disk) -{ - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - ped_disk_delete_all (disk); - return read_table (disk); -} - -#ifndef DISCOVER_ONLY -static int -fill_raw_part (PC98RawPartition* raw_part, const PedPartition* part) -{ - PC98PartitionData* pc98_data; - int c, h, s; - const char* name; - - PED_ASSERT (raw_part != NULL, return 0); - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - pc98_data = part->disk_specific; - raw_part->mid = (pc98_data->system >> 8) & 0xFF; - raw_part->sid = pc98_data->system & 0xFF; - - SET_BIT(raw_part->mid, 7, pc98_data->boot); - SET_BIT(raw_part->sid, 7, !pc98_data->hidden); - - memset (raw_part->name, ' ', sizeof(raw_part->name)); - name = ped_partition_get_name (part); - PED_ASSERT (name != NULL, return 0); - PED_ASSERT (strlen (name) <= 16, return 0); - if (!strlen (name) && part->fs_type) - name = part->fs_type->name; - memcpy (raw_part->name, name, strlen (name)); - - sector_to_chs (part->disk->dev, part->geom.start, &c, &h, &s); - raw_part->cyl = PED_CPU_TO_LE16(c); - raw_part->head = h; - raw_part->sector = s; - - if (pc98_data->ipl_sector) { - sector_to_chs (part->disk->dev, pc98_data->ipl_sector, - &c, &h, &s); - raw_part->ipl_cyl = PED_CPU_TO_LE16(c); - raw_part->ipl_head = h; - raw_part->ipl_sect = s; - } else { - raw_part->ipl_cyl = raw_part->cyl; - raw_part->ipl_head = raw_part->head; - raw_part->ipl_sect = raw_part->sector; - } - - sector_to_chs (part->disk->dev, part->geom.end, &c, &h, &s); - if (h != part->disk->dev->hw_geom.heads - 1 - || s != part->disk->dev->hw_geom.sectors - 1) { - ped_exception_throw ( - PED_EXCEPTION_NO_FEATURE, - PED_EXCEPTION_CANCEL, - _("Partition %d isn't aligned to cylinder " - "boundaries. This is still unsupported."), - part->num); - return 0; - } - raw_part->end_cyl = PED_CPU_TO_LE16(c); -#if 0 - raw_part->end_head = h; - raw_part->end_sector = s; -#else - raw_part->end_head = 0; - raw_part->end_sector = 0; -#endif - - return 1; -} - -static int -pc98_write (const PedDisk* disk) -{ - PC98RawTable table; - PedPartition* part; - int i; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - if (!ped_device_read (disk->dev, &table, 0, 2)) - return 0; - - if (!pc98_check_ipl_signature (&table)) { - memset (table.boot_code, 0, sizeof(table.boot_code)); - memcpy (table.boot_code, MBR_BOOT_CODE, sizeof(MBR_BOOT_CODE)); - } - - memset (table.partitions, 0, sizeof (table.partitions)); - table.magic = PED_CPU_TO_LE16(PC9800_EXTFMT_MAGIC); - - for (i = 1; i <= MAX_PART_COUNT; i++) { - part = ped_disk_get_partition (disk, i); - if (!part) - continue; - - if (!fill_raw_part (&table.partitions [i - 1], part)) - return 0; - } - - if (!ped_device_write (disk->dev, (void*) &table, 0, 2)) - return 0; - return ped_device_sync (disk->dev); -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -pc98_partition_new ( - const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, PedSector start, PedSector end) -{ - PedPartition* part; - PC98PartitionData* pc98_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (ped_partition_is_active (part)) { - part->disk_specific - = pc98_data = ped_malloc (sizeof (PC98PartitionData)); - if (!pc98_data) - goto error_free_part; - pc98_data->ipl_sector = 0; - pc98_data->hidden = 0; - pc98_data->boot = 0; - strcpy (pc98_data->name, ""); - } else { - part->disk_specific = NULL; - } - return part; - - ped_free (pc98_data); -error_free_part: - ped_free (part); -error: - return 0; -} - -static PedPartition* -pc98_partition_duplicate (const PedPartition* part) -{ - PedPartition* new_part; - PC98PartitionData* new_pc98_data; - PC98PartitionData* old_pc98_data; - - new_part = ped_partition_new (part->disk, part->type, - part->fs_type, part->geom.start, - part->geom.end); - if (!new_part) - return NULL; - new_part->num = part->num; - - old_pc98_data = (PC98PartitionData*) part->disk_specific; - new_pc98_data = (PC98PartitionData*) new_part->disk_specific; - - /* ugly, but C is ugly :p */ - memcpy (new_pc98_data, old_pc98_data, sizeof (PC98PartitionData)); - return new_part; -} - -static void -pc98_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) - ped_free (part->disk_specific); - ped_free (part); -} - -static int -pc98_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - PC98PartitionData* pc98_data = part->disk_specific; - - part->fs_type = fs_type; - - pc98_data->system = 0x2062; - if (fs_type) { - if (!strcmp (fs_type->name, "fat16")) { - if (part->geom.length * 512 >= 32 * 1024 * 1024) - pc98_data->system = 0x2021; - else - pc98_data->system = 0x2011; - } else if (!strcmp (fs_type->name, "fat32")) { - pc98_data->system = 0x2061; - } else if (!strcmp (fs_type->name, "ntfs")) { - pc98_data->system = 0x2031; - } else if (!strncmp (fs_type->name, "ufs", 3)) { - pc98_data->system = 0x2044; - } else { /* ext2, reiser, xfs, etc. */ - /* ext2 partitions must be marked boot */ - pc98_data->boot = 1; - pc98_data->system = 0xa062; - } - } - - if (pc98_data->boot) - pc98_data->system |= 0x8000; - if (!pc98_data->hidden) - pc98_data->system |= 0x0080; - return 1; -} - -static int -pc98_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - PC98PartitionData* pc98_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - pc98_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_HIDDEN: - pc98_data->hidden = state; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_BOOT: - pc98_data->boot = state; - return ped_partition_set_system (part, part->fs_type); - - default: - return 0; - } -} - -static int -pc98_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - PC98PartitionData* pc98_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - pc98_data = part->disk_specific; - switch (flag) { - case PED_PARTITION_HIDDEN: - return pc98_data->hidden; - - case PED_PARTITION_BOOT: - return pc98_data->boot; - - default: - return 0; - } -} - -static int -pc98_partition_is_flag_available ( - const PedPartition* part, PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_HIDDEN: - case PED_PARTITION_BOOT: - return 1; - - default: - return 0; - } -} - -static void -pc98_partition_set_name (PedPartition* part, const char* name) -{ - PC98PartitionData* pc98_data; - int i; - - PED_ASSERT (part != NULL, return); - PED_ASSERT (part->disk_specific != NULL, return); - pc98_data = part->disk_specific; - - strncpy (pc98_data->name, name, 16); - pc98_data->name [16] = 0; - for (i = strlen (pc98_data->name) - 1; pc98_data->name[i] == ' '; i--) - pc98_data->name [i] = 0; -} - -static const char* -pc98_partition_get_name (const PedPartition* part) -{ - PC98PartitionData* pc98_data; - - PED_ASSERT (part != NULL, return NULL); - PED_ASSERT (part->disk_specific != NULL, return NULL); - pc98_data = part->disk_specific; - - return pc98_data->name; -} - -static PedConstraint* -_primary_constraint (PedDisk* disk) -{ - PedDevice* dev = disk->dev; - PedAlignment start_align; - PedAlignment end_align; - PedGeometry max_geom; - PedSector cylinder_size; - - cylinder_size = dev->hw_geom.sectors * dev->hw_geom.heads; - - if (!ped_alignment_init (&start_align, 0, cylinder_size)) - return NULL; - if (!ped_alignment_init (&end_align, -1, cylinder_size)) - return NULL; - if (!ped_geometry_init (&max_geom, dev, cylinder_size, - dev->length - cylinder_size)) - return NULL; - - return ped_constraint_new (&start_align, &end_align, &max_geom, - &max_geom, 1, dev->length); -} - -static int -pc98_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - if (_ped_partition_attempt_align (part, constraint, - _primary_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -next_primary (PedDisk* disk) -{ - int i; - for (i=1; i<=MAX_PART_COUNT; i++) { - if (!ped_disk_get_partition (disk, i)) - return i; - } - return 0; -} - -static int -pc98_partition_enumerate (PedPartition* part) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - /* don't re-number a partition */ - if (part->num != -1) - return 1; - - PED_ASSERT (ped_partition_is_active (part), return 0); - - part->num = next_primary (part->disk); - if (!part->num) { - ped_exception_throw (PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Can't add another partition.")); - return 0; - } - - return 1; -} - -static int -pc98_alloc_metadata (PedDisk* disk) -{ - PedPartition* new_part; - PedConstraint* constraint_any = NULL; - PedSector cyl_size; - - PED_ASSERT (disk != NULL, goto error); - PED_ASSERT (disk->dev != NULL, goto error); - - constraint_any = ped_constraint_any (disk->dev); - - cyl_size = disk->dev->hw_geom.sectors * disk->dev->hw_geom.heads; - new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, - 0, cyl_size - 1); - if (!new_part) - goto error; - - if (!ped_disk_add_partition (disk, new_part, constraint_any)) { - ped_partition_destroy (new_part); - goto error; - } - - ped_constraint_destroy (constraint_any); - return 1; - -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static int -pc98_get_max_primary_partition_count (const PedDisk* disk) -{ - return MAX_PART_COUNT; -} - -static PedDiskOps pc98_disk_ops = { - .probe = pc98_probe, -#ifndef DISCOVER_ONLY - .clobber = pc98_clobber, -#else - .clobber = NULL, -#endif - .alloc = pc98_alloc, - .duplicate = pc98_duplicate, - .free = pc98_free, - .read = pc98_read, -#ifndef DISCOVER_ONLY - .write = pc98_write, -#else - .write = NULL, -#endif - - .partition_new = pc98_partition_new, - .partition_duplicate = pc98_partition_duplicate, - .partition_destroy = pc98_partition_destroy, - .partition_set_system = pc98_partition_set_system, - .partition_set_flag = pc98_partition_set_flag, - .partition_get_flag = pc98_partition_get_flag, - .partition_is_flag_available = pc98_partition_is_flag_available, - .partition_set_name = pc98_partition_set_name, - .partition_get_name = pc98_partition_get_name, - .partition_align = pc98_partition_align, - .partition_enumerate = pc98_partition_enumerate, - - .alloc_metadata = pc98_alloc_metadata, - .get_max_primary_partition_count = - pc98_get_max_primary_partition_count -}; - -static PedDiskType pc98_disk_type = { - .next = NULL, - .name = "pc98", - .ops = &pc98_disk_ops, - .features = PED_DISK_TYPE_PARTITION_NAME -}; - -void -ped_disk_pc98_init () -{ - PED_ASSERT (sizeof (PC98RawTable) == 512 * 2, return); - ped_disk_type_register (&pc98_disk_type); -} - -void -ped_disk_pc98_done () -{ - ped_disk_type_unregister (&pc98_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/rdb.c b/usr/src/lib/libparted/common/libparted/labels/rdb.c deleted file mode 100644 index 11ff6795a6..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/rdb.c +++ /dev/null @@ -1,1183 +0,0 @@ -/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - - libparted - a library for manipulating disk partitions - disk_amiga.c - libparted module to manipulate amiga RDB partition tables. - Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - Contributor: Sven Luther -*/ - -#include - -#include -#include -#include - -#ifndef MAX -# define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* String manipulation */ -static void _amiga_set_bstr (const char *cstr, char *bstr, int maxsize) { - int size = strlen (cstr); - int i; - - if (size >= maxsize) return; - bstr[0] = size; - for (i = 0; i"; - default : - return ""; - } -} - -struct AmigaIds { - uint32_t ID; - struct AmigaIds *next; -}; - -static struct AmigaIds * -_amiga_add_id (uint32_t id, struct AmigaIds *ids) { - struct AmigaIds *newid; - - if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) - return 0; - newid->ID = id; - newid->next = ids; - return newid; -} - -static void -_amiga_free_ids (struct AmigaIds *ids) { - struct AmigaIds *current, *next; - - for (current = ids; current != NULL; current = next) { - next = current->next; - ped_free (current); - } -} -static int -_amiga_id_in_list (uint32_t id, struct AmigaIds *ids) { - struct AmigaIds *current; - - for (current = ids; current != NULL; current = current->next) { - if (id == current->ID) - return 1; - } - return 0; -} - -struct AmigaBlock { - uint32_t amiga_ID; /* Identifier 32 bit word */ - uint32_t amiga_SummedLongss; /* Size of the structure for checksums */ - int32_t amiga_ChkSum; /* Checksum of the structure */ -}; -#define AMIGA(pos) ((struct AmigaBlock *)(pos)) - -static int -_amiga_checksum (struct AmigaBlock *blk) { - uint32_t *rdb = (uint32_t *) blk; - uint32_t sum; - int i, end; - - sum = PED_BE32_TO_CPU (rdb[0]); - end = PED_BE32_TO_CPU (rdb[1]); - - if (end > PED_SECTOR_SIZE_DEFAULT) end = PED_SECTOR_SIZE_DEFAULT; - - for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]); - - return sum; -} - -static void -_amiga_calculate_checksum (struct AmigaBlock *blk) { - blk->amiga_ChkSum = PED_CPU_TO_BE32( - PED_BE32_TO_CPU(blk->amiga_ChkSum) - - _amiga_checksum((struct AmigaBlock *) blk)); - return; -} - -static struct AmigaBlock * -_amiga_read_block (const PedDevice *dev, struct AmigaBlock *blk, - PedSector block, struct AmigaIds *ids) -{ - if (!ped_device_read (dev, blk, block, 1)) - return NULL; - if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids)) - return NULL; - if (_amiga_checksum (blk) != 0) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, - _("%s : Bad checksum on block %llu of type %s."), - __func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID)))) - { - case PED_EXCEPTION_CANCEL : - return NULL; - case PED_EXCEPTION_FIX : - _amiga_calculate_checksum(AMIGA(blk)); - if (!ped_device_write ((PedDevice*)dev, blk, block, 1)) - return NULL; - case PED_EXCEPTION_IGNORE : - case PED_EXCEPTION_UNHANDLED : - default : - return blk; - } - } - return blk; -} - -struct RigidDiskBlock { - uint32_t rdb_ID; /* Identifier 32 bit word : 'RDSK' */ - uint32_t rdb_SummedLongs; /* Size of the structure for checksums */ - int32_t rdb_ChkSum; /* Checksum of the structure */ - uint32_t rdb_HostID; /* SCSI Target ID of host, not really used */ - uint32_t rdb_BlockBytes; /* Size of disk blocks */ - uint32_t rdb_Flags; /* RDB Flags */ - /* block list heads */ - uint32_t rdb_BadBlockList; /* Bad block list */ - uint32_t rdb_PartitionList; /* Partition list */ - uint32_t rdb_FileSysHeaderList; /* File system header list */ - uint32_t rdb_DriveInit; /* Drive specific init code */ - uint32_t rdb_BootBlockList; /* Amiga OS 4 Boot Blocks */ - uint32_t rdb_Reserved1[5]; /* Unused word, need to be set to $ffffffff */ - /* physical drive characteristics */ - uint32_t rdb_Cylinders; /* Number of the cylinders of the drive */ - uint32_t rdb_Sectors; /* Number of sectors of the drive */ - uint32_t rdb_Heads; /* Number of heads of the drive */ - uint32_t rdb_Interleave; /* Interleave */ - uint32_t rdb_Park; /* Head parking cylinder */ - uint32_t rdb_Reserved2[3]; /* Unused word, need to be set to $ffffffff */ - uint32_t rdb_WritePreComp; /* Starting cylinder of write precompensation */ - uint32_t rdb_ReducedWrite; /* Starting cylinder of reduced write current */ - uint32_t rdb_StepRate; /* Step rate of the drive */ - uint32_t rdb_Reserved3[5]; /* Unused word, need to be set to $ffffffff */ - /* logical drive characteristics */ - uint32_t rdb_RDBBlocksLo; /* low block of range reserved for hardblocks */ - uint32_t rdb_RDBBlocksHi; /* high block of range for these hardblocks */ - uint32_t rdb_LoCylinder; /* low cylinder of partitionable disk area */ - uint32_t rdb_HiCylinder; /* high cylinder of partitionable data area */ - uint32_t rdb_CylBlocks; /* number of blocks available per cylinder */ - uint32_t rdb_AutoParkSeconds; /* zero for no auto park */ - uint32_t rdb_HighRDSKBlock; /* highest block used by RDSK */ - /* (not including replacement bad blocks) */ - uint32_t rdb_Reserved4; - /* drive identification */ - char rdb_DiskVendor[8]; - char rdb_DiskProduct[16]; - char rdb_DiskRevision[4]; - char rdb_ControllerVendor[8]; - char rdb_ControllerProduct[16]; - char rdb_ControllerRevision[4]; - uint32_t rdb_Reserved5[10]; -}; - -#define RDSK(pos) ((struct RigidDiskBlock *)(pos)) - -#define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff) -#define RDB_LOCATION_LIMIT 16 -#define AMIGA_MAX_PARTITIONS 128 -#define MAX_RDB_BLOCK (RDB_LOCATION_LIMIT + 2 * AMIGA_MAX_PARTITIONS + 2) - -static uint32_t -_amiga_find_rdb (const PedDevice *dev, struct RigidDiskBlock *rdb) { - int i; - struct AmigaIds *ids; - - ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL); - - for (i = 0; irdb_ID) == IDNAME_RIGIDDISK) { - _amiga_free_ids (ids); - return i; - } - } - _amiga_free_ids (ids); - return AMIGA_RDB_NOT_FOUND; -} - -struct PartitionBlock { - uint32_t pb_ID; /* Identifier 32 bit word : 'PART' */ - uint32_t pb_SummedLongs; /* Size of the structure for checksums */ - int32_t pb_ChkSum; /* Checksum of the structure */ - uint32_t pb_HostID; /* SCSI Target ID of host, not really used */ - uint32_t pb_Next; /* Block number of the next PartitionBlock */ - uint32_t pb_Flags; /* Part Flags (NOMOUNT and BOOTABLE) */ - uint32_t pb_Reserved1[2]; - uint32_t pb_DevFlags; /* Preferred flags for OpenDevice */ - char pb_DriveName[32]; /* Preferred DOS device name: BSTR form */ - uint32_t pb_Reserved2[15]; - uint32_t de_TableSize; /* Size of Environment vector */ - /* Size of the blocks in 32 bit words, usually 128 */ - uint32_t de_SizeBlock; - uint32_t de_SecOrg; /* Not used; must be 0 */ - uint32_t de_Surfaces; /* Number of heads (surfaces) */ - /* Disk sectors per block, used with SizeBlock, usually 1 */ - uint32_t de_SectorPerBlock; - uint32_t de_BlocksPerTrack; /* Blocks per track. drive specific */ - uint32_t de_Reserved; /* DOS reserved blocks at start of partition. */ - uint32_t de_PreAlloc; /* DOS reserved blocks at end of partition */ - uint32_t de_Interleave; /* Not used, usually 0 */ - uint32_t de_LowCyl; /* First cylinder of the partition */ - uint32_t de_HighCyl; /* Last cylinder of the partition */ - uint32_t de_NumBuffers; /* Initial # DOS of buffers. */ - uint32_t de_BufMemType; /* Type of mem to allocate for buffers */ - uint32_t de_MaxTransfer; /* Max number of bytes to transfer at a time */ - uint32_t de_Mask; /* Address Mask to block out certain memory */ - int32_t de_BootPri; /* Boot priority for autoboot */ - uint32_t de_DosType; /* Dostype of the file system */ - uint32_t de_Baud; /* Baud rate for serial handler */ - uint32_t de_Control; /* Control word for handler/filesystem */ - uint32_t de_BootBlocks; /* Number of blocks containing boot code */ - uint32_t pb_EReserved[12]; -}; - -#define PART(pos) ((struct PartitionBlock *)(pos)) - -#define PBFB_BOOTABLE 0 /* this partition is intended to be bootable */ -#define PBFF_BOOTABLE 1L /* (expected directories and files exist) */ -#define PBFB_NOMOUNT 1 /* do not mount this partition (e.g. manually */ -#define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */ -#define PBFB_RAID 2 /* this partition is intended to be part of */ -#define PBFF_RAID 4L /* a RAID array */ -#define PBFB_LVM 3 /* this partition is intended to be part of */ -#define PBFF_LVM 8L /* a LVM volume group */ - - -struct LinkedBlock { - uint32_t lk_ID; /* Identifier 32 bit word */ - uint32_t lk_SummedLongs; /* Size of the structure for checksums */ - int32_t lk_ChkSum; /* Checksum of the structure */ - uint32_t pb_HostID; /* SCSI Target ID of host, not really used */ - uint32_t lk_Next; /* Block number of the next PartitionBlock */ -}; -struct Linked2Block { - uint32_t lk2_ID; /* Identifier 32 bit word */ - uint32_t lk2_SummedLongs; /* Size of the structure for checksums */ - int32_t lk2_ChkSum; /* Checksum of the structure */ - uint32_t lk2_HostID; /* SCSI Target ID of host, not really used */ - uint32_t lk2_Next; /* Block number of the next PartitionBlock */ - uint32_t lk2_Reverved[13]; - uint32_t lk2_Linked; /* Secondary linked list */ -}; -#define LINK_END (uint32_t)0xffffffff -#define LNK(pos) ((struct LinkedBlock *)(pos)) -#define LNK2(pos) ((struct Linked2Block *)(pos)) - - -static PedDiskType amiga_disk_type; - -static int -amiga_probe (const PedDevice *dev) -{ - struct RigidDiskBlock *rdb; - uint32_t found; - PED_ASSERT(dev != NULL, return 0); - - if ((rdb=RDSK(ped_malloc(dev->sector_size)))==NULL) - return 0; - found = _amiga_find_rdb (dev, rdb); - ped_free (rdb); - - return (found == AMIGA_RDB_NOT_FOUND ? 0 : 1); -} - -static PedDisk* -amiga_alloc (const PedDevice* dev) -{ - PedDisk *disk; - struct RigidDiskBlock *rdb; - PedSector cyl_size; - int highest_cylinder, highest_block; - - PED_ASSERT(dev != NULL, return NULL); - cyl_size = dev->hw_geom.sectors * dev->hw_geom.heads; - - if (!(disk = _ped_disk_alloc (dev, &amiga_disk_type))) - return NULL; - - if (!(disk->disk_specific = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { - ped_free (disk); - return NULL; - } - rdb = disk->disk_specific; - - memset(rdb, 0, sizeof(struct RigidDiskBlock)); - - rdb->rdb_ID = PED_CPU_TO_BE32 (IDNAME_RIGIDDISK); - rdb->rdb_SummedLongs = PED_CPU_TO_BE32 (64); - rdb->rdb_HostID = PED_CPU_TO_BE32 (0); - rdb->rdb_BlockBytes = PED_CPU_TO_BE32 (PED_SECTOR_SIZE_DEFAULT); - rdb->rdb_Flags = PED_CPU_TO_BE32 (0); - - /* Block lists */ - rdb->rdb_BadBlockList = PED_CPU_TO_BE32 (LINK_END); - rdb->rdb_PartitionList = PED_CPU_TO_BE32 (LINK_END); - rdb->rdb_FileSysHeaderList = PED_CPU_TO_BE32 (LINK_END); - rdb->rdb_DriveInit = PED_CPU_TO_BE32 (LINK_END); - rdb->rdb_BootBlockList = PED_CPU_TO_BE32 (LINK_END); - - /* Physical drive characteristics */ - rdb->rdb_Cylinders = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); - rdb->rdb_Sectors = PED_CPU_TO_BE32 (dev->hw_geom.sectors); - rdb->rdb_Heads = PED_CPU_TO_BE32 (dev->hw_geom.heads); - rdb->rdb_Interleave = PED_CPU_TO_BE32 (0); - rdb->rdb_Park = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); - rdb->rdb_WritePreComp = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); - rdb->rdb_ReducedWrite = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); - rdb->rdb_StepRate = PED_CPU_TO_BE32 (0); - - highest_cylinder = 1 + MAX_RDB_BLOCK / cyl_size; - highest_block = highest_cylinder * cyl_size - 1; - - /* Logical driver characteristics */ - rdb->rdb_RDBBlocksLo = PED_CPU_TO_BE32 (0); - rdb->rdb_RDBBlocksHi = PED_CPU_TO_BE32 (highest_block); - rdb->rdb_LoCylinder = PED_CPU_TO_BE32 (highest_cylinder); - rdb->rdb_HiCylinder = PED_CPU_TO_BE32 (dev->hw_geom.cylinders -1); - rdb->rdb_CylBlocks = PED_CPU_TO_BE32 (cyl_size); - rdb->rdb_AutoParkSeconds = PED_CPU_TO_BE32 (0); - /* rdb_HighRDSKBlock will only be set when writing */ - rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32 (0); - - /* Driver identification */ - _amiga_set_bstr("", rdb->rdb_DiskVendor, 8); - _amiga_set_bstr(dev->model, rdb->rdb_DiskProduct, 16); - _amiga_set_bstr("", rdb->rdb_DiskRevision, 4); - _amiga_set_bstr("", rdb->rdb_ControllerVendor, 8); - _amiga_set_bstr("", rdb->rdb_ControllerProduct, 16); - _amiga_set_bstr("", rdb->rdb_ControllerRevision, 4); - - /* And calculate the checksum */ - _amiga_calculate_checksum ((struct AmigaBlock *) rdb); - - return disk; -} - -static PedDisk* -amiga_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - struct RigidDiskBlock * new_rdb; - struct RigidDiskBlock * old_rdb; - PED_ASSERT(disk != NULL, return NULL); - PED_ASSERT(disk->dev != NULL, return NULL); - PED_ASSERT(disk->disk_specific != NULL, return NULL); - - old_rdb = (struct RigidDiskBlock *) disk->disk_specific; - - if (!(new_disk = ped_disk_new_fresh (disk->dev, &amiga_disk_type))) - return NULL; - - new_rdb = (struct RigidDiskBlock *) new_disk->disk_specific; - memcpy (new_rdb, old_rdb, 256); - return new_disk; -} - -static void -amiga_free (PedDisk* disk) -{ - PED_ASSERT(disk != NULL, return); - PED_ASSERT(disk->disk_specific != NULL, return); - - ped_free (disk->disk_specific); - _ped_disk_free (disk); -} - -#ifndef DISCOVER_ONLY -static int -amiga_clobber (PedDevice* dev) -{ - struct RigidDiskBlock *rdb; - uint32_t i; - int result = 0; - PED_ASSERT(dev != NULL, return 0); - - if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE_DEFAULT)))==NULL) - return 0; - - while ((i = _amiga_find_rdb (dev, rdb)) != AMIGA_RDB_NOT_FOUND) { - rdb->rdb_ID = PED_CPU_TO_BE32 (0); - result = ped_device_write (dev, (void*) rdb, i, 1); - } - - ped_free (rdb); - - return result; -} -#endif /* !DISCOVER_ONLY */ - -static int -_amiga_loop_check (uint32_t block, uint32_t * blocklist, uint32_t max) -{ - uint32_t i; - - for (i = 0; i < max; i++) - if (block == blocklist[i]) { - /* We are looping, let's stop. */ - return 1; - } - blocklist[max] = block; - return 0; -} - -/* We have already allocated a rdb, we are now reading it from the disk */ -static int -amiga_read (PedDisk* disk) -{ - struct RigidDiskBlock *rdb; - struct PartitionBlock *partition; - uint32_t partblock; - uint32_t partlist[AMIGA_MAX_PARTITIONS]; - PedSector cylblocks; - int i; - - PED_ASSERT(disk != NULL, return 0); - PED_ASSERT(disk->dev != NULL, return 0); - PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, - return 0); - PED_ASSERT(disk->disk_specific != NULL, return 0); - rdb = RDSK(disk->disk_specific); - - if (_amiga_find_rdb (disk->dev, rdb) == AMIGA_RDB_NOT_FOUND) { - ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("%s : Didn't find rdb block, should never happen."), __func__); - return 0; - } - - /* Let's copy the rdb read geometry to the dev */ - /* FIXME: should this go into disk->dev->bios_geom instead? */ - disk->dev->hw_geom.cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders); - disk->dev->hw_geom.heads = PED_BE32_TO_CPU (rdb->rdb_Heads); - disk->dev->hw_geom.sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors); - cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) * - (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors); - - /* Remove all partitions in the former in memory table */ - ped_disk_delete_all (disk); - - /* Let's allocate a partition block */ - if (!(partition = ped_malloc (disk->dev->sector_size))) - return 0; - - /* We initialize the hardblock free list to detect loops */ - for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = LINK_END; - - for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList); - i < AMIGA_MAX_PARTITIONS && partblock != LINK_END; - i++, partblock = PED_BE32_TO_CPU(partition->pb_Next)) - { - PedPartition *part; - PedSector start, end; - PedConstraint *constraint_exact; - - /* Let's look for loops in the partition table */ - if (_amiga_loop_check(partblock, partlist, i)) { - break; - } - - /* Let's allocate and read a partition block to get its geometry*/ - if (!_amiga_read_block (disk->dev, AMIGA(partition), - (PedSector)partblock, NULL)) { - ped_free(partition); - return 0; - } - - start = ((PedSector) PED_BE32_TO_CPU (partition->de_LowCyl)) - * cylblocks; - end = (((PedSector) PED_BE32_TO_CPU (partition->de_HighCyl)) - + 1) * cylblocks - 1; - - /* We can now construct a new partition */ - if (!(part = ped_partition_new (disk, 0, NULL, start, end))) { - ped_free(partition); - return 0; - } - /* And copy over the partition block */ - memcpy(part->disk_specific, partition, 256); - - part->num = i; - part->type = 0; - /* Let's probe what file system is present on the disk */ - part->fs_type = ped_file_system_probe (&part->geom); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) { - ped_partition_destroy(part); - ped_free(partition); - return 0; - } - ped_constraint_destroy (constraint_exact); - } - ped_free(partition); - return 1; -} - -static int -_amiga_find_free_blocks(const PedDisk *disk, uint32_t *table, - struct LinkedBlock *block, uint32_t first, uint32_t type) -{ - PedSector next; - - PED_ASSERT(disk != NULL, return 0); - PED_ASSERT(disk->dev != NULL, return 0); - - for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) { - if (table[next] != IDNAME_FREE) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, - _("%s : Loop detected at block %d."), __func__, next)) - { - case PED_EXCEPTION_CANCEL : - return 0; - case PED_EXCEPTION_FIX : - /* TODO : Need to add fixing code */ - case PED_EXCEPTION_IGNORE : - case PED_EXCEPTION_UNHANDLED : - default : - return 1; - } - } - - if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) { - return 0; - } - if (PED_BE32_TO_CPU(block->lk_ID) != type) { - switch (ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : The %s list seems bad at block %s."), - __func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next)) - { - /* TODO : to more subtile things here */ - case PED_EXCEPTION_CANCEL : - case PED_EXCEPTION_UNHANDLED : - default : - return 0; - } - } - table[next] = type; - if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) { - if (_amiga_find_free_blocks(disk, table, block, - PED_BE32_TO_CPU(LNK2(block)->lk2_Linked), - IDNAME_LOADSEG) == 0) return 0; - } - } - return 1; -} -static uint32_t -_amiga_next_free_block(uint32_t *table, uint32_t start, uint32_t type) { - int i; - - for (i = start; table[i] != type && table[i] != IDNAME_FREE; i++); - return i; -} -static PedPartition * -_amiga_next_real_partition(const PedDisk *disk, PedPartition *part) { - PedPartition *next; - - for (next = ped_disk_next_partition (disk, part); - next != NULL && !ped_partition_is_active (next); - next = ped_disk_next_partition (disk, next)); - return next; -} -#ifndef DISCOVER_ONLY -static int -amiga_write (const PedDisk* disk) -{ - struct RigidDiskBlock *rdb; - struct LinkedBlock *block; - struct PartitionBlock *partition; - PedPartition *part, *next_part; - PedSector cylblocks, first_hb, last_hb, last_used_hb; - uint32_t * table; - uint32_t i; - uint32_t rdb_num, part_num, block_num, next_num; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - PED_ASSERT (disk->disk_specific != NULL, return 0); - - if (!(rdb = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) - return 0; - - /* Let's read the rdb */ - if ((rdb_num = _amiga_find_rdb (disk->dev, rdb)) == AMIGA_RDB_NOT_FOUND) { - rdb_num = 2; - size_t pb_size = sizeof (struct PartitionBlock); - /* Initialize only the part that won't be copied over - with a partition block in amiga_read. */ - memset ((char *)(RDSK(disk->disk_specific)) + pb_size, - 0, PED_SECTOR_SIZE_DEFAULT - pb_size); - } else { - memcpy (RDSK(disk->disk_specific), rdb, PED_SECTOR_SIZE_DEFAULT); - } - ped_free (rdb); - rdb = RDSK(disk->disk_specific); - - cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) * - (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors); - first_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksLo); - last_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksHi); - last_used_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock); - - /* Allocate a free block table and initialize it. - There must be room for at least RDB_NUM + 2 entries, since - the first RDB_NUM+1 entries get IDNAME_RIGIDDISK, and the - following one must have LINK_END to serve as sentinel. */ - size_t tab_size = 2 + MAX (last_hb - first_hb, rdb_num); - if (!(table = ped_malloc (tab_size * sizeof *table))) - return 0; - - for (i = 0; i <= rdb_num; i++) - table[i] = IDNAME_RIGIDDISK; - for ( ; i < tab_size; i++) - table[i] = LINK_END; - - /* Let's allocate a partition block */ - if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { - ped_free (table); - return 0; - } - - /* And fill the free block table */ - if (_amiga_find_free_blocks(disk, table, block, - PED_BE32_TO_CPU (rdb->rdb_BadBlockList), IDNAME_BADBLOCK) == 0) - { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to list bad blocks."), __func__); - goto error_free_table; - } - if (_amiga_find_free_blocks(disk, table, block, - PED_BE32_TO_CPU (rdb->rdb_PartitionList), IDNAME_PARTITION) == 0) - { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to list partition blocks."), __func__); - goto error_free_table; - } - if (_amiga_find_free_blocks(disk, table, block, - PED_BE32_TO_CPU (rdb->rdb_FileSysHeaderList), IDNAME_FILESYSHEADER) == 0) - { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to list file system blocks."), __func__); - goto error_free_table; - } - if (_amiga_find_free_blocks(disk, table, block, - PED_BE32_TO_CPU (rdb->rdb_BootBlockList), IDNAME_BOOT) == 0) - { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("%s : Failed to list boot blocks."), __func__); - goto error_free_table; - } - - block_num = next_num = part_num = _amiga_next_free_block(table, rdb_num+1, - IDNAME_PARTITION); - part = _amiga_next_real_partition(disk, NULL); - rdb->rdb_PartitionList = PED_CPU_TO_BE32(part ? part_num : LINK_END); - for (; part != NULL; part = next_part, block_num = next_num) { - PED_ASSERT(part->disk_specific != NULL, return 0); - PED_ASSERT(part->geom.start % cylblocks == 0, return 0); - PED_ASSERT((part->geom.end + 1) % cylblocks == 0, return 0); - - next_part = _amiga_next_real_partition(disk, part); - next_num = _amiga_next_free_block(table, block_num+1, IDNAME_PARTITION); - - partition = PART(part->disk_specific); - if (next_part == NULL) - partition->pb_Next = PED_CPU_TO_BE32(LINK_END); - else - partition->pb_Next = PED_CPU_TO_BE32(next_num); - partition->de_LowCyl = PED_CPU_TO_BE32(part->geom.start/cylblocks); - partition->de_HighCyl = PED_CPU_TO_BE32((part->geom.end+1)/cylblocks-1); - _amiga_calculate_checksum(AMIGA(partition)); - if (!ped_device_write (disk->dev, (void*) partition, block_num, 1)) { - ped_exception_throw(PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Failed to write partition block at %d."), - block_num); - goto error_free_table; - /* WARNING : If we fail here, we stop everything, - * and the partition table is lost. A better - * solution should be found, using the second - * half of the hardblocks to not overwrite the - * old partition table. It becomes problematic - * if we use more than half of the hardblocks. */ - } - } - - if (block_num > PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock)) - rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32(block_num); - - _amiga_calculate_checksum(AMIGA(rdb)); - if (!ped_device_write (disk->dev, (void*) disk->disk_specific, rdb_num, 1)) - goto error_free_table; - - ped_free (table); - ped_free (block); - return ped_device_sync (disk->dev); - -error_free_table: - ped_free (table); - ped_free (block); - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -amiga_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition *part; - PedDevice *dev; - PedSector cyl; - struct PartitionBlock *partition; - struct RigidDiskBlock *rdb; - - PED_ASSERT(disk != NULL, return NULL); - PED_ASSERT(disk->dev != NULL, return NULL); - PED_ASSERT(disk->disk_specific != NULL, return NULL); - dev = disk->dev; - cyl = (PedSector) (dev->hw_geom.sectors * dev->hw_geom.heads); - rdb = RDSK(disk->disk_specific); - - if (!(part = _ped_partition_alloc (disk, part_type, fs_type, start, end))) - return NULL; - - if (ped_partition_is_active (part)) { - if (!(part->disk_specific = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { - ped_free (part); - return NULL; - } - partition = PART(part->disk_specific); - memset(partition, 0, sizeof(struct PartitionBlock)); - - partition->pb_ID = PED_CPU_TO_BE32(IDNAME_PARTITION); - partition->pb_SummedLongs = PED_CPU_TO_BE32(64); - partition->pb_HostID = rdb->rdb_HostID; - partition->pb_Flags = PED_CPU_TO_BE32(0); - /* TODO : use a scheme including the device name and the - * partition number, if it is possible */ - _amiga_set_bstr("dhx", partition->pb_DriveName, 32); - - partition->de_TableSize = PED_CPU_TO_BE32(19); - partition->de_SizeBlock = PED_CPU_TO_BE32(128); - partition->de_SecOrg = PED_CPU_TO_BE32(0); - partition->de_Surfaces = PED_CPU_TO_BE32(dev->hw_geom.heads); - partition->de_SectorPerBlock = PED_CPU_TO_BE32(1); - partition->de_BlocksPerTrack - = PED_CPU_TO_BE32(dev->hw_geom.sectors); - partition->de_Reserved = PED_CPU_TO_BE32(2); - partition->de_PreAlloc = PED_CPU_TO_BE32(0); - partition->de_Interleave = PED_CPU_TO_BE32(0); - partition->de_LowCyl = PED_CPU_TO_BE32(start/cyl); - partition->de_HighCyl = PED_CPU_TO_BE32((end+1)/cyl-1); - partition->de_NumBuffers = PED_CPU_TO_BE32(30); - partition->de_BufMemType = PED_CPU_TO_BE32(0); - partition->de_MaxTransfer = PED_CPU_TO_BE32(0x7fffffff); - partition->de_Mask = PED_CPU_TO_BE32(0xffffffff); - partition->de_BootPri = PED_CPU_TO_BE32(0); - partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); - partition->de_Baud = PED_CPU_TO_BE32(0); - partition->de_Control = PED_CPU_TO_BE32(0); - partition->de_BootBlocks = PED_CPU_TO_BE32(0); - - } else { - part->disk_specific = NULL; - } - return part; -} - -static PedPartition* -amiga_partition_duplicate (const PedPartition* part) -{ - PedPartition *new_part; - struct PartitionBlock *new_amiga_part; - struct PartitionBlock *old_amiga_part; - - PED_ASSERT(part != NULL, return NULL); - PED_ASSERT(part->disk != NULL, return NULL); - PED_ASSERT(part->disk_specific != NULL, return NULL); - old_amiga_part = (struct PartitionBlock *) part->disk_specific; - - new_part = ped_partition_new (part->disk, part->type, - part->fs_type, part->geom.start, - part->geom.end); - if (!new_part) - return NULL; - - new_amiga_part = (struct PartitionBlock *) new_part->disk_specific; - memcpy (new_amiga_part, old_amiga_part, 256); - - return new_part; -} - -static void -amiga_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) { - PED_ASSERT (part->disk_specific != NULL, return); - ped_free (part->disk_specific); - } - _ped_partition_free (part); -} - -static int -amiga_partition_set_system (PedPartition* part, - const PedFileSystemType* fs_type) -{ - struct PartitionBlock *partition; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - partition = PART(part->disk_specific); - - part->fs_type = fs_type; - - if (!fs_type) - partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ - else if (!strcmp (fs_type->name, "ext2")) - partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ - else if (!strcmp (fs_type->name, "ext3")) - partition->de_DosType = PED_CPU_TO_BE32(0x45585403); /* 'EXT\3' */ - else if (!strcmp (fs_type->name, "linux-swap")) - partition->de_DosType = PED_CPU_TO_BE32(0x53575000); /* 'SWP\0' */ - else if (!strcmp (fs_type->name, "fat16")) - partition->de_DosType = PED_CPU_TO_BE32(0x46415400); /* 'FAT\0' */ - else if (!strcmp (fs_type->name, "fat32")) - partition->de_DosType = PED_CPU_TO_BE32(0x46415401); /* 'FAT\1'*/ - else if (!strcmp (fs_type->name, "hfs")) - partition->de_DosType = PED_CPU_TO_BE32(0x48465300); /* 'HFS\0' */ - else if (!strcmp (fs_type->name, "jfs")) - partition->de_DosType = PED_CPU_TO_BE32(0x4a465300); /* 'JFS\0' */ - else if (!strcmp (fs_type->name, "ntfs")) - partition->de_DosType = PED_CPU_TO_BE32(0x4e544653); /* 'NTFS' */ - else if (!strcmp (fs_type->name, "reiserfs")) - partition->de_DosType = PED_CPU_TO_BE32(0x52465300); /* 'RFS\0' */ - else if (!strcmp (fs_type->name, "sun-ufs")) - partition->de_DosType = PED_CPU_TO_BE32(0x53554653); /* 'SUFS' */ - else if (!strcmp (fs_type->name, "hp-ufs")) - partition->de_DosType = PED_CPU_TO_BE32(0x48554653); /* 'HUFS' */ - else if (!strcmp (fs_type->name, "xfs")) - partition->de_DosType = PED_CPU_TO_BE32(0x58465300); /* 'XFS\0' */ - else - partition->de_DosType = PED_CPU_TO_BE32(0x00000000); /* unknown */ - return 1; -} - -static int -amiga_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - struct PartitionBlock *partition; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - partition = PART(part->disk_specific); - - switch (flag) { - case PED_PARTITION_BOOT: - if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_BOOTABLE); - else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_BOOTABLE)); - return 1; - case PED_PARTITION_HIDDEN: - if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_NOMOUNT); - else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_NOMOUNT)); - return 1; - case PED_PARTITION_RAID: - if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_RAID); - else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_RAID)); - return 1; - case PED_PARTITION_LVM: - if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_LVM); - else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_LVM)); - return 1; - default: - return 0; - } -} - -static int -amiga_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - struct PartitionBlock *partition; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - partition = PART(part->disk_specific); - - switch (flag) { - case PED_PARTITION_BOOT: - return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_BOOTABLE)); - case PED_PARTITION_HIDDEN: - return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_NOMOUNT)); - case PED_PARTITION_RAID: - return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_RAID)); - case PED_PARTITION_LVM: - return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_LVM)); - default: - return 0; - } -} - -static int -amiga_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_BOOT: - case PED_PARTITION_HIDDEN: - case PED_PARTITION_RAID: - case PED_PARTITION_LVM: - return 1; - default: - return 0; - } -} - -static void -amiga_partition_set_name (PedPartition* part, const char* name) -{ - struct PartitionBlock *partition; - - PED_ASSERT (part != NULL, return); - PED_ASSERT (part->disk_specific != NULL, return); - - partition = PART(part->disk_specific); - _amiga_set_bstr(name, partition->pb_DriveName, 32); -} -static const char* -amiga_partition_get_name (const PedPartition* part) -{ - struct PartitionBlock *partition; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - partition = PART(part->disk_specific); - - return _amiga_get_bstr(partition->pb_DriveName); -} - -static PedConstraint* -_amiga_get_constraint (const PedDisk *disk) -{ - PedDevice *dev = disk->dev; - PedAlignment start_align, end_align; - PedGeometry max_geom; - PedSector cyl_size = dev->hw_geom.sectors * dev->hw_geom.heads; - - if (!ped_alignment_init(&start_align, 0, cyl_size)) - return NULL; - if (!ped_alignment_init(&end_align, -1, cyl_size)) - return NULL; - if (!ped_geometry_init(&max_geom, dev, MAX_RDB_BLOCK + 1, - dev->length - MAX_RDB_BLOCK - 1)) - return NULL; - - return ped_constraint_new (&start_align, &end_align, - &max_geom, &max_geom, 1, dev->length); -} - -static int -amiga_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - if (_ped_partition_attempt_align (part, constraint, - _amiga_get_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -amiga_partition_enumerate (PedPartition* part) -{ - int i; - PedPartition* p; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk != NULL, return 0); - - /* never change the partition numbers */ - if (part->num != -1) - return 1; - for (i = 1; i <= AMIGA_MAX_PARTITIONS; i++) { - p = ped_disk_get_partition (part->disk, i); - if (!p) { - part->num = i; - return 1; - } - } - - /* failed to allocate a number */ -#ifndef DISCOVER_ONLY - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Unable to allocate a partition number.")); -#endif - return 0; -} - -static int -amiga_alloc_metadata (PedDisk* disk) -{ - PedPartition* new_part; - PedConstraint* constraint_any = NULL; - - PED_ASSERT (disk != NULL, goto error); - PED_ASSERT (disk->dev != NULL, goto error); - - constraint_any = ped_constraint_any (disk->dev); - - /* Allocate space for the RDB */ - new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, - 0, MAX_RDB_BLOCK); - if (!new_part) - goto error; - - if (!ped_disk_add_partition (disk, new_part, constraint_any)) { - ped_partition_destroy (new_part); - goto error; - } - - ped_constraint_destroy (constraint_any); - return 1; -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static int -amiga_get_max_primary_partition_count (const PedDisk* disk) -{ - return AMIGA_MAX_PARTITIONS; -} - -static PedDiskOps amiga_disk_ops = { - .probe = amiga_probe, -#ifndef DISCOVER_ONLY - .clobber = amiga_clobber, -#else - .clobber = NULL, -#endif - .alloc = amiga_alloc, - .duplicate = amiga_duplicate, - .free = amiga_free, - .read = amiga_read, -#ifndef DISCOVER_ONLY - .write = amiga_write, -#else - .write = NULL, -#endif - - .partition_new = amiga_partition_new, - .partition_duplicate = amiga_partition_duplicate, - .partition_destroy = amiga_partition_destroy, - .partition_set_system = amiga_partition_set_system, - .partition_set_flag = amiga_partition_set_flag, - .partition_get_flag = amiga_partition_get_flag, - .partition_is_flag_available = - amiga_partition_is_flag_available, - .partition_set_name = amiga_partition_set_name, - .partition_get_name = amiga_partition_get_name, - .partition_align = amiga_partition_align, - .partition_enumerate = amiga_partition_enumerate, - - - .alloc_metadata = amiga_alloc_metadata, - .get_max_primary_partition_count = - amiga_get_max_primary_partition_count -}; - -static PedDiskType amiga_disk_type = { - .next = NULL, - .name = "amiga", - .ops = &amiga_disk_ops, - .features = PED_DISK_TYPE_PARTITION_NAME -}; - -void -ped_disk_amiga_init () -{ - PED_ASSERT (sizeof (struct AmigaBlock) != 3, return); - PED_ASSERT (sizeof (struct RigidDiskBlock) != 64, return); - PED_ASSERT (sizeof (struct PartitionBlock) != 64, return); - PED_ASSERT (sizeof (struct LinkedBlock) != 5, return); - PED_ASSERT (sizeof (struct Linked2Block) != 18, return); - - ped_disk_type_register (&amiga_disk_type); -} - -void -ped_disk_amiga_done () -{ - ped_disk_type_unregister (&amiga_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/labels/sun.c b/usr/src/lib/libparted/common/libparted/labels/sun.c deleted file mode 100644 index 50e8be2e9a..0000000000 --- a/usr/src/lib/libparted/common/libparted/labels/sun.c +++ /dev/null @@ -1,868 +0,0 @@ -/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - - libparted - a library for manipulating disk partitions - Copyright (C) 2000, 2001, 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - Contributor: Ben Collins -*/ - -#include - -#include -#include -#include - -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -/* Most of this came from util-linux's sun support, which was mostly done - by Jakub Jelinek. */ - -#define SUN_DISK_MAGIC 0xDABE /* Disk magic number */ -#define SUN_DISK_MAXPARTITIONS 8 - -#define WHOLE_DISK_ID 0x05 -#define WHOLE_DISK_PART 2 /* as in 0, 1, 2 (3rd partition) */ -#define LINUX_SWAP_ID 0x82 - -typedef struct _SunRawPartition SunRawPartition; -typedef struct _SunPartitionInfo SunPartitionInfo; -typedef struct _SunRawLabel SunRawLabel; -typedef struct _SunPartitionData SunPartitionData; -typedef struct _SunDiskData SunDiskData; - -#if defined(__sun) -typedef uint8_t u_int8_t; -typedef uint16_t u_int16_t; -typedef uint32_t u_int32_t; -#endif - -#ifdef __sun -#define __attribute__(X) /*nothing*/ -#endif /* __sun */ - -#ifdef __sun -#pragma pack(1) -#endif -struct __attribute__ ((packed)) _SunRawPartition { - u_int32_t start_cylinder; /* where the part starts... */ - u_int32_t num_sectors; /* ...and it's length */ -}; - -struct __attribute__ ((packed)) _SunPartitionInfo { - u_int8_t spare1; - u_int8_t id; /* Partition type */ - u_int8_t spare2; - u_int8_t flags; /* Partition flags */ -}; - -struct __attribute__ ((packed)) _SunRawLabel { - char info[128]; /* Informative text string */ - u_int8_t spare0[14]; - SunPartitionInfo infos[SUN_DISK_MAXPARTITIONS]; - u_int8_t spare1[246]; /* Boot information etc. */ - u_int16_t rspeed; /* Disk rotational speed */ - u_int16_t pcylcount; /* Physical cylinder count */ - u_int16_t sparecyl; /* extra sects per cylinder */ - u_int8_t spare2[4]; /* More magic... */ - u_int16_t ilfact; /* Interleave factor */ - u_int16_t ncyl; /* Data cylinder count */ - u_int16_t nacyl; /* Alt. cylinder count */ - u_int16_t ntrks; /* Tracks per cylinder */ - u_int16_t nsect; /* Sectors per track */ - u_int8_t spare3[4]; /* Even more magic... */ - SunRawPartition partitions[SUN_DISK_MAXPARTITIONS]; - u_int16_t magic; /* Magic number */ - u_int16_t csum; /* Label xor'd checksum */ -}; -#ifdef __sun -#pragma pack() -#endif - -struct _SunPartitionData { - u_int8_t type; - int is_boot; - int is_root; - int is_lvm; -}; - -struct _SunDiskData { - PedSector length; /* This is based on cyl - alt-cyl */ - SunRawLabel raw_label; -}; - -static PedDiskType sun_disk_type; - -/* Checksum computation */ -static void -sun_compute_checksum (SunRawLabel *label) -{ - u_int16_t *ush = (u_int16_t *)label; - u_int16_t csum = 0; - - while(ush < (u_int16_t *)(&label->csum)) - csum ^= *ush++; - label->csum = csum; -} - -/* Checksum Verification */ -static int -sun_verify_checksum (SunRawLabel *label) -{ - u_int16_t *ush = ((u_int16_t *)(label + 1)) - 1; - u_int16_t csum = 0; - - while (ush >= (u_int16_t *)label) - csum ^= *ush--; - - return !csum; -} - -static int -sun_probe (const PedDevice *dev) -{ - SunRawLabel label; - - PED_ASSERT (dev != NULL, return 0); - - if (dev->sector_size != 512) - return 0; - - if (!ped_device_read (dev, &label, 0, 1)) - return 0; - - /* check magic */ - if (PED_BE16_TO_CPU (label.magic) != SUN_DISK_MAGIC) - return 0; - -#ifndef DISCOVER_ONLY - if (!sun_verify_checksum(&label)) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Corrupted Sun disk label detected.")); - return 0; - } -#endif - - return 1; -} - -#ifndef DISCOVER_ONLY -static int -sun_clobber (PedDevice* dev) -{ - SunRawLabel label; - - PED_ASSERT (dev != NULL, return 0); - PED_ASSERT (sun_probe (dev), return 0); - - if (!ped_device_read (dev, &label, 0, 1)) - return 0; - - label.magic = 0; - return ped_device_write (dev, &label, 0, 1); -} -#endif /* !DISCOVER_ONLY */ - -static PedDisk* -sun_alloc (const PedDevice* dev) -{ - PedDisk* disk; - SunRawLabel* label; - SunDiskData* sun_specific; - PedCHSGeometry* bios_geom = &((PedDevice*)dev)->bios_geom; - PedSector cyl_size = bios_geom->sectors * bios_geom->heads; - - disk = _ped_disk_alloc (dev, &sun_disk_type); - if (!disk) - goto error; - - disk->disk_specific = (SunDiskData*) ped_malloc (sizeof (SunDiskData)); - if (!disk->disk_specific) - goto error_free_disk; - sun_specific = (SunDiskData*) disk->disk_specific; - - bios_geom->cylinders = dev->length / cyl_size; - sun_specific->length = bios_geom->cylinders * cyl_size; - - label = &sun_specific->raw_label; - memset(label, 0, sizeof(SunRawLabel)); - - /* #gentoo-sparc people agree that nacyl = 0 is the best option */ - label->magic = PED_CPU_TO_BE16 (SUN_DISK_MAGIC); - label->nacyl = 0; - label->pcylcount = PED_CPU_TO_BE16 (bios_geom->cylinders); - label->rspeed = PED_CPU_TO_BE16 (5400); - label->ilfact = PED_CPU_TO_BE16 (1); - label->sparecyl = 0; - label->ntrks = PED_CPU_TO_BE16 (bios_geom->heads); - label->nsect = PED_CPU_TO_BE16 (bios_geom->sectors); - label->ncyl = PED_CPU_TO_BE16 (bios_geom->cylinders - 0); - - /* Add a whole disk partition at a minimum */ - label->infos[WHOLE_DISK_PART].id = WHOLE_DISK_ID; - label->partitions[WHOLE_DISK_PART].start_cylinder = 0; - label->partitions[WHOLE_DISK_PART].num_sectors = - PED_CPU_TO_BE32(bios_geom->cylinders * cyl_size); - - /* Now a neato string to describe this label */ - snprintf(label->info, sizeof(label->info) - 1, - "GNU Parted Custom cyl %d alt %d hd %d sec %d", - PED_BE16_TO_CPU(label->ncyl), - PED_BE16_TO_CPU(label->nacyl), - PED_BE16_TO_CPU(label->ntrks), - PED_BE16_TO_CPU(label->nsect)); - - sun_compute_checksum(label); - return disk; - -error_free_disk: - _ped_disk_free (disk); -error: - return NULL; -} - -static PedDisk* -sun_duplicate (const PedDisk* disk) -{ - PedDisk* new_disk; - SunDiskData* new_sun_data; - SunDiskData* old_sun_data = (SunDiskData*) disk->disk_specific; - - new_disk = ped_disk_new_fresh (disk->dev, &sun_disk_type); - if (!new_disk) - return NULL; - - new_sun_data = (SunDiskData*) new_disk->disk_specific; - memcpy (new_sun_data, old_sun_data, sizeof (SunDiskData)); - return new_disk; -} - -static void -sun_free (PedDisk *disk) -{ - ped_free (disk->disk_specific); - _ped_disk_free (disk); -} - -static int -_check_geometry_sanity (PedDisk* disk, SunRawLabel* label) -{ - PedDevice* dev = disk->dev; - - if (PED_BE16_TO_CPU(label->nsect) == dev->hw_geom.sectors && - PED_BE16_TO_CPU(label->ntrks) == dev->hw_geom.heads) - dev->bios_geom = dev->hw_geom; - - if (PED_BE16_TO_CPU(label->nsect) != dev->bios_geom.sectors || - PED_BE16_TO_CPU(label->ntrks) != dev->bios_geom.heads) { -#ifndef DISCOVER_ONLY - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The disk CHS geometry (%d,%d,%d) reported " - "by the operating system does not match " - "the geometry stored on the disk label " - "(%d,%d,%d)."), - dev->bios_geom.cylinders, - dev->bios_geom.heads, - dev->bios_geom.sectors, - PED_BE16_TO_CPU(label->pcylcount), - PED_BE16_TO_CPU(label->ntrks), - PED_BE16_TO_CPU(label->nsect)) - == PED_EXCEPTION_CANCEL) - return 0; -#endif - dev->bios_geom.sectors = PED_BE16_TO_CPU(label->nsect); - dev->bios_geom.heads = PED_BE16_TO_CPU(label->ntrks); - dev->bios_geom.cylinders = PED_BE16_TO_CPU(label->pcylcount); - - if (dev->bios_geom.sectors * dev->bios_geom.heads - * dev->bios_geom.cylinders > dev->length) { - if (ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The disk label describes a disk bigger than " - "%s."), - dev->path) - != PED_EXCEPTION_IGNORE) - return 0; - } - } - return 1; -} - -static int -sun_read (PedDisk* disk) -{ - SunRawLabel* label; - SunPartitionData* sun_data; - SunDiskData* disk_data; - int i; - PedPartition* part; - PedSector end, start, block; - PedConstraint* constraint_exact; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - PED_ASSERT (disk->disk_specific != NULL, return 0); - - disk_data = (SunDiskData*) disk->disk_specific; - label = &disk_data->raw_label; - - ped_disk_delete_all (disk); - - if (!ped_device_read (disk->dev, label, 0, 1)) - goto error; - if (!_check_geometry_sanity (disk, label)) - goto error; - - block = disk->dev->bios_geom.sectors * disk->dev->bios_geom.heads; - disk_data->length = block * disk->dev->bios_geom.cylinders; - - for (i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { - if (!PED_BE32_TO_CPU(label->partitions[i].num_sectors)) - continue; - if (!label->infos[i].id) - continue; - if (label->infos[i].id == WHOLE_DISK_ID) - continue; - - start = PED_BE32_TO_CPU(label->partitions[i].start_cylinder) - * block; - end = start - + PED_BE32_TO_CPU(label->partitions[i].num_sectors) - 1; - - part = ped_partition_new (disk, 0, NULL, start, end); - if (!part) - goto error; - - sun_data = part->disk_specific; - sun_data->type = label->infos[i].id; - sun_data->is_boot = sun_data->type == 0x1; - sun_data->is_root = sun_data->type == 0x2; - sun_data->is_lvm = sun_data->type == 0x8e; - - part->num = i + 1; - part->fs_type = ped_file_system_probe (&part->geom); - - constraint_exact = ped_constraint_exact (&part->geom); - if (!ped_disk_add_partition (disk, part, constraint_exact)) - goto error; - ped_constraint_destroy (constraint_exact); - } - - return 1; - - error: - return 0; -} - -#ifndef DISCOVER_ONLY -static void -_probe_and_use_old_info (const PedDisk* disk) -{ - SunDiskData* sun_specific; - SunRawLabel old_label; - - sun_specific = (SunDiskData*) disk->disk_specific; - - if (!ped_device_read (disk->dev, &old_label, 0, 1)) - return; - if (old_label.info [0] - && PED_BE16_TO_CPU (old_label.magic) == SUN_DISK_MAGIC) - memcpy (&sun_specific->raw_label, &old_label, 512); -} - -static int -sun_write (const PedDisk* disk) -{ - SunRawLabel* label; - SunPartitionData* sun_data; - SunDiskData* disk_data; - PedPartition* part; - int i; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - _probe_and_use_old_info (disk); - - disk_data = (SunDiskData*) disk->disk_specific; - label = &disk_data->raw_label; - - memset (label->partitions, 0, - sizeof (SunRawPartition) * SUN_DISK_MAXPARTITIONS); - memset (label->infos, 0, - sizeof (SunPartitionInfo) * SUN_DISK_MAXPARTITIONS); - - for (i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { - part = ped_disk_get_partition (disk, i + 1); - - if (!part && i == WHOLE_DISK_PART) { - /* Ok, nothing explicitly in the whole disk - partition, so let's put it there for safety - sake. */ - - label->infos[i].id = WHOLE_DISK_ID; - label->partitions[i].start_cylinder = 0; - label->partitions[i].num_sectors = - PED_CPU_TO_BE32(disk_data->length); - continue; - } - if (!part) - continue; - - sun_data = part->disk_specific; - label->infos[i].id = sun_data->type; - label->partitions[i].start_cylinder - = PED_CPU_TO_BE32 (part->geom.start - / (disk->dev->bios_geom.sectors - * disk->dev->bios_geom.heads)); - label->partitions[i].num_sectors - = PED_CPU_TO_BE32 (part->geom.end - - part->geom.start + 1); - } - - /* We assume the harddrive is always right, and that the label may - be wrong. I don't think this will cause any problems, since the - cylinder count is always enforced by our alignment, and we - sanity checked the sectors/heads when we detected the device. The - worst that could happen here is that the drive seems bigger or - smaller than it really is, but we'll have that problem even if we - don't do this. */ - - if (disk->dev->bios_geom.cylinders > 65536) { - ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE, - _("The disk has %d cylinders, which is greater than " - "the maximum of 65536."), - disk->dev->bios_geom.cylinders); - } - - label->pcylcount = PED_CPU_TO_BE16 (disk->dev->bios_geom.cylinders); - label->ncyl = PED_CPU_TO_BE16 (disk->dev->bios_geom.cylinders - - PED_BE16_TO_CPU (label->nacyl)); - - sun_compute_checksum (label); - - if (!ped_device_write (disk->dev, label, 0, 1)) - goto error; - return ped_device_sync (disk->dev); - -error: - return 0; -} -#endif /* !DISCOVER_ONLY */ - -static PedPartition* -sun_partition_new (const PedDisk* disk, PedPartitionType part_type, - const PedFileSystemType* fs_type, - PedSector start, PedSector end) -{ - PedPartition* part; - SunPartitionData* sun_data; - - part = _ped_partition_alloc (disk, part_type, fs_type, start, end); - if (!part) - goto error; - - if (ped_partition_is_active (part)) { - part->disk_specific - = sun_data = ped_malloc (sizeof (SunPartitionData)); - if (!sun_data) - goto error_free_part; - sun_data->type = 0; - sun_data->is_boot = 0; - sun_data->is_root = 0; - sun_data->is_lvm = 0; - } else { - part->disk_specific = NULL; - } - - return part; - - ped_free (sun_data); -error_free_part: - ped_free (part); -error: - return NULL; -} - -static PedPartition* -sun_partition_duplicate (const PedPartition* part) -{ - PedPartition* new_part; - SunPartitionData* new_sun_data; - SunPartitionData* old_sun_data; - - new_part = ped_partition_new (part->disk, part->type, - part->fs_type, part->geom.start, - part->geom.end); - if (!new_part) - return NULL; - new_part->num = part->num; - - old_sun_data = (SunPartitionData*) part->disk_specific; - new_sun_data = (SunPartitionData*) new_part->disk_specific; - new_sun_data->type = old_sun_data->type; - new_sun_data->is_boot = old_sun_data->is_boot; - new_sun_data->is_root = old_sun_data->is_root; - new_sun_data->is_lvm = old_sun_data->is_lvm; - return new_part; -} - -static void -sun_partition_destroy (PedPartition* part) -{ - PED_ASSERT (part != NULL, return); - - if (ped_partition_is_active (part)) - ped_free (part->disk_specific); - ped_free (part); -} - -static int -sun_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) -{ - SunPartitionData* sun_data = part->disk_specific; - - part->fs_type = fs_type; - - if (sun_data->is_boot) { - sun_data->type = 0x1; - return 1; - } - if (sun_data->is_root) { - sun_data->type = 0x2; - return 1; - } - if (sun_data->is_lvm) { - sun_data->type = 0x8e; - return 1; - } - - sun_data->type = 0x83; - if (fs_type) { - if (!strcmp (fs_type->name, "linux-swap")) - sun_data->type = 0x82; - else if (!strcmp (fs_type->name, "ufs")) - sun_data->type = 0x6; - } - - return 1; -} - -static int -sun_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) -{ - SunPartitionData* sun_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - PED_ASSERT (ped_partition_is_flag_available (part, flag), return 0); - - sun_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_BOOT: - sun_data->is_boot = state; - if (state) - sun_data->is_root = sun_data->is_lvm = 0; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_ROOT: - sun_data->is_root = state; - if (state) - sun_data->is_boot = sun_data->is_lvm = 0; - return ped_partition_set_system (part, part->fs_type); - - case PED_PARTITION_LVM: - sun_data->is_lvm = state; - if (state) - sun_data->is_root = sun_data->is_boot = 0; - return ped_partition_set_system (part, part->fs_type); - - default: - return 0; - } -} - - -static int -sun_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) -{ - SunPartitionData* sun_data; - - PED_ASSERT (part != NULL, return 0); - PED_ASSERT (part->disk_specific != NULL, return 0); - - sun_data = part->disk_specific; - - switch (flag) { - case PED_PARTITION_BOOT: - return sun_data->is_boot; - case PED_PARTITION_ROOT: - return sun_data->is_root; - case PED_PARTITION_LVM: - return sun_data->is_lvm; - - default: - return 0; - } -} - - -static int -sun_partition_is_flag_available (const PedPartition* part, - PedPartitionFlag flag) -{ - switch (flag) { - case PED_PARTITION_BOOT: - case PED_PARTITION_ROOT: - case PED_PARTITION_LVM: - return 1; - - default: - return 0; - } -} - - -static int -sun_get_max_primary_partition_count (const PedDisk* disk) -{ - return SUN_DISK_MAXPARTITIONS; -} - -static PedConstraint* -_get_strict_constraint (PedDisk* disk) -{ - PedDevice* dev = disk->dev; - PedAlignment start_align; - PedAlignment end_align; - PedGeometry max_geom; - SunDiskData* disk_data = disk->disk_specific; - PedSector block = dev->bios_geom.sectors * dev->bios_geom.heads; - - if (!ped_alignment_init (&start_align, 0, block)) - return NULL; - if (!ped_alignment_init (&end_align, -1, block)) - return NULL; - if (!ped_geometry_init (&max_geom, dev, 0, disk_data->length)) - return NULL; - - return ped_constraint_new (&start_align, &end_align, &max_geom, - &max_geom, 1, dev->length); -} - -static PedConstraint* -_get_lax_constraint (PedDisk* disk) -{ - PedDevice* dev = disk->dev; - PedAlignment start_align; - PedGeometry max_geom; - SunDiskData* disk_data = disk->disk_specific; - PedSector block = dev->bios_geom.sectors * dev->bios_geom.heads; - - if (!ped_alignment_init (&start_align, 0, block)) - return NULL; - if (!ped_geometry_init (&max_geom, dev, 0, disk_data->length)) - return NULL; - - return ped_constraint_new (&start_align, ped_alignment_any, &max_geom, - &max_geom, 1, dev->length); -} - -/* _get_strict_constraint() will align the partition to the end of the cylinder. - * This isn't required, but since partitions must start at the start of the - * cylinder, space between the end of a partition and the end of a cylinder - * is unusable, so there's no point wasting space! - * However, if they really insist (via constraint)... which they will - * if they're reading a weird table of the disk... then we allow the end to - * be anywhere, with _get_lax_constraint() - */ -static int -sun_partition_align (PedPartition* part, const PedConstraint* constraint) -{ - PED_ASSERT (part != NULL, return 0); - - if (_ped_partition_attempt_align (part, constraint, - _get_strict_constraint (part->disk))) - return 1; - if (_ped_partition_attempt_align (part, constraint, - _get_lax_constraint (part->disk))) - return 1; - -#ifndef DISCOVER_ONLY - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Unable to satisfy all constraints on the partition.")); -#endif - return 0; -} - -static int -sun_partition_enumerate (PedPartition* part) -{ - int i; - PedPartition* p; - - /* never change the partition numbers */ - if (part->num != -1) - return 1; - for (i = 1; i <= SUN_DISK_MAXPARTITIONS; i++) { - /* skip the Whole Disk partition for now */ - if (i == WHOLE_DISK_PART + 1) - continue; - p = ped_disk_get_partition (part->disk, i); - if (!p) { - part->num = i; - return 1; - } - } - -#ifndef DISCOVER_ONLY - /* Ok, now allocate the Whole disk if it isn't already */ - p = ped_disk_get_partition (part->disk, WHOLE_DISK_PART + 1); - if (!p) { - int j = ped_exception_throw ( - PED_EXCEPTION_WARNING, - PED_EXCEPTION_IGNORE_CANCEL, - _("The Whole Disk partition is the only " - "available one left. Generally, it is not a " - "good idea to overwrite this partition with " - "a real one. Solaris may not be able to " - "boot without it, and SILO (the sparc boot " - "loader) appreciates it as well.")); - if (j == PED_EXCEPTION_IGNORE) { - /* bad bad bad...you will suffer your own fate */ - part->num = WHOLE_DISK_PART + 1; - return 1; - } - } - - /* failed to allocate a number, this means we are full */ - ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Sun disk label is full.")); -#endif - return 0; -} - -static int -sun_alloc_metadata (PedDisk* disk) -{ - PedPartition* new_part; - SunDiskData* disk_data; - PedConstraint* constraint_any; - - PED_ASSERT (disk != NULL, return 0); - PED_ASSERT (disk->disk_specific != NULL, return 0); - PED_ASSERT (disk->dev != NULL, return 0); - - constraint_any = ped_constraint_any (disk->dev); - - /* Sun disk label does not need to allocate a sector. The disk - label is contained within the first 512 bytes, which should not - be overwritten by any boot loader or superblock. It is safe for - most partitions to start at sector 0. We do however, allocate - the space used by alt-cyl's, since we cannot use those. Put them - at the end of the disk. */ - - disk_data = disk->disk_specific; - - if (disk->dev->length <= 0 || - disk_data->length <= 0 || - disk->dev->length == disk_data->length) - goto error; - - new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, - disk_data->length, disk->dev->length - 1); - if (!new_part) - goto error; - - if (!ped_disk_add_partition (disk, new_part, constraint_any)) { - ped_partition_destroy (new_part); - goto error; - } - - ped_constraint_destroy (constraint_any); - return 1; -error: - ped_constraint_destroy (constraint_any); - return 0; -} - -static PedDiskOps sun_disk_ops = { - .probe = sun_probe, -#ifndef DISCOVER_ONLY - .clobber = sun_clobber, -#else - .clobber = NULL, -#endif - .alloc = sun_alloc, - .duplicate = sun_duplicate, - .free = sun_free, - .read = sun_read, -#ifndef DISCOVER_ONLY - .write = sun_write, -#else - .write = NULL, -#endif - - .partition_new = sun_partition_new, - .partition_duplicate = sun_partition_duplicate, - .partition_destroy = sun_partition_destroy, - .partition_set_system = sun_partition_set_system, - .partition_set_flag = sun_partition_set_flag, - .partition_get_flag = sun_partition_get_flag, - .partition_is_flag_available = sun_partition_is_flag_available, - .partition_align = sun_partition_align, - .partition_enumerate = sun_partition_enumerate, - .alloc_metadata = sun_alloc_metadata, - .get_max_primary_partition_count = - sun_get_max_primary_partition_count, - - .partition_set_name = NULL, - .partition_get_name = NULL, -}; - -static PedDiskType sun_disk_type = { - .next = NULL, - .name = "sun", - .ops = &sun_disk_ops, - .features = 0 -}; - -void -ped_disk_sun_init () -{ - PED_ASSERT (sizeof (SunRawLabel) == 512, return); - ped_disk_type_register (&sun_disk_type); -} - -void -ped_disk_sun_done () -{ - ped_disk_type_unregister (&sun_disk_type); -} diff --git a/usr/src/lib/libparted/common/libparted/libparted.c b/usr/src/lib/libparted/common/libparted/libparted.c deleted file mode 100644 index 7b019608d0..0000000000 --- a/usr/src/lib/libparted/common/libparted/libparted.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 1999, 2000, 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include "configmake.h" - -#include -#include - -#ifdef linux -# include -#elif defined(__BEOS__) -# include -#elif defined(__sun) -# include -#else -# include -#endif - -#if ENABLE_NLS -# include -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - -const PedArchitecture* ped_architecture; - -/* ped_malloc() debugging. Stick the address and size of memory blocks that - * weren't ped_free()d in here, and an exception will be thrown when it is - * allocated. That way, you can find out what, exactly, the allocated thing - * is, and where it is created. - */ -typedef struct -{ - void* pointer; - size_t size; -} pointer_size_type; - -/* IMHO, none of the DEBUG-related code below is useful, and the - ped_malloc memset code is actually quite harmful: it masked at - least two nasty bugs that were fixed in June of 2007. */ -#undef DEBUG -#ifdef DEBUG -static pointer_size_type dodgy_malloc_list[] = { - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0} -}; - -static int dodgy_memory_active[100]; -#endif /* DEBUG */ - -int -ped_set_architecture (const PedArchitecture* arch) -{ - PED_ASSERT (ped_device_get_next (NULL) == NULL, return 0); - - ped_architecture = arch; - return 1; -} - -extern void ped_disk_aix_init (); -extern void ped_disk_bsd_init (); -extern void ped_disk_dvh_init (); -extern void ped_disk_gpt_init (); -extern void ped_disk_loop_init (); -extern void ped_disk_mac_init (); -extern void ped_disk_msdos_init (); -extern void ped_disk_pc98_init (); -extern void ped_disk_sun_init (); -extern void ped_disk_amiga_init (); -extern void ped_disk_dasd_init (); - -static void -init_disk_types () -{ - ped_disk_loop_init (); /* must be last in the probe list */ - -#if defined(__s390__) || defined(__s390x__) - ped_disk_dasd_init(); -#endif - - ped_disk_sun_init (); -#ifdef ENABLE_PC98 - ped_disk_pc98_init (); -#endif - ped_disk_msdos_init (); - ped_disk_mac_init (); - ped_disk_gpt_init (); - ped_disk_dvh_init (); - ped_disk_bsd_init (); - ped_disk_amiga_init (); - ped_disk_aix_init (); -} - -#ifdef ENABLE_FS -extern void ped_file_system_amiga_init (void); -extern void ped_file_system_xfs_init (void); -extern void ped_file_system_ufs_init (void); -extern void ped_file_system_reiserfs_init (void); -extern void ped_file_system_ntfs_init (void); -extern void ped_file_system_linux_swap_init (void); -extern void ped_file_system_jfs_init (void); -extern void ped_file_system_hfs_init (void); -extern void ped_file_system_fat_init (void); -extern void ped_file_system_ext2_init (void); -extern void ped_file_system_solaris_x86_init (void); - -static void -init_file_system_types () -{ - ped_file_system_amiga_init (); - ped_file_system_xfs_init (); - ped_file_system_ufs_init (); - ped_file_system_reiserfs_init (); - ped_file_system_ntfs_init (); - ped_file_system_linux_swap_init (); - ped_file_system_jfs_init (); - ped_file_system_hfs_init (); - ped_file_system_fat_init (); - ped_file_system_ext2_init (); - ped_file_system_solaris_x86_init (); -} -#endif /* ENABLE_FS */ - -extern void ped_disk_aix_done (); -extern void ped_disk_bsd_done (); -extern void ped_disk_dvh_done (); -extern void ped_disk_gpt_done (); -extern void ped_disk_loop_done (); -extern void ped_disk_mac_done (); -extern void ped_disk_msdos_done (); -extern void ped_disk_pc98_done (); -extern void ped_disk_sun_done (); -extern void ped_disk_amiga_done (); -extern void ped_disk_dasd_done (); - -static void -done_disk_types () -{ -#if defined(__s390__) || (__s390x__) - ped_disk_dasd_done (); -#endif - ped_disk_sun_done (); -#ifdef ENABLE_PC98 - ped_disk_pc98_done (); -#endif - ped_disk_msdos_done (); - ped_disk_mac_done (); - ped_disk_loop_done (); - ped_disk_gpt_done (); - ped_disk_dvh_done (); - ped_disk_bsd_done (); - ped_disk_amiga_done (); - ped_disk_aix_done (); -} - -static void _init() __attribute__ ((constructor)); - -static void -_init() -{ -#ifdef ENABLE_NLS - bindtextdomain (PACKAGE, LOCALEDIR); -#endif - - init_disk_types (); - -#ifdef ENABLE_FS - init_file_system_types (); -#endif - - /* FIXME: a better way of doing this? */ -#ifdef linux - ped_set_architecture (&ped_linux_arch); -#elif defined(__BEOS__) - ped_set_architecture (&ped_beos_arch); -#elif defined (__sun) - ped_set_architecture (&ped_solaris_arch); -#else - ped_set_architecture (&ped_gnu_arch); -#endif - -#ifdef DEBUG - memset (dodgy_memory_active, 0, sizeof (dodgy_memory_active)); -#endif -} - -#ifdef ENABLE_FS -extern void ped_file_system_ext2_done (void); -extern void ped_file_system_fat_done (void); -extern void ped_file_system_hfs_done (void); -extern void ped_file_system_jfs_done (void); -extern void ped_file_system_linux_swap_done (void); -extern void ped_file_system_ntfs_done (void); -extern void ped_file_system_reiserfs_done (void); -extern void ped_file_system_ufs_done (void); -extern void ped_file_system_xfs_done (void); -extern void ped_file_system_amiga_done (void); - -static void -done_file_system_types () -{ - ped_file_system_ext2_done (); - ped_file_system_fat_done (); - ped_file_system_hfs_done (); - ped_file_system_jfs_done (); - ped_file_system_linux_swap_done (); - ped_file_system_ntfs_done (); - ped_file_system_reiserfs_done (); - ped_file_system_ufs_done (); - ped_file_system_xfs_done (); - ped_file_system_amiga_done (); -} -#endif /* ENABLE_FS */ - -static void _done() __attribute__ ((destructor)); - -static void -_done() -{ - ped_device_free_all (); - - done_disk_types (); - -#ifdef ENABLE_FS - done_file_system_types (); -#endif -} - -const char* -ped_get_version () -{ - return VERSION; -} - -#ifdef DEBUG -static void -_check_dodgy_pointer (const void* ptr, size_t size, int is_malloc) -{ - int i; - - for (i=0; dodgy_malloc_list[i].pointer; i++) { - if (dodgy_malloc_list[i].pointer != ptr) - continue; - if (is_malloc && dodgy_malloc_list[i].size != size) - continue; - if (!is_malloc && !dodgy_memory_active[i]) - continue; - - - if (is_malloc) { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - "Dodgy malloc(%x) == %p occurred (active==%d)", - size, ptr, dodgy_memory_active[i]); - dodgy_memory_active[i]++; - } else { - ped_exception_throw ( - PED_EXCEPTION_INFORMATION, - PED_EXCEPTION_OK, - "Dodgy free(%p) occurred (active==%d)", - ptr, dodgy_memory_active[i]); - dodgy_memory_active[i]--; - } - - return; - } -} -#endif /* DEBUG */ - -void* -ped_malloc (size_t size) -{ - void* mem; - - mem = (void*) malloc (size); - if (!mem) { - ped_exception_throw (PED_EXCEPTION_FATAL, PED_EXCEPTION_CANCEL, - _("Out of memory.")); - return NULL; - } - -#ifdef DEBUG - memset (mem, 0xff, size); - _check_dodgy_pointer (mem, size, 1); -#endif - - return mem; -} - -int -ped_realloc (void** old, size_t size) -{ - void* mem; - - mem = (void*) realloc (*old, size); - if (!mem) { - ped_exception_throw (PED_EXCEPTION_FATAL, PED_EXCEPTION_CANCEL, - _("Out of memory.")); - return 0; - } - *old = mem; - return 1; -} - - -void* ped_calloc (size_t size) -{ - void* buf = ped_malloc (size); - - memset (buf, 0, size); - - return buf; -} - - -void -ped_free (void* ptr) -{ -#ifdef DEBUG - _check_dodgy_pointer (ptr, 0, 0); -#endif - - free (ptr); -} diff --git a/usr/src/lib/libparted/common/libparted/timer.c b/usr/src/lib/libparted/common/libparted/timer.c deleted file mode 100644 index 3e962ae84d..0000000000 --- a/usr/src/lib/libparted/common/libparted/timer.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2001, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file timer.c */ - -/** - * \addtogroup PedTimer - * - * \brief A PedTimer keeps track of the progress of a single (possibly - * compound) operation. - * - * The user of libparted constructs a PedTimer, and passes it to libparted - * functions that are likely to be expensive operations - * (like ped_file_system_resize). Use of timers is optional... you may - * pass NULL instead. - * - * When you create a PedTimer, you must specify a timer handler function. - * This will be called when there's an update on how work is progressing. - * - * Timers may be nested. When a timer is constructed, you can choose - * to assign it a parent, along with an estimate of what proportion of - * the total (parent's) time will be used in the nested operation. In - * this case, the nested timer's handler is internal to libparted, - * and simply updates the parent's progress, and calls its handler. - * - * @{ - */ - - -#include -#include -#include - -#define PED_TIMER_START_DELAY 2 - -typedef struct { - PedTimer* parent; - float nest_frac; - float start_frac; -} NestedContext; - - -/** - * \brief Creates a timer. - * - * Context will be passed in the \p context - * argument to the \p handler, when it is invoked. - * - * \return a new PedTimer - */ -PedTimer* -ped_timer_new (PedTimerHandler* handler, void* context) -{ - PedTimer* timer; - - PED_ASSERT (handler != NULL, return NULL); - - timer = (PedTimer*) ped_malloc (sizeof (PedTimer)); - if (!timer) - return NULL; - - timer->handler = handler; - timer->context = context; - ped_timer_reset (timer); - return timer; -} - - -/** - * \brief Destroys a \p timer. - */ -void -ped_timer_destroy (PedTimer* timer) -{ - if (!timer) - return; - - ped_free (timer); -} - -/* This function is used by ped_timer_new_nested() as the timer->handler - * function. - */ -static void -_nest_handler (PedTimer* timer, void* context) -{ - NestedContext* ncontext = (NestedContext*) context; - - ped_timer_update ( - ncontext->parent, - ncontext->start_frac + ncontext->nest_frac * timer->frac); -} - - -/** - * \brief Creates a new nested timer. - * - * This function creates a "nested" timer that describes the progress - * of a subtask. \p parent is the parent timer, and \p nested_frac is - * the estimated proportion (between 0 and 1) of the time that will be - * spent doing the nested timer's operation. The timer should only be - * constructed immediately prior to starting the nested operation. - * (It will be inaccurate, otherwise). - * Updates to the progress of the subtask are propagated - * back through to the parent task's timer. - * - * \return nested timer - */ -PedTimer* -ped_timer_new_nested (PedTimer* parent, float nest_frac) -{ - NestedContext* context; - - if (!parent) - return NULL; - - PED_ASSERT (nest_frac >= 0.0, return NULL); - PED_ASSERT (nest_frac <= 1.0, return NULL); - - context = (NestedContext*) ped_malloc (sizeof (NestedContext)); - if (!context) - return NULL; - context->parent = parent; - context->nest_frac = nest_frac; - context->start_frac = parent->frac; - - return ped_timer_new (_nest_handler, context); -} - -/** - * \brief Destroys a nested \p timer. - */ -void -ped_timer_destroy_nested (PedTimer* timer) -{ - if (!timer) - return; - - ped_free (timer->context); - ped_timer_destroy (timer); -} - -/** - * \internal - * - * \brief This function calls the update handler, making sure that it has - * the latest time. - * - * First it updates \p timer->now and recomputes \p timer->predicted_end, - * and then calls the handler. - */ -void -ped_timer_touch (PedTimer* timer) -{ - if (!timer) - return; - - timer->now = time (NULL); - if (timer->now > timer->predicted_end) - timer->predicted_end = timer->now; - - timer->handler (timer, timer->context); -} - -/** - * \internal - * - * \brief This function sets the \p timer into a "start of task" position. - * - * It resets the \p timer, by setting \p timer->start and \p timer->now - * to the current time. - */ -void -ped_timer_reset (PedTimer* timer) -{ - if (!timer) - return; - - timer->start = timer->now = timer->predicted_end = time (NULL); - timer->state_name = NULL; - timer->frac = 0; - - ped_timer_touch (timer); -} - -/** - * \internal - * - * \brief This function tells a \p timer what fraction \p frac of the task - * has been completed. - * - * Sets the new \p timer->frac, and calls ped_timer_touch(). - */ -void -ped_timer_update (PedTimer* timer, float frac) -{ - if (!timer) - return; - - timer->now = time (NULL); - timer->frac = frac; - - if (frac) - timer->predicted_end - = timer->start - + (long) ((timer->now - timer->start) / frac); - - ped_timer_touch (timer); -} - -/** - * \internal - * - * \brief This function changes the description of the current task that the - * \p timer describes. - * - * Sets a new name - \p state_name - for the current "phase" of the operation, - * and calls ped_timer_touch(). - */ -void -ped_timer_set_state_name (PedTimer* timer, const char* state_name) -{ - if (!timer) - return; - - timer->state_name = state_name; - ped_timer_touch (timer); -} - -/** @} */ diff --git a/usr/src/lib/libparted/common/libparted/unit.c b/usr/src/lib/libparted/common/libparted/unit.c deleted file mode 100644 index 29c4ed50ce..0000000000 --- a/usr/src/lib/libparted/common/libparted/unit.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - libparted - a library for manipulating disk partitions - Copyright (C) 2005, 2007 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** \file unit.c */ - -/** - * \addtogroup PedUnit - * - * \brief The PedUnit module provides a standard mechanism for describing - * and parsing locations within devices in human-friendly plain text. - * - * Internally, libparted uses PedSector (which is typedef'ed to be long long - * in ) to describe device locations such as the start and - * end of partitions. However, sector numbers are often long and unintuitive. - * For example, my extended partition starts at sector 208845. PedUnit allows - * this location to be represented in more intutitive ways, including "106Mb", - * "0Gb" and "0%", as well as "208845s". PedUnit aims to provide facilities - * to provide a consistent system for describing device locations all - * throughout libparted. - * - * PedUnit provides two basic services: converting a PedSector into a text - * representation, and parsing a text representation into a PedSector. - * PedUnit currently supports these units: - * - * sectors, bytes, kilobytes, megabytes, gigabytes, terabytes, compact, - * cylinder and percent. - * - * PedUnit has a global variable that contains the default unit for all - * conversions. - * - * @{ - */ - - - - -#include -#include -#include - -#include -#include -#include - -#define N_(String) String -#if ENABLE_NLS -# include -# define _(String) dgettext (PACKAGE, String) -#else -# define _(String) (String) -#endif /* ENABLE_NLS */ - - -static PedUnit default_unit = PED_UNIT_COMPACT; -static const char* unit_names[] = { - "s", - "B", - "kB", - "MB", - "GB", - "TB", - "compact", - "cyl", - "chs", - "%", - "kiB", - "MiB", - "GiB", - "TiB" -}; - - -/** - * \brief Set the default \p unit used by subsequent calls to the PedUnit API. - * - * In particular, this affects how locations inside error messages - * (exceptions) are displayed. - */ -void -ped_unit_set_default (PedUnit unit) -{ - default_unit = unit; -} - - -/** - * \brief Get the current default unit. - */ -PedUnit -ped_unit_get_default () -{ - return default_unit; -} - -/** - * Get the byte size of a given \p unit. - */ -long long -ped_unit_get_size (const PedDevice* dev, PedUnit unit) -{ - PedSector cyl_size = dev->bios_geom.heads * dev->bios_geom.sectors; - - switch (unit) { - case PED_UNIT_SECTOR: return dev->sector_size; - case PED_UNIT_BYTE: return 1; - case PED_UNIT_KILOBYTE: return PED_KILOBYTE_SIZE; - case PED_UNIT_MEGABYTE: return PED_MEGABYTE_SIZE; - case PED_UNIT_GIGABYTE: return PED_GIGABYTE_SIZE; - case PED_UNIT_TERABYTE: return PED_TERABYTE_SIZE; - case PED_UNIT_KIBIBYTE: return PED_KIBIBYTE_SIZE; - case PED_UNIT_MEBIBYTE: return PED_MEBIBYTE_SIZE; - case PED_UNIT_GIBIBYTE: return PED_GIBIBYTE_SIZE; - case PED_UNIT_TEBIBYTE: return PED_TEBIBYTE_SIZE; - case PED_UNIT_CYLINDER: return cyl_size * dev->sector_size; - case PED_UNIT_CHS: return dev->sector_size; - - case PED_UNIT_PERCENT: - return dev->length * dev->sector_size / 100; - - case PED_UNIT_COMPACT: - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("Cannot get unit size for special unit " - "'COMPACT'.")); - return 0; - } - - /* never reached */ - PED_ASSERT(0, return 0); - return 0; -} - -/** - * Get a textual (non-internationalized) representation of a \p unit. - * - * For example, the textual representation of PED_UNIT_SECTOR is "s". - */ -const char* -ped_unit_get_name (PedUnit unit) -{ - return unit_names[unit]; -} - -/** - * Get a unit based on its textual representation: \p unit_name. - * - * For example, ped_unit_get_by_name("Mb") returns PED_UNIT_MEGABYTE. - */ -PedUnit -ped_unit_get_by_name (const char* unit_name) -{ - PedUnit unit; - for (unit = PED_UNIT_FIRST; unit <= PED_UNIT_LAST; unit++) { - if (!strcasecmp (unit_names[unit], unit_name)) - return unit; - } - return -1; -} - -static char* -ped_strdup (const char *str) -{ - char *result; - result = ped_malloc (strlen (str) + 1); - if (!result) - return NULL; - strcpy (result, str); - return result; -} - -/** - * \brief Get a string that describes the location of the \p byte on - * device \p dev. - * - * The string is described with the desired \p unit. - * The returned string must be freed with ped_free(). - */ -char* -ped_unit_format_custom_byte (const PedDevice* dev, PedSector byte, PedUnit unit) -{ - char buf[100]; - PedSector sector = byte / dev->sector_size; - double d, w; - int p; - - PED_ASSERT (dev != NULL, return NULL); - - /* CHS has a special comma-separated format. */ - if (unit == PED_UNIT_CHS) { - const PedCHSGeometry *chs = &dev->bios_geom; - snprintf (buf, 100, "%lld,%lld,%lld", - sector / chs->sectors / chs->heads, - (sector / chs->sectors) % chs->heads, - sector % chs->sectors); - return ped_strdup (buf); - } - - /* Cylinders, sectors and bytes should be rounded down... */ - if (unit == PED_UNIT_CYLINDER - || unit == PED_UNIT_SECTOR - || unit == PED_UNIT_BYTE) { - snprintf (buf, 100, "%lld%s", - byte / ped_unit_get_size (dev, unit), - ped_unit_get_name (unit)); - return ped_strdup (buf); - } - - if (unit == PED_UNIT_COMPACT) { - if (byte >= 10LL * PED_TERABYTE_SIZE) - unit = PED_UNIT_TERABYTE; - else if (byte >= 10LL * PED_GIGABYTE_SIZE) - unit = PED_UNIT_GIGABYTE; - else if (byte >= 10LL * PED_MEGABYTE_SIZE) - unit = PED_UNIT_MEGABYTE; - else if (byte >= 10LL * PED_KILOBYTE_SIZE) - unit = PED_UNIT_KILOBYTE; - else - unit = PED_UNIT_BYTE; - } - - /* IEEE754 says that 100.5 has to be rounded to 100 (by printf) */ - /* but 101.5 has to be rounded to 102... so we multiply by 1+E. */ - /* This just divide by 2 the natural IEEE754 extended precision */ - /* and won't cause any trouble before 1000 TB */ - d = ((double)byte / (double)ped_unit_get_size (dev, unit)) - * (1. + DBL_EPSILON); - w = d + ( (d < 10. ) ? 0.005 : - (d < 100.) ? 0.05 : - 0.5 ); - p = (w < 10. ) ? 2 : - (w < 100.) ? 1 : - 0 ; - -#ifdef __BEOS__ - snprintf (buf, 100, "%.*f%s", p, d, ped_unit_get_name(unit)); -#else - snprintf (buf, 100, "%1$.*2$f%3$s", d, p, ped_unit_get_name (unit)); -#endif - - return ped_strdup (buf); -} - -/** - * \brief Get a string that describes the location of the \p byte on - * device \p dev. - * - * The string is described with the default unit, which is set - * by ped_unit_set_default(). - * The returned string must be freed with ped_free(). - */ -char* -ped_unit_format_byte (const PedDevice* dev, PedSector byte) -{ - PED_ASSERT (dev != NULL, return NULL); - return ped_unit_format_custom_byte (dev, byte, default_unit); -} - -/** - * \brief Get a string that describes the location \p sector on device \p dev. - * - * The string is described with the desired \p unit. - * The returned string must be freed with ped_free(). - */ -char* -ped_unit_format_custom (const PedDevice* dev, PedSector sector, PedUnit unit) -{ - PED_ASSERT (dev != NULL, return NULL); - return ped_unit_format_custom_byte(dev, sector*dev->sector_size, unit); -} - -/** - * \brief Get a string that describes the location \p sector on device \p dev. - * - * The string is described with the default unit, which is set - * by ped_unit_set_default(). - * The returned string must be freed with ped_free(). - */ -char* -ped_unit_format (const PedDevice* dev, PedSector sector) -{ - PED_ASSERT (dev != NULL, return NULL); - return ped_unit_format_custom_byte (dev, sector * dev->sector_size, - default_unit); -} - -/** - * If \p str contains a valid description of a location on \p dev, - * then \p *sector is modified to describe the location and a geometry - * is created in \p *range describing a 2 units large area centered on - * \p *sector. If the \p range as described here would be partially outside - * the device \p dev, the geometry returned is the intersection between the - * former and the whole device geometry. If no units are specified, then the - * default unit is assumed. - * - * \return \c 1 if \p str is a valid location description, \c 0 otherwise - */ -int -ped_unit_parse (const char* str, const PedDevice* dev, PedSector *sector, - PedGeometry** range) -{ - return ped_unit_parse_custom (str, dev, default_unit, sector, range); -} - -/* Inefficiently removes all spaces from a string, in-place. */ -static void -strip_string (char* str) -{ - int i; - - for (i = 0; str[i] != 0; i++) { - if (isspace (str[i])) { - int j; - for (j = i + 1; str[j] != 0; j++) - str[j - 1] = str[j]; - } - } -} - - -/* Find non-number suffix. Eg: find_suffix("32Mb") returns a pointer to - * "Mb". */ -static char* -find_suffix (const char* str) -{ - while (str[0] != 0 && (isdigit (str[0]) || strchr(",.-", str[0]))) - str++; - return (char *) str; -} - -static void -remove_punct (char* str) -{ - int i = 0; - - for (i = 0; str[i]; i++) { - if (ispunct (str[i])) - str[i] = ' '; - } -} - -static int -is_chs (const char* str) -{ - int punct_count = 0; - int i = 0; - - for (i = 0; str[i]; i++) - punct_count += ispunct (str[i]) != 0; - return punct_count == 2; -} - -static int -parse_chs (const char* str, const PedDevice* dev, PedSector* sector, - PedGeometry** range) -{ - PedSector cyl_size = dev->bios_geom.heads * dev->bios_geom.sectors; - char* copy = ped_strdup (str); - PedCHSGeometry chs; - - copy = ped_strdup (str); - if (!copy) - return 0; - strip_string (copy); - remove_punct (copy); - - if (sscanf (copy, "%d %d %d", - &chs.cylinders, &chs.heads, &chs.sectors) != 3) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("\"%s\" has invalid syntax for locations."), - copy); - goto error_free_copy; - } - - if (chs.heads >= dev->bios_geom.heads) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("The maximum head value is %d."), - dev->bios_geom.heads - 1); - goto error_free_copy; - } - if (chs.sectors >= dev->bios_geom.sectors) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("The maximum sector value is %d."), - dev->bios_geom.sectors - 1); - goto error_free_copy; - } - - *sector = 1LL * chs.cylinders * cyl_size - + chs.heads * dev->bios_geom.sectors - + chs.sectors; - - if (*sector >= dev->length) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("The location %s is outside of the " - "device %s."), - str, dev->path); - goto error_free_copy; - } - if (range) - *range = ped_geometry_new (dev, *sector, 1); - ped_free (copy); - return !range || *range != NULL; - -error_free_copy: - ped_free (copy); - *sector = 0; - if (range) - *range = NULL; - return 0; -} - -static PedSector -clip (const PedDevice* dev, PedSector sector) -{ - if (sector < 0) - return 0; - if (sector > dev->length - 1) - return dev->length - 1; - return sector; -} - -static PedGeometry* -geometry_from_centre_radius (const PedDevice* dev, - PedSector sector, PedSector radius) -{ - PedSector start = clip (dev, sector - radius); - PedSector end = clip (dev, sector + radius); - if (sector - end > radius || start - sector > radius) - return NULL; - return ped_geometry_new (dev, start, end - start + 1); -} - -static PedUnit -parse_unit_suffix (const char* suffix, PedUnit suggested_unit) -{ - if (strlen (suffix) > 1 && tolower (suffix[1]) == 'i') { - switch (tolower (suffix[0])) { - case 'k': return PED_UNIT_KIBIBYTE; - case 'm': return PED_UNIT_MEBIBYTE; - case 'g': return PED_UNIT_GIBIBYTE; - case 't': return PED_UNIT_TEBIBYTE; - } - } else if (strlen (suffix) > 0) { - switch (tolower (suffix[0])) { - case 's': return PED_UNIT_SECTOR; - case 'b': return PED_UNIT_BYTE; - case 'k': return PED_UNIT_KILOBYTE; - case 'm': return PED_UNIT_MEGABYTE; - case 'g': return PED_UNIT_GIGABYTE; - case 't': return PED_UNIT_TERABYTE; - case 'c': return PED_UNIT_CYLINDER; - case '%': return PED_UNIT_PERCENT; - } - } - - if (suggested_unit == PED_UNIT_COMPACT) { - if (default_unit == PED_UNIT_COMPACT) - return PED_UNIT_MEGABYTE; - else - return default_unit; - } - - return suggested_unit; -} - -/** - * If \p str contains a valid description of a location on \p dev, then - * \p *sector is modified to describe the location and a geometry is created - * in \p *range describing a 2 units large area centered on \p *sector. If the - * \p range as described here would be partially outside the device \p dev, the - * geometry returned is the intersection between the former and the whole - * device geometry. If no units are specified, then the default unit is - * assumed. - * - * \throws PED_EXCEPTION_ERROR if \p str contains invalid description of a - * location - * \throws PED_EXCEPTION_ERROR if location described by \p str - * is outside of the device \p dev->path - * - * \return \c 1 if \p str is a valid location description, \c 0 otherwise. - */ -int -ped_unit_parse_custom (const char* str, const PedDevice* dev, PedUnit unit, - PedSector* sector, PedGeometry** range) -{ - char* copy; - char* suffix; - double num; - long long unit_size; - PedSector radius; - - if (is_chs (str)) - return parse_chs (str, dev, sector, range); - - copy = ped_strdup (str); - if (!copy) - goto error; - strip_string (copy); - - suffix = find_suffix (copy); - unit = parse_unit_suffix (suffix, unit); - suffix[0] = 0; - - if (sscanf (copy, "%lf", &num) != 1) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, - PED_EXCEPTION_CANCEL, - _("Invalid number.")); - goto error_free_copy; - } - - unit_size = ped_unit_get_size (dev, unit); - radius = ped_div_round_up (unit_size, dev->sector_size) - 1; - if (radius < 0) - radius = 0; - - *sector = num * unit_size / dev->sector_size; - /* negative numbers count from the end */ - if (copy[0] == '-') - *sector += dev->length; - if (range) { - *range = geometry_from_centre_radius (dev, *sector, radius); - if (!*range) { - ped_exception_throw ( - PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, - _("The location %s is outside of the " - "device %s."), - str, dev->path); - goto error_free_copy; - } - } - *sector = clip (dev, *sector); - - ped_free (copy); - return 1; - -error_free_copy: - ped_free (copy); -error: - *sector = 0; - if (range) - *range = NULL; - return 0; -} - - -/** @} */ diff --git a/usr/src/lib/libparted/common/mapfile-vers b/usr/src/lib/libparted/common/mapfile-vers deleted file mode 100644 index 0cfbd9ab88..0000000000 --- a/usr/src/lib/libparted/common/mapfile-vers +++ /dev/null @@ -1,156 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms of the -# Common Development and Distribution License (the "License"). -# You may not use this file except in compliance with the License. -# -# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing permissions -# and limitations under the License. -# -# When distributing Covered Code, include this CDDL HEADER in each -# file and include the License file at usr/src/OPENSOLARIS.LICENSE. -# If applicable, add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your own identifying -# information: Portions Copyright [yyyy] [name of copyright owner] -# -# CDDL HEADER END -# -# -# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -# - -# -# MAPFILE HEADER START -# -# WARNING: STOP NOW. DO NOT MODIFY THIS FILE. -# Object versioning must comply with the rules detailed in -# -# usr/src/lib/README.mapfiles -# -# You should not be making modifications here until you've read the most current -# copy of that file. If you need help, contact a gatekeeper for guidance. -# -# MAPFILE HEADER END -# - -$mapfile_version 2 - -SYMBOL_VERSION SUNW_8.1 { - global: - close_stdout; - error; - ped_alignment_any; - ped_assert; - ped_constraint_any; - ped_constraint_destroy; - ped_constraint_done; - ped_constraint_exact; - ped_constraint_init; - ped_constraint_intersect; - ped_constraint_new; - ped_debug; - ped_device_close; - ped_device_destroy; - ped_device_free_all; - ped_device_get; - ped_device_get_constraint; - ped_device_get_next; - ped_device_is_busy; - ped_device_open; - ped_device_probe_all; - ped_device_read; - ped_device_sync; - ped_device_write; - ped_disk_add_partition; - ped_disk_check; - ped_disk_commit; - ped_disk_commit_to_dev; - ped_disk_commit_to_os; - ped_disk_delete_partition; - ped_disk_destroy; - ped_disk_extended_partition; - ped_disk_get_max_primary_partition_count; - ped_disk_get_partition; - ped_disk_get_partition_by_sector; - ped_disk_new; - ped_disk_new_fresh; - ped_disk_next_partition; - ped_disk_probe; - ped_disk_remove_partition; - ped_disk_set_partition_geom; - ped_disk_type_check_feature; - ped_disk_type_get; - ped_disk_type_get_next; - ped_exception_catch; - ped_exception_fetch_all; - ped_exception_get_option_string; - ped_exception_get_type_string; - ped_exception_leave_all; - ped_exception_set_handler; - ped_exception_throw; - ped_file_system_check; - ped_file_system_clobber; - ped_file_system_close; - ped_file_system_copy; - ped_file_system_create; - ped_file_system_get_copy_constraint; - ped_file_system_get_resize_constraint; - ped_file_system_open; - ped_file_system_probe; - ped_file_system_probe_specific; - ped_file_system_resize; - ped_file_system_type_get; - ped_file_system_type_get_next; - ped_free; - ped_geometry_destroy; - ped_geometry_init; - ped_geometry_new; - ped_geometry_read; - ped_geometry_set; - ped_geometry_test_inside; - ped_geometry_test_overlap; - ped_geometry_test_sector_inside; - ped_geometry_write; - ped_get_version; - ped_malloc; - ped_partition_destroy; - ped_partition_flag_get_by_name; - ped_partition_flag_get_name; - ped_partition_flag_next; - ped_partition_get_flag; - ped_partition_get_name; - ped_partition_get_path; - ped_partition_is_active; - ped_partition_is_busy; - ped_partition_is_flag_available; - ped_partition_new; - ped_partition_set_flag; - ped_partition_set_name; - ped_partition_set_system; - ped_partition_type_get_name; - ped_realloc; - ped_timer_destroy; - ped_timer_new; - ped_timer_reset; - ped_timer_set_state_name; - ped_timer_update; - ped_unit_format; - ped_unit_format_byte; - ped_unit_format_custom; - ped_unit_get_by_name; - ped_unit_get_default; - ped_unit_get_name; - ped_unit_parse; - ped_unit_set_default; - program_name { FLAGS = PARENT }; - version_etc; - xalloc_die; - xmalloc; - xrealloc; - xstrdup; - local: - *; -}; diff --git a/usr/src/man/man1m/Makefile b/usr/src/man/man1m/Makefile index 2a7e41030d..cd58ae6a90 100644 --- a/usr/src/man/man1m/Makefile +++ b/usr/src/man/man1m/Makefile @@ -598,21 +598,8 @@ _MANFILES= 6to4relay.1m \ zpool.1m \ zstreamdump.1m -i386_MANFILES= lms.1m \ - parted.1m \ - mkntfs.1m \ - ntfscat.1m \ - ntfsclone.1m \ - ntfscluster.1m \ - ntfscmp.1m \ - ntfscp.1m \ - ntfsfix.1m \ - ntfsinfo.1m \ - ntfslabel.1m \ - ntfsls.1m \ - ntfsprogs.1m \ - ntfsresize.1m \ - ntfsundelete.1m +i386_MANFILES= \ + lms.1m sparc_MANFILES= cvcd.1m \ dcs.1m \ diff --git a/usr/src/man/man1m/mkntfs.1m b/usr/src/man/man1m/mkntfs.1m deleted file mode 100644 index 98921794ca..0000000000 --- a/usr/src/man/man1m/mkntfs.1m +++ /dev/null @@ -1,319 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH MKNTFS 1M "May 27, 2009" -.SH NAME -mkntfs \- create an NTFS file system -.SH SYNOPSIS -.LP -.nf -\fBmkntfs\fR [\fIoptions\fR] \fIdevice\fR [\fInumber_of_sectors\fR] -.fi - -.LP -.nf -\fBmkntfs\fR [\fB-C\fR] [\fB-c\fR \fIcluster-size\fR] [\fB-F\fR] [\fB-f\fR] [\fB-H\fR \fIheads\fR] [\fB-h\fR] [\fB-I\fR] - [\fB-L\fR \fIvolume-label\fR] [\fB-l\fR] [\fB-n\fR] [\fB-p\fR \fIpart-start-sect\fR] [\fB-Q\fR] [\fB-q\fR] - [\fB-S\fR \fIsectors-per-track\fR] [\fB-s\fR \fIsector-size\fR] [\fB-T\fR] [\fB-V\fR] [\fB-v\fR] - [\fB-z\fR \fImft-zone-multiplier\fR] [\fB--debug\fR] \fIdevice\fR [\fInumber-of-sectors\fR] -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBmkntfs\fR utility is used to create an NTFS file system on a device, -usually a disk partition, or file. The \fIdevice\fR operand is the special -file corresponding to the device; for example, \fB/dev/dsk/c0d0p0\fR. The -\fInumber-of-sectors\fR operand is the number of blocks on the device. If -omitted, \fBmkntfs\fR automatically figures the file system size. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.LP -Options are divided among basic, advanced, output, and help options, as listed -below. -.SS "Basic Options" -.sp -.ne 2 -.na -\fB\fB-C\fR, \fB--enable-compression\fR\fR -.ad -.sp .6 -.RS 4n -Enable compression on the volume. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--fast\fR or \fB-q\fR, \fB--quick\fR\fR -.ad -.sp .6 -.RS 4n -Perform quick (fast) format. This option skips both zeroing of the volume and -bad sector checking. -.RE - -.sp -.ne 2 -.na -\fB\fB-L\fR, \fB--label\fR \fIstring\fR\fR -.ad -.sp .6 -.RS 4n -Set the volume label for the filesystem to \fIstring\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-n\fR, \fB--no-action\fR\fR -.ad -.sp .6 -.RS 4n -Causes \fBmkntfs\fR to not actually create a file system, but display what it -would do if it were to create a file system. All formatting steps are carried -out except the actual writing to the device. -.RE - -.SS "Advanced Options" -.sp -.ne 2 -.na -\fB\fB-c\fR, \fB--cluster-size\fR \fIbytes\fR\fR -.ad -.sp .6 -.RS 4n -Specify the size of clusters in bytes. Valid cluster size values are powers of -two, with at least 256, and at most 65536, bytes per cluster. If omitted, -\fBmkntfs\fR uses 4096 bytes as the default cluster size. -.sp -Note that the default cluster size is set to be at least equal to the sector -size, as a cluster cannot be smaller than a sector. Also, note that values -greater than 4096 have the side effect that compression is disabled on the -volume. This is due to limitations in the NTFS compression algorithm used by -Windows. -.RE - -.sp -.ne 2 -.na -\fB\fB-F\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Force \fBmkntfs\fR to run, even if the specified device is not a block special -device, or appears to be mounted. -.RE - -.sp -.ne 2 -.na -\fB\fB-H\fR, \fB--heads\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Specify the number of heads. The maximum is 65535 (0xffff). If omitted, -\fBmkntfs\fR attempts to determine the number of heads automatically. If that -fails a default of 0 is used. Note that specifying \fInum\fR is required for -Windows to be able to boot from the created volume. -.RE - -.sp -.ne 2 -.na -\fB\fB-I\fR, \fB--no-indexing\fR\fR -.ad -.sp .6 -.RS 4n -Disable content indexing on the volume. This option is only meaningful on -Windows 2000 and later. Windows NT 4.0 and earlier ignore this, as they do not -implement content indexing. -.RE - -.sp -.ne 2 -.na -\fB\fB-p\fR, \fB--partition-start\fR \fIsector\fR\fR -.ad -.sp .6 -.RS 4n -Specify the partition start sector. The maximum is 4294967295 (2^32-1). If -omitted, \fBmkntfs\fR attempts to determine \fIsector\fRautomatically. If that -fails, a default of 0 is used. Note that specifying \fIsector\fR is required -for Windows to be able to boot from the created volume. -.RE - -.sp -.ne 2 -.na -\fB\fB-S\fR, \fB--sectors-per-track\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Specify the number of sectors per track. The maximum is 65535 (0xffff). If -omitted, mkntfs attempts to determine the number of sectors-per-track -automatically and if that fails a default of 0 is used. Note that -sectors-per-track is required for Windows to be able to boot from the created -volume. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--sector-size\fR \fIbytes\fR\fR -.ad -.sp .6 -.RS 4n -Specify the size of sectors in bytes. Valid sector size values are 256, 512, -1024, 2048, and 4096. If omitted, \fBmkntfs\fR attempts to determine the -sector-size automatically. If that fails, a default of 512 bytes per sector is -used. -.RE - -.sp -.ne 2 -.na -\fB\fB-T\fR, \fB--zero-time\fR\fR -.ad -.sp .6 -.RS 4n -Fake the time to be 00:00:00 UTC, Jan 1, 1970, instead of the current system -time. This can be useful for debugging purposes. -.RE - -.sp -.ne 2 -.na -\fB\fB-z\fR, \fB--mft-zone-multiplier\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Set the master file table (MFT) zone multiplier, which determines the size of -the MFT zone to use on the volume. The MFT zone is the area at the beginning of -the volume reserved for the MFT, which stores the on-disk inodes (MFT records). -It is noteworthy that small files are stored entirely within the inode; thus, -if you expect to use the volume for storing large numbers of very small files, -it is useful to set the zone multiplier to a higher value. Although the MFT -zone is resized on the fly as required during operation of the NTFS driver, -choosing an optimal value reduces fragmentation. Valid values are \fB1\fR, -\fB2\fR, \fB3\fR, and \fB4\fR. The values have the following meaning: -.sp -.in +2 -.nf -MFT zone MFT zone size -multiplier (% of volume size) -1 12.5% (default) -2 25.0% -3 37.5% -4 50.0% -.fi -.in -2 -.sp - -.RE - -.SS "Output Options" -.sp -.ne 2 -.na -\fB\fB--debug\fR\fR -.ad -.sp .6 -.RS 4n -Includes the verbose output from the \fB-v\fR option, as well as additional -output useful for debugging \fBmkntfs\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Verbose execution. Errors are written to stderr, no output to stdout occurs at -all. Useful if \fBmkntfs\fR is run in a script. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Verbose execution. -.RE - -.SS "Help Options" -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each one. -.RE - -.sp -.ne 2 -.na -\fB\fB-l\fR, \fB--license\fR\fR -.ad -.sp .6 -.RS 4n -Display the \fBmkntfs\fR licensing information and exit. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Display the \fBmkntfs\fR version number and exit. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsprogs\fR(1M), \fBntfsresize\fR(1M), \fBntfsundelete\fR(1M), -\fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBmkntfs\fR was written by Anton Altaparmakov, Richard Russon, Erik Sornes and -Szabolcs Szakacsits. diff --git a/usr/src/man/man1m/ntfscat.1m b/usr/src/man/man1m/ntfscat.1m deleted file mode 100644 index 4166857579..0000000000 --- a/usr/src/man/man1m/ntfscat.1m +++ /dev/null @@ -1,217 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSCAT 1M "May 28, 2009" -.SH NAME -ntfscat \- display NTFS files and streams on the standard output -.SH SYNOPSIS -.LP -.nf -\fBntfscat\fR [\fIoptions\fR] \fIdevice\fR [\fIfile\fR] -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfscat\fR command reads a file or stream from an NTFS volume and -display the contents on the standard output. -.sp -.LP -The case of the filename passed to \fBntfscat\fR is ignored. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-a\fR, \fB--attribute\fR \fItype\fR\fR -.ad -.sp .6 -.RS 4n -Display the contents of a particular attribute type. By default, the unnamed -\fB$DATA\fR attribute will be shown. The attribute can be specified by a number -in decimal or hexadecimal, or by name. -.sp -.in +2 -.nf -Hex Decimal Name -0x10 16 "$STANDARD_INFORMATION" -0x20 32 "$ATTRIBUTE_LIST" -0x30 48 "$FILE_NAME" -0x40 64 "$OBJECT_ID" -0x50 80 "$SECURITY_DESCRIPTOR" -0x60 96 "$VOLUME_NAME" -0x70 112 "$VOLUME_INFORMATION" -0x80 128 "$DATA" -0x90 144 "$INDEX_ROOT" -0xA0 160 "$INDEX_ALLOCATION" -0xB0 176 "$BITMAP" -0xC0 192 "$REPARSE_POINT" -0xD0 208 "$EA_INFORMATION" -0xE0 224 "$EA" -0xF0 240 "$PROPERTY_SET" -0x100 256 "$LOGGED_UTILITY_STREAM" -.fi -.in -2 -.sp - -The attribute names can be specified without the leading dollar sign (\fB$\fR) -symbol. If you use the \fB$\fR symbol, you must quote the name to prevent the -shell from interpreting the name. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not using a mounted volume. Use this -option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--inode\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Specify a file by its inode number instead of its name. -.RE - -.sp -.ne 2 -.na -\fB\fB-n\fR, \fB--attribute-name\fR \fIname\fR\fR -.ad -.sp .6 -.RS 4n -Display the attribute identified by \fIname\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH EXAMPLES -.LP -\fBExample 1 \fRDisplaying Contents of File in Root -.sp -.LP -The following command displays the contents of a file in the root of an NTFS -volume. - -.sp -.in +2 -.nf -# \fBntfscat /dev/dsk/c0d0p1 boot.ini\fR -.fi -.in -2 -.sp - -.LP -\fBExample 2 \fRDisplaying Contents of File in Subdirectory -.sp -.LP -The following command displays the contents of a file in a subdirectory of an -NTFS volume. - -.sp -.in +2 -.nf -# \fBntfscat /dev/dsk/c0d0p1 /winnt/system32/drivers/etc/hosts\fR -.fi -.in -2 -.sp - -.LP -\fBExample 3 \fRDisplay Contents of an Attribute -.sp -.LP -The following command displays the contents of the \fB$INDEX_ROOT\fR attribute -of the root directory (inode 5). - -.sp -.in +2 -.nf -# \fBntfscat /dev/dsk/c0d0p1 -a INDEX_ROOT -i 5\fR -.fi -.in -2 -.sp - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsls\fR(1M), \fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfscat\fR was written by Richard Russon, Anton Altaparmakov and Szabolcs -Szakacsits. diff --git a/usr/src/man/man1m/ntfsclone.1m b/usr/src/man/man1m/ntfsclone.1m deleted file mode 100644 index a288e018fe..0000000000 --- a/usr/src/man/man1m/ntfsclone.1m +++ /dev/null @@ -1,460 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSCLONE 1M "May 14, 2009" -.SH NAME -ntfsclone \- clone, image, restore, or rescue an NTFS -.SH SYNOPSIS -.LP -.nf -\fBntfsclone\fR [\fIoptions\fR] \fIsource\fR -.fi - -.LP -.nf -\fBntfsclone\fR \fB--save-image\fR [\fIoptions\fR] \fIsource\fR -.fi - -.LP -.nf -\fBntfsclone\fR \fB--resotore-image\fR [\fIoptions\fR] \fIsource\fR -.fi - -.LP -.nf -\fBntfsclone\fR \fB--metadata\fR [\fIoptions\fR] \fIsource\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsclone\fR utility efficiently clones (which includes copy, save, -backup, and restore operations) or rescues an NTFS filesystem to a sparse file, -an image, a device (partition), or to standard output. It works at disk sector -level and copies only the written data (that is, not empty space). Unused disk -space becomes zero (cloning to sparse file), encoded with control codes (saving -in special image format), left unchanged (cloning to a disk/partition) or -filled with zeros (cloning to standard output). -.sp -.LP -\fBntfsclone\fR can be useful in making backups\(emtaking an exact snapshot of -an NTFS filesystem\(emand restoring it later on. It also can be used to test -NTFS read/write functionality and allows you to troubleshoot users' issues -using the clone, without the risk of destroying the original file system. -.sp -.LP -If not using the special image format (see section of the same name below), the -clone is an exact copy of the original NTFS file system, from sector to sector. -Thus, it can also be mounted just like the original NTFS filesystem. For -example, if you clone to a file and the kernel has a loopback device and NTFS -support, then the file can be mounted using: -.sp -.in +2 -.nf -# \fBmount -t ntfs -o loop ntfsclone.img\fR -.fi -.in -2 -.sp - -.SS "Windows Cloning" -.sp -.LP -You must exercise great care to copy, move or restore a system or boot -partition to another computer, or to a different disk or partition (for -example, \fB/dev/dsk/c0d0p1\fR to \fB/dev/dsk/c0d0p2\fR, \fB/dev/dsk/c0d0p1\fR -to \fB/dev/dsk/c0d1p1\fR or to a different disk sector offset). -.sp -.LP -Under most circumstances, to enable Windows to boot you must copy, move, or -restore NTFS to the same partition that has the following characteristics as -the original partition and disk: -.RS +4 -.TP -.ie t \(bu -.el o -starts at the same sector -.RE -.RS +4 -.TP -.ie t \(bu -.el o -on the same type of disk -.RE -.RS +4 -.TP -.ie t \(bu -.el o -having the same BIOS legacy cylinder setting -.RE -.sp -.LP -The \fBntfsclone\fR utility guarantees an exact copy of NTFS but does not deal -with booting issues. This is by design: \fBntfsclone\fR is a file system, not a -system, utility. Its goal is only NTFS cloning, not Windows cloning. Because of -this, \fBntfsclone\fR can be used as a very fast and reliable building block -for Windows cloning, but is not a complete answer. You can find useful tips on -NTFS cloning at the NTFS web site, http://wiki.linux-ntfs.org\&. -.SS "Sparse Files" -.sp -.LP -A file containing unallocated blocks (holes) is referred to as a "sparse file". -The reported size of such files is always higher than the disk space consumed -by them. The \fBdu\fR(1) command reports the real disk space used by a sparse -file. The holes are always read as zeros. All major Linux file systems, such -as, \fBext2\fR, \fBext3\fR, \fBreiserfs\fR, \fBReiser4\fR, JFS, and XFS support -sparse files. However, the ISO 9600 CD-ROM file system, as one example, does -not. -.SS "Special Image Format" -.sp -.LP -It is recommended that you save an NTFS filesystem to a special image format. -Instead of representing unallocated blocks as holes, they are encoded using -control codes. Thus, the image saves space without requiring sparse file -support. The image format is ideal for streaming file system images over the -network. The disadvantage of the special image format is that you cannot mount -the image directly; you must first restore it. -.sp -.LP -To save an image using the special image format, use the \fB-s\fR or the -\fB--save-image\fR option. To restore an image, use the \fB-r\fR or the -\fB--restore-image\fR option. Note that you can restore images from standard -input by using a hyphen (\fB-\fR) as the source file. -.SS "Metadata-only Cloning" -.sp -.LP -Using the \fB-m\fR or \fB--metadata\fR option, \fBntfsclone\fR can save only -the NTFS metadata and the clone still will be mountable. In this usage, all -non-metadata file content is lost; reading back the data results in all zeros. -.sp -.LP -The metadata-only image can be compressed very well, usually to a size in the -range of 1 to 8 MB. It is convenient to transfer such an image for -investigation and troubleshooting. -.sp -.LP -In metadata-only mode, \fBntfsclone\fR saves none of the user's data, which -includes the resident user's data embedded into metadata. All is filled with -zeros. Moreover, all the file timestamps, and deleted and unused spaces inside -the metadata are filled with zeros. Thus, this mode is inappropriate, for -example, for forensic analyses. -.sp -.LP -Note that filenames are not removed. Because a filename might contain sensitive -information, consider the possibities for breaches of security or privacy -before sending out a metadata-only image. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Forces \fBntfsclone\fR to proceed, even if the filesystem is marked "dirty" -following a consistency check. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each one. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--ignore-fs-check\fR\fR -.ad -.sp .6 -.RS 4n -Ignore the result of the file system consistency check. This option can be used -only with the \fB--meta-data\fR option. Any clusters that cause an -inconsistency are saved. -.RE - -.sp -.ne 2 -.na -\fB\fB-m\fR, \fB--metadata\fR\fR -.ad -.sp .6 -.RS 4n -Clone only metadata. With this option, you must clone only to a file. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR, \fB--output\fR \fIfile\fR\fR -.ad -.sp .6 -.RS 4n -Clone NTFS to the non-existent \fIfile\fR. If \fIfile\fR is a hyphen (\fB-\fR), -clone to the standard output. -.RE - -.sp -.ne 2 -.na -\fB\fB-O\fR, \fB--overwrite\fR \fIfile\fR\fR -.ad -.sp .6 -.RS 4n -Clone NTFS to \fIfile\fR, overwriting \fIfile\fR if it already exists. -.RE - -.sp -.ne 2 -.na -\fB\fB--rescue\fR\fR -.ad -.sp .6 -.RS 4n -Ignore disk read errors so that a disk having bad sectors, for example, a -failing disk, can be rescued with minimal impact on the disk. \fBntfsclone\fR -works at the lowest, sector level in this mode, enabling more data to be -rescued. The contents of the unreadable sectors are filled with the question -mark (\fB?\fR) character; the beginning of such sectors are marked by the -string: \fBBadSector\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-r\fR, \fB--restore-image\fR \fIsource\fR\fR -.ad -.sp .6 -.RS 4n -Restore from the special image format specified by \fIsource\fR. If -\fIsource\fR is a hyphen (\fB-\fR), the image is read from the standard input. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--save-image\fR\fR -.ad -.sp .6 -.RS 4n -Save to the special image format. In terms of space usage and speed, this is -the most efficient option if imaging is done to the standard output. This -option is useful for image compression, encryption, or streaming through a -network. -.RE - -.SH EXAMPLES -.LP -\fBExample 1 \fRCloning with Overwrite Option -.sp -.LP -The following command clones with the \fB--overwrite\fR option. - -.sp -.in +2 -.nf -# \fBntfsclone --overwrite /dev/dsk/c0d2p1 /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 2 \fRSaving to Special Image Format -.sp -.LP -The following command clones to the special image format to its original -partition. - -.sp -.in +2 -.nf -# \fBntfsclone --save-image --output backup.img /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 3 \fRRestoring from a Special Image File -.sp -.LP -The following command restores an NTFS from a special image file. - -.sp -.in +2 -.nf -# \fBntfsclone --restore-image --overwrite /dev/dsk/c0d0p1 backup.img\fR -.fi -.in -2 -.sp - -.LP -\fBExample 4 \fRSaving to a Compressed Image -.sp -.LP -The following command saves an NTFS to a compressed image file. - -.sp -.in +2 -.nf -# \fBntfsclone --save-image -o - /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 5 \fRRestoring from a Compressed Image -.sp -.LP -The following command restores an NTFS volume from a compressed image file. - -.sp -.in +2 -.nf -# \fBgunzip -c backup.img.gz | \e\fR -\fBntfsclone --restore-image --overwrite /dev/dsk/c0d0p1 -\fR -.fi -.in -2 -.sp - -.LP -\fBExample 6 \fRBacking up to a Remote Host Using \fBssh\fR -.sp -.LP -The following command backs up to a remote host, using \fBssh\fR(1). Note that -\fBssh\fR will probably require a password. - -.sp -.in +2 -.nf -# \fBntfsclone --save-image --output - /dev/dsk/c0d0p1 | \e\fR -\fBgzip -c | ssh host `cat > backup.img.gz`\fR -.fi -.in -2 -.sp - -.LP -\fBExample 7 \fRRestoring from a Remote Host Using \fBssh\fR -.sp -.LP -The following command backs up to a remote host, using \fBssh\fR(1). Note that -\fBssh\fR will probably require a password. - -.sp -.in +2 -.nf -# \fBssh host `cat backup.img.gz` | gunzip -c | \e\fR -\fBntfsclone --restore-image --overwrite /dev/dsk/c0d0p1 -\fR -.fi -.in -2 -.sp - -.LP -\fBExample 8 \fRStreaming an Image File from a Web Server -.sp -.LP -The following command streams an image file from a web server and restore it to -a partition. - -.sp -.in +2 -.nf -# \fBwget -qO - http://server/backup.img | \e\fR -\fBntfsclone --restore-image --overwrite /dev/dsk/c0d0p1 -\fR -.fi -.in -2 -.sp - -.LP -\fBExample 9 \fRCloning to a New File -.sp -.LP -The following command clones an NTFS volume to a non-existent file. - -.sp -.in +2 -.nf -# \fBntfsclone --output ntfs-clone.img /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 10 \fRPacking NTFS Metadata -.sp -.LP -The following command packs NTFS metadata into an image file. Note that -\fBbzip2\fR takes a much longer time than \fBgzip\fR, but produces an archive -that is up to ten times smaller than the latter produces. - -.sp -.in +2 -.nf -# \fBntfsclone --metadata --output ntfsmeta.img /dev/dsk/c0d0p1\fR -\fBbzip2 ntfsmeta.img\fR -.fi -.in -2 -.sp - -.LP -\fBExample 11 \fRUnpacking NTFS Metadata -.sp -.LP -The following command unpacks NTFS metadata into a sparse file. - -.sp -.in +2 -.nf -# \fBbunzip2 -c ntfsmeta.img.bz2 | \e\fR -\fBcp --sparse=always /proc/self/fd/0 ntfsmeta.img\fR -.fi -.in -2 -.sp - -.SH EXIT STATUS -.sp -.LP -The return code is zero on success, non-zero otherwise. -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBdu\fR(1), \fBssh\fR(1), \fBntfsresize\fR(1M), \fBntfsundelete\fR(1M), -\fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfsclone\fR was written by Szabolcs Szakacsits with contributions from Per -Olofsson (special image format support) and Anton Altaparmakov. diff --git a/usr/src/man/man1m/ntfscluster.1m b/usr/src/man/man1m/ntfscluster.1m deleted file mode 100644 index 62494b22db..0000000000 --- a/usr/src/man/man1m/ntfscluster.1m +++ /dev/null @@ -1,225 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSCLUSTER 1M "May 28, 2009" -.SH NAME -ntfscluster \- identify files in a specified region of an NTFS volume -.SH SYNOPSIS -.LP -.nf -\fBntfscluster\fR [\fIoptions\fR] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfscluster\fR utility has three modes of operation: \fBinfo\fR, -\fBsector\fR, and \fBcluster\fR, described as follows. -.sp -.ne 2 -.na -\fB\fBInfo\fR\fR -.ad -.sp .6 -.RS 4n -The default mode, \fBinfo\fR is currently not implemented. It will display -general information about the NTFS volume when it is working. -.RE - -.sp -.ne 2 -.na -\fB\fBSector\fR\fR -.ad -.sp .6 -.RS 4n -The \fBsector\fR mode displays a list of files that have data in the specified -range of sectors. This mode is put in effect by the \fB--sector\fR option. -.RE - -.sp -.ne 2 -.na -\fB\fBCluster\fR\fR -.ad -.sp .6 -.RS 4n -The \fBcluster\fR mode displays a list of files that have data in the specified -range of clusters. When the cluster size is one sector, this is equivalent to -the \fBsector\fR mode of operation. This mode is put in effect by the -\fB--cluster\fR option. -.RE - -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-c\fR, \fB--cluster\fR \fIrange\fR\fR -.ad -.sp .6 -.RS 4n -Any files whose data is in this range of clusters will be displayed. -.RE - -.sp -.ne 2 -.na -\fB\fB-F\fR, \fB--filename\fR \fIfilename\fR\fR -.ad -.sp .6 -.RS 4n -Display information about \fIfilename\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not working with a mounted volume. -Use this option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each. -.RE - -.sp -.ne 2 -.na -\fB\fB-I\fR, \fB--inode\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Show information about this inode. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--info\fR\fR -.ad -.sp .6 -.RS 4n -This option is not yet implemented. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--sector\fR \fIrange\fR\fR -.ad -.sp .6 -.RS 4n -Any files whose data is in this range of sectors will be displayed. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH EXAMPLES -.LP -\fBExample 1 \fRDisplaying Information About a Volume -.sp -.LP -The following command displays information about the volume -\fB/dev/dsk/c0d0p1\fR. - -.sp -.in +2 -.nf -# \fBntfscluster /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 2 \fRDisplaying List of Files in a Cluster Range -.sp -.LP -The following command looks for files in the first 500 clusters of -\fB/dev/dsk/c0d0p1\fR. - -.sp -.in +2 -.nf -# \fBntfscluster -c 0-500 /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsinfo\fR(1M), \fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfscluster\fR was written by Richard Russon, with contributions from Anton -Altaparmakov. diff --git a/usr/src/man/man1m/ntfscmp.1m b/usr/src/man/man1m/ntfscmp.1m deleted file mode 100644 index 921ea78a0f..0000000000 --- a/usr/src/man/man1m/ntfscmp.1m +++ /dev/null @@ -1,104 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSCMP 1M "May 28, 2009" -.SH NAME -ntfscmp \- compare two NTFS file systems and report the differences -.SH SYNOPSIS -.LP -.nf -\fBntfscmp\fR [\fIoptions\fR] \fIdevice1\fR \fIdevice2\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfscmp\fR utility compares all aspects of two NTFS file systems and -reports all differences it finds. The file systems can be on block devices or -in image files. \fBntfscmp\fR can be used for volume verification. However, its -primary purpose is to be an efficient development tool, used to quickly locate, -identify, and check the correctness of the metadata changes made to NTFS. -.sp -.LP -If one is interested only in the NTFS metadata changes, it can be useful to -compare the metadata images created by using the \fB--metadata\fR option of -\fBntfsclone\fR(1M) to eliminate the usually uninteresting timestamp changes. -.sp -.LP -The terse output of \fBntfscmp\fR is intentional, because the provided -information is sufficient to determine exact differences. More copious output -can be obtained by using \fBdiff\fR(1) to compare the verbose output of -\fBntfsinfo\fR(1M) for each reported inode. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Options have both single-letter and -full-name forms. -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Display help and exit. -.RE - -.sp -.ne 2 -.na -\fB\fB-P\fR, \fB--no-progress-bar\fR\fR -.ad -.sp .6 -.RS 4n -Do not show progress bars. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH EXIT STATUS -.sp -.LP -The exit code is \fB0\fR on success, non-zero otherwise. -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBdiff\fR(1), \fBntfscat\fR(1M), \fBntfsclone\fR(1M), \fBntfsinfo\fR(1M), -\fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfscmp\fR was written by Szabolcs Szakacsits. diff --git a/usr/src/man/man1m/ntfscp.1m b/usr/src/man/man1m/ntfscp.1m deleted file mode 100644 index e18047fa8e..0000000000 --- a/usr/src/man/man1m/ntfscp.1m +++ /dev/null @@ -1,199 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSCP 1M "May 28, 2009" -.SH NAME -ntfscp \- copy file to an NTFS volume -.SH SYNOPSIS -.LP -.nf -\fBntfscp\fR [\fIoptions\fR] \fIdevice\fR \fIsource_file\fR \fIdestination\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfscp\fR utility copies files to an NTFS volume. \fIdestination\fR (see -Synopis) can be either a file or a directory. If \fIdestination\fR is a -directory specified by name, \fIsource_file\fR is copied into this directory. -If \fIdestination\fR is a directory specified by inode number, an unnamed data -attribute is created for this inode and \fIsource_file\fR is copied into it. -Consider possible negative consequence before specifying a directory by inode -number: it is unusual to have an unnamed data stream in a directory. -.SS "Data Streams" -.sp -.LP -All data on NTFS is stored in streams, which can have names. A file can have -more than one data stream, but exactly one must have no name. The size of a -file is the size of its unnamed data stream. Usually, when you do not specify a -stream name, you are seeking access to the unnamed data stream. If you want -access to a named data stream, you need to add \fB:\fR\fIstream_name\fR to the -filename. For example, by opening \fBsome.mp3:artist\fR you will open stream -\fBartist\fR in \fBsome.mp3\fR. In an operating system, such as Windows, that -prevents you from accessing named data streams, you need to use some program -like \fBFAR\fR or utilities from \fBcygwin\fR to access those streams. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-a\fR, \fB--attribute\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Write to attribute designated by \fInum\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not working with a mounted volume. -Use this option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each one. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--inode\fR\fR -.ad -.sp .6 -.RS 4n -Treat \fIdestination\fR (see Synopsis) as inode number. -.RE - -.sp -.ne 2 -.na -\fB\fB-N\fR, \fB--attr-name\fR \fIname\fR\fR -.ad -.sp .6 -.RS 4n -Write to attribute with this name. -.RE - -.sp -.ne 2 -.na -\fB\fB-n\fR, \fB--no-action\fR\fR -.ad -.sp .6 -.RS 4n -Use this option to make a test run before doing the actual copy operation. -Volume will be opened read-only and no write will be done. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH EXAMPLES -.LP -\fBExample 1 \fRCopying from Home to Root Directory -.sp -.LP -The following command copies \fBnew_boot.ini\fR from \fB/home/user\fR as -\fBboot.ini\fR to the root of an \fB/dev/dsk/c0d0p1\fR NTFS volume. - -.sp -.in +2 -.nf -# \fBntfscp /dev/dsk/c0d0p1 /home/user/new_boot.ini boot.ini\fR -.fi -.in -2 -.sp - -.LP -\fBExample 2 \fRCopying a Stream -.sp -.LP -The following command copies \fBmyfile\fR to \fBC:\some\path\myfile:stream\fR -(assume that \fB/dev/dsk/c0d0p1\fR drive designator is \fBC\fR). - -.sp -.in +2 -.nf -# \fBntfscp -N stream /dev/dsk/c0d0p1 myfile /some/path\fR -.fi -.in -2 -.sp - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsresize\fR(1M), \fBntfsprogs\fR(1M), \fBparted\fR(1M), -\fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfscp\fR was written by Yura Pakhuchiy, with contributions from Anton -Altaparmakov and Hil Liao. diff --git a/usr/src/man/man1m/ntfsfix.1m b/usr/src/man/man1m/ntfsfix.1m deleted file mode 100644 index c2e2ae13c2..0000000000 --- a/usr/src/man/man1m/ntfsfix.1m +++ /dev/null @@ -1,81 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSFIX 1M "May 28, 2009" -.SH NAME -ntfsfix \- fix common errors and force operating system to check NTFS -.SH SYNOPSIS -.LP -.nf -\fBntfsfix\fR [\fIoptions\fR] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsfix\fR utility fixes some common NTFS problems. Note that it is not -a version of \fBchkdsk\fR. It repairs some fundamental NTFS inconsistencies, -resets the NTFS journal file, and schedules an NTFS consistency check for the -next reboot of the operating system. -.sp -.LP -Run \fBntfsfix\fR on an NTFS volume if you think it was damaged by the -operating system or in some other way and it cannot be mounted. -.SH OPTIONS -.sp -.LP -Supported options are listed below. -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBmkntfs\fR(1M), \fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfsfix\fR was written by Anton Altaparmakov, with contributions from -Szabolcs Szakacsits. diff --git a/usr/src/man/man1m/ntfsinfo.1m b/usr/src/man/man1m/ntfsinfo.1m deleted file mode 100644 index 147d130a69..0000000000 --- a/usr/src/man/man1m/ntfsinfo.1m +++ /dev/null @@ -1,151 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSINFO 1M "May 28, 2009" -.SH NAME -ntfsinfo \- dump a file's attributes -.SH SYNOPSIS -.LP -.nf -\fBntfsinfo\fR [\fIoptions\fR] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsinfo\fR utility dumps the attributes of inode \fIinode-number\fR or -the file \fIpath-filename\fR and/or information about the MFT (\fB-m\fR -option). Run \fBntfsinfo\fR without arguments for a full list of options. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-F\fR, \fB--file\fR \fIfile\fR\fR -.ad -.sp .6 -.RS 4n -Show information about \fIfile\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not overwriting an existing file. Use -this option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--inode\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Show information about inode identified by \fInum\fR. -.RE - -.sp -.ne 2 -.na -\fB\fB-m\fR, \fB--mft\fR\fR -.ad -.sp .6 -.RS 4n -Show information about the volume. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-t\fR, \fB--notime\fR\fR -.ad -.sp .6 -.RS 4n -Do not display timestamps in the output. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsprogs\fR(1M), \fBntfsundelete\fR(1M), \fBparted\fR(1M), -\fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfsinfo\fR was written by Matthew J. Fanto, Anton Altaparmakov, Richard -Russon, Szabolcs Szakacsits, Yuval Fledel, Yura Pakhuchiy and Cristian Klein. diff --git a/usr/src/man/man1m/ntfslabel.1m b/usr/src/man/man1m/ntfslabel.1m deleted file mode 100644 index f8ec796def..0000000000 --- a/usr/src/man/man1m/ntfslabel.1m +++ /dev/null @@ -1,133 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSLABEL 1M "May 28, 2009" -.SH NAME -ntfslabel \- display or change the label on an NTFS file system -.SH SYNOPSIS -.LP -.nf -\fBntfslabel\fR [\fIoptions\fR] \fIdevice\fR [\fInew_label\fR] -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfslabel\fR utility displays or changes the file system label on the -NTFS file system located on \fIdevice\fR (see Synopsis). -.sp -.LP -If the optional argument \fInew_label\fR is not present, \fBntfslabel\fR -displays the current file system label. -.sp -.LP -If the optional argument \fInew_label\fR is present, \fBntfslabel\fR sets the -file system label to be \fInew_label\fR. NTFS file system labels can be at most -128 Unicode characters long; if \fInew_label\fR is longer than 128 Unicode -characters, \fBntfslabel\fR truncates it and displays a warning message. -.sp -.LP -It is also possible to set the file system label using the \fB-L\fR option of -\fBmkntfs\fR(1M) during creation of the file system. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not working with a mounted volume. -Use this option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each. -.RE - -.sp -.ne 2 -.na -\fB\fB-n\fR, \fB--no-action\fR\fR -.ad -.sp .6 -.RS 4n -Do not actually write a new label to disk. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Show the version number, copyright, and license information. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBmkntfs\fR(1M), \fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfslabel\fR was written by Matthew J. Fanto, with contributions from Anton -Altaparmakov and Richard Russon. diff --git a/usr/src/man/man1m/ntfsls.1m b/usr/src/man/man1m/ntfsls.1m deleted file mode 100644 index 8202a955e5..0000000000 --- a/usr/src/man/man1m/ntfsls.1m +++ /dev/null @@ -1,204 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSLS 1M "May 28, 2009" -.SH NAME -ntfsls \- list directory contents on an NTFS file system -.SH SYNOPSIS -.LP -.nf -\fBntfsls\fR [\fIoptions\fR] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsls\fR utility lists information about the files specified by the -\fBPATH\fR option (the root directory by default). \fIdevice\fR (see Synopsis) -is the special file corresponding to the device (for example, -\fB/dev/dsk/c0d0p0\fR\fInum\fR) or an NTFS image file. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-a\fR, \fB--all\fR\fR -.ad -.sp .6 -.RS 4n -Display all files. If this option is not specified file names in the POSIX -namespace are not displayed. -.RE - -.sp -.ne 2 -.na -\fB\fB-F\fR, \fB--classify\fR\fR -.ad -.sp .6 -.RS 4n -Append one of the indicators shown below to entries. -.sp -.in +2 -.nf -* / = @ | -.fi -.in -2 -.sp - -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Force execution. For example, this option is necessary to run on an NTFS -partition stored in a normal file. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Display usage information and exit. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--inode\fR\fR -.ad -.sp .6 -.RS 4n -Display the inode number of each file. This is the MFT reference number, in -NTFS terminology. -.RE - -.sp -.ne 2 -.na -\fB\fB-l\fR, \fB--long\fR\fR -.ad -.sp .6 -.RS 4n -Use a long listing format. -.RE - -.sp -.ne 2 -.na -\fB\fB-p\fR, \fB--path\fR \fIpath\fR\fR -.ad -.sp .6 -.RS 4n -The directory whose contents to list or the file (including the path) about -which to display information. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Suppress some debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-R\fR, \fB--recursive\fR\fR -.ad -.sp .6 -.RS 4n -Show the contents of all directories beneath the specified directory. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--system\fR\fR -.ad -.sp .6 -.RS 4n -Unless this options is specified, all files beginning with a dollar sign -character will not be listed, as these files are usually system files. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display more debug, warning, and error messages. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Display the \fBntfsls\fR version number and exit. -.RE - -.sp -.ne 2 -.na -\fB\fB-x\fR, \fB--dos\fR\fR -.ad -.sp .6 -.RS 4n -Display short file names, that is, files in the DOS namespace, instead of long -file names, that is, files in the WIN32 namespace. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -, \fBntfsprogs\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -This version of \fBntfsls\fR was written by Lode Leroy, Anton Altaparmakov, -Richard Russon, Carmelo Kintana and Giang Nguyen. diff --git a/usr/src/man/man1m/ntfsprogs.1m b/usr/src/man/man1m/ntfsprogs.1m deleted file mode 100644 index 8be9e8f989..0000000000 --- a/usr/src/man/man1m/ntfsprogs.1m +++ /dev/null @@ -1,185 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSPROGS 1M "May 28, 2009" -.SH NAME -ntfsprogs \- list of NTFS tools -.SH SYNOPSIS -.LP -.nf -\fBntfsprogs\fR -.fi - -.SH DESCRIPTION -.sp -.LP -\fBntfsprogs\fR is the name of a suite of NTFS utilities based around a shared -library. The tools are available for free and come with full source code. The -tools are listed below. -.sp -.ne 2 -.na -\fB\fBmkntfs\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Create an NTFS filesystem. -.RE - -.sp -.ne 2 -.na -\fB\fBntfscat\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Dump a file's content to the standard output. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsclone\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Efficiently clone, backup, restore, or rescue NTFS. -.RE - -.sp -.ne 2 -.na -\fB\fBntfscluster\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Locate the files that use the specified sectors or clusters. -.RE - -.sp -.ne 2 -.na -\fB\fBntfscmp\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Compare two NTFS file systems and report the differences. -.RE - -.sp -.ne 2 -.na -\fB\fBntfscp\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Copy a file to an NTFS volume. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsfix\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Check and fix some common errors, clear the log file, and make the operating -system perform a thorough check next time it boots. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsinfo\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Show information about NTFS or one of the files or directories within it. -.RE - -.sp -.ne 2 -.na -\fB\fBntfslabel\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Show, or set, an NTFS filesystem's volume label. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsls\fR(1M)\fR -.ad -.sp .6 -.RS 4n -List information about files in a directory residing on an NTFS. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsmount(1M)\fR (not a SunOS man page)\fR -.ad -.sp .6 -.RS 4n -Read-write NTFS user space driver. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsresize\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Resize NTFS without losing data. -.RE - -.sp -.ne 2 -.na -\fB\fBntfsundelete\fR(1M)\fR -.ad -.sp .6 -.RS 4n -Recover deleted files from NTFS. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -The tools were written by Anton Altaparmakov, Carmelo Kintana, Cristian Klein, -Erik Sornes, Giang Nguyen, Holger Ohmacht, Lode Leroy, Matthew J. Fanto, Per -Olofsson, Richard Russon, Szabolcs Szakacsits, Yura Pakhuchiy, and Yuval -Fledel. diff --git a/usr/src/man/man1m/ntfsresize.1m b/usr/src/man/man1m/ntfsresize.1m deleted file mode 100644 index 34a72a9b09..0000000000 --- a/usr/src/man/man1m/ntfsresize.1m +++ /dev/null @@ -1,280 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSRESIZE 1M "May 21, 2009" -.SH NAME -ntfsresize \- resize an NTFS file system without data loss -.SH SYNOPSIS -.LP -.nf -\fBntfsresize\fR [\fIoptions\fR] \fB--info\fR \fIdevice\fR -.fi - -.LP -.nf -\fBntfsresize\fR [\fIoptions\fR] [\fB--size\fR \fIsize\fR[k|M|G]] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsresize\fR program safely resizes Windows XP, Windows Server 2003, -Windows 2000, Windows NT4 and Longhorn NTFS filesystems without data loss. All -NTFS versions used by 32-bit and 64-bit Windows "operating systems" are -supported. Defragmentation is not required prior to resizing, because -\fBntfsresize\fR can relocate any data if needed, without risking data -integrity. -.sp -.LP -\fBntfsresize\fR can be used to shrink or enlarge any NTFS file system located -on an unmounted device (usually a disk partition). The new file system will -have a size that you specify. The size parameter can have one of the optional -modifiers \fBk\fR, \fBM\fR, \fBG\fR, denoting, respectively, kilobytes, -megabytes, or gigabytes. \fBntfsresize\fR conforms to the SI, ATA, an IEEE -standards and the disk manufacturers by supporting \fBk=10\fR^3, \fBM=10\fR^6 -and \fBG=10\fR^9. -.sp -.LP -If both \fB---info\fR and \fB---size\fR options are omitted then the NTFS file -system will be enlarged to the underlying device size. -.sp -.LP -To resize a file system on a partition, you must resize both the file system -and the partition, by editing the partition table on the disk. Similarly to -other command-line file system resizers, \fBntfsresize\fR does not manipulate -the size of the partitions. To do that you must use a disk partitioning tool, -such as \fBfdisk\fR(1M). Alternatively, you could use one of the many user -friendly partitioners that uses \fBntfsresize\fR internally. Such partitioners -include, among others, Mandriva's DiskDrake, QTParted, SUSE/Novell's YaST -Partitioner, IBM's EVMS, GParted, or Debian/Ubuntu's Partman. -.sp -.LP -Back up your data and your partition table before using any partitioning tool. -For an NTFS file system, you can use \fBntfsclone\fR(1M) as a means of backup. -.sp -.LP -To shrink an NTFS partition, first use \fBntfsresize\fR to shrink the size of -the file system. Then use a utility such as \fBfdisk\fR(1M) to shrink the size -of the partition by deleting the partition and recreating it with the smaller -size. Do not make the partition smaller than the new size of NTFS; otherwise, -you will not be able to boot from that partition. If you mistakenly made a -too-small partition, you would have to recreate the partition to be as large as -newly sized NTFS file system. -.sp -.LP -To enlarge an NTFS file system, you must first enlarge the size of the -underlying partition. You can use \fBfdisk\fR(1M) to delete the partition and -recreate it with a larger size. Make sure the newly sized partition does not -overlap with any other partition. Then use \fBntfsresize\fR to enlarge the file -system. -.sp -.LP -When recreating a partition, make sure you create it at the same starting -sector and with the same partition type as was used in the partition you are -replacing. Otherwise, you will not be able to access your file system. Use the -\fBfdisk u\fR command to switch from the default cylinder unit to the reliable -sector unit. Also, if the bootable flag was set in the old partition, make sure -to set it in the recreated partiton. Otherwise, you might not be able to boot -from the new partition. -.SH EXTENDED DESCRIPTION -.sp -.LP -There are a handful of very rarely met restrictions in the use of -\fBntfsresize\fR. An example of such a restriction occurs with a file system -stored on a disk having unknown bad sectors. Relocation of the first \fBMFT\fR -extent and resizing into the middle of a \fB$MFTMirr\fR extent are not -supported. These cases are detected and resizing is restricted to a safe size -or the closest safe size is displayed. -.sp -.LP -Upon completion of a resizing, \fBntfsresize\fR schedules an NTFS consistency -check. In Windows, this check is performed by \fBchkdsk\fR. Upon the first -subsequent reboot into Windows, you will note \fBchkdsk\fR running in a blue -background. This is normal. Windows might force a quick reboot after the -consistency check. Depending on your hardware configuration, Windows might -alert you to a systems setting change and recommend or require a reboot. -Acknowledge the message and reboot a second time. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-b\fR, \fB--bad-sectors\fR\fR -.ad -.sp .6 -.RS 4n -By default, \fBntfsresize\fR exits upon encountering bad sectors. This option -allows the utility to proceed in spite of such sectors. -.sp -Prior using this option, it is strongly recommended that you use -\fBntfsclone\fR(1M) with the \fB--rescue\fR option to make a backup, then, in -Windows, run \fBchkdsk /f /r volume\fR: from the command line. If the disk -guarantee displays as valid, then replace it, as it is defective. Note that no -software can repair bad sector errors. The most that can be done is to work -around these defects. -.sp -This option has no effect if a disk has no bad sectors. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -\fBntfsresize\fR always marks a file system for consistency check before a real -(not using \fB--no-action\fR) resize operation and it leaves that way for extra -safety. Thus, if an NTFS file system was marked by \fBntfsresize\fR, it is safe -to use this option. You must use this option, if you need to resize several -times without booting into Windows between each resizing step. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Display usage information and exit. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--info\fR\fR -.ad -.sp .6 -.RS 4n -Used when you want to shrink a file system. Causes \fBntfsresize\fR to -determine the smallest shrunken file system size supported. Most of the time -the smallest size is the space already used on the file system. -\fBntfsresize\fR does not shrink a file system to a smaller size than what is -returned by this option. Depending on several factors, it might be unable to -shrink to this theoretical size. Although the integrity of your data should be -never at risk, it is nevertheless strongly recommended to make a test run by -using the \fB--no-action\fR option before actual resizing. -.sp -Based on testing, the smallest attainable size is approximately space used in -the file system plus 20-200 MB. Note also that Windows might need an additional -50-100 MB to boot safely. -.sp -This option never causes any changes to the file system; the partition is -opened read-only. -.RE - -.sp -.ne 2 -.na -\fB\fB-n\fR, \fB--no-action\fR\fR -.ad -.sp .6 -.RS 4n -Use this option to make a test run before doing the resize operation. Volume -will be opened read-only and \fBntfsresize\fR displays what it would do if it -were to resize the file system. Proceed with the actual resizing only if the -test run passed. -.RE - -.sp -.ne 2 -.na -\fB\fB-P\fR, \fB--no-progress-bar\fR\fR -.ad -.sp .6 -.RS 4n -Do not display progress bars during \fBntfsresize\fR operation. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--size\fR \fIsize\fR[k|M|G]]\fR -.ad -.sp .6 -.RS 4n -Resize file system to \fIsize\fR bytes. The new file system will have a size -that you specify. The size parameter can have one of the optional modifiers -\fBk\fR, \fBM\fR, \fBG\fR, denoting, respectively, kilobytes, megabytes, or -gigabytes. \fBntfsresize\fR conforms to the SI, ATA, an IEEE standards and the -disk manufacturers by supporting \fBk=10\fR^3, \fBM=10\fR^6 and \fBG=10\fR^9. -Before performing an actual resizing, run \fBntfsresize\fR with the -\fB--no-action\fR option, along with this option, first. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR\fR -.ad -.sp .6 -.RS 4n -Display copious output. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Display the version number of \fBntfsresize\fR. -.RE - -.SH EXIT STATUS -.sp -.LP -Display zero on success, non-zero otherwise. -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBfdisk\fR(1M), \fBntfsclone\fR(1M), \fBparted\fR(1M), \fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH NOTES -.sp -.LP -In Linux version 2.6, with partitions that have been manipulated by -\fBparted\fR(1M), use of \fBntfsresize\fR preceded corruption of partition -tables, which resulted in unbootable Windows systems. This occurred even if the -NTFS file system was consistent. This problem is independent of NTFS and, thus, -\fBntfsresize\fR. Moreover, \fBntfsresize\fR never touches the partition table. -Under the conditions just described, you can, in the BIOS, change \fBDisk -Access Mode\fR to \fBLBA\fR to regain the ability to boot. For further -discussion of this condition see the \fBntfsresize\fR FAQ at: -\fBhttp://mlf.linux.rulez.org/mlf/ezaz/ntfsresize.html\fR. -.SH AUTHORS -.sp -.LP -\fBntfsresize\fR was written by Szabolcs Szakacsits, with contributions from -Anton Altaparmakov and Richard Russon. diff --git a/usr/src/man/man1m/ntfsundelete.1m b/usr/src/man/man1m/ntfsundelete.1m deleted file mode 100644 index 62ed3ad473..0000000000 --- a/usr/src/man/man1m/ntfsundelete.1m +++ /dev/null @@ -1,476 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (c) 2002-2006 Szabolcs Szakacsits -.\" Copyright (c) 2002-2005 Anton Altaparmakov -.\" Copyright (c) 2002-2003 Richard Russon -.\" Copyright (c) 2007 Yura Pakhuchiy -.\" 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 -.\" (in the main directory of the Linux-NTFS distribution in the file COPYING); if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 11-1307 USA -.TH NTFSUNDELETE 1M "May 22, 2009" -.SH NAME -ntfsundelete \- recover a deleted file from an NTFS volume -.SH SYNOPSIS -.LP -.nf -\fBntfsundelete\fR [\fIoptions\fR] \fIdevice\fR -.fi - -.SH DESCRIPTION -.sp -.LP -The \fBntfsundelete\fR utility can, under the right circumstances, recover a -deleted file from an NTFS volume. The command has three modes of operation: -.sp -.ne 2 -.na -\fB\fBScan\fR\fR -.ad -.sp .6 -.RS 4n -The default mode, \fBscan\fR simply reads an NTFS Volume and looks for files -that have been deleted. It then displays a list, giving the inode number, name, -and size of each deleted file. -.RE - -.sp -.ne 2 -.na -\fB\fBUndelete\fR\fR -.ad -.sp .6 -.RS 4n -The undelete mode takes the files either matching the regular expression -(option \fB-m\fR) or specified by the \fIinode-expressions\fR and recovers as -much of the data as possible. It saves the result to another location. -.RE - -.sp -.ne 2 -.na -\fB\fBCopy\fR\fR -.ad -.sp .6 -.RS 4n -The "wizard's" option. Saves a portion of the MFT to a file, which can be -useful when debugging \fBntfsundelete\fR. -.RE - -.sp -.LP -There are many circumstances under which \fBntfsundelete\fR is unable to -recover a file. For example, consider the following scenario. When a file is -deleted the MFT Record is marked as not in use and the bitmap representing the -disk usage is updated. If the power is not turned off immediately, the free -space, where the file used to reside might get overwritten. Worse, the MFT -Record might be reused for another file. If this happens, it is impossible to -tell where the file was on disk. -.sp -.LP -Even if all the clusters of a file are not in use, there is no guarantee that -they have not been overwritten by some short-lived file. -.sp -.LP -\fBntfsundelete\fR cannot recover compressed or encrypted files. During a scan, -it will display such a file as being 0% recoverable. -.SS "Locale" -.sp -.LP -In NTFS, all filenames are stored as Unicode. A filename is converted into the -current locale for display by \fBntfsundelete\fR. The utility has successfully -displayed Chinese pictogram filenames and then correctly recovered them. -.SS "Extended MFT Records" -.sp -.LP -In rare circumstances, a single MFT Record will not be large enough to hold the -metadata describing a file (a file would have to be in hundreds of fragments -for this to happen). In these cases, one MFT record might hold the filename, -while another will hold the information about the data. \fBntfsundelete\fR will -not try and piece together such records. It will simply list unnamed files with -data. -.SS "Recovered File's Size and Creation Date" -.sp -.LP -To recover a file, \fBntfsundelete\fR has to read the file's metadata. -Unfortunately, when a file is deleted, the metadata can be left in an -inconsistent state. For example, the file size might be recorded as zero; the -creation date of a file might be set to the time it was deleted or to a random -time. In such situations, \fBntfsundelete\fR picks the largest file size it -finds and writes that to disk. It also tries to set the file's creation date to -the last-modified date. This date might be the correct last modified date, or -something unexpected. -.SH OPTIONS -.sp -.LP -Supported options are listed below. Most options have both single-letter and -full-name forms. Multiple single-letter options that do not take an argument -can be combined. For example, \fB-fv\fR is the equivalent of \fB-f\fR \fB-v\fR. -A full-name option can be abbreviated to a unique prefix of its name. -.sp -.ne 2 -.na -\fB\fB-b\fR, \fB--byte\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Fill in the parts of unrecoverable file clusters with byte represented by -\fInum\fR. The default is zeros. -.RE - -.sp -.ne 2 -.na -\fB\fB-C\fR, \fB--case\fR\fR -.ad -.sp .6 -.RS 4n -Make filename search, when attempting a match with the \fB--match\fR option, -case-sensitive. The default filename search is case-insensitive. -.RE - -.sp -.ne 2 -.na -\fB\fB-c\fR, \fB--copy\fR \fIrange\fR\fR -.ad -.sp .6 -.RS 4n -This "wizard" option writes a block of MFT FILE records to a file. The default -file is mft which will be created in the current directory. This option can be -combined with the \fB--output\fR and \fB--destination\fR options. -.RE - -.sp -.ne 2 -.na -\fB\fB-d\fR, \fB--destination\fR \fIdir\fR\fR -.ad -.sp .6 -.RS 4n -Specify the location of the output file for the \fB--copy\fR and -\fB--undelete\fR options. -.RE - -.sp -.ne 2 -.na -\fB\fB-f\fR, \fB--force\fR\fR -.ad -.sp .6 -.RS 4n -Overrides some sensible defaults, such as not overwriting an existing file. Use -this option with caution. -.RE - -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Show a list of options with a brief description of each one. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--inodes\fR \fIrange\fR\fR -.ad -.sp .6 -.RS 4n -Recover the files within the specified range of inode numbers. \fIrange\fR can -be a single inode number, several numbers separated by commas, or a range -separated by a dash (\fB-\fR). -.RE - -.sp -.ne 2 -.na -\fB\fB-m\fR, \fB--match\fR \fIpattern\fR\fR -.ad -.sp .6 -.RS 4n -Filter the output by looking only for filenames that match \fIpattern\fR. The -pattern can include the wildcards \fB?\fR, matching exactly one character, or -\fB*\fR, matching zero or more characters. By default, the matching is -case-insensitive. To make the search case-sensitive, use the \fB--case\fR -option. -.RE - -.sp -.ne 2 -.na -\fB\fB-O\fR, \fB--optimistic\fR\fR -.ad -.sp .6 -.RS 4n -Recover parts of the file even if they are currently marked as in use. -.RE - -.sp -.ne 2 -.na -\fB\fB-o\fR, \fB--output\fR \fIfile\fR\fR -.ad -.sp .6 -.RS 4n -Set the name of the output file created by the \fB--copy\fR or \fB--undelete\fR -options. -.RE - -.sp -.ne 2 -.na -\fB\fB-P\fR, \fB--parent\fR\fR -.ad -.sp .6 -.RS 4n -Display the parent directory of a deleted file. -.RE - -.sp -.ne 2 -.na -\fB\fB-p\fR, \fB--percentage\fR \fInum\fR\fR -.ad -.sp .6 -.RS 4n -Filter the output of the \fB--scan\fR option by matching only files with -\fInum\fR percent of recoverable content. -.RE - -.sp -.ne 2 -.na -\fB\fB-q\fR, \fB--quiet\fR\fR -.ad -.sp .6 -.RS 4n -Reduce the amount of output to a minimum. This option is not useful with the -\fB--scan\fR option. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--scan\fR\fR -.ad -.sp .6 -.RS 4n -Search through an NTFS volume and display a list of files that could be -recovered. This is the default action of \fBntfsundelete\fR. This list can be -filtered by filename, size, percentage recoverable, or last modification time, -using the \fB--match\fR, \fB--size\fR, \fB--percent\fR, and \fB--time\fR -options, respectively. -.sp -In the output from this option, the \fB%age\fR (percentage) field displays how -much of a file can potentially be recovered. -.RE - -.sp -.ne 2 -.na -\fB\fB-S\fR, \fB--size\fR \fIrange\fR\fR -.ad -.sp .6 -.RS 4n -Filter the output of the \fB--scan\fR option by looking for a particular range -of file sizes. \fIrange\fR can be specified as two numbers separated by a -hyphen (\fB-\fR). A unit of size can be abbreviated using the suffixes \fBk\fR, -\fBm\fR, \fBg\fR, and \fBt\fR, for kilobytes, megabytes, gigabytes, and -terabytes respectively. -.RE - -.sp -.ne 2 -.na -\fB\fB-t\fR, \fB--time\fR \fIsince\fR\fR -.ad -.sp .6 -.RS 4n -Filter the output of the \fB--scan\fR option. Match only files that have been -altered since this time. The time must be given as number and a suffix of -\fBd\fR, \fBw\fR, \fBm\fR, or \fBy\fR for, respectively, days, weeks, -months, or years. -.RE - -.sp -.ne 2 -.na -\fB\fB-T\fR, \fB--truncate\fR\fR -.ad -.sp .6 -.RS 4n -The default behavior of \fBntfsundelete\fR is to round \fBup\fR a file's size -to the nearest cluster (which will be a multiple of 512 bytes). In cases where -the utility has complete data about the size of a file, this option restores -the file to exactly that size. -.RE - -.sp -.ne 2 -.na -\fB\fB-u\fR, \fB--undelete\fR\fR -.ad -.sp .6 -.RS 4n -Specifies undelete mode. You can specify the files to be recovered using by -using \fB--match\fR or \fB--inodes\fR options. This option can be combined with -\fB--output\fR, \fB--destination\fR, and \fB--byte\fR. -.sp -When the file is recovered it will be given its original name, unless the -\fB--output\fR option is used. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--verbose\fR \fI\fR\fR -.ad -.sp .6 -.RS 4n -Increase the amount of output that \fBntfsundelete\fR displays. -.RE - -.sp -.ne 2 -.na -\fB\fB-V\fR, \fB--version\fR \fI\fR\fR -.ad -.sp .6 -.RS 4n -Display the version number, copyright, and license for \fBntfsundelete\fR. -.RE - -.SH EXAMPLES -.LP -\fBExample 1 \fRSearching for Deleted Files -.sp -.LP -The following command searches for deleted files on a specific device. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1\fR -.fi -.in -2 -.sp - -.LP -\fBExample 2 \fRScanning for Files Matching a Wildcard -.sp -.LP -The following command searches for deleted files that match \fB*.doc\fR. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1 -s -m '*.doc'\fR -.fi -.in -2 -.sp - -.LP -\fBExample 3 \fRSearching for Files of a Certain Size -.sp -.LP -The following command looks for deleted files between 5000 and 6000000 bytes, -with at least 90% of the data recoverable, on \fB/dev/dsk/c0d0p1\fR. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1 -S 5k-6m -p 90\fR -.fi -.in -2 -.sp - -.LP -\fBExample 4 \fRSearching for Recently Changed Files -.sp -.LP -The following command searches for deleted files altered in the last two days. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1 -t 2d\fR -.fi -.in -2 -.sp - -.LP -\fBExample 5 \fRSpecifying an Inode Range -.sp -.LP -The following command undeletes inodes 2, 5 and 100 to 131 of device -\fB/dev/sda1\fR. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/sda1 -u -i 2,5,100-131\fR -.fi -.in -2 -.sp - -.LP -\fBExample 6 \fRSpecifying an Output File and Directory -.sp -.LP -The following command undeletes inode number 3689, names the file -\fBwork.doc\fR, and stores it in the user's home directory. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1 -u -i 3689 -o work.doc -d ~\fR -.fi -.in -2 -.sp - -.LP -\fBExample 7 \fRSaving MFT Records -.sp -.LP -The following command saves MFT records 3689 to 3690 to a file \fBdebug\fR. - -.sp -.in +2 -.nf -# \fBntfsundelete /dev/dsk/c0d0p1 -c 3689-3690 -o debug\fR -.fi -.in -2 -.sp - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBntfsclone\fR(1M), \fBntfsresize\fR(1M), \fBparted\fR(1M), -\fBattributes\fR(5) -.sp -.LP -http://wiki.linux-ntfs.org -.SH AUTHORS -.sp -.LP -\fBntfsundelete\fR was written by Richard Russon and Holger Ohmacht, with -contributions from Anton Altaparmakov. diff --git a/usr/src/man/man1m/parted.1m b/usr/src/man/man1m/parted.1m deleted file mode 100644 index 31cb0f4286..0000000000 --- a/usr/src/man/man1m/parted.1m +++ /dev/null @@ -1,347 +0,0 @@ -'\" te -.\" Portions Copyright (c) 2009, Sun Microsystems, Inc. All Rights Reserved -.\" Copyright (C) 1999, 2000, 2007 Free Software Foundation, Inc. -.\" This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed -.\" in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. -.\" If not, see: http://www.gnu.org/copyleft/gpl.html -.TH PARTED 1M "May 27, 2009" -.SH NAME -parted \- partition manipulation program -.SH SYNOPSIS -.LP -.nf -\fBparted\fR [\fIoptions\fR] [\fIdevice\fR [\fIoptions\fR...]...]] -.fi - -.SH DESCRIPTION -.sp -.LP -\fBparted\fR is a disk partitioning and partition resizing program. It allows -you to create, destroy, resize, move, and copy \fBext2\fR, \fBext3\fR, -\fBlinux-swap\fR, \fBFAT\fR, \fBFAT32\fR, and \fBreiserfs\fR partitions. It -can create, resize, and move Macintosh HFS partitions, as well as detect -\fBjfs\fR, \fBntfs\fR, \fBufs\fR, and \fBxfs\fR partitions. It is useful for -creating space for new operating systems, reorganizing disk usage, and copying -data to new hard disks. -.sp -.LP -This manual page documents \fBparted\fR briefly. Complete \fBparted\fR -documentation is distributed with the package in "GNU Info" format. -.sp -.LP -\fBparted\fR is implemented with a set of top-level options and a set of -subcommands, most of which have their own options and operands. These -subcommands are described below. \fBparted\fR has an optional operand: -.sp -.ne 2 -.na -\fB\fIdevice\fR\fR -.ad -.RS 10n -The block device to be used. When none is given, \fBparted\fR uses the first -block device it finds. -.RE - -.SH OPTIONS -.sp -.LP -The following options are supported: -.sp -.ne 2 -.na -\fB\fB-h\fR, \fB--help\fR\fR -.ad -.sp .6 -.RS 4n -Displays a help message. -.RE - -.sp -.ne 2 -.na -\fB\fB-i\fR, \fB--interactive\fR\fR -.ad -.sp .6 -.RS 4n -Prompts for user intervention. -.RE - -.sp -.ne 2 -.na -\fB\fB-l\fR, \fB--list\fR\fR -.ad -.sp .6 -.RS 4n -Lists partition layout on all block devices. -.RE - -.sp -.ne 2 -.na -\fB\fB-m\fR, \fB--machine\fR\fR -.ad -.sp .6 -.RS 4n -Displays machine-parseable output. -.RE - -.sp -.ne 2 -.na -\fB\fB-s\fR, \fB--script\fR\fR -.ad -.sp .6 -.RS 4n -Never prompts for user intervention. -.RE - -.sp -.ne 2 -.na -\fB\fB-v\fR, \fB--version\fR\fR -.ad -.sp .6 -.RS 4n -Displays the version number. -.RE - -.SH SUB-COMMANDS -.sp -.LP -If you omit a subcommand in a \fBparted\fR command line, the utility issues a -command prompt. -.sp -.ne 2 -.na -\fB\fBcheck\fR \fIpartition\fR\fR -.ad -.sp .6 -.RS 4n -Do a simple check on \fIpartition\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBcp\fR [\fIsource-device\fR] \fIsource\fR \fIdest\fR\fR -.ad -.sp .6 -.RS 4n -Copy the source partition's filesystem on \fIsource-device\fR (or the current -device if no other device was specified) to the \fIdest\fR partition on the -current device. -.RE - -.sp -.ne 2 -.na -\fB\fBhelp\fR \fIcommand\fR\fR -.ad -.sp .6 -.RS 4n -Display general help, or help on a command, if specified. -.RE - -.sp -.ne 2 -.na -\fB\fBmkfs\fR \fIpartition\fR \fIfs-type\fR\fR -.ad -.sp .6 -.RS 4n -Make a filesystem \fIfs-type\fR on partition. \fIfs-type\fR can be one of -\fBfat16\fR, \fBfat32\fR, \fBext2\fR, \fBlinux-wap\fR, or \fBreiserfs\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBmklabel\fR \fIlabel-type\fR\fR -.ad -.sp .6 -.RS 4n -Create a new disk label (partition table) of \fIlabel-type\fR. \fIlabel-type\fR -should be one of \fBbsd\fR, \fBdvh\fR, \fBgpt\fR, \fBloop\fR, \fBmac\fR, -\fBmsdos\fR, \fBpc98\fR, or \fBsun\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBmkpart\fR \fIpart-type\fR [\fIfs-type\fR] \fIstart\fR \fIend\fR\fR -.ad -.sp .6 -.RS 4n -Make a \fIpart-type\fR partition with file system \fIfs-type\fR (if specified), -beginning at \fIstart\fR and ending at \fIend\fR (by default, in megabytes). -\fIfs-type\fR can be one of \fBfat16\fR, \fBfat32\fR, \fBext2\fR, \fBHFS\fR, -\fBlinux-swap\fR, \fBNTFS\fR, \fBreiserfs\fR, or \fBufs\fR. \fIpart-type\fR -should be one of \fBprimary\fR, \fBlogical\fR, or \fBextended\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBmkpartfs\fR \fIpart-type\fR \fIfs-type\fR \fIstart\fR \fIend\fR\fR -.ad -.sp .6 -.RS 4n -Make a \fIpart-type\fR partition with file system \fIfs-type\fR, beginning at -\fIstart\fR and ending at \fIend\fR (by default, in megabytes). -.RE - -.sp -.ne 2 -.na -\fB\fBmove\fR \fIpartition\fR \fIstart\fR \fIend\fR\fR -.ad -.sp .6 -.RS 4n -Move partition so that it begins at \fIstart\fR and ends at \fIend\fR. Note -that \fBmove\fR never changes the minor number. -.RE - -.sp -.ne 2 -.na -\fB\fBname\fR \fIpartition\fR \fIname\fR\fR -.ad -.sp .6 -.RS 4n -Set the name of partition to \fIname\fR. This option works only on Mac, PC98, -and GPT disk labels. The name can be placed in quotes, if necessary. -.RE - -.sp -.ne 2 -.na -\fB\fBprint\fR\fR -.ad -.sp .6 -.RS 4n -Display the partition table. -.RE - -.sp -.ne 2 -.na -\fB\fBquit\fR\fR -.ad -.sp .6 -.RS 4n -Exit from \fBparted\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBrescue\fR \fIstart\fR \fIend\fR\fR -.ad -.sp .6 -.RS 4n -Rescue a lost partition that was located somewhere between \fIstart\fR and -\fIend\fR. If a partition is found, \fBparted\fR will ask if you want to create -an entry for it in the partition table. -.RE - -.sp -.ne 2 -.na -\fB\fBresize\fR \fIpartition\fR \fIstart\fR \fIend\fR\fR -.ad -.sp .6 -.RS 4n -Resize the file system on \fIpartition\fR so that it begins at \fIstart\fR and -ends at \fIend\fR (by default, in megabytes). -.RE - -.sp -.ne 2 -.na -\fB\fBrm\fR \fIpartition\fR\fR -.ad -.sp .6 -.RS 4n -Delete \fIpartition\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBselect\fR \fIdevice\fR\fR -.ad -.sp .6 -.RS 4n -Choose \fIdevice\fR as the current device to edit. \fIdevice\fR should usually -be a Solaris or Linux hard disk device, but it can be a partition, software -raid device, or an SVM or LVM logical volume if necessary. -.RE - -.sp -.ne 2 -.na -\fB\fBset\fR \fIpartition\fR \fIflag\fR \fIstate\fR\fR -.ad -.sp .6 -.RS 4n -Change the state of the \fIflag\fR on \fIpartition\fR to \fIstate\fR. Supported -flags are: \fBboot\fR, \fBroot\fR, \fBswap\fR, \fBhidden\fR, \fBraid\fR, -\fBlvm\fR, \fBlba\fR, and \fBpalo\fR. \fIstate\fR should be either \fBon\fR or -\fBoff\fR. -.RE - -.sp -.ne 2 -.na -\fB\fBunit\fR \fIunit\fR\fR -.ad -.sp .6 -.RS 4n -Set \fIunit\fR as the unit to use when displaying locations and sizes, and for -interpreting those given by the user when not suffixed with an explicit unit. -\fIunit\fR can be one of \fBs\fR (sectors), \fBB\fR (bytes), \fBkB\fR, -\fBMB\fR, \fBGB\fR, \fBTB\fR, \fB%\fR (percentage of device size), \fBcyl\fR -(cylinders), \fBchs\fR (cylinders, heads, sectors), or \fBcompact\fR (megabytes -for input, and a human-friendly form for output). -.RE - -.sp -.ne 2 -.na -\fB\fBversion\fR\fR -.ad -.sp .6 -.RS 4n -Display version information and a copyright message. -.RE - -.SH ATTRIBUTES -.sp -.LP -See \fBattributes\fR(5) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Uncommitted -.TE - -.SH SEE ALSO -.sp -.LP -\fBfdisk\fR(1M), \fBmkfs\fR(1M), \fBattributes\fR(5) -.sp -.LP -The \fBparted\fR program is fully documented in the \fBinfo(1)\fR format GNU -partitioning software manual. -.SH AUTHOR -.sp -.LP -This manual page was written by Timshel Knoll for the Debian GNU/Linux system. -It is here adapted for the Solaris operating system. diff --git a/usr/src/pkg/manifests/SUNWntfsprogs.mf b/usr/src/pkg/manifests/SUNWntfsprogs.mf index ba1854b6cb..f4a7ac1a3b 100644 --- a/usr/src/pkg/manifests/SUNWntfsprogs.mf +++ b/usr/src/pkg/manifests/SUNWntfsprogs.mf @@ -21,9 +21,9 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. -# +# Was renamed to system/file-system/ntfsprogs, both now obsolete. set name=pkg.fmri value=pkg:/SUNWntfsprogs@2.0.0,5.11-0.133 -set name=pkg.renamed value=true +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true set name=variant.arch value=i386 -depend fmri=pkg:/system/file-system/ntfsprogs@2.0.0,5.11-0.133 type=require diff --git a/usr/src/pkg/manifests/SUNWparted.mf b/usr/src/pkg/manifests/SUNWparted.mf index 2df897251c..6897afb193 100644 --- a/usr/src/pkg/manifests/SUNWparted.mf +++ b/usr/src/pkg/manifests/SUNWparted.mf @@ -21,9 +21,9 @@ # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. -# +# Was renamed to system/storage/parted, both now obsolete set name=pkg.fmri value=pkg:/SUNWparted@1.8.8,5.11-0.133 -set name=pkg.renamed value=true +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true set name=variant.arch value=i386 -depend fmri=pkg:/system/storage/parted@1.8.8,5.11-0.133 type=require diff --git a/usr/src/lib/libparted/i386/Makefile b/usr/src/pkg/manifests/system-file-system-ntfsprogs.mf similarity index 55% rename from usr/src/lib/libparted/i386/Makefile rename to usr/src/pkg/manifests/system-file-system-ntfsprogs.mf index 77b0c2e552..97f3de55de 100644 --- a/usr/src/lib/libparted/i386/Makefile +++ b/usr/src/pkg/manifests/system-file-system-ntfsprogs.mf @@ -18,35 +18,13 @@ # # CDDL HEADER END # + # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -include ../Makefile.com - -SUBDIRS= pics/lib \ - pics/libparted \ - pics/libparted/arch \ - pics/libparted/cs \ - pics/libparted/fs/amiga \ - pics/libparted/fs/ext2 \ - pics/libparted/fs/fat \ - pics/libparted/fs/hfs \ - pics/libparted/fs/jfs \ - pics/libparted/fs/linux_swap \ - pics/libparted/fs/ntfs \ - pics/libparted/fs/reiserfs \ - pics/libparted/fs/solaris_x86 \ - pics/libparted/fs/ufs \ - pics/libparted/fs/xfs \ - pics/libparted/labels - -.KEEP_STATE: - -all: $(SUBDIRS) $(LIBS) - -install: all $(ROOTLIBS) $(ROOTLINKS) $(DYNLINKLIB) - -$(SUBDIRS): - mkdir -p $@ +set name=pkg.fmri \ + value=pkg:/system/file-system/ntfsprogs@2.0.0,$(PKGVERS_BUILTON)-$(PKGVERS_BRANCH) +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true +set name=variant.arch value=i386 diff --git a/usr/src/lib/libntfs/i386/Makefile b/usr/src/pkg/manifests/system-storage-parted.mf similarity index 73% rename from usr/src/lib/libntfs/i386/Makefile rename to usr/src/pkg/manifests/system-storage-parted.mf index 0925ec1791..938e887d83 100644 --- a/usr/src/lib/libntfs/i386/Makefile +++ b/usr/src/pkg/manifests/system-storage-parted.mf @@ -18,20 +18,13 @@ # # CDDL HEADER END # + # -# Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. +# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # -include ../Makefile.com - -SUBDIRS= pics/$(LIBNTFSDIR) - -.KEEP_STATE: - -all: $(SUBDIRS) $(LIBS) - -install: all $(ROOTLIBS) $(ROOTLINKS) $(DYNLINKLIB) - -$(SUBDIRS): - mkdir -p $@ +set name=pkg.fmri \ + value=pkg:/system/storage/parted@1.8.8,$(PKGVERS_BUILTON)-$(PKGVERS_BRANCH) +set name=pkg.obsolete value=true +set name=org.opensolaris.noincorp value=true +set name=variant.arch value=i386 -- 2.11.4.GIT