Wheee! Lots of last minute fixes and enhancements.

- Compiler warning fixes for gnome-vfs and fuse modules. (Anton)
- Change volume mounting (actually device opening) to happen with
  O_EXCL bit set so at least on Linux no one can change the device
  block size under our feet.  (Anton)
- Change volume mounting and mkntfs to set the device block size to the
  sector size using BLKBSZSET ioctl (Linux only).  This should be
  optimal for performance and should fixes the bug of not being able to
  create the backup boot sector if the number of sectors on the device
  is odd, the sector size is 512 bytes, and the kernel is 2.4.  (Anton)
- Enforce cluster size, mft record size, and index record size to be at
  least equal to the sector size and verify they are still valid and in
  particular display a warning message if the volume will not be
  mountable by the kernel driver (it requires mft record size and index
  record size to be below or equal to the system page size which we
  determine using sysconf()).  (Anton)
edge.strict_endians
antona 2006-02-03 22:19:17 +00:00
parent e57cc4521a
commit af9fd39611
14 changed files with 238 additions and 172 deletions

View File

@ -100,6 +100,20 @@
- Fix stupid bug in libntfs/bitmap.c::ntfs_bitmap_set_bits_in_run()
which caused bits to not be cleared or set if the first bit in the
run was not a multiple of eight. (Anton)
- Change volume mounting (actually device opening) to happen with
O_EXCL bit set so at least on Linux no one can change the device
block size under our feet. (Anton)
- Change volume mounting and mkntfs to set the device block size to the
sector size using BLKBSZSET ioctl (Linux only). This should be
optimal for performance and should fixes the bug of not being able to
create the backup boot sector if the number of sectors on the device
is odd, the sector size is 512 bytes, and the kernel is 2.4. (Anton)
- Enforce cluster size, mft record size, and index record size to be at
least equal to the sector size and verify they are still valid and in
particular display a warning message if the volume will not be
mountable by the kernel driver (it requires mft record size and index
record size to be below or equal to the system page size which we
determine using sysconf()). (Anton)
10/10/2005 - 1.12.1 - Minor fix to location of mount.ntfs-fuse and mkfs.ntfs.

26
NEWS
View File

@ -18,30 +18,4 @@ changing the file size and can read/write/add/remove named data streams via
"file:stream" interface and list them via "ntfs.streams.list" extended
attribute (this only if xattr support is enabled). (Yura Pakhuchiy)
Attribute resize code for normal and sparse files is completed. Thus, ntfscp
should always successfully overwrite any normal or sparse file even if file
size is changed. (Yura Pakhuchiy)
Moved back from BitKeeper to CVS on SF.net.
ntfsprogs should now work completely on Windows 2000 and XP (Cygwin).
mkntfs does not create bootable volumes when on Windows. Volumes are locked
when using a R/W utility in order to prevent data corruption. (Yuval Fledel,
Anton Altaparmakov)
ntfsinfo has been extended and now provides much more detailed information as
well as being able to resolve a path/filename instead of requiring the inode
number. (Yuval Fledel, Anton Altaparmakov)
mkntfs now creates bootable ntfs volumes so you can install Windows on an
ntfs volume created with mkntfs and Windows will manage to boot afterwards.
ntfsresize now supports relocation which generally means you are now able to
resize to any size you like (as long as there is enough free space). Note,
this modifies the command line options a little as well as the returned output
so applications using ntfsresize might need modifications before they will
work with the updated ntfsresize. (Szakacsits Szabolcs)
ntfsprogs ("make libs" only) now compiles on FreeBSD, NetBSD, Windows (Cygwin),
and DOS (DJGPP). Thanks to Christophe Grenier for DOS and FreeBSD testing
and fixes and to Lode Leroy for Windows testing and fixes.

View File

@ -358,7 +358,7 @@ AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF
AC_CHECK_FUNCS([atexit dup2 fdatasync getopt_long hasmntopt mbsinit memmove \
memset realpath regcomp setlocale setxattr strcasecmp strchr strdup \
strerror strnlen strtol strtoul utime])
strerror strnlen strtol strtoul sysconf utime])
# Makefiles to be created by configure.
AC_CONFIG_FILES([

View File

@ -1,7 +1,7 @@
/*
* device.h - Exports for low level device io. Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2000-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -118,5 +118,6 @@ extern s64 ntfs_device_partition_start_sector_get(struct ntfs_device *dev);
extern int ntfs_device_heads_get(struct ntfs_device *dev);
extern int ntfs_device_sectors_per_track_get(struct ntfs_device *dev);
extern int ntfs_device_sector_size_get(struct ntfs_device *dev);
extern int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size);
#endif /* defined _NTFS_DEVICE_H */

View File

@ -1,7 +1,7 @@
/*
* device_io.h - Exports for default device io. Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2000-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -36,7 +36,7 @@
#else /* __CYGWIN32__ */
#ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x10000301
# define HDIO_GETGEO 0x301
/**
* struct hd_geometry -
*/
@ -48,13 +48,16 @@ struct hd_geometry {
};
#endif
#ifndef BLKGETSIZE
# define BLKGETSIZE 0x10001260
# define BLKGETSIZE 0x1260
#endif
#ifndef BLKSSZGET
# define BLKSSZGET 0x10001268
# define BLKSSZGET 0x1268
#endif
#ifndef BLKGETSIZE64
# define BLKGETSIZE64 0x10001272
# define BLKGETSIZE64 0x80041272
#endif
#ifndef BLKBSZSET
# define BLKBSZSET 0x40041271
#endif
/* On Cygwin; use Win32 low level device operations. */

View File

@ -1,7 +1,7 @@
/**
* bootsect.c - Boot sector handling code. Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2005 Anton Altaparmakov
* Copyright (c) 2000-2006 Anton Altaparmakov
* Copyright (c) 2005 Yura Pakhuchiy
*
* This program/include file is free software; you can redistribute it and/or
@ -270,4 +270,3 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
vol->mftmirr_size = vol->cluster_size / vol->mft_record_size;
return 0;
}

View File

@ -1,7 +1,7 @@
/**
* device.c - Low level device io functions. Part of the Linux-NTFS project.
*
* Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2004-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -50,6 +50,9 @@
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
#endif
@ -75,6 +78,9 @@
#if defined(linux) && defined(_IO) && !defined(BLKSSZGET)
# define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytes. */
#endif
#if defined(linux) && defined(_IO) && !defined(BLKBSZSET)
# define BLKBSZSET _IOW(0x12,113,size_t) /* Set device block size in bytes. */
#endif
/**
* ntfs_device_alloc - allocate an ntfs device structure and pre-initialize it
@ -641,6 +647,7 @@ int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
#endif
return -1;
}
/**
* ntfs_device_sector_size_get - get sector size of a device
* @dev: open device
@ -650,8 +657,8 @@ int ntfs_device_sectors_per_track_get(struct ntfs_device *dev)
*
* The following error codes are defined:
* EINVAL Input parameter error
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
* EOPNOTSUPP System does not support BLKSSZGET ioctl
* ENOTTY @dev is a file or a device not supporting BLKSSZGET
*/
int ntfs_device_sector_size_get(struct ntfs_device *dev)
{
@ -674,3 +681,37 @@ int ntfs_device_sector_size_get(struct ntfs_device *dev)
return -1;
}
/**
* ntfs_device_block_size_set - set block size of a device
* @dev: open device
* @block_size: block size to set @dev to
*
* On success, return 0.
* On error return -1 with errno set to the error code.
*
* The following error codes are defined:
* EINVAL Input parameter error
* EOPNOTSUPP System does not support HDIO_GETGEO ioctl
* ENOTTY @dev is a file or a device not supporting HDIO_GETGEO
*/
int ntfs_device_block_size_set(struct ntfs_device *dev, int block_size)
{
if (!dev) {
errno = EINVAL;
return -1;
}
#ifdef BLKBSZSET
{
size_t s_block_size = block_size;
if (!dev->d_ops->ioctl(dev, BLKBSZSET, &s_block_size)) {
ntfs_log_debug("Used BLKBSZSET to set block size to "
"%d bytes\n", block_size);
return 0;
}
}
#else
errno = EOPNOTSUPP;
#endif
return -1;
}

View File

@ -3,7 +3,7 @@
* libntfs. Part of the Linux-NTFS project.
*
* Copyright (c) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
* Copyright (c) 2003-2005 Anton Altaparmakov
* Copyright (c) 2003-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -659,7 +659,7 @@ static GnomeVFSResult libntfs_gnomevfs_seek(GnomeVFSMethod *method,
static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSFileOffset *offset_return)
GnomeVFSFileSize *offset_return)
{
GnomeVFSResult errvfsresult;
struct libntfs_file *libntfs_file;
@ -676,7 +676,7 @@ static GnomeVFSResult libntfs_gnomevfs_tell(GnomeVFSMethod *method,
return errvfsresult;
*offset_return = libntfs_file->pos;
g_assert(*offset_return == libntfs_file->pos);
g_assert((s64)*offset_return == libntfs_file->pos);
return errvfsresult;
}

View File

@ -1,7 +1,7 @@
/**
* unix_io.c - Unix style disk io functions. Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2003 Anton Altaparmakov
* Copyright (c) 2000-2006 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -60,12 +60,13 @@
#include "device.h"
#include "logging.h"
#if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
# define BLKGETSIZE _IO(0x12,96) /* Get device size in 512byte blocks. */
#endif
#define DEV_FD(dev) (*(int *)dev->d_private)
/* Define to nothing if not present on this system. */
#ifndef O_EXCL
# define O_EXCL 0
#endif
/**
* ntfs_device_unix_io_open - Open a device and lock it exclusively
* @dev:
@ -86,8 +87,12 @@ static int ntfs_device_unix_io_open(struct ntfs_device *dev, int flags)
}
if (!(dev->d_private = malloc(sizeof(int))))
return -1;
/* Open the device/file obtaining the file descriptor. */
if ((*(int *)dev->d_private = open(dev->d_name, flags)) == -1) {
/*
* Open the device/file obtaining the file descriptor for exclusive
* access.
*/
*(int*)dev->d_private = open(dev->d_name, flags | O_EXCL);
if (*(int*)dev->d_private == -1) {
err = errno;
goto err_out;
}

View File

@ -1,7 +1,7 @@
/**
* volume.c - NTFS volume handling code. Part of the Linux-NTFS project.
*
* Copyright (c) 2000-2005 Anton Altaparmakov
* Copyright (c) 2000-2006 Anton Altaparmakov
* Copyright (c) 2002-2005 Szabolcs Szakacsits
* Copyright (c) 2004-2005 Richard Russon
*
@ -467,7 +467,12 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags)
}
free(bs);
bs = NULL;
/* Now set the device block size to the sector size. */
if (ntfs_device_block_size_set(vol->dev, vol->sector_size))
ntfs_log_debug("Failed to set the device block size to the "
"sector size. This may affect performance "
"but should be harmless otherwise. Error: "
"%s\n", strerror(errno));
/*
* We now initialize the cluster allocator.
*

View File

@ -4,7 +4,7 @@
* Part of the Linux-NTFS project.
*
* Copyright (c) 2003-2004 Lode Leroy
* Copyright (c) 2003-2005 Anton Altaparmakov
* Copyright (c) 2003-2006 Anton Altaparmakov
* Copyright (c) 2004-2005 Yuval Fledel
*
* This program/include file is free software; you can redistribute it and/or
@ -1433,6 +1433,12 @@ static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
case BLKSSZGET:
ntfs_log_debug("BLKSSZGET detected.\n");
return ntfs_win32_blksszget(dev, (int *)argp);
#endif
#ifdef BLKBSZSET
case BLKBSZSET:
ntfs_log_debug("BLKBSZSET detected.\n");
/* Nothing to do on Windows. */
return 0;
#endif
default:
ntfs_log_debug("unimplemented ioctl %d.\n", request);

View File

@ -271,26 +271,6 @@ and exit.
\fB\-h\fR, \fB\-\-help\fR
Show a list of options with a brief description of each one.
.SH BUGS
.B mkntfs
writes the backup boot sector to the last sector of the block
.I device
being formatted. However, current versions of the Linux kernel (all versions
up to and including todays 2.4.18) either only report an even number of sectors
when the sector size is below 1024 bytes, which is the case for most hard
drives today (512 bytes sector size) or they return the correct number but
accessing the last sector fails. Either way, this means that when a partition
has an odd number of 512\-byte sectors, the last sector is either not reported
to us at all or it is not writable by us and hence the created NTFS volume
will either have the backup boot sector placed one sector ahead of where it
should be or it cannot be written at all. For this reason,
.B mkntfs
marks the NTFS volume dirty, so that when you reboot into Windows, check disk
runs automatically and creates a copy of the backup boot sector in the correct
location. This also has the benefit of catching any bugs in
.B mkntfs
as check disk would find any corrupt structures and repair them, as well as
report them.
.sp
If you find a bug please send an email describing the problem to the
development team:
.br

View File

@ -171,7 +171,7 @@ runlist *g_rl_boot = NULL;
runlist *g_rl_bad = NULL;
INDEX_ALLOCATION *g_index_block = NULL;
ntfs_volume *g_vol = NULL;
int g_mft_size = 0; /* The bigger of 16kB & one cluster */
int g_mft_size = 0;
long long g_mft_lcn = 0; /* lcn of $MFT, $DATA attribute */
long long g_mftmirr_lcn = 0; /* lcn of $MFTMirr, $DATA */
long long g_logfile_lcn = 0; /* lcn of $LogFile, $DATA */
@ -3457,8 +3457,10 @@ static BOOL mkntfs_open_partition(ntfs_volume *vol)
}
ntfs_log_warning("mkntfs forced anyway.\n");
#ifdef HAVE_LINUX_MAJOR_H
} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && MINOR(sbuf.st_rdev) % 64 == 0) ||
(SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) && MINOR(sbuf.st_rdev) % 16 == 0)) {
} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
MINOR(sbuf.st_rdev) % 64 == 0) ||
(SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
MINOR(sbuf.st_rdev) % 16 == 0)) {
ntfs_log_error("%s is entire device, not just one partition.\n", vol->dev->d_name);
if (!opts.force) {
ntfs_log_error("Refusing to make a filesystem here!\n");
@ -3484,12 +3486,13 @@ done:
}
/**
* mkntfs_override_phys_params -
* mkntfs_override_vol_params -
*/
static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
{
int i;
s64 volume_size;
long page_size;
int i;
BOOL winboot = TRUE;
/* If user didn't specify the sector size, determine it now. */
@ -3503,7 +3506,6 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
opts.sector_size = 512;
}
}
/* Validate sector size. */
if ((opts.sector_size - 1) & opts.sector_size) {
ntfs_log_error("The sector size is invalid. It must be a "
@ -3516,10 +3518,17 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
return FALSE;
}
ntfs_log_debug("sector size = %ld bytes\n", opts.sector_size);
/* Now set the device block size to the sector size. */
if (ntfs_device_block_size_set(vol->dev, opts.sector_size))
ntfs_log_debug("Failed to set the device block size to the "
"sector size. This may cause problems when "
"creating the backup boot sector and also may "
"affect performance but should be harmless "
"otherwise. Error: %s\n", strerror(errno));
/* If user didn't specify the number of sectors, determine it now. */
if (opts.num_sectors < 0) {
opts.num_sectors = ntfs_device_size_get(vol->dev, opts.sector_size);
opts.num_sectors = ntfs_device_size_get(vol->dev,
opts.sector_size);
if (opts.num_sectors <= 0) {
ntfs_log_error("Couldn't determine the size of %s. "
"Please specify the number of sectors "
@ -3528,8 +3537,7 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
}
}
ntfs_log_debug("number of sectors = %lld (0x%llx)\n", opts.num_sectors,
opts.num_sectors);
opts.num_sectors);
/*
* Reserve the last sector for the backup boot sector unless the
* sector size is less than 512 bytes in which case reserve 512 bytes
@ -3539,10 +3547,10 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
if (opts.sector_size < 512)
i = 512 / opts.sector_size;
opts.num_sectors -= i;
/* If user didn't specify the partition start sector, determine it. */
if (opts.part_start_sect < 0) {
opts.part_start_sect = ntfs_device_partition_start_sector_get(vol->dev);
opts.part_start_sect = ntfs_device_partition_start_sector_get(
vol->dev);
if (opts.part_start_sect < 0) {
ntfs_log_warning("The partition start sector was not "
"specified for %s and it could not be obtained "
@ -3563,10 +3571,10 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
"4294967295 (2^32-1).\n");
return FALSE;
}
/* If user didn't specify the sectors per track, determine it now. */
if (opts.sectors_per_track < 0) {
opts.sectors_per_track = ntfs_device_sectors_per_track_get(vol->dev);
opts.sectors_per_track = ntfs_device_sectors_per_track_get(
vol->dev);
if (opts.sectors_per_track < 0) {
ntfs_log_warning("The number of sectors per track was "
"not specified for %s and it could not be "
@ -3587,7 +3595,6 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
"is 65535.\n");
return FALSE;
}
/* If user didn't specify the number of heads, determine it now. */
if (opts.heads < 0) {
opts.heads = ntfs_device_heads_get(vol->dev);
@ -3610,17 +3617,14 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
ntfs_log_error("Invalid number of heads. Maximum is 65535.\n");
return FALSE;
}
volume_size = opts.num_sectors * opts.sector_size;
/* Validate volume size. */
if (volume_size < (1 << 20)) { /* 1MiB */
ntfs_log_error("Device is too small (%llikiB). Minimum NTFS "
"volume size is 1MiB.\n", volume_size / 1024);
ntfs_log_error("Device is too small (%llikiB). Minimum NTFS "
"volume size is 1MiB.\n", volume_size / 1024);
return FALSE;
}
ntfs_log_debug("volume size = %llikiB\n", volume_size / 1024);
/* If user didn't specify the cluster size, determine it now. */
if (!vol->cluster_size) {
if (volume_size <= 512LL << 20) /* <= 512MB */
@ -3643,28 +3647,29 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
vol->cluster_size <<= 1;
if (vol->cluster_size > 65535) {
ntfs_log_error("Device is too large to hold an "
"NTFS volume (maximum size is 256TiB).\n");
"NTFS volume (maximum size is "
"256TiB).\n");
return FALSE;
}
}
ntfs_log_quiet("Cluster size has been automatically set to %d "
"bytes.\n", vol->cluster_size);
"bytes.\n", vol->cluster_size);
}
/* Validate cluster size. */
if (vol->cluster_size & (vol->cluster_size - 1)) {
ntfs_log_error("The cluster size is invalid. It must be a "
"power of two, e.g. 1024, 4096.\n");
"power of two, e.g. 1024, 4096.\n");
return FALSE;
}
if (vol->cluster_size < (u32)opts.sector_size) {
ntfs_log_error("The cluster size is invalid. It must be equal "
"to, or larger than, the sector size.\n");
"to, or larger than, the sector size.\n");
return FALSE;
}
if (vol->cluster_size > 128 * (u32)opts.sector_size) {
ntfs_log_error("The cluster size is invalid. It cannot be "
"more that 128 times the size of the sector size.\n");
"more that 128 times the size of the sector "
"size.\n");
return FALSE;
}
if (vol->cluster_size > 65536) {
@ -3672,60 +3677,109 @@ static BOOL mkntfs_override_phys_params(ntfs_volume *vol)
"cluster size is 65536 bytes (64kiB).\n");
return FALSE;
}
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
ntfs_log_debug("cluster size = %u bytes\n", (unsigned int)vol->cluster_size);
ntfs_log_debug("cluster size = %u bytes\n",
(unsigned int)vol->cluster_size);
if (vol->cluster_size > 4096) {
if (opts.enable_compression) {
if (!opts.force) {
ntfs_log_error("Windows cannot use compression "
"when the cluster size is larger than "
"4096 bytes.\n");
"when the cluster size is "
"larger than 4096 bytes.\n");
return FALSE;
}
opts.enable_compression = 0;
}
ntfs_log_warning("Windows cannot use compression when the "
"cluster size is larger than 4096 bytes. Compression "
"has been disabled for this volume.\n");
"cluster size is larger than 4096 bytes. "
"Compression has been disabled for this "
"volume.\n");
}
vol->nr_clusters = volume_size / vol->cluster_size;
/*
* Check the cluster_size and num_sectors for consistency with
* sector_size and num_sectors. And check both of these for consistency
* with volume_size.
*/
if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) / vol->cluster_size) ||
(volume_size / opts.sector_size) != opts.num_sectors ||
(volume_size / vol->cluster_size) != vol->nr_clusters)) {
if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) /
vol->cluster_size) ||
(volume_size / opts.sector_size) != opts.num_sectors ||
(volume_size / vol->cluster_size) !=
vol->nr_clusters)) {
/* XXX is this code reachable? */
ntfs_log_error("Illegal combination of volume/cluster/sector size and/or cluster/sector number.\n");
ntfs_log_error("Illegal combination of volume/cluster/sector "
"size and/or cluster/sector number.\n");
return FALSE;
}
ntfs_log_debug("number of clusters = %llu (0x%llx)\n", vol->nr_clusters, vol->nr_clusters);
ntfs_log_debug("number of clusters = %llu (0x%llx)\n",
vol->nr_clusters, vol->nr_clusters);
/* Number of clusters must fit within 32 bits (Win2k limitation). */
if (vol->nr_clusters >> 32) {
if (vol->cluster_size >= 65536) {
ntfs_log_error("Device is too large to hold an NTFS "
"volume (maximum size is 256TiB).\n");
"volume (maximum size is 256TiB).\n");
return FALSE;
}
ntfs_log_error("Number of clusters exceeds 32 bits. Please "
"try again with a larger\ncluster size or leave the "
"cluster size unspecified and the smallest possible "
"cluster size for the size of the device will be used.\n");
"try again with a larger\ncluster size or "
"leave the cluster size unspecified and the "
"smallest possible cluster size for the size "
"of the device will be used.\n");
return FALSE;
}
page_size = sysconf(_SC_PAGESIZE);
if (page_size < 0)
page_size = sysconf(_SC_PAGE_SIZE);
if (page_size >= 0)
ntfs_log_debug("System page size is %li bytes.\n", page_size);
else {
ntfs_log_warning("Failed to determine system page size. "
"Assuming safe default of 4096 bytes.\n");
page_size = 4096;
}
/*
* Set the mft record size. By default this is 1024 but it has to be
* at least as big as a sector and not bigger than a page on the system
* or the NTFS kernel driver will not be able to mount the volume.
* TODO: The mft record size should be user specifiable just like the
* "inode size" can be specified on other Linux/Unix file systems.
*/
vol->mft_record_size = 1024;
if (vol->mft_record_size < vol->sector_size)
vol->mft_record_size = vol->sector_size;
if (vol->mft_record_size > (unsigned long)page_size)
ntfs_log_warning("Mft record size (%u bytes) exceeds system "
"page size (%li bytes). You will not be able "
"to mount this volume using the NTFS kernel "
"driver.\n", (unsigned)vol->mft_record_size,
page_size);
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
ntfs_log_debug("mft record size = %u bytes\n",
(unsigned)vol->mft_record_size);
/*
* Set the index record size. By default this is 4096 but it has to be
* at least as big as a sector and not bigger than a page on the system
* or the NTFS kernel driver will not be able to mount the volume.
* FIXME: Should we make the index record size to be user specifiable?
*/
vol->indx_record_size = 4096;
if (vol->indx_record_size < vol->sector_size)
vol->indx_record_size = vol->sector_size;
if (vol->indx_record_size > (unsigned long)page_size)
ntfs_log_warning("Index record size (%u bytes) exceeds system "
"page size (%li bytes). You will not be able "
"to mount this volume using the NTFS kernel "
"driver.\n", vol->indx_record_size, page_size);
vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
ntfs_log_debug("index record size = %u bytes\n",
(unsigned)vol->indx_record_size);
if (!winboot) {
ntfs_log_warning("To boot from a device, Windows needs the "
"'partition start sector', the 'sectors per track' and "
"the 'number of heads' to be set.\n");
"'partition start sector', the 'sectors per "
"track' and the 'number of heads' to be "
"set.\n");
ntfs_log_warning("Windows will not be able to boot from this "
"device.\n");
"device.\n");
}
return TRUE;
}
@ -3759,6 +3813,11 @@ static BOOL mkntfs_initialize_bitmaps(void)
* Determine mft_size: (16 (1.2) or 27 (3.0+) mft records) or
* one cluster, whichever is bigger.
*/
if (g_vol->major_ver >= 3)
g_mft_size = 27;
else
g_mft_size = 16;
g_mft_size *= g_vol->mft_record_size;
g_mft_size = ((16 + 11 * (g_vol->major_ver >= 3)) *
g_vol->mft_record_size);
if (g_mft_size < (s32)g_vol->cluster_size)
@ -4254,16 +4313,17 @@ static int create_backup_boot_sector(u8 *buff)
s = strerror(e);
else
s = "unknown error";
if (bw != -1LL || (bw == -1LL && e != ENOSPC)) {
/* At least some 2.4 kernels return EIO instead of ENOSPC. */
if (bw != -1LL || (bw == -1LL && e != ENOSPC && e != EIO)) {
ntfs_log_critical("Couldn't write backup boot sector: %s\n", s);
return -1;
}
bb_err:
ntfs_log_error("Couldn't write backup boot sector. This is due to a "
"limitation in the\nLinux kernel. This is not "
"a major problem as Windows check disk will "
"create the\nbackup boot sector when it "
"is run on your next boot into Windows.\n");
"limitation in the\nLinux kernel. This is not a major "
"problem as Windows check disk will create the\n"
"backup boot sector when it is run on your next boot "
"into Windows.\n");
return -1;
}
@ -4653,20 +4713,17 @@ static BOOL mkntfs_create_root_structures(void)
ntfs_log_error("Couldn't create $Boot: %s\n", strerror(-err));
return FALSE;
}
if (create_backup_boot_sector((u8*)bs)) {
/*
* Pre-2.6 kernels couldn't access the last sector
* if it was odd hence we schedule chkdsk to create it.
* Pre-2.6 kernels couldn't access the last sector if it was
* odd and we failed to set the device block size to the sector
* size, hence we schedule chkdsk to create it.
*/
volume_flags |= VOLUME_IS_DIRTY;
}
free(bs);
if (!create_file_volume(m, root_ref, volume_flags))
return FALSE;
ntfs_log_verbose("Creating $BadClus (mft record 8)\n");
m = (MFT_RECORD*)(g_buf + 8 * g_vol->mft_record_size);
/* FIXME: This should be IGNORE_CASE */
@ -4937,18 +4994,15 @@ static int mkntfs_redirect(struct mkntfs_options *opts2)
ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n");
goto done;
}
/* Initialize the random number generator with the current time. */
srandom(mkntfs_time());
/* Allocate and initialize ntfs_volume structure g_vol. */
g_vol = ntfs_volume_alloc();
if (!g_vol) {
ntfs_log_perror("Could not create volume");
goto done;
}
/* transfer some options to the volume */
/* Transfer some options to the volume. */
if (opts.label) {
g_vol->vol_name = strdup(opts.label);
if (!g_vol->vol_name) {
@ -4956,7 +5010,6 @@ static int mkntfs_redirect(struct mkntfs_options *opts2)
goto done;
}
}
if (opts.ver_major) {
g_vol->major_ver = opts.ver_major;
g_vol->minor_ver = opts.ver_minor;
@ -4967,10 +5020,6 @@ static int mkntfs_redirect(struct mkntfs_options *opts2)
}
if (opts.cluster_size >= 0)
g_vol->cluster_size = opts.cluster_size;
g_vol->mft_record_size = 1024;
g_vol->mft_record_size_bits = 10;
/* Length is in unicode characters. */
g_vol->upcase_len = 65536;
g_vol->upcase = malloc(g_vol->upcase_len * sizeof(ntfschar));
@ -4979,84 +5028,73 @@ static int mkntfs_redirect(struct mkntfs_options *opts2)
goto done;
}
init_upcase_table(g_vol->upcase, g_vol->upcase_len * sizeof(ntfschar));
g_vol->indx_record_size = 4096;
g_vol->indx_record_size_bits = 12;
if (g_vol->major_ver < 3) {
g_vol->attrdef = ntfs_calloc(1, 36000);
if (g_vol->attrdef) {
memcpy(g_vol->attrdef, attrdef_ntfs12_array, sizeof(attrdef_ntfs12_array));
memcpy(g_vol->attrdef, attrdef_ntfs12_array,
sizeof(attrdef_ntfs12_array));
g_vol->attrdef_len = 36000;
}
} else {
g_vol->attrdef = malloc(sizeof(attrdef_ntfs3x_array));
if (g_vol->attrdef) {
memcpy(g_vol->attrdef, attrdef_ntfs3x_array, sizeof(attrdef_ntfs3x_array));
memcpy(g_vol->attrdef, attrdef_ntfs3x_array,
sizeof(attrdef_ntfs3x_array));
g_vol->attrdef_len = sizeof(attrdef_ntfs3x_array);
}
}
if (!g_vol->attrdef) {
ntfs_log_perror("Could not create attrdef structure");
goto done;
}
/* Open the partition. */
if (!mkntfs_open_partition(g_vol))
goto done;
/* Decide on the sectors/tracks/heads/size, etc. */
if (!mkntfs_override_phys_params(g_vol))
/*
* Decide on the sector size, cluster size, mft record and index record
* sizes as well as the number of sectors/tracks/heads/size, etc.
*/
if (!mkntfs_override_vol_params(g_vol))
goto done;
/* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
if (!mkntfs_initialize_bitmaps())
goto done;
/* Initialize MFT & set g_logfile_lcn. */
if (!mkntfs_initialize_rl_mft())
goto done;
/* Initialize $LogFile. */
if (!mkntfs_initialize_rl_logfile())
goto done;
/* Initialize $Boot. */
if (!mkntfs_initialize_rl_boot())
goto done;
/* Allocate a buffer large enough to hold the mft. */
g_buf = ntfs_calloc(1, g_mft_size);
if (!g_buf)
goto done;
/* Create runlist for $BadClus, $DATA named stream $Bad. */
if (!mkntfs_initialize_rl_bad())
goto done;
/* If not quick format, fill the device with 0s. */
if (!opts.quick_format) {
if (!mkntfs_fill_device_with_zeroes())
goto done;
}
/* Create NTFS volume structures. */
if (!mkntfs_create_root_structures())
goto done;
/*
* - Do not step onto bad blocks!!!
* - If any bad blocks were specified or found, modify $BadClus, allocating the
* bad clusters in $Bitmap.
* - If any bad blocks were specified or found, modify $BadClus,
* allocating the bad clusters in $Bitmap.
* - C&w bootsector backup bootsector (backup in last sector of the
* partition).
* - If NTFS 3.0+, c&w $Secure file and $Extend directory with the
* corresponding special files in it, i.e. $ObjId, $Quota, $Reparse, and
* $UsnJrnl. And others? Or not all necessary?
* corresponding special files in it, i.e. $ObjId, $Quota, $Reparse,
* and $UsnJrnl. And others? Or not all necessary?
* - RE: Populate $root with the system files (and $Extend directory if
* applicable). Possibly should move this as far to the top as possible and
* update during each subsequent c&w of each system file.
* applicable). Possibly should move this as far to the top as
* possible and update during each subsequent c&w of each system file.
*/
ntfs_log_verbose("Syncing root directory index record.\n");
if (!mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 *

View File

@ -220,7 +220,7 @@ static long ntfs_fuse_get_nr_free_clusters(ntfs_volume *vol)
* Return 0 on success or -errno on error.
*/
static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
struct statvfs *sfs)
#else
struct statfs *sfs)
@ -234,7 +234,7 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
return -ENODEV;
/* Optimal transfer block size. */
sfs->f_bsize = vol->cluster_size;
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
sfs->f_frsize = vol->cluster_size;
#endif
/*
@ -257,7 +257,7 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
size = 0;
sfs->f_ffree = size;
/* Maximum length of filenames. */
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
sfs->f_namemax = NTFS_MAX_NAME_LEN;
#else
sfs->f_namelen = NTFS_MAX_NAME_LEN;
@ -1763,7 +1763,7 @@ static int parse_options(int argc, char *argv[])
int main(int argc, char *argv[])
{
char *parsed_options;
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
#endif
struct fuse *fh;
@ -1795,7 +1795,7 @@ int main(int argc, char *argv[])
}
free(opts.device);
/* Create filesystem. */
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
if ((fuse_opt_add_arg(&margs, "") == -1 ||
fuse_opt_add_arg(&margs, "-o") == -1 ||
fuse_opt_add_arg(&margs, parsed_options) == -1))
@ -1812,7 +1812,7 @@ int main(int argc, char *argv[])
return 5;
}
free(parsed_options);
#if FUSE_VERSION >= 25
#if defined(FUSE_VERSION) && (FUSE_VERSION >= 25)
fh = (struct fuse *)1; /* Cast anything except NULL to handle errors. */
margs = (struct fuse_args)FUSE_ARGS_INIT(0, NULL);
if (fuse_opt_add_arg(&margs, "") == -1 ||