Merge commit 'v2_0_0' into libntfs-3g_port-v2_0_0

Conflicts:
	configure.ac
	include/ntfs/Makefile.am
	include/ntfs/attrib.h
	include/ntfs/bitmap.h
	include/ntfs/collate.h
	include/ntfs/debug.h
	include/ntfs/dir.h
	include/ntfs/endians.h
	include/ntfs/index.h
	include/ntfs/inode.h
	include/ntfs/layout.h
	include/ntfs/logfile.h
	include/ntfs/logging.h
	include/ntfs/mft.h
	include/ntfs/ntfstime.h
	include/ntfs/runlist.h
	include/ntfs/support.h
	include/ntfs/types.h
	include/ntfs/unistr.h
	include/ntfs/volume.h
	libntfs/Makefile.am
	libntfs/attrib.c
	libntfs/attrlist.c
	libntfs/bitmap.c
	libntfs/bootsect.c
	libntfs/collate.c
	libntfs/compress.c
	libntfs/debug.c
	libntfs/device.c
	libntfs/device_io.c
	libntfs/dir.c
	libntfs/index.c
	libntfs/inode.c
	libntfs/lcnalloc.c
	libntfs/logfile.c
	libntfs/logging.c
	libntfs/mft.c
	libntfs/mst.c
	libntfs/runlist.c
	libntfs/security.c
	libntfs/unistr.c
	libntfs/unix_io.c
	libntfs/volume.c
	libntfs/win32_io.c
	ntfsprogs/Makefile.am
	ntfsprogs/mkntfs.c
	ntfsprogs/ntfscat.c
	ntfsprogs/ntfsclone.c
	ntfsprogs/ntfscmp.c
	ntfsprogs/ntfscp.c
	ntfsprogs/ntfsinfo.c
	ntfsprogs/ntfsmount.8.in
	ntfsprogs/ntfsmount.c
	ntfsprogs/ntfsundelete.c
	ntfsprogs/upcase.c
edge.strict_endians
Erik Larsson 2010-11-29 08:37:31 +01:00
commit 713fbb390e
69 changed files with 6172 additions and 5818 deletions

View File

@ -22,3 +22,4 @@ stamp-h.in
ltconfig
missing
INSTALL
cscope.out

13
AUTHORS
View File

@ -1,10 +1,9 @@
ntfsprogs is written and maintained by Anton Altaparmakov <aia21@cantab.net>.
ntfsprogs is written by the Linux-NTFS project (www.linux-ntfs.org) and
maintained by Anton Altaparmakov <aia21 at cantab.net>.
Current active developers on the project are (in alphabetical order):
Current active project members are (in alphabetical order):
Anton Altaparmakov <aia21@cantab.net>
Yuval Fledel (no email address on request)
Yura Pakhuchiy <pakhuchiy@gmail.com>
Richard Russon <ntfs@flatcap.org>
Szakacsits Szabolcs <szaka@sienet.hu>
Anton Altaparmakov <aia21 at cantab.net>
Mario Emmenlauer <mario at emmenlauer.de>
Yura Pakhuchiy <pakhuchiy at gmail.com>

63
CREDITS
View File

@ -3,37 +3,38 @@ project.
The list is sorted alphabetically, so please keep it this way!
Please let me know (email Anton Altaparmakov <aia21@cantab.net>) if you believe
someone is missing or if you prefer to not be listed.
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>
Alexei Alexandrov <alex_alexandrov@hotmail.com>
Anton Altaparmakov <aia21@cantab.net>
Albert D. Cahalan <acahalan@cs.uml.edu>
Russ Christensen <rchriste@cs.utah.edu>
Pete Curran <curran@rpi.edu>
Mario Emmenlauer <mario@emmenlauer.de>
Andras Erdei <ccg@freemail.hu>
Matthew J. Fanto <mattjf@uncompiled.com>
Yuval Fledel (no email address on request)
Marcin GibuÅa <m.gibula@conecto.pl>
Christophe Grenier <grenier@cgsecurity.org>
Ian Jackson <ian@davenant.greenend.org.uk>
Carmelo Kintana <kintana@berkeley.edu>
Jan Kratochvil <project-captive@jankratochvil.net>
Lode Leroy <lode_leroy@hotmail.com>
David Martínez Moreno <ender@debian.org>
Giang Nguyen <cauthu@hotmail.com>
Leonard Norrgård <vinsci@nic.funet.fi>
Holger Ohmacht <holger.ohmacht@web.de>
Per Olofsson <pelle@dsv.su.se>
Yura Pakhuchiy <pakhuchiy@gmail.com>
Yuri Per <yuri@acronis.com>
Richard Russon <ntfs@flatcap.org>
Erik Sørnes <erso1970@yahoo.no>
Szabolcs Szakacsits <szaka@sienet.hu>
Also, various code snippets and especially the autoconf/automake automated
configuration, compilation and installation system have been ripped shamelessly
from numerous different GNU and Gnome utilities and libraries so "Many thanks!"
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!

213
ChangeLog
View File

@ -1,3 +1,210 @@
28/09/2007 - 2.0.0 - ntfsmount sports full read/write, libntfs can read
encrypted files and ntfsresize supports Vista.
- ntfsmount now creates files and directories with security descriptor
that grant full access to everyone. (Yura)
- Fix typo that lead to incorrect sparse file size calculation. (Yuval)
- Fix long standing stupendously stupid bug in libntfs/attrib.c::
ntfs_external_attr_find() and also port a bugfix from the advanced
ntfs kernel driver to the same function. (Anton)
- Add new API ntfs_attr_exist() that checks whether attribute with
selected type and name already present in inode. (Szaka)
- Extend ntfs_index_{add_filename,rm} to support almost all cases of
index operations. (Szaka)
- Support index operations when index root is in the base MFT
record. (Yura)
- calloc/malloc -> ntfs_{calloc,malloc} conversions. (Szaka)
- ntfsclone: don't create image files with executable bit set. (Szaka)
- ntfsclone: metadata cloning: write out extent records. (Szaka)
- ntfsclone: fix sometimes missing error messages and be more
detailed. (Szaka)
- ntfsclone: fix crash in wipe_index_allocation_timestamps(): don't
dump empty index allocation attribute. (Szaka)
- ntfscmp: fine grained AT_INDEX_ALLOCATION comparison. (Szaka)
- ntfsinfo: rename 'Flags:' fields to be unique. (Szaka)
- ntfsinfo: add ntfs_dump_index_header(); dump full index attribute
INDEX_HEADER. (Szaka)
- ntfsinfo: add ntfs_dump_index_block() and use it. (Szaka)
- ntfsinfo: fix output indenting. (Szaka)
- ntfsinfo: make stdout line buffered. (Szaka)
- ntfsinfo: fix segfaults when SDS has absolute security
descriptor. (Szaka)
- ntfsinfo: redirect stderr to /dev/null if --debug isn't used in
debug mode. (Szaka)
- ntfsinfo: fix segfaults on corrupt index blocks. (Szaka)
- ntfsinfo: dump number of entries per block in index allocation
attributes. (Szaka)
- ntfsinfo: dump ATTR_LIST_ENTRY padding in verbose mode. (Szaka)
- ntfsinfo: dump all VCN's in the same numeral system. (Szaka)
- ntfsinfo: dump the FILE_ATTR_DIRECTORY flag. (Szaka)
- ntfsinfo: dump padding between the Update Sequence Array and the
first attribute in verbose mode. (Szaka)
- ntfsinfo: Fix endianness. (Yura)
- ntfsinfo: Make more resilient to corrupt index entries in an index
node. (Anton)
- ntfsinfo: Print in both decimal and hexadecimal where it makes sense
and is useful. (Anton)
- ntfsclone: Define endianness safe image format. (Anton)
- ntfsclone: Redefine image format version number to be the image
format version and not the NTFS version of the imaged volume which is
totally useless. (Anton)
- ntfsclone: Make ntfsclone image format extensible. (Anton)
- ntfsclone: Fix endianness problems. (Anton)
- Allow ntfscp to create the destination file if it does not already
exists by calling ntfs_create(). (Hil)
- Fix GUID to string conversion. (Anton)
- Multiple big-endianness fixes. (zhanglinbao, Yuval)
- Spelling mistake fixes. (Yuval)
- Remove inline keywords from static non-one-liners. (Szaka, Yuval)
- Memory leak fixes. (Yura, Yuval)
- Change ntfs_collate()'s signature to take size_t's. (Yuval)
- Move ntfs_is_collation_rule_supported() from collate.h to collate.c
and rewrite it to be clearer. (Yuval)
- Move ntfs_index_entry_mark_dirty() to index.c. (Szaka)
- Introduce misc.c. Move ntfs_[mc]alloc there. (Szaka)
- Change malloc() calls to ntfs_malloc(). (Szaka)
- ntfsmount: require FUSE version >= 2.6.0 for build. Fixes fusermount
lookup problem and allows to drop compatibility code. (Yura)
- Rewrite ntfs_attr_add() algorithm to be faster and cleverer. (Yura)
- Rename MS_{RDONLY,NOATIME} to NTFS_MNT_{RDONLY,NOATIME}. Introduce
NTFS_MNT_CASE_SENSITIVE. (Yura)
- Treat filenames in POSIX namespace as case insensitive in case of
case insensitive mounts. (Anton, Yura)
- Windows cares only about first 4 records in $MFTMirr and ignores
everything beyond them. Update libntfs behaviour to be like in
windows. (Yura)
- ntfsmount: Fix free clusters and MFT records calculation. (Yura)
- ntfsmount: Fix st_blocks calculation for resident files. (Yuval,
Yura)
- ntfsmount: Umount volume in DESTROY. This is guarantees that all
data would be synced before umount return for volumes mounted with
blkdev option. (Yura)
- Introduce MNT_NTFS_NOT_EXCLUSIVE mount option that tells libntfs do
not open volume exclusively. Useful if libntfs user cares about this
himself, eg. FUSE with blkdev option. (Yura)
- Empty the journal at mount time. (Anton)
- Set the volume dirty bit at mount time (if it is not set already and
clear it again at umount time but only if it was not set to start
with. (Anton)
- Introduce NTFS_MNT_FORENSIC mount option for logfile dumping for
example otherwise the logfile gets wiped out by the mount attempt if
it is not read-only. Also use it for ntfsresize as it wishes to do
its own logfile emptying and volume dirtying. (Anton)
- Raise FUSE dependence to 2.6.1 (the most stable and featured ATM),
rename --enable-fuse-module to more clear --enable-ntfsmount and
cleanup autotools scripts a bit. (Yura)
- ntfsclone: don't check free space if output file is FIFO. (Andree
Leidenfrost)
- Turn ntfs_pathname_to_inode() into ntfs_pathname_to_inode_num() which
returns ntfs inode number instead of opened inode itself.
Reimplement ntfs_pathname_to_inode() as wrapper to new API. (Yura)
- ntfsmount: fix rename if destination already exists. (Yura)
- ntfsfix: do not set VOLUME_MOUNTED_ON_NT4 flag as it causes Vista to
not boot any more.
- Implement ntfs_pread() and ntfs_pwrite() in terms of device
operations pread() and pwrite() respectively and fall back to using
seek() + read()/write() if no pread()/pwrite() device operation is
supplied or the OS does not support the pread()/pwrite() system call.
Adapt unix_io pread()/pwrite() device operations to use pread()/
pwrite() system call and adapt win32_io device operations to not
supply pread()/pwrite(). (Csaba Henk, Anton)
- mkntfs: Generate a random DCE compliant UUID for the created volume
and include --with-uuid[=PFX] and --without-uuid options. (Anton)
- configure.ac: Set language to C. (Anton)
- mkntfs: Always set default cluster size to 4096 bytes regardless of
volume size. This is what Windows Vista does and it makes perfect
sense from a performance point of view. (Anton)
- mkntfs: As announced, remove the deprecated support for creation of
NTFS 1.2/3.0 volumes. We now create NTFS 3.1 volumes only. (Anton)
- mkntfs: Remove lots of unused/unneeded debugging code. (Anton)
- libntfs: Add support for FreeBSD 5.0+ sector aligned access
requirements. (Max Khon)
- mkntfs: Create more Vista like volumes. We now match the security
descriptor attributes (but not yet the security descriptors stored in
$Secure). (Anton)
- libntfs: Rewrite ntfs_upcase_table_build() to generate a Vista
compatible upcase table ($UpCase). (Anton)
- mkntfs: Remove own generation of upcase table, i.e. delete
ntfsprogs/upcase.[ch] and use ntfs_upcase_table_build() supplied by
libntfs. (Anton)
- Upgrade ntfsmount to new FUSE option parsing API. (Yura)
- ntfsmount: Remove "show_sys_files" as potential harmful and
introduce new "case_insensitive" option to support both case
sensitive and insensitive mounts. (Yura)
- ntfsmount: st_block calculation was wrong. (Yuval)
- mkntfs: Use Vista $Boot rather than XP one. (Anton)
- ntfsmount: use utimens() instead of deprecated utime(). (Yura)
- libntfs: Ignore bootsector checksum inconsistencies as too many 3rd
party utilities update the boot sector without correcting the
checksum. Ported change from kernel driver. (Anton)
- ntfsdecrypt: Major improvement! We now validate the .pfx file to be
the right type of RSA key and we also determine the thumbprint and
compare the one in the keys to the one in the .pfx file thus we only
try to decrypt the FEK once we have the correct key. Several other
bug fixes leading to crashes. Also make compilation work on OS X
when gnutls is otherwise not found. (Anton, Yura)
- ntfsmount: fix errno in truncate() operation. (Yura)
- Add new API: __ntfs_attr_truncate that allow user to select whether
holes should be created or clusters allocated. (Yura)
- Add new API: ntfs_attr_map_runlist_range to map part of runlist from
selected VCN to selected VCN. (Yura)
- Make ntfs_attr_update_mapping_pairs to be mostly O(1) for normal
files. (Yura)
- Introduce sparse bitwise annotations to automatically catch endian
bugs. Adopt libntfs (and fix 2 bugs) and ntfsprogs (and fix lots of
bugs). (Yura)
- ntfsinfo: nicely dump special LCN values. (Yura)
- Transparently integrate reading of encrypted files into library.
This adds crypto.[ch], several exported functions that you are not
interested to use and dependency on >=libconfig-1.0.1 to read list of
PFX files with keys. See libntfs/config for example configuration
file. (Yura)
- Add new API ntfs_attr_get_name - returns pointer to unicode name of
attribute. (Yura)
- ntfsinfo: Dump raw content of LOGGED_UTILITY_STREAM in verbose
mode. (Yura)
- Export NTFS_EFS string. (Yura)
- Merge --enable-debug and --enable-debug-logging. (Yura)
- Add --enable-sparse configure option. (Yura)
- Fix corner case in hole instantiating in ntfs_attr_pwrite(). (Szaka)
- Fix heavy memory usage during whole instantiating and add new API:
ntfs_rl_fill_zero. (Szaka, Yura)
- ntfs_delete() now takes pointer to pointer to ntfs_inode for file to
delete and closes inode only in cases there are no more hard links
left to file. (Yura)
- Library no longer perform time updates, only provides API for
performing time updates. Remove ntfs_inode_update_{a,}time() and
introduce ntfs_inode_update_times(). Make ntfsmount update time
according to SUS. (Yura)
- Fix cache handling in utils_attr_get_name. (Bogdan, Yura)
- ntfsmount: Submit inode number during readdir. (Ted Anderson, Szaka)
- Fix syslog logging handler to respect all logging flags. (Yura)
- ntfs_readdir, ntfs_fuse_filler: return with error if FUSE filler
failed. (Szaka, Yura)
- Fix rare directory corruption in index code. (Szaka, Yura)
- ntfsmount: Mount block devices with blkdev mount option. (Yura)
- ntfsmount: Add set-uid-root binary support. (Yura)
- ntfsmount: Implement {no,}relatime (relative atime) options. (Yura)
- Make libntfs keep track number of free clusters and MFT records.
Thanks to David Fox and Szabolcs Szakacsits for idea. (Yura)
- ntfsmount: Add bmap support. (Szaka, Yura)
- Introduce NTFS_MNT_FORCE instead of third parameter (force) of
utils_mount_volume. (Yura)
- ntfs_attr_pwrite: Write 4096 bytes blocks when possible. (David Fox,
Szaka, Anton, Yura)
- Allow mounting volumes with non-clean logfile with force mount
option. Thanks to Szaka for idea. (Yura)
- libntfs: Attach opened inodes to volume. (Yura)
- libntfs: Attach opened attributes to inode. (Yura)
- ntfsmount: Save pointer to ntfs_attr in (fuse_file_info *)->fh and
use it in ntfs_fuse_{read,write}. (Yura)
- ntfsmount: Implement .create(), .ftruncate(), .fgetattr(). (Yura)
- libntfs: Sync and warn about not closed inodes in ntfs_umount. (Yura)
- ntfsmount: Cache directory in which was performed last
operation. (Yura)
- Install mount.fuse.ntfs symbolic link. (Yura)
- ntfsmount: Fill .st_mode in readdir(). (Szaka, Yura)
21/06/2006 - 1.13.1 - Various fixes.
- Fix bug in ntfs_attr_pwrite() when we sometimes lose current run in
@ -18,13 +225,13 @@
compressed metadata image size by 10-25% and more importantly it
eliminates non-interesting ntfscmp differences. (Szaka)
- Change utils_parse_size() to use a base of 0 instead of 10 when
calling strtoll(). This automagically allows specification of
calling strtoll(). This automatically allows specification of
numbers in hex (and octal if anyone is crazy enough to use that) in
addition to decimal numbers on the command line options to most if
not all utilities. (Anton)
- Fix comparison of $MFT and $MFTMirr to not bail out when there are
unused, invalid mft records which are the same in both $MFT and
$MFTMirr. Ported from kernel driver 2.1.27 release and aplied both
$MFTMirr. Ported from kernel driver 2.1.27 release and applied both
to libntfs/volume.c mount related code and to ntfsprogs/ntfsfix.c's
fixup code. (Anton)
- Change ntfsinfo to dump the key data as well as the keys themselves
@ -129,7 +336,7 @@
- New APIs (dir.[ch]):
ntfs_create_device() for Interix block and character devices
creation.
ntfs_crate_symlink() for Interix symbolic links creation. (Yura)
ntfs_create_symlink() for Interix symbolic links creation. (Yura)
- Teach ntfs_create() to create Interix FIFOs and sockets. (Yura)
- Fix the -u option in ntfsundelete. Instead of a confusing optional
parameter, there's a new option -i with a required parameter. (Rich)

27
NEWS
View File

@ -1,21 +1,16 @@
Current news
============
ntfsprogs 2.0.0
===============
mkntfs now creates NTFS 3.1 (Windows XP) volumes by default. The old NTFS 1.2
format is now deprecated and whilst it can still be specified using a command
line option, it will be removed in a future release.
ntfsmount (and libntfs) now has full basic read/write support.
ntfsmount can create/delete/move files and directories! It is not a full
implementation, thus sometimes it will say 'Operation is not supported',
nothing bad will happen to user data in this case. (Yura Pakhuchiy)
Cryptographic code is now integrated into libntfs, thus ntfscat and ntfsmount
now can read encrypted files. See "man 8 libntfs" for details.
Older news
==========
ntfsresize (and the entirety of ntfsprogs/libntfs in fact) now have full
support for Windows Vista.
Add new utility: ntfsmount. It is a FUSE module that uses on libntfs. So,
you need FUSE 2.3 to compile it. This module supports file overwrite including
changing the file size and can read/write/add/remove named data streams via
"file:stream" interface and list them via "ntfs.streams.list" extended
attribute (this only if xattr support is enabled). (Yura Pakhuchiy)
ntfsprogs and libntfs are now entirely endian safe and more over now we have
checks that automatically reports endian errors.
Moved back from BitKeeper to CVS on SF.net.
mkntfs now creates a DCE compliant GUID for the volume and does a few other
things to be more compliant with Windows Vista.

2
README
View File

@ -5,7 +5,7 @@ Linux-NTFS
The Linux-NTFS project aims to bring full support for the NTFS filesystem to
the Linux operating system.
Linux-NTFS is copyright (c) 2000-2006 Anton Altaparmakov.
Linux-NTFS is copyright (c) 2000-2007 Anton Altaparmakov.
All of the contents of the Linux-NTFS project are free software, released under
the GNU General Public License and you are welcome to redistribute them under

View File

@ -1,10 +1,3 @@
********************
* libntfs-gnomevfs *
********************
- be generic filter: provide ntfs_device_operations from parent GnomeVFSHandle
***********
* libntfs *
***********
@ -13,13 +6,7 @@
* HIGH priority *
*****************
- complete ntfs_index_{add_filename,rm}
- move ntfsdecrypt to library.
- complete the implementation of ntfs_attr_truncate() (for compressed files)
- add write of compressed attributes
- Make ntfs_attr_{truncate,pwrite} work for compressed/encrypted attributes
- detect presence of usnjrnl and if present and mounting rw, re-stamp it (see
current ntfs driver for example in 2.6.15 kernel)
@ -30,6 +17,9 @@
previous mount left the block size to larger value and we expect 512 bytes as
that would be incredibly inefficient
- fix freebsd_io.c and win32_io.c to support device operations ->pread() and
->pwrite() to improve their performance
*******************
* MEDIUM priority *
*******************
@ -50,10 +40,6 @@
* LOW priority *
****************
- Do we attach attributes (ntfs_attr) to the corresponding ntfs_inode? Now we
just atach the inode to the attribute and expect the user to not shoot
themselves in the foot.
- add ACL read/write support to library
- add MS BackupAPI to library
@ -63,3 +49,12 @@
- add defrag API to library
- write utilities for all of the above
********************
* libntfs-gnomevfs *
********************
- be generic filter: provide ntfs_device_operations from parent GnomeVFSHandle

View File

@ -65,7 +65,6 @@ Thanks,
**********
- add ability to copy multiply files at once.
- add ability to create new files.
***********
@ -93,7 +92,6 @@ Thanks,
* ntfsmount *
*************
- Cache opened inodes for faster access.
**************

View File

@ -1,5 +1,5 @@
#!/bin/bash
# Run this to generate all the initial makefiles, etc.
#!/usr/bin/env bash
# Run this to generate configure, Makefile.in's, etc
if test "$srcdir" == ""; then
srcdir=.
@ -24,6 +24,17 @@ fi
exit 1
}
UNAME=`which uname`
if [ $? -eq 0 -a -n ${UNAME} -a -x ${UNAME} ]; then
OS=`${UNAME} -s`
if [ $? -eq 0 -a -n ${OS} -a "${OS}" == "Darwin" ]; then
echo ""
echo "Running on Mac OS X / Darwin. Setting LIBTOOLIZE=glibtoolize..."
echo ""
export LIBTOOLIZE="glibtoolize"
fi
fi
echo Running autoreconf --verbose --install
autoreconf --force --verbose --install

View File

@ -22,7 +22,7 @@
#
AC_PREREQ(2.59)
AC_INIT([ntfsprogs],[1.13.1-ntfs-3g.1],[ntfs-3g-devel@lists.sourceforge.net])
AC_INIT([ntfsprogs],[2.0.0-ntfs-3g.1],[ntfs-3g-devel@lists.sourceforge.net])
#
# Before making a release, the LTVERSION string should be modified.
@ -50,9 +50,10 @@ AC_INIT([ntfsprogs],[1.13.1-ntfs-3g.1],[ntfs-3g-devel@lists.sourceforge.net])
#
# - If the interface is the same as the previous version, change to C:R+1:A
#
LTVERSION_LIBNTFS="9:0:0"
LTVERSION_LIBNTFS="10:0:0"
AC_SUBST(LTVERSION_LIBNTFS)
AC_LANG([C])
AC_CANONICAL_HOST([])
AC_CANONICAL_TARGET([])
AC_CONFIG_SRCDIR([config.h.in])
@ -85,6 +86,11 @@ AC_ARG_ENABLE(debug,
enable_debug=no
)
AC_ARG_ENABLE(sparse,
AS_HELP_STRING(--enable-sparse,enable sparse code checking), ,
enable_sparse=no
)
# AH_TEMPLATE is needed here because we want to have a template in config.h
# regardless of whether the option is given or not.
AH_TEMPLATE([NO_NTFS_DEVICE_DEFAULT_IO_OPS],
@ -108,8 +114,8 @@ AC_ARG_ENABLE(gnome-vfs,
AC_ARG_ENABLE(crypto,
AS_HELP_STRING(--enable-crypto,enable crypto related code and utilities
(default=no)), ,
enable_crypto=no
(default=detect)), ,
enable_crypto=auto
)
AC_ARG_ENABLE(really-static,
@ -130,26 +136,7 @@ AC_ARG_ENABLE(test,
)
AM_CONDITIONAL(ENABLE_TEST, test "$enable_test" = yes)
if test "$enable_test" = "yes"; then
CFLAGS="$CFLAGS -DNTFS_TEST"
fi
AH_TEMPLATE([NTFS_DISABLE_DEBUG_LOGGING],
[Define this if you want to compile out the debug log messages.
This will reduce the size of the binaries.])
AC_ARG_ENABLE(debug-logging,
AS_HELP_STRING(--disable-debug-logging,Remove debug logging from the code),
if test "$enable_debug_logging" == "no"; then
AC_DEFINE(NTFS_DISABLE_DEBUG_LOGGING)
fi,
)
AC_ARG_ENABLE(rich,
AS_HELP_STRING(--enable-rich,enable Rich's "rm" test code), ,
enable_rich=no
)
AM_CONDITIONAL(ENABLE_RICH, test "$enable_rich" = yes)
if test "$enable_rich" = "yes"; then
CFLAGS="$CFLAGS -DNTFS_RICH"
CFLAGS="${CFLAGS} -DNTFS_TEST"
fi
# Use GNU extensions if available.
@ -167,6 +154,7 @@ esac
# Checks for programs.
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
AM_PROG_CC_C_O
AC_PROG_INSTALL
AC_PATH_PROG(RM, rm, rm)
AC_PROG_LN_S
@ -203,7 +191,7 @@ PKG_CHECK_MODULES(NTFS_3G_MODULE, libntfs-3g >= 2010.5.22, [],
compile_crypto=false
if test "$enable_crypto" != "no"; then
have_libgcrypt=false
AM_PATH_LIBGCRYPT(1.2.0, [ have_libgcrypt=true ],
AM_PATH_LIBGCRYPT(1.2.2, [ have_libgcrypt=true ],
[
if test "$enable_crypto" = "yes"; then
AC_MSG_ERROR([Linux-NTFS crypto code requires the gcrypt library.])
@ -212,17 +200,29 @@ if test "$enable_crypto" != "no"; then
fi
])
have_libgnutls=false
PKG_CHECK_MODULES(GNUTLS_MODULE, gnutls >= 1.2.8, [ have_libgnutls=true ],
[
PKG_CHECK_MODULES(GNUTLS, gnutls >= 1.4.4, [ have_libgnutls=true ],
if test "$enable_crypto" = "yes"; then
AC_MSG_ERROR([Linux-NTFS crypto code requires the gnutls library.])
else
AC_MSG_WARN([Linux-NTFS crypto code requires the gnutls library.])
fi
])
)
have_libconfig=false
PKG_CHECK_MODULES(libconfig, libconfig >= 1.0.1, [ have_libconfig=true ],
if test "$enable_crypto" = "yes"; then
AC_MSG_ERROR([Linux-NTFS crypto code requires the libconfig.])
else
AC_MSG_WARN([Linux-NTFS crypto code requires the libconfig.])
fi
)
if test "$have_libgcrypt" = "true"; then
if test "$have_libgnutls" = "true"; then
compile_crypto=true
if test "$have_libconfig" = "true"; then
compile_crypto=true
AC_DEFINE([ENABLE_CRYPTO], 1,
[Define this to 1 if you want to enable support of
encrypted files in libntfs and utilities.])
fi
fi
fi
fi
@ -234,6 +234,42 @@ all_includes="$all_includes $USER_INCLUDES"
AC_SUBST(all_includes)
AC_SUBST(all_libraries)
# Specify support for generating DCE compliant UUIDs (aka GUIDs). We check if
# uuid/uuid.h header is present and the uuid library is present that goes with
# it and then check if uuid_generate() is present and usable.
#
# DCE UUIDs are enabled by default and can be disabled with the --disable-uuid
# option to the configure script.
AC_ARG_WITH(uuid, [
--with-uuid@<:@=PFX@:>@ generate DCE compliant UUIDs, with optional prefix
to uuid library and headers @<:@default=detect@:>@
--without-uuid do not generate DCE compliant UUIDs],
if test "$with_uuid" = "yes"; then
extrapath=default
elif test "$with_uuid" = "no"; then
extrapath=
else
extrapath=$with_uuid
fi,
extrapath=default
)
if test "x$extrapath" != "x"; then
if test "x$extrapath" != "xdefault"; then
MKNTFS_CPPFLAGS="$MKNTFS_CPPFLAGS -I$extrapath/include"
MKNTFS_LIBS="$MKNTFS_LIBS -L$extrapath/lib"
fi
AC_CHECK_HEADER([uuid/uuid.h],
AC_CHECK_LIB([uuid], [uuid_generate],
AC_DEFINE([ENABLE_UUID], 1,
[Define this to 1 if you want to enable generation of
DCE compliant UUIDs.])
MKNTFS_LIBS="$MKNTFS_LIBS -luuid",
AC_MSG_WARN([Linux-NTFS DCE compliant UUID generation code requires the uuid library.]),
),
AC_MSG_WARN([Linux-NTFS DCE compliant UUID generation code requires the uuid library.]),
)
fi
# Get compiler name
if test ! -z "$CC"; then
_cc="$CC"
@ -273,7 +309,13 @@ fi
# Add debugging switches if --enable-debug was specified.
if test "$enable_debug" = "yes"; then
CFLAGS="$CFLAGS -ggdb3 -DDEBUG"
CFLAGS="$CFLAGS -ggdb3 -DDEBUG -O0"
fi
# Set cgcc as compiler and add sparse flags if --enable-sparse was specified.
if test "$enable_sparse" = "yes"; then
CC="cgcc"
CFLAGS="$CFLAGS -Wbitwise -Wno-transparent-union"
fi
AC_SUBST(CFLAGS)
@ -285,6 +327,9 @@ AC_SUBST(LIBNTFS_CFLAGS)
AC_SUBST(LIBNTFS_GNOMEVFS_CFLAGS)
AC_SUBST(LIBNTFS_GNOMEVFS_LIBS)
AC_SUBST(MKNTFS_CPPFLAGS)
AC_SUBST(MKNTFS_LIBS)
AC_SUBST(AUTODIRS)
# Checks for libraries.
@ -297,7 +342,7 @@ AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h limits.h locale.h \
endian.h byteswap.h sys/byteorder.h sys/endian.h sys/param.h \
sys/ioctl.h sys/mount.h sys/stat.h sys/types.h sys/vfs.h \
sys/statvfs.h sys/sysmacros.h linux/major.h linux/fd.h linux/hdreg.h \
machine/endian.h gcrypt.h windows.h gnutls/pkcs12.h syslog.h])
machine/endian.h windows.h syslog.h pwd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
@ -333,6 +378,7 @@ AC_CONFIG_FILES([
include/ntfs/Makefile
libntfs/Makefile
libntfs/libntfs.conf
libntfs/libntfs.8
libntfs/libntfs-gnomevfs.8
ntfsprogs/Makefile
ntfsprogs/mkntfs.8

View File

@ -3,8 +3,6 @@ linux_ntfsincludedir = $(includedir)/ntfs
linux_ntfsinclude_HEADERS = \
gnome-vfs-method.h \
gnome-vfs-module.h \
list.h \
rich.h \
tree.h
list.h
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,46 @@
/**
* 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 */

View File

@ -32,7 +32,7 @@ G_BEGIN_DECLS
G_LOCK_EXTERN(libntfs);
#define libntfs_newn(objp, n) ((objp) = g_new(typeof(*(objp)), (n)))
#define libntfs_newn(objp, n) ((objp) = (typeof(objp))g_new(typeof(*(objp)), (n)))
#define libntfs_new(objp) (libntfs_newn((objp), 1))
#define LIBNTFS_MEMZERO(objp) (memset((objp), 0, sizeof(*(objp))))

View File

@ -24,7 +24,7 @@
/**
* struct list_head - Simple doubly linked list implementation.
*
*
* Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor
* modifications). - AIA
*

View File

@ -1,40 +0,0 @@
/*
* rich.h - Temporary junk file. Part of the Linux-NTFS project.
*
* 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_RICH_H_
#define _NTFS_RICH_H_
#include "layout.h"
#include "attrib.h"
#include "bitmap.h"
#define ROUND_UP(num,bound) (((num)+((bound)-1)) & ~((bound)-1))
#define ROUND_DOWN(num,bound) ((num) & ~((bound)-1))
#define ATTR_SIZE(s) ROUND_UP(s,8)
ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft);
int utils_free_non_residents3(struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_RECORD *attr);
int utils_free_non_residents2(ntfs_inode *inode, struct ntfs_bmp *bmp);
void ntfs_name_print(ntfschar *name, int name_len);
#endif /* _NTFS_RICH_H_ */

View File

@ -1,82 +0,0 @@
/*
* tree.h - Directory tree handling code. Part of the Linux-NTFS project.
*
* 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_TREE_H_
#define _NTFS_TREE_H_
#include "layout.h"
#include "volume.h"
struct ntfs_dir;
/**
* struct ntfs_dt -
*/
struct ntfs_dt {
struct ntfs_dir *dir;
struct ntfs_dt *parent;
u8 *data;
int data_len;
int child_count;
INDEX_ENTRY **children;
struct ntfs_dt **sub_nodes;
ntfs_inode **inodes;
VCN vcn;
INDEX_HEADER *header;
BOOL changed;
};
void ntfs_dt_free(struct ntfs_dt *dt);
int ntfs_dt_rollback(struct ntfs_dt *dt);
int ntfs_dt_commit(struct ntfs_dt *dt);
BOOL ntfs_dt_create_children2(struct ntfs_dt *dt, int count);
BOOL ntfs_dt_resize_children3(struct ntfs_dt *dt, int new);
int ntfs_dt_root_count(struct ntfs_dt *dt);
int ntfs_dt_alloc_count(struct ntfs_dt *dt);
int ntfs_dt_initialise2(ntfs_volume *vol, struct ntfs_dt *dt);
struct ntfs_dt * ntfs_dt_create(struct ntfs_dir *dir, struct ntfs_dt *parent, VCN vcn);
MFT_REF ntfs_dt_find(struct ntfs_dt *dt, ntfschar *name, int name_len);
struct ntfs_dt * ntfs_dt_find2(struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
struct ntfs_dt * ntfs_dt_find3(struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
struct ntfs_dt * ntfs_dt_find4(struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
void ntfs_dt_find_all(struct ntfs_dt *dt);
int ntfs_dt_find_parent(struct ntfs_dt *dt);
BOOL ntfs_dt_isroot(struct ntfs_dt *dt);
int ntfs_dt_root_freespace(struct ntfs_dt *dt);
int ntfs_dt_alloc_freespace(struct ntfs_dt *dt);
int ntfs_dt_transfer(struct ntfs_dt *old, struct ntfs_dt *new, int start, int count);
int ntfs_dt_alloc_insert(struct ntfs_dt *dt, INDEX_ENTRY *first, int count);
INDEX_ENTRY * ntfs_dt_alloc_insert2(struct ntfs_dt *dt, int before, int count, int bytes);
int ntfs_dt_root_insert(struct ntfs_dt *dt, INDEX_ENTRY *first, int count);
int ntfs_dt_alloc_remove2(struct ntfs_dt *dt, int start, int count);
int ntfs_dt_root_remove2(struct ntfs_dt *dt, int start, int count);
int ntfs_dt_transfer2(struct ntfs_dt *old, struct ntfs_dt *new, int start, int count);
int ntfs_dt_root_replace(struct ntfs_dt *del, int del_num, INDEX_ENTRY *del_ie, INDEX_ENTRY *suc_ie);
BOOL ntfs_dt_alloc_replace(struct ntfs_dt *del, int del_num, INDEX_ENTRY *del_ie, INDEX_ENTRY *suc_ie);
BOOL ntfs_dt_root_remove(struct ntfs_dt *del, int del_num);
BOOL ntfs_dt_alloc_remove(struct ntfs_dt *del, int del_num);
int ntfs_dt_alloc_add(struct ntfs_dt *parent, int index_num, INDEX_ENTRY *ie, struct ntfs_dt *child);
int ntfs_dt_root_add(struct ntfs_dt *parent, int index_num, INDEX_ENTRY *ie, struct ntfs_dt *child);
int ntfs_dt_add2(INDEX_ENTRY *ie, struct ntfs_dt *suc, int suc_num, struct ntfs_dt *ded);
#endif /* _NTFS_TREE_H_ */

View File

@ -48,11 +48,12 @@ libntfs_gnomevfs_la_SOURCES = \
gnome-vfs-method.c \
gnome-vfs-module.c
man_MANS = libntfs-gnomevfs.8
man_MANS = libntfs.8 \
libntfs-gnomevfs.8
AM_CPPFLAGS = $(linux_ntfsincludedir) $(all_includes)
EXTRA_DIST = libntfs.conf.in
EXTRA_DIST = libntfs.conf.in config
MAINTAINERCLEANFILES = Makefile.in

10
libntfs/config 100644
View File

@ -0,0 +1,10 @@
# libntfs sample configuration file
crypto : {
keys = (
("/home/yura/ntfs/my3.pfx", "my3"), # key with password
# ("/home/yura/ntfs/my-rec.pfx", ""), // password-less key
("/home/yura/ntfs/my.pfx") /* password-less key */
);
};

1518
libntfs/crypto.c 100644

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,546 @@
/**
* freebsd_io.c - FreeBSD disk io functions. Part of the Linux-NTFS project.
*
* FreeBSD 5.0+ does not have block devices and requires read/writes from/to
* character devices to be sector aligned.
*
* Copyright (c) 2006 Max Khon
* Copyright (c) 2006 Anton Altaparmakov
* 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 NTFS-3G
* 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 <sys/disk.h>
#include "types.h"
#include "mst.h"
#include "debug.h"
#include "device.h"
#include "logging.h"
typedef struct {
int fd;
s64 pos;
s32 block_size;
s64 media_size;
} freebsd_fd;
#define DEV_FD(dev) (((freebsd_fd *) dev->d_private))
#define RAW_IO_ALIGNED(dev, offset, count) \
(DEV_FD(dev)->block_size == 0 || \
((offset) % DEV_FD(dev)->block_size == 0 && \
(count) % DEV_FD(dev)->block_size == 0))
#define RAW_IO_ALIGN(dev, offset) \
((offset) / DEV_FD(dev)->block_size * DEV_FD(dev)->block_size)
#define RAW_IO_MAX_SIZE (128 * 1024 * 1024)
/* Define to nothing if not present on this system. */
#ifndef O_EXCL
# define O_EXCL 0
#endif
/**
* Get block_size and media_size
*/
static int freebsd_get_size(struct ntfs_device *dev)
{
off_t ms;
int bs;
struct stat sb;
if (fstat(DEV_FD(dev)->fd, &sb) < 0) {
ntfs_log_perror("Failed to stat '%s'", dev->d_name);
return -1;
}
if (S_ISREG(sb.st_mode)) {
DEV_FD(dev)->media_size = sb.st_size;
ntfs_log_trace("%s: regular file (media_size %lld)\n",
dev->d_name, DEV_FD(dev)->media_size);
return 0;
}
if (ioctl(DEV_FD(dev)->fd, DIOCGSECTORSIZE, &bs) < 0) {
ntfs_log_perror("Failed to ioctl(DIOCGSECTORSIZE) '%s'",
dev->d_name);
return -1;
}
DEV_FD(dev)->block_size = bs;
ntfs_log_trace("%s: block size %d\n", dev->d_name, bs);
if (ioctl(DEV_FD(dev)->fd, DIOCGMEDIASIZE, &ms) < 0) {
ntfs_log_perror("Failed to ioctl(DIOCGMEDIASIZE) '%s'",
dev->d_name);
return -1;
}
DEV_FD(dev)->media_size = ms;
ntfs_log_trace("%s: media size %lld\n", dev->d_name, ms);
return 0;
}
/**
* freebsd_pread - Aligned read
*/
static inline ssize_t freebsd_pread(struct ntfs_device *dev, char *buf,
size_t count, s64 offset)
{
return pread(DEV_FD(dev)->fd, buf, count, offset);
}
/**
* freebsd_pwrite - Aligned write
*/
static inline ssize_t freebsd_pwrite(struct ntfs_device *dev, const char *buf,
size_t count, s64 offset)
{
return pwrite(DEV_FD(dev)->fd, buf, count, offset);
}
/**
* ntfs_device_freebsd_io_open - Open a device and lock it exclusively
* @dev:
* @flags:
*
* Description...
*
* Returns:
*/
static int ntfs_device_freebsd_io_open(struct ntfs_device *dev, int flags)
{
#if 0
struct flock flk;
#endif
struct stat sbuf;
int err;
if (NDevOpen(dev)) {
errno = EBUSY;
return -1;
}
if (stat(dev->d_name, &sbuf)) {
ntfs_log_perror("Failed to access '%s'", dev->d_name);
return -1;
}
if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode))
NDevSetBlock(dev);
dev->d_private = malloc(sizeof(freebsd_fd));
if (!dev->d_private)
return -1;
DEV_FD(dev)->fd = -1;
DEV_FD(dev)->pos = 0;
DEV_FD(dev)->block_size = 0;
DEV_FD(dev)->media_size = 0;
DEV_FD(dev)->fd = open(dev->d_name, flags);
if (DEV_FD(dev)->fd == -1) {
err = errno;
goto err_out;
}
if ((flags & O_RDWR) != O_RDWR)
NDevSetReadOnly(dev);
#if 0
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)->fd, F_SETLK, &flk)) {
err = errno;
ntfs_log_perror("Failed to %s lock '%s'", NDevReadOnly(dev) ?
"read" : "write", dev->d_name);
if (close(DEV_FD(dev)->fd))
ntfs_log_perror("Failed to close '%s'", dev->d_name);
goto err_out;
}
#endif
if (freebsd_get_size(dev) < 0) {
err = errno;
close(DEV_FD(dev)->fd);
goto err_out;
}
NDevSetOpen(dev);
return 0;
err_out:
free(dev->d_private);
dev->d_private = NULL;
errno = err;
return -1;
}
/**
* ntfs_device_freebsd_io_close - Close the device, releasing the lock
* @dev:
*
* Description...
*
* Returns:
*/
static int ntfs_device_freebsd_io_close(struct ntfs_device *dev)
{
#if 0
struct flock flk;
#endif
if (!NDevOpen(dev)) {
errno = EBADF;
return -1;
}
if (NDevDirty(dev))
fsync(DEV_FD(dev)->fd);
#if 0
/* 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)->fd, F_SETLK, &flk))
ntfs_log_perror("ntfs_device_freebsd_io_close: Warning: Could not "
"unlock %s", dev->d_name);
#endif
/* Close the file descriptor and clear our open flag. */
if (close(DEV_FD(dev)->fd))
return -1;
NDevClearOpen(dev);
free(dev->d_private);
dev->d_private = NULL;
return 0;
}
/**
* ntfs_device_freebsd_io_seek - Seek to a place on the device
* @dev:
* @offset:
* @whence:
*
* Description...
*
* Returns:
*/
static s64 ntfs_device_freebsd_io_seek(struct ntfs_device *dev, s64 offset,
int whence)
{
s64 abs_pos;
ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);
switch (whence) {
case SEEK_SET:
abs_pos = offset;
break;
case SEEK_CUR:
abs_pos = DEV_FD(dev)->pos + offset;
break;
case SEEK_END:
abs_pos = DEV_FD(dev)->media_size + offset;
break;
default:
ntfs_log_trace("Wrong mode %d.\n", whence);
errno = EINVAL;
return -1;
}
if (abs_pos < 0 || abs_pos > DEV_FD(dev)->media_size) {
ntfs_log_trace("Seeking outsize seekable area.\n");
errno = EINVAL;
return -1;
}
DEV_FD(dev)->pos = abs_pos;
return abs_pos;
}
/**
* ntfs_device_freebsd_io_read - Read from the device, from the current location
* @dev:
* @buf:
* @count:
*
* Description...
*
* Returns:
*/
static s64 ntfs_device_freebsd_io_read(struct ntfs_device *dev, void *buf,
s64 count)
{
s64 start, start_aligned;
s64 end, end_aligned;
size_t count_aligned;
char *buf_aligned;
ssize_t nr;
/* short-circuit for regular files */
start = DEV_FD(dev)->pos;
if (count > RAW_IO_MAX_SIZE)
count = RAW_IO_MAX_SIZE;
if (RAW_IO_ALIGNED(dev, start, count)) {
nr = freebsd_pread(dev, buf, count, start);
if (nr <= 0)
return nr;
DEV_FD(dev)->pos += nr;
return nr;
}
/*
* +- start_aligned +- end_aligned
* | |
* | +- start +- end |
* v v v v
* |----------|----------|----------|
* ^ ^
* +----- count ------+
* ^ ^
* +-------- count_aligned ---------+
*/
start_aligned = RAW_IO_ALIGN(dev, start);
end = start + count;
end_aligned = RAW_IO_ALIGN(dev, end) +
(RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
count_aligned = end_aligned - start_aligned;
ntfs_log_trace(
"%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
dev->d_name, count, count_aligned,
start, start_aligned, end, end_aligned);
/* allocate buffer */
buf_aligned = malloc(count_aligned);
if (buf_aligned == NULL) {
ntfs_log_trace("malloc(%d) failed\n", count_aligned);
return -1;
}
/* read aligned data */
nr = freebsd_pread(dev, buf_aligned, count_aligned, start_aligned);
if (nr == 0)
return 0;
if (nr < 0 || nr < start - start_aligned) {
free(buf_aligned);
return -1;
}
/* copy out */
memcpy(buf, buf_aligned + (start - start_aligned), count);
free(buf_aligned);
nr -= start - start_aligned;
if (nr > count)
nr = count;
DEV_FD(dev)->pos += nr;
return nr;
}
/**
* ntfs_device_freebsd_io_write - Write to the device, at the current location
* @dev:
* @buf:
* @count:
*
* Description...
*
* Returns:
*/
static s64 ntfs_device_freebsd_io_write(struct ntfs_device *dev, const void *buf,
s64 count)
{
s64 start, start_aligned;
s64 end, end_aligned;
size_t count_aligned;
char *buf_aligned;
ssize_t nw;
if (NDevReadOnly(dev)) {
errno = EROFS;
return -1;
}
NDevSetDirty(dev);
/* short-circuit for regular files */
start = DEV_FD(dev)->pos;
if (count > RAW_IO_MAX_SIZE)
count = RAW_IO_MAX_SIZE;
if (RAW_IO_ALIGNED(dev, start, count)) {
nw = freebsd_pwrite(dev, buf, count, start);
if (nw <= 0)
return nw;
DEV_FD(dev)->pos += nw;
return nw;
}
/*
* +- start_aligned +- end_aligned
* | |
* | +- start +- end |
* v v v v
* |----------|----------|----------|
* ^ ^
* +----- count ------+
* ^ ^
* +-------- count_aligned ---------+
*/
start_aligned = RAW_IO_ALIGN(dev, start);
end = start + count;
end_aligned = RAW_IO_ALIGN(dev, end) +
(RAW_IO_ALIGNED(dev, end, 0) ? 0 : DEV_FD(dev)->block_size);
count_aligned = end_aligned - start_aligned;
ntfs_log_trace(
"%s: count = 0x%llx/0x%x, start = 0x%llx/0x%llx, end = 0x%llx/0x%llx\n",
dev->d_name, count, count_aligned,
start, start_aligned, end, end_aligned);
/* allocate buffer */
buf_aligned = malloc(count_aligned);
if (buf_aligned == NULL) {
ntfs_log_trace("malloc(%d) failed\n", count_aligned);
return -1;
}
/* read aligned lead-in */
if (freebsd_pread(dev, buf_aligned, DEV_FD(dev)->block_size, start_aligned) != DEV_FD(dev)->block_size) {
ntfs_log_trace("read lead-in failed\n");
free(buf_aligned);
return -1;
}
/* read aligned lead-out */
if (end != end_aligned && count_aligned > DEV_FD(dev)->block_size) {
if (freebsd_pread(dev, buf_aligned + count_aligned - DEV_FD(dev)->block_size, DEV_FD(dev)->block_size, end_aligned - DEV_FD(dev)->block_size) != DEV_FD(dev)->block_size) {
ntfs_log_trace("read lead-out failed\n");
free(buf_aligned);
return -1;
}
}
/* copy data to write */
memcpy(buf_aligned + (start - start_aligned), buf, count);
/* write aligned data */
nw = freebsd_pwrite(dev, buf_aligned, count_aligned, start_aligned);
free(buf_aligned);
if (nw < 0 || nw < start - start_aligned)
return -1;
nw -= start - start_aligned;
if (nw > count)
nw = count;
DEV_FD(dev)->pos += nw;
return nw;
}
/**
* ntfs_device_freebsd_io_sync - Flush any buffered changes to the device
* @dev:
*
* Description...
*
* Returns:
*/
static int ntfs_device_freebsd_io_sync(struct ntfs_device *dev)
{
if (!NDevReadOnly(dev)) {
int res = fsync(DEV_FD(dev)->fd);
if (!res)
NDevClearDirty(dev);
return res;
}
return 0;
}
/**
* ntfs_device_freebsd_io_stat - Get information about the device
* @dev:
* @buf:
*
* Description...
*
* Returns:
*/
static int ntfs_device_freebsd_io_stat(struct ntfs_device *dev, struct stat *buf)
{
return fstat(DEV_FD(dev)->fd, buf);
}
/**
* ntfs_device_freebsd_io_ioctl - Perform an ioctl on the device
* @dev:
* @request:
* @argp:
*
* Description...
*
* Returns:
*/
static int ntfs_device_freebsd_io_ioctl(struct ntfs_device *dev, int request,
void *argp)
{
return ioctl(DEV_FD(dev)->fd, request, argp);
}
/**
* Device operations for working with unix style devices and files.
*/
struct ntfs_device_operations ntfs_device_unix_io_ops = {
.open = ntfs_device_freebsd_io_open,
.close = ntfs_device_freebsd_io_close,
.seek = ntfs_device_freebsd_io_seek,
.read = ntfs_device_freebsd_io_read,
.write = ntfs_device_freebsd_io_write,
.sync = ntfs_device_freebsd_io_sync,
.stat = ntfs_device_freebsd_io_stat,
.ioctl = ntfs_device_freebsd_io_ioctl,
};

View File

@ -162,7 +162,8 @@ static GnomeVFSResult libntfs_gnomevfs_uri_parent_init(
return GNOME_VFS_ERROR_INVALID_URI;
}
if (!(volume = ntfs_mount(uri->parent->text, MS_RDONLY))) {
if (!(volume = ntfs_mount(uri->parent->text,
NTFS_MNT_RDONLY))) {
g_free(uri_parent_string);
return GNOME_VFS_ERROR_WRONG_FORMAT;
}
@ -213,7 +214,7 @@ static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,
*pathname_next != G_DIR_SEPARATOR; pathname_next++) ;
if (*pathname_next) {
/* terminate current path element */
*pathname_next++ = '\0';
*pathname_next++ = 0;
}
while (*pathname_next == G_DIR_SEPARATOR)
pathname_next++;
@ -223,7 +224,8 @@ static GnomeVFSResult inode_open_by_pathname(ntfs_inode **inode_return,
libntfs_newn(pathname_parse_ucs2,
strlen(pathname_parse_unescaped) + 1);
for (i = 0; pathname_parse_unescaped[i]; i++)
pathname_parse_ucs2[i] = pathname_parse_unescaped[i];
pathname_parse_ucs2[i] = cpu_to_le16(
pathname_parse_unescaped[i]);
pathname_parse_ucs2[i] = 0;
g_free(pathname_parse_unescaped);
G_LOCK(libntfs);
@ -325,7 +327,8 @@ static gchar *libntfs_ntfscharo_utf8(const ntfschar *name, const int name_len)
gstring = g_string_sized_new(name_len);
for (i = 0; i < name_len; i++)
gstring = g_string_append_unichar(gstring, name[i]);
gstring = g_string_append_unichar(gstring,
le16_to_cpu(name[i]));
return g_string_free(gstring, /* returns utf8-formatted string */
FALSE); /* free_segment */
}
@ -346,8 +349,8 @@ static int libntfs_gnomevfs_read_directory_filldir(
g_return_val_if_fail(name_len >= 0, -1);
g_return_val_if_fail(pos >= 0, -1);
/* system directory; FIXME: What is its proper identification? */
if (name_len > 0 && name[0] == '$')
/* system directory */
if (MREF(mref) != FILE_root && MREF(mref) < FILE_first_user)
return 0; /* continue traversal */
file_info = gnome_vfs_file_info_new();

View File

@ -28,9 +28,6 @@
#include <glib/gmessages.h>
#include <glib/gutils.h> /* for g_atexit() */
/* Filesystem-module-scope lock for _any_ libntfs access. */
G_LOCK_DEFINE(libntfs);
static void vfs_module_shutdown_atexit(void);
/**

View File

@ -0,0 +1,34 @@
.\" Copyright (c) 2007 Yura Pakhuchiy
.\" This file may be copied under the terms of the GNU Public License.
.TH LIBNTFS 8 "September 2007" "ntfsprogs @VERSION@"
.SH NAME
libntfs \- library for accessing and managing NTFS volumes
.SH OVERVIEW
\fBlibntfs\fR is GPL licensed library for accessing and managing NTFS volumes.
It is used by\fB ntfsprogs\fR and some other projects.
.SH ACCESSING ENCRYPTED FILES
Programs that uses\fB libntfs\fR can transparently access encrypted files on
NTFS volumes if\fB libntfs\fR was compiled with \fB--enable-crypto\fR option
(it depends on\fB libgcrypt\fR,\fB GNU TLS\fR and \fBlibconfig\fR) and user
wrote configuration file. Configuration file should be placed in
\fB/etc/libntfs/config\fR or \fB$(HOME)/.libntfs/config\fR and contain list
of .PFX key files (see ntfsprogs-<version>/libntfs/config in ntfsprogs source
tarball for sample configuration file). Key files can be created/exported
using\fB cipher\fR tool under windows.
.SH AUTHORS
\fBlibntfs\fR was written by Anton Altaparmakov, Richard Russon, Szabolcs Szakacsits, Yuval Fledel and Yura Pakhuchiy.
.SH AVAILABILITY
The \fBntfsprogs\fR can be downloaded from:
.br
.nh
http://www.linux\-ntfs.org/content/view/19/37
.hy
.sp
These manual pages can be viewed online at:
.br
.nh
http://man.linux-ntfs.org/
.hy
.SH SEE ALSO
.BR ntfsprogs (8),
.BR libntfs\-gnomevfs (8)

63
libntfs/misc.c 100644
View File

@ -0,0 +1,63 @@
/**
* 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 "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;
}

View File

@ -1,215 +0,0 @@
/**
* rich.c - Temporary junk file. Part of the Linux-NTFS project.
*
* 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 NTFS_RICH
#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_ERRNO_H
#include <errno.h>
#endif
#include "rich.h"
#include "layout.h"
#include "logging.h"
/**
* find_attribute - Find an attribute of the given type
* @type: An attribute type, e.g. AT_FILE_NAME
* @ctx: A search context, created using ntfs_get_attr_search_ctx
*
* Using the search context to keep track, find the first/next occurrence of a
* given attribute type.
*
* N.B. This will return a pointer into @mft. As long as the search context
* has been created without an inode, it won't overflow the buffer.
*
* Return: Pointer Success, an attribute was found
* NULL Error, no matching attributes were found
*/
ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
{
if (!ctx) {
errno = EINVAL;
return NULL;
}
ntfs_log_trace ("\n");
if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) {
ntfs_log_debug("find_attribute didn't find an attribute of type: 0x%02x.\n", type);
return NULL; /* None / no more of that type */
}
ntfs_log_debug("find_attribute found an attribute of type: 0x%02x.\n", type);
return ctx->attr;
}
/**
* find_first_attribute - Find the first attribute of a given type
* @type: An attribute type, e.g. AT_FILE_NAME
* @mft: A buffer containing a raw MFT record
*
* Search through a raw MFT record for an attribute of a given type.
* The return value is a pointer into the MFT record that was supplied.
*
* N.B. This will return a pointer into @mft. The pointer won't stray outside
* the buffer, since we created the search context without an inode.
*
* Return: Pointer Success, an attribute was found
* NULL Error, no matching attributes were found
*/
ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
{
ntfs_attr_search_ctx *ctx;
ATTR_RECORD *rec;
if (!mft) {
errno = EINVAL;
return NULL;
}
ntfs_log_trace ("\n");
ctx = ntfs_attr_get_search_ctx(NULL, mft);
if (!ctx) {
//XXX ntfs_log_error("Couldn't create a search context.\n");
return NULL;
}
rec = find_attribute(type, ctx);
ntfs_attr_put_search_ctx(ctx);
if (rec)
ntfs_log_debug("find_first_attribute: found attr of type 0x%02x.\n", type);
else
ntfs_log_debug("find_first_attribute: didn't find attr of type 0x%02x.\n", type);
return rec;
}
/**
* ntfs_name_print - Send a Unicode name to the debug log
* @name:
* @name_len:
*
* Description...
*
* Returns:
*/
void ntfs_name_print(ntfschar *name, int name_len)
{
char *buffer = NULL;
if (name_len) {
ntfs_ucstombs(name, name_len, &buffer, 0);
ntfs_log_debug("%s", buffer);
free(buffer);
} else {
ntfs_log_debug("!");
}
}
/**
* utils_free_non_residents3 - Free all the non-resident attributes of an inode
* @bmp:
* @inode:
* @attr:
*
* Description...
*
* Returns:
*/
int utils_free_non_residents3(struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_RECORD *attr)
{
ntfs_attr *na;
runlist_element *rl;
LCN size;
LCN count;
if (!bmp)
return 1;
if (!inode)
return 1;
if (!attr)
return 1;
if (!attr->non_resident)
return 0;
ntfs_log_trace ("\n");
na = ntfs_attr_open(inode, attr->type, NULL, 0);
if (!na)
return 1;
ntfs_attr_map_whole_runlist(na);
rl = na->rl;
size = na->allocated_size >> inode->vol->cluster_size_bits;
for (count = 0; count < size; count += rl->length, rl++) {
if (ntfs_bmp_set_range(bmp, rl->lcn, rl->length, 0) < 0) {
ntfs_log_warning("set range : %lld - %lld FAILED\n", rl->lcn, rl->lcn+rl->length-1);
}
}
ntfs_attr_close(na);
return 0;
}
/**
* utils_free_non_residents2 - Find all the non-resident attributes of an inode
* @inode:
* @bmp:
*
* Description...
*
* Returns:
*/
int utils_free_non_residents2(ntfs_inode *inode, struct ntfs_bmp *bmp)
{
ntfs_attr_search_ctx *ctx;
if (!inode)
return -1;
if (!bmp)
return -1;
ntfs_log_trace ("\n");
ctx = ntfs_attr_get_search_ctx(NULL, inode->mrec);
if (!ctx) {
ntfs_log_info("can't create a search context\n");
return -1;
}
while (ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx) == 0) {
utils_free_non_residents3(bmp, inode, ctx->attr);
}
ntfs_attr_put_search_ctx(ctx);
return 0;
}
#endif /* NTFS_RICH */

File diff suppressed because it is too large Load Diff

View File

@ -37,16 +37,15 @@ This package contains the NTFS GNOME virtual filesystem (VFS) module which
allows GNOME VFS clients to seamlessly utilize the NTFS library (libntfs).
%package fuse
%package -n ntfsmount
Summary : NTFS FUSE module (ntfsmount)
Group : System Environment/Base
Requires : ntfsprogs = %{ver}-%{rel}
Requires : fuse >= 2.3.0
%description fuse
This package contains the ntfsmount utility which is an NTFS filesystem in
userspace (FUSE) module allowing users to mount an ntfs filesystem from
userspace and accessing it using the functionality provided by the NTFS
library (libntfs).
Requires : fuse >= 2.6.1
%description -n ntfsmount
This package contains the ntfsmount utility which is an userspace read/write
NTFS driver allowing users to mount an ntfs filesystem using FUSE and accessing
it using the functionality provided by the NTFS library (libntfs).
%package devel
@ -101,7 +100,7 @@ rm -rf "$RPM_BUILD_ROOT"
%{_libdir}/gnome-vfs-2.0/modules/libntfs-gnomevfs.*so*
%config %{_sysconfdir}/gnome-vfs-2.0/modules/libntfs.conf
%files fuse
%files -n ntfsmount
%defattr(-,root,root)
%{bindir}/ntfsmount*
/sbin/mount.ntfs-fuse
@ -115,6 +114,9 @@ rm -rf "$RPM_BUILD_ROOT"
%{_libdir}/gnome-vfs-2.0/modules/libntfs-gnomevfs.*a*
%changelog
* Mon Sep 10 2007 Yura Pakhuchiy <pakhuchiy@gmail.com>
- Rename rpm ntfsprogs-fuse to ntfsmount.
* Fri Oct 7 2005 Anton Altaparmakov <aia21@cantab.net>
- Fix the file distribution after new binaries have been added as they were
ending up in the wrong rpms.

View File

@ -4,6 +4,7 @@ Makefile
Makefile.in
mkntfs
ntfscat
ntfsck
ntfsclone
ntfscluster
ntfscmp

View File

@ -16,7 +16,7 @@ bin_PROGRAMS = ntfsfix ntfsinfo ntfscluster ntfsls ntfscat ntfscmp
sbin_PROGRAMS = mkntfs ntfslabel ntfsundelete ntfsresize ntfsclone \
ntfscp
EXTRA_PROGRAMS = ntfsdump_logfile ntfswipe ntfstruncate ntfsmove \
ntfsmftalloc
ntfsmftalloc ntfsck
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
@ -34,10 +34,6 @@ if ENABLE_CRYPTO
EXTRA_PROGRAMS += ntfsdecrypt
endif
if ENABLE_RICH
EXTRA_PROGRAMS += ntfsrm
endif
# Set the include path.
AM_CPPFLAGS = -I$(top_srcdir)/include/ntfs $(all_includes)
@ -45,8 +41,9 @@ ntfsfix_SOURCES = ntfsfix.c utils.c utils.h
ntfsfix_LDADD = $(AM_LIBS)
ntfsfix_LDFLAGS = $(AM_LFLAGS)
mkntfs_SOURCES = attrdef.c attrdef.h upcase.c upcase.h boot.c boot.h sd.c sd.h mkntfs.c utils.c utils.h
mkntfs_LDADD = $(AM_LIBS)
mkntfs_CPPFLAGS = $(AM_CPPFLAGS) $(MKNTFS_CPPFLAGS)
mkntfs_SOURCES = attrdef.c attrdef.h boot.c boot.h sd.c sd.h mkntfs.c utils.c utils.h
mkntfs_LDADD = $(AM_LIBS) $(MKNTFS_LIBS)
mkntfs_LDFLAGS = $(AM_LFLAGS)
ntfslabel_SOURCES = ntfslabel.c utils.c utils.h
@ -85,18 +82,16 @@ ntfscp_SOURCES = ntfscp.c utils.c utils.h
ntfscp_LDADD = $(AM_LIBS)
ntfscp_LDFLAGS = $(AM_LFLAGS)
ntfsck_SOURCES = ntfsck.c utils.c utils.h
ntfsck_LDADD = $(AM_LIBS)
ntfsck_LDFLAGS = $(AM_LFLAGS)
ntfscmp_SOURCES = ntfscmp.c utils.c utils.h
ntfscmp_LDADD = $(AM_LIBS)
ntfscmp_LDFLAGS = $(AM_LFLAGS)
# We don't distribute these
if ENABLE_RICH
ntfsrm_SOURCES = ntfsrm.c ntfsrm.h utils.c utils.h
ntfsrm_LDADD = $(AM_LIBS)
ntfsrm_LDFLAGS = $(AM_LFLAGS)
endif
ntfstruncate_SOURCES = attrdef.c ntfstruncate.c utils.c utils.h
ntfstruncate_LDADD = $(AM_LIBS)
ntfstruncate_LDFLAGS = $(AM_LFLAGS)
@ -120,7 +115,8 @@ ntfsdump_logfile_LDFLAGS= $(AM_LFLAGS)
if ENABLE_CRYPTO
ntfsdecrypt_SOURCES = ntfsdecrypt.c utils.c utils.h
ntfsdecrypt_LDADD = $(AM_LIBS)
ntfsdecrypt_LDFLAGS = $(AM_LFLAGS) -lgcrypt -lgnutls
ntfsdecrypt_LDFLAGS = $(AM_LFLAGS) `libgnutls-config --libs`
ntfsdecrypt_CFLAGS = `libgnutls-config --cflags`
endif
# Extra targets

View File

@ -1,158 +1,4 @@
/**
* attrdef_ntfs12_array
*/
const unsigned char attrdef_ntfs12_array[2400] = {
36, 0, 83, 0, 84, 0, 65, 0, 78, 0, 68, 0, 65, 0, 82, 0,
68, 0, 95, 0, 73, 0, 78, 0, 70, 0, 79, 0, 82, 0, 77, 0,
65, 0, 84, 0, 73, 0, 79, 0, 78, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
48, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0,
36, 0, 65, 0, 84, 0, 84, 0, 82, 0, 73, 0, 66, 0, 85, 0,
84, 0, 69, 0, 95, 0, 76, 0, 73, 0, 83, 0, 84, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 70, 0, 73, 0, 76, 0, 69, 0, 95, 0, 78, 0, 65, 0,
77, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0,
68, 0, 0, 0, 0, 0, 0, 0, 66, 2, 0, 0, 0, 0, 0, 0,
36, 0, 86, 0, 79, 0, 76, 0, 85, 0, 77, 0, 69, 0, 95, 0,
86, 0, 69, 0, 82, 0, 83, 0, 73, 0, 79, 0, 78, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
36, 0, 83, 0, 69, 0, 67, 0, 85, 0, 82, 0, 73, 0, 84, 0,
89, 0, 95, 0, 68, 0, 69, 0, 83, 0, 67, 0, 82, 0, 73, 0,
80, 0, 84, 0, 79, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 86, 0, 79, 0, 76, 0, 85, 0, 77, 0, 69, 0, 95, 0,
78, 0, 65, 0, 77, 0, 69, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
36, 0, 86, 0, 79, 0, 76, 0, 85, 0, 77, 0, 69, 0, 95, 0,
73, 0, 78, 0, 70, 0, 79, 0, 82, 0, 77, 0, 65, 0, 84, 0,
73, 0, 79, 0, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
12, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0,
36, 0, 68, 0, 65, 0, 84, 0, 65, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 73, 0, 78, 0, 68, 0, 69, 0, 88, 0, 95, 0, 82, 0,
79, 0, 79, 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
144, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 73, 0, 78, 0, 68, 0, 69, 0, 88, 0, 95, 0, 65, 0,
76, 0, 76, 0, 79, 0, 67, 0, 65, 0, 84, 0, 73, 0, 79, 0,
78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 66, 0, 73, 0, 84, 0, 77, 0, 65, 0, 80, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
176, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 83, 0, 89, 0, 77, 0, 66, 0, 79, 0, 76, 0, 73, 0,
67, 0, 95, 0, 76, 0, 73, 0, 78, 0, 75, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255,
36, 0, 69, 0, 65, 0, 95, 0, 73, 0, 78, 0, 70, 0, 79, 0,
82, 0, 77, 0, 65, 0, 84, 0, 73, 0, 79, 0, 78, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
208, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
36, 0, 69, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
224, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#include "attrdef.h"
/**
* attrdef_ntfs3x_array

View File

@ -1,7 +1,6 @@
#ifndef _NTFS_ATTRDEF_H_
#define _NTFS_ATTRDEF_H_
extern const unsigned char attrdef_ntfs12_array[2400];
extern const unsigned char attrdef_ntfs3x_array[2560];
#endif /* _NTFS_ATTRDEF_H_ */

View File

@ -1,222 +1,268 @@
/**
* boot_array - the first 3429 bytes of $Boot
* The first 3429 bytes of $Boot. The rest is just zero. Total 8192 bytes.
*/
const unsigned char boot_array[3429] = {
235, 91, 144, 78, 84, 70, 83, 32, 32, 32, 32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 250, 51, 192,
142, 208, 188, 0, 124, 251, 184, 192, 7, 142, 216, 199, 6, 84, 0, 0,
0, 199, 6, 86, 0, 0, 0, 199, 6, 91, 0, 16, 0, 184, 0, 13,
142, 192, 43, 219, 232, 7, 0, 104, 0, 13, 104, 102, 2, 203, 80, 83,
81, 82, 6, 102, 161, 84, 0, 102, 3, 6, 28, 0, 102, 51, 210, 102,
15, 183, 14, 24, 0, 102, 247, 241, 254, 194, 136, 22, 90, 0, 102, 139,
208, 102, 193, 234, 16, 247, 54, 26, 0, 136, 22, 37, 0, 163, 88, 0,
161, 24, 0, 42, 6, 90, 0, 64, 59, 6, 91, 0, 118, 3, 161, 91,
0, 80, 180, 2, 139, 22, 88, 0, 177, 6, 210, 230, 10, 54, 90, 0,
139, 202, 134, 233, 138, 54, 37, 0, 178, 128, 205, 19, 88, 114, 42, 1,
6, 84, 0, 131, 22, 86, 0, 0, 41, 6, 91, 0, 118, 11, 193, 224,
5, 140, 194, 3, 208, 142, 194, 235, 138, 7, 90, 89, 91, 88, 195, 190,
89, 1, 235, 8, 190, 227, 1, 235, 3, 190, 57, 1, 232, 9, 0, 190,
173, 1, 232, 3, 0, 251, 235, 254, 172, 60, 0, 116, 9, 180, 14, 187,
7, 0, 205, 16, 235, 242, 195, 29, 0, 65, 32, 100, 105, 115, 107, 32,
114, 101, 97, 100, 32, 101, 114, 114, 111, 114, 32, 111, 99, 99, 117, 114,
114, 101, 100, 46, 13, 10, 0, 41, 0, 65, 32, 107, 101, 114, 110, 101,
108, 32, 102, 105, 108, 101, 32, 105, 115, 32, 109, 105, 115, 115, 105, 110,
103, 32, 102, 114, 111, 109, 32, 116, 104, 101, 32, 100, 105, 115, 107, 46,
13, 10, 0, 37, 0, 65, 32, 107, 101, 114, 110, 101, 108, 32, 102, 105,
108, 101, 32, 105, 115, 32, 116, 111, 111, 32, 100, 105, 115, 99, 111, 110,
116, 105, 103, 117, 111, 117, 115, 46, 13, 10, 0, 51, 0, 73, 110, 115,
101, 114, 116, 32, 97, 32, 115, 121, 115, 116, 101, 109, 32, 100, 105, 115,
107, 101, 116, 116, 101, 32, 97, 110, 100, 32, 114, 101, 115, 116, 97, 114,
116, 13, 10, 116, 104, 101, 32, 115, 121, 115, 116, 101, 109, 46, 13, 10,
0, 23, 0, 92, 78, 84, 76, 68, 82, 32, 105, 115, 32, 99, 111, 109,
112, 114, 101, 115, 115, 101, 100, 46, 13, 10, 0, 0, 0, 0, 85, 170,
5, 0, 78, 0, 84, 0, 76, 0, 68, 0, 82, 0, 4, 0, 36, 0,
73, 0, 51, 0, 48, 0, 0, 224, 0, 0, 0, 48, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 140, 200, 142, 216, 193, 224, 4, 250, 139, 224,
251, 102, 15, 183, 6, 11, 0, 102, 15, 182, 30, 13, 0, 102, 247, 227,
102, 163, 78, 2, 102, 139, 14, 64, 0, 128, 249, 0, 15, 143, 14, 0,
246, 217, 102, 184, 1, 0, 0, 0, 102, 211, 224, 235, 8, 144, 102, 161,
78, 2, 102, 247, 225, 102, 163, 82, 2, 102, 15, 183, 30, 11, 0, 102,
51, 210, 102, 247, 243, 102, 163, 86, 2, 232, 44, 4, 102, 139, 14, 74,
2, 102, 137, 14, 34, 2, 102, 3, 14, 82, 2, 102, 137, 14, 38, 2,
102, 3, 14, 82, 2, 102, 137, 14, 42, 2, 102, 3, 14, 82, 2, 102,
137, 14, 58, 2, 102, 3, 14, 82, 2, 102, 137, 14, 66, 2, 102, 184,
144, 0, 0, 0, 102, 139, 14, 34, 2, 232, 65, 9, 102, 11, 192, 15,
132, 22, 254, 102, 163, 46, 2, 102, 184, 160, 0, 0, 0, 102, 139, 14,
38, 2, 232, 40, 9, 102, 163, 50, 2, 102, 184, 176, 0, 0, 0, 102,
139, 14, 42, 2, 232, 22, 9, 102, 163, 54, 2, 102, 161, 46, 2, 102,
11, 192, 15, 132, 227, 253, 103, 128, 120, 8, 0, 15, 133, 218, 253, 103,
102, 141, 80, 16, 103, 3, 66, 4, 103, 102, 15, 182, 72, 12, 102, 137,
14, 94, 2, 103, 102, 139, 72, 8, 102, 137, 14, 90, 2, 102, 161, 90,
2, 102, 15, 183, 14, 11, 0, 102, 51, 210, 102, 247, 241, 102, 163, 98,
2, 102, 161, 66, 2, 102, 3, 6, 90, 2, 102, 163, 70, 2, 102, 131,
62, 50, 2, 0, 15, 132, 25, 0, 102, 131, 62, 54, 2, 0, 15, 132,
135, 253, 102, 139, 30, 54, 2, 30, 7, 102, 139, 62, 70, 2, 232, 177,
1, 102, 15, 183, 14, 0, 2, 102, 184, 2, 2, 0, 0, 232, 153, 6,
102, 11, 192, 15, 132, 88, 253, 103, 102, 139, 0, 30, 7, 102, 139, 62,
58, 2, 232, 209, 4, 102, 161, 58, 2, 102, 187, 128, 0, 0, 0, 102,
185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 203, 0, 102, 11,
192, 15, 132, 42, 253, 103, 102, 15, 183, 88, 12, 102, 129, 227, 255, 0,
0, 0, 15, 133, 30, 253, 102, 139, 216, 104, 0, 32, 7, 102, 43, 255,
232, 79, 1, 138, 22, 36, 0, 184, 232, 3, 142, 192, 141, 54, 11, 0,
43, 192, 104, 0, 32, 80, 203, 80, 83, 81, 82, 6, 255, 54, 91, 0,
255, 54, 84, 0, 255, 54, 86, 0, 139, 195, 193, 232, 4, 140, 193, 3,
193, 37, 255, 15, 45, 0, 16, 247, 216, 139, 14, 91, 0, 193, 225, 5,
81, 59, 193, 118, 2, 139, 193, 80, 193, 232, 5, 163, 91, 0, 232, 61,
252, 88, 89, 43, 200, 118, 11, 140, 194, 3, 208, 142, 194, 184, 0, 16,
235, 222, 143, 6, 86, 0, 143, 6, 84, 0, 143, 6, 91, 0, 7, 90,
89, 91, 88, 195, 6, 30, 102, 96, 102, 139, 218, 102, 15, 182, 14, 13,
0, 102, 247, 225, 102, 163, 84, 0, 102, 139, 195, 102, 247, 225, 163, 91,
0, 139, 223, 131, 227, 15, 140, 192, 102, 193, 239, 4, 3, 199, 80, 7,
232, 116, 255, 102, 97, 144, 31, 7, 195, 103, 3, 64, 20, 103, 102, 131,
56, 255, 15, 132, 76, 0, 103, 102, 57, 24, 15, 133, 51, 0, 102, 11,
201, 15, 133, 10, 0, 103, 128, 120, 9, 0, 15, 133, 35, 0, 195, 103,
58, 72, 9, 15, 133, 26, 0, 102, 139, 240, 103, 3, 112, 10, 232, 61,
5, 102, 81, 30, 7, 102, 139, 250, 243, 167, 102, 89, 15, 133, 1, 0,
195, 103, 102, 131, 120, 4, 0, 15, 132, 7, 0, 103, 102, 3, 64, 4,
235, 171, 102, 43, 192, 195, 102, 139, 243, 232, 18, 5, 103, 102, 3, 0,
103, 247, 64, 12, 2, 0, 15, 133, 52, 0, 103, 102, 141, 80, 16, 103,
58, 74, 64, 15, 133, 24, 0, 103, 102, 141, 114, 66, 232, 239, 4, 102,
81, 30, 7, 102, 139, 251, 243, 167, 102, 89, 15, 133, 1, 0, 195, 103,
131, 120, 8, 0, 15, 132, 6, 0, 103, 3, 64, 8, 235, 194, 102, 51,
192, 195, 103, 128, 123, 8, 0, 15, 133, 28, 0, 6, 30, 102, 96, 103,
102, 141, 83, 16, 103, 102, 139, 10, 102, 139, 243, 103, 3, 114, 4, 243,
164, 102, 97, 144, 31, 7, 195, 103, 102, 141, 83, 16, 103, 102, 139, 74,
8, 102, 65, 102, 43, 192, 232, 1, 0, 195, 6, 30, 102, 96, 103, 128,
123, 8, 1, 15, 132, 3, 0, 233, 127, 251, 102, 131, 249, 0, 15, 133,
6, 0, 102, 97, 144, 31, 7, 195, 102, 83, 102, 80, 102, 81, 102, 87,
6, 232, 87, 3, 102, 139, 209, 7, 102, 95, 102, 89, 102, 59, 202, 15,
141, 3, 0, 102, 139, 209, 232, 171, 254, 102, 43, 202, 102, 139, 218, 102,
139, 194, 102, 15, 182, 22, 13, 0, 102, 247, 226, 102, 15, 183, 22, 11,
0, 102, 247, 226, 102, 3, 248, 102, 88, 102, 3, 195, 102, 91, 235, 170,
6, 30, 102, 96, 103, 128, 123, 8, 1, 15, 132, 3, 0, 233, 25, 251,
102, 131, 249, 0, 15, 133, 6, 0, 102, 97, 144, 31, 7, 195, 102, 83,
102, 80, 102, 81, 102, 87, 6, 102, 81, 102, 51, 210, 102, 15, 182, 14,
13, 0, 102, 247, 241, 102, 82, 232, 225, 2, 102, 15, 182, 30, 13, 0,
102, 247, 227, 102, 90, 102, 3, 194, 102, 80, 102, 15, 182, 6, 13, 0,
102, 247, 225, 102, 139, 208, 102, 88, 102, 89, 7, 102, 95, 102, 89, 102,
59, 202, 15, 141, 3, 0, 102, 139, 209, 102, 163, 84, 0, 137, 22, 91,
0, 6, 30, 102, 96, 139, 223, 131, 227, 15, 140, 192, 102, 193, 239, 4,
3, 199, 80, 7, 232, 160, 253, 102, 97, 144, 31, 7, 102, 43, 202, 102,
139, 218, 102, 139, 194, 102, 15, 183, 22, 11, 0, 102, 247, 226, 102, 3,
248, 102, 88, 102, 3, 195, 102, 91, 233, 101, 255, 6, 30, 102, 96, 38,
103, 102, 15, 183, 95, 4, 38, 103, 102, 15, 183, 79, 6, 102, 11, 201,
15, 132, 101, 250, 102, 3, 223, 102, 131, 195, 2, 102, 129, 199, 254, 1,
0, 0, 102, 73, 102, 11, 201, 15, 132, 23, 0, 38, 103, 139, 3, 38,
103, 137, 7, 102, 131, 195, 2, 102, 129, 199, 0, 2, 0, 0, 102, 73,
235, 226, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 184, 1, 0,
0, 0, 102, 163, 30, 2, 102, 161, 26, 2, 102, 3, 6, 82, 2, 102,
163, 74, 2, 102, 161, 48, 0, 102, 15, 182, 30, 13, 0, 102, 247, 227,
102, 163, 84, 0, 102, 161, 86, 2, 163, 91, 0, 102, 139, 30, 26, 2,
30, 7, 232, 242, 252, 102, 15, 183, 251, 232, 111, 255, 102, 161, 26, 2,
102, 187, 32, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0,
0, 0, 232, 100, 253, 102, 11, 192, 15, 132, 87, 0, 102, 139, 216, 30,
7, 102, 139, 62, 22, 2, 232, 249, 253, 102, 139, 30, 22, 2, 103, 102,
129, 59, 128, 0, 0, 0, 15, 132, 6, 0, 103, 3, 91, 4, 235, 238,
103, 102, 129, 59, 128, 0, 0, 0, 15, 133, 39, 0, 102, 83, 103, 102,
139, 67, 16, 102, 139, 62, 74, 2, 30, 7, 232, 9, 1, 102, 91, 102,
161, 82, 2, 102, 1, 6, 74, 2, 102, 255, 6, 30, 2, 103, 3, 91,
4, 235, 205, 102, 97, 144, 31, 7, 195, 102, 139, 208, 102, 139, 14, 30,
2, 102, 161, 26, 2, 102, 82, 102, 80, 102, 81, 102, 82, 102, 187, 128,
0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232,
215, 252, 102, 11, 192, 15, 132, 64, 249, 102, 139, 216, 102, 88, 232, 42,
1, 102, 11, 192, 15, 132, 7, 0, 102, 91, 102, 91, 102, 91, 195, 102,
89, 102, 88, 102, 90, 102, 3, 6, 82, 2, 226, 185, 102, 51, 192, 195,
6, 30, 102, 96, 102, 80, 102, 81, 102, 51, 210, 102, 15, 182, 30, 13,
0, 102, 247, 243, 102, 82, 232, 144, 255, 102, 11, 192, 15, 132, 249, 248,
102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 90, 102, 3, 194, 102, 163,
84, 0, 102, 89, 102, 15, 182, 30, 13, 0, 102, 59, 203, 15, 142, 19,
0, 137, 30, 91, 0, 102, 43, 203, 102, 88, 102, 3, 195, 102, 80, 102,
81, 235, 20, 144, 102, 88, 102, 3, 193, 102, 80, 137, 14, 91, 0, 102,
185, 0, 0, 0, 0, 102, 81, 6, 102, 87, 139, 223, 131, 227, 15, 140,
192, 102, 193, 239, 4, 3, 199, 80, 7, 232, 155, 251, 102, 95, 7, 102,
3, 62, 78, 2, 102, 89, 102, 88, 102, 131, 249, 0, 15, 143, 116, 255,
102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 247, 38, 86, 2, 102,
139, 14, 86, 2, 232, 89, 255, 232, 241, 253, 102, 97, 144, 31, 7, 195,
6, 30, 102, 96, 102, 247, 38, 98, 2, 102, 139, 30, 50, 2, 102, 139,
14, 98, 2, 30, 7, 102, 139, 62, 66, 2, 232, 35, 253, 232, 203, 253,
102, 97, 144, 31, 7, 195, 102, 80, 102, 83, 102, 81, 102, 139, 30, 70,
2, 102, 139, 200, 102, 193, 232, 3, 102, 131, 225, 7, 102, 3, 216, 102,
184, 1, 0, 0, 0, 102, 211, 224, 103, 132, 3, 15, 132, 4, 0, 248,
235, 2, 144, 249, 102, 89, 102, 91, 102, 88, 195, 103, 128, 123, 8, 1,
15, 132, 4, 0, 102, 43, 192, 195, 103, 102, 141, 115, 16, 103, 102, 139,
86, 8, 102, 59, 194, 15, 135, 11, 0, 103, 102, 139, 22, 102, 59, 194,
15, 131, 4, 0, 102, 43, 192, 195, 103, 3, 94, 16, 102, 43, 246, 103,
128, 59, 0, 15, 132, 62, 0, 232, 129, 0, 102, 3, 241, 232, 57, 0,
102, 3, 202, 102, 59, 193, 15, 140, 33, 0, 102, 139, 209, 102, 80, 103,
102, 15, 182, 11, 102, 139, 193, 102, 131, 224, 15, 102, 193, 233, 4, 102,
3, 217, 102, 3, 216, 102, 67, 102, 88, 235, 196, 102, 43, 200, 102, 43,
194, 102, 3, 198, 195, 102, 43, 192, 195, 102, 43, 201, 103, 138, 11, 128,
225, 15, 102, 131, 249, 0, 15, 133, 4, 0, 102, 43, 201, 195, 102, 83,
102, 82, 102, 3, 217, 103, 102, 15, 190, 19, 102, 73, 102, 75, 102, 131,
249, 0, 15, 132, 13, 0, 102, 193, 226, 8, 103, 138, 19, 102, 75, 102,
73, 235, 235, 102, 139, 202, 102, 90, 102, 91, 195, 102, 83, 102, 82, 102,
43, 210, 103, 138, 19, 102, 131, 226, 15, 102, 43, 201, 103, 138, 11, 192,
233, 4, 102, 131, 249, 0, 15, 133, 8, 0, 102, 43, 201, 102, 90, 102,
91, 195, 102, 3, 218, 102, 3, 217, 103, 102, 15, 190, 19, 102, 73, 102,
75, 102, 131, 249, 0, 15, 132, 13, 0, 102, 193, 226, 8, 103, 138, 19,
102, 75, 102, 73, 235, 235, 102, 139, 202, 102, 90, 102, 91, 195, 102, 11,
201, 15, 133, 1, 0, 195, 102, 81, 102, 86, 103, 131, 62, 97, 15, 140,
12, 0, 103, 131, 62, 122, 15, 143, 4, 0, 103, 131, 46, 32, 102, 131,
198, 2, 226, 230, 102, 94, 102, 89, 195, 102, 80, 102, 81, 102, 139, 208,
102, 161, 46, 2, 103, 102, 141, 88, 16, 103, 3, 67, 4, 103, 102, 141,
64, 16, 102, 139, 218, 232, 158, 250, 102, 11, 192, 15, 132, 5, 0, 102,
89, 102, 89, 195, 102, 161, 50, 2, 102, 11, 192, 15, 133, 8, 0, 102,
89, 102, 89, 102, 51, 192, 195, 102, 139, 22, 50, 2, 103, 102, 141, 82,
16, 103, 102, 139, 66, 8, 102, 64, 102, 139, 30, 78, 2, 102, 247, 227,
102, 51, 210, 102, 247, 54, 90, 2, 102, 80, 102, 88, 102, 11, 192, 15,
132, 48, 0, 102, 72, 102, 80, 232, 28, 254, 114, 238, 232, 241, 253, 102,
90, 102, 89, 102, 91, 102, 83, 102, 81, 102, 82, 102, 161, 66, 2, 103,
102, 141, 64, 24, 232, 47, 250, 102, 11, 192, 116, 206, 102, 89, 102, 89,
102, 89, 195, 102, 89, 102, 89, 102, 51, 192, 195, 6, 30, 102, 96, 102,
139, 54, 66, 2, 102, 185, 32, 0, 0, 0, 102, 247, 193, 3, 0, 0,
0, 15, 133, 3, 0, 232, 13, 0, 102, 173, 232, 105, 0, 226, 235, 102,
97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 51, 192, 102, 51, 219, 176,
13, 180, 14, 187, 7, 0, 205, 16, 176, 10, 180, 14, 187, 7, 0, 205,
16, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 11, 201, 15, 133,
9, 0, 232, 208, 255, 102, 97, 144, 31, 7, 195, 102, 51, 192, 102, 51,
219, 173, 180, 14, 187, 7, 0, 205, 16, 226, 240, 232, 183, 255, 102, 97,
144, 31, 7, 195, 96, 172, 60, 0, 116, 9, 180, 14, 187, 7, 0, 205,
16, 235, 242, 97, 144, 195, 6, 30, 102, 96, 102, 185, 8, 0, 0, 0,
102, 139, 208, 102, 131, 226, 15, 102, 82, 102, 193, 232, 4, 226, 241, 102,
185, 8, 0, 0, 0, 102, 88, 102, 131, 248, 9, 15, 143, 7, 0, 102,
131, 192, 48, 235, 9, 144, 102, 131, 232, 10, 102, 131, 192, 65, 102, 51,
219, 180, 14, 187, 7, 0, 205, 16, 226, 219, 176, 32, 180, 14, 187, 7,
0, 205, 16, 102, 97, 144, 31, 7, 232, 96, 0, 195, 6, 30, 102, 96,
102, 190, 22, 13, 0, 0, 232, 79, 245, 102, 97, 144, 31, 7, 195, 6,
30, 102, 96, 102, 190, 38, 13, 0, 0, 232, 60, 245, 102, 97, 144, 31,
7, 195, 6, 30, 102, 96, 102, 190, 54, 13, 0, 0, 232, 41, 245, 102,
97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 190, 70, 13, 0, 0, 232,
22, 245, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 190, 86, 13,
0, 0, 232, 3, 245, 102, 97, 144, 31, 7, 195, 102, 80, 102, 184, 0,
0, 245, 255, 102, 64, 102, 11, 192, 117, 249, 102, 88, 195, 102, 81, 102,
80, 102, 184, 5, 0, 0, 0, 30, 7, 102, 139, 249, 232, 71, 252, 102,
139, 193, 102, 91, 102, 83, 102, 15, 183, 14, 12, 2, 102, 186, 14, 2,
0, 0, 232, 68, 248, 102, 91, 102, 89, 102, 11, 192, 15, 133, 47, 0,
102, 139, 193, 102, 139, 203, 102, 80, 102, 83, 232, 35, 0, 102, 91, 102,
95, 102, 11, 192, 15, 132, 23, 0, 30, 7, 232, 9, 252, 102, 139, 199,
102, 15, 183, 14, 12, 2, 102, 186, 14, 2, 0, 0, 232, 10, 248, 195,
102, 81, 102, 187, 32, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186,
0, 0, 0, 0, 232, 242, 247, 102, 11, 192, 15, 132, 82, 0, 102, 139,
216, 30, 7, 102, 139, 62, 22, 2, 232, 135, 248, 30, 7, 102, 139, 30,
22, 2, 102, 89, 38, 102, 57, 15, 15, 132, 46, 0, 38, 102, 131, 63,
255, 15, 132, 45, 0, 38, 131, 127, 4, 0, 15, 132, 36, 0, 38, 102,
15, 183, 71, 4, 3, 216, 139, 195, 37, 0, 128, 116, 215, 140, 192, 5,
0, 8, 142, 192, 129, 227, 255, 127, 235, 202, 38, 102, 139, 71, 16, 195,
102, 89, 102, 51, 192, 195, 68, 101, 98, 117, 103, 32, 80, 111, 105, 110,
116, 32, 48, 13, 10, 0, 68, 101, 98, 117, 103, 32, 80, 111, 105, 110,
116, 32, 49, 13, 10, 0, 68, 101, 98, 117, 103, 32, 80, 111, 105, 110,
116, 32, 50, 13, 10, 0, 68, 101, 98, 117, 103, 32, 80, 111, 105, 110,
116, 32, 51, 13, 10, 0, 68, 101, 98, 117, 103, 32, 80, 111, 105, 110,
116, 32, 52, 13, 10
};
#include "boot.h"
/**
* boot_array - the first 4136 bytes of $Boot
*
* The first 4136 bytes of $Boot. The rest is just zero. Total 8192 bytes.
*/
const unsigned char boot_array[4136] = {
235, 82, 144, 78, 84, 70, 83, 32, 32, 32, 32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 250, 51, 192, 142, 208, 188, 0, 124, 251, 104, 192, 7,
31, 30, 104, 102, 0, 203, 136, 22, 14, 0, 102, 129, 62, 3, 0, 78,
84, 70, 83, 117, 21, 180, 65, 187, 170, 85, 205, 19, 114, 12, 129, 251,
85, 170, 117, 6, 247, 193, 1, 0, 117, 3, 233, 210, 0, 30, 131, 236,
24, 104, 26, 0, 180, 72, 138, 22, 14, 0, 139, 244, 22, 31, 205, 19,
159, 131, 196, 24, 158, 88, 31, 114, 225, 59, 6, 11, 0, 117, 219, 163,
15, 0, 193, 46, 15, 0, 4, 30, 90, 51, 219, 185, 0, 32, 43, 200,
102, 255, 6, 17, 0, 3, 22, 15, 0, 142, 194, 255, 6, 22, 0, 232,
64, 0, 43, 200, 119, 239, 184, 0, 187, 205, 26, 102, 35, 192, 117, 45,
102, 129, 251, 84, 67, 80, 65, 117, 36, 129, 249, 2, 1, 114, 30, 22,
104, 7, 187, 22, 104, 112, 14, 22, 104, 9, 0, 102, 83, 102, 83, 102,
85, 22, 22, 22, 104, 184, 1, 102, 97, 14, 7, 205, 26, 233, 106, 1,
144, 144, 102, 96, 30, 6, 102, 161, 17, 0, 102, 3, 6, 28, 0, 30,
102, 104, 0, 0, 0, 0, 102, 80, 6, 83, 104, 1, 0, 104, 16, 0,
180, 66, 138, 22, 14, 0, 22, 31, 139, 244, 205, 19, 102, 89, 91, 90,
102, 89, 102, 89, 31, 15, 130, 22, 0, 102, 255, 6, 17, 0, 3, 22,
15, 0, 142, 194, 255, 14, 22, 0, 117, 188, 7, 31, 102, 97, 195, 160,
248, 1, 232, 8, 0, 160, 251, 1, 232, 2, 0, 235, 254, 180, 1, 139,
240, 172, 60, 0, 116, 9, 180, 14, 187, 7, 0, 205, 16, 235, 242, 195,
13, 10, 65, 32, 100, 105, 115, 107, 32, 114, 101, 97, 100, 32, 101, 114,
114, 111, 114, 32, 111, 99, 99, 117, 114, 114, 101, 100, 0, 13, 10, 66,
79, 79, 84, 77, 71, 82, 32, 105, 115, 32, 109, 105, 115, 115, 105, 110,
103, 0, 13, 10, 66, 79, 79, 84, 77, 71, 82, 32, 105, 115, 32, 99,
111, 109, 112, 114, 101, 115, 115, 101, 100, 0, 13, 10, 80, 114, 101, 115,
115, 32, 67, 116, 114, 108, 43, 65, 108, 116, 43, 68, 101, 108, 32, 116,
111, 32, 114, 101, 115, 116, 97, 114, 116, 13, 10, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 128, 157, 178, 202, 0, 0, 85, 170,
7, 0, 66, 0, 79, 0, 79, 0, 84, 0, 77, 0, 71, 0, 82, 0,
4, 0, 36, 0, 73, 0, 51, 0, 48, 0, 0, 224, 0, 0, 0, 48,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 235, 34, 144, 144, 5, 0, 78, 0, 84, 0,
76, 0, 68, 0, 82, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 15, 183, 6, 11, 0,
102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 163, 82, 2, 102, 139, 14,
64, 0, 128, 249, 0, 15, 143, 14, 0, 246, 217, 102, 184, 1, 0, 0,
0, 102, 211, 224, 235, 8, 144, 102, 161, 82, 2, 102, 247, 225, 102, 163,
102, 2, 102, 15, 183, 30, 11, 0, 102, 51, 210, 102, 247, 243, 102, 163,
86, 2, 232, 149, 4, 102, 139, 14, 78, 2, 102, 137, 14, 38, 2, 102,
3, 14, 102, 2, 102, 137, 14, 42, 2, 102, 3, 14, 102, 2, 102, 137,
14, 46, 2, 102, 3, 14, 102, 2, 102, 137, 14, 62, 2, 102, 3, 14,
102, 2, 102, 137, 14, 70, 2, 102, 184, 144, 0, 0, 0, 102, 139, 14,
38, 2, 232, 131, 9, 102, 11, 192, 15, 132, 83, 254, 102, 163, 50, 2,
102, 184, 160, 0, 0, 0, 102, 139, 14, 42, 2, 232, 106, 9, 102, 163,
54, 2, 102, 184, 176, 0, 0, 0, 102, 139, 14, 46, 2, 232, 88, 9,
102, 163, 58, 2, 102, 161, 50, 2, 102, 11, 192, 15, 132, 32, 254, 103,
128, 120, 8, 0, 15, 133, 23, 254, 103, 102, 141, 80, 16, 103, 3, 66,
4, 103, 102, 15, 182, 72, 12, 102, 137, 14, 114, 2, 103, 102, 139, 72,
8, 102, 137, 14, 110, 2, 102, 161, 110, 2, 102, 15, 183, 14, 11, 0,
102, 51, 210, 102, 247, 241, 102, 163, 118, 2, 102, 161, 70, 2, 102, 3,
6, 110, 2, 102, 163, 74, 2, 102, 131, 62, 54, 2, 0, 15, 132, 29,
0, 102, 131, 62, 58, 2, 0, 15, 132, 196, 253, 102, 139, 30, 58, 2,
30, 7, 102, 139, 62, 74, 2, 102, 161, 46, 2, 232, 224, 1, 102, 15,
183, 14, 0, 2, 102, 184, 2, 2, 0, 0, 232, 34, 8, 102, 11, 192,
15, 133, 22, 0, 102, 15, 183, 14, 90, 2, 102, 184, 92, 2, 0, 0,
232, 12, 8, 102, 11, 192, 15, 132, 66, 12, 103, 102, 139, 0, 30, 7,
102, 139, 62, 62, 2, 232, 63, 6, 102, 161, 62, 2, 102, 187, 32, 0,
0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 228,
0, 102, 133, 192, 15, 133, 35, 0, 102, 161, 62, 2, 102, 187, 128, 0,
0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 196,
0, 102, 11, 192, 15, 133, 68, 0, 233, 241, 11, 102, 51, 210, 102, 185,
128, 0, 0, 0, 102, 161, 62, 2, 232, 202, 8, 102, 11, 192, 15, 132,
218, 11, 30, 7, 102, 139, 62, 62, 2, 232, 219, 5, 102, 161, 62, 2,
102, 187, 128, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0,
0, 0, 232, 128, 0, 102, 11, 192, 15, 132, 176, 11, 103, 102, 15, 183,
88, 12, 102, 129, 227, 255, 0, 0, 0, 15, 133, 165, 11, 102, 139, 216,
104, 0, 32, 7, 102, 43, 255, 102, 161, 62, 2, 232, 0, 1, 104, 0,
32, 7, 102, 43, 255, 102, 161, 62, 2, 232, 172, 10, 138, 22, 14, 0,
184, 232, 3, 142, 192, 141, 54, 11, 0, 43, 192, 104, 0, 32, 80, 203,
6, 30, 102, 96, 102, 139, 218, 102, 15, 182, 14, 13, 0, 102, 247, 225,
102, 163, 17, 0, 102, 139, 195, 102, 247, 225, 163, 22, 0, 139, 223, 131,
227, 15, 140, 192, 102, 193, 239, 4, 3, 199, 80, 7, 232, 51, 252, 102,
97, 144, 31, 7, 195, 103, 3, 64, 20, 103, 102, 131, 56, 255, 15, 132,
76, 0, 103, 102, 57, 24, 15, 133, 51, 0, 102, 11, 201, 15, 133, 10,
0, 103, 128, 120, 9, 0, 15, 133, 35, 0, 195, 103, 58, 72, 9, 15,
133, 26, 0, 102, 139, 240, 103, 3, 112, 10, 232, 151, 6, 102, 81, 30,
7, 102, 139, 250, 243, 167, 102, 89, 15, 133, 1, 0, 195, 103, 102, 131,
120, 4, 0, 15, 132, 7, 0, 103, 102, 3, 64, 4, 235, 171, 102, 43,
192, 195, 102, 139, 243, 232, 108, 6, 103, 102, 3, 0, 103, 247, 64, 12,
2, 0, 15, 133, 52, 0, 103, 102, 141, 80, 16, 103, 58, 74, 64, 15,
133, 24, 0, 103, 102, 141, 114, 66, 232, 73, 6, 102, 81, 30, 7, 102,
139, 251, 243, 167, 102, 89, 15, 133, 1, 0, 195, 103, 131, 120, 8, 0,
15, 132, 6, 0, 103, 3, 64, 8, 235, 194, 102, 51, 192, 195, 103, 128,
123, 8, 0, 15, 133, 28, 0, 6, 30, 102, 96, 103, 102, 141, 83, 16,
103, 102, 139, 10, 102, 139, 243, 103, 3, 114, 4, 243, 164, 102, 97, 144,
31, 7, 195, 102, 80, 103, 102, 141, 83, 16, 102, 133, 192, 15, 133, 10,
0, 103, 102, 139, 74, 8, 102, 65, 235, 17, 144, 103, 102, 139, 66, 24,
102, 51, 210, 102, 247, 54, 82, 2, 102, 139, 200, 102, 43, 192, 102, 94,
232, 1, 0, 195, 6, 30, 102, 96, 103, 128, 123, 8, 1, 15, 132, 3,
0, 233, 107, 251, 102, 131, 249, 0, 15, 133, 6, 0, 102, 97, 144, 31,
7, 195, 102, 83, 102, 80, 102, 81, 102, 86, 102, 87, 6, 232, 145, 4,
102, 139, 209, 7, 102, 95, 102, 94, 102, 89, 102, 133, 192, 15, 132, 52,
0, 102, 59, 202, 15, 141, 3, 0, 102, 139, 209, 232, 130, 254, 102, 43,
202, 102, 139, 218, 102, 139, 194, 102, 15, 182, 22, 13, 0, 102, 247, 226,
102, 15, 183, 22, 11, 0, 102, 247, 226, 102, 3, 248, 102, 88, 102, 3,
195, 102, 91, 235, 159, 102, 133, 246, 15, 132, 3, 251, 102, 81, 102, 87,
6, 103, 102, 15, 182, 67, 9, 102, 133, 192, 15, 132, 32, 0, 102, 209,
224, 102, 43, 224, 102, 139, 252, 102, 84, 102, 86, 103, 102, 15, 183, 115,
10, 102, 3, 243, 102, 139, 200, 243, 164, 102, 94, 235, 3, 144, 102, 80,
102, 80, 103, 102, 139, 3, 102, 80, 103, 102, 139, 67, 24, 102, 80, 103,
102, 139, 86, 32, 102, 133, 210, 15, 132, 11, 0, 102, 139, 254, 30, 7,
102, 139, 194, 232, 113, 3, 102, 139, 198, 102, 90, 102, 89, 102, 66, 102,
81, 102, 86, 232, 63, 6, 102, 133, 192, 15, 132, 146, 250, 102, 94, 102,
89, 102, 139, 254, 30, 7, 232, 78, 3, 102, 139, 198, 102, 139, 217, 102,
89, 102, 90, 102, 81, 102, 86, 102, 209, 233, 232, 248, 253, 102, 133, 192,
15, 132, 107, 250, 102, 94, 102, 89, 102, 3, 225, 7, 102, 95, 102, 89,
102, 139, 208, 102, 88, 102, 91, 102, 139, 218, 233, 245, 254, 6, 30, 102,
96, 38, 103, 102, 15, 183, 95, 4, 38, 103, 102, 15, 183, 79, 6, 102,
11, 201, 15, 132, 57, 250, 102, 3, 223, 102, 131, 195, 2, 102, 129, 199,
254, 1, 0, 0, 102, 73, 102, 11, 201, 15, 132, 23, 0, 38, 103, 139,
3, 38, 103, 137, 7, 102, 131, 195, 2, 102, 129, 199, 0, 2, 0, 0,
102, 73, 235, 226, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 184,
1, 0, 0, 0, 102, 163, 34, 2, 102, 161, 30, 2, 102, 3, 6, 102,
2, 102, 163, 106, 2, 102, 3, 6, 102, 2, 102, 163, 78, 2, 102, 161,
48, 0, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 139, 30, 78, 2,
102, 137, 7, 102, 163, 17, 0, 131, 195, 4, 102, 161, 86, 2, 102, 137,
7, 163, 22, 0, 131, 195, 4, 102, 137, 30, 78, 2, 102, 139, 30, 30,
2, 30, 7, 232, 92, 249, 102, 139, 251, 232, 81, 255, 102, 161, 30, 2,
102, 187, 32, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0,
0, 0, 232, 16, 253, 102, 11, 192, 15, 132, 25, 1, 102, 139, 216, 30,
7, 102, 139, 62, 26, 2, 102, 51, 192, 232, 162, 253, 102, 139, 30, 26,
2, 102, 129, 63, 128, 0, 0, 0, 15, 132, 235, 0, 3, 95, 4, 235,
240, 102, 83, 102, 139, 71, 16, 102, 247, 38, 86, 2, 102, 80, 102, 51,
210, 102, 15, 182, 30, 13, 0, 102, 247, 243, 102, 82, 232, 220, 0, 102,
11, 192, 15, 132, 57, 249, 102, 139, 14, 86, 2, 102, 15, 182, 30, 13,
0, 102, 247, 227, 102, 90, 102, 3, 194, 102, 139, 30, 78, 2, 102, 137,
7, 131, 195, 4, 102, 15, 182, 6, 13, 0, 102, 43, 194, 102, 59, 193,
15, 134, 3, 0, 102, 139, 193, 102, 137, 7, 102, 43, 200, 102, 90, 15,
132, 117, 0, 102, 3, 194, 102, 80, 102, 51, 210, 102, 15, 182, 30, 13,
0, 102, 247, 243, 102, 81, 232, 130, 0, 102, 89, 102, 11, 192, 15, 132,
221, 248, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 139, 30, 78, 2,
102, 139, 23, 131, 195, 4, 102, 3, 23, 102, 59, 208, 15, 133, 21, 0,
102, 15, 182, 6, 13, 0, 102, 59, 193, 15, 134, 3, 0, 102, 139, 193,
102, 1, 7, 235, 165, 131, 195, 4, 102, 137, 30, 78, 2, 102, 137, 7,
131, 195, 4, 102, 15, 182, 6, 13, 0, 102, 59, 193, 15, 134, 3, 0,
102, 139, 193, 102, 137, 7, 235, 130, 131, 195, 4, 102, 255, 6, 34, 2,
102, 137, 30, 78, 2, 102, 91, 3, 95, 4, 102, 129, 63, 128, 0, 0,
0, 15, 132, 12, 255, 102, 97, 144, 31, 7, 195, 102, 139, 208, 102, 139,
14, 34, 2, 102, 139, 54, 106, 2, 102, 3, 54, 102, 2, 102, 82, 102,
81, 102, 82, 102, 139, 30, 106, 2, 102, 139, 62, 86, 2, 102, 139, 4,
102, 163, 17, 0, 131, 198, 4, 102, 139, 4, 163, 22, 0, 131, 198, 4,
30, 7, 232, 221, 247, 102, 43, 248, 15, 132, 8, 0, 247, 38, 11, 0,
3, 216, 235, 217, 102, 139, 62, 106, 2, 30, 7, 232, 191, 253, 102, 161,
106, 2, 102, 187, 128, 0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 139,
209, 232, 129, 251, 102, 11, 192, 15, 132, 244, 247, 102, 139, 216, 102, 88,
102, 86, 232, 44, 1, 102, 94, 102, 11, 192, 15, 132, 5, 0, 102, 91,
102, 91, 195, 102, 89, 102, 90, 226, 132, 102, 51, 192, 195, 6, 30, 102,
96, 102, 80, 102, 81, 102, 51, 210, 102, 15, 182, 30, 13, 0, 102, 247,
243, 102, 82, 102, 87, 232, 83, 255, 102, 95, 102, 11, 192, 15, 132, 174,
247, 102, 15, 182, 30, 13, 0, 102, 247, 227, 102, 90, 102, 3, 194, 102,
163, 17, 0, 102, 89, 102, 15, 182, 30, 13, 0, 102, 59, 203, 15, 142,
19, 0, 137, 30, 22, 0, 102, 43, 203, 102, 88, 102, 3, 195, 102, 80,
102, 81, 235, 20, 144, 102, 88, 102, 3, 193, 102, 80, 137, 14, 22, 0,
102, 185, 0, 0, 0, 0, 102, 81, 6, 102, 87, 139, 223, 131, 227, 15,
140, 192, 102, 193, 239, 4, 3, 199, 80, 7, 232, 5, 247, 102, 95, 7,
102, 3, 62, 82, 2, 102, 89, 102, 88, 102, 131, 249, 0, 15, 143, 112,
255, 102, 97, 144, 31, 7, 195, 6, 30, 102, 96, 102, 247, 38, 86, 2,
102, 139, 14, 86, 2, 232, 85, 255, 232, 210, 252, 102, 97, 144, 31, 7,
195, 6, 30, 102, 96, 102, 247, 38, 114, 2, 102, 139, 30, 54, 2, 102,
139, 14, 114, 2, 102, 139, 54, 42, 2, 30, 7, 102, 139, 62, 70, 2,
232, 129, 251, 232, 167, 252, 102, 97, 144, 31, 7, 195, 102, 80, 102, 83,
102, 81, 102, 139, 30, 74, 2, 102, 139, 200, 102, 193, 232, 3, 102, 131,
225, 7, 102, 3, 216, 102, 184, 1, 0, 0, 0, 102, 211, 224, 103, 132,
3, 15, 132, 4, 0, 248, 235, 2, 144, 249, 102, 89, 102, 91, 102, 88,
195, 103, 128, 123, 8, 1, 15, 132, 4, 0, 102, 43, 192, 195, 103, 102,
141, 115, 16, 103, 102, 139, 86, 8, 102, 59, 194, 15, 135, 11, 0, 103,
102, 139, 22, 102, 59, 194, 15, 131, 4, 0, 102, 43, 192, 195, 103, 3,
94, 16, 102, 43, 246, 103, 128, 59, 0, 15, 132, 62, 0, 232, 129, 0,
102, 3, 241, 232, 57, 0, 102, 3, 202, 102, 59, 193, 15, 140, 33, 0,
102, 139, 209, 102, 80, 103, 102, 15, 182, 11, 102, 139, 193, 102, 131, 224,
15, 102, 193, 233, 4, 102, 3, 217, 102, 3, 216, 102, 67, 102, 88, 235,
196, 102, 43, 200, 102, 43, 194, 102, 3, 198, 195, 102, 43, 192, 195, 102,
43, 201, 103, 138, 11, 128, 225, 15, 102, 131, 249, 0, 15, 133, 4, 0,
102, 43, 201, 195, 102, 83, 102, 82, 102, 3, 217, 103, 102, 15, 190, 19,
102, 73, 102, 75, 102, 131, 249, 0, 15, 132, 13, 0, 102, 193, 226, 8,
103, 138, 19, 102, 75, 102, 73, 235, 235, 102, 139, 202, 102, 90, 102, 91,
195, 102, 83, 102, 82, 102, 43, 210, 103, 138, 19, 102, 131, 226, 15, 102,
43, 201, 103, 138, 11, 192, 233, 4, 102, 131, 249, 0, 15, 133, 8, 0,
102, 43, 201, 102, 90, 102, 91, 195, 102, 3, 218, 102, 3, 217, 103, 102,
15, 190, 19, 102, 73, 102, 75, 102, 131, 249, 0, 15, 132, 13, 0, 102,
193, 226, 8, 103, 138, 19, 102, 75, 102, 73, 235, 235, 102, 139, 202, 102,
90, 102, 91, 195, 102, 11, 201, 15, 133, 1, 0, 195, 102, 81, 102, 86,
103, 131, 62, 97, 15, 140, 12, 0, 103, 131, 62, 122, 15, 143, 4, 0,
103, 131, 46, 32, 102, 131, 198, 2, 226, 230, 102, 94, 102, 89, 195, 102,
80, 102, 81, 102, 139, 208, 102, 161, 50, 2, 103, 102, 141, 88, 16, 103,
3, 67, 4, 103, 102, 141, 64, 16, 102, 139, 218, 232, 68, 249, 102, 11,
192, 15, 132, 5, 0, 102, 89, 102, 89, 195, 102, 161, 54, 2, 102, 11,
192, 15, 133, 8, 0, 102, 89, 102, 89, 102, 51, 192, 195, 102, 139, 22,
54, 2, 103, 102, 141, 82, 16, 103, 102, 139, 66, 24, 102, 51, 210, 102,
247, 54, 110, 2, 102, 51, 246, 102, 80, 102, 86, 102, 88, 102, 94, 102,
59, 198, 15, 132, 58, 0, 102, 86, 102, 64, 102, 80, 102, 72, 232, 27,
254, 114, 232, 232, 235, 253, 102, 90, 102, 94, 102, 89, 102, 91, 102, 83,
102, 81, 102, 86, 102, 82, 102, 161, 70, 2, 103, 102, 141, 64, 24, 232,
208, 248, 102, 11, 192, 116, 196, 102, 89, 102, 89, 102, 89, 102, 89, 195,
102, 89, 102, 89, 102, 51, 192, 195, 102, 81, 102, 80, 102, 184, 5, 0,
0, 0, 30, 7, 102, 139, 249, 232, 141, 253, 102, 139, 193, 102, 187, 32,
0, 0, 0, 102, 185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232,
51, 248, 102, 91, 102, 89, 102, 133, 192, 15, 133, 21, 0, 102, 139, 193,
102, 15, 183, 14, 16, 2, 102, 186, 18, 2, 0, 0, 232, 22, 248, 235,
51, 144, 102, 51, 210, 102, 139, 193, 102, 139, 203, 102, 80, 102, 83, 232,
35, 0, 102, 91, 102, 95, 102, 11, 192, 15, 132, 23, 0, 30, 7, 232,
53, 253, 102, 139, 199, 102, 15, 183, 14, 16, 2, 102, 186, 18, 2, 0,
0, 232, 225, 247, 195, 102, 82, 102, 81, 102, 187, 32, 0, 0, 0, 102,
185, 0, 0, 0, 0, 102, 186, 0, 0, 0, 0, 232, 199, 247, 102, 11,
192, 15, 132, 99, 0, 102, 139, 216, 30, 7, 102, 139, 62, 26, 2, 102,
51, 192, 232, 89, 248, 30, 7, 102, 139, 30, 26, 2, 102, 89, 102, 90,
38, 102, 57, 15, 15, 133, 12, 0, 38, 102, 57, 87, 8, 15, 132, 49,
0, 235, 19, 144, 38, 102, 131, 63, 255, 15, 132, 47, 0, 38, 131, 127,
4, 0, 15, 132, 38, 0, 38, 102, 15, 183, 71, 4, 3, 216, 139, 195,
37, 0, 128, 116, 203, 140, 192, 5, 0, 8, 142, 192, 129, 227, 255, 127,
235, 190, 38, 102, 139, 71, 16, 195, 102, 89, 102, 90, 102, 51, 192, 195,
102, 80, 102, 81, 102, 139, 199, 102, 193, 232, 4, 6, 89, 3, 200, 81,
7, 102, 131, 231, 15, 102, 89, 102, 88, 195, 96, 6, 190, 189, 13, 191,
0, 32, 30, 7, 185, 13, 0, 144, 243, 165, 7, 97, 195, 1, 35, 69,
103, 137, 171, 205, 239, 254, 220, 186, 152, 118, 84, 50, 16, 240, 225, 210,
195, 0, 0, 0, 0, 32, 32, 96, 139, 54, 24, 32, 38, 138, 5, 136,
4, 71, 70, 102, 255, 6, 20, 32, 129, 254, 96, 32, 117, 6, 232, 91,
0, 190, 32, 32, 226, 230, 137, 54, 24, 32, 97, 195, 102, 96, 139, 54,
24, 32, 176, 128, 136, 4, 70, 50, 192, 129, 254, 96, 32, 117, 6, 232,
58, 0, 190, 32, 32, 129, 254, 88, 32, 117, 233, 102, 51, 192, 102, 163,
88, 32, 102, 161, 20, 32, 102, 193, 224, 3, 102, 15, 200, 102, 163, 92,
32, 232, 24, 0, 187, 0, 32, 102, 139, 7, 102, 15, 200, 102, 137, 7,
131, 195, 4, 129, 251, 52, 32, 117, 238, 102, 97, 195, 102, 96, 187, 32,
32, 102, 139, 7, 102, 15, 200, 102, 137, 7, 131, 195, 4, 129, 251, 96,
32, 117, 238, 187, 0, 32, 102, 139, 15, 102, 139, 87, 4, 102, 139, 119,
8, 102, 139, 127, 12, 102, 139, 111, 16, 187, 32, 32, 199, 6, 26, 32,
48, 15, 198, 6, 28, 32, 20, 144, 83, 139, 30, 26, 32, 255, 23, 102,
3, 71, 2, 91, 102, 3, 232, 102, 3, 47, 102, 139, 193, 102, 193, 192,
5, 102, 3, 197, 102, 139, 239, 102, 139, 254, 102, 139, 242, 102, 193, 198,
30, 102, 139, 209, 102, 139, 200, 102, 139, 7, 102, 51, 71, 8, 102, 51,
71, 32, 102, 51, 71, 52, 102, 209, 192, 102, 137, 71, 64, 131, 195, 4,
254, 14, 28, 32, 117, 178, 131, 6, 26, 32, 6, 129, 62, 26, 32, 72,
15, 117, 159, 187, 0, 32, 102, 1, 15, 102, 1, 87, 4, 102, 1, 119,
8, 102, 1, 127, 12, 102, 1, 111, 16, 102, 97, 195, 102, 139, 198, 102,
51, 199, 102, 35, 194, 102, 51, 199, 195, 102, 139, 194, 102, 51, 198, 102,
51, 199, 195, 102, 83, 102, 139, 194, 102, 35, 198, 102, 139, 218, 102, 35,
223, 102, 11, 195, 102, 139, 222, 102, 35, 223, 102, 11, 195, 102, 91, 195,
252, 14, 153, 121, 130, 90, 9, 15, 161, 235, 217, 110, 19, 15, 220, 188,
27, 143, 9, 15, 214, 193, 98, 202, 6, 30, 102, 96, 102, 51, 219, 184,
0, 187, 205, 26, 102, 35, 192, 15, 133, 187, 0, 102, 129, 251, 84, 67,
80, 65, 15, 133, 176, 0, 129, 249, 2, 1, 15, 130, 168, 0, 102, 97,
144, 31, 7, 6, 30, 102, 96, 103, 128, 123, 8, 0, 15, 133, 12, 0,
103, 102, 141, 83, 16, 103, 102, 139, 10, 235, 37, 144, 103, 102, 141, 83,
16, 103, 102, 139, 74, 40, 102, 129, 249, 0, 0, 8, 0, 15, 131, 12,
0, 103, 102, 139, 66, 44, 102, 35, 192, 15, 132, 3, 0, 102, 51, 201,
14, 31, 232, 245, 253, 102, 35, 201, 15, 132, 50, 0, 102, 186, 0, 128,
0, 0, 102, 59, 202, 15, 134, 31, 0, 102, 43, 202, 6, 102, 81, 102,
87, 102, 82, 102, 139, 202, 232, 183, 253, 232, 251, 253, 102, 90, 102, 95,
102, 89, 7, 102, 3, 250, 235, 218, 232, 165, 253, 232, 233, 253, 232, 11,
254, 14, 7, 102, 187, 84, 67, 80, 65, 102, 191, 0, 32, 0, 0, 102,
185, 20, 0, 0, 0, 102, 184, 7, 187, 0, 0, 102, 186, 10, 0, 0,
0, 102, 51, 246, 205, 26, 102, 97, 144, 31, 7, 195, 160, 249, 1, 233,
64, 241, 160, 250, 1, 233, 58, 241
};

View File

@ -1,7 +1,7 @@
#ifndef _NTFS_BOOT_H_
#define _NTFS_BOOT_H_
extern const unsigned char boot_array[3429];
extern const unsigned char boot_array[4136];
#endif /* _NTFS_BOOT_H_ */

View File

@ -45,10 +45,6 @@ mkntfs \- create an NTFS file system
.B \-n
]
[
.B \-N
.I ntfs\-version
]
[
.B \-p
.I part\-start\-sect
]
@ -123,39 +119,6 @@ Set the volume label for the filesystem.
\fB\-C\fR, \fB\-\-enable\-compression\fR
Enable compression on the volume.
.TP
\fB\-c\fR, \fB\-\-cluster\-size\fR BYTES
Specify the size of clusters in bytes. Valid cluster size values are powers of
two, with at least 256, and at most 65536 bytes per cluster. If omitted,
.B mkntfs
determines the
.I cluster\-size
from the volume size. The value is determined as follows:
.TS
box;
lB lB lB
l l r.
Volume size Default cluster size
0 \- 512MB 512 bytes
512MB \- 1GB 1024 bytes
1GB \- 2GB 2048 bytes
2GB + 4096 bytes
.TE
.sp
.sp
Note that the default cluster size is set to be at least equal to the sector
size as a cluster cannot be smaller than a sector. Also, note that values
greater than 4096 have the side effect that compression is disabled on the
volume (due to limitations in the NTFS compression algorithm currently in use
by Windows).
.TP
\fB\-N\fR, \fB\-\-ntfs\-version\fR STRING
Select the version of NTFS you wish to create. This can be "1.2"
(Windows NT 4.0) or "3.1" (Windows XP, Server 2003 and Vista).
Versions are upwards compatible and Windows 2000, which uses version "3.0",
can read/write both.
If this option is omitted then version "3.1" is used.
.TP
\fB\-n\fR, \fB\-\-no\-action\fR
Causes
.B mkntfs
@ -164,6 +127,18 @@ to create a filesystem. All steps of the format are carried out except the
actual writing to the device.
.SS Advanced options
.TP
\fB\-c\fR, \fB\-\-cluster\-size\fR BYTES
Specify the size of clusters in bytes. Valid cluster size values are powers of
two, with at least 256, and at most 65536 bytes per cluster. If omitted,
.B mkntfs
uses 4096 bytes as the default cluster size.
.sp
Note that the default cluster size is set to be at least equal to the sector
size as a cluster cannot be smaller than a sector. Also, note that values
greater than 4096 have the side effect that compression is disabled on the
volume (due to limitations in the NTFS compression algorithm currently in use
by Windows).
.TP
\fB\-s\fR, \fB\-\-sector\-size\fR BYTES
Specify the size of sectors in bytes. Valid sector size values are 256, 512,
1024, 2048 and 4096 bytes per sector. If omitted,

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,8 @@
.\" Copyright (c) 2003\-2005 Richard Russon.
.\" Copyright (c) 2007 Yura Pakhuchiy.
.\" This file may be copied under the terms of the GNU Public License.
.\"
.TH NTFSCAT 8 "November 2005" "ntfsprogs @VERSION@"
.TH NTFSCAT 8 "September 2007" "ntfsprogs @VERSION@"
.SH NAME
ntfscat \- print NTFS files and streams on the standard output
.SH SYNOPSIS
@ -133,5 +134,8 @@ The manual pages are available online at:
http://man.linux-ntfs.org/
.hy
.SH SEE ALSO
Read \fBlibntfs\fR(8) for details how to access encrypted files.
.sp
.BR libntfs (8),
.BR ntfsls (8),
.BR ntfsprogs (8)

View File

@ -4,6 +4,7 @@
* Copyright (c) 2003-2005 Richard Russon
* Copyright (c) 2003-2005 Anton Altaparmakov
* Copyright (c) 2003-2005 Szabolcs Szakacsits
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility will concatenate files and print on the standard output.
*
@ -60,11 +61,12 @@ static struct options opts;
*/
static void version(void)
{
ntfs_log_info("\n%s v%s (libntfs-3g) - Concatenate files and print on the "
"standard output.\n\n", EXEC_NAME, VERSION);
ntfs_log_info("\n%s v%s (libntfs-3g) - Concatenate files and print "
"on the standard output.\n\n", EXEC_NAME, VERSION);
ntfs_log_info("Copyright (c) 2003-2005 Richard Russon\n");
ntfs_log_info("Copyright (c) 2003-2005 Anton Altaparmakov\n");
ntfs_log_info("Copyright (c) 2003-2005 Szabolcs Szakacsits\n");
ntfs_log_info("Copyright (c) 2007 Yura Pakhuchiy\n");
ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -86,7 +88,8 @@ static void usage(void)
" -q, --quiet Less output\n"
" -V, --version Version information\n"
" -v, --verbose More output\n\n",
//" -r --raw Display the compressed or encrypted file",
// Does not work for compressed files at present so leave undocumented...
// " -r --raw Display the raw data (e.g. for compressed or encrypted file)",
EXEC_NAME);
ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
}
@ -130,15 +133,15 @@ static int parse_attribute(const char *value, ATTR_TYPES *attr)
for (i = 0; attr_name[i]; i++) {
if ((strcmp(value, attr_name[i]) == 0) ||
(strcmp(value, attr_name[i]+1) == 0)) {
*attr = (ATTR_TYPES) ((i+1)*16);
(strcmp(value, attr_name[i] + 1) == 0)) {
*attr = (ATTR_TYPES)cpu_to_le32((i + 1) * 16);
return 1;
}
}
num = strtol(value, NULL, 0);
if ((num > 0) && (num < 257)) {
*attr = (ATTR_TYPES) num;
*attr = (ATTR_TYPES)cpu_to_le32(num);
return 1;
}
@ -156,7 +159,7 @@ static int parse_attribute(const char *value, ATTR_TYPES *attr)
*/
static int parse_options(int argc, char **argv)
{
static const char *sopt = "-a:fh?i:n:qVv";
static const char *sopt = "-a:fh?i:n:qVvr";
static const struct option lopt[] = {
{ "attribute", required_argument, NULL, 'a' },
{ "attribute-name", required_argument, NULL, 'n' },
@ -166,6 +169,7 @@ static int parse_options(int argc, char **argv)
{ "quiet", no_argument, NULL, 'q' },
{ "version", no_argument, NULL, 'V' },
{ "verbose", no_argument, NULL, 'v' },
{ "raw", no_argument, NULL, 'r' },
{ NULL, 0, NULL, 0 }
};
@ -179,7 +183,7 @@ static int parse_options(int argc, char **argv)
opterr = 0; /* We'll handle the errors, thank you. */
opts.inode = -1;
opts.attr = -1;
opts.attr = cpu_to_le32(-1);
opts.attr_name = NULL;
opts.attr_name_len = 0;
@ -187,17 +191,19 @@ static int parse_options(int argc, char **argv)
switch (c) {
case 1: /* A non-option argument */
if (!opts.device) {
opts.device = argv[optind-1];
opts.device = argv[optind - 1];
} else if (!opts.file) {
opts.file = argv[optind-1];
opts.file = argv[optind - 1];
} else {
ntfs_log_error("You must specify exactly one file.\n");
ntfs_log_error("You must specify exactly one "
"file.\n");
err++;
}
break;
case 'a':
if (opts.attr != (ATTR_TYPES)-1) {
ntfs_log_error("You must specify exactly one attribute.\n");
if (opts.attr != cpu_to_le32(-1)) {
ntfs_log_error("You must specify exactly one "
"attribute.\n");
} else if (parse_attribute(optarg, &attr) > 0) {
opts.attr = attr;
break;
@ -232,7 +238,8 @@ static int parse_options(int argc, char **argv)
opts.attr_name_len = ntfs_mbstoucs_libntfscompat(optarg,
&opts.attr_name, 0);
if (opts.attr_name_len < 0) {
ntfs_log_perror("Invalid attribute name '%s'", optarg);
ntfs_log_perror("Invalid attribute name '%s'",
optarg);
usage();
}
@ -247,6 +254,9 @@ static int parse_options(int argc, char **argv)
opts.verbose++;
ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
break;
case 'r':
opts.raw = TRUE;
break;
default:
ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
err++;
@ -312,8 +322,7 @@ static int index_get_size(ntfs_inode *inode)
return 0; // not a directory
iroot = (INDEX_ROOT*)((u8*)attr90 + le16_to_cpu(attr90->value_offset));
return iroot->index_block_size;
return le32_to_cpu(iroot->index_block_size);
}
/**
@ -335,7 +344,8 @@ static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type,
attr = ntfs_attr_open(inode, type, name, namelen);
if (!attr) {
ntfs_log_error("Cannot find attribute type 0x%lx.\n", (long) type);
ntfs_log_error("Cannot find attribute type 0x%x.\n",
le32_to_cpu(type));
free(buffer);
return 1;
}
@ -349,10 +359,11 @@ static int cat(ntfs_volume *vol, ntfs_inode *inode, ATTR_TYPES type,
offset = 0;
for (;;) {
if (block_size > 0) {
if (!opts.raw && block_size > 0) {
// These types have fixup
bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer);
bytes_read *= block_size;
if (bytes_read > 0)
bytes_read *= block_size;
} else {
bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer);
}
@ -399,7 +410,8 @@ int main(int argc, char *argv[])
utils_set_locale();
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol) {
ntfs_log_perror("ERROR: couldn't mount volume");
return 1;
@ -416,7 +428,7 @@ int main(int argc, char *argv[])
}
attr = AT_DATA;
if (opts.attr != (ATTR_TYPES)-1)
if (opts.attr != cpu_to_le32(-1))
attr = opts.attr;
result = cat(vol, inode, attr, opts.attr_name, opts.attr_name_len);

View File

@ -38,6 +38,7 @@ struct options {
int force; /* Override common sense */
int quiet; /* Less output */
int verbose; /* Extra output */
BOOL raw; /* Raw data output */
};
#endif /* _NTFSCAT_H_ */

866
ntfsprogs/ntfsck.c 100644
View File

@ -0,0 +1,866 @@
/**
* ntfsck - Part of the Linux-NTFS project.
*
* Copyright (c) 2006 Yuval Fledel
*
* This utility will check and fix errors on an NTFS volume.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#include "layout.h"
#include "cluster.h"
#include "bitmap.h"
#include "utils.h"
#include "endians.h"
#include "bootsect.h"
#define RETURN_FS_ERRORS_CORRECTED (1)
#define RETURN_SYSTEM_NEEDS_REBOOT (2)
#define RETURN_FS_ERRORS_LEFT_UNCORRECTED (4)
#define RETURN_OPERATIONAL_ERROR (8)
#define RETURN_USAGE_OR_SYNTAX_ERROR (16)
#define RETURN_CANCELLED_BY_USER (32)
/* Where did 64 go? */
#define RETURN_SHARED_LIBRARY_ERROR (128)
/* todo: command line: (everything is optional)
* fsck-frontend options:
* -C [fd] : display progress bar (send it to the file descriptor if specified)
* -T : don't show the title on startup
* fsck-checker options:
* -a : auto-repair. no questions. (optional: if marked clean and -f not specified, just check if mounable)
* -p : auto-repair safe. no questions (optional: same)
* -n : only check. no repair.
* -r : interactively repair.
* -y : always yes.
* -v : verbose.
* -V : version.
* taken from fsck.ext2
* -b sb : use the superblock from sb. For corrupted volumes. (do we want separete boot/mft options?)
* -c : use badblocks(8) to find bad blocks (R/O mode) and add the findings to $Bad.
* -C fd : write competion info to fd. If 0, print a completion bar.
* -d : debugging output.
* -D : rebalance indices.
* -f : force checking even if marked clean.
* -F : flush buffers before beginning. (for time-benchmarking)
* -k : When used with -c, don't erase previous $Bad items.
* -n : Open fs as readonly. assume always no. (why is it needed if -r is not specified?)
* -t : Print time statistics.
* taken from fsck.reiserfs
* --rebuild-sb : try to find $MFT start and rebuild the boot sector.
* --rebuild-tree : scan for items and rebuild the indices that point to them (0x30, $SDS, etc.)
* --clean-reserved: zero rezerved fields. (use with care!)
* --adjust-size -z: insert a sparse hole if the data_size is larger than the size marked in the runlist.
* --logfile file : report corruptions (unlike other errors) to a file instead of stderr.
* --nolog : don't report corruptions at all.
* --quiet -q : no progress bar.
* taken from fsck.msdos
* -w : flush after every write.
* - do n passes. (only 2 in fsck.msdos. second should not report errors. Bonus: stop when error list does not change)
* taken from fsck.jfs
* --omit-journal-reply: self-descriptive (why would someone do that?)
* --replay-journal-only: self-descriptive. don't check otherwise.
* taken from fsck.xfs
* -s : only serious errors should be reported.
* -i ino : verbose behaviour only for inode ino.
* -b bno : verbose behaviour only for cluster bno.
* -L : zero log.
* inspired by others
* - don't do cluster accounting.
* - don't do mft record accounting.
* - don't do file names accounting.
* - don't do security_id accounting.
* - don't check acl inheritance problems.
* - undelete unused mft records. (bonus: different options for 100% salvagable and less)
* - error-level-report n: only report errors above this error level
* - error-level-repair n: only repair errors below this error level
* - don't fail on ntfsclone metadata pruning.
* signals:
* SIGUSR1 : start displaying progress bar
* SIGUSR2 : stop displaying progress bar.
*/
/* Assuming NO_NTFS_DEVICE_DEFAULT_IO_OPS is not set */
static int errors = 0;
static int unsupported = 0;
static short bytes_per_sector, sectors_per_cluster;
//static s64 mft_offset, mftmirr_offset;
static s64 current_mft_record;
/**
* This is just a preliminary volume.
* Filled while checking the boot sector and used in the preliminary MFT check.
*/
static ntfs_volume vol;
static runlist_element *mft_rl, *mft_bitmap_rl;
#define check_failed(FORMAT, ARGS...) \
do { \
errors++; \
ntfs_log_redirect(__FUNCTION__,__FILE__,__LINE__, \
NTFS_LOG_LEVEL_ERROR,NULL,FORMAT,##ARGS); \
} while (0);
/**
* 0 success.
* 1 fail.
*/
static int assert_u32_equal(u32 val, u32 ok, const char *name)
{
if (val!=ok) {
check_failed("Assertion failed for '%lld:%s'. should be 0x%x, "
"was 0x%x.\n", current_mft_record, name,
(int)ok, (int)val);
//errors++;
return 1;
}
return 0;
}
static int assert_u32_noteq(u32 val, u32 wrong, const char *name)
{
if (val==wrong) {
check_failed("Assertion failed for '%lld:%s'. should not be "
"0x%x.\n", current_mft_record, name, (int)wrong);
return 1;
}
return 0;
}
static int assert_u32_lesseq(u32 val1, u32 val2, const char *name)
{
if (val1 > val2) {
check_failed("Assertion failed for '%s'. 0x%x > 0x%x\n",
name, (int)val1, (int)val2);
//errors++;
return 1;
}
return 0;
}
static int assert_u32_less(u32 val1, u32 val2, const char *name)
{
if (val1 >= val2) {
check_failed("Assertion failed for '%s'. 0x%x >= 0x%x\n",
name, (int)val1, (int)val2);
//errors++;
return 1;
}
return 0;
}
/**
* Return: 0 ok, 1 error.
*
* todo: may we use ntfs_boot_sector_is_ntfs() instead?
* It already does the checks but will not be able to fix anything.
*/
static BOOL verify_boot_sector(struct ntfs_device *dev)
{
u8 buf[512];
NTFS_BOOT_SECTOR *ntfs_boot = (NTFS_BOOT_SECTOR *)&buf;
//u32 bytes_per_cluster;
current_mft_record = 9;
if (dev->d_ops->pread(dev, buf, sizeof(buf), 0)!=sizeof(buf)) {
check_failed("Failed to read boot sector.\n");
return 1;
}
if ((buf[0]!=0xeb) ||
((buf[1]!=0x52) && (buf[1]!=0x5b)) ||
(buf[2]!=0x90)) {
check_failed("Boot sector: Bad jump.\n");
}
if (ntfs_boot->oem_id != NTFS_SB_MAGIC) {
check_failed("Boot sector: Bad NTFS magic.\n");
}
bytes_per_sector = le16_to_cpu(ntfs_boot->bpb.bytes_per_sector);
if (!bytes_per_sector) {
check_failed("Boot sector: Bytes per sector is 0.\n");
}
if (bytes_per_sector%512) {
check_failed("Boot sector: Bytes per sector is not a multiple"
" of 512.\n");
}
sectors_per_cluster = ntfs_boot->bpb.sectors_per_cluster;
// todo: if partition, query bios and match heads/tracks? */
// Initialize some values from vol. We will need those later.
ntfs_boot_sector_parse(&vol, (NTFS_BOOT_SECTOR *)buf);
vol.dev = dev;
return 0;
}
/**
* Load the runlist of the <attr_type> attribute.
*
* Return NULL if an error.
* The caller is responsible on freeing the allocated memory if the result is not NULL.
*
* Set size_of_file_record to some reasonable size when in doubt (the Windows default is 1024.)
*
* attr_type must be little endian.
*
* This function has code duplication with check_file_record() and
* check_attr_record() but its goal is to be less strict. Thus the
* duplicated checks are the minimal required for not crashing.
*
* Assumes dev is open.
*/
static runlist *load_runlist(struct ntfs_device *dev, s64 offset_to_file_record, u32 attr_type, u32 size_of_file_record)
{
u8 *buf;
u16 attrs_offset;
u32 length;
ATTR_RECORD *attr_rec;
if (size_of_file_record<22) // offset to attrs_offset
return NULL;
buf = (u8*)ntfs_malloc(size_of_file_record);
if (!buf)
return NULL;
if (dev->d_ops->pread(dev, buf, size_of_file_record, offset_to_file_record)!=size_of_file_record) {
check_failed("Failed to read file record at offset %lld (0x%llx).\n", offset_to_file_record, offset_to_file_record);
return NULL;
}
attrs_offset = le16_to_cpu(((MFT_RECORD*)buf)->attrs_offset);
// first attribute must be after the header.
if (attrs_offset<42) {
check_failed("First attribute must be after the header (%u).\n", (int)attrs_offset);
}
attr_rec = (ATTR_RECORD *)(buf + attrs_offset);
//printf("uv1.\n");
while ((u8*)attr_rec<=buf+size_of_file_record-4) {
//printf("Attr type: 0x%x.\n", attr_rec->type);
// Check attribute record. (Only what is in the buffer)
if (attr_rec->type==AT_END) {
check_failed("Attribute 0x%x not found in file record at offset %lld (0x%llx).\n", (int)le32_to_cpu(attr_rec->type), offset_to_file_record, offset_to_file_record);
return NULL;
}
if ((u8*)attr_rec>buf+size_of_file_record-8) {
// not AT_END yet no room for the length field.
check_failed("Attribute 0x%x is not AT_END, yet no "
"room for the length field.\n",
(int)le32_to_cpu(attr_rec->type));
return NULL;
}
length = le32_to_cpu(attr_rec->length);
// Check that this attribute does not overflow the mft_record
if ((u8*)attr_rec+length >= buf+size_of_file_record) {
check_failed("Attribute (0x%x) is larger than FILE record at offset %lld (0x%llx).\n",
(int)le32_to_cpu(attr_rec->type), offset_to_file_record, offset_to_file_record);
return NULL;
}
// todo: what ATTRIBUTE_LIST (0x20)?
if (attr_rec->type==attr_type) {
// Eurika!
// ntfs_mapping_pairs_decompress only use two values from vol. Just fake it.
// todo: it will also use vol->major_ver if defined(DEBUG). But only for printing purposes.
// Assume ntfs_boot_sector_parse() was called.
return ntfs_mapping_pairs_decompress(&vol, attr_rec, NULL);
}
attr_rec = (ATTR_RECORD*)((u8*)attr_rec+length);
}
// If we got here, there was an overflow.
check_failed("file record corrupted at offset %lld (0x%llx).\n", offset_to_file_record, offset_to_file_record);
return NULL;
}
/**
* Return: >=0 last VCN
* LCN_EINVAL error.
*/
static VCN get_last_vcn(runlist *rl)
{
VCN res;
if (!rl)
return LCN_EINVAL;
res = LCN_EINVAL;
while (rl->length) {
ntfs_log_verbose("vcn: %lld, length: %lld.\n", rl->vcn,
rl->length);
if (rl->vcn<0)
res = rl->vcn;
else
res = rl->vcn + rl->length;
rl++;
}
return res;
}
static u32 mft_bitmap_records;
static u8 *mft_bitmap_buf;
/**
* Assumes mft_bitmap_rl is initialized.
* return: 0 ok.
* RETURN_OPERATIONAL_ERROR on error.
*/
static int mft_bitmap_load(struct ntfs_device *dev)
{
VCN vcn;
u32 mft_bitmap_length;
vcn = get_last_vcn(mft_bitmap_rl);
if (vcn<=LCN_EINVAL) {
mft_bitmap_buf = NULL;
/* This case should not happen, not even with on-disk errors */
goto error;
}
mft_bitmap_length = vcn * vol.cluster_size;
mft_bitmap_records = 8 * mft_bitmap_length * vol.cluster_size /
vol.mft_record_size;
//printf("sizes: %d, %d.\n", mft_bitmap_length, mft_bitmap_records);
mft_bitmap_buf = (u8*)ntfs_malloc(mft_bitmap_length);
if (!mft_bitmap_buf)
goto error;
if (ntfs_rl_pread(&vol, mft_bitmap_rl, 0, mft_bitmap_length,
mft_bitmap_buf)!=mft_bitmap_length)
goto error;
return 0;
error:
mft_bitmap_records = 0;
ntfs_log_error("Could not load $MFT/Bitmap.\n");
return RETURN_OPERATIONAL_ERROR;
}
/**
* -1 Error.
* 0 Unused record
* 1 Used record
*
* Assumes mft_bitmap_rl was initialized.
*/
static int mft_bitmap_get_bit(s64 mft_no)
{
if (mft_no>=mft_bitmap_records)
return -1;
return ntfs_bit_get(mft_bitmap_buf, mft_no);
}
/**
* @attr_rec: The attribute record to check
* @mft_rec: The parent FILE record.
* @buflen: The size of the FILE record.
*
* Return:
* NULL: Fatal error occured. Not sure where is the next record.
* otherwise: pointer to the next attribute record.
*
* The function only check fields that are inside this attr record.
*
* Assumes mft_rec is current_mft_record.
*/
static ATTR_REC *check_attr_record(ATTR_REC *attr_rec, MFT_RECORD *mft_rec,
u16 buflen)
{
u16 name_offset;
u16 attrs_offset = le16_to_cpu(mft_rec->attrs_offset);
u32 attr_type = le32_to_cpu(attr_rec->type);
u32 length = le32_to_cpu(attr_rec->length);
// Check that this attribute does not overflow the mft_record
if ((u8*)attr_rec+length >= ((u8*)mft_rec)+buflen) {
check_failed("Attribute (0x%x) is larger than FILE record (%lld).\n",
(int)attr_type, current_mft_record);
return NULL;
}
// Attr type must be a multiple of 0x10 and 0x10<=x<=0x100.
if ((attr_type & ~0x0F0) && (attr_type != 0x100)) {
check_failed("Unknown attribute type 0x%x.\n",
(int)attr_type);
goto check_attr_record_next_attr;
}
if (length<24) {
check_failed("Attribute %lld:0x%x Length too short (%u).\n",
current_mft_record, (int)attr_type, (int)length);
goto check_attr_record_next_attr;
}
// If this is the first attribute:
// todo: instance number must be smaller than next_instance.
if ((u8*)attr_rec == ((u8*)mft_rec) + attrs_offset) {
if (!mft_rec->base_mft_record)
assert_u32_equal(attr_type, 0x10,
"First attribute type");
// The following not always holds.
// attr 0x10 becomes instance 1 and attr 0x40 becomes 0.
//assert_u32_equal(attr_rec->instance, 0,
// "First attribute instance number");
} else {
assert_u32_noteq(attr_type, 0x10,
"Not-first attribute type");
// The following not always holds.
//assert_u32_noteq(attr_rec->instance, 0,
// "Not-first attribute instance number");
}
//if (current_mft_record==938 || current_mft_record==1683 || current_mft_record==3152 || current_mft_record==22410)
//printf("Attribute %lld:0x%x instance: %u isbase:%d.\n",
// current_mft_record, (int)attr_type, (int)le16_to_cpu(attr_rec->instance), (int)mft_rec->base_mft_record);
// todo: instance is unique.
// Check flags.
if (attr_rec->flags & ~(const_cpu_to_le16(0xc0ff))) {
check_failed("Attribute %lld:0x%x Unknown flags (0x%x).\n",
current_mft_record, (int)attr_type,
(int)le16_to_cpu(attr_rec->flags));
}
if (attr_rec->non_resident>1) {
check_failed("Attribute %lld:0x%x Unknown non-resident "
"flag (0x%x).\n", current_mft_record,
(int)attr_type, (int)attr_rec->non_resident);
goto check_attr_record_next_attr;
}
name_offset = le16_to_cpu(attr_rec->name_offset);
/*
* todo: name must be legal unicode.
* Not really, information below in urls is about filenames, but I
* believe it also applies to attribute names. (Yura)
* http://blogs.msdn.com/michkap/archive/2006/09/24/769540.aspx
* http://blogs.msdn.com/michkap/archive/2006/09/10/748699.aspx
*/
if (attr_rec->non_resident) {
// Non-Resident
// Make sure all the fields exist.
if (length<64) {
check_failed("Non-resident attribute %lld:0x%x too short (%u).\n",
current_mft_record, (int)attr_type, (int)length);
goto check_attr_record_next_attr;
}
if (attr_rec->compression_unit && (length<72)) {
check_failed("Compressed attribute %lld:0x%x too short (%u).\n",
current_mft_record, (int)attr_type, (int)length);
goto check_attr_record_next_attr;
}
// todo: name comes before mapping pairs, and after the header.
// todo: length==mapping_pairs_offset+length of compressed mapping pairs.
// todo: mapping_pairs_offset is 8-byte aligned.
// todo: lowest vcn <= highest_vcn
// todo: if base record -> lowest vcn==0
// todo: lowest_vcn!=0 -> attribute list is used.
// todo: lowest_vcn & highest_vcn are in the drive (0<=x<total clusters)
// todo: mapping pairs agree with highest_vcn.
// todo: compression unit == 0 or 4.
// todo: reserved1 == 0.
// todo: if not compressed nor sparse, initialized_size <= allocated_size and data_size <= allocated_size.
// todo: if compressed or sparse, allocated_size <= initialized_size and allocated_size <= data_size
// todo: if mft_no!=0 and not compressed/sparse, data_size==initialized_size.
// todo: if mft_no!=0 and compressed/sparse, allocated_size==initialized_size.
// todo: what about compressed_size if compressed?
// todo: attribute must not be 0x10, 0x30, 0x40, 0x60, 0x70, 0x90, 0xd0 (not sure about 0xb0, 0xe0, 0xf0)
} else {
u16 value_offset = le16_to_cpu(attr_rec->value_offset);
u32 value_length = le32_to_cpu(attr_rec->value_length);
// Resident
if (attr_rec->name_length) {
if (name_offset < 24)
check_failed("Resident attribute with "
"name intersecting header.\n");
if (value_offset < name_offset +
attr_rec->name_length)
check_failed("Named resident attribute "
"with value before name.\n");
}
// if resident, length==value_length+value_offset
//assert_u32_equal(le32_to_cpu(attr_rec->value_length)+
// value_offset, length,
// "length==value_length+value_offset");
// if resident, length==value_length+value_offset
if (value_length+value_offset > length) {
check_failed("value_length(%d)+value_offset(%d)>length(%d) for attribute 0x%x.\n", (int)value_length, (int)value_offset, (int)length, (int)attr_type);
return NULL;
}
// Check resident_flags.
if (attr_rec->resident_flags>0x01) {
check_failed("Unknown resident flags (0x%x) for attribute 0x%x.\n", (int)attr_rec->resident_flags, (int)attr_type);
} else if (attr_rec->resident_flags && (attr_type!=0x30)) {
check_failed("Resident flags mark attribute 0x%x as indexed.\n", (int)attr_type);
}
// reservedR is 0.
assert_u32_equal(attr_rec->reservedR, 0, "Resident Reserved");
// todo: attribute must not be 0xa0 (not sure about 0xb0, 0xe0, 0xf0)
// todo: check content well-formness per attr_type.
}
return 0;
check_attr_record_next_attr:
return (ATTR_REC *)(((u8 *)attr_rec) + length);
}
/**
* All checks that can be satisfied only by data from the buffer.
* No other [MFT records/metadata files] are required.
*
* The buffer is changed by removing the Update Sequence.
*
* Return:
* 0 Everything's cool.
* else Consider this record as damaged.
*/
static BOOL check_file_record(u8 *buffer, u16 buflen)
{
u16 usa_count, usa_ofs, attrs_offset, usa;
u32 bytes_in_use, bytes_allocated, i;
MFT_RECORD *mft_rec = (MFT_RECORD *)buffer;
ATTR_REC *attr_rec;
// check record magic
assert_u32_equal(mft_rec->magic, magic_FILE, "FILE record magic");
// todo: records 16-23 must be filled in order.
// todo: what to do with magic_BAAD?
// check usa_count+offset to update seq <= attrs_offset <
// bytes_in_use <= bytes_allocated <= buflen.
usa_ofs = le16_to_cpu(mft_rec->usa_ofs);
usa_count = le16_to_cpu(mft_rec->usa_count);
attrs_offset = le16_to_cpu(mft_rec->attrs_offset);
bytes_in_use = le32_to_cpu(mft_rec->bytes_in_use);
bytes_allocated = le32_to_cpu(mft_rec->bytes_allocated);
if (assert_u32_lesseq(usa_ofs+usa_count, attrs_offset,
"usa_ofs+usa_count <= attrs_offset") ||
assert_u32_less(attrs_offset, bytes_in_use,
"attrs_offset < bytes_in_use") ||
assert_u32_lesseq(bytes_in_use, bytes_allocated,
"bytes_in_use <= bytes_allocated") ||
assert_u32_lesseq(bytes_allocated, buflen,
"bytes_allocated <= max_record_size")) {
return 1;
}
// We should know all the flags.
if (mft_rec->flags>0xf) {
check_failed("Unknown MFT record flags (0x%x).\n",
(unsigned int)mft_rec->flags);
}
// todo: flag in_use must be on.
// Remove update seq & check it.
usa = *(u16*)(buffer+usa_ofs); // The value that should be at the end of every sector.
assert_u32_equal(usa_count-1, buflen/bytes_per_sector, "USA length");
for (i=1;i<usa_count;i++) {
u16 *fixup = (u16*)(buffer+bytes_per_sector*i-2); // the value at the end of the sector.
u16 saved_val = *(u16*)(buffer+usa_ofs+2*i); // the actual data value that was saved in the us array.
assert_u32_equal(*fixup, usa, "fixup");
*fixup = saved_val; // remove it.
}
attr_rec = (ATTR_REC *)(buffer + attrs_offset);
while ((u8*)attr_rec<=buffer+buflen-4) {
// Check attribute record. (Only what is in the buffer)
if (attr_rec->type==AT_END) {
// Done.
return 0;
}
if ((u8*)attr_rec>buffer+buflen-8) {
// not AT_END yet no room for the length field.
check_failed("Attribute 0x%x is not AT_END, yet no "
"room for the length field.\n",
(int)le32_to_cpu(attr_rec->type));
return 1;
}
attr_rec = check_attr_record(attr_rec, mft_rec, buflen);
if (!attr_rec)
return 1;
}
// If we got here, there was an overflow.
return 1;
// todo: an attribute should be at the offset to first attribute, and the offset should be inside the buffer. It should have the value of "next attribute id".
// todo: if base record, it should start with attribute 0x10.
// Highlevel check of attributes.
// todo: Attributes are well-formed.
// todo: Room for next attribute in the end of the previous record.
return FALSE;
}
static void replay_log(ntfs_volume *vol)
{
// At this time, only check that the log is fully replayed.
ntfs_log_warning("Unsupported: replay_log()\n");
// todo: if logfile is clean, return success.
unsupported++;
}
static void verify_mft_record(ntfs_volume *vol, s64 mft_num)
{
u8 *buffer;
int is_used;
current_mft_record = mft_num;
is_used = mft_bitmap_get_bit(mft_num);
if (is_used<0) {
ntfs_log_error("Error getting bit value for record %lld.\n", mft_num);
} else if (!is_used) {
ntfs_log_verbose("Record %lld unused. Skipping.\n", mft_num);
return;
}
buffer = ntfs_malloc(vol->mft_record_size);
if (!buffer)
goto verify_mft_record_error;
ntfs_log_verbose("MFT record %lld\n", mft_num);
if (ntfs_attr_pread(vol->mft_na, mft_num*vol->mft_record_size, vol->mft_record_size, buffer) < 0) {
ntfs_log_perror("Couldn't read $MFT record %lld", mft_num);
goto verify_mft_record_error;
}
check_file_record(buffer, vol->mft_record_size);
// todo: if offset to first attribute >= 0x30, number of mft record should match.
// todo: Match the "record is used" with the mft bitmap.
// todo: if this is not base, check that the parent is a base, and is in use, and pointing to this record.
// todo: if base record: for each extent record:
// todo: verify_file_record
// todo: hard link count should be the number of 0x30 attributes.
// todo: Order of attributes.
// todo: make sure compression_unit is the same.
return;
verify_mft_record_error:
if (buffer)
free(buffer);
errors++;
}
/**
* This function serves as bootstraping for the more comprehensive checks.
* It will load the MFT runlist and MFT/Bitmap runlist.
* It should not depend on other checks or we may have a circular dependancy.
* Also, this loadng must be forgiving, unlike the comprehensive checks.
*/
static int verify_mft_preliminary(struct ntfs_device *dev)
{
current_mft_record = 0;
s64 mft_offset, mftmirr_offset;
int res;
ntfs_log_trace("Entering verify_mft_preliminary().\n");
// todo: get size_of_file_record from boot sector
// Load the first segment of the $MFT/DATA runlist.
mft_offset = vol.mft_lcn * vol.cluster_size;
mftmirr_offset = vol.mftmirr_lcn * vol.cluster_size;
mft_rl = load_runlist(dev, mft_offset, AT_DATA, 1024);
if (!mft_rl) {
check_failed("Loading $MFT runlist failed. Trying $MFTMirr.\n");
mft_rl = load_runlist(dev, mftmirr_offset, AT_DATA, 1024);
}
if (!mft_rl) {
check_failed("Loading $MFTMirr runlist failed too. Aborting.\n");
return RETURN_FS_ERRORS_LEFT_UNCORRECTED | RETURN_OPERATIONAL_ERROR;
}
// TODO: else { recover $MFT } // Use $MFTMirr to recover $MFT.
// todo: support loading the next runlist extents when ATTRIBUTE_LIST is used on $MFT.
// If attribute list: Gradually load mft runlist. (parse runlist from first file record, check all referenced file records, continue with the next file record). If no attribute list, just load it.
// Load the runlist of $MFT/Bitmap.
// todo: what about ATTRIBUTE_LIST? Can we reuse code?
mft_bitmap_rl = load_runlist(dev, mft_offset, AT_BITMAP, 1024);
if (!mft_bitmap_rl) {
check_failed("Loading $MFT/Bitmap runlist failed. Trying $MFTMirr.\n");
mft_bitmap_rl = load_runlist(dev, mftmirr_offset, AT_BITMAP, 1024);
}
if (!mft_bitmap_rl) {
check_failed("Loading $MFTMirr/Bitmap runlist failed too. Aborting.\n");
return RETURN_FS_ERRORS_LEFT_UNCORRECTED;
// todo: rebuild the bitmap by using the "in_use" file record flag or by filling it with 1's.
}
/* Load $MFT/Bitmap */
if ((res = mft_bitmap_load(dev)))
return res;
return -1; /* FIXME: Just added to fix compiler warning without
thinking about what should be here. (Yura) */
}
static void check_volume(ntfs_volume *vol)
{
s64 mft_num, nr_mft_records;
ntfs_log_warning("Unsupported: check_volume()\n");
unsupported++;
// For each mft record, verify that it contains a valid file record.
nr_mft_records = vol->mft_na->initialized_size >>
vol->mft_record_size_bits;
ntfs_log_info("Checking %lld MFT records.\n", nr_mft_records);
for (mft_num=0; mft_num < nr_mft_records; mft_num++) {
verify_mft_record(vol, mft_num);
}
// todo: Check metadata files.
// todo: Second pass on mft records. Now check the contents as well.
// todo: When going through runlists, build a bitmap.
// todo: cluster accounting.
return;
}
static int reset_dirty(ntfs_volume *vol)
{
u16 flags;
if (!(vol->flags | VOLUME_IS_DIRTY))
return 0;
ntfs_log_verbose("Resetting dirty flag.\n");
flags = vol->flags & ~VOLUME_IS_DIRTY;
if (ntfs_volume_write_flags(vol, flags)) {
ntfs_log_error("Error setting volume flags.\n");
return -1;
}
return 0;
}
/**
* main - Does just what C99 claim it does.
*
* For more details on arguments and results, check the man page.
*/
int main(int argc, char **argv)
{
struct ntfs_device *dev;
ntfs_volume *vol;
const char *name;
int ret;
if (argc != 2)
return RETURN_USAGE_OR_SYNTAX_ERROR;
name = argv[1];
ntfs_log_set_handler(ntfs_log_handler_outerr);
//ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE | NTFS_LOG_LEVEL_QUIET | NTFS_LOG_LEVEL_INFO | NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_PROGRESS);
/* Allocate an ntfs_device structure. */
dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
if (!dev)
return RETURN_OPERATIONAL_ERROR;
if (dev->d_ops->open(dev, O_RDONLY)) { //O_RDWR/O_RDONLY?
ntfs_log_perror("Error opening partition device");
ntfs_device_free(dev);
return RETURN_OPERATIONAL_ERROR;
}
if ((ret = verify_boot_sector(dev))) {
dev->d_ops->close(dev);
return ret;
}
ntfs_log_verbose("Boot sector verification complete. Proceeding to $MFT");
verify_mft_preliminary(dev);
/* ntfs_device_mount() expects the device to be closed. */
if (dev->d_ops->close(dev))
ntfs_log_perror("Failed to close the device.");
// at this point we know that the volume is valid enough for mounting.
/* Call ntfs_device_mount() to do the actual mount. */
vol = ntfs_device_mount(dev, NTFS_MNT_RDONLY);
if (!vol) {
ntfs_device_free(dev);
return 2;
}
replay_log(vol);
if (vol->flags & VOLUME_IS_DIRTY)
ntfs_log_warning("Volume is dirty.\n");
check_volume(vol);
if (errors)
ntfs_log_info("Errors found.\n");
if (unsupported)
ntfs_log_info("Unsupported cases found.\n");
if (!errors && !unsupported) {
reset_dirty(vol);
}
ntfs_umount(vol, FALSE);
if (errors)
return 2;
if (unsupported)
return 1;
return 0;
}

View File

@ -2,7 +2,7 @@
* ntfsclone - Part of the Linux-NTFS project.
*
* Copyright (c) 2003-2006 Szabolcs Szakacsits
* Copyright (c) 2004-2005 Anton Altaparmakov
* Copyright (c) 2004-2006 Anton Altaparmakov
* Special image format support copyright (c) 2004 Per Olofsson
*
* Clone NTFS data and/or metadata to a sparse file, image, device or stdout.
@ -55,6 +55,12 @@
#include <getopt.h>
#endif
/*
* FIXME: ntfsclone do bad things about endians handling. Fix it and remove
* this note and define.
*/
#define NTFS_DO_NOT_CHECK_ENDIANS
#include <ntfs-3g/debug.h>
#include <ntfs-3g/types.h>
#include <ntfs-3g/support.h>
@ -96,7 +102,7 @@ static const char *dirty_volume_msg =
"Volume '%s' is scheduled for a check or it was shutdown \n"
"uncleanly. Please boot Windows or use the --force option to progress.\n";
struct {
static struct {
int verbose;
int quiet;
int debug;
@ -117,7 +123,6 @@ struct {
struct bitmap {
s64 size;
u8 *bm;
u8 padding[4]; /* Unused: padding to 64 bit. */
};
struct progress_bar {
@ -141,24 +146,44 @@ struct ntfs_walk_cluster {
};
ntfs_volume *vol = NULL;
struct bitmap lcn_bitmap;
static ntfs_volume *vol = NULL;
static struct bitmap lcn_bitmap;
int fd_in;
int fd_out;
FILE *msg_out = NULL;
static int fd_in;
static int fd_out;
static FILE *msg_out = NULL;
int wipe = 0;
unsigned int nr_used_mft_records = 0;
unsigned int wiped_unused_mft_data = 0;
unsigned int wiped_unused_mft = 0;
unsigned int wiped_resident_data = 0;
unsigned int wiped_timestamp_data = 0;
static int wipe = 0;
static unsigned int nr_used_mft_records = 0;
static unsigned int wiped_unused_mft_data = 0;
static unsigned int wiped_unused_mft = 0;
static unsigned int wiped_resident_data = 0;
static unsigned int wiped_timestamp_data = 0;
static BOOL image_is_host_endian = FALSE;
#define IMAGE_MAGIC "\0ntfsclone-image"
#define IMAGE_MAGIC_SIZE 16
struct {
/* This is the first endianness safe format version. */
#define NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE 10
#define NTFSCLONE_IMG_VER_MINOR_ENDIANNESS_SAFE 0
/*
* Set the version to 10.0 to avoid colisions with old ntfsclone which
* stupidly used the volume version as the image version... )-: I hope NTFS
* never reaches version 10.0 and if it does one day I hope no-one is using
* such an old ntfsclone by then...
*
* NOTE: Only bump the minor version if the image format and header are still
* backwards compatible. Otherwise always bump the major version. If in
* doubt, bump the major version.
*/
#define NTFSCLONE_IMG_VER_MAJOR 10
#define NTFSCLONE_IMG_VER_MINOR 0
/* All values are in little endian. */
static struct {
char magic[IMAGE_MAGIC_SIZE];
u8 major_ver;
u8 minor_ver;
@ -166,8 +191,12 @@ struct {
s64 device_size;
s64 nr_clusters;
s64 inuse;
u32 offset_to_image_data; /* From start of image_hdr. */
} __attribute__((__packed__)) image_hdr;
#define NTFSCLONE_IMG_HEADER_SIZE_OLD \
(offsetof(typeof(image_hdr), offset_to_image_data))
#define NTFS_MBYTE (1000 * 1000)
#define ERR_PREFIX "ERROR"
@ -528,7 +557,7 @@ static void copy_cluster(int rescue, u64 rescue_lcn)
{
char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
/* vol is NULL if opt.restore_image is set */
u32 csize = image_hdr.cluster_size;
u32 csize = le32_to_cpu(image_hdr.cluster_size);
void *fd = (void *)&fd_in;
off_t rescue_pos;
@ -590,10 +619,12 @@ static void lseek_to_cluster(s64 lcn)
static void image_skip_clusters(s64 count)
{
if (opt.save_image && count > 0) {
typeof(count) count_buf;
char buff[1 + sizeof(count)];
buff[0] = 0;
memcpy(buff + 1, &count, sizeof(count));
count_buf = cpu_to_sle64(count);
memcpy(buff + 1, &count_buf, sizeof(count_buf));
if (write_all(&fd_out, buff, sizeof(buff)) == -1)
perr_exit("write_all");
@ -630,13 +661,15 @@ static void clone_ntfs(u64 nr_clusters)
else
Printf("Cloning NTFS ...\n");
if ((buf = calloc(1, csize)) == NULL)
buf = ntfs_calloc(csize);
if (!buf)
perr_exit("clone_ntfs");
progress_init(&progress, p_counter, nr_clusters, 100);
if (opt.save_image) {
if (write_all(&fd_out, &image_hdr, sizeof(image_hdr)) == -1)
if (write_all(&fd_out, &image_hdr,
image_hdr.offset_to_image_data) == -1)
perr_exit("write_all");
}
@ -679,7 +712,7 @@ static void write_empty_clusters(s32 csize, s64 count,
static void restore_image(void)
{
s64 pos = 0, count;
s32 csize = image_hdr.cluster_size;
s32 csize = le32_to_cpu(image_hdr.cluster_size);
char cmd;
u64 p_counter = 0;
struct progress_bar progress;
@ -687,21 +720,25 @@ static void restore_image(void)
Printf("Restoring NTFS from image ...\n");
progress_init(&progress, p_counter, opt.std_out ?
image_hdr.nr_clusters : image_hdr.inuse, 100);
sle64_to_cpu(image_hdr.nr_clusters) :
sle64_to_cpu(image_hdr.inuse),
100);
while (pos < image_hdr.nr_clusters) {
while (pos < sle64_to_cpu(image_hdr.nr_clusters)) {
if (read_all(&fd_in, &cmd, sizeof(cmd)) == -1)
perr_exit("read_all");
if (cmd == 0) {
if (read_all(&fd_in, &count, sizeof(count)) == -1)
perr_exit("read_all");
if (!image_is_host_endian)
count = sle64_to_cpu(count);
if (opt.std_out)
write_empty_clusters(csize, count,
&progress, &p_counter);
else {
if (lseek(fd_out, count * csize, SEEK_CUR)
== (off_t)-1)
if (lseek(fd_out, count * csize, SEEK_CUR) ==
(off_t)-1)
perr_exit("restore_image: lseek");
}
pos += count;
@ -719,15 +756,16 @@ static void wipe_index_entry_timestams(INDEX_ENTRY *e)
static const struct timespec zero_time = { .tv_sec = 0, .tv_nsec = 0 };
s64 timestamp = timespec2ntfs(zero_time);
/* FIXME: can fall into infinite loop if corrupted */
while (!(e->ie_flags & INDEX_ENTRY_END)) {
e->key.file_name.creation_time = timestamp;
e->key.file_name.last_data_change_time = timestamp;
e->key.file_name.last_mft_change_time = timestamp;
e->key.file_name.last_access_time = timestamp;
wiped_timestamp_data += 32;
e = (INDEX_ENTRY *)((u8 *)e + le16_to_cpu(e->length));
}
}
@ -745,7 +783,8 @@ static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
indexr = ntfs_index_root_get(ni, attr);
if (!indexr) {
ntfs_log_perror("Failed to read $INDEX_ROOT attribute");
perr_printf("Failed to read $INDEX_ROOT attribute of inode "
"%lld", ni->mft_no);
return;
}
@ -754,34 +793,38 @@ static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
name_len = attr->name_length;
byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL);
if (!byte) {
ntfs_log_perror("Failed to read $BITMAP attribute");
perr_printf("Failed to read $BITMAP attribute");
goto out_indexr;
}
na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, name, name_len);
if (!na) {
ntfs_log_perror("Failed to open $INDEX_ALLOCATION attribute");
perr_printf("Failed to open $INDEX_ALLOCATION attribute");
goto out_bitmap;
}
tmp_indexa = indexa = malloc(na->data_size);
if (!tmp_indexa) {
ntfs_log_perror("malloc failed");
if (!na->data_size)
goto out_na;
}
tmp_indexa = indexa = ntfs_malloc(na->data_size);
if (!tmp_indexa)
goto out_na;
if (ntfs_attr_pread(na, 0, na->data_size, indexa) != na->data_size) {
ntfs_log_perror("Failed to read $INDEX_ALLOCATION attribute");
perr_printf("Failed to read $INDEX_ALLOCATION attribute");
goto out_indexa;
}
bit = 0;
while ((u8 *)tmp_indexa < (u8 *)indexa + na->data_size) {
if (*byte & (1 << bit)) {
if (*byte & (1 << bit)) {
if (ntfs_mst_post_read_fixup((NTFS_RECORD *)tmp_indexa,
indexr->index_block_size)) {
ntfs_log_perror("Damaged INDX record");
le32_to_cpu(
indexr->index_block_size))) {
perr_printf("Damaged INDX record");
goto out_indexa;
}
entry = (INDEX_ENTRY *)((u8 *)tmp_indexa + le32_to_cpu(
@ -793,22 +836,22 @@ static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
perr_exit("ntfs_mft_usn_dec");
if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)tmp_indexa,
indexr->index_block_size)) {
ntfs_log_perror("INDX write fixup failed");
le32_to_cpu(
indexr->index_block_size))) {
perr_printf("INDX write fixup failed");
goto out_indexa;
}
}
tmp_indexa = (INDEX_ALLOCATION *)((u8 *)tmp_indexa +
indexr->index_block_size);
tmp_indexa = (INDEX_ALLOCATION *)((u8 *)tmp_indexa +
le32_to_cpu(indexr->index_block_size));
bit++;
if (bit > 7) {
bit = 0;
byte++;
}
}
if (ntfs_rl_pwrite(vol, na->rl, 0, 0, na->data_size, indexa) != na->data_size)
ntfs_log_perror("ntfs_rl_pwrite failed");
perr_printf("ntfs_rl_pwrite failed for inode %lld", ni->mft_no);
out_indexa:
free(indexa);
out_na:
@ -848,7 +891,7 @@ static void wipe_index_root_timestamps(ATTR_RECORD *attr, s64 timestamp)
QUOTA_CONTROL_ENTRY *quota_q;
quota_q = (QUOTA_CONTROL_ENTRY *)((u8 *)entry +
entry->data_offset);
le16_to_cpu(entry->data_offset));
/*
* FIXME: no guarantee it's indeed /$Extend/$Quota:$Q.
* For now, as a minimal safeguard, we check only for
@ -867,7 +910,7 @@ static void wipe_index_root_timestamps(ATTR_RECORD *attr, s64 timestamp)
#define WIPE_TIMESTAMPS(atype, attr, timestamp) \
do { \
atype *ats; \
ats = (atype *)((char *)(attr) + (attr)->value_offset); \
ats = (atype *)((char *)(attr) + le16_to_cpu((attr)->value_offset)); \
\
ats->creation_time = (timestamp); \
ats->last_data_change_time = (timestamp); \
@ -889,7 +932,7 @@ static void wipe_timestamps(ntfs_walk_clusters_ctx *image)
else if (a->type == AT_STANDARD_INFORMATION)
WIPE_TIMESTAMPS(STANDARD_INFORMATION, a, timestamp);
else if (a->type == AT_INDEX_ROOT)
wipe_index_root_timestamps(a, timestamp);
}
@ -1133,11 +1176,26 @@ static void mft_record_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
{
if (ntfs_mft_usn_dec(ni->mrec))
perr_exit("ntfs_mft_usn_dec");
if (ntfs_mft_record_write(volume, ni->mft_no, ni->mrec))
perr_exit("ntfs_mft_record_write");
}
static void mft_inode_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
{
s32 i;
mft_record_write_with_same_usn(volume, ni);
if (ni->nr_extents <= 0)
return;
for (i = 0; i < ni->nr_extents; ++i) {
ntfs_inode *eni = ni->extent_nis[i];
mft_record_write_with_same_usn(volume, eni);
}
}
static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
{
s64 inode = 0;
@ -1160,7 +1218,7 @@ static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
/* FIXME: Terrible kludge for libntfs not being able to return
a deleted MFT record as inode */
ni = (ntfs_inode*)calloc(1, sizeof(ntfs_inode));
ni = ntfs_calloc(sizeof(ntfs_inode));
if (!ni)
perr_exit("walk_clusters");
@ -1209,7 +1267,7 @@ static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
out:
if (wipe) {
wipe_unused_mft_data(ni);
mft_record_write_with_same_usn(volume, ni);
mft_inode_write_with_same_usn(volume, ni);
}
if (ntfs_inode_close(ni))
@ -1241,7 +1299,8 @@ static void setup_lcn_bitmap(void)
/* Determine lcn bitmap byte size and allocate it. */
lcn_bitmap.size = rounded_up_division(vol->nr_clusters, 8);
if (!(lcn_bitmap.bm = (unsigned char *)calloc(1, lcn_bitmap.size)))
lcn_bitmap.bm = ntfs_calloc(lcn_bitmap.size);
if (!lcn_bitmap.bm)
perr_exit("Failed to allocate internal buffer");
bitmap_file_data_fixup(vol->nr_clusters, &lcn_bitmap);
@ -1261,14 +1320,15 @@ static void print_volume_size(const char *str, s64 bytes)
}
static void print_disk_usage(u32 cluster_size, s64 nr_clusters, s64 inuse)
static void print_disk_usage(const char *spacer, u32 cluster_size,
s64 nr_clusters, s64 inuse)
{
s64 total, used;
total = nr_clusters * cluster_size;
used = inuse * cluster_size;
Printf("Space in use : %lld MB (%.1f%%) ",
Printf("Space in use %s: %lld MB (%.1f%%) ", spacer,
(long long)rounded_up_division(used, NTFS_MBYTE),
100.0 * ((float)used / total));
@ -1277,16 +1337,21 @@ static void print_disk_usage(u32 cluster_size, s64 nr_clusters, s64 inuse)
static void print_image_info(void)
{
Printf("NTFS volume version: %d.%d\n",
image_hdr.major_ver, image_hdr.minor_ver);
Printf("Cluster size : %u bytes\n",
(unsigned int)image_hdr.cluster_size);
print_volume_size("Image volume size ",
image_hdr.nr_clusters * image_hdr.cluster_size);
Printf("Image device size : %lld bytes\n", image_hdr.device_size);
print_disk_usage(image_hdr.cluster_size,
image_hdr.nr_clusters,
image_hdr.inuse);
Printf("Ntfsclone image version: %d.%d\n",
image_hdr.major_ver, image_hdr.minor_ver);
Printf("Cluster size : %u bytes\n",
(unsigned)le32_to_cpu(image_hdr.cluster_size));
print_volume_size("Image volume size ",
sle64_to_cpu(image_hdr.nr_clusters) *
le32_to_cpu(image_hdr.cluster_size));
Printf("Image device size : %lld bytes\n",
sle64_to_cpu(image_hdr.device_size));
print_disk_usage(" ", le32_to_cpu(image_hdr.cluster_size),
sle64_to_cpu(image_hdr.nr_clusters),
sle64_to_cpu(image_hdr.inuse));
Printf("Offset to image data : %u (0x%x) bytes\n",
(unsigned)le32_to_cpu(image_hdr.offset_to_image_data),
(unsigned)le32_to_cpu(image_hdr.offset_to_image_data));
}
static void check_if_mounted(const char *device, unsigned long new_mntflag)
@ -1331,7 +1396,7 @@ static void mount_volume(unsigned long new_mntflag)
exit(1);
}
if (vol->flags & VOLUME_IS_DIRTY)
if (NVolWasDirty(vol))
if (opt.force-- <= 0)
err_exit(dirty_volume_msg, opt.volume);
@ -1349,7 +1414,7 @@ static void mount_volume(unsigned long new_mntflag)
volume_size(vol, vol->nr_clusters));
}
struct ntfs_walk_cluster backup_clusters = { NULL, NULL };
static struct ntfs_walk_cluster backup_clusters = { NULL, NULL };
static int device_offset_valid(int fd, s64 ofs)
{
@ -1476,21 +1541,68 @@ static s64 open_image(void)
if ((fd_in = open(opt.volume, O_RDONLY)) == -1)
perr_exit("failed to open image");
}
if (read_all(&fd_in, &image_hdr, sizeof(image_hdr)) == -1)
if (read_all(&fd_in, &image_hdr, NTFSCLONE_IMG_HEADER_SIZE_OLD) == -1)
perr_exit("read_all");
if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0)
err_exit("Input file is not an image! (invalid magic)\n");
if (image_hdr.major_ver < NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE) {
image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
#if (__BYTE_ORDER == __BIG_ENDIAN)
Printf("Old image format detected. If the image was created "
"on a little endian architecture it will not "
"work. Use a more recent version of "
"ntfsclone to recreate the image.\n");
image_hdr.cluster_size = cpu_to_le32(image_hdr.cluster_size);
image_hdr.device_size = cpu_to_sle64(image_hdr.device_size);
image_hdr.nr_clusters = cpu_to_sle64(image_hdr.nr_clusters);
image_hdr.inuse = cpu_to_sle64(image_hdr.inuse);
#endif
image_hdr.offset_to_image_data =
const_cpu_to_le32((sizeof(image_hdr) + 7) & ~7);
image_is_host_endian = TRUE;
} else {
typeof(image_hdr.offset_to_image_data) offset_to_image_data;
int delta;
return image_hdr.device_size;
if (image_hdr.major_ver > NTFSCLONE_IMG_VER_MAJOR)
err_exit("Do not know how to handle image format "
"version %d.%d. Please obtain a "
"newer version of ntfsclone.\n",
image_hdr.major_ver,
image_hdr.minor_ver);
/* Read the image header data offset. */
if (read_all(&fd_in, &offset_to_image_data,
sizeof(offset_to_image_data)) == -1)
perr_exit("read_all");
image_hdr.offset_to_image_data =
le32_to_cpu(offset_to_image_data);
/*
* Read any fields from the header that we have not read yet so
* that the input stream is positioned correctly. This means
* we can support future minor versions that just extend the
* header in a backwards compatible way.
*/
delta = offset_to_image_data - (NTFSCLONE_IMG_HEADER_SIZE_OLD +
sizeof(image_hdr.offset_to_image_data));
if (delta > 0) {
char *dummy_buf;
dummy_buf = malloc(delta);
if (!dummy_buf)
perr_exit("malloc dummy_buffer");
if (read_all(&fd_in, dummy_buf, delta) == -1)
perr_exit("read_all");
}
}
return sle64_to_cpu(image_hdr.device_size);
}
static s64 open_volume(void)
{
s64 device_size;
mount_volume(MS_RDONLY);
mount_volume(NTFS_MNT_RDONLY);
device_size = ntfs_device_size_get(vol->dev, 1);
if (device_size <= 0)
@ -1509,12 +1621,14 @@ static s64 open_volume(void)
static void initialise_image_hdr(s64 device_size, s64 inuse)
{
memcpy(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE);
image_hdr.major_ver = vol->major_ver;
image_hdr.minor_ver = vol->minor_ver;
image_hdr.cluster_size = vol->cluster_size;
image_hdr.device_size = device_size;
image_hdr.nr_clusters = vol->nr_clusters;
image_hdr.inuse = inuse;
image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
image_hdr.cluster_size = cpu_to_le32(vol->cluster_size);
image_hdr.device_size = cpu_to_sle64(device_size);
image_hdr.nr_clusters = cpu_to_sle64(vol->nr_clusters);
image_hdr.inuse = cpu_to_sle64(inuse);
image_hdr.offset_to_image_data = cpu_to_le32((sizeof(image_hdr) + 7) &
~7);
}
static void check_output_device(s64 input_size)
@ -1611,10 +1725,11 @@ static void check_dest_free_space(u64 src_bytes)
{
u64 dest_bytes;
struct statvfs stvfs;
struct stat st;
if (opt.metadata || opt.blkdev_out || opt.std_out)
return;
/*
/*
* TODO: save_image needs a bit more space than src_bytes
* due to the free space encoding overhead.
*/
@ -1623,11 +1738,18 @@ static void check_dest_free_space(u64 src_bytes)
strerror(errno));
return;
}
/* If file is a FIFO then there is no point in checking the size. */
if (!fstat(fd_out, &st)) {
if (S_ISFIFO(st.st_mode))
return;
} else
Printf("WARNING: fstat failed: %s\n", strerror(errno));
dest_bytes = (u64)stvfs.f_frsize * stvfs.f_bfree;
if (!dest_bytes)
dest_bytes = (u64)stvfs.f_bsize * stvfs.f_bfree;
if (dest_bytes < src_bytes)
err_exit("Destination doesn't have enough free space: "
"%llu MB < %llu MB\n",
@ -1652,11 +1774,13 @@ int main(int argc, char **argv)
if (opt.restore_image) {
device_size = open_image();
ntfs_size = image_hdr.nr_clusters * image_hdr.cluster_size;
ntfs_size = sle64_to_cpu(image_hdr.nr_clusters) *
le32_to_cpu(image_hdr.cluster_size);
} else {
device_size = open_volume();
ntfs_size = vol->nr_clusters * vol->cluster_size;
}
// FIXME: This needs to be the cluster size...
ntfs_size += 512; /* add backup boot sector */
if (opt.std_out) {
@ -1672,7 +1796,7 @@ int main(int argc, char **argv)
flags |= O_EXCL;
}
if ((fd_out = open(opt.output, flags, S_IRWXU)) == -1)
if ((fd_out = open(opt.output, flags, S_IRUSR | S_IWUSR)) == -1)
perr_exit("Opening file '%s' failed", opt.output);
if (!opt.save_image)
@ -1692,7 +1816,7 @@ int main(int argc, char **argv)
walk_clusters(vol, &backup_clusters);
compare_bitmaps(&lcn_bitmap);
print_disk_usage(vol->cluster_size, vol->nr_clusters, image.inuse);
print_disk_usage("", vol->cluster_size, vol->nr_clusters, image.inuse);
check_dest_free_space(vol->cluster_size * image.inuse);

View File

@ -492,7 +492,8 @@ int main(int argc, char *argv[])
utils_set_locale();
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol)
return 1;

View File

@ -56,7 +56,6 @@ struct match {
ATTR_TYPES type; /* Attribute type */
ntfschar *name; /* Attribute name */
int name_len; /* Length of attribute name */
u8 padding[4]; /* Unused: padding to 64 bit. */
};
#endif /* _NTFSCLUSTER_H_ */

View File

@ -1,10 +1,26 @@
/**
* ntfscmp - compare two NTFS volumes.
* ntfscmp - Part of the Linux-NTFS project.
*
* Copyright (c) 2005-2006 Szabolcs Szakacsits
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility is part of the Linux-NTFS project.
* This utility compare two NTFS volumes.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS
* distribution in the file COPYING); if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
@ -17,6 +33,9 @@
#include <errno.h>
#include <getopt.h>
#include <ntfs-3g/mst.h>
#include <ntfs-3g/support.h>
#include "utils.h"
/* #include "version.h" */
@ -37,7 +56,7 @@ static const char *hibernated_volume_msg =
"turned off properly\n";
struct {
static struct {
int debug;
int show_progress;
int verbose;
@ -55,7 +74,6 @@ struct progress_bar {
int resolution;
int flags;
float unit;
u8 padding[4]; /* Unused: padding to 64 bit. */
};
/* WARNING: don't modify the text, external tools grep for it */
@ -308,7 +326,7 @@ static inline s64 get_nr_mft_records(ntfs_volume *vol)
#define NTFSCMP_EXTENSION_RECORD 4
#define NTFSCMP_INODE_CLOSE_ERROR 5
const char *ntfscmp_errs[] = {
static const char *ntfscmp_errs[] = {
"OK",
"INODE_OPEN_ERROR",
"INODE_OPEN_IO_ERROR",
@ -385,7 +403,8 @@ static void print_attribute_name(char *name)
}
#define GET_ATTR_NAME(a) \
((ntfschar *)(((u8 *)(a)) + ((a)->name_offset))), ((a)->name_length)
((ntfschar *)(((u8 *)(a)) + le16_to_cpu((a)->name_offset))), \
((a)->name_length)
static void free_name(char **name)
{
@ -464,6 +483,119 @@ static void print_ctx(ntfs_attr_search_ctx *ctx)
free_name(&name);
}
static void print_differ(ntfs_attr *na)
{
print_na(na);
printf("content: DIFFER\n");
}
static int cmp_buffer(u8 *buf1, u8 *buf2, long long int size, ntfs_attr *na)
{
if (memcmp(buf1, buf2, size)) {
print_differ(na);
return -1;
}
return 0;
}
struct cmp_ia {
INDEX_ALLOCATION *ia;
INDEX_ALLOCATION *tmp_ia;
u8 *bitmap;
u8 *byte;
s64 bm_size;
};
static int setup_cmp_ia(ntfs_attr *na, struct cmp_ia *cia)
{
cia->bitmap = ntfs_attr_readall(na->ni, AT_BITMAP, na->name,
na->name_len, &cia->bm_size);
if (!cia->bitmap) {
perr_println("Failed to readall BITMAP");
return -1;
}
cia->byte = cia->bitmap;
cia->tmp_ia = cia->ia = ntfs_malloc(na->data_size);
if (!cia->tmp_ia)
goto free_bm;
if (ntfs_attr_pread(na, 0, na->data_size, cia->ia) != na->data_size) {
perr_println("Failed to pread INDEX_ALLOCATION");
goto free_ia;
}
return 0;
free_ia:
free(cia->ia);
free_bm:
free(cia->bitmap);
return -1;
}
static void cmp_index_allocation(ntfs_attr *na1, ntfs_attr *na2)
{
struct cmp_ia cia1, cia2;
int bit, ret1, ret2;
u32 ib_size;
if (setup_cmp_ia(na1, &cia1))
return;
if (setup_cmp_ia(na2, &cia2))
return;
/*
* FIXME: ia can be the same even if the bitmap sizes are different.
*/
if (cia1.bm_size != cia1.bm_size)
goto out;
if (cmp_buffer(cia1.bitmap, cia2.bitmap, cia1.bm_size, na1))
goto out;
if (cmp_buffer((u8 *)cia1.ia, (u8 *)cia2.ia, 0x18, na1))
goto out;
ib_size = le32_to_cpu(cia1.ia->index.allocated_size) + 0x18;
bit = 0;
while ((u8 *)cia1.tmp_ia < (u8 *)cia1.ia + na1->data_size) {
if (*cia1.byte & (1 << bit)) {
ret1 = ntfs_mst_post_read_fixup((NTFS_RECORD *)
cia1.tmp_ia, ib_size);
ret2 = ntfs_mst_post_read_fixup((NTFS_RECORD *)
cia2.tmp_ia, ib_size);
if (ret1 != ret2) {
print_differ(na1);
goto out;
}
if (ret1 == -1)
continue;
if (cmp_buffer(((u8 *)cia1.tmp_ia) + 0x18,
((u8 *)cia2.tmp_ia) + 0x18,
le32_to_cpu(cia1.ia->
index.index_length), na1))
goto out;
}
cia1.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia1.tmp_ia + ib_size);
cia2.tmp_ia = (INDEX_ALLOCATION *)((u8 *)cia2.tmp_ia + ib_size);
bit++;
if (bit > 7) {
bit = 0;
cia1.byte++;
}
}
out:
free(cia1.ia);
free(cia2.ia);
free(cia1.bitmap);
free(cia2.bitmap);
return;
}
static void cmp_attribute_data(ntfs_attr *na1, ntfs_attr *na2)
{
s64 pos;
@ -503,14 +635,8 @@ static void cmp_attribute_data(ntfs_attr *na1, ntfs_attr *na2)
exit(1);
}
if (memcmp(buf1, buf2, count1)) {
print_na(na1);
printf("content");
if (opt.verbose)
printf(" (len = %lld)", count1);
printf(": DIFFER\n");
if (cmp_buffer(buf1, buf2, count1, na1))
return;
}
}
err_printf("%s read overrun: ", __FUNCTION__);
@ -531,7 +657,7 @@ static int cmp_attribute_header(ATTR_RECORD *a1, ATTR_RECORD *a2)
/*
* FIXME: includes paddings which are not handled by ntfsinfo!
*/
header_size = a1->length;
header_size = le32_to_cpu(a1->length);
}
return memcmp(a1, a2, header_size);
@ -575,7 +701,10 @@ static void cmp_attribute(ntfs_attr_search_ctx *ctx1,
return;
}
cmp_attribute_data(na1, na2);
if (na1->type == AT_INDEX_ALLOCATION)
cmp_index_allocation(na1, na2);
else
cmp_attribute_data(na1, na2);
close_attribs:
ntfs_attr_close(na1);
@ -708,9 +837,11 @@ static int cmp_attributes(ntfs_inode *ni1, ntfs_inode *ni2)
old_atype1 = atype1;
old_ret1 = ret1;
if (!ret1 && (atype1 <= atype2 || ret2))
if (!ret1 && (le32_to_cpu(atype1) <= le32_to_cpu(atype2) ||
ret2))
ret1 = next_attr(ctx1, &atype1, &name1, &errno1);
if (!ret2 && (old_atype1 >= atype2 || old_ret1))
if (!ret2 && (le32_to_cpu(old_atype1) >= le32_to_cpu(atype2) ||
old_ret1))
ret2 = next_attr(ctx2, &atype2, &name2, &errno2);
print_attributes(ni1, atype1, atype2, name1, name2);
@ -724,14 +855,15 @@ static int cmp_attributes(ntfs_inode *ni1, ntfs_inode *ni2)
break;
}
if (ret2 || atype1 < atype2) {
if (ret2 || le32_to_cpu(atype1) < le32_to_cpu(atype2)) {
if (new_attribute(ctx1, prev_atype, prev_name)) {
print_ctx(ctx1);
printf("presence: EXISTS != MISSING\n");
set_prev(&prev_name, &prev_atype, name1, atype1);
set_prev(&prev_name, &prev_atype, name1,
atype1);
}
} else if (ret1 || atype1 > atype2) {
} else if (ret1 || le32_to_cpu(atype1) > le32_to_cpu(atype2)) {
if (new_attribute(ctx2, prev_atype, prev_name)) {
print_ctx(ctx2);
printf("presence: MISSING != EXISTS \n");
@ -829,7 +961,7 @@ static ntfs_volume *mount_volume(const char *volume)
"You must 'umount' it first.\n", volume);
}
vol = ntfs_mount(volume, MS_RDONLY);
vol = ntfs_mount(volume, NTFS_MNT_RDONLY);
if (vol == NULL) {
int err = errno;

View File

@ -1,30 +1,20 @@
.\" Copyright (c) 2004\-2005 Yura Pakhuchiy.
.\" Copyright (c) 2004\-2007 Yura Pakhuchiy.
.\" Copyright (c) 2005 Richard Russon.
.\" This file may be copied under the terms of the GNU Public License.
.\"
.TH NTFSCP 8 "November 2005" "ntfsprogs @VERSION@"
.TH NTFSCP 8 "September 2007" "ntfsprogs @VERSION@"
.SH NAME
ntfscp \- overwrite file on an NTFS volume.
ntfscp \- copy file to an NTFS volume.
.SH SYNOPSIS
.B ntfscp
[\fIoptions\fR] \fIdevice source_file destination\fR
\fBntfscp\fR [\fIoptions\fR] \fIdevice source_file destination\fR
.SH DESCRIPTION
.B ntfscp
will overwrite file on an NTFS volume. At present
.B ntfscp
can't create new files.
.B destination
can be either file or directory. In case if
.B destination
is directory specified by name then
.B source_file
is copied into this directory, in case if
.B destination
is directory and specified by inode number then unnamed data attribute is
created for this inode and
.B source_file
is copied into it (WARNING: it's unusual to have unnamed data streams in the
directories, think twice before specifying directory by inode number).
\fBntfscp\fR will copy file to an NTFS volume. \fIdestination\fR can be either
file or directory. In case if \fIdestination\fR is directory specified by name
then \fIsource_file\fR is copied into this directory, in case if
\fIdestination\fR is directory and specified by inode number then unnamed data
attribute is created for this inode and \fIsource_file\fR is copied into it
(WARNING: it's unusual to have unnamed data streams in the directories, think
twice before specifying directory by inode number).
.SH OPTIONS
Below is a summary of all the options that
.B ntfscp
@ -96,24 +86,19 @@ windows is C):
.sp
.RE
.SH BUGS
There are no known problems with
.BR ntfscp .
If you find a bug please send an email describing the problem to the
development team:
There are no known problems with \fBntfscp\fR. If you find a bug please send an
email describing the problem to the development team:
.br
.nh
linux\-ntfs\-dev@lists.sourceforge.net
.hy
.SH AUTHORS
.B ntfscp
was written by Yura Pakhuchiy, with contributions from Anton Altaparmakov.
\fBntfscp\fR was written by Yura Pakhuchiy, with contributions from Anton
Altaparmakov and Hil Liao.
.SH DEDICATION
With love to Marina Sapego.
.SH AVAILABILITY
.B ntfscp
is part of the
.B ntfsprogs
package and is available from:
\fBntfscp\fR is part of the \fBntfsprogs\fR package and is available from:
.br
.nh
http://www.linux\-ntfs.org/content/view/19/37

View File

@ -1,10 +1,11 @@
/**
* ntfscp - Part of the Linux-NTFS project.
*
* Copyright (c) 2004-2005 Yura Pakhuchiy
* Copyright (c) 2004-2007 Yura Pakhuchiy
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2006 Hil Liao
*
* This utility will overwrite files on NTFS volume.
* This utility will copy file to an NTFS volume.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -43,6 +44,9 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#include <ntfs-3g/types.h>
#include <ntfs-3g/attrib.h>
@ -69,7 +73,7 @@ struct options {
static const char *EXEC_NAME = "ntfscp";
static struct options opts;
volatile sig_atomic_t caught_terminate = 0;
static volatile sig_atomic_t caught_terminate = 0;
/**
* version - Print version information about the program
@ -80,9 +84,11 @@ volatile sig_atomic_t caught_terminate = 0;
*/
static void version(void)
{
ntfs_log_info("\n%s v%s (libntfs-3g) - Overwrite files on NTFS "
ntfs_log_info("\n%s v%s (libntfs-3g) - Copy file to an NTFS "
"volume.\n\n", EXEC_NAME, VERSION);
ntfs_log_info("Copyright (c) 2004-2005 Yura Pakhuchiy\n");
ntfs_log_info("Copyright (c) 2004-2007 Yura Pakhuchiy\n");
ntfs_log_info("Copyright (c) 2005 Anton Altaparmakov\n");
ntfs_log_info("Copyright (c) 2006 Hil Liao\n");
ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -179,7 +185,7 @@ static int parse_options(int argc, char **argv)
ntfs_log_error("Couldn't parse attribute.\n");
err++;
} else
opts.attribute = (ATTR_TYPES)attr;
opts.attribute = (ATTR_TYPES)cpu_to_le32(attr);
break;
case 'i':
opts.inode++;
@ -271,6 +277,34 @@ static void signal_handler(int arg __attribute__((unused)))
caught_terminate++;
}
/**
* Create a regular file under the given directory inode
*
* It is a wrapper function to ntfs_create(...)
*
* Return: the created file inode
*/
static ntfs_inode *ntfs_new_file(ntfs_inode *dir_ni,
const char *filename)
{
ntfschar *ufilename;
/* inode to the file that is being created */
ntfs_inode *ni;
int ufilename_len;
/* ntfs_mbstoucs(...) will allocate memory for ufilename if it's NULL */
ufilename = NULL;
ufilename_len = ntfs_mbstoucs_libntfscompat(filename, &ufilename, 0);
if (ufilename_len == -1) {
ntfs_log_perror("ERROR: Failed to convert '%s' to unicode",
filename);
return NULL;
}
ni = ntfs_create(dir_ni, ufilename, ufilename_len, S_IFREG);
free(ufilename);
return ni;
}
/**
* main - Begin here
*
@ -313,15 +347,17 @@ int main(int argc, char *argv[])
}
if (opts.noaction)
flags = MS_RDONLY;
flags = NTFS_MNT_RDONLY;
if (opts.force)
flags |= NTFS_MNT_FORCE;
vol = utils_mount_volume(opts.device, flags, opts.force);
vol = utils_mount_volume(opts.device, flags);
if (!vol) {
ntfs_log_perror("ERROR: couldn't mount volume");
return 1;
}
if ((vol->flags & VOLUME_IS_DIRTY) && (!opts.force))
if (NVolWasDirty(vol) && !opts.force)
goto umount;
{
@ -353,45 +389,113 @@ int main(int argc, char *argv[])
} else
out = ntfs_pathname_to_inode(vol, NULL, opts.dest_file);
if (!out) {
ntfs_log_perror("ERROR: Couldn't open destination file");
goto close_src;
}
if ((le16_to_cpu(out->mrec->flags) & MFT_RECORD_IS_DIRECTORY) &&
!opts.inode){
/*
* @out is directory and it was specified by pathname, add
* filename to path and reopen inode.
*/
char *filename, *new_dest_file;
/* Copy the file if the dest_file's parent dir can be opened. */
char *parent_dirname;
char *filename;
ntfs_inode *dir_ni;
ntfs_inode *ni;
int dest_path_len;
char *dirname_last_whack;
/*
* FIXME: There should exist more beautiful way to get filename.
* Not sure that it will work in windows, but I don't think that
* someone will use ntfscp under windows.
*/
filename = strrchr(opts.src_file, '/');
if (filename)
filename++;
else
filename = opts.src_file;
/* Add 2 bytes for '/' and null-terminator. */
new_dest_file = malloc(strlen(opts.dest_file) +
strlen(filename) + 2);
if (!new_dest_file) {
ntfs_log_perror("ERROR: malloc() failed");
goto close_dst;
}
strcpy(new_dest_file, opts.dest_file);
strcat(new_dest_file, "/");
strcat(new_dest_file, filename);
ntfs_inode_close(out);
out = ntfs_pathname_to_inode(vol, NULL, new_dest_file);
free(new_dest_file);
if (!out) {
ntfs_log_perror("ERROR: Failed to open destination "
"file");
filename = basename(opts.dest_file);
dest_path_len = strlen(opts.dest_file);
parent_dirname = strdup(opts.dest_file);
if (!parent_dirname) {
ntfs_log_perror("strdup() failed");
goto close_src;
}
dirname_last_whack = strrchr(parent_dirname, '/');
if (dirname_last_whack) {
dirname_last_whack[1] = 0;
dir_ni = ntfs_pathname_to_inode(vol, NULL,
parent_dirname);
} else {
ntfs_log_verbose("Target path does not contain '/'. "
"Using root directory as parent.\n");
dir_ni = ntfs_inode_open(vol, FILE_root);
}
if (dir_ni) {
if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
/* Remove the last '/' for estetic reasons. */
dirname_last_whack[0] = 0;
ntfs_log_error("The file '%s' already exists "
"and is not a directory. "
"Aborting.\n", parent_dirname);
free(parent_dirname);
ntfs_inode_close(dir_ni);
goto close_src;
}
ntfs_log_verbose("Creating a new file '%s' under '%s'"
"\n", filename, parent_dirname);
ni = ntfs_new_file(dir_ni, filename);
ntfs_inode_close(dir_ni);
if (!ni) {
ntfs_log_perror("Failed to create '%s' under "
"'%s'", filename,
parent_dirname);
free(parent_dirname);
goto close_src;
}
out = ni;
} else {
ntfs_log_perror("ERROR: Couldn't open '%s'",
parent_dirname);
free(parent_dirname);
goto close_src;
}
free(parent_dirname);
}
/* The destination is a directory. */
if ((out->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !opts.inode) {
char *filename;
char *overwrite_filename;
int overwrite_filename_len;
ntfs_inode *ni;
ntfs_inode *dir_ni;
int filename_len;
int dest_dirname_len;
filename = basename(opts.src_file);
dir_ni = out;
filename_len = strlen(filename);
dest_dirname_len = strlen(opts.dest_file);
overwrite_filename_len = filename_len+dest_dirname_len + 2;
overwrite_filename = malloc(overwrite_filename_len);
if (!overwrite_filename) {
ntfs_log_perror("ERROR: Failed to allocate %i bytes "
"memory for the overwrite filename",
overwrite_filename_len);
ntfs_inode_close(out);
goto close_src;
}
strcpy(overwrite_filename, opts.dest_file);
if (opts.dest_file[dest_dirname_len - 1] != '/') {
strcat(overwrite_filename, "/");
}
strcat(overwrite_filename, filename);
ni = ntfs_pathname_to_inode(vol, NULL, overwrite_filename);
/* Does a file with the same name exist in the dest dir? */
if (ni) {
ntfs_log_verbose("Destination path has a file with "
"the same name\nOverwriting the file "
"'%s'\n", overwrite_filename);
ntfs_inode_close(out);
out = ni;
} else {
ntfs_log_verbose("Creating a new file '%s' under "
"'%s'\n", filename, opts.dest_file);
ni = ntfs_new_file(dir_ni, filename);
ntfs_inode_close(dir_ni);
if (!ni) {
ntfs_log_perror("ERROR: Failed to create the "
"destination file under '%s'",
opts.dest_file);
free(overwrite_filename);
goto close_src;
}
out = ni;
}
free(overwrite_filename);
}
attr_name = ntfs_str2ucs(opts.attr_name, &attr_name_len);
@ -425,7 +529,7 @@ int main(int argc, char *argv[])
ntfs_log_verbose("Old file size: %lld\n", na->data_size);
if (na->data_size != new_size) {
if (ntfs_attr_truncate(na, new_size)) {
if (__ntfs_attr_truncate(na, new_size, FALSE)) {
ntfs_log_perror("ERROR: Couldn't resize attribute");
goto close_attr;
}

View File

@ -2,7 +2,8 @@
* ntfsdecrypt - Decrypt ntfs encrypted files. Part of the Linux-NTFS project.
*
* Copyright (c) 2005 Yuval Fledel
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2005-2007 Anton Altaparmakov
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility will decrypt files and print the decrypted data on the standard
* output.
@ -25,10 +26,6 @@
#include "config.h"
#if !defined(HAVE_GCRYPT_H) || !defined(HAVE_GNUTLS_PKCS12_H)
#error A required header file is missing. Aborting.
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
@ -56,12 +53,8 @@
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_GCRYPT_H
#include <gcrypt.h>
#endif
#ifdef HAVE_GNUTLS_PKCS12_H
#include <gnutls/pkcs12.h>
#endif
#include <ntfs-3g/types.h>
#include <ntfs-3g/attrib.h>
@ -75,6 +68,19 @@
typedef gcry_sexp_t ntfs_rsa_private_key;
#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"
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)
*
@ -102,14 +108,14 @@ typedef enum {
*/
typedef struct {
gcry_cipher_hd_t gcry_cipher_hd;
u32 alg_id;
le32 alg_id;
u8 *key_data;
gcry_cipher_hd_t *des_gcry_cipher_hd_ptr;
} ntfs_fek;
/* DESX-MS128 implementation for libgcrypt. */
static gcry_module_t ntfs_desx_module;
static unsigned ntfs_desx_algorithm_id = -1;
static int ntfs_desx_algorithm_id = -1;
typedef struct {
u64 in_whitening, out_whitening;
@ -447,19 +453,34 @@ static ntfs_rsa_private_key ntfs_rsa_private_key_import_from_gnutls(
return (ntfs_rsa_private_key)rsa_key;
}
/**
* ntfs_rsa_private_key_release
*/
static void ntfs_rsa_private_key_release(ntfs_rsa_private_key rsa_key)
{
gcry_sexp_release((gcry_sexp_t)rsa_key);
}
/**
* ntfs_pkcs12_extract_rsa_key
*/
static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
char *password)
char *password, char *thumbprint, int thumbprint_size,
NTFS_DF_TYPES *df_type)
{
int err, bag_index, flags;
gnutls_datum_t dpfx, dkey;
gnutls_pkcs12_t pkcs12;
gnutls_pkcs12_bag_t bag;
gnutls_x509_privkey_t pkey;
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 rsa_key = NULL;
char purpose_oid[100];
size_t purpose_oid_size = sizeof(purpose_oid);
size_t tp_size = thumbprint_size;
BOOL have_thumbprint = FALSE;
*df_type = DF_TYPE_UNKNOWN;
/* Create a pkcs12 structure. */
err = gnutls_pkcs12_init(&pkcs12);
if (err) {
@ -475,7 +496,7 @@ static ntfs_rsa_private_key ntfs_pkcs12_extract_rsa_key(u8 *pfx, int pfx_size,
ntfs_log_error("Failed to convert the PFX file from DER to "
"native PKCS#12 format: %s\n",
gnutls_strerror(err));
goto out;
goto err;
}
/*
* Verify that the password is correct and that the key file has not
@ -492,9 +513,9 @@ retry_verify:
password = NULL;
goto retry_verify;
}
ntfs_log_error("Failed to verify the MAC (%s). Is the "
ntfs_log_error("Failed to verify the MAC: %s Is the "
"password correct?\n", gnutls_strerror(err));
goto out;
goto err;
}
for (bag_index = 0; ; bag_index++) {
err = gnutls_pkcs12_bag_init(&bag);
@ -502,29 +523,31 @@ retry_verify:
ntfs_log_error("Failed to initialize PKCS#12 Bag "
"structure: %s\n",
gnutls_strerror(err));
goto out;
goto err;
}
err = gnutls_pkcs12_get_bag(pkcs12, bag_index, bag);
if (err) {
if (err == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
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 bag_out;
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 bag_out;
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 bag_out;
goto err;
}
flags = 0;
switch (err) {
@ -535,14 +558,14 @@ check_again:
if (err < 0) {
ntfs_log_error("Failed to obtain Bag data: "
"%s\n", gnutls_strerror(err));
goto bag_out;
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 bag_out;
goto err;
}
/* Decrypt the private key into GNU TLS format. */
err = gnutls_x509_privkey_import_pkcs8(pkey, &dkey,
@ -552,7 +575,7 @@ check_again:
"key from DER to GNU TLS "
"format: %s\n",
gnutls_strerror(err));
goto key_out;
goto err;
}
#if 0
/*
@ -580,38 +603,106 @@ check_again:
#endif
/* Convert the private key to our internal format. */
rsa_key = ntfs_rsa_private_key_import_from_gnutls(pkey);
goto key_out;
if (!rsa_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 bag_out;
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))
*df_type = DF_TYPE_DRF;
else if (!strcmp(purpose_oid,
NTFS_EFS_CERT_PURPOSE_OID_DDF))
*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, 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,
thumbprint_size);
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);
}
key_out:
gnutls_x509_privkey_deinit(pkey);
bag_out:
gnutls_pkcs12_bag_deinit(bag);
out:
gnutls_pkcs12_deinit(pkcs12);
err:
if (rsa_key && (err || *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_rsa_private_key_release
*/
static void ntfs_rsa_private_key_release(ntfs_rsa_private_key rsa_key)
{
gcry_sexp_release((gcry_sexp_t)rsa_key);
}
/**
* ntfs_buffer_reverse -
*
@ -972,23 +1063,27 @@ static inline BOOL ntfs_des_test(void)
/**
* ntfs_fek_import_from_raw
*/
static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
unsigned fek_size __attribute__((unused)))
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;
// TODO: Sanity checking of sizes and offsets.
key_size = le32_to_cpup(fek_buf);
//ntfs_log_debug("key_size 0x%x\n", key_size);
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 = *(u32*)(fek_buf + 8);
fek->alg_id = *(le32*)(fek_buf + 8);
//ntfs_log_debug("alg_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);
@ -1040,7 +1135,8 @@ static ntfs_fek *ntfs_fek_import_from_raw(u8 *fek_buf,
}
if (key_size != wanted_key_size) {
ntfs_log_error("%s key of %u bytes but needed size is %u "
"bytes, assuming corrupt key. Aborting.\n",
"bytes, assuming corrupt or incorrect key. "
"Aborting.\n",
gcry_cipher_algo_name(gcry_algo),
(unsigned)key_size, (unsigned)wanted_key_size);
err = EIO;
@ -1084,7 +1180,8 @@ static void ntfs_fek_release(ntfs_fek *fek)
* ntfs_df_array_fek_get
*/
static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
ntfs_rsa_private_key rsa_key)
ntfs_rsa_private_key rsa_key, char *thumbprint,
int thumbprint_size)
{
EFS_DF_HEADER *df_header;
EFS_DF_CREDENTIAL_HEADER *df_cred;
@ -1094,14 +1191,41 @@ static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
u32 df_count, fek_size;
unsigned i;
df_header = (EFS_DF_HEADER*)(df_array + 1);
df_count = le32_to_cpu(df_array->df_count);
for (i = 0; i < df_count; i++) {
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),
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. */
@ -1116,8 +1240,6 @@ static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
} else
ntfs_log_error("Failed to decrypt the file "
"encryption key.\n");
df_header = (EFS_DF_HEADER*)((u8*)df_header +
le32_to_cpu(df_header->df_length));
}
return NULL;
}
@ -1126,10 +1248,11 @@ static ntfs_fek *ntfs_df_array_fek_get(EFS_DF_ARRAY_HEADER *df_array,
* ntfs_inode_fek_get -
*/
static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
ntfs_rsa_private_key rsa_key)
ntfs_rsa_private_key rsa_key, char *thumbprint,
int thumbprint_size, NTFS_DF_TYPES df_type)
{
EFS_ATTR_HEADER *efs;
EFS_DF_ARRAY_HEADER *df_array;
EFS_DF_ARRAY_HEADER *df_array = NULL;
ntfs_fek *fek = NULL;
/* Obtain the $EFS contents. */
@ -1138,17 +1261,29 @@ static ntfs_fek *ntfs_inode_fek_get(ntfs_inode *inode,
ntfs_log_perror("Failed to read $EFS attribute");
return NULL;
}
/* Iterate through the DDFs & DRFs until we obtain a key. */
if (efs->offset_to_ddf_array) {
df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
le32_to_cpu(efs->offset_to_ddf_array));
fek = ntfs_df_array_fek_get(df_array, rsa_key);
}
if (!fek && efs->offset_to_drf_array) {
df_array = (EFS_DF_ARRAY_HEADER*)((u8*)efs +
le32_to_cpu(efs->offset_to_drf_array));
fek = ntfs_df_array_fek_get(df_array, rsa_key);
}
/*
* Depending on whether the key is a normal key or a data recovery key,
* iterate through the DDF or DRF array, respectively.
*/
if (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 (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, thumbprint,
thumbprint_size);
free(efs);
return fek;
}
@ -1179,18 +1314,20 @@ static int ntfs_fek_decrypt_sector(ntfs_fek *fek, u8 *data, const u64 offset)
}
/* Apply the IV. */
if (fek->alg_id == CALG_AES_256) {
((u64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
((u64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
((le64*)data)[0] ^= cpu_to_le64(0x5816657be9161312ULL + offset);
((le64*)data)[1] ^= cpu_to_le64(0x1989adbe44918961ULL + offset);
} else {
/* All other algos (Des, 3Des, DesX) use the same IV. */
((u64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
((le64*)data)[0] ^= cpu_to_le64(0x169119629891ad13ULL + offset);
}
return 512;
}
/**
* ntfs_cat_decrypt
* TODO:
* ntfs_cat_decrypt - Decrypt the contents of an encrypted file to stdout.
* @inode: An encrypted file's inode structure, as obtained by
* ntfs_inode_open().
* @fek: A file encryption key. As obtained by ntfs_inode_fek_get().
*/
static int ntfs_cat_decrypt(ntfs_inode *inode, ntfs_fek *fek)
{
@ -1273,6 +1410,8 @@ int main(int argc, char *argv[])
ntfs_fek *fek;
unsigned pfx_size;
int res;
NTFS_DF_TYPES df_type;
char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE];
ntfs_log_set_handler(ntfs_log_handler_stderr);
@ -1301,19 +1440,20 @@ int main(int argc, char *argv[])
return 1;
}
/* Obtain the user's private RSA key from the key file. */
rsa_key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, password);
rsa_key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, password,
thumbprint, sizeof(thumbprint), &df_type);
/* Destroy the password. */
memset(password, 0, strlen(password));
/* No longer need the pfx file contents. */
free(pfx_buf);
if (!rsa_key) {
ntfs_log_error("Failed to extract the private RSA key. Did "
"you perhaps mistype the password?\n");
ntfs_log_error("Failed to extract the private RSA key.\n");
ntfs_crypto_deinit();
return 1;
}
/* Mount the ntfs volume. */
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol) {
ntfs_log_error("Failed to mount ntfs volume. Aborting.\n");
ntfs_rsa_private_key_release(rsa_key);
@ -1333,7 +1473,8 @@ int main(int argc, char *argv[])
return 1;
}
/* Obtain the file encryption key of the encrypted file. */
fek = ntfs_inode_fek_get(inode, rsa_key);
fek = ntfs_inode_fek_get(inode, rsa_key, thumbprint,
sizeof(thumbprint), df_type);
ntfs_rsa_private_key_release(rsa_key);
if (fek) {
res = ntfs_cat_decrypt(inode, fek);

View File

@ -198,7 +198,7 @@ static int logfile_open(BOOL is_volume, const char *filename,
ntfs_inode *ni;
ntfs_attr *na;
vol = ntfs_mount(filename, MS_RDONLY);
vol = ntfs_mount(filename, NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC);
if (!vol)
log_err_exit(NULL, "Failed to mount %s: %s\n",
filename, strerror(errno));

View File

@ -14,14 +14,14 @@ is a utility that fixes some common NTFS problems.
.B ntfsfix
is
.B NOT
a Linux version of chkdsk. It only repairs some fundamental NTFS
a Linux version of chkdsk. It only repairs some fundamental NTFS
inconsistencies, resets the NTFS journal file and schedules an NTFS consistency
check for the first boot into Windows.
.sp
You may run
.B ntfsfix
on an NTFS volume if you think it was damaged by Windows or some other way
and it can't be mounted.
and it cannot be mounted.
.SH OPTIONS
Below is a summary of all the options that
.B ntfsfix

View File

@ -1,8 +1,9 @@
/**
* ntfsfix - Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2006 Anton Altaparmakov.
* Copyright (c) 2002-2006 Szabolcs Szakacsits.
* Copyright (c) 2000-2006 Anton Altaparmakov
* Copyright (c) 2002-2006 Szabolcs Szakacsits
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility fixes some common NTFS problems, resets the NTFS journal file
* and schedules an NTFS consistency check for the first boot into Windows.
@ -83,10 +84,8 @@ switch if you want to be able to build the NTFS utilities."
static const char *EXEC_NAME = "ntfsfix";
static const char *OK = "OK\n";
static const char *FAILED = "FAILED\n";
static BOOL vol_is_dirty = FALSE;
static BOOL journal_is_empty = FALSE;
struct {
static struct {
char *volume;
} opt;
@ -119,8 +118,9 @@ static void version(void)
{
ntfs_log_info("%s v%s\n\n"
"Attempt to fix an NTFS partition.\n\n"
"Copyright (c) 2000-2006 Anton Altaparmakov.\n"
"Copyright (c) 2002-2006 Szabolcs Szakacsits.\n\n",
"Copyright (c) 2000-2006 Anton Altaparmakov\n"
"Copyright (c) 2002-2006 Szabolcs Szakacsits\n"
"Copyright (c) 2007 Yura Pakhuchiy\n\n",
EXEC_NAME, VERSION);
ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
exit(1);
@ -171,7 +171,7 @@ static void parse_options(int argc, char **argv)
/**
* OLD_ntfs_volume_set_flags
*/
static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const u16 flags)
static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const le16 flags)
{
MFT_RECORD *m = NULL;
ATTR_RECORD *a;
@ -228,7 +228,7 @@ static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const u16 flags)
goto err_out;
}
/* Set the volume flags. */
vol->flags = c->flags = cpu_to_le16(flags);
vol->flags = c->flags = flags;
if (ntfs_mft_record_write(vol, FILE_Volume, m)) {
ntfs_log_perror("Error writing $Volume");
goto err_out;
@ -246,56 +246,24 @@ err_exit:
*/
static int set_dirty_flag(ntfs_volume *vol)
{
u16 flags;
le16 flags;
if (vol_is_dirty == TRUE)
if (NVolWasDirty(vol))
return 0;
ntfs_log_info("Setting required flags on partition... ");
/*
* Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
* and fix it for us.
*/
flags = vol->flags | VOLUME_IS_DIRTY;
/* If NTFS volume version >= 2.0 then set mounted on NT4 flag. */
if (vol->major_ver >= 2)
flags |= VOLUME_MOUNTED_ON_NT4;
if (OLD_ntfs_volume_set_flags(vol, flags)) {
ntfs_log_info(FAILED);
ntfs_log_error("Error setting volume flags.\n");
return -1;
}
vol->flags = flags;
NVolSetWasDirty(vol);
ntfs_log_info(OK);
vol_is_dirty = TRUE;
return 0;
}
/**
* set_dirty_flag_mount
*/
static int set_dirty_flag_mount(ntfs_volume *vol)
{
u16 flags;
if (vol_is_dirty == TRUE)
return 0;
ntfs_log_info("Setting required flags on partition... ");
/*
* Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
* and fix it for us.
*/
flags = vol->flags | VOLUME_IS_DIRTY;
/* If NTFS volume version >= 2.0 then set mounted on NT4 flag. */
if (vol->major_ver >= 2)
flags |= VOLUME_MOUNTED_ON_NT4;
if (ntfs_volume_write_flags(vol, flags)) {
ntfs_log_info(FAILED);
ntfs_log_error("Error setting volume flags.\n");
return -1;
}
ntfs_log_info(OK);
vol_is_dirty = TRUE;
return 0;
}
@ -304,9 +272,8 @@ static int set_dirty_flag_mount(ntfs_volume *vol)
*/
static int empty_journal(ntfs_volume *vol)
{
if (journal_is_empty == TRUE)
if (NVolLogFileEmpty(vol))
return 0;
ntfs_log_info("Going to empty the journal ($LogFile)... ");
if (ntfs_logfile_reset(vol)) {
ntfs_log_info(FAILED);
@ -314,7 +281,6 @@ static int empty_journal(ntfs_volume *vol)
return -1;
}
ntfs_log_info(OK);
journal_is_empty = TRUE;
return 0;
}
@ -399,7 +365,7 @@ static int fix_mftmirr(ntfs_volume *vol)
use_mirr = FALSE;
mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
if (mrec->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec)) {
if (ntfs_is_baad_record(mrec->magic)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFT error: Incomplete multi "
"sector transfer detected in "
@ -407,7 +373,7 @@ static int fix_mftmirr(ntfs_volume *vol)
")-:\n", s);
goto error_exit;
}
if (!ntfs_is_mft_recordp(mrec)) {
if (!ntfs_is_mft_record(mrec->magic)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFT error: Invalid mft "
"record for %s.\nCannot "
@ -417,14 +383,14 @@ static int fix_mftmirr(ntfs_volume *vol)
}
mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
if (mrec2->flags & MFT_RECORD_IN_USE) {
if (ntfs_is_baad_recordp(mrec2)) {
if (ntfs_is_baad_record(mrec2->magic)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFTMirr error: Incomplete "
"multi sector transfer "
"detected in %s.\n", s);
goto error_exit;
}
if (!ntfs_is_mft_recordp(mrec2)) {
if (!ntfs_is_mft_record(mrec2->magic)) {
ntfs_log_info(FAILED);
ntfs_log_error("$MFTMirr error: Invalid mft "
"record for %s.\n", s);
@ -432,7 +398,7 @@ static int fix_mftmirr(ntfs_volume *vol)
}
/* $MFT is corrupt but $MFTMirr is ok, use $MFTMirr. */
if (!(mrec->flags & MFT_RECORD_IN_USE) &&
!ntfs_is_mft_recordp(mrec))
!ntfs_is_mft_record(mrec->magic))
use_mirr = TRUE;
}
if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
@ -476,13 +442,13 @@ static int fix_mount(void)
ntfs_log_info("Attempting to correct errors... ");
dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops, NULL);
dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
NULL);
if (!dev) {
ntfs_log_info(FAILED);
ntfs_log_perror("Failed to allocate device");
return -1;
}
vol = ntfs_volume_startup(dev, 0);
if (!vol) {
ntfs_log_info(FAILED);
@ -491,17 +457,12 @@ static int fix_mount(void)
ntfs_device_free(dev);
return -1;
}
if (fix_mftmirr(vol) < 0)
goto error_exit;
/* FIXME: Will this fail? Probably... */
if (set_dirty_flag(vol) < 0)
goto error_exit;
if (empty_journal(vol) < 0)
goto error_exit;
ret = 0;
error_exit:
/* ntfs_umount() will invoke ntfs_device_free() for us. */
@ -551,7 +512,8 @@ int main(int argc, char **argv)
exit(1);
}
}
/* So the unmount does not clear it again. */
NVolSetWasDirty(vol);
/* Check NTFS version is ok for us (in $Volume) */
ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
vol->minor_ver);
@ -559,22 +521,13 @@ int main(int argc, char **argv)
ntfs_log_error("Error: Unknown NTFS version.\n");
goto error_exit;
}
if (set_dirty_flag_mount(vol) < 0)
goto error_exit;
if (empty_journal(vol) < 0)
goto error_exit;
if (vol->major_ver >= 3) {
/* FIXME: If on NTFS 3.0+, check for presence of the usn journal and
disable it (if present) as Win2k might be unhappy otherwise and Bad
Things(TM) could happen depending on what applications are actually
using it for. */
/*
* FIXME: If on NTFS 3.0+, check for presence of the usn
* journal and stamp it if present.
*/
}
/* FIXME: Should we be marking the quota out of date, too? */
/* FIXME: We should be marking the quota out of date, too. */
/* That's all for now! */
ntfs_log_info("NTFS partition %s was processed successfully.\n",
vol->dev->d_name);

File diff suppressed because it is too large Load Diff

View File

@ -326,7 +326,7 @@ static int change_label(ntfs_volume *vol, unsigned long mnt_flags, char *label,
"allowed. Truncating excess characters.\n",
(unsigned)(0x100 / sizeof(ntfschar)));
label_len = 0x100;
new_label[label_len / sizeof(ntfschar)] = cpu_to_le16(L'\0');
new_label[label_len / sizeof(ntfschar)] = 0;
}
if (a) {
if (resize_resident_attribute_value(ctx->mrec, a, label_len)) {
@ -394,8 +394,9 @@ int main(int argc, char **argv)
if (!opts.label)
opts.noaction++;
vol = utils_mount_volume(opts.device, opts.noaction ? MS_RDONLY : 0,
opts.force);
vol = utils_mount_volume(opts.device,
(opts.noaction ? NTFS_MNT_RDONLY : 0) |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol)
return 1;

View File

@ -651,7 +651,8 @@ int main(int argc, char **argv)
utils_set_locale();
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol) {
// FIXME: Print error... (AIA)
return 2;

View File

@ -313,7 +313,7 @@ int main(int argc, char **argv)
/* Mount the device. */
if (opts.no_action) {
ntfs_log_quiet("Running in READ-ONLY mode!\n");
ul = MS_RDONLY;
ul = NTFS_MNT_RDONLY;
} else
ul = 0;
vol = ntfs_mount(dev_name, ul);

View File

@ -746,7 +746,8 @@ static s64 move_datarun(ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
}
/**
* move_attribute
* move_attribute -
*
* > 0 Bytes moved / size to be moved
* = 0 Nothing to do
* < 0 Error
@ -791,7 +792,8 @@ static s64 move_attribute(ntfs_volume *vol, ntfs_inode *ino, ATTR_RECORD *rec,
}
/**
* move_file
* move_file -
*
* > 0 Bytes moved / size to be moved
* = 0 Nothing to do
* < 0 Error
@ -873,9 +875,11 @@ int main(int argc, char *argv[])
utils_set_locale();
if (opts.noaction)
flags |= MS_RDONLY;
flags |= NTFS_MNT_RDONLY;
if (opts.force)
flags |= NTFS_MNT_FORCE;
vol = utils_mount_volume(opts.device, flags, opts.force);
vol = utils_mount_volume(opts.device, flags);
if (!vol) {
ntfs_log_info("!vol\n");
return 1;
@ -889,10 +893,7 @@ int main(int argc, char *argv[])
count = move_file(vol, inode, opts.location, 0);
if ((count > 0) && (!opts.nodirty)) {
if (ntfs_volume_write_flags(vol, vol->flags | VOLUME_IS_DIRTY) <
0) {
ntfs_log_error("Couldn't mark volume dirty\n");
}
NVolSetWasDirty(vol);
ntfs_log_info("Relocated %lld bytes\n", count);
}
if (count >= 0)

View File

@ -39,7 +39,6 @@ struct options {
int verbose; /* Extra output */
int noaction; /* Do not write to disk */
int nodirty; /* Do not mark volume dirty */
u8 padding[4]; /* Unused: alignment to 64 bit. */
};
#endif /* _NTFSMOVE_H_ */

View File

@ -1,9 +1,10 @@
.\" Copyright (c) 2002\-2005 Richard Russon.
.\" Copyright (c) 2002\-2003 Anton Altaparmakov.
.\" Copyright (c) 2005\-2006 Szabolcs Szakacsits.
.\" Copyright (c) 2005\-2007 Yura Pakhuchiy.
.\" This file may be copied under the terms of the GNU Public License.
.\"
.TH NTFSPROGS 8 "April 2006" "ntfsprogs @VERSION@"
.TH NTFSPROGS 8 "September 2007" "ntfsprogs @VERSION@"
.SH NAME
ntfsprogs \- tools for doing neat things with NTFS
.SH OVERVIEW
@ -28,7 +29,7 @@ available for free and come with full source code.
\- Compare two NTFS filesystems and tell the differences.
.PP
.BR ntfscp (8)
\- Overwrite a file on an NTFS.
\- Copy a file to an NTFS volume.
.PP
.BR ntfsfix (8)
\- Check and fix some common errors, clear the LogFile and make Windows
@ -68,5 +69,6 @@ These manual pages can be viewed online at:
http://man.linux-ntfs.org/
.hy
.SH SEE ALSO
.BR libntfs (8),
.BR libntfs\-gnomevfs (8)

View File

@ -4,6 +4,7 @@
* Copyright (c) 2002-2006 Szabolcs Szakacsits
* Copyright (c) 2002-2005 Anton Altaparmakov
* Copyright (c) 2002-2003 Richard Russon
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility will resize an NTFS volume without data loss.
*
@ -126,7 +127,7 @@ static const char *many_bad_sectors_msg =
"* other reason. We suggest to get a replacement disk as soon as possible. *\n"
"***************************************************************************\n";
struct {
static struct {
int verbose;
int debug;
int ro_flag;
@ -141,7 +142,6 @@ struct {
struct bitmap {
s64 size;
u8 *bm;
u8 padding[4]; /* Unused: padding to 64 bit. */
};
#define NTFS_PROGBAR 0x0001
@ -153,7 +153,6 @@ struct progress_bar {
int resolution;
int flags;
float unit;
u8 padding[4]; /* Unused: padding to 64 bit. */
};
struct llcn_t {
@ -203,7 +202,7 @@ typedef struct {
/* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster
allocation related structure, attached to ntfs_resize_t */
s64 max_free_cluster_range = 0;
static s64 max_free_cluster_range = 0;
#define NTFS_MBYTE (1000 * 1000)
@ -350,7 +349,7 @@ static void proceed_question(void)
printf("Are you sure you want to proceed (y/[n])? ");
buf[0] = 0;
fgets(buf, sizeof(buf), stdin);
if (strchr(short_yes, buf[0]) == 0) {
if (!strchr(short_yes, buf[0])) {
printf("OK quitting. NO CHANGES have been made to your "
"NTFS volume.\n");
exit(1);
@ -370,6 +369,7 @@ static void version(void)
printf("Copyright (c) 2002-2006 Szabolcs Szakacsits\n");
printf("Copyright (c) 2002-2005 Anton Altaparmakov\n");
printf("Copyright (c) 2002-2003 Richard Russon\n");
printf("Copyright (c) 2007 Yura Pakhuchiy\n");
printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -487,7 +487,7 @@ static int parse_options(int argc, char **argv)
opt.info++;
break;
case 'n':
opt.ro_flag = MS_RDONLY;
opt.ro_flag = NTFS_MNT_RDONLY;
break;
case 'P':
opt.show_progress = 0;
@ -523,7 +523,7 @@ static int parse_options(int argc, char **argv)
err++;
}
if (opt.info) {
opt.ro_flag = MS_RDONLY;
opt.ro_flag = NTFS_MNT_RDONLY;
if (opt.bytes) {
printf(NERR_PREFIX "Options --info and --size "
"can't be used together.\n");
@ -804,11 +804,9 @@ static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
lcn_length);
for (j = 0; j < lcn_length; j++) {
u64 k = (u64)lcn + j;
if (k >= (u64)vol->nr_clusters) {
long long outsiders = lcn_length - j;
fsck->outsider += outsiders;
@ -824,7 +822,7 @@ static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) {
if (++fsck->multi_ref <= 10 || opt.verbose)
printf("Cluster %lld is referenced "
"multiply times!\n",
"multiple times!\n",
(long long)k);
continue;
}
@ -1174,7 +1172,7 @@ static void replace_attribute_runlist(ntfs_volume *vol,
ntfs_log_verbose("Bytes in use : %u\n", (unsigned int)
le32_to_cpu(ctx->mrec->bytes_in_use));
next_attr = (char *)a + le16_to_cpu(a->length);
next_attr = (char *)a + le32_to_cpu(a->length);
l = mp_size - l;
ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
@ -1201,11 +1199,12 @@ static void replace_attribute_runlist(ntfs_volume *vol,
memmove(next_attr + l, next_attr, remains_size);
ctx->mrec->bytes_in_use = cpu_to_le32(l +
le32_to_cpu(ctx->mrec->bytes_in_use));
a->length += l;
a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
}
if (!(mp = calloc(1, mp_size)))
perr_exit("Couldn't get memory");
mp = ntfs_calloc(mp_size);
if (!mp)
perr_exit("ntfsc_calloc couldn't get memory");
if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl, 0, NULL))
perr_exit("ntfs_mapping_pairs_build");
@ -1469,8 +1468,9 @@ static void rl_split_run(runlist **rl, int run, s64 pos)
size_head = run * sizeof(runlist_element);
size_tail = (items - run - 1) * sizeof(runlist_element);
if (!(rl_new = (runlist *)malloc(new_size)))
perr_exit("malloc");
rl_new = ntfs_malloc(new_size);
if (!rl_new)
perr_exit("ntfs_malloc");
rle_new = rl_new + run;
rle = *rl + run;
@ -1612,8 +1612,8 @@ static int is_mftdata(ntfs_resize_t *resize)
if (resize->mref == 0)
return 1;
if ( MREF(resize->mrec->base_mft_record) == 0 &&
MSEQNO(resize->mrec->base_mft_record) != 0)
if (MREF_LE(resize->mrec->base_mft_record) == 0 &&
MSEQNO_LE(resize->mrec->base_mft_record) != 0)
return 1;
return 0;
@ -1720,9 +1720,9 @@ static void relocate_inodes(ntfs_resize_t *resize)
progress_init(&resize->progress, 0, resize->relocations, resize->progress.flags);
resize->relocations = 0;
resize->mrec = (MFT_RECORD *)malloc(resize->vol->mft_record_size);
resize->mrec = ntfs_malloc(resize->vol->mft_record_size);
if (!resize->mrec)
perr_exit("malloc failed");
perr_exit("ntfs_malloc failed");
nr_mft_records = resize->vol->mft_na->initialized_size >>
resize->vol->mft_record_size_bits;
@ -1875,9 +1875,9 @@ static void truncate_badclust_bad_attr(ntfs_resize_t *resize)
rl_truncate(&rl_bad, nr_clusters);
a->highest_vcn = cpu_to_le64(nr_clusters - 1LL);
a->allocated_size = cpu_to_le64(nr_clusters * vol->cluster_size);
a->data_size = cpu_to_le64(nr_clusters * vol->cluster_size);
a->highest_vcn = cpu_to_sle64(nr_clusters - 1LL);
a->allocated_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
a->data_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
replace_attribute_runlist(vol, resize->ctx, rl_bad);
@ -1952,10 +1952,10 @@ static void truncate_bitmap_data_attr(ntfs_resize_t *resize)
realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
}
a->highest_vcn = cpu_to_le64(nr_bm_clusters - 1LL);
a->allocated_size = cpu_to_le64(nr_bm_clusters * vol->cluster_size);
a->data_size = cpu_to_le64(bm_bsize);
a->initialized_size = cpu_to_le64(bm_bsize);
a->highest_vcn = cpu_to_sle64(nr_bm_clusters - 1LL);
a->allocated_size = cpu_to_sle64(nr_bm_clusters * vol->cluster_size);
a->data_size = cpu_to_sle64(bm_bsize);
a->initialized_size = cpu_to_sle64(bm_bsize);
replace_attribute_runlist(vol, resize->ctx, rl);
@ -2031,7 +2031,7 @@ static int check_bad_sectors(ntfs_volume *vol)
if (!ctx->attr->non_resident)
err_exit("Resident attribute in $BadClust! Please report to "
"%s\n", NTFS_DEV_LIST);
/*
/*
* FIXME: The below would be partial for non-base records in the
* not yet supported multi-record case. Alternatively use audited
* ntfs_attr_truncate after an umount & mount.
@ -2120,7 +2120,8 @@ static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters)
/* Determine lcn bitmap byte size and allocate it. */
bm->size = rounded_up_division(nr_clusters, 8);
if (!(bm->bm = (unsigned char *)calloc(1, bm->size)))
bm->bm = ntfs_calloc(bm->size);
if (!bm->bm)
return -1;
bitmap_file_data_fixup(nr_clusters, bm);
@ -2153,7 +2154,7 @@ static void update_bootsector(ntfs_resize_t *r)
r->progress.flags |= NTFS_PROGBAR_SUPPRESS;
copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old,
r->mftmir_rl.length);
bs.mftmirr_lcn = cpu_to_le64(r->mftmir_rl.lcn);
bs.mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS;
}
@ -2238,9 +2239,12 @@ static ntfs_volume *mount_volume(void)
err_exit("Device '%s' is mounted. "
"You must 'umount' it first.\n", opt.volume);
}
if (!(vol = ntfs_mount(opt.volume, opt.ro_flag /*| MS_NOATIME*/))) {
/*
* Pass NTFS_MNT_FORENSIC so that the mount process does not modify the
* volume at all. We will do the logfile emptying and dirty setting
* later if needed.
*/
if (!(vol = ntfs_mount(opt.volume, opt.ro_flag | NTFS_MNT_FORENSIC))) {
int err = errno;
perr_printf("Opening '%s' as NTFS failed", opt.volume);
@ -2257,7 +2261,7 @@ static ntfs_volume *mount_volume(void)
exit(1);
}
if (vol->flags & VOLUME_IS_DIRTY)
if (NVolWasDirty(vol))
if (opt.force-- <= 0)
err_exit("Volume is scheduled for check.\nRun chkdsk /f"
" and please try again, or see option -f.\n");
@ -2287,31 +2291,21 @@ static ntfs_volume *mount_volume(void)
*/
static void prepare_volume_fixup(ntfs_volume *vol)
{
u16 flags;
flags = vol->flags | VOLUME_IS_DIRTY;
if (vol->major_ver >= 2)
flags |= VOLUME_MOUNTED_ON_NT4;
printf("Schedule chkdsk for NTFS consistency check at Windows "
"boot time ...\n");
if (ntfs_volume_write_flags(vol, flags))
perr_exit("Failed to set $Volume dirty");
printf("Schedule chkdsk for NTFS consistency check at Windows boot "
"time ...\n");
vol->flags |= VOLUME_IS_DIRTY;
if (ntfs_volume_write_flags(vol, vol->flags))
perr_exit("Failed to set the volume dirty");
NVolSetWasDirty(vol);
if (vol->dev->d_ops->sync(vol->dev) == -1)
perr_exit("Failed to sync device");
printf("Resetting $LogFile ... (this might take a while)\n");
if (ntfs_logfile_reset(vol))
perr_exit("Failed to reset $LogFile");
if (vol->dev->d_ops->sync(vol->dev) == -1)
perr_exit("Failed to sync device");
}
static void set_disk_usage_constraint(ntfs_resize_t *resize)
{
/* last lcn for a filled up volume (no empty space) */
@ -2394,7 +2388,7 @@ int main(int argc, char **argv)
utils_set_locale();
if ((vol = mount_volume()) == NULL)
if (!(vol = mount_volume()))
err_exit("Couldn't open volume '%s'!\n", opt.volume);
device_size = ntfs_device_size_get(vol->dev, vol->sector_size);

View File

@ -1027,7 +1027,7 @@ int main(int argc, char *argv[])
#endif
if (opts.noaction)
flags |= MS_RDONLY;
flags |= NTFS_MNT_RDONLY;
//ntfs_log_set_levels (NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE);
//ntfs_log_set_levels (NTFS_LOG_LEVEL_DEBUG);

View File

@ -716,7 +716,7 @@ int main(int argc, char **argv)
* Setup a default $AttrDef. FIXME: Should be reading this from the
* volume itself, at ntfs_mount() time.
*/
attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
attr_defs = (ATTR_DEF*)&attrdef_ntfs3x_array;
/* Parse command line options. */
parse_options(argc, argv);
@ -738,7 +738,7 @@ int main(int argc, char **argv)
/* Mount the device. */
if (opts.no_action) {
ntfs_log_quiet("Running in READ-ONLY mode!\n");
ul = MS_RDONLY;
ul = NTFS_MNT_RDONLY;
} else
ul = 0;
vol = ntfs_mount(dev_name, ul);
@ -808,4 +808,3 @@ int main(int argc, char **argv)
ntfs_log_quiet("ntfstruncate completed successfully. Have a nice day.\n");
return 0;
}

View File

@ -3,7 +3,8 @@
*
* Copyright (c) 2002-2005 Richard Russon
* Copyright (c) 2004-2005 Holger Ohmacht
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2005 Anton Altaparmakov
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility will recover deleted files from an NTFS volume.
*
@ -222,10 +223,12 @@ static int parse_inode_arg(void)
*/
static void version(void)
{
ntfs_log_info("\n%s v%s (libntfs-3g) - Recover deleted files from an NTFS "
"Volume.\n\n", EXEC_NAME, VERSION);
ntfs_log_info("\n%s v%s (libntfs-3g) - Recover deleted files from an "
"NTFS Volume.\n\n", EXEC_NAME, VERSION);
ntfs_log_info("Copyright (c) 2002-2005 Richard Russon\n"
"Copyright (c) 2004-2005 Holger Ohmacht\n");
"Copyright (c) 2004-2005 Holger Ohmacht\n"
"Copyright (c) 2005 Anton Altaparmakov\n"
"Copyright (c) 2007 Yura Pakhuchiy\n");
ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
}
@ -834,7 +837,8 @@ static void get_parent_name(struct filename* name, ntfs_volume* vol)
rec = calloc(1, vol->mft_record_size);
if (!rec) {
ntfs_log_error("ERROR: Couldn't allocate memory in get_parent_name()\n");
ntfs_log_error("ERROR: Couldn't allocate memory in "
"get_parent_name()\n");
return;
}
@ -842,10 +846,12 @@ static void get_parent_name(struct filename* name, ntfs_volume* vol)
if (!mft_data) {
ntfs_log_perror("ERROR: Couldn't open $MFT/$DATA");
} else {
inode_num = MREF(name->parent_mref);
inode_num = MREF_LE(name->parent_mref);
if (ntfs_attr_pread(mft_data, vol->mft_record_size * inode_num, vol->mft_record_size, rec) < 1) {
ntfs_log_error("ERROR: Couldn't read MFT Record %lld.\n", inode_num);
if (ntfs_attr_pread(mft_data, vol->mft_record_size * inode_num,
vol->mft_record_size, rec) < 1) {
ntfs_log_error("ERROR: Couldn't read MFT Record %lld"
".\n", inode_num);
} else if ((filename_attr = verify_parent(name, rec))) {
if (ntfs_ucstombs(filename_attr->file_name,
filename_attr->file_name_length,
@ -906,11 +912,13 @@ static int get_filenames(struct ufile *file, ntfs_volume* vol)
while ((rec = find_attribute(AT_FILE_NAME, ctx))) {
/* We know this will always be resident. */
attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->value_offset));
attr = (FILE_NAME_ATTR *)((char *)rec +
le16_to_cpu(rec->value_offset));
name = calloc(1, sizeof(*name));
if (!name) {
ntfs_log_error("ERROR: Couldn't allocate memory in get_filenames().\n");
ntfs_log_error("ERROR: Couldn't allocate memory in "
"get_filenames().\n");
count = -1;
break;
}
@ -990,28 +998,32 @@ static int get_data(struct ufile *file, ntfs_volume *vol)
while ((rec = find_attribute(AT_DATA, ctx))) {
data = calloc(1, sizeof(*data));
if (!data) {
ntfs_log_error("ERROR: Couldn't allocate memory in get_data().\n");
ntfs_log_error("ERROR: Couldn't allocate memory in "
"get_data().\n");
count = -1;
break;
}
data->resident = !rec->non_resident;
data->compressed = rec->flags & ATTR_IS_COMPRESSED;
data->encrypted = rec->flags & ATTR_IS_ENCRYPTED;
data->compressed = (rec->flags & ATTR_IS_COMPRESSED) ? 1 : 0;
data->encrypted = (rec->flags & ATTR_IS_ENCRYPTED) ? 1 : 0;
if (rec->name_length) {
data->uname = (ntfschar *) ((char *) rec + le16_to_cpu(rec->name_offset));
data->uname = (ntfschar *)((char *)rec +
le16_to_cpu(rec->name_offset));
data->uname_len = rec->name_length;
if (ntfs_ucstombs(data->uname, data->uname_len, &data->name,
0) < 0) {
ntfs_log_error("ERROR: Cannot translate name into current locale.\n");
if (ntfs_ucstombs(data->uname, data->uname_len,
&data->name, 0) < 0) {
ntfs_log_error("ERROR: Cannot translate name "
"into current locale.\n");
}
}
if (data->resident) {
data->size_data = le32_to_cpu(rec->value_length);
data->data = ((char*) (rec)) + le16_to_cpu(rec->value_offset);
data->size_data = le32_to_cpu(rec->value_length);
data->data = (char*)rec +
le16_to_cpu(rec->value_offset);
} else {
data->size_alloc = sle64_to_cpu(rec->allocated_size);
data->size_data = sle64_to_cpu(rec->data_size);
@ -1169,17 +1181,20 @@ static int calc_percentage(struct ufile *file, ntfs_volume *vol)
clusters_free = 0;
if (data->encrypted) {
ntfs_log_verbose("File is encrypted, recovery is impossible.\n");
ntfs_log_verbose("File is encrypted, recovery is "
"impossible.\n");
continue;
}
if (data->compressed) {
ntfs_log_verbose("File is compressed, recovery not yet implemented.\n");
ntfs_log_verbose("File is compressed, recovery not yet "
"implemented.\n");
continue;
}
if (data->resident) {
ntfs_log_verbose("File is resident, therefore recoverable.\n");
ntfs_log_verbose("File is resident, therefore "
"recoverable.\n");
percent = 100;
data->percent = 100;
continue;
@ -1187,16 +1202,18 @@ static int calc_percentage(struct ufile *file, ntfs_volume *vol)
rl = data->runlist;
if (!rl) {
ntfs_log_verbose("File has no runlist, hence no data.\n");
ntfs_log_verbose("File has no runlist, hence no data."
"\n");
continue;
}
if (rl[0].length <= 0) {
ntfs_log_verbose("File has an empty runlist, hence no data.\n");
ntfs_log_verbose("File has an empty runlist, hence no "
"data.\n");
continue;
}
if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */
if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */
ntfs_log_verbose("Missing segment at beginning, %lld "
"clusters\n", (long long)rl[0].length);
clusters_inuse += rl[0].length;
@ -1288,12 +1305,18 @@ static void dump_record(struct ufile *file)
ntfs_log_quiet("Filename: (%d) %s\n", f->name_space, f->name);
ntfs_log_quiet("File Flags: ");
if (f->flags & FILE_ATTR_SYSTEM) ntfs_log_quiet("System ");
if (f->flags & FILE_ATTR_DIRECTORY) ntfs_log_quiet("Directory ");
if (f->flags & FILE_ATTR_SPARSE_FILE) ntfs_log_quiet("Sparse ");
if (f->flags & FILE_ATTR_REPARSE_POINT) ntfs_log_quiet("Reparse ");
if (f->flags & FILE_ATTR_COMPRESSED) ntfs_log_quiet("Compressed ");
if (f->flags & FILE_ATTR_ENCRYPTED) ntfs_log_quiet("Encrypted ");
if (f->flags & FILE_ATTR_SYSTEM)
ntfs_log_quiet("System ");
if (f->flags & FILE_ATTR_DIRECTORY)
ntfs_log_quiet("Directory ");
if (f->flags & FILE_ATTR_SPARSE_FILE)
ntfs_log_quiet("Sparse ");
if (f->flags & FILE_ATTR_REPARSE_POINT)
ntfs_log_quiet("Reparse ");
if (f->flags & FILE_ATTR_COMPRESSED)
ntfs_log_quiet("Compressed ");
if (f->flags & FILE_ATTR_ENCRYPTED)
ntfs_log_quiet("Encrypted ");
if (!(f->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_DIRECTORY |
FILE_ATTR_SPARSE_FILE | FILE_ATTR_REPARSE_POINT |
FILE_ATTR_COMPRESSED | FILE_ATTR_ENCRYPTED))) {
@ -1310,13 +1333,17 @@ static void dump_record(struct ufile *file)
ntfs_log_quiet("Size alloc: %lld\n", f->size_alloc);
ntfs_log_quiet("Size data: %lld\n", f->size_data);
strftime(buffer, sizeof(buffer), "%F %R", localtime(&f->date_c));
strftime(buffer, sizeof(buffer), "%F %R",
localtime(&f->date_c));
ntfs_log_quiet("Date C: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%F %R", localtime(&f->date_a));
strftime(buffer, sizeof(buffer), "%F %R",
localtime(&f->date_a));
ntfs_log_quiet("Date A: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%F %R", localtime(&f->date_m));
strftime(buffer, sizeof(buffer), "%F %R",
localtime(&f->date_m));
ntfs_log_quiet("Date M: %s\n", buffer);
strftime(buffer, sizeof(buffer), "%F %R", localtime(&f->date_r));
strftime(buffer, sizeof(buffer), "%F %R",
localtime(&f->date_r));
ntfs_log_quiet("Date R: %s\n", buffer);
}
@ -1349,7 +1376,8 @@ static void dump_record(struct ufile *file)
}
}
ntfs_log_quiet("Amount potentially recoverable %d%%\n", d->percent);
ntfs_log_quiet("Amount potentially recoverable %d%%\n",
d->percent);
}
ntfs_log_quiet("________________________________________\n\n");
@ -1402,10 +1430,14 @@ static void list_record(struct ufile *file)
struct data *d = list_entry(item, struct data, list);
if (!d->name) {
if (d->resident) flagr = 'R';
else flagr = 'N';
if (d->compressed) flagc = 'C'; /* These two are mutually exclusive */
if (d->encrypted) flagc = 'E';
if (d->resident)
flagr = 'R';
else
flagr = 'N';
if (d->compressed)
flagc = 'C';
if (d->encrypted)
flagc = 'E';
percent = max(percent, d->percent);
}
@ -2123,7 +2155,8 @@ int main(int argc, char *argv[])
utils_set_locale();
vol = utils_mount_volume(opts.device, MS_RDONLY, opts.force);
vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
(opts.force ? NTFS_MNT_FORCE : 0));
if (!vol)
return 1;

View File

@ -2,6 +2,7 @@
* ntfsundelete - Part of the Linux-NTFS project.
*
* Copyright (c) 2002 Richard Russon
* Copyright (c) 2007 Yura Pakhuchiy
*
* This utility will recover deleted files from an NTFS volume.
*
@ -58,7 +59,6 @@ struct options {
s64 mft_begin; /* Range for mft copy */
s64 mft_end;
char fillbyte; /* Use for unrecoverable sections */
char padding[7]; /* Unused: padding to 64 bit. */
};
struct filename {
@ -74,9 +74,8 @@ struct filename {
time_t date_r; /* read */
char *name; /* Filename in current locale */
FILE_NAME_TYPE_FLAGS name_space;
long long parent_mref;
leMFT_REF parent_mref;
char *parent_name;
char padding[7]; /* Unused: padding to 64 bit. */
};
struct data {
@ -94,7 +93,6 @@ struct data {
runlist_element *runlist; /* Decoded data runs */
int percent; /* Amount potentially recoverable */
void *data; /* If resident, a pointer to the data */
char padding[4]; /* Unused: padding to 64 bit. */
};
struct ufile {
@ -108,7 +106,6 @@ struct ufile {
int attr_list; /* MFT record may be one of many */
int directory; /* MFT record represents a directory */
MFT_RECORD *mft; /* Raw MFT record */
char padding[4]; /* Unused: padding to 64 bit. */
};
#endif /* _NTFSUNDELETE_H_ */

View File

@ -1340,13 +1340,15 @@ int main(int argc, char *argv[])
print_summary();
if (opts.info || opts.noaction)
flags = MS_RDONLY;
flags = NTFS_MNT_RDONLY;
if (opts.force)
flags |= NTFS_MNT_FORCE;
vol = utils_mount_volume(opts.device, flags, opts.force);
vol = utils_mount_volume(opts.device, flags);
if (!vol)
goto free;
if ((vol->flags & VOLUME_IS_DIRTY) && (!opts.force))
if (NVolWasDirty(vol) && !opts.force)
goto umount;
if (opts.info) {

View File

@ -3,25 +3,16 @@
#include "sd.h"
/**
* init_system_file_sd
* init_system_file_sd -
*
* NTFS 1.2, 3.0, 3.1 - System files security decriptors
* NTFS 3.1 - System files security decriptors
* =====================================================
*
* Create the security descriptor for system file number @sys_file_no and
* return a pointer to the descriptor.
*
* $MFT, $MFTMirr, $LogFile, $AttrDef, $Bitmap, $Boot, $BadClus, and $UpCase
* are the same.
*
* $Volume, $Quota, and system files 0xb-0xf are the same. They are almost the
* same as the above, the only difference being that the two SIDs present in
* the DACL grant GENERIC_WRITE and GENERIC_READ equivalent privileges while
* the above only grant GENERIC_READ equivalent privileges. (For some reason
* the flags for GENERIC_READ/GENERIC_WRITE are not set by NT4, even though
* the permissions are equivalent, so we comply.
*
* Root directory system file (".") is different altogether.
* Note the root directory system file (".") is very different and handled by a
* different function.
*
* The sd is returned in *@sd_val and has length *@sd_val_len.
*
@ -46,15 +37,9 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
sd->revision = 1;
sd->alignment = 0;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
if (sys_file_no == FILE_root) {
*sd_val_len = 0x50;
sd->owner = const_cpu_to_le32(0x30);
sd->group = const_cpu_to_le32(0x40);
} else {
*sd_val_len = 0x68;
sd->owner = const_cpu_to_le32(0x48);
sd->group = const_cpu_to_le32(0x58);
}
*sd_val_len = 0x64;
sd->owner = const_cpu_to_le32(0x48);
sd->group = const_cpu_to_le32(0x54);
sd->sacl = const_cpu_to_le32(0);
sd->dacl = const_cpu_to_le32(0x14);
/*
@ -64,13 +49,8 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
acl = (ACL*)((char*)sd + le32_to_cpu(sd->dacl));
acl->revision = 2;
acl->alignment1 = 0;
if (sys_file_no == FILE_root) {
acl->size = const_cpu_to_le16(0x1c);
acl->ace_count = const_cpu_to_le16(1);
} else {
acl->size = const_cpu_to_le16(0x34);
acl->ace_count = const_cpu_to_le16(2);
}
acl->size = const_cpu_to_le16(0x34);
acl->ace_count = const_cpu_to_le16(2);
acl->alignment2 = const_cpu_to_le16(0);
/*
* Now at offset 0x1c, just after the DACL's ACL, we have the first
@ -78,31 +58,20 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
*/
aa_ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
aa_ace->type = ACCESS_ALLOWED_ACE_TYPE;
if (sys_file_no == FILE_root)
aa_ace->flags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
else
aa_ace->flags = 0;
aa_ace->flags = 0;
aa_ace->size = const_cpu_to_le16(0x14);
switch (sys_file_no) {
case FILE_MFT: case FILE_MFTMirr: case FILE_LogFile:
case FILE_AttrDef: case FILE_Bitmap: case FILE_Boot:
case FILE_BadClus: case FILE_UpCase:
case FILE_AttrDef:
case FILE_Boot:
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
FILE_READ_ATTRIBUTES | FILE_READ_EA | FILE_READ_DATA;
break;
case FILE_Volume: case FILE_Secure: case 0xb ... 0xffff:
default:
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_WRITE |
FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
FILE_WRITE_EA | FILE_READ_EA | FILE_APPEND_DATA |
FILE_WRITE_DATA | FILE_READ_DATA;
break;
case FILE_root:
aa_ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_READ_ATTRIBUTES | FILE_DELETE_CHILD |
FILE_TRAVERSE | FILE_WRITE_EA | FILE_READ_EA |
FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE |
FILE_LIST_DIRECTORY;
break;
}
aa_ace->sid.revision = 1;
aa_ace->sid.sub_authority_count = 1;
@ -111,67 +80,57 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
aa_ace->sid.identifier_authority.value[2] = 0;
aa_ace->sid.identifier_authority.value[3] = 0;
aa_ace->sid.identifier_authority.value[4] = 0;
if (sys_file_no == FILE_root) {
/* SECURITY_WORLD_SID_AUTHORITY (S-1-1) */
aa_ace->sid.identifier_authority.value[5] = 1;
aa_ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_WORLD_RID);
/* This is S-1-1-0, the WORLD_SID. */
} else {
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
aa_ace->sid.identifier_authority.value[5] = 5;
aa_ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
}
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
aa_ace->sid.identifier_authority.value[5] = 5;
aa_ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
/*
* Now at offset 0x30 within security descriptor, just after the first
* ACE of the DACL. All system files, except the root directory, have
* a second ACE.
*/
if (sys_file_no != FILE_root) {
/* The second ACE of the DACL. Type is access allowed. */
aa_ace = (ACCESS_ALLOWED_ACE*)((char*)aa_ace +
le16_to_cpu(aa_ace->size));
aa_ace->type = ACCESS_ALLOWED_ACE_TYPE;
aa_ace->flags = 0;
aa_ace->size = const_cpu_to_le16(0x18);
switch (sys_file_no) {
case FILE_MFT: case FILE_MFTMirr:
case FILE_LogFile: case FILE_AttrDef:
case FILE_Bitmap: case FILE_Boot:
case FILE_BadClus: case FILE_UpCase:
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
FILE_READ_ATTRIBUTES | FILE_READ_EA |
FILE_READ_DATA;
break;
case FILE_Volume: case FILE_Secure:
case 0xb ... 0xffff :
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
FILE_WRITE_ATTRIBUTES |
FILE_READ_ATTRIBUTES | FILE_WRITE_EA |
FILE_READ_EA | FILE_APPEND_DATA |
FILE_WRITE_DATA | FILE_READ_DATA;
break;
}
aa_ace->sid.revision = 1;
aa_ace->sid.sub_authority_count = 2;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
aa_ace->sid.identifier_authority.value[0] = 0;
aa_ace->sid.identifier_authority.value[1] = 0;
aa_ace->sid.identifier_authority.value[2] = 0;
aa_ace->sid.identifier_authority.value[3] = 0;
aa_ace->sid.identifier_authority.value[4] = 0;
aa_ace->sid.identifier_authority.value[5] = 5;
aa_ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
aa_ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
/* Now at offset 0x48 into the security descriptor. */
/* The second ACE of the DACL. Type is access allowed. */
aa_ace = (ACCESS_ALLOWED_ACE*)((char*)aa_ace +
le16_to_cpu(aa_ace->size));
aa_ace->type = ACCESS_ALLOWED_ACE_TYPE;
aa_ace->flags = 0;
aa_ace->size = const_cpu_to_le16(0x18);
/* Only $AttrDef and $Boot behave differently to everything else. */
switch (sys_file_no) {
case FILE_AttrDef:
case FILE_Boot:
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
FILE_READ_ATTRIBUTES | FILE_READ_EA |
FILE_READ_DATA;
break;
default:
aa_ace->mask = SYNCHRONIZE | STANDARD_RIGHTS_READ |
FILE_WRITE_ATTRIBUTES |
FILE_READ_ATTRIBUTES | FILE_WRITE_EA |
FILE_READ_EA | FILE_APPEND_DATA |
FILE_WRITE_DATA | FILE_READ_DATA;
break;
}
/* As specified in the security descriptor, we now have the owner SID.*/
aa_ace->sid.revision = 1;
aa_ace->sid.sub_authority_count = 2;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
aa_ace->sid.identifier_authority.value[0] = 0;
aa_ace->sid.identifier_authority.value[1] = 0;
aa_ace->sid.identifier_authority.value[2] = 0;
aa_ace->sid.identifier_authority.value[3] = 0;
aa_ace->sid.identifier_authority.value[4] = 0;
aa_ace->sid.identifier_authority.value[5] = 5;
aa_ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
aa_ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
/*
* Now at offset 0x48 into the security descriptor, as specified in the
* security descriptor, we now have the owner SID.
*/
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 1;
sid->sub_authority_count = 2;
sid->sub_authority_count = 1;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
@ -179,12 +138,10 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
/*
* Now at offset 0x40 or 0x58 (root directory and the other system
* files, respectively) into the security descriptor, as specified in
* the security descriptor, we have the group SID.
* Now at offset 0x54 into the security descriptor, as specified in the
* security descriptor, we have the group SID.
*/
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
sid->revision = 1;
@ -201,56 +158,53 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
}
/**
* init_root_sd_31 (ERSO)
* creates the security_descriptor for the root folder on ntfs 3.1.
* It is very long; lots of ACE's at first, then large pieces of zeroes;
* the owner user/group is near the end. On a partition created with
* w2k3 the owner user/group at the end is surrounded by 'garbage', which I
* yet do not understand. Here I have replaced the 'garbage' with
* zeros, which seems to work. Chkdsk does not add the 'garbage', nor alter
* this security descriptor in any way.
* init_root_sd -
*
* Creates the security_descriptor for the root folder on ntfs 3.1 as created
* by Windows Vista (when the format is done from the disk management MMC
* snap-in, note this is different from the format done from the disk
* properties in Windows Explorer).
*/
void init_root_sd_31(u8 **sd_val, int *sd_val_len)
void init_root_sd(u8 **sd_val, int *sd_val_len)
{
SECURITY_DESCRIPTOR_RELATIVE *sd;
ACL *acl;
ACCESS_ALLOWED_ACE *ace;
SID *sid;
static char sd_array[0x1030];
*sd_val_len = 0x1030;
static char sd_array[0x102c];
*sd_val_len = 0x102c;
*sd_val = (u8*)&sd_array;
//security descriptor relative
sd = (SECURITY_DESCRIPTOR_RELATIVE*)sd_array;
sd->revision = 0x01;
sd->alignment = 0x00;
sd->revision = SECURITY_DESCRIPTOR_REVISION;
sd->alignment = 0;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
sd->owner = const_cpu_to_le32(0x1014);
sd->group = const_cpu_to_le32(0x1024);
sd->sacl = const_cpu_to_le32(0x00);
sd->dacl = const_cpu_to_le32(0x14);
sd->group = const_cpu_to_le32(0x1020);
sd->sacl = 0;
sd->dacl = const_cpu_to_le32(sizeof(SECURITY_DESCRIPTOR_RELATIVE));
//acl
acl = (ACL*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
acl->revision = 0x02;
acl->alignment1 = 0x00;
acl->revision = ACL_REVISION;
acl->alignment1 = 0;
acl->size = const_cpu_to_le16(0x1000);
acl->ace_count = const_cpu_to_le16(0x07);
acl->alignment2 = const_cpu_to_le16(0x00);
acl->ace_count = const_cpu_to_le16(0x08);
acl->alignment2 = 0;
//ace1
ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL));
ace->type = 0x00;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = 0;
ace->size = const_cpu_to_le16(0x18);
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = 0x01;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
@ -261,21 +215,17 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//ace2
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
ace->size = const_cpu_to_le16(0x14);
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE;
ace->size = const_cpu_to_le16(0x18);
ace->mask = GENERIC_ALL;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
@ -284,35 +234,40 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//ace3
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = 0;
ace->size = const_cpu_to_le16(0x14);
ace->mask = const_cpu_to_le32(0x10000000);
ace->sid.revision = 0x01;
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_CREATOR_SID_AUTHORITY (S-1-3) */
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 3;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_CREATOR_OWNER_RID);
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//ace4
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
ace->size = const_cpu_to_le16(0x18);
ace->mask = const_cpu_to_le32(0x1200A9);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE;
ace->size = const_cpu_to_le16(0x14);
ace->mask = GENERIC_ALL;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
@ -321,18 +276,20 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//ace5
ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = CONTAINER_INHERIT_ACE;
ace->size = const_cpu_to_le16(0x18);
ace->mask = const_cpu_to_le32(0x04);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = 0;
ace->size = const_cpu_to_le16(0x14);
ace->mask = SYNCHRONIZE | READ_CONTROL | DELETE |
FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES |
FILE_TRAVERSE | FILE_WRITE_EA | FILE_READ_EA |
FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE |
FILE_LIST_DIRECTORY;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
@ -341,18 +298,17 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID);
//ace6
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE;
ace->size = const_cpu_to_le16(0x18);
ace->mask = const_cpu_to_le32(0x02);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE;
ace->size = const_cpu_to_le16(0x14);
ace->mask = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
@ -361,43 +317,60 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
const_cpu_to_le32(SECURITY_AUTHENTICATED_USER_RID);
//ace7
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x14);
ace->mask = const_cpu_to_le32(0x1200A9);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_WORLD_SID_AUTHORITY (S-1-1) */
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = 0;
ace->size = const_cpu_to_le16(0x18);
ace->mask = SYNCHRONIZE | READ_CONTROL | FILE_READ_ATTRIBUTES |
FILE_TRAVERSE | FILE_READ_EA | FILE_LIST_DIRECTORY;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 1;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_WORLD_RID);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
//ace8
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
INHERIT_ONLY_ACE;
ace->size = const_cpu_to_le16(0x18);
ace->mask = GENERIC_READ | GENERIC_EXECUTE;
ace->sid.revision = SID_REVISION;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//group sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
@ -410,419 +383,18 @@ void init_root_sd_31(u8 **sd_val, int *sd_val_len)
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
sid->sub_authority[0] = const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
}
/**
* init_secure
*
* NTFS 3.0 - System files security decriptors
* ===========================================
* Create the security descriptor entries in $SDS data stream like they
* are in a partition, newly formatted with windows 2000
*/
void init_secure_30(char *sd_val)
{
SECURITY_DESCRIPTOR_HEADER *sds;
SECURITY_DESCRIPTOR_RELATIVE *sd;
ACL *acl;
ACCESS_ALLOWED_ACE *ace;
SID *sid;
/*
* security descriptor #1
*/
//header
sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val);
sds->hash = const_cpu_to_le32(0xF80312F0);
sds->security_id = const_cpu_to_le32(0x0100);
sds->offset = const_cpu_to_le64(0x00);
sds->length = const_cpu_to_le32(0x7C);
//security descriptor relative
sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
sizeof(SECURITY_DESCRIPTOR_HEADER));
sd->revision = 0x01;
sd->alignment = 0x00;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
sd->owner = const_cpu_to_le32(0x48);
sd->group = const_cpu_to_le32(0x58);
sd->sacl = const_cpu_to_le32(0x00);
sd->dacl = const_cpu_to_le32(0x14);
//acl
acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
acl->revision = 0x02;
acl->alignment1 = 0x00;
acl->size = const_cpu_to_le16(0x34);
acl->ace_count = const_cpu_to_le16(0x02);
acl->alignment2 = 0x00;
//ace1
ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x14);
ace->mask = const_cpu_to_le32(0x120089);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//ace2
ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x18);
ace->mask = const_cpu_to_le32(0x120089);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//group sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
/*
* security descriptor #2
*/
//header
sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80);
sds->hash = const_cpu_to_le32(0xB32451);
sds->security_id = const_cpu_to_le32(0x0101);
sds->offset = const_cpu_to_le64(0x80);
sds->length = const_cpu_to_le32(0x7C);
//security descriptor relative
sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
sizeof(SECURITY_DESCRIPTOR_HEADER));
sd->revision = 0x01;
sd->alignment = 0x00;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
sd->owner = const_cpu_to_le32(0x48);
sd->group = const_cpu_to_le32(0x58);
sd->sacl = const_cpu_to_le32(0x00);
sd->dacl = const_cpu_to_le32(0x14);
//acl
acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
acl->revision = 0x02;
acl->alignment1 = 0x00;
acl->size = const_cpu_to_le16(0x34);
acl->ace_count = const_cpu_to_le16(0x02);
acl->alignment2 = 0x00;
//ace1
ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x14);
ace->mask = const_cpu_to_le32(0x12019F);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//ace2
ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x18);
ace->mask = const_cpu_to_le32(0x12019F);
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//group sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
/*
* security descriptor #3
*/
//header
sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80 + 0x80);
sds->hash = const_cpu_to_le32(0x0A9F9562);
sds->security_id = const_cpu_to_le32(0x0102);
sds->offset = const_cpu_to_le64(0x0100);
sds->length = const_cpu_to_le32(0x60);
//security descriptor relative
sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
sizeof(SECURITY_DESCRIPTOR_HEADER));
sd->revision = 0x01;
sd->alignment = 0x00;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
sd->owner = const_cpu_to_le32(0x30);
sd->group = const_cpu_to_le32(0x40);
sd->sacl = const_cpu_to_le32(0x00);
sd->dacl = const_cpu_to_le32(0x14);
//acl
acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
acl->revision = 0x02;
acl->alignment1 = 0x00;
acl->size = const_cpu_to_le16(0x1C);
acl->ace_count = const_cpu_to_le16(0x01);
acl->alignment2 = 0x00;
//ace1
ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x14);
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//group sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
sid->revision = 0x01;
sid->sub_authority_count = 0x01;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
/*
* security descriptor #4
*/
//header
sds = (SECURITY_DESCRIPTOR_HEADER*)((char*)sd_val + 0x80 + 0x80 + 0x60);
sds->hash = const_cpu_to_le32(0x453F0A2E);
sds->security_id = const_cpu_to_le32(0x0103);
sds->offset = const_cpu_to_le64(0x0160);
sds->length = const_cpu_to_le32(0x78);
//security descriptor relative
sd = (SECURITY_DESCRIPTOR_RELATIVE*)((char*)sds +
sizeof(SECURITY_DESCRIPTOR_HEADER));
sd->revision = 0x01;
sd->alignment = 0x00;
sd->control = SE_SELF_RELATIVE | SE_DACL_PRESENT;
sd->owner = const_cpu_to_le32(0x48);
sd->group = const_cpu_to_le32(0x58);
sd->sacl = const_cpu_to_le32(0x00);
sd->dacl = const_cpu_to_le32(0x14);
//acl
acl = (ACL*)((char*)sd + sizeof(SECURITY_DESCRIPTOR_RELATIVE));
acl->revision = 0x02;
acl->alignment1 = 0x00;
acl->size = const_cpu_to_le16(0x34);
acl->ace_count = const_cpu_to_le16(0x02);
acl->alignment2 = 0x00;
//ace1
ace = (ACCESS_ALLOWED_ACE*)((char*)acl + sizeof(ACL));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x18);
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x02;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
ace->sid.sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//ace2
ace = (ACCESS_ALLOWED_ACE*)((char*)ace + le16_to_cpu(ace->size));
ace->type = 0x00;
ace->flags = 0x00;
ace->size = const_cpu_to_le16(0x14);
ace->mask = STANDARD_RIGHTS_ALL | FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY | FILE_WRITE_DATA |
FILE_ADD_SUBDIRECTORY | FILE_READ_EA | FILE_WRITE_EA |
FILE_TRAVERSE | FILE_DELETE_CHILD |
FILE_READ_ATTRIBUTES;
ace->sid.revision = 0x01;
ace->sid.sub_authority_count = 0x01;
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
ace->sid.identifier_authority.value[0] = 0;
ace->sid.identifier_authority.value[1] = 0;
ace->sid.identifier_authority.value[2] = 0;
ace->sid.identifier_authority.value[3] = 0;
ace->sid.identifier_authority.value[4] = 0;
ace->sid.identifier_authority.value[5] = 5;
ace->sid.sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
//owner sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
sid->revision = 0x01;
sid->sub_authority_count = 0x02;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] =
const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
//group sid
sid = (SID*)((char*)sd + le32_to_cpu(sd->group));
sid->revision = 0x01;
sid->sub_authority_count = 0x01;
// SECURITY_NT_SID_AUTHORITY (S-1-5)
sid->identifier_authority.value[0] = 0;
sid->identifier_authority.value[1] = 0;
sid->identifier_authority.value[2] = 0;
sid->identifier_authority.value[3] = 0;
sid->identifier_authority.value[4] = 0;
sid->identifier_authority.value[5] = 5;
sid->sub_authority[0] =
const_cpu_to_le32(SECURITY_LOCAL_SYSTEM_RID);
return;
}
/**
* init_secure_31(char **r, int size);
* init_secure_sds -
*
* NTFS 3.1 - System files security decriptors
* ===========================================
* Create the security descriptor entries in $SDS data stream like they
* are in a partition, newly formatted with windows 2003
*/
void init_secure_31(char *sd_val)
void init_secure_sds(char *sd_val)
{
SECURITY_DESCRIPTOR_HEADER *sds;
SECURITY_DESCRIPTOR_RELATIVE *sd;

View File

@ -4,9 +4,8 @@
#include <ntfs-3g/types.h>
void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len);
void init_root_sd_31(u8 **sd_val, int *sd_val_len);
void init_secure_30(char *sd_val);
void init_secure_31(char *sd_val);
void init_root_sd(u8 **sd_val, int *sd_val_len);
void init_secure_sds(char *sd_val);
#endif /* _NTFS_SD_H_ */

View File

@ -1,90 +0,0 @@
/**
* upcase - Part of the Linux-NTFS project.
*
* Copyright (c) 2001 Richard Russon
* Copyright (c) 2001-2006 Anton Altaparmakov
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the Linux-NTFS source
* in the file COPYING); if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <ntfs-3g/endians.h>
#include <ntfs-3g/types.h>
#include "upcase.h"
/**
* init_upcase_table
*/
void init_upcase_table(ntfschar *uc, u32 uc_len)
{
static int uc_run_table[][3] = { /* Start, End, Add */
{0x0061, 0x007B, -32}, {0x0451, 0x045D, -80}, {0x1F70, 0x1F72, 74},
{0x00E0, 0x00F7, -32}, {0x045E, 0x0460, -80}, {0x1F72, 0x1F76, 86},
{0x00F8, 0x00FF, -32}, {0x0561, 0x0587, -48}, {0x1F76, 0x1F78, 100},
{0x0256, 0x0258, -205}, {0x1F00, 0x1F08, 8}, {0x1F78, 0x1F7A, 128},
{0x028A, 0x028C, -217}, {0x1F10, 0x1F16, 8}, {0x1F7A, 0x1F7C, 112},
{0x03AC, 0x03AD, -38}, {0x1F20, 0x1F28, 8}, {0x1F7C, 0x1F7E, 126},
{0x03AD, 0x03B0, -37}, {0x1F30, 0x1F38, 8}, {0x1FB0, 0x1FB2, 8},
{0x03B1, 0x03C2, -32}, {0x1F40, 0x1F46, 8}, {0x1FD0, 0x1FD2, 8},
{0x03C2, 0x03C3, -31}, {0x1F51, 0x1F52, 8}, {0x1FE0, 0x1FE2, 8},
{0x03C3, 0x03CC, -32}, {0x1F53, 0x1F54, 8}, {0x1FE5, 0x1FE6, 7},
{0x03CC, 0x03CD, -64}, {0x1F55, 0x1F56, 8}, {0x2170, 0x2180, -16},
{0x03CD, 0x03CF, -63}, {0x1F57, 0x1F58, 8}, {0x24D0, 0x24EA, -26},
{0x0430, 0x0450, -32}, {0x1F60, 0x1F68, 8}, {0xFF41, 0xFF5B, -32},
{0}
};
static int uc_dup_table[][2] = { /* Start, End */
{0x0100, 0x012F}, {0x01A0, 0x01A6}, {0x03E2, 0x03EF}, {0x04CB, 0x04CC},
{0x0132, 0x0137}, {0x01B3, 0x01B7}, {0x0460, 0x0481}, {0x04D0, 0x04EB},
{0x0139, 0x0149}, {0x01CD, 0x01DD}, {0x0490, 0x04BF}, {0x04EE, 0x04F5},
{0x014A, 0x0178}, {0x01DE, 0x01EF}, {0x04BF, 0x04BF}, {0x04F8, 0x04F9},
{0x0179, 0x017E}, {0x01F4, 0x01F5}, {0x04C1, 0x04C4}, {0x1E00, 0x1E95},
{0x018B, 0x018B}, {0x01FA, 0x0218}, {0x04C7, 0x04C8}, {0x1EA0, 0x1EF9},
{0}
};
static int uc_byte_table[][2] = { /* Offset, Value */
{0x00FF, 0x0178}, {0x01AD, 0x01AC}, {0x01F3, 0x01F1}, {0x0269, 0x0196},
{0x0183, 0x0182}, {0x01B0, 0x01AF}, {0x0253, 0x0181}, {0x026F, 0x019C},
{0x0185, 0x0184}, {0x01B9, 0x01B8}, {0x0254, 0x0186}, {0x0272, 0x019D},
{0x0188, 0x0187}, {0x01BD, 0x01BC}, {0x0259, 0x018F}, {0x0275, 0x019F},
{0x018C, 0x018B}, {0x01C6, 0x01C4}, {0x025B, 0x0190}, {0x0283, 0x01A9},
{0x0192, 0x0191}, {0x01C9, 0x01C7}, {0x0260, 0x0193}, {0x0288, 0x01AE},
{0x0199, 0x0198}, {0x01CC, 0x01CA}, {0x0263, 0x0194}, {0x0292, 0x01B7},
{0x01A8, 0x01A7}, {0x01DD, 0x018E}, {0x0268, 0x0197},
{0}
};
int i, r;
memset(uc, 0, uc_len);
uc_len >>= 1;
/* Generate the little endian Unicode upcase table used by ntfs. */
for (i = 0; (u32)i < uc_len; i++)
uc[i] = cpu_to_le16(i);
for (r = 0; uc_run_table[r][0]; r++)
for (i = uc_run_table[r][0]; i < uc_run_table[r][1]; i++)
uc[i] = cpu_to_le16(le16_to_cpu(uc[i]) +
uc_run_table[r][2]);
for (r = 0; uc_dup_table[r][0]; r++)
for (i = uc_dup_table[r][0]; i < uc_dup_table[r][1]; i += 2)
uc[i + 1] = cpu_to_le16(le16_to_cpu(uc[i + 1]) - 1);
for (r = 0; uc_byte_table[r][0]; r++)
uc[uc_byte_table[r][0]] = cpu_to_le16(uc_byte_table[r][1]);
}

View File

@ -1,7 +0,0 @@
#ifndef _NTFS_UPCASE_H_
#define _NTFS_UPCASE_H_
void init_upcase_table(ntfschar *uc, u32 uc_len);
#endif /* _NTFS_UPCASE_H_ */

View File

@ -4,6 +4,7 @@
* Copyright (c) 2002-2005 Richard Russon
* Copyright (c) 2003-2006 Anton Altaparmakov
* Copyright (c) 2003 Lode Leroy
* Copyright (c) 2005-2007 Yura Pakhuchiy
*
* A set of shared functions for ntfs utilities
*
@ -82,6 +83,50 @@ const char *ntfs_gpl = "This program is free software, released under the GNU "
"\"COPYING\" distributed with this program, or online at:\n"
"http://www.gnu.org/copyleft/gpl.html\n";
static const char *invalid_ntfs_msg =
"The device '%s' doesn't have a valid NTFS.\n"
"Maybe you selected the wrong device? Or the whole disk instead of a\n"
"partition (e.g. /dev/hda, not /dev/hda1)? Or the other way around?\n";
static const char *corrupt_volume_msg =
"NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n"
"The usage of the /f parameter is very IMPORTANT! No modification was\n"
"made to NTFS by this software.\n";
static const char *hibernated_volume_msg =
"The NTFS partition is hibernated. Please resume Windows and turned it \n"
"off properly, so mounting could be done safely.\n";
static const char *unclean_journal_msg =
"Access is denied because the NTFS journal file is unclean. Choices are:\n"
" A) Shutdown Windows properly.\n"
" B) Click the 'Safely Remove Hardware' icon in the Windows taskbar\n"
" notification area before disconnecting the device.\n"
" C) Use 'Eject' from Windows Explorer to safely remove the device.\n"
" D) If you ran chkdsk previously then boot Windows again which will\n"
" automatically initialize the journal.\n"
" E) Submit 'force' option (WARNING: This solution it not recommended).\n"
" F) ntfsmount: Mount the volume read-only by using the 'ro' mount option.\n";
static const char *opened_volume_msg =
"Access is denied because the NTFS volume is already exclusively opened.\n"
"The volume may be already mounted, or another software may use it which\n"
"could be identified for example by the help of the 'fuser' command.\n";
static const char *dirty_volume_msg =
"Volume is scheduled for check.\n"
"Please boot into Windows TWICE, or use the 'force' option.\n"
"NOTE: If you had not scheduled check and last time accessed this volume\n"
"using ntfsmount and shutdown system properly, then init scripts in your\n"
"distribution are broken. Please report to your distribution developers\n"
"(NOT to us!) that init scripts kill ntfsmount or mount.ntfs-fuse during\n"
"shutdown instead of proper umount.\n";
static const char *fakeraid_msg =
"You seem to have a SoftRAID/FakeRAID hardware and must use an activated,\n"
"different device under /dev/mapper, (e.g. /dev/mapper/nvidia_eahaabcc1)\n"
"to mount NTFS. Please see the 'dmraid' documentation for help.\n";
/**
* utils_set_locale
*/
@ -92,16 +137,16 @@ int utils_set_locale(void)
locale = setlocale(LC_ALL, "");
if (!locale) {
locale = setlocale(LC_ALL, NULL);
ntfs_log_error("Failed to set locale, using default '%s'.\n", locale);
ntfs_log_error("Failed to set locale, using default '%s'.\n",
locale);
return 1;
} else {
return 0;
}
}
#ifndef NTFS_RICH
/**
* utils_valid_device - Perform some safety checks on the device, before we start
* utils_valid_device - Perform some safety checks on the device, before start
* @name: Full pathname of the device/file to work with
* @force: Continue regardless of problems
*
@ -117,7 +162,7 @@ int utils_valid_device(const char *name, int force)
struct stat st;
#ifdef __CYGWIN32__
/* FIXME: This doesn't work for Cygwin, so just return success for now... */
/* FIXME: This doesn't work for Cygwin, so just return success. */
return 1;
#endif
if (!name) {
@ -126,37 +171,30 @@ int utils_valid_device(const char *name, int force)
}
if (stat(name, &st) == -1) {
if (errno == ENOENT) {
if (errno == ENOENT)
ntfs_log_error("The device %s doesn't exist\n", name);
} else {
ntfs_log_perror("Error getting information about %s", name);
}
else
ntfs_log_perror("Error getting information about %s",
name);
return 0;
}
if (!S_ISBLK(st.st_mode) && !S_ISREG(st.st_mode)) {
ntfs_log_warning("%s is not a block device, "
"nor regular file.\n", name);
if (!force) {
ntfs_log_error("Use the force option to work with other"
" file types, for your own risk!\n");
return 0;
}
ntfs_log_warning("Forced to continue.\n");
}
/* Make sure the file system is not mounted. */
if (ntfs_check_if_mounted(name, &mnt_flags)) {
ntfs_log_perror("Failed to determine whether %s is mounted", name);
ntfs_log_perror("Failed to determine whether %s is mounted",
name);
if (!force) {
ntfs_log_error("Use the force option to ignore this error.\n");
ntfs_log_error("Use the force option to ignore this "
"error.\n");
return 0;
}
ntfs_log_warning("Forced to continue.\n");
} else if (mnt_flags & NTFS_MF_MOUNTED) {
ntfs_log_warning("The device %s, is mounted.\n", name);
if (!force) {
ntfs_log_error("Use the force option to work a mounted filesystem.\n");
ntfs_log_error("%s", opened_volume_msg);
ntfs_log_error("You can use force option to avoid this "
"check, but this is not recommended\n"
"and may lead to data corruption.\n");
return 0;
}
ntfs_log_warning("Forced to continue.\n");
@ -168,7 +206,7 @@ int utils_valid_device(const char *name, int force)
/**
* utils_mount_volume - Mount an NTFS volume
*/
ntfs_volume * utils_mount_volume(const char *device, unsigned long flags, BOOL force)
ntfs_volume * utils_mount_volume(const char *device, ntfs_mount_flags flags)
{
ntfs_volume *vol;
@ -177,42 +215,39 @@ ntfs_volume * utils_mount_volume(const char *device, unsigned long flags, BOOL f
return NULL;
}
if (!utils_valid_device(device, force))
if (!utils_valid_device(device, flags & NTFS_MNT_FORCE))
return NULL;
vol = ntfs_mount(device, flags);
if (!vol) {
int err;
err = errno;
ntfs_log_perror("Couldn't mount device '%s'", device);
if (err == EPERM)
ntfs_log_error("Windows was hibernated. Try to mount "
"volume in windows, shut down and try "
"again.\n");
if (err == EOPNOTSUPP)
ntfs_log_error("Windows did not shut down properly. "
"Try to mount volume in windows, "
"shut down and try again.\n");
ntfs_log_perror("Failed to mount '%s'", device);
if (errno == EINVAL)
ntfs_log_error(invalid_ntfs_msg, device);
else if (errno == EIO)
ntfs_log_error("%s", corrupt_volume_msg);
else if (errno == EPERM)
ntfs_log_error("%s", hibernated_volume_msg);
else if (errno == EOPNOTSUPP)
ntfs_log_error("%s", unclean_journal_msg);
else if (errno == EBUSY)
ntfs_log_error("%s", opened_volume_msg);
else if (errno == ENXIO)
ntfs_log_error("%s", fakeraid_msg);
return NULL;
}
if (vol->flags & VOLUME_IS_DIRTY) {
ntfs_log_warning("Volume is dirty.\n");
if (!force) {
ntfs_log_error("Run chkdsk and try again, or use the "
"force option.\n");
if (NVolWasDirty(vol)) {
if (!(flags & NTFS_MNT_FORCE)) {
ntfs_log_error("%s", dirty_volume_msg);
ntfs_umount(vol, FALSE);
return NULL;
}
ntfs_log_warning("Forced to continue.\n");
ntfs_log_error("WARNING: Dirty volume mount was forced by the "
"'force' mount option.\n");
}
return vol;
}
#endif
/**
* utils_parse_size - Convert a string representing a size
* @value: String to be parsed
@ -334,7 +369,6 @@ int utils_parse_range(const char *string, s64 *start, s64 *finish, BOOL scale)
return 1;
}
#ifndef NTFS_RICH
/**
* find_attribute - Find an attribute of the given type
* @type: An attribute type, e.g. AT_FILE_NAME
@ -404,7 +438,6 @@ ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
return rec;
}
#endif
/**
* utils_inode_get_name
*
@ -415,11 +448,12 @@ ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
* if parent is 5 (/) stop
* get inode of parent
*/
#define max_path 20
int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
{
// XXX option: names = posix/win32 or dos
// flags: path, filename, or both
const int max_path = 20;
ntfs_volume *vol;
ntfs_attr_search_ctx *ctx;
@ -427,7 +461,7 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
FILE_NAME_ATTR *attr;
int name_space;
MFT_REF parent = FILE_root;
char *names[max_path + 1];// XXX malloc? and make max bigger?
char *names[max_path + 1];// XXX ntfs_malloc? and make max bigger?
int i, len, offset = 0;
if (!inode || !buffer) {
@ -471,7 +505,7 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
&names[i], 0) < 0) {
char *temp;
ntfs_log_error("Couldn't translate filename to current locale.\n");
temp = malloc(30);
temp = ntfs_malloc(30);
if (!temp)
return 0;
snprintf(temp, 30, "<MFT%llu>", (unsigned
@ -529,6 +563,7 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
return 1;
}
#undef max_path
/**
* utils_attr_get_name
@ -550,7 +585,8 @@ int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int b
name = NULL;
namelen = ntfs_ucsnlen(attrdef->name, sizeof(attrdef->name));
if (ntfs_ucstombs(attrdef->name, namelen, &name, 0) < 0) {
ntfs_log_error("Couldn't translate attribute type to current locale.\n");
ntfs_log_error("Couldn't translate attribute type to "
"current locale.\n");
// <UNKNOWN>?
return 0;
}
@ -574,9 +610,10 @@ int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int b
name = NULL;
namelen = attr->name_length;
if (ntfs_ucstombs((ntfschar *)((char *)attr + attr->name_offset),
namelen, &name, 0) < 0) {
ntfs_log_error("Couldn't translate attribute name to current locale.\n");
if (ntfs_ucstombs((ntfschar *)((char *)attr + le16_to_cpu(
attr->name_offset)), namelen, &name, 0) < 0) {
ntfs_log_error("Couldn't translate attribute name to current "
"locale.\n");
// <UNKNOWN>?
len = snprintf(buffer, bufsize, "<UNKNOWN>");
return 0;
@ -604,7 +641,10 @@ int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int b
*
* This function has a static buffer in which it caches a section of $Bitmap.
* If the lcn, being tested, lies outside the range, the buffer will be
* refreshed.
* refreshed. @bmplcn stores offset to the first bit (in bits) stored in the
* buffer.
*
* NOTE: Be very carefull with shifts by 3 everywhere in this function.
*
* Return: 1 Cluster is in use
* 0 Cluster is free space
@ -613,8 +653,7 @@ int utils_attr_get_name(ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int b
int utils_cluster_in_use(ntfs_volume *vol, long long lcn)
{
static unsigned char buffer[512];
static long long bmplcn = -sizeof(buffer) - 1; /* Which bit of $Bitmap is in the buffer */
static long long bmplcn = -(sizeof(buffer) << 3);
int byte, bit;
ntfs_attr *attr;
@ -636,7 +675,8 @@ int utils_cluster_in_use(ntfs_volume *vol, long long lcn)
memset(buffer, 0xFF, sizeof(buffer));
bmplcn = lcn & (~((sizeof(buffer) << 3) - 1));
if (ntfs_attr_pread(attr, (bmplcn>>3), sizeof(buffer), buffer) < 0) {
if (ntfs_attr_pread(attr, (bmplcn >> 3), sizeof(buffer),
buffer) < 0) {
ntfs_log_perror("Couldn't read $Bitmap");
ntfs_attr_close(attr);
return -1;
@ -648,7 +688,9 @@ int utils_cluster_in_use(ntfs_volume *vol, long long lcn)
bit = 1 << (lcn & 7);
byte = (lcn >> 3) & (sizeof(buffer) - 1);
ntfs_log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] & bit);
ntfs_log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, "
"in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] &
bit);
return (buffer[byte] & bit);
}
@ -674,15 +716,15 @@ int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref)
{
static u8 buffer[512];
static s64 bmpmref = -sizeof(buffer) - 1; /* Which bit of $BITMAP is in the buffer */
int byte, bit;
ntfs_log_trace("Entering.\n");
if (!vol) {
errno = EINVAL;
return -1;
}
ntfs_log_trace("entering\n");
/* Does mref lie in the section of $Bitmap we already have cached? */
if (((s64)MREF(mref) < bmpmref) || ((s64)MREF(mref) >= (bmpmref +
(sizeof(buffer) << 3)))) {
@ -757,7 +799,7 @@ int utils_is_metadata(ntfs_inode *inode)
file = inode->mrec;
if (file && (file->base_mft_record != 0)) {
num = MREF(file->base_mft_record);
num = MREF_LE(file->base_mft_record);
if (__metadata(vol, num) == 1)
return 1;
}
@ -768,9 +810,9 @@ int utils_is_metadata(ntfs_inode *inode)
return -1;
/* We know this will always be resident. */
attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu(rec->value_offset));
attr = (FILE_NAME_ATTR *)((char *)rec + le16_to_cpu(rec->value_offset));
num = MREF(attr->parent_directory);
num = MREF_LE(attr->parent_directory);
if ((num != FILE_root) && (__metadata(vol, num) == 1))
return 1;
@ -971,10 +1013,9 @@ int mft_next_record(struct mft_search_ctx *ctx)
ctx->inode->mft_no = ctx->mft_num;
ctx->inode->vol = ctx->vol;
ctx->inode->mrec = malloc(ctx->vol->mft_record_size);
ctx->inode->mrec = ntfs_malloc(ctx->vol->mft_record_size);
if (!ctx->inode->mrec) {
free(ctx->inode); // == ntfs_inode_close
ntfs_log_error("Out of memory. Aborting.\n");
return -1;
}

View File

@ -52,15 +52,11 @@ int utils_mftrec_in_use(ntfs_volume *vol, MFT_REF mref);
int utils_is_metadata(ntfs_inode *inode);
void utils_dump_mem(void *buf, int start, int length, int flags);
#ifndef _NTFS_RICH_H_
ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft);
#endif
#if !(defined(_NTFS_VOLUME_H) && defined(NTFS_RICH))
int utils_valid_device(const char *name, int force);
ntfs_volume * utils_mount_volume(const char *device, unsigned long flags, BOOL force);
#endif
ntfs_volume * utils_mount_volume(const char *device, ntfs_mount_flags flags);
/**
* defines...

View File

@ -57,3 +57,6 @@ testf: runlist
diff -qs {runlist-data/,}frag$$i; \
done
dist-hook:
rm -rf `find $(distdir)/runlist-data -name CVS`