summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/Makefile3
-rw-r--r--usr/src/lib/libntfs/COPYING340
-rw-r--r--usr/src/lib/libntfs/CREDITS40
-rw-r--r--usr/src/lib/libntfs/Makefile124
-rw-r--r--usr/src/lib/libntfs/Makefile.com89
-rw-r--r--usr/src/lib/libntfs/README16
-rw-r--r--usr/src/lib/libntfs/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/attrib.h382
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/attrlist.h51
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/bitmap.h134
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/bootsect.h47
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/collate.h38
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/compat.h58
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/compress.h33
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/config.h313
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/crypto.h46
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/debug.h63
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/device.h128
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/device_io.h77
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/dir.h112
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/endians.h248
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/index.h131
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/inode.h215
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/layout.h3063
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/lcnalloc.h50
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/list.h192
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/logfile.h441
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/logging.h143
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/mft.h116
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/mst.h34
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/ntfstime.h69
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/runlist.h90
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/security.h55
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/support.h121
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/types.h142
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/unistr.h69
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/version.h29
-rw-r--r--usr/src/lib/libntfs/common/include/ntfs/volume.h247
-rw-r--r--usr/src/lib/libntfs/common/libntfs/attrib.c5234
-rw-r--r--usr/src/lib/libntfs/common/libntfs/attrlist.c320
-rw-r--r--usr/src/lib/libntfs/common/libntfs/bitmap.c249
-rw-r--r--usr/src/lib/libntfs/common/libntfs/bootsect.c273
-rw-r--r--usr/src/lib/libntfs/common/libntfs/collate.c220
-rw-r--r--usr/src/lib/libntfs/common/libntfs/compat.c73
-rw-r--r--usr/src/lib/libntfs/common/libntfs/compress.c553
-rw-r--r--usr/src/lib/libntfs/common/libntfs/crypto.c1519
-rw-r--r--usr/src/lib/libntfs/common/libntfs/debug.c73
-rw-r--r--usr/src/lib/libntfs/common/libntfs/device.c796
-rw-r--r--usr/src/lib/libntfs/common/libntfs/device_io.c46
-rw-r--r--usr/src/lib/libntfs/common/libntfs/dir.c1773
-rw-r--r--usr/src/lib/libntfs/common/libntfs/index.c1862
-rw-r--r--usr/src/lib/libntfs/common/libntfs/inode.c1200
-rw-r--r--usr/src/lib/libntfs/common/libntfs/lcnalloc.c858
-rw-r--r--usr/src/lib/libntfs/common/libntfs/logfile.c769
-rw-r--r--usr/src/lib/libntfs/common/libntfs/logging.c644
-rw-r--r--usr/src/lib/libntfs/common/libntfs/mft.c1583
-rw-r--r--usr/src/lib/libntfs/common/libntfs/misc.c64
-rw-r--r--usr/src/lib/libntfs/common/libntfs/mst.c216
-rw-r--r--usr/src/lib/libntfs/common/libntfs/runlist.c2154
-rw-r--r--usr/src/lib/libntfs/common/libntfs/security.c272
-rw-r--r--usr/src/lib/libntfs/common/libntfs/unistr.c776
-rw-r--r--usr/src/lib/libntfs/common/libntfs/unix_io.c321
-rw-r--r--usr/src/lib/libntfs/common/libntfs/version.c45
-rw-r--r--usr/src/lib/libntfs/common/libntfs/volume.c1689
-rw-r--r--usr/src/lib/libntfs/common/mapfile-vers134
-rw-r--r--usr/src/lib/libntfs/i386/Makefile37
-rw-r--r--usr/src/lib/libparted/COPYING676
-rw-r--r--usr/src/lib/libparted/Makefile110
-rw-r--r--usr/src/lib/libparted/Makefile.com132
-rw-r--r--usr/src/lib/libparted/README22
-rw-r--r--usr/src/lib/libparted/THANKS.txt28
-rw-r--r--usr/src/lib/libparted/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/lib/libparted/common/include/parted/constraint.h96
-rw-r--r--usr/src/lib/libparted/common/include/parted/crc32.h34
-rw-r--r--usr/src/lib/libparted/common/include/parted/debug.h89
-rw-r--r--usr/src/lib/libparted/common/include/parted/device.h150
-rw-r--r--usr/src/lib/libparted/common/include/parted/disk.h348
-rw-r--r--usr/src/lib/libparted/common/include/parted/endian.h85
-rw-r--r--usr/src/lib/libparted/common/include/parted/exception.h116
-rw-r--r--usr/src/lib/libparted/common/include/parted/filesys.h116
-rw-r--r--usr/src/lib/libparted/common/include/parted/geom.h83
-rw-r--r--usr/src/lib/libparted/common/include/parted/natmath.h108
-rw-r--r--usr/src/lib/libparted/common/include/parted/parted.h63
-rw-r--r--usr/src/lib/libparted/common/include/parted/solaris.h42
-rw-r--r--usr/src/lib/libparted/common/include/parted/timer.h65
-rw-r--r--usr/src/lib/libparted/common/include/parted/unit.h93
-rw-r--r--usr/src/lib/libparted/common/lib/__fpending.h34
-rw-r--r--usr/src/lib/libparted/common/lib/basename.c129
-rw-r--r--usr/src/lib/libparted/common/lib/close-stream.c76
-rw-r--r--usr/src/lib/libparted/common/lib/close-stream.h2
-rw-r--r--usr/src/lib/libparted/common/lib/closeout.c86
-rw-r--r--usr/src/lib/libparted/common/lib/closeout.h33
-rw-r--r--usr/src/lib/libparted/common/lib/config.h597
-rw-r--r--usr/src/lib/libparted/common/lib/configmake.h25
-rw-r--r--usr/src/lib/libparted/common/lib/dirname.c85
-rw-r--r--usr/src/lib/libparted/common/lib/dirname.h70
-rw-r--r--usr/src/lib/libparted/common/lib/error.c339
-rw-r--r--usr/src/lib/libparted/common/lib/error.h66
-rw-r--r--usr/src/lib/libparted/common/lib/exitfail.c26
-rw-r--r--usr/src/lib/libparted/common/lib/exitfail.h20
-rw-r--r--usr/src/lib/libparted/common/lib/full-write.c81
-rw-r--r--usr/src/lib/libparted/common/lib/full-write.h35
-rw-r--r--usr/src/lib/libparted/common/lib/getopt.c1191
-rw-r--r--usr/src/lib/libparted/common/lib/getopt_int.h131
-rw-r--r--usr/src/lib/libparted/common/lib/gettext.h270
-rw-r--r--usr/src/lib/libparted/common/lib/localcharset.c460
-rw-r--r--usr/src/lib/libparted/common/lib/localcharset.h41
-rw-r--r--usr/src/lib/libparted/common/lib/long-options.c89
-rw-r--r--usr/src/lib/libparted/common/lib/long-options.h26
-rw-r--r--usr/src/lib/libparted/common/lib/memcpy.c36
-rw-r--r--usr/src/lib/libparted/common/lib/memmove.c26
-rw-r--r--usr/src/lib/libparted/common/lib/memset.c28
-rw-r--r--usr/src/lib/libparted/common/lib/quotearg.c697
-rw-r--r--usr/src/lib/libparted/common/lib/quotearg.h140
-rw-r--r--usr/src/lib/libparted/common/lib/regcomp.c3832
-rw-r--r--usr/src/lib/libparted/common/lib/regex.c71
-rw-r--r--usr/src/lib/libparted/common/lib/regex.h675
-rw-r--r--usr/src/lib/libparted/common/lib/regex_internal.c1741
-rw-r--r--usr/src/lib/libparted/common/lib/regex_internal.h853
-rw-r--r--usr/src/lib/libparted/common/lib/regexec.c4399
-rw-r--r--usr/src/lib/libparted/common/lib/rpmatch.c79
-rw-r--r--usr/src/lib/libparted/common/lib/safe-read.c78
-rw-r--r--usr/src/lib/libparted/common/lib/safe-read.h35
-rw-r--r--usr/src/lib/libparted/common/lib/safe-write.c19
-rw-r--r--usr/src/lib/libparted/common/lib/safe-write.h25
-rw-r--r--usr/src/lib/libparted/common/lib/strcspn.c41
-rw-r--r--usr/src/lib/libparted/common/lib/stripslash.c45
-rw-r--r--usr/src/lib/libparted/common/lib/strndup.c37
-rw-r--r--usr/src/lib/libparted/common/lib/version-etc-fsf.c31
-rw-r--r--usr/src/lib/libparted/common/lib/version-etc.c173
-rw-r--r--usr/src/lib/libparted/common/lib/version-etc.h37
-rw-r--r--usr/src/lib/libparted/common/lib/xalloc-die.c42
-rw-r--r--usr/src/lib/libparted/common/lib/xalloc.h271
-rw-r--r--usr/src/lib/libparted/common/lib/xmalloc.c123
-rw-r--r--usr/src/lib/libparted/common/lib/xstrndup.c37
-rw-r--r--usr/src/lib/libparted/common/lib/xstrndup.h25
-rw-r--r--usr/src/lib/libparted/common/libparted/arch/solaris.c1393
-rw-r--r--usr/src/lib/libparted/common/libparted/cs/constraint.c529
-rw-r--r--usr/src/lib/libparted/common/libparted/cs/geom.c474
-rw-r--r--usr/src/lib/libparted/common/libparted/cs/natmath.c503
-rw-r--r--usr/src/lib/libparted/common/libparted/debug.c120
-rw-r--r--usr/src/lib/libparted/common/libparted/device.c445
-rw-r--r--usr/src/lib/libparted/common/libparted/disk.c2265
-rw-r--r--usr/src/lib/libparted/common/libparted/exception.c312
-rw-r--r--usr/src/lib/libparted/common/libparted/filesys.c782
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/affs.c462
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/affs.h19
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/amiga.c349
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/amiga.h70
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/apfs.c150
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/apfs.h17
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/asfs.c142
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/asfs.h17
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/amiga/interface.c87
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c792
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2.h249
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_block_relocator.c927
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_buffer.c446
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_fs.h323
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_inode_relocator.c599
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_meta.c145
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_mkfs.c632
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/ext2_resize.c730
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/interface.c352
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.c135
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/parted_io.h27
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/tune.c39
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ext2/tune.h29
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/bootsector.c452
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/bootsector.h142
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/calc.c435
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/calc.h77
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/clstdup.c424
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/clstdup.h28
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/context.c260
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/context.h69
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/count.c403
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/count.h55
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/fat.c887
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/fat.h168
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/fatio.c151
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/fatio.h48
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/resize.c877
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/table.c481
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/table.h74
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/traverse.c365
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/fat/traverse.h73
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/advfs.c328
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/advfs.h48
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.c383
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/advfs_plus.h51
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/cache.c238
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/cache.h117
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/file.c228
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/file.h41
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.c273
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/file_plus.h60
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/hfs.c1353
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/hfs.h830
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/journal.c389
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/journal.h44
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/probe.c230
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/probe.h43
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/reloc.c670
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/reloc.h35
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.c945
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/hfs/reloc_plus.h36
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/jfs/jfs.c109
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/jfs/jfs_superblock.h144
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/jfs/jfs_types.h530
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/linux_swap/linux_swap.c522
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ntfs/ntfs.c599
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.c138
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/reiserfs/geom_dal.h60
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.c866
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/reiserfs/reiserfs.h108
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/solaris_x86/solaris_x86.c171
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/ufs/ufs.c324
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/xfs/platform_defs.h117
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/xfs/xfs.c119
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/xfs/xfs_sb.h489
-rw-r--r--usr/src/lib/libparted/common/libparted/fs/xfs/xfs_types.h302
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/aix.c295
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/bsd.c633
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/dos.c2280
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/dvh.c911
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/dvh.h178
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/efi_crc32.c126
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/gpt.c1538
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/loop.c333
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/mac.c1629
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/pc98.c896
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/rdb.c1183
-rw-r--r--usr/src/lib/libparted/common/libparted/labels/sun.c868
-rw-r--r--usr/src/lib/libparted/common/libparted/libparted.c351
-rw-r--r--usr/src/lib/libparted/common/libparted/timer.c245
-rw-r--r--usr/src/lib/libparted/common/libparted/unit.c565
-rw-r--r--usr/src/lib/libparted/common/mapfile-vers156
-rw-r--r--usr/src/lib/libparted/i386/Makefile52
239 files changed, 0 insertions, 93477 deletions
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 291f8c5a83..93c2e9e7ee 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -263,8 +263,6 @@ SUBDIRS += \
$($(MACH)_SUBDIRS)
i386_SUBDIRS= \
- libntfs \
- libparted \
libfdisk \
libsaveargs
@@ -500,7 +498,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.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 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.
-
- <signature of Ty Coon>, 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 <linux-ntfs-dev at lists.sf.net> if you believe someone is
-missing or if you prefer not to be listed.
-
-Alexei Alexandrov <alex_alexandrov at hotmail.com>
-Anton Altaparmakov <aia21 at cantab.net>
-Albert D. Cahalan <acahalan at cs.uml.edu>
-Russ Christensen <rchriste at cs.utah.edu>
-Pete Curran <curran at rpi.edu>
-Mario Emmenlauer <mario at emmenlauer.de>
-Andras Erdei <ccg at freemail.hu>
-Matthew J. Fanto <mattjf at uncompiled.com>
-Yuval Fledel <yuvalfl at gmail.com>
-Marcin Gibuła <m.gibula at conecto.pl>
-Christophe Grenier <grenier at cgsecurity.org>
-Csaba Henk <csaba.henk at creo.hu>
-Ian Jackson <ian at davenant.greenend.org.uk>
-Max Khon <fjoe at samodelkin.net>
-Carmelo Kintana <kintana at berkeley.edu>
-Jan Kratochvil <project-captive at jankratochvil.net>
-Lode Leroy <lode_leroy at hotmail.com>
-David Martínez Moreno <ender at debian.org>
-Giang Nguyen <cauthu at hotmail.com>
-Leonard Norrgård <vinsci at nic.funet.fi>
-Holger Ohmacht <holger.ohmacht at web.de>
-Per Olofsson <pelle at dsv.su.se>
-Yura Pakhuchiy <pakhuchiy at gmail.com>
-Yuri Per <yuri at acronis.com>
-Richard Russon <ntfs at flatcap.org>
-Erik Sørnes <erso1970 at yahoo.no>
-Szabolcs Szakacsits <szaka at sienet.hu>
-zhanglinbao <zhanglinbao2000 at 163.com>
-
-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 <byteswap.h> header file. */
-/* #undef HAVE_BYTESWAP_H */
-
-/* Define to 1 if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the <dlfcn.h> 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 <endian.h> header file. */
-/* #undef HAVE_ENDIAN_H */
-
-/* Define to 1 if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define to 1 if you have the <fcntl.h> 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 <features.h> 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 <getopt.h> 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 <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the <libgen.h> header file. */
-#define HAVE_LIBGEN_H 1
-
-/* Define to 1 if you have the <libintl.h> header file. */
-#define HAVE_LIBINTL_H 1
-
-/* Define to 1 if you have the <limits.h> header file. */
-#define HAVE_LIMITS_H 1
-
-/* Define to 1 if you have the <linux/fd.h> header file. */
-/* #undef HAVE_LINUX_FD_H */
-
-/* Define to 1 if you have the <linux/hdreg.h> header file. */
-/* #undef HAVE_LINUX_HDREG_H */
-
-/* Define to 1 if you have the <linux/major.h> header file. */
-/* #undef HAVE_LINUX_MAJOR_H */
-
-/* Define to 1 if you have the <locale.h> header file. */
-#define HAVE_LOCALE_H 1
-
-/* Define to 1 if you have the <machine/endian.h> 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 <memory.h> 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 <mntent.h> header file. */
-/* #undef HAVE_MNTENT_H */
-
-/* Define to 1 if you have the <pwd.h> 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 <stdarg.h> 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 <stddef.h> header file. */
-#define HAVE_STDDEF_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> 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 <syslog.h> header file. */
-#define HAVE_SYSLOG_H 1
-
-/* Define to 1 if you have the <sys/byteorder.h> header file. */
-#define HAVE_SYS_BYTEORDER_H 1
-
-/* Define to 1 if you have the <sys/endian.h> header file. */
-/* #undef HAVE_SYS_ENDIAN_H */
-
-/* Define to 1 if you have the <sys/ioctl.h> header file. */
-#define HAVE_SYS_IOCTL_H 1
-
-/* Define to 1 if you have the <sys/mount.h> header file. */
-#define HAVE_SYS_MOUNT_H 1
-
-/* Define to 1 if you have the <sys/param.h> header file. */
-#define HAVE_SYS_PARAM_H 1
-
-/* Define to 1 if you have the <sys/statvfs.h> header file. */
-#define HAVE_SYS_STATVFS_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/sysmacros.h> header file. */
-#define HAVE_SYS_SYSMACROS_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <sys/vfs.h> header file. */
-#define HAVE_SYS_VFS_H 1
-
-/* Define to 1 if you have the <time.h> header file. */
-#define HAVE_TIME_H 1
-
-/* Define to 1 if you have the <unistd.h> 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 <utime.h> 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 <wchar.h> header file. */
-#define HAVE_WCHAR_H 1
-
-/* Define to 1 if you have the <windows.h> 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 <sys/types.h> does not define. */
-/* #undef off_t */
-
-/* Define to `unsigned int' if <sys/types.h> 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 <linux/fs.h>)
- */
-#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 <endian.h>
-#endif
-#ifdef HAVE_SYS_ENDIAN_H
-#include <sys/endian.h>
-#endif
-#ifdef HAVE_MACHINE_ENDIAN_H
-#include <machine/endian.h>
-#endif
-#ifdef HAVE_SYS_BYTEORDER_H
-#include <sys/byteorder.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#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 <byteswap.h>
-#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 <stdarg.h>
-#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 <time.h>
-#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 <stddef.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#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 <stdint.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#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 <windef.h>'s
- * As long as this file will be included after <windows.h> 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 <stdio.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-#ifdef HAVE_MNTENT_H
-#include <mntent.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <string.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <gcrypt.h>
-#include <gnutls/pkcs12.h>
-#include <gnutls/x509.h>
-
-#include <libconfig.h>
-
-#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 <errno.h>
-#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 <unistd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifdef HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#endif
-#ifdef HAVE_LINUX_HDREG_H
-#include <linux/hdreg.h>
-#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, &sect_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 <stdlib.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_SYS_SYSMACROS_H
-#include <sys/sysmacros.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_SYSLOG_H
-#include <syslog.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#include <time.h>
-
-#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 <stdlib.h>
-#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 <errno.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <stdio.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_WCHAR_H
-#include <wchar.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#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 <unistd.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_IOCTL_H
-#include <sys/ioctl.h>
-#endif
-#ifdef HAVE_LINUX_FD_H
-#include <linux/fd.h>
-#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 <stdlib.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_LIMITS_H
-#include <limits.h>
-#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/libntfs/i386/Makefile b/usr/src/lib/libntfs/i386/Makefile
deleted file mode 100644
index 0925ec1791..0000000000
--- a/usr/src/lib/libntfs/i386/Makefile
+++ /dev/null
@@ -1,37 +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.
-#
-
-include ../Makefile.com
-
-SUBDIRS= pics/$(LIBNTFSDIR)
-
-.KEEP_STATE:
-
-all: $(SUBDIRS) $(LIBS)
-
-install: all $(ROOTLIBS) $(ROOTLINKS) $(DYNLINKLIB)
-
-$(SUBDIRS):
- mkdir -p $@
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. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-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:
-
- <program> Copyright (C) <year> <name of author>
- 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
-<http://www.gnu.org/licenses/>.
-
- 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
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.
-
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 <jon@rockgeeks.net> for binary unit support and more.
- * Kamil Ignacak <acerion@wp.pl> 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 <fab@orlen.de> for RPM spec file, help with hidden
-partitions and autoconfusion :-) - and lots of other misc. help.
- * Falk Hueffner <falk.hueffner@student.uni-tuebingen.de> for bug fixes.
- * Kevin Lindsay <klindsay@stormix.com> for lots of bug reports, etc.
- * John Weismiller <john@stormix.com> for lots of bug reports, etc.
- * Andries Brouwer <Andries.Brouwer@cwi.nl> for advice on BIOS geometry
- * Simon Kirby <sim@stormix.com> for advice on BIOS geometry
- * Glenn McGrath <Glenn.McGrath@jcu.edu.au>
- * Timshel Knoll <timshel@pobox.com> for Debian stuff
- * Tim Waugh <twaugh@redhat.com> for bug reports and fixes
- * My friends for helping with testing: Tristan Zwalf, Menaka Lashitha Bandara,
-Thomas Hambleton
- * Ryan Weaver <ryanw@infohwy.com> for parted.spec.in patches
- * Benjamin Herrenschmidt <bh40@calva.net> for answering all of our questions
-on Mac's
- * Ethan Benson <erbenson@alaska.net> for lots of advice / testing on ppc
- * Charles Stevenson <csteven@terraplex.com> - 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PED_CONSTRAINT_H_INCLUDED
-#define PED_CONSTRAINT_H_INCLUDED
-
-typedef struct _PedConstraint PedConstraint;
-
-#include <parted/device.h>
-#include <parted/natmath.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CRC32_H
-#define _CRC32_H
-
-#include <stdint.h>
-
-/*
- * 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PED_DEBUG_H_INCLUDED
-#define PED_DEBUG_H_INCLUDED
-
-#include <stdarg.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \addtogroup PedDevice
- * @{
- */
-
-/** \file device.h */
-
-#ifndef PED_DEVICE_H_INCLUDED
-#define PED_DEVICE_H_INCLUDED
-
-#include <parted/timer.h>
-
-/** 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \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 <parted/device.h>
-#include <parted/filesys.h>
-#include <parted/natmath.h>
-#include <parted/geom.h>
-
-/** @} */
-
-/**
- * \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 <http://www.gnu.org/licenses/>.
-*/
-
-/* should only be #included by files in libparted */
-
-#ifndef PED_ENDIAN_H_INCLUDED
-#define PED_ENDIAN_H_INCLUDED
-
-#include <stdint.h>
-
-/* 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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \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 <parted/geom.h>
-#include <parted/disk.h>
-#include <parted/exception.h>
-#include <parted/constraint.h>
-#include <parted/timer.h>
-#include <stdio.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \addtogroup PedGeometry
- * @{
- */
-
-/** \file geom.h */
-
-#ifndef PED_GEOM_H_INCLUDED
-#define PED_GEOM_H_INCLUDED
-
-#include <parted/device.h>
-#include <parted/timer.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \addtogroup PedAlignment
- * @{
- */
-
-/** \file natmath.h */
-
-#ifndef PED_NATMATH_H_INCLUDED
-#define PED_NATMATH_H_INCLUDED
-
-
-typedef struct _PedAlignment PedAlignment;
-
-#include <parted/disk.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PARTED_H_INCLUDED
-#define PARTED_H_INCLUDED
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct _PedArchitecture PedArchitecture;
-
-#include <parted/constraint.h>
-#include <parted/device.h>
-#include <parted/disk.h>
-#include <parted/exception.h>
-#include <parted/filesys.h>
-#include <parted/natmath.h>
-#include <parted/unit.h>
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-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 <parted/parted.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \addtogroup PedTimer
- * @{
- */
-
-/** \file timer.h */
-
-#ifndef PED_TIMER_H_INCLUDED
-#define PED_TIMER_H_INCLUDED
-
-#include <time.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \addtogroup PedUnit
- * @{
- */
-
-/** \file unit.h */
-
-#ifndef PED_UNIT_H_INCLUDED
-#define PED_UNIT_H_INCLUDED
-
-#include <parted/device.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-
-#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 <stddef.h>
-#include <stdio.h>
-
-#ifndef HAVE_DECL___FPENDING
-"this configure-time declaration test was not run"
-#endif
-
-#if HAVE_DECL___FPENDING
-# if HAVE_STDIO_EXT_H
-# include <stdio_ext.h>
-# 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 <config.h>
-
-#include "dirname.h"
-
-#include <string.h>
-#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 <config.h>
-
-#include "close-stream.h"
-
-#include <errno.h>
-#include <stdbool.h>
-
-#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 <stdio.h>
-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 <config.h>
-
-#include "closeout.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#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 <stdint.h> 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 <alloca.h>, 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 <alloca.h> 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 <bp-sym.h> 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 <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the <getopt.h> 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 <inttypes.h> 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 <langinfo.h> 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 <locale.h> 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 <wchar.h> 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 <memory.h> 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 <readline/history.h> header file. */
-/* #undef HAVE_READLINE_HISTORY_H */
-
-/* Define to 1 if you have the <readline/readline.h> 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 <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdio_ext.h> header file. */
-#define HAVE_STDIO_EXT_H 1
-
-/* Define to 1 if you have the <stdlib.h> 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 <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> 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 <utime.h>. Some systems
- have utime.h but don't declare the struct anywhere. */
-#define HAVE_STRUCT_UTIMBUF 1
-
-/* Define to 1 if you have the <sys/bitypes.h> header file. */
-/* #undef HAVE_SYS_BITYPES_H */
-
-/* Define to 1 if you have the <sys/inttypes.h> header file. */
-#define HAVE_SYS_INTTYPES_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#define HAVE_SYS_TIME_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <termcap.h> header file. */
-/* #undef HAVE_TERMCAP_H */
-
-/* Define to 1 if you have the <unistd.h> 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 <utime.h> 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 <wchar.h> 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 <wctype.h> 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 <inttypes.h> 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 <stdint.h> defines the limit macros, since gnulib's
- <inttypes.h> 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 <wchar.h> 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 <sys/types.h> 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 <config.h>
-
-#include "dirname.h"
-
-#include <string.h>
-#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 <stdbool.h>
-# include <stddef.h>
-
-# 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 <djm@gnu.ai.mit.edu>. */
-
-#if !_LIBC
-# include <config.h>
-#endif
-
-#include "error.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if !_LIBC && ENABLE_NLS
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#endif
-
-#ifdef _LIBC
-# include <libintl.h>
-# include <stdbool.h>
-# include <stdint.h>
-# include <wchar.h>
-# 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 <errno.h>
-# include <limits.h>
-# include <libio/libioP.h>
-
-/* 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 <libio/iolibio.h>
-# define fflush(s) INTUSE(_IO_fflush) (s)
-# undef putc
-# define putc(c, fp) INTUSE(_IO_putc) (c, fp)
-
-# include <bits/libc-lock.h>
-
-#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 <config.h>
-
-#include "exitfail.h"
-
-#include <stdlib.h>
-
-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 <config.h>
-
-/* Specification. */
-#ifdef FULL_READ
-# include "full-read.h"
-#else
-# include "full-write.h"
-#endif
-
-#include <errno.h>
-
-#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 <stddef.h>
-
-
-#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 <config.h>
-#endif
-
-#include "getopt.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#ifdef __VMS
-# include <unixlib.h>
-#endif
-
-#ifdef _LIBC
-# include <libintl.h>
-#else
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#endif
-
-#if defined _LIBC && defined USE_IN_LIBIO
-# include <wchar.h>
-#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 <libintl.h>.
- 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 <libintl.h>
-
-/* 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 <locale.h> a NOP. We don't include <libintl.h>
- as well because people using "gettext.h" will not include <libintl.h>,
- and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
- is OK. */
-#if defined(__sun)
-# include <locale.h>
-#endif
-
-/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
- <libintl.h>, which chokes if dcgettext is defined as a macro. So include
- it now, to make later inclusions of <libintl.h> a NOP. */
-#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
-# include <cstdlib>
-# if (__GLIBC__ >= 2) || _GLIBCXX_HAVE_LIBINTL_H
-# include <libintl.h>
-# 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 <string.h>
-
-#define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS \
- (((__GNUC__ >= 3 || __GNUG__ >= 2) && !__STRICT_ANSI__) \
- /* || __STDC_VERSION__ >= 199901L */ )
-
-#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
-#include <stdlib.h>
-#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 <bruno@clisp.org>. */
-
-#include <config.h>
-
-/* Specification. */
-#include "localcharset.h"
-
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#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 <langinfo.h>
-# else
-# if 0 /* see comment below */
-# include <locale.h>
-# endif
-# endif
-# ifdef __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-# endif
-#elif defined WIN32_NATIVE
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-#if defined OS2
-# define INCL_DOS
-# include <os2.h>
-#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 <config.h>
-
-/* Specification. */
-#include "long-options.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <getopt.h>
-
-#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 <meyering@na-net.ornl.gov>. */
-
-#include <config.h>
-
-#include <stddef.h>
-
-/* 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 <djm@gnu.ai.mit.edu>. */
-
-#include <config.h>
-
-#include <stddef.h>
-
-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 <stddef.h>
-
-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 <eggert@twinsun.com> */
-
-#include <config.h>
-
-#include "quotearg.h"
-
-#include "xalloc.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <wchar.h>
-#include <wctype.h>
-
-#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
- <http://en.wikipedia.org/wiki/Quotation_mark#Glyphs>
- 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 <eggert@twinsun.com> */
-
-#ifndef QUOTEARG_H_
-# define QUOTEARG_H_ 1
-
-# include <stddef.h>
-
-/* 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 <isamu@yamato.ibm.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, 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 (&regexp, 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 (&regexp);
- 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 (&regexp, 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 (&regexp);
-
- 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 <reg_exp>:
- CAT
- / \
- / \
- <reg_exp> 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 (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
- tree = parse_reg_exp (regexp, preg, &current_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
- <branch1>|<branch2>:
- ALT
- / \
- / \
- <branch1> <branch2>
-
- 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
- <exp1><exp2>:
- CAT
- / \
- / \
- <exp1> <exp2>
-
- 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 "<ANCHOR(^)><CHAR(*)>",
- it must not be "<ANCHOR(^)><REPEAT(*)>". */
- 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
- (<reg_exp>):
- SUBEXP
- |
- <reg_exp>
-*/
-
-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; /* <re>{} 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 "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
- 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 <re>{0,n} as (<re>(<re>...<re>?)?)?... 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 [:<character_class>:], [.<collating_element>.], and
- [=<equivalent_class>=]. */
-
-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 <locale/weight.h>
- /* 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 <isamu@yamato.ibm.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, 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 <config.h>
-
-/* 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 <regex.h>, which correctly
- #undefs RE_DUP_MAX and sets it to the right value. */
-#include <limits.h>
-
-#include "regex.h"
-#include "regex_internal.h"
-
-#include "regex_internal.c"
-#include "regcomp.c"
-#include "regexec.c"
-
-/* Binary backward compatibility. */
-#if _LIBC
-# include <shlib-compat.h>
-# 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 <sys/types.h>
-
-/* 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 \<digit> matches <digit>.
- If not set, then \<digit> 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 <limits.h>, 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 <isamu@yamato.ibm.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, 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:
- <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
- Then wide character buffer will be:
- <wc1> , WEOF , <wc2> , WEOF , <wc3>
- 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 <isamu@yamato.ibm.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, 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 <assert.h>
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifdef _LIBC
-# include <langinfo.h>
-#else
-# include "localcharset.h"
-#endif
-#if defined HAVE_LOCALE_H || defined _LIBC
-# include <locale.h>
-#endif
-
-#include <wchar.h>
-#include <wctype.h>
-#include <stdint.h>
-#if defined _LIBC
-# include <bits/libc-lock.h>
-#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 <locale/localeinfo.h>
-# include <locale/elem-hash.h>
-# include <locale/coll-lookup.h>
-# endif
-#endif
-
-/* This is for other GNU distributions with internationalized messages. */
-#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
-# include <libintl.h>
-# 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 <alloca.h>
-
-#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 <locale/weight.h>
- 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 <isamu@yamato.ibm.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, 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 <shlib-compat.h>
-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:
- <src> <dst> ( <subexp> )
- ( <subexp> ) <src> <dst>
- ( <subexp1> <src> <subexp2> <dst> <subexp3> ) */
- 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 <locale/weight.h>
-
- /* 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 <config.h>
-
-#include <stddef.h>
-#include <stdlib.h>
-
-#if ENABLE_NLS
-# include <sys/types.h>
-# include <limits.h>
-# include <regex.h>
-# 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 <config.h>
-
-/* Specification. */
-#ifdef SAFE_WRITE
-# include "safe-write.h"
-#else
-# include "safe-read.h"
-#endif
-
-/* Get ssize_t. */
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <errno.h>
-
-#ifdef EINTR
-# define IS_EINTR(x) ((x) == EINTR)
-#else
-# define IS_EINTR(x) 0
-#endif
-
-#include <limits.h>
-
-#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
- <http://lists.gnu.org/archive/html/bug-gnu-utils/2002-04/msg00010.html>.
- 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 <stddef.h>
-
-#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 <stddef.h>
-
-#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 <config.h>
-
-#include <stddef.h>
-#include <string.h>
-
-#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 <config.h>
-
-#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 <config.h>
-
-#include <string.h>
-
-#include <stdlib.h>
-
-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 <config.h>
-
-/* 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 <config.h>
-
-/* Specification. */
-#include "version-etc.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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 <http://gnu.org/licenses/gpl.html>\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 <stdarg.h>
-# include <stdio.h>
-
-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 <config.h>
-
-#include "xalloc.h"
-
-#include <stdlib.h>
-
-#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 <stddef.h>
-
-
-# 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 <typename T> inline T *
-xrealloc (T *p, size_t s)
-{
- return (T *) xrealloc ((void *) p, s);
-}
-
-template <typename T> inline T *
-xnrealloc (T *p, size_t n, size_t s)
-{
- return (T *) xnrealloc ((void *) p, n, s);
-}
-
-template <typename T> inline T *
-x2realloc (T *p, size_t *pn)
-{
- return (T *) x2realloc ((void *) p, pn);
-}
-
-template <typename T> inline T *
-x2nrealloc (T *p, size_t *pn, size_t s)
-{
- return (T *) x2nrealloc ((void *) p, pn, s);
-}
-
-template <typename T> 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 <config.h>
-
-#if ! HAVE_INLINE
-# define static_inline
-#endif
-#include "xalloc.h"
-#undef static_inline
-
-#include <stdlib.h>
-#include <string.h>
-
-#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 <config.h>
-
-/* Specification. */
-#include "xstrndup.h"
-
-#include <string.h>
-#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 <stddef.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. */
-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 <sys/types.h>
-#include <sys/mkdev.h>
-#include "config.h"
-#include "xalloc.h"
-#include <sys/dkio.h>
-
-/*
- * __attribute doesn't exist on solaris
- */
-#define __attribute__(X) /* nothing */
-
-#include <sys/vtoc.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/solaris.h>
-#include <malloc.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <unistd.h>
-#include <dirent.h>
-#include <libdiskmgt.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/swap.h>
-#include <sys/mnttab.h>
-#include <sys/mntent.h>
-
-#if ENABLE_NLS
-#include <libintl.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \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 <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-/**
- * 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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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:
- *
- * - <tt>start + length - 1 == end</tt>
- * - <tt>length > 0</tt>
- * - <tt>start >= 0</tt>
- * - <tt>end < dev->length</tt>
- *
- * @{
- */
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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:
- * <tt>offset + n * granularity</tt>
- *
- * \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 <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * \file natmath.c
- */
-
-/**
- * \addtogroup PedAlignment
- *
- * \brief Alignment constraint model.
- *
- * This part of libparted models alignment constraints.
- *
- * @{
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/natmath.h>
-
-/* 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
- * <tt>s = offset + X * grain_size</tt> 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 <tt>offset + X * grain_size</tt>.
- */
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#ifdef DEBUG
-
-#if HAVE_BACKTRACE
-#include <execinfo.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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 <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#include <limits.h>
-#include <unistd.h>
-#include <errno.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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 <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <tt>disk</tt>'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 <tt>ped_constraint_exact(&part->geom)</tt>,
- * 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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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 <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#define N_(String) String
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \file filesys.c */
-
-/**
- * \addtogroup PedFileSystem
- *
- * \note File systems exist on a PedGeometry - NOT a PedPartition.
- *
- * @{
- */
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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; i<detected_count; i++) {
- if (!detected[i]->ops->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; i<detected_count; i++) {
- if (detected[i]->ops->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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#include "amiga.h"
-#include "affs.h"
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
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 <http://www.gnu.org/licenses/>.
-
- Contributor: Sven Luther <luther@debian.org>
-*/
-
-#include <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#include "amiga.h"
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 "<free>";
- default :
- return "<unknown>";
- }
-}
-
-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; i<RDB_LOCATION_LIMIT; i++) {
- if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) {
- continue;
- }
- if (PED_BE32_TO_CPU (rdb->rdb_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 <http://www.gnu.org/licenses/>.
-*/
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#include "amiga.h"
-#include "apfs.h"
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#include "amiga.h"
-#include "asfs.h"
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
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 <http://www.gnu.org/licenses/>.
-*/
-
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-#include <uuid/uuid.h>
-#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;i<fs->numgroups;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;
- j<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
- 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;i<fs->numgroups;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;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);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;i<num;i++)
- if (!ext2_copy_block(fs, src+i, dest+i))
- return 0;
- }
- else
- {
- for (i=num;i>0;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;i<num;i++)
- {
- if (!ext2_bcache_flush(fs, block+i))
- goto error_free_buf;
- if (!ext2_write_blocks(fs, buf, block+i, 1))
- goto error_free_buf;
- }
-
- ped_free(buf);
- return 1;
- }
- ped_exception_catch();
- ped_exception_leave_all();
-
- for (i=0;i<num;i++)
- {
- struct ext2_buffer_head *bh;
-
- bh = ext2_bcreate(fs, block+i);
- if (!bh)
- goto error;
- bh->dirty = 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _EXT2_H
-#define _EXT2_H
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <sys/types.h>
-#include "tune.h"
-
-#if HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <linux/ext2_fs.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#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;i<EXT2_NDIR_BLOCKS;i++)
- if ((blk = EXT2_INODE_BLOCK(buf, i)) != 0)
- if (!doblock(fs,
- state,
- blk,
- inodeblock,
- inodeoffset + offsetof(struct ext2_inode, i_block[i]),
- 0))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_IND_BLOCK)) != 0)
- if (!doindblock(fs,
- state,
- blk,
- inodeblock,
- inodeoffset + offsetof(struct ext2_inode, i_block[EXT2_IND_BLOCK])))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_DIND_BLOCK)) != 0)
- if (!dodindblock(fs,
- state,
- blk,
- inodeblock,
- inodeoffset + offsetof(struct ext2_inode, i_block[EXT2_DIND_BLOCK])))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_TIND_BLOCK)) != 0)
- if (!dotindblock(fs,
- state,
- blk,
- inodeblock,
- inodeoffset + offsetof(struct ext2_inode, i_block[EXT2_TIND_BLOCK])))
- return 0;
-
- }
-
- return 1;
-}
-
-/* This function scans the entire filesystem, to find all references to blocks
- * that are scheduled to be moved.
- */
-static int doscan(struct ext2_fs *fs, struct ext2_block_relocator_state *state)
-{
- int i;
-
- state->start[0].num = 0;
- state->start[1].num = 0;
- state->start[2].num = 0;
- state->start[3].num = 0;
-
- for (i=0;i<fs->numgroups;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;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);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;i<state->usedentries;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;i<num;i++)
- if (dst[i].refblock == block->num)
- 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;i<fs->numgroups;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;
- j<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
- 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;j<num;j++)
- if (!ext2_block_relocator_ref(fs, state, &dst[j]))
- return 0;
-
- if (fs->opt_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;i<fs->numgroups;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;j<diff;j++)
- {
- blk_t block;
- blk_t k;
-
- k = EXT2_GROUP_INODE_TABLE(fs->gd[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;i<fs->numgroups;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;
- j<EXT2_GROUP_INODE_TABLE(fs->gd[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;j<groupsize;j++)
- if (bh->data[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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#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;i<bc->size;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;i<bc->size;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;i<bc->size;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<<ext2_hash_bits);i++)
- if (fs->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;i<size;i++)
- {
- bc->heads[i].data = bc->buffermem + (i << fs->logsize);
- bc->heads[i].bc = bc;
- bc->heads[i].alloc = 0;
- }
-
- for (i=0;i<(1<<ext2_hash_bits);i++)
- bc->hash[i] = NULL;
-
- fs->bc = bc;
-
- return 1;
-}
-
-int ext2_bcache_sync(struct ext2_fs *fs)
-{
- int i;
-
- for (i=0;i<fs->bc->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 <clausen@gnu.org>
- * Copyright (C) 2000 Free Software Foundation, Inc.
- */
-
-#ifndef _EXT2_FS_H
-#define _EXT2_FS_H
-
-#include <parted/endian.h>
-#include <stdint.h>
-
-/*
- * 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h> /* 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;i<ent->numreferences;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;i<EXT2_NDIR_BLOCKS;i++)
- if ((blk = EXT2_INODE_BLOCK(buf, i)) != 0)
- if (!doblock(fs, state, blk))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_IND_BLOCK)) != 0)
- if (!doindblock(fs, state, blk))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_DIND_BLOCK)) != 0)
- if (!dodindblock(fs, state, blk))
- return 0;
-
- if ((blk = EXT2_INODE_BLOCK(buf, EXT2_TIND_BLOCK)) != 0)
- if (!dotindblock(fs, state, blk))
- return 0;
- }
-
- return 1;
-}
-
-static int doscangroup(struct ext2_fs *fs, struct ext2_inode_relocator_state *state, int group)
-{
- struct ext2_buffer_head *bh;
- unsigned int i;
- int offset;
-
- if (fs->opt_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;i<EXT2_SUPER_INODES_PER_GROUP(fs->sb);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;i<state->usedentries;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;i<state->usedentries;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;i<state->usedentries;i++)
- {
- struct ext2_inode_entry *entry;
- int j;
- uint32_t t;
-
- entry = &state->inode[i];
- t = entry->dest;
-
- for (j=0;j<entry->numreferences;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;i<fs->numgroups;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 (;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);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;i<ent->numreferences;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;i<fs->numgroups;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;j<EXT2_SUPER_INODES_PER_GROUP(fs->sb);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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#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;i<fs->numgroups;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;j<diff;j++)
- if (!ext2_get_block_state(fs, fromblock+j))
- {
- fprintf(stderr,
- "error: block relocator "
- "should have relocated "
- "%i\n",
- fromblock);
-
- return 0;
- }
- }
-
- for (j=0;j<diff;j++)
- if (!ext2_set_block_state(fs, fromblock+j, 1, 0))
- return 0;
-
- if (!ext2_move_blocks(fs,
- EXT2_GROUP_INODE_TABLE(fs->gd[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;j<diff;j++)
- if (!ext2_set_block_state(fs, fromblock+j-diff, 0, 0))
- return 0;
-
- if (fs->opt_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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#define USE_EXT2_IS_DATA_BLOCK
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <time.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-#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;i<numgroups;i++)
- {
- if (is_sparse(i))
- {
- int offset;
-
- offset = EXT2_SUPER_FIRST_DATA_BLOCK(*sb)
- + i * EXT2_SUPER_BLOCKS_PER_GROUP(*sb);
-
- sb_for_io->s_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<numgroups;i++)
- {
- int admin;
- blk_t bbblock;
- int groupsize;
- int groupoffset;
- blk_t ibblock;
- int j;
-
- ped_timer_update (timer, 1.0 * i / numgroups);
-
- groupoffset = i*EXT2_SUPER_BLOCKS_PER_GROUP(*sb)
- + EXT2_SUPER_FIRST_DATA_BLOCK(*sb);
- groupsize = PED_MIN(EXT2_SUPER_BLOCKS_COUNT(*sb) - groupoffset,
- EXT2_SUPER_BLOCKS_PER_GROUP(*sb));
-
- admin = itsize + 2;
- bbblock = groupoffset;
- ibblock = groupoffset + 1;
- if (is_sparse(i))
- {
- admin += gdtsize + 1;
- bbblock = groupoffset + gdtsize + 1;
- ibblock = groupoffset + gdtsize + 2;
- }
-
- {
- memset(bb, 0, 1024 << EXT2_SUPER_LOG_BLOCK_SIZE(*sb));
- if (is_sparse(i))
- for (j=0;j<gdtsize+1;j++)
- bb[j>>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<itsize;j++)
- {
- int k = j + gdtsize + 3;
-
- bb[k>>3] |= _bitmap[k&7];
- }
-
- for (j=groupsize;j<blocksize;j++)
- bb[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<blocksize;j++)
- bb[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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <stdio.h>
-#include <stdlib.h>
-#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;i<fs->numgroups;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;i<fs->inodeblocks;i++)
- {
- blk_t j;
-
- j = EXT2_GROUP_INODE_TABLE(fs->gd[group])
- - groupstart + i;
- bh->data[j>>3] |= _bitmap[j&7];
- }
-
- for (i=groupsize;i<EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);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;i<fs->numgroups;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;i<num;i++)
- if (ext2_is_data_block(fs, offset+i) &&
- ext2_get_block_state(fs, offset+i))
- {
- fprintf(stderr,
- "error: block relocator "
- "should have relocated "
- "%i\n",
- offset+i);
-
- return 0;
- }
- }
- }
-
- 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;
-
- 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;i<newsize;i++)
- ext2_set_block_state(fs, groupoff + i, 0, 1);
-
- fs->sb.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;i<gblocks;i++)
- {
- if (fs->opt_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;i<fs->numgroups;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 <http://www.gnu.org/licenses/>.
-*/
-
-/* VERSION: libext2resize 1.1.6 (by Lennert)
- * merged 1.1.11 changes (by Andrew)
- */
-
-#include <config.h>
-
-#include <parted/parted.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#ifndef DISCOVER_ONLY
-
-#include <parted/parted.h>
-#include <stdio.h>
-#include <stdlib.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "fat.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-/* 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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "fat.h"
-#include "traverse.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <string.h>
-#include <uuid/uuid.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef FAT_H_INCLUDED
-#define FAT_H_INCLUDED
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "fat.h"
-#include "fatio.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "fat.h"
-#include "traverse.h"
-#include "count.h"
-#include "fatio.h"
-#include "calc.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <parted/endian.h>
-#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 <cluster> 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 <cluster> represents an EOF marker
-*/
-int
-fat_table_is_eof (const FatTable* ft, FatCluster cluster)
-{
- return _test_code_eof (ft, cluster);
-}
-
-/*
- returns true if <cluster> 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 <cluster> 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 <cluster> 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 <cluster> 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 <cluster> 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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "fat.h"
-#include "traverse.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _ADVFS_H
-#define _ADVFS_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _ADVFS_PLUS_H
-#define _ADVFS_PLUS_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 >> CR_SHIFT ) + 1 :
- ( block_number + ((1<<CR_SHIFT)-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _CACHE_H
-#define _CACHE_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _FILE_H
-#define _FILE_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _FILE_PLUS_H
-#define _FILE_PLUS_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/*
- Author : Guillaume Knispel <k_guillaume@libertysurf.fr>
- Report bug to <bug-parted@gnu.org>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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<<HFSP_JOURNALED)) {
- if (!hfsj_replay_journal(fs))
- goto hpo_pg;
- }
-
- priv_data->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 <stdio.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _JOURNAL_H
-#define _JOURNAL_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _PROBE_H
-#define _PROBE_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _RELOC_H
-#define _RELOC_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef DISCOVER_ONLY
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-#include <stdint.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _RELOC_PLUS_H
-#define _RELOC_PLUS_H
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-
-#define _JFS_UTILITY
-#include "jfs_types.h"
-#include "jfs_superblock.h"
-
-#define JFS_SUPER_SECTOR 64
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
- *
- */
-#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 <http://www.gnu.org/licenses/>.
- */
-
-#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 <sys/types.h>
-//#include <asm/byteorder.h>
-typedef unsigned short UniChar;
-#else
-#include <linux/types.h>
-#include <linux/jfs_fs.h>
-#include <linux/nls.h>
-
-#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 <elm> at head of list anchored at <header>
- *
- * 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 <elm> at tail of list anchored at <header>
- *
- * 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 <elm> after <listelm> of list anchored at <header>
- *
- * 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 <elm> before <listelm> of list anchored at <header>
- *
- * 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 <elm> from list anchored at <header>
- *
- * 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 <http://www.gnu.org/licenses/>.
-*/
-
-/* It's a bit silly calling a swap partition a file system. Oh well... */
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <unistd.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <unistd.h>
-#include <string.h>
-#include <limits.h> /* 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#if (DYNAMIC_LOADING || HAVE_LIBREISERFS) && !DISCOVER_ONLY
-
-#include "geom_dal.h"
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-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 <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef GEOM_DAL_H
-#define GEOM_DAL_H
-
-#include <parted/parted.h>
-
-#if DYNAMIC_LOADING || !DISCOVER_ONLY
-
-#include <sys/stat.h>
-
-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 <http://www.gnu.org/licenses/>.
-
- 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 <config.h>
-
-#if (HAVE_LIBREISERFS || DYNAMIC_LOADING) && !DISCOVER_ONLY
-# define REISER_FULL_SUPPORT
-#endif
-
-#include <uuid/uuid.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifdef DYNAMIC_LOADING
-# include <dlfcn.h>
-#endif
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <mark.logan@sun.com>
- */
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-#include <libintl.h>
-#define _(String) dgettext(PACKAGE, String)
-#else
-#define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <unistd.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
-
- Contributor: Ben Collins <bcollins@debian.org>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-#include <parted/debug.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <unistd.h>
-#include <string.h>
-
-#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 <http://www.gnu.org/licenses/>.
- *
- * 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 <stdio.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# define _(String) dgettext (PACKAGE, String)
-#else
-# define _(String) (String)
-#endif /* ENABLE_NLS */
-
-#include <uuid/uuid.h>
-#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 <http://www.gnu.org/licenses/>.
- *
- * 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 <http://www.gnu.org/licenses/>.
- *
- * 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)<<IRIX_DEV_BITSMINOR) \
- | (minor&IRIX_DEV_MAXMIN)))
-
-#define IRIX_DEV_TO_KDEVT(dev) MKDEV(IRIX_DEV_MAJOR(dev),IRIX_DEV_MINOR(dev))
-#define IRIX_DEV_TO_DEVT(dev) ((IRIX_DEV_MAJOR(dev)<<8)|IRIX_DEV_MINOR(dev))
-
-/* __psint_t is the same size as a pointer */
-#if (BITS_PER_LONG == 32)
-typedef int32_t __psint_t;
-typedef uint32_t __psunsigned_t;
-#elif (BITS_PER_LONG == 64)
-typedef int64_t __psint_t;
-typedef uint64_t __psunsigned_t;
-#else
-#error BITS_PER_LONG must be 32 or 64
-#endif
-
-
-/*
- * struct for passing owner/requestor id
- */
-typedef struct flid {
-#ifdef CELL_CAPABLE
- pid_t fl_pid;
- sysid_t fl_sysid;
-#endif
-} flid_t;
-
-#endif /* __KERNEL__ */
-
-#endif /* !__XFS_TYPES_H */
diff --git a/usr/src/lib/libparted/common/libparted/labels/aix.c b/usr/src/lib/libparted/common/libparted/labels/aix.c
deleted file mode 100644
index 43c99d17df..0000000000
--- a/usr/src/lib/libparted/common/libparted/labels/aix.c
+++ /dev/null
@@ -1,295 +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 <http://www.gnu.org/licenses/>.
-
- Contributor: Matt Wilson <msw@redhat.com>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-
- Contributor: Matt Wilson <msw@redhat.com>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <sys/time.h>
-#include <stdbool.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#include "dvh.h"
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#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 <Matt_Domsch@dell.com>
- * - Copied crc32.c from the linux/drivers/net/cipe directory.
- * - Now pass seed as an arg
- * - changed unsigned long to uint32_t, added #include<stdint.h>
- * - 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 <config.h>
-#include <stdint.h>
-
-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 <Matt_Domsch@dell.com>
- 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-#include <parted/crc32.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-
- Contributor: Sven Luther <luther@debian.org>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#ifndef MAX
-# define MAX(a,b) ((a) < (b) ? (b) : (a))
-#endif
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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<size; i++) bstr[i+1] = cstr[i];
-}
-static const char * _amiga_get_bstr (char * bstr) {
- char * cstr = bstr + 1;
- int size = bstr[0];
-
- cstr[size] = '\0';
- return cstr;
-}
-
-#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 "<free>";
- default :
- return "<unknown>";
- }
-}
-
-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; i<RDB_LOCATION_LIMIT; i++) {
- if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) {
- continue;
- }
- if (PED_BE32_TO_CPU (rdb->rdb_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 <http://www.gnu.org/licenses/>.
-
- Contributor: Ben Collins <bcollins@debian.org>
-*/
-
-#include <config.h>
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-#include <parted/endian.h>
-
-#if ENABLE_NLS
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-#include <config.h>
-#include "configmake.h"
-
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#ifdef linux
-# include <parted/linux.h>
-#elif defined(__BEOS__)
-# include <parted/beos.h>
-#elif defined(__sun)
-# include <parted/solaris.h>
-#else
-# include <parted/gnu.h>
-#endif
-
-#if ENABLE_NLS
-# include <locale.h>
-# include <libintl.h>
-# 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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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 <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#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 <http://www.gnu.org/licenses/>.
-*/
-
-/** \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 <parted/device.h>) 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 <config.h>
-#include <parted/parted.h>
-#include <parted/debug.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <float.h>
-
-#define N_(String) String
-#if ENABLE_NLS
-# include <libintl.h>
-# 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/lib/libparted/i386/Makefile b/usr/src/lib/libparted/i386/Makefile
deleted file mode 100644
index 77b0c2e552..0000000000
--- a/usr/src/lib/libparted/i386/Makefile
+++ /dev/null
@@ -1,52 +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.
-#
-
-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 $@