parent
							
								
									bfb9a428eb
								
							
						
					
					
						commit
						563fc17118
					
				| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue