mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Merge remote branch 'linux-ntfs/libntfs-3g_port-v2_0_0' into PERMISSION_HANDLING_BRANCH
Conflicts: .cvsignore AUTHORS CREDITS ChangeLog NEWS README TODO.libntfs autogen.sh configure.ac include/ntfs/Makefile.am libntfs-3g/misc.c libntfs/Makefile.am libntfs/gnome-vfs-method.c libntfs/gnome-vfs-module.c ntfsprogs.spec.in ntfsprogs/.cvsignore ntfsprogs/mkntfs.c ntfsprogs/ntfscat.8.in ntfsprogs/ntfsclone.c ntfsprogs/ntfscp.8.in ntfsprogs/ntfsinfo.c ntfsprogs/ntfsprogs.8.in ntfsprogs/ntfsresize.c ntfsprogs/ntfsrm.c ntfsprogs/ntfsundelete.h ntfsprogs/upcase.c ntfsprogs/utils.c test/Makefile.am
This commit is contained in:
commit
bcdc76f12d
@ -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.
|
||||
|
||||
|
||||
**************
|
||||
|
58
configure.ac
58
configure.ac
@ -278,7 +278,7 @@ fi
|
||||
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([ntfsprogs crypto code requires the gcrypt library.])
|
||||
@ -287,17 +287,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([ntfsprogs crypto code requires the gnutls library.])
|
||||
else
|
||||
AC_MSG_WARN([ntfsprogs 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([ntfsprogs crypto code requires the libconfig.])
|
||||
else
|
||||
AC_MSG_WARN([ntfsprogs crypto code requires the libconfig.])
|
||||
fi
|
||||
)
|
||||
if test "$have_libgcrypt" = "true"; then
|
||||
if test "$have_libgnutls" = "true"; then
|
||||
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
|
||||
@ -309,6 +321,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([ntfsprogs DCE compliant UUID generation code requires the uuid library.]),
|
||||
),
|
||||
AC_MSG_WARN([ntfsprogs DCE compliant UUID generation code requires the uuid library.]),
|
||||
)
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS([ctype.h fcntl.h libgen.h libintl.h limits.h locale.h \
|
||||
@ -317,7 +365,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/mkdev.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
|
||||
|
46
include/ntfs/crypto.h
Normal file
46
include/ntfs/crypto.h
Normal 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 */
|
10
libntfs/config
Normal file
10
libntfs/config
Normal 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
Normal file
1518
libntfs/crypto.c
Normal file
File diff suppressed because it is too large
Load Diff
546
libntfs/freebsd_io.c
Normal file
546
libntfs/freebsd_io.c
Normal 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,
|
||||
};
|
34
libntfs/libntfs.8.in
Normal file
34
libntfs/libntfs.8.in
Normal 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
Normal file
63
libntfs/misc.c
Normal 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;
|
||||
}
|
@ -17,7 +17,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 \
|
||||
@ -40,8 +40,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
|
||||
@ -80,6 +81,10 @@ 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)
|
||||
@ -108,8 +113,9 @@ 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_LDADD = $(AM_LIBS) $(GNUTLS_LIBS) $(LIBGCRYPT_LIBS)
|
||||
ntfsdecrypt_LDFLAGS = $(AM_LFLAGS)
|
||||
ntfsdecrypt_CFLAGS = $(GNUTLS_CFLAGS) $(LIBGCRYPT_CFLAGS)
|
||||
endif
|
||||
|
||||
# Extra targets
|
||||
|
@ -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
|
||||
|
@ -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_ */
|
||||
|
488
ntfsprogs/boot.c
488
ntfsprogs/boot.c
@ -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
|
||||
};
|
||||
|
@ -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_ */
|
||||
|
||||
|
@ -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,
|
||||
|
1252
ntfsprogs/mkntfs.c
1252
ntfsprogs/mkntfs.c
File diff suppressed because it is too large
Load Diff
@ -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" "ntfs-3g @VERSION@"
|
||||
.TH NTFSCAT 8 "September 2007" "ntfs-3g @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)
|
||||
|
@ -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,9 +359,10 @@ 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);
|
||||
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, MS_RDONLY |
|
||||
(opts.force ? MS_RECOVER : 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);
|
||||
|
@ -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_ */
|
||||
|
868
ntfsprogs/ntfsck.c
Normal file
868
ntfsprogs/ntfsck.c
Normal file
@ -0,0 +1,868 @@
|
||||
/**
|
||||
* 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 <ntfs-3g/layout.h>
|
||||
#include <ntfs-3g/bitmap.h>
|
||||
#include <ntfs-3g/endians.h>
|
||||
#include <ntfs-3g/bootsect.h>
|
||||
#include <ntfs-3g/misc.h>
|
||||
|
||||
#include "cluster.h"
|
||||
#include "utils.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, MS_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;
|
||||
}
|
||||
|
@ -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 "debug.h"
|
||||
#include "types.h"
|
||||
#include "support.h"
|
||||
@ -73,6 +79,7 @@
|
||||
#include "ntfstime.h"
|
||||
#include "utils.h"
|
||||
/* #include "version.h" */
|
||||
#include "misc.h"
|
||||
|
||||
#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
|
||||
#define BLKGETSIZE _IO(0x12,96) /* Get device size in 512-byte blocks. */
|
||||
@ -95,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;
|
||||
@ -116,7 +123,6 @@ struct {
|
||||
struct bitmap {
|
||||
s64 size;
|
||||
u8 *bm;
|
||||
u8 padding[4]; /* Unused: padding to 64 bit. */
|
||||
};
|
||||
|
||||
struct progress_bar {
|
||||
@ -140,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;
|
||||
@ -165,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"
|
||||
@ -527,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;
|
||||
|
||||
@ -589,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");
|
||||
@ -629,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");
|
||||
}
|
||||
|
||||
@ -678,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;
|
||||
@ -686,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;
|
||||
@ -718,6 +756,7 @@ 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;
|
||||
@ -744,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;
|
||||
}
|
||||
|
||||
@ -756,22 +796,25 @@ static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -779,8 +822,9 @@ static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
|
||||
while ((u8 *)tmp_indexa < (u8 *)indexa + na->data_size) {
|
||||
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(
|
||||
@ -792,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);
|
||||
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:
|
||||
@ -847,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
|
||||
@ -866,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); \
|
||||
@ -1137,6 +1181,21 @@ static void mft_record_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
|
||||
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;
|
||||
@ -1159,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");
|
||||
|
||||
@ -1208,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))
|
||||
@ -1240,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);
|
||||
@ -1260,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));
|
||||
|
||||
@ -1276,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",
|
||||
Printf("Ntfsclone image version: %d.%d\n",
|
||||
image_hdr.major_ver, image_hdr.minor_ver);
|
||||
Printf("Cluster size : %u bytes\n",
|
||||
(unsigned int)image_hdr.cluster_size);
|
||||
(unsigned)le32_to_cpu(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);
|
||||
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)
|
||||
@ -1348,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)
|
||||
{
|
||||
@ -1475,14 +1541,61 @@ 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)
|
||||
@ -1508,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)
|
||||
@ -1610,6 +1725,7 @@ 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;
|
||||
@ -1623,6 +1739,13 @@ static void check_dest_free_space(u64 src_bytes)
|
||||
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;
|
||||
@ -1651,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) {
|
||||
@ -1671,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)
|
||||
@ -1691,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);
|
||||
|
||||
|
@ -491,7 +491,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, MS_RDONLY |
|
||||
(opts.force ? MS_RECOVER : 0));
|
||||
if (!vol)
|
||||
return 1;
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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) 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,10 @@
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <ntfs-3g/mst.h>
|
||||
#include <ntfs-3g/support.h>
|
||||
#include <ntfs-3g/misc.h>
|
||||
|
||||
#include "utils.h"
|
||||
/* #include "version.h" */
|
||||
|
||||
@ -37,7 +57,7 @@ static const char *hibernated_volume_msg =
|
||||
"turned off properly\n";
|
||||
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
int debug;
|
||||
int show_progress;
|
||||
int verbose;
|
||||
@ -55,7 +75,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 +327,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 +404,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 +484,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,15 +636,9 @@ 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__);
|
||||
print_na(na1);
|
||||
@ -531,7 +658,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,6 +702,9 @@ static void cmp_attribute(ntfs_attr_search_ctx *ctx1,
|
||||
return;
|
||||
}
|
||||
|
||||
if (na1->type == AT_INDEX_ALLOCATION)
|
||||
cmp_index_allocation(na1, na2);
|
||||
else
|
||||
cmp_attribute_data(na1, na2);
|
||||
|
||||
close_attribs:
|
||||
@ -708,9 +838,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 +856,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");
|
||||
|
@ -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" "ntfs-3g @VERSION@"
|
||||
.TH NTFSCP 8 "September 2007" "ntfs-3g @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,26 @@ 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
|
||||
ntfs\-3g\-devel@lists.sf.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
|
||||
<<<<<<< HEAD
|
||||
.B ntfscp
|
||||
is part of the
|
||||
.B ntfs-3g
|
||||
package and is available from:
|
||||
=======
|
||||
\fBntfscp\fR is part of the \fBntfsprogs\fR package and is available from:
|
||||
>>>>>>> linux-ntfs/libntfs-3g_port-v2_0_0
|
||||
.br
|
||||
.nh
|
||||
http://www.tuxera.com/community/
|
||||
|
@ -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 "types.h"
|
||||
#include "attrib.h"
|
||||
@ -68,7 +72,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
|
||||
@ -79,9 +83,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);
|
||||
}
|
||||
|
||||
@ -178,7 +184,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++;
|
||||
@ -270,6 +276,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, 0, ufilename, ufilename_len, S_IFREG);
|
||||
free(ufilename);
|
||||
return ni;
|
||||
}
|
||||
|
||||
/**
|
||||
* main - Begin here
|
||||
*
|
||||
@ -313,14 +347,16 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (opts.noaction)
|
||||
flags = MS_RDONLY;
|
||||
if (opts.force)
|
||||
flags |= MS_RECOVER;
|
||||
|
||||
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 ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
|
||||
goto umount;
|
||||
|
||||
{
|
||||
@ -352,45 +388,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);
|
||||
@ -424,7 +528,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;
|
||||
}
|
||||
|
@ -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 "types.h"
|
||||
#include "attrib.h"
|
||||
@ -74,6 +67,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)
|
||||
*
|
||||
@ -101,14 +107,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;
|
||||
@ -446,19 +452,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) {
|
||||
@ -474,7 +495,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
|
||||
@ -491,9 +512,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);
|
||||
@ -501,29 +522,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) {
|
||||
@ -534,14 +557,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,
|
||||
@ -551,7 +574,7 @@ check_again:
|
||||
"key from DER to GNU TLS "
|
||||
"format: %s\n",
|
||||
gnutls_strerror(err));
|
||||
goto key_out;
|
||||
goto err;
|
||||
}
|
||||
#if 0
|
||||
/*
|
||||
@ -579,38 +602,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:
|
||||
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);
|
||||
bag_out:
|
||||
if (bag)
|
||||
gnutls_pkcs12_bag_deinit(bag);
|
||||
out:
|
||||
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 -
|
||||
*
|
||||
@ -971,23 +1062,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);
|
||||
@ -1039,7 +1134,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;
|
||||
@ -1083,7 +1179,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;
|
||||
@ -1093,14 +1190,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. */
|
||||
@ -1115,8 +1239,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;
|
||||
}
|
||||
@ -1125,10 +1247,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. */
|
||||
@ -1137,17 +1260,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) {
|
||||
/*
|
||||
* 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));
|
||||
fek = ntfs_df_array_fek_get(df_array, rsa_key);
|
||||
}
|
||||
if (!fek && efs->offset_to_drf_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));
|
||||
fek = ntfs_df_array_fek_get(df_array, rsa_key);
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -1178,18 +1313,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)
|
||||
{
|
||||
@ -1272,6 +1409,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);
|
||||
|
||||
@ -1300,19 +1439,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, MS_RDONLY |
|
||||
(opts.force ? MS_RECOVER : 0));
|
||||
if (!vol) {
|
||||
ntfs_log_error("Failed to mount ntfs volume. Aborting.\n");
|
||||
ntfs_rsa_private_key_release(rsa_key);
|
||||
@ -1332,7 +1472,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);
|
||||
|
@ -197,6 +197,9 @@ static int logfile_open(BOOL is_volume, const char *filename,
|
||||
ntfs_inode *ni;
|
||||
ntfs_attr *na;
|
||||
|
||||
/* Porting note: NTFS_MNT_FORENSIC is not needed when we mount
|
||||
* the volume in read-only mode. No changes will be made to the
|
||||
* logfile or anything else when we are in read only-mode. */
|
||||
vol = ntfs_mount(filename, MS_RDONLY);
|
||||
if (!vol)
|
||||
log_err_exit(NULL, "Failed to mount %s: %s\n",
|
||||
|
@ -21,7 +21,7 @@ check for the first boot into Windows.
|
||||
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
|
||||
|
@ -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.
|
||||
@ -82,10 +83,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;
|
||||
|
||||
@ -118,8 +117,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);
|
||||
@ -170,7 +170,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;
|
||||
@ -227,7 +227,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;
|
||||
@ -245,56 +245,33 @@ err_exit:
|
||||
*/
|
||||
static int set_dirty_flag(ntfs_volume *vol)
|
||||
{
|
||||
u16 flags;
|
||||
le16 flags;
|
||||
|
||||
if (vol_is_dirty == TRUE)
|
||||
/* Porting note: We test for the current state of VOLUME_IS_DIRTY. This
|
||||
* should actually be more appropriate than testing for NVolWasDirty. */
|
||||
if (vol->flags | VOLUME_IS_DIRTY)
|
||||
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;
|
||||
|
||||
/* Porting note: libntfs-3g does not have the 'WasDirty' flag/property,
|
||||
* and never touches the 'dirty' bit except when explicitly told to do
|
||||
* so. Since we just wrote the VOLUME_IS_DIRTY bit to disk, and
|
||||
* vol->flags is up-to-date, we can just ignore the NVolSetWasDirty
|
||||
* statement. */
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -303,9 +280,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);
|
||||
@ -313,7 +289,6 @@ static int empty_journal(ntfs_volume *vol)
|
||||
return -1;
|
||||
}
|
||||
ntfs_log_info(OK);
|
||||
journal_is_empty = TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -398,7 +373,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 "
|
||||
@ -406,7 +381,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 "
|
||||
@ -416,14 +391,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);
|
||||
@ -431,7 +406,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))) {
|
||||
@ -475,13 +450,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);
|
||||
@ -490,17 +465,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. */
|
||||
@ -550,6 +520,20 @@ int main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
/* So the unmount does not clear it again. */
|
||||
|
||||
/* Porting note: The WasDirty flag was set here to prevent ntfs_unmount
|
||||
* from clearing the dirty bit (which might have been set in
|
||||
* fix_mount()). So the intention is to leave the dirty bit set.
|
||||
*
|
||||
* libntfs-3g does not automatically set or clear dirty flags on
|
||||
* mount/unmount, this means that the assumption that the dirty flag is
|
||||
* now set does not hold. So we need to set it if not already set. */
|
||||
if(!(vol->flags & VOLUME_IS_DIRTY) && ntfs_volume_write_flags(vol,
|
||||
vol->flags | VOLUME_IS_DIRTY)) {
|
||||
ntfs_log_error("Error: Failed to set volume dirty flag (%d "
|
||||
"(%s))!\n", errno, strerror(errno));
|
||||
}
|
||||
|
||||
/* Check NTFS version is ok for us (in $Volume) */
|
||||
ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
|
||||
@ -558,22 +542,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
@ -325,7 +325,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)) {
|
||||
@ -393,8 +393,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 ? MS_RDONLY : 0) |
|
||||
(opts.force ? MS_RECOVER : 0));
|
||||
if (!vol)
|
||||
return 1;
|
||||
|
||||
|
@ -650,7 +650,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, MS_RDONLY |
|
||||
(opts.force ? MS_RECOVER : 0));
|
||||
if (!vol) {
|
||||
// FIXME: Print error... (AIA)
|
||||
return 2;
|
||||
|
@ -745,7 +745,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
|
||||
@ -790,7 +791,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,8 +875,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (opts.noaction)
|
||||
flags |= MS_RDONLY;
|
||||
if (opts.force)
|
||||
flags |= MS_RECOVER;
|
||||
|
||||
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;
|
||||
@ -888,10 +892,19 @@ 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");
|
||||
|
||||
/* Porting note: libntfs-3g does not automatically set or clear
|
||||
* dirty flags on mount/unmount. It always preserves them until
|
||||
* they are explicitly changed with ntfs_volume_write_flags.
|
||||
* This means that the dirty flag is possibly not set, but
|
||||
* should be set. So we explicitly set it with a call to
|
||||
* ntfs_volume_write_flags. */
|
||||
if(!(vol->flags & VOLUME_IS_DIRTY) && ntfs_volume_write_flags(
|
||||
vol, vol->flags | VOLUME_IS_DIRTY)) {
|
||||
ntfs_log_error("Error: Failed to set volume dirty "
|
||||
"flag (%d (%s))!\n", errno, strerror(errno));
|
||||
}
|
||||
|
||||
ntfs_log_info("Relocated %lld bytes\n", count);
|
||||
}
|
||||
if (count >= 0)
|
||||
|
@ -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_ */
|
||||
|
@ -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" "ntfs-3g @VERSION@"
|
||||
.TH NTFSPROGS 8 "September 2007" "ntfs-3g @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
|
||||
|
@ -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.
|
||||
*
|
||||
@ -65,6 +66,7 @@
|
||||
#include "runlist.h"
|
||||
#include "utils.h"
|
||||
/* #include "version.h" */
|
||||
#include "misc.h"
|
||||
|
||||
static const char *EXEC_NAME = "ntfsresize";
|
||||
|
||||
@ -125,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;
|
||||
@ -140,7 +142,6 @@ struct {
|
||||
struct bitmap {
|
||||
s64 size;
|
||||
u8 *bm;
|
||||
u8 padding[4]; /* Unused: padding to 64 bit. */
|
||||
};
|
||||
|
||||
#define NTFS_PROGBAR 0x0001
|
||||
@ -152,7 +153,6 @@ struct progress_bar {
|
||||
int resolution;
|
||||
int flags;
|
||||
float unit;
|
||||
u8 padding[4]; /* Unused: padding to 64 bit. */
|
||||
};
|
||||
|
||||
struct llcn_t {
|
||||
@ -202,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)
|
||||
|
||||
@ -349,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);
|
||||
@ -369,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);
|
||||
}
|
||||
|
||||
@ -803,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;
|
||||
@ -823,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;
|
||||
}
|
||||
@ -1173,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)
|
||||
@ -1200,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");
|
||||
@ -1468,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;
|
||||
@ -1611,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;
|
||||
@ -1719,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;
|
||||
@ -1874,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);
|
||||
|
||||
@ -1951,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);
|
||||
|
||||
@ -2119,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);
|
||||
@ -2152,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;
|
||||
}
|
||||
|
||||
@ -2237,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);
|
||||
@ -2286,31 +2291,26 @@ static ntfs_volume *mount_volume(void)
|
||||
*/
|
||||
static void prepare_volume_fixup(ntfs_volume *vol)
|
||||
{
|
||||
u16 flags;
|
||||
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");
|
||||
|
||||
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");
|
||||
/* Porting note: This flag does not exist in libntfs-3g. The dirty flag
|
||||
* is never modified by libntfs-3g on unmount and we set it above. We
|
||||
* can safely comment out this statement. */
|
||||
/* 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) */
|
||||
@ -2393,7 +2393,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);
|
||||
|
@ -715,7 +715,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);
|
||||
@ -807,4 +807,3 @@ int main(int argc, char **argv)
|
||||
ntfs_log_quiet("ntfstruncate completed successfully. Have a nice day.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2002-2005 Richard Russon
|
||||
* Copyright (c) 2004-2005 Holger Ohmacht
|
||||
* Copyright (c) 2005 Anton Altaparmakov
|
||||
* Copyright (c) 2007 Yura Pakhuchiy
|
||||
*
|
||||
* This utility will recover deleted files from an NTFS volume.
|
||||
*
|
||||
@ -221,10 +222,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);
|
||||
}
|
||||
|
||||
@ -833,7 +836,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;
|
||||
}
|
||||
|
||||
@ -841,10 +845,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,
|
||||
@ -905,11 +911,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;
|
||||
}
|
||||
@ -989,28 +997,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->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);
|
||||
@ -1168,17 +1180,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;
|
||||
@ -1186,12 +1201,14 @@ 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;
|
||||
}
|
||||
|
||||
@ -1287,12 +1304,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))) {
|
||||
@ -1309,13 +1332,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);
|
||||
}
|
||||
|
||||
@ -1348,7 +1375,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");
|
||||
@ -1401,10 +1429,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);
|
||||
}
|
||||
@ -2122,7 +2154,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, MS_RDONLY |
|
||||
(opts.force ? MS_RECOVER : 0));
|
||||
if (!vol)
|
||||
return 1;
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
@ -27,6 +28,7 @@
|
||||
#include "types.h"
|
||||
#include "list.h"
|
||||
#include "runlist.h"
|
||||
#include "utils.h"
|
||||
|
||||
enum optmode {
|
||||
MODE_NONE = 0,
|
||||
@ -57,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 {
|
||||
@ -73,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 {
|
||||
@ -93,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 {
|
||||
@ -107,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_ */
|
||||
|
@ -1340,12 +1340,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (opts.info || opts.noaction)
|
||||
flags = MS_RDONLY;
|
||||
if (opts.force)
|
||||
flags |= MS_RECOVER;
|
||||
|
||||
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 ((vol->flags & VOLUME_IS_DIRTY) && !opts.force)
|
||||
goto umount;
|
||||
|
||||
if (opts.info) {
|
||||
|
680
ntfsprogs/sd.c
680
ntfsprogs/sd.c
@ -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_val_len = 0x64;
|
||||
sd->owner = const_cpu_to_le32(0x48);
|
||||
sd->group = const_cpu_to_le32(0x58);
|
||||
}
|
||||
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->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->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,41 +80,30 @@ 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);
|
||||
}
|
||||
/*
|
||||
* 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);
|
||||
/* Only $AttrDef and $Boot behave differently to everything else. */
|
||||
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_READ |
|
||||
FILE_WRITE_ATTRIBUTES |
|
||||
FILE_READ_ATTRIBUTES | FILE_WRITE_EA |
|
||||
@ -166,12 +124,13 @@ void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len)
|
||||
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.*/
|
||||
/*
|
||||
* 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,32 +317,52 @@ 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);
|
||||
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
|
||||
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
|
||||
|
||||
//ace8
|
||||
ace = (ACCESS_ALLOWED_ACE*)((u8*)ace + le16_to_cpu(ace->size));
|
||||
ace->type = ACCESS_ALLOWED_ACE_TYPE;
|
||||
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE |
|
||||
INHERIT_ONLY_ACE;
|
||||
ace->size = const_cpu_to_le16(0x18);
|
||||
ace->mask = GENERIC_READ | GENERIC_EXECUTE;
|
||||
ace->sid.revision = SID_REVISION;
|
||||
ace->sid.sub_authority_count = 0x02;
|
||||
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
|
||||
ace->sid.identifier_authority.value[0] = 0;
|
||||
ace->sid.identifier_authority.value[1] = 0;
|
||||
ace->sid.identifier_authority.value[2] = 0;
|
||||
ace->sid.identifier_authority.value[3] = 0;
|
||||
ace->sid.identifier_authority.value[4] = 0;
|
||||
ace->sid.identifier_authority.value[5] = 5;
|
||||
ace->sid.sub_authority[0] =
|
||||
const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
|
||||
ace->sid.sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_USERS);
|
||||
|
||||
//owner sid
|
||||
sid = (SID*)((char*)sd + le32_to_cpu(sd->owner));
|
||||
sid->revision = 0x01;
|
||||
sid->sub_authority_count = 0x02;
|
||||
sid->sub_authority_count = 0x01;
|
||||
/* SECURITY_NT_SID_AUTHORITY (S-1-5) */
|
||||
sid->identifier_authority.value[0] = 0;
|
||||
sid->identifier_authority.value[1] = 0;
|
||||
@ -394,10 +370,7 @@ 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_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);
|
||||
|
||||
//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;
|
||||
|
@ -4,9 +4,8 @@
|
||||
#include "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_ */
|
||||
|
||||
|
@ -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 "endians.h"
|
||||
#include "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]);
|
||||
}
|
@ -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_ */
|
||||
|
@ -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
|
||||
*
|
||||
@ -71,6 +72,7 @@
|
||||
#include "dir.h"
|
||||
/* #include "version.h" */
|
||||
#include "logging.h"
|
||||
#include "misc.h"
|
||||
|
||||
const char *ntfs_bugs = "Developers' email address: "NTFS_DEV_LIST"\n";
|
||||
const char *ntfs_home = "Linux NTFS homepage: http://www.linux-ntfs.org\n";
|
||||
@ -81,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
|
||||
*/
|
||||
@ -91,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
|
||||
*
|
||||
@ -116,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) {
|
||||
@ -125,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");
|
||||
@ -167,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;
|
||||
|
||||
@ -176,42 +215,58 @@ ntfs_volume * utils_mount_volume(const char *device, unsigned long flags, BOOL f
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!utils_valid_device(device, force))
|
||||
/* Porting notes:
|
||||
*
|
||||
* libntfs-3g does not have the 'force' flag in ntfs_mount_flags.
|
||||
* The 'force' flag in libntfs bypasses two safety checks when mounting
|
||||
* read/write:
|
||||
* 1. Do not mount when the VOLUME_IS_DIRTY flag in
|
||||
* VOLUME_INFORMATION is set.
|
||||
* 2. Do not mount when the logfile is unclean.
|
||||
*
|
||||
* libntfs-3g only has safety check number 2. The dirty flag is simply
|
||||
* ignored because we are confident that we can handle a dirty volume.
|
||||
* So we treat MS_RECOVER like NTFS_MNT_FORCE, knowing that the first
|
||||
* check is always bypassed.
|
||||
*/
|
||||
|
||||
if (!utils_valid_device(device, flags & MS_RECOVER))
|
||||
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;
|
||||
}
|
||||
|
||||
/* Porting notes:
|
||||
* libntfs-3g does not record whether the volume log file was dirty
|
||||
* before mount, so we can only warn if the VOLUME_IS_DIRTY flag is set
|
||||
* in VOLUME_INFORMATION. */
|
||||
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 (!(flags & MS_RECOVER)) {
|
||||
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
|
||||
@ -333,7 +388,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
|
||||
@ -403,7 +457,6 @@ ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
|
||||
return rec;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* utils_inode_get_name
|
||||
*
|
||||
@ -414,11 +467,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;
|
||||
@ -426,7 +480,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) {
|
||||
@ -470,7 +524,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
|
||||
@ -528,6 +582,7 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#undef max_path
|
||||
|
||||
/**
|
||||
* utils_attr_get_name
|
||||
@ -549,7 +604,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;
|
||||
}
|
||||
@ -573,9 +629,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;
|
||||
@ -603,7 +660,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
|
||||
@ -612,8 +672,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;
|
||||
|
||||
@ -635,7 +694,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;
|
||||
@ -647,7 +707,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);
|
||||
}
|
||||
@ -673,15 +735,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)))) {
|
||||
@ -756,7 +818,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;
|
||||
}
|
||||
@ -767,9 +829,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;
|
||||
|
||||
@ -970,10 +1032,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;
|
||||
}
|
||||
|
||||
|
@ -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...
|
||||
@ -154,4 +150,14 @@ static __inline__ int ntfs_mbstoucs_libntfscompat(const char *ins,
|
||||
return ntfs_mbstoucs(ins, outs);
|
||||
}
|
||||
|
||||
/* This simple utility function was missing from libntfs-3g. */
|
||||
static __inline__ ntfschar *ntfs_attr_get_name(ATTR_RECORD *attr)
|
||||
{
|
||||
return (ntfschar*)((u8*)attr + le16_to_cpu(attr->name_offset));
|
||||
}
|
||||
|
||||
/* The define 'leMFT_REF' is not present in libntfs-3g. It is only symbolic so
|
||||
* typedef it to MFT_REF.*/
|
||||
typedef MFT_REF leMFT_REF;
|
||||
|
||||
#endif /* _NTFS_UTILS_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user