start using utils

(Logical change 1.104)
This commit is contained in:
flatcap.org!flatcap 2003-01-19 11:48:06 +00:00
parent bfb9a428eb
commit 563fc17118

View File

@ -98,6 +98,8 @@
#include "mst.h"
#include "dir.h"
#include "runlist.h"
//#include "debug.h"
#include "utils.h"
extern const unsigned char attrdef_ntfs12_array[2400];
extern const unsigned char boot_array[3429];
@ -156,11 +158,11 @@ struct {
int attr_defs_len; /* in bytes */
uchar_t *upcase; /* filename, upcase table. */
u32 upcase_len; /* Determined automatically. */
char quiet; /* -q, quiet execution. */
char verbose; /* -v, verbose execution, given twice,
int quiet; /* -q, quiet execution. */
int verbose; /* -v, verbose execution, given twice,
* really verbose execution (debug
* mode). */
char force; /* -F, force fs creation. */
int force; /* -F, force fs creation. */
char quick_format; /* -f or -Q, fast format, don't zero
the volume first. */
char enable_compression; /* -C, enables compression of all files
@ -168,18 +170,11 @@ struct {
char disable_indexing; /* -I, disables indexing of file
contents on the volume by default. */
/* -V, print version and exit. */
} opt;
} opts;
/* Error output. Ignores quiet (-q). */
void Eprintf(const char *fmt, ...)
{
va_list ap;
fprintf(stderr, "ERROR: ");
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
GEN_PRINTF (Eprintf, stderr, NULL, FALSE)
GEN_PRINTF (Vprintf, stdout, &opts.verbose, TRUE)
GEN_PRINTF (Qprintf, stdout, &opts.quiet, FALSE)
void err_exit(const char *fmt, ...) __attribute__ ((noreturn));
@ -201,7 +196,7 @@ void Dprintf(const char *fmt, ...)
{
va_list ap;
if (!opt.quiet && opt.verbose > 1) {
if (!opts.quiet && opts.verbose > 1) {
printf("DEBUG: ");
va_start(ap, fmt);
vprintf(fmt, ap);
@ -209,45 +204,21 @@ void Dprintf(const char *fmt, ...)
}
}
/* Verbose output (-v). */
void Vprintf(const char *fmt, ...)
{
va_list ap;
if (!opt.quiet && opt.verbose > 0) {
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
/* Quietable output (if not -q). */
void Qprintf(const char *fmt, ...)
{
va_list ap;
if (!opt.quiet) {
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
}
}
void append_to_bad_blocks(unsigned long block)
{
long long *new_buf;
if (!(opt.nr_bad_blocks & 15)) {
new_buf = realloc(opt.bad_blocks, (opt.nr_bad_blocks + 16) *
if (!(opts.nr_bad_blocks & 15)) {
new_buf = realloc(opts.bad_blocks, (opts.nr_bad_blocks + 16) *
sizeof(long long));
if (!new_buf)
err_exit("Reallocating memory for bad blocks list "
"failed: %s\n", strerror(errno));
if (opt.bad_blocks != new_buf)
free(opt.bad_blocks);
opt.bad_blocks = new_buf;
if (opts.bad_blocks != new_buf)
free(opts.bad_blocks);
opts.bad_blocks = new_buf;
}
opt.bad_blocks[opt.nr_bad_blocks++] = block;
opts.bad_blocks[opts.nr_bad_blocks++] = block;
}
__inline__ long long mkntfs_write(int fd, const void *buf, long long count)
@ -255,7 +226,7 @@ __inline__ long long mkntfs_write(int fd, const void *buf, long long count)
long long bytes_written, total;
int retry;
if (opt.no_action)
if (opts.no_action)
return count;
total = 0LL;
retry = 0;
@ -301,7 +272,7 @@ s64 ntfs_rlwrite(int fd, const runlist *rl, const char *val,
if (inited_size)
*inited_size = 0LL;
if (opt.no_action)
if (opts.no_action)
return val_len;
total = delta = 0LL;
for (i = 0; rl[i].length; i++) {
@ -628,15 +599,15 @@ void dump_attr_record(ATTR_RECORD *a)
return;
}
u = le32_to_cpu(a->type);
for (i = 0; opt.attr_defs[i].type; i++)
if (le32_to_cpu(opt.attr_defs[i].type) >= u)
for (i = 0; opts.attr_defs[i].type; i++)
if (le32_to_cpu(opts.attr_defs[i].type) >= u)
break;
if (opt.attr_defs[i].type) {
// printf("type = 0x%x\n", le32_to_cpu(opt.attr_defs[i].type));
// { char *p = (char*)opt.attr_defs[i].name;
if (opts.attr_defs[i].type) {
// printf("type = 0x%x\n", le32_to_cpu(opts.attr_defs[i].type));
// { char *p = (char*)opts.attr_defs[i].name;
// printf("name = %c%c%c%c%c\n", *p, p[1], p[2], p[3], p[4]);
// }
if (ucstos(s, opt.attr_defs[i].name, sizeof(s)) == -1) {
if (ucstos(s, opts.attr_defs[i].name, sizeof(s)) == -1) {
Eprintf("Could not convert Unicode string to single "
"byte string in current locale.\n");
strncpy(s, "Error converting Unicode string",
@ -794,7 +765,7 @@ void format_mft_record(MFT_RECORD *m)
a->type = AT_END;
a->length = cpu_to_le32(0);
#if 0
if (!opt.quiet && opt.verbose > 1)
if (!opts.quiet && opts.verbose > 1)
dump_mft_record(m);
#endif
}
@ -891,11 +862,11 @@ runlist *allocate_scattered_clusters(s64 clusters)
s64 prev_run_len = 0LL;
char bit;
end = opt.nr_clusters;
end = opts.nr_clusters;
/* Loop until all clusters are allocated. */
while (clusters) {
/* Loop in current zone until we run out of free clusters. */
for (lcn = opt.mft_zone_end; lcn < end; lcn++) {
for (lcn = opts.mft_zone_end; lcn < end; lcn++) {
bit = ntfs_bit_get_and_set(lcn_bitmap, lcn, 1);
if (bit)
continue;
@ -930,10 +901,10 @@ runlist *allocate_scattered_clusters(s64 clusters)
}
/* Switch to next zone, decreasing mft zone by factor 2. */
end = opt.mft_zone_end;
opt.mft_zone_end >>= 1;
end = opts.mft_zone_end;
opts.mft_zone_end >>= 1;
/* Have we run out of space on the volume? */
if (opt.mft_zone_end <= 0)
if (opts.mft_zone_end <= 0)
goto err_end;
}
return rl;
@ -1129,7 +1100,7 @@ int insert_positioned_attr_in_mft_record(MFT_RECORD *m, const ATTR_TYPES type,
if (err >= 0)
err = -EIO;
Eprintf("insert_positioned_attr_in_mft_record failed with "
"error %i.\n", err < 0 ? err : bw);
"error %lld.\n", err < 0 ? err : bw);
}
err_out:
if (ctx)
@ -1314,7 +1285,7 @@ int insert_non_resident_attr_in_mft_record(MFT_RECORD *m, const ATTR_TYPES type,
if (err >= 0)
err = -EIO;
Eprintf("insert_non_resident_attr_in_mft_record failed with "
"error %i.\n", err < 0 ? err : bw);
"error %lld.\n", (long long) (err < 0 ? err : bw));
}
err_out:
if (ctx)
@ -1722,14 +1693,14 @@ int add_attr_index_root(MFT_RECORD *m, const char *name, const u32 name_len,
free(r);
return -EINVAL;
}
if (index_block_size < opt.sector_size) {
if (index_block_size < opts.sector_size) {
Eprintf("add_attr_index_root: index block size is "
"smaller than the sector size.\n");
free(r);
return -EINVAL;
}
r->clusters_per_index_block = index_block_size /
opt.sector_size;
opts.sector_size;
}
memset(&r->reserved, 0, sizeof(r->reserved));
r->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
@ -2250,11 +2221,11 @@ int create_hardlink(INDEX_BLOCK *index, const MFT_REF ref_parent,
void init_options()
{
memset(&opt, 0, sizeof(opt));
opt.index_block_size = 4096;
opt.attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
opt.attr_defs_len = sizeof(attrdef_ntfs12_array);
//Dprintf("Attr_defs table length = %u\n", opt.attr_defs_len);
memset(&opts, 0, sizeof(opts));
opts.index_block_size = 4096;
opts.attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
opts.attr_defs_len = sizeof(attrdef_ntfs12_array);
//Dprintf("Attr_defs table length = %u\n", opts.attr_defs_len);
}
void usage(void) __attribute__ ((noreturn));
@ -2285,7 +2256,7 @@ void parse_options(int argc, char *argv[])
while ((c = getopt(argc, argv, "c:fnqs:vz:CFIL:QV")) != EOF)
switch (c) {
case 'n':
opt.no_action = 1;
opts.no_action = 1;
break;
case 'c':
l = strtol(optarg, &s, 0);
@ -2295,34 +2266,34 @@ void parse_options(int argc, char *argv[])
break;
case 'f':
case 'Q':
opt.quick_format = 1;
opts.quick_format = 1;
break;
case 'q':
opt.quiet = 1;
opts.quiet = 1;
break;
case 's':
l = strtol(optarg, &s, 0);
if (!l || l > INT_MAX || *s)
err_exit("Invalid sector size.\n");
opt.sector_size = l;
opts.sector_size = l;
break;
case 'v':
opt.verbose++;
opts.verbose++;
break;
case 'z':
l = strtol(optarg, &s, 0);
if (l < 1 || l > 4 || *s)
err_exit("Invalid MFT zone multiplier.\n");
opt.mft_zone_multiplier = l;
opts.mft_zone_multiplier = l;
break;
case 'C':
opt.enable_compression = 1;
opts.enable_compression = 1;
break;
case 'F':
opt.force = 1;
opts.force = 1;
break;
case 'I':
opt.disable_indexing = 1;
opts.disable_indexing = 1;
break;
case 'L':
vol->vol_name = optarg;
@ -2341,7 +2312,7 @@ void parse_options(int argc, char *argv[])
if (*s || !u || (u >= ULONG_MAX && errno == ERANGE))
err_exit("Invalid number of sectors: %s\n",
argv[optind - 1]);
opt.nr_sectors = u;
opts.nr_sectors = u;
}
if (optind < argc)
usage();
@ -2377,10 +2348,10 @@ void mkntfs_exit(void)
free(rl_bad);
if (rl_index)
free(rl_index);
if (opt.bad_blocks)
free(opt.bad_blocks);
if (opt.attr_defs != (ATTR_DEF*)attrdef_ntfs12_array)
free(opt.attr_defs);
if (opts.bad_blocks)
free(opts.bad_blocks);
if (opts.attr_defs != (ATTR_DEF*)attrdef_ntfs12_array)
free(opts.attr_defs);
if (vol->upcase)
free(vol->upcase);
flk.l_type = F_UNLCK;
@ -2396,10 +2367,10 @@ void mkntfs_exit(void)
free(vol);
}
// What's wrong with MK_MREF?
#define MAKE_MFT_REF(_ref, _seqno) cpu_to_le64((((u64)(_seqno)) << 48) \
| ((u64)(_ref)))
int main(int argc, char **argv)
{
int i, j, err;
@ -2430,7 +2401,7 @@ int main(int argc, char **argv)
if (!vol->upcase)
err_exit("Could not allocate memory for internal buffer.\n");
init_upcase_table(vol->upcase, vol->upcase_len * sizeof(uchar_t));
/* Initialize opt to zero / required values. */
/* Initialize opts to zero / required values. */
init_options();
/* Parse command line options. */
parse_options(argc, argv);
@ -2444,25 +2415,25 @@ int main(int argc, char **argv)
}
if (!S_ISBLK(sbuf.st_mode)) {
Eprintf("%s is not a block device.\n", vol->dev_name);
if (!opt.force)
if (!opts.force)
err_exit("Refusing to make a filesystem here!\n");
if (!opt.nr_sectors) {
if (!opts.nr_sectors) {
if (!sbuf.st_size && !sbuf.st_blocks)
err_exit("You must specify the number of "
"sectors.\n");
if (opt.sector_size) {
if (opts.sector_size) {
if (sbuf.st_size)
opt.nr_sectors = sbuf.st_size /
opt.sector_size;
opts.nr_sectors = sbuf.st_size /
opts.sector_size;
else
opt.nr_sectors = ((s64)sbuf.st_blocks
<< 9) / opt.sector_size;
opts.nr_sectors = ((s64)sbuf.st_blocks
<< 9) / opts.sector_size;
} else {
if (sbuf.st_size)
opt.nr_sectors = sbuf.st_size / 512;
opts.nr_sectors = sbuf.st_size / 512;
else
opt.nr_sectors = sbuf.st_blocks;
opt.sector_size = 512;
opts.nr_sectors = sbuf.st_blocks;
opts.sector_size = 512;
}
}
fprintf(stderr, "mkntfs forced anyway.\n");
@ -2482,14 +2453,14 @@ int main(int argc, char **argv)
vol->dev_name, strerror(errno));
else if (mnt_flags & NTFS_MF_MOUNTED) {
Eprintf("%s is mounted.\n", vol->dev_name);
if (!opt.force)
if (!opts.force)
err_exit("Refusing to make a filesystem here!\n");
fprintf(stderr, "mkntfs forced anyway. Hope /etc/mtab is "
"incorrect.\n");
}
/* Open the device for reading or reading and writing. */
if (opt.no_action) {
if (opts.no_action) {
Qprintf("Running in READ-ONLY mode!\n");
i = O_RDONLY;
} else
@ -2500,7 +2471,7 @@ int main(int argc, char **argv)
strerror(errno));
/* Acquire exlusive (mandatory) write lock on the whole device. */
memset(&flk, 0, sizeof(flk));
if (opt.no_action)
if (opts.no_action)
flk.l_type = F_RDLCK;
else
flk.l_type = F_WRLCK;
@ -2509,7 +2480,7 @@ int main(int argc, char **argv)
err = fcntl(vol->fd, F_SETLK, &flk);
if (err == -1) {
Eprintf("Could not lock %s for %s: %s\n", vol->dev_name,
opt.no_action ? "reading" : "writing",
opts.no_action ? "reading" : "writing",
strerror(errno));
err = close(vol->fd);
if (err == -1)
@ -2526,12 +2497,12 @@ int main(int argc, char **argv)
exit(1);
}
/* If user didn't specify the sector size, determine it now. */
if (!opt.sector_size) {
if (!opts.sector_size) {
#ifdef BLKSSZGET
int _sect_size = 0;
if (ioctl(vol->fd, BLKSSZGET, &_sect_size) >= 0)
opt.sector_size = _sect_size;
opts.sector_size = _sect_size;
else
#endif
{
@ -2539,57 +2510,57 @@ int main(int argc, char **argv)
"not be obtained automatically.\n"
"Assuming sector size is 512 bytes.\n",
vol->dev_name);
opt.sector_size = 512;
opts.sector_size = 512;
}
}
/* Validate sector size. */
if ((opt.sector_size - 1) & opt.sector_size ||
opt.sector_size < 256 || opt.sector_size > 4096)
if ((opts.sector_size - 1) & opts.sector_size ||
opts.sector_size < 256 || opts.sector_size > 4096)
err_exit("Error: sector_size is invalid. It must be a power "
"of two, and it must be\n greater or equal 256 and "
"less than or equal 4096 bytes.\n");
Dprintf("sector size = %i bytes\n", opt.sector_size);
Dprintf("sector size = %i bytes\n", opts.sector_size);
/* If user didn't specify the number of sectors, determine it now. */
if (!opt.nr_sectors) {
opt.nr_sectors = ntfs_device_size_get(vol->fd, opt.sector_size);
if (opt.nr_sectors <= 0)
if (!opts.nr_sectors) {
opts.nr_sectors = ntfs_device_size_get(vol->fd, opts.sector_size);
if (opts.nr_sectors <= 0)
err_exit("ntfs_device_size_get(%s) failed. Please "
"specify it manually.\n",
vol->dev_name);
}
Dprintf("number of sectors = %Ld (0x%Lx)\n", opt.nr_sectors,
opt.nr_sectors);
Dprintf("number of sectors = %Ld (0x%Lx)\n", opts.nr_sectors,
opts.nr_sectors);
/* Reserve the last sector for the backup boot sector. */
opt.nr_sectors--;
opts.nr_sectors--;
/* If user didn't specify the volume size, determine it now. */
if (!opt.volume_size)
opt.volume_size = opt.nr_sectors * opt.sector_size;
else if (opt.volume_size & (opt.sector_size - 1))
if (!opts.volume_size)
opts.volume_size = opts.nr_sectors * opts.sector_size;
else if (opts.volume_size & (opts.sector_size - 1))
err_exit("Error: volume_size is not a multiple of "
"sector_size.\n");
/* Validate volume size. */
if (opt.volume_size < 1 << 20 /* 1MiB */)
if (opts.volume_size < 1 << 20 /* 1MiB */)
err_exit("Error: device is too small (%ikiB). Minimum NTFS "
"volume size is 1MiB.\n", opt.volume_size / 1024);
Dprintf("volume size = %LikiB\n", opt.volume_size / 1024);
"volume size is 1MiB.\n", opts.volume_size / 1024);
Dprintf("volume size = %LikiB\n", opts.volume_size / 1024);
/* If user didn't specify the cluster size, determine it now. */
if (!vol->cluster_size) {
if (opt.volume_size <= 512LL << 20) /* <= 512MB */
if (opts.volume_size <= 512LL << 20) /* <= 512MB */
vol->cluster_size = 512;
else if (opt.volume_size <= 1LL << 30) /* ]512MB-1GB] */
else if (opts.volume_size <= 1LL << 30) /* ]512MB-1GB] */
vol->cluster_size = 1024;
else if (opt.volume_size <= 2LL << 30) /* ]1GB-2GB] */
else if (opts.volume_size <= 2LL << 30) /* ]1GB-2GB] */
vol->cluster_size = 2048;
else
vol->cluster_size = 4096;
/* For small volumes on devices with large sector sizes. */
if (vol->cluster_size < opt.sector_size)
vol->cluster_size = opt.sector_size;
if (vol->cluster_size < opts.sector_size)
vol->cluster_size = opts.sector_size;
}
/* Validate cluster size. */
if (vol->cluster_size & (vol->cluster_size - 1) ||
vol->cluster_size < opt.sector_size ||
vol->cluster_size > 128 * opt.sector_size ||
vol->cluster_size < opts.sector_size ||
vol->cluster_size > 128 * opts.sector_size ||
vol->cluster_size > 65536)
err_exit("Error: cluster_size is invalid. It must be a power "
"of two, be at least\nthe same as sector_size, be "
@ -2599,15 +2570,15 @@ int main(int argc, char **argv)
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
Dprintf("cluster size = %i bytes\n", vol->cluster_size);
if (vol->cluster_size > 4096) {
if (opt.enable_compression) {
if (!opt.force)
if (opts.enable_compression) {
if (!opts.force)
err_exit("Error: cluster_size is above 4096 "
"bytes and compression is "
"requested.\nThis is not "
"possible due to limitations "
"in the compression algorithm "
"used by\nWindows.\n");
opt.enable_compression = 0;
opts.enable_compression = 0;
}
Qprintf("Warning: compression will be disabled on this volume "
"because it is not\nsupported when the cluster "
@ -2616,23 +2587,23 @@ int main(int argc, char **argv)
"by Windows.\n");
}
/* If user didn't specify the number of clusters, determine it now. */
if (!opt.nr_clusters)
opt.nr_clusters = opt.volume_size / vol->cluster_size;
if (!opts.nr_clusters)
opts.nr_clusters = opts.volume_size / vol->cluster_size;
/*
* Check the cluster_size and nr_sectors for consistency with
* sector_size and nr_sectors. And check both of these for consistency
* with volume_size.
*/
if (opt.nr_clusters != (opt.nr_sectors * opt.sector_size) /
if (opts.nr_clusters != (opts.nr_sectors * opts.sector_size) /
vol->cluster_size ||
opt.volume_size / opt.sector_size != opt.nr_sectors ||
opt.volume_size / vol->cluster_size != opt.nr_clusters)
opts.volume_size / opts.sector_size != opts.nr_sectors ||
opts.volume_size / vol->cluster_size != opts.nr_clusters)
err_exit("Illegal combination of volume/cluster/sector size "
"and/or cluster/sector number.\n");
Dprintf("number of clusters = %Lu (0x%Lx)\n", opt.nr_clusters,
opt.nr_clusters);
Dprintf("number of clusters = %Lu (0x%Lx)\n", opts.nr_clusters,
opts.nr_clusters);
/* Determine lcn bitmap byte size and allocate it. */
lcn_bitmap_byte_size = (opt.nr_clusters + 7) >> 3;
lcn_bitmap_byte_size = (opts.nr_clusters + 7) >> 3;
/* Needs to be multiple of 8 bytes. */
lcn_bitmap_byte_size = (lcn_bitmap_byte_size + 7) & ~7;
i = (lcn_bitmap_byte_size + vol->cluster_size - 1) &
@ -2647,17 +2618,17 @@ int main(int argc, char **argv)
* $Bitmap can overlap the end of the volume. Any bits in this region
* must be set. This region also encompasses the backup boot sector.
*/
for (i = opt.nr_clusters; i < lcn_bitmap_byte_size << 3; i++)
for (i = opts.nr_clusters; i < lcn_bitmap_byte_size << 3; i++)
ntfs_bit_set(lcn_bitmap, (u64)i, 1);
/*
* Determine mft_size: 16 mft records or 1 cluster, which ever is
* bigger, rounded to multiples of cluster size.
*/
opt.mft_size = (16 * vol->mft_record_size + vol->cluster_size - 1)
opts.mft_size = (16 * vol->mft_record_size + vol->cluster_size - 1)
& ~(vol->cluster_size - 1);
Dprintf("MFT size = %i (0x%x) bytes\n", opt.mft_size, opt.mft_size);
Dprintf("MFT size = %i (0x%x) bytes\n", opts.mft_size, opts.mft_size);
/* Determine mft bitmap size and allocate it. */
mft_bitmap_size = opt.mft_size / vol->mft_record_size;
mft_bitmap_size = opts.mft_size / vol->mft_record_size;
/* Convert to bytes, at least one. */
mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
/* Mft bitmap is allocated in multiples of 8 bytes. */
@ -2687,66 +2658,66 @@ int main(int argc, char **argv)
/* Allocate cluster for mft bitmap. */
ntfs_bit_set(lcn_bitmap, (s64)j, 1);
/* If user didn't specify the mft lcn, determine it now. */
if (!opt.mft_lcn) {
if (!opts.mft_lcn) {
/*
* We start at the higher value out of 16kiB and just after the
* mft bitmap.
*/
opt.mft_lcn = rl_mft_bmp[0].lcn + rl_mft_bmp[0].length;
if (opt.mft_lcn * vol->cluster_size < 16 * 1024)
opt.mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
opts.mft_lcn = rl_mft_bmp[0].lcn + rl_mft_bmp[0].length;
if (opts.mft_lcn * vol->cluster_size < 16 * 1024)
opts.mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
vol->cluster_size;
}
Dprintf("$MFT logical cluster number = 0x%x\n", opt.mft_lcn);
Dprintf("$MFT logical cluster number = 0x%x\n", opts.mft_lcn);
/* Determine MFT zone size. */
opt.mft_zone_end = opt.nr_clusters;
switch (opt.mft_zone_multiplier) { /* % of volume size in clusters */
opts.mft_zone_end = opts.nr_clusters;
switch (opts.mft_zone_multiplier) { /* % of volume size in clusters */
case 4:
opt.mft_zone_end = opt.mft_zone_end >> 1; /* 50% */
opts.mft_zone_end = opts.mft_zone_end >> 1; /* 50% */
break;
case 3:
opt.mft_zone_end = opt.mft_zone_end * 3 >> 3; /* 37.5% */
opts.mft_zone_end = opts.mft_zone_end * 3 >> 3; /* 37.5% */
break;
case 2:
opt.mft_zone_end = opt.mft_zone_end >> 2; /* 25% */
opts.mft_zone_end = opts.mft_zone_end >> 2; /* 25% */
break;
/* case 1: */
default:
opt.mft_zone_end = opt.mft_zone_end >> 3; /* 12.5% */
opts.mft_zone_end = opts.mft_zone_end >> 3; /* 12.5% */
break;
}
Dprintf("MFT zone size = %lukiB\n", opt.mft_zone_end / 1024);
Dprintf("MFT zone size = %lukiB\n", opts.mft_zone_end / 1024);
/*
* The mft zone begins with the mft data attribute, not at the beginning
* of the device.
*/
opt.mft_zone_end += opt.mft_lcn;
opts.mft_zone_end += opts.mft_lcn;
/* Create runlist for mft. */
rl_mft = (runlist *)malloc(2 * sizeof(runlist));
if (!rl_mft)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
rl_mft[0].vcn = 0LL;
rl_mft[0].lcn = opt.mft_lcn;
rl_mft[0].lcn = opts.mft_lcn;
/* We already rounded mft size up to a cluster. */
j = opt.mft_size / vol->cluster_size;
j = opts.mft_size / vol->cluster_size;
rl_mft[1].vcn = rl_mft[0].length = j;
rl_mft[1].lcn = -1LL;
rl_mft[1].length = 0LL;
/* Allocate clusters for mft. */
for (i = 0; i < j; i++)
ntfs_bit_set(lcn_bitmap, opt.mft_lcn + i, 1);
ntfs_bit_set(lcn_bitmap, opts.mft_lcn + i, 1);
/* Determine mftmirr_lcn (middle of volume). */
opt.mftmirr_lcn = (opt.nr_sectors * opt.sector_size >> 1)
opts.mftmirr_lcn = (opts.nr_sectors * opts.sector_size >> 1)
/ vol->cluster_size;
Dprintf("$MFTMirr logical cluster number = 0x%x\n", opt.mftmirr_lcn);
Dprintf("$MFTMirr logical cluster number = 0x%x\n", opts.mftmirr_lcn);
/* Create runlist for mft mirror. */
rl_mftmirr = (runlist *)malloc(2 * sizeof(runlist));
if (!rl_mftmirr)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
rl_mftmirr[0].vcn = 0LL;
rl_mftmirr[0].lcn = opt.mftmirr_lcn;
rl_mftmirr[0].lcn = opts.mftmirr_lcn;
/*
* The mft mirror is either 4kb (the first four records) or one cluster
* in size, which ever is bigger. In either case, it contains a
@ -2760,49 +2731,49 @@ int main(int argc, char **argv)
rl_mftmirr[1].length = 0LL;
/* Allocate clusters for mft mirror. */
for (i = 0; i < j; i++)
ntfs_bit_set(lcn_bitmap, opt.mftmirr_lcn + i, 1);
opt.logfile_lcn = opt.mftmirr_lcn + j;
Dprintf("$LogFile logical cluster number = 0x%x\n", opt.logfile_lcn);
ntfs_bit_set(lcn_bitmap, opts.mftmirr_lcn + i, 1);
opts.logfile_lcn = opts.mftmirr_lcn + j;
Dprintf("$LogFile logical cluster number = 0x%x\n", opts.logfile_lcn);
/* Create runlist for log file. */
rl_logfile = (runlist *)malloc(2 * sizeof(runlist));
if (!rl_logfile)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
rl_logfile[0].vcn = 0LL;
rl_logfile[0].lcn = opt.logfile_lcn;
rl_logfile[0].lcn = opts.logfile_lcn;
/*
* Determine logfile_size from volume_size (rounded up to a cluster),
* making sure it does not overflow the end of the volume.
*/
if (opt.volume_size < 2048LL * 1024) /* < 2MiB */
opt.logfile_size = 256LL * 1024; /* -> 256kiB */
else if (opt.volume_size < 4000000LL) /* < 4MB */
opt.logfile_size = 512LL * 1024; /* -> 512kiB */
else if (opt.volume_size <= 200LL * 1024 * 1024)/* < 200MiB */
opt.logfile_size = 2048LL * 1024; /* -> 2MiB */
else if (opt.volume_size >= 400LL << 20) /* > 400MiB */
opt.logfile_size = 4 << 20; /* -> 4MiB */
if (opts.volume_size < 2048LL * 1024) /* < 2MiB */
opts.logfile_size = 256LL * 1024; /* -> 256kiB */
else if (opts.volume_size < 4000000LL) /* < 4MB */
opts.logfile_size = 512LL * 1024; /* -> 512kiB */
else if (opts.volume_size <= 200LL * 1024 * 1024)/* < 200MiB */
opts.logfile_size = 2048LL * 1024; /* -> 2MiB */
else if (opts.volume_size >= 400LL << 20) /* > 400MiB */
opts.logfile_size = 4 << 20; /* -> 4MiB */
else
opt.logfile_size = (opt.volume_size / 100) &
opts.logfile_size = (opts.volume_size / 100) &
~(vol->cluster_size - 1);
j = opt.logfile_size / vol->cluster_size;
while (rl_logfile[0].lcn + j >= opt.nr_clusters) {
j = opts.logfile_size / vol->cluster_size;
while (rl_logfile[0].lcn + j >= opts.nr_clusters) {
/*
* $Logfile would overflow volume. Need to make it smaller than
* the standard size. It's ok as we are creating a non-standard
* volume anyway if it is that small.
*/
opt.logfile_size >>= 1;
j = opt.logfile_size / vol->cluster_size;
opts.logfile_size >>= 1;
j = opts.logfile_size / vol->cluster_size;
}
opt.logfile_size = (opt.logfile_size + vol->cluster_size - 1) &
opts.logfile_size = (opts.logfile_size + vol->cluster_size - 1) &
~(vol->cluster_size - 1);
Dprintf("$LogFile (journal) size = %ikiB\n", opt.logfile_size / 1024);
Dprintf("$LogFile (journal) size = %ikiB\n", opts.logfile_size / 1024);
/*
* FIXME: The 256kiB limit is arbitrary. Should find out what the real
* minimum requirement for Windows is so it doesn't blue screen.
*/
if (opt.logfile_size < 256 << 10)
if (opts.logfile_size < 256 << 10)
err_exit("$LogFile would be created with invalid size. This "
"is not allowed as it would cause Windows to "
"blue screen and during boot.\n");
@ -2811,7 +2782,7 @@ int main(int argc, char **argv)
rl_logfile[1].length = 0LL;
/* Allocate clusters for log file. */
for (i = 0; i < j; i++)
ntfs_bit_set(lcn_bitmap, opt.logfile_lcn + i, 1);
ntfs_bit_set(lcn_bitmap, opts.logfile_lcn + i, 1);
/* Create runlist for $Boot. */
rl_boot = (runlist *)malloc(2 * sizeof(runlist));
if (!rl_boot)
@ -2831,7 +2802,7 @@ int main(int argc, char **argv)
for (i = 0; i < j; i++)
ntfs_bit_set(lcn_bitmap, 0LL + i, 1);
/* Allocate a buffer large enough to hold the mft. */
buf = calloc(1, opt.mft_size);
buf = calloc(1, opts.mft_size);
if (!buf)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
@ -2846,7 +2817,7 @@ int main(int argc, char **argv)
* $BadClus named stream $Bad contains the whole volume as a single
* sparse runlist entry.
*/
rl_bad[1].vcn = rl_bad[0].length = opt.nr_clusters;
rl_bad[1].vcn = rl_bad[0].length = opts.nr_clusters;
rl_bad[1].lcn = -1LL;
rl_bad[1].length = 0LL;
@ -2856,15 +2827,15 @@ int main(int argc, char **argv)
* If not quick format, fill the device with 0s.
* FIXME: Except bad blocks! (AIA)
*/
if (!opt.quick_format) {
if (!opts.quick_format) {
unsigned long position;
unsigned long mid_clust;
float progress_inc = (float)opt.nr_clusters / 100;
float progress_inc = (float)opts.nr_clusters / 100;
Qprintf("Initialising device with zeroes: 0%%");
fflush(stdout);
mid_clust = (opt.volume_size >> 1) / vol->cluster_size;
for (position = 0; position < opt.nr_clusters; position++) {
mid_clust = (opts.volume_size >> 1) / vol->cluster_size;
for (position = 0; position < opts.nr_clusters; position++) {
if (!(position % (int)(progress_inc+1))) {
Qprintf("\b\b\b\b%3.0f%%", position /
progress_inc);
@ -2889,7 +2860,7 @@ int main(int argc, char **argv)
append_to_bad_blocks(position);
Qprintf("\nFound bad cluster (%ld). Adding to "
"list of bad blocks.\nInitialising "
"device with zeroes: %3.0i%%", position,
"device with zeroes: %3.0f%%", position,
position / progress_inc);
/* Seek to next cluster. */
lseek(vol->fd, ((off_t)position + 1) *
@ -2897,11 +2868,11 @@ int main(int argc, char **argv)
}
}
Qprintf("\b\b\b\b100%%");
position = (opt.volume_size & (vol->cluster_size - 1)) /
opt.sector_size;
position = (opts.volume_size & (vol->cluster_size - 1)) /
opts.sector_size;
for (i = 0; i < position; i++) {
bw = mkntfs_write(vol->fd, buf, opt.sector_size);
if (bw != opt.sector_size) {
bw = mkntfs_write(vol->fd, buf, opts.sector_size);
if (bw != opts.sector_size) {
if (bw != -1 || errno != EIO)
err_exit("This should not happen.\n");
else if (i + 1 == position &&
@ -2912,7 +2883,7 @@ int main(int argc, char **argv)
"location reserved for system "
"file $Boot.\n");
/* Seek to next sector. */
lseek(vol->fd, opt.sector_size, SEEK_CUR);
lseek(vol->fd, opts.sector_size, SEEK_CUR);
}
}
Qprintf(" - Done.\n");
@ -2951,9 +2922,9 @@ int main(int argc, char **argv)
ntfs_bit_set(mft_bitmap, 0LL + i, 1);
file_attrs = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM;
if (i == FILE_root) {
if (opt.disable_indexing)
if (opts.disable_indexing)
file_attrs |= FILE_ATTR_NOT_CONTENT_INDEXED;
if (opt.enable_compression)
if (opts.enable_compression)
file_attrs |= FILE_ATTR_COMPRESSED;
}
add_attr_std_info(m, file_attrs);
@ -2976,7 +2947,7 @@ int main(int argc, char **argv)
// FIXME: This should be IGNORE_CASE
if (!err)
err = add_attr_index_root(m, "$I30", 4, 0, AT_FILE_NAME,
COLLATION_FILE_NAME, opt.index_block_size);
COLLATION_FILE_NAME, opts.index_block_size);
// FIXME: This should be IGNORE_CASE
if (!err)
err = upgrade_to_large_index(m, "$I30", 4, 0, &index_block);
@ -3006,11 +2977,11 @@ int main(int argc, char **argv)
Vprintf("Creating $MFT (mft record 0)\n");
m = (MFT_RECORD*)buf;
err = add_attr_data_positioned(m, NULL, 0, 0, 0, rl_mft, buf,
opt.mft_size);
opts.mft_size);
if (!err)
err = create_hardlink(index_block, root_ref, m,
MAKE_MFT_REF(FILE_MFT, 1), opt.mft_size,
opt.mft_size, FILE_ATTR_HIDDEN |
MAKE_MFT_REF(FILE_MFT, 1), opts.mft_size,
opts.mft_size, FILE_ATTR_HIDDEN |
FILE_ATTR_SYSTEM, 0, 0, "$MFT",
FILE_NAME_WIN32_AND_DOS);
if (!err) {
@ -3044,19 +3015,19 @@ int main(int argc, char **argv)
//dump_mft_record(m);
Vprintf("Creating $LogFile (mft record 2)\n");
m = (MFT_RECORD*)(buf + 2 * vol->mft_record_size);
buf2 = malloc(opt.logfile_size);
buf2 = malloc(opts.logfile_size);
if (!buf2)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
memset(buf2, -1, opt.logfile_size);
memset(buf2, -1, opts.logfile_size);
err = add_attr_data_positioned(m, NULL, 0, 0, 0, rl_logfile, buf2,
opt.logfile_size);
opts.logfile_size);
free(buf2);
buf2 = NULL;
if (!err)
err = create_hardlink(index_block, root_ref, m,
MAKE_MFT_REF(FILE_LogFile, FILE_LogFile),
opt.logfile_size, opt.logfile_size,
opts.logfile_size, opts.logfile_size,
FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
"$LogFile", FILE_NAME_WIN32_AND_DOS);
if (!err) {
@ -3095,12 +3066,12 @@ int main(int argc, char **argv)
if (vol->major_ver < 3)
buf2_size = 36000;
else
buf2_size = opt.attr_defs_len;
buf2_size = opts.attr_defs_len;
buf2 = (char*)calloc(1, buf2_size);
if (!buf2)
err_exit("Failed to allocate internal buffer: %s\n",
strerror(errno));
memcpy(buf2, opt.attr_defs, opt.attr_defs_len);
memcpy(buf2, opts.attr_defs, opts.attr_defs_len);
err = add_attr_data(m, NULL, 0, 0, 0, buf2, buf2_size);
free(buf2);
buf2 = NULL;
@ -3149,18 +3120,18 @@ int main(int argc, char **argv)
* already inserted, so no need to worry about these things.
*/
bs = (NTFS_BOOT_SECTOR*)buf2;
bs->bpb.bytes_per_sector = cpu_to_le16(opt.sector_size);
bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size);
bs->bpb.sectors_per_cluster = (u8)(vol->cluster_size /
opt.sector_size);
opts.sector_size);
bs->bpb.media_type = 0xf8; /* hard disk */
/*
* If there are problems go back to bs->unused[0-3] and set them. See
* ../include/bootsect.h for details. Other fields to also consider
* setting are: bs->bpb.sectors_per_track, .heads, and .hidden_sectors.
*/
bs->number_of_sectors = scpu_to_le64(opt.nr_sectors);
bs->mft_lcn = scpu_to_le64(opt.mft_lcn);
bs->mftmirr_lcn = scpu_to_le64(opt.mftmirr_lcn);
bs->number_of_sectors = scpu_to_le64(opts.nr_sectors);
bs->mft_lcn = scpu_to_le64(opts.mft_lcn);
bs->mftmirr_lcn = scpu_to_le64(opts.mftmirr_lcn);
if (vol->mft_record_size >= vol->cluster_size)
bs->clusters_per_mft_record = vol->mft_record_size /
vol->cluster_size;
@ -3174,13 +3145,13 @@ int main(int argc, char **argv)
Dprintf("Clusters per mft record = %i (0x%x)\n",
bs->clusters_per_mft_record,
bs->clusters_per_mft_record);
if (opt.index_block_size >= vol->cluster_size)
bs->clusters_per_index_record = opt.index_block_size /
if (opts.index_block_size >= vol->cluster_size)
bs->clusters_per_index_record = opts.index_block_size /
vol->cluster_size;
else {
bs->clusters_per_index_record = -(ffs(opt.index_block_size) - 1);
bs->clusters_per_index_record = -(ffs(opts.index_block_size) - 1);
if ((1 << -bs->clusters_per_index_record) !=
opt.index_block_size)
opts.index_block_size)
err_exit("BUG: calculated clusters_per_index_record "
"is wrong (= 0x%x)\n",
bs->clusters_per_index_record);
@ -3197,7 +3168,7 @@ int main(int argc, char **argv)
*/
bs->checksum = cpu_to_le32(0);
/* Make sure the bootsector is ok. */
if (!ntfs_boot_sector_is_ntfs(bs, opt.verbose > 0 ? 0 : 1))
if (!ntfs_boot_sector_is_ntfs(bs, opts.verbose > 0 ? 0 : 1))
err_exit("FATAL: Generated boot sector is invalid!\n");
err = add_attr_data_positioned(m, NULL, 0, 0, 0, rl_boot, buf2, 8192);
if (!err)
@ -3215,10 +3186,10 @@ int main(int argc, char **argv)
err_exit("Couldn't create $Boot: %s\n", strerror(-err));
Vprintf("Creating backup boot sector.\n");
/*
* Write the first max(512, opt.sector_size) bytes from buf2 to the
* Write the first max(512, opts.sector_size) bytes from buf2 to the
* last sector.
*/
if (lseek(vol->fd, (opt.nr_sectors + 1) * opt.sector_size - i,
if (lseek(vol->fd, (opts.nr_sectors + 1) * opts.sector_size - i,
SEEK_SET) == (off_t)-1)
goto bb_err;
bw = mkntfs_write(vol->fd, buf2, i);
@ -3249,7 +3220,7 @@ bb_err:
// FIXME: This should be IGNORE_CASE
/* Create a sparse named stream of size equal to the volume size. */
err = add_attr_data_positioned(m, "$Bad", 4, 0, 0, rl_bad, NULL,
opt.nr_clusters * vol->cluster_size);
opts.nr_clusters * vol->cluster_size);
if (!err) {
err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
}
@ -3301,7 +3272,7 @@ bb_err:
//dump_mft_record(m);
/* NTFS 1.2 reserved system files (mft records 0xb-0xf) */
for (i = 0xb; i < 0x10; i++) {
Vprintf("Creating system file (mft record 0x%x)\n", i, i);
Vprintf("Creating system file (mft record 0x%x)\n", i);
m = (MFT_RECORD*)(buf + i * vol->mft_record_size);
err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
if (!err) {
@ -3391,10 +3362,10 @@ bb_err:
* its creation.
*/
Vprintf("Syncing $MFT.\n");
pos = opt.mft_lcn * vol->cluster_size;
pos = opts.mft_lcn * vol->cluster_size;
lw = 1;
for (i = 0; i < opt.mft_size / vol->mft_record_size; i++) {
if (!opt.no_action)
for (i = 0; i < opts.mft_size / vol->mft_record_size; i++) {
if (!opts.no_action)
lw = ntfs_mst_pwrite(vol->fd, pos, 1,
vol->mft_record_size,
buf + i * vol->mft_record_size);
@ -3404,7 +3375,7 @@ bb_err:
pos += vol->mft_record_size;
}
Vprintf("Updating $MFTMirr.\n");
pos = opt.mftmirr_lcn * vol->cluster_size;
pos = opts.mftmirr_lcn * vol->cluster_size;
lw = 1;
for (i = 0; i < rl_mftmirr[0].length * vol->cluster_size /
vol->mft_record_size; i++) {
@ -3421,7 +3392,7 @@ bb_err:
if (usn-- <= 1)
usn = 0xfffe;
*usnp = cpu_to_le16(usn);
if (!opt.no_action)
if (!opts.no_action)
lw = ntfs_mst_pwrite(vol->fd, pos, 1,
vol->mft_record_size,
buf + i * vol->mft_record_size);