xref: /onnv-gate/usr/src/cmd/ntfsprogs/mkntfs.c (revision 10465:f9789e1a1626)
1 /**
2  * mkntfs - Part of the Linux-NTFS project.
3  *
4  * Copyright (c) 2000-2007 Anton Altaparmakov
5  * Copyright (c) 2001-2005 Richard Russon
6  * Copyright (c) 2002-2006 Szabolcs Szakacsits
7  * Copyright (c) 2005      Erik Sornes
8  * Copyright (c) 2007      Yura Pakhuchiy
9  *
10  * This utility will create an NTFS 1.2 or 3.1 volume on a user
11  * specified (block) device.
12  *
13  * Some things (option handling and determination of mount status) have been
14  * adapted from e2fsprogs-1.19 and lib/ext2fs/ismounted.c and misc/mke2fs.c in
15  * particular.
16  *
17  * This program is free software; you can redistribute it and/or modify
18  * it under the terms of the GNU General Public License as published by
19  * the Free Software Foundation; either version 2 of the License, or
20  * (at your option) any later version.
21  *
22  * This program is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  * GNU General Public License for more details.
26  *
27  * You should have received a copy of the GNU General Public License
28  * along with this program (in the main directory of the Linux-NTFS source
29  * in the file COPYING); if not, write to the Free Software Foundation,
30  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #ifdef  HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 #ifdef HAVE_STDLIB_H
41 #include <stdlib.h>
42 #endif
43 #ifdef HAVE_STDIO_H
44 #include <stdio.h>
45 #endif
46 #ifdef HAVE_STDARG_H
47 #include <stdarg.h>
48 #endif
49 #ifdef HAVE_STRING_H
50 #include <string.h>
51 #endif
52 #ifdef HAVE_ERRNO_H
53 #include <errno.h>
54 #endif
55 #ifdef HAVE_TIME_H
56 #include <time.h>
57 #endif
58 #ifdef HAVE_SYS_STAT_H
59 #include <sys/stat.h>
60 #endif
61 #ifdef HAVE_FCNTL_H
62 #include <fcntl.h>
63 #endif
64 #ifdef HAVE_LIMITS_H
65 #include <limits.h>
66 #endif
67 #ifdef HAVE_LIBGEN_H
68 #include <libgen.h>
69 #endif
70 #ifdef ENABLE_UUID
71 #include <uuid/uuid.h>
72 #endif
73 
74 
75 #ifdef HAVE_GETOPT_H
76 #include <getopt.h>
77 #else
78 	extern char *optarg;
79 	extern int optind;
80 #endif
81 
82 #ifdef HAVE_LINUX_MAJOR_H
83 #	include <linux/major.h>
84 #	ifndef MAJOR
85 #		define MAJOR(dev)	((dev) >> 8)
86 #		define MINOR(dev)	((dev) & 0xff)
87 #	endif
88 #	ifndef IDE_DISK_MAJOR
89 #		ifndef IDE0_MAJOR
90 #			define IDE0_MAJOR	3
91 #			define IDE1_MAJOR	22
92 #			define IDE2_MAJOR	33
93 #			define IDE3_MAJOR	34
94 #			define IDE4_MAJOR	56
95 #			define IDE5_MAJOR	57
96 #			define IDE6_MAJOR	88
97 #			define IDE7_MAJOR	89
98 #			define IDE8_MAJOR	90
99 #			define IDE9_MAJOR	91
100 #		endif
101 #		define IDE_DISK_MAJOR(M) \
102 				((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
103 				(M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
104 				(M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
105 				(M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
106 				(M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
107 #	endif
108 #	ifndef SCSI_DISK_MAJOR
109 #		ifndef SCSI_DISK0_MAJOR
110 #			define SCSI_DISK0_MAJOR	8
111 #			define SCSI_DISK1_MAJOR	65
112 #			define SCSI_DISK7_MAJOR	71
113 #		endif
114 #		define SCSI_DISK_MAJOR(M) \
115 				((M) == SCSI_DISK0_MAJOR || \
116 				((M) >= SCSI_DISK1_MAJOR && \
117 				(M) <= SCSI_DISK7_MAJOR))
118 #	endif
119 #endif
120 
121 #include "compat.h"
122 #include "security.h"
123 #include "types.h"
124 #include "attrib.h"
125 #include "bitmap.h"
126 #include "bootsect.h"
127 #include "device.h"
128 #include "dir.h"
129 #include "mft.h"
130 #include "mst.h"
131 #include "runlist.h"
132 #include "utils.h"
133 #include "ntfstime.h"
134 #include "sd.h"
135 #include "boot.h"
136 #include "attrdef.h"
137 #include "version.h"
138 #include "logging.h"
139 #include "support.h"
140 #include "unistr.h"
141 
142 #ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
143 #error "No default device io operations!  Cannot build mkntfs.  \
144 You need to run ./configure without the --disable-default-device-io-ops \
145 switch if you want to be able to build the NTFS utilities."
146 #endif
147 
148 /* Page size on ia32. Can change to 8192 on Alpha. */
149 #define NTFS_PAGE_SIZE	4096
150 
151 static char EXEC_NAME[] = "mkntfs";
152 
153 /**
154  * global variables
155  */
156 static u8		  *g_buf		  = NULL;
157 static int		   g_mft_bitmap_byte_size = 0;
158 static u8		  *g_mft_bitmap		  = NULL;
159 static int		   g_lcn_bitmap_byte_size = 0;
160 static u8		  *g_lcn_bitmap		  = NULL;
161 static runlist		  *g_rl_mft		  = NULL;
162 static runlist		  *g_rl_mft_bmp		  = NULL;
163 static runlist		  *g_rl_mftmirr		  = NULL;
164 static runlist		  *g_rl_logfile		  = NULL;
165 static runlist		  *g_rl_boot		  = NULL;
166 static runlist		  *g_rl_bad		  = NULL;
167 static INDEX_ALLOCATION  *g_index_block	  = NULL;
168 static ntfs_volume	  *g_vol		  = NULL;
169 static int		   g_mft_size		  = 0;
170 static long long	   g_mft_lcn		  = 0;		/* lcn of $MFT, $DATA attribute */
171 static long long	   g_mftmirr_lcn	  = 0;		/* lcn of $MFTMirr, $DATA */
172 static long long	   g_logfile_lcn	  = 0;		/* lcn of $LogFile, $DATA */
173 static int		   g_logfile_size	  = 0;		/* in bytes, determined from volume_size */
174 static long long	   g_mft_zone_end	  = 0;		/* Determined from volume_size and mft_zone_multiplier, in clusters */
175 static long long	   g_num_bad_blocks	  = 0;		/* Number of bad clusters */
176 static long long	  *g_bad_blocks		  = NULL;	/* Array of bad clusters */
177 
178 /**
179  * struct mkntfs_options
180  */
181 static struct mkntfs_options {
182 	char *dev_name;			/* Name of the device, or file, to use */
183 	BOOL enable_compression;	/* -C, enables compression of all files on the volume by default. */
184 	BOOL quick_format;		/* -f or -Q, fast format, don't zero the volume first. */
185 	BOOL force;			/* -F, force fs creation. */
186 	long heads;			/* -H, number of heads on device */
187 	BOOL disable_indexing;		/* -I, disables indexing of file contents on the volume by default. */
188 	BOOL no_action;			/* -n, do not write to device, only display what would be done. */
189 	long long part_start_sect;	/* -p, start sector of partition on parent device */
190 	long sector_size;		/* -s, in bytes, power of 2, default is 512 bytes. */
191 	long sectors_per_track;		/* -S, number of sectors per track on device */
192 	BOOL use_epoch_time;		/* -T, fake the time to be 00:00:00 UTC, Jan 1, 1970. */
193 	long mft_zone_multiplier;	/* -z, value from 1 to 4. Default is 1. */
194 	long long num_sectors;		/* size of device in sectors */
195 	long cluster_size;		/* -c, format with this cluster-size */
196 	char *label;			/* -L, volume label */
197 } opts;
198 
199 
200 /**
201  * mkntfs_license
202  */
mkntfs_license(void)203 static void mkntfs_license(void)
204 {
205 	ntfs_log_info("%s", ntfs_gpl);
206 }
207 
208 /**
209  * mkntfs_usage
210  */
mkntfs_usage(void)211 static void mkntfs_usage(void)
212 {
213 	ntfs_log_info("\nUsage: %s [options] device [number-of-sectors]\n"
214 "\n"
215 "Basic options:\n"
216 "    -f, --fast                      Perform a quick format\n"
217 "    -Q, --quick                     Perform a quick format\n"
218 "    -L, --label STRING              Set the volume label\n"
219 "    -C, --enable-compression        Enable compression on the volume\n"
220 "    -I, --no-indexing               Disable indexing on the volume\n"
221 "    -n, --no-action                 Do not write to disk\n"
222 "\n"
223 "Advanced options:\n"
224 "    -c, --cluster-size BYTES        Specify the cluster size for the volume\n"
225 "    -s, --sector-size BYTES         Specify the sector size for the device\n"
226 "    -p, --partition-start SECTOR    Specify the partition start sector\n"
227 "    -H, --heads NUM                 Specify the number of heads\n"
228 "    -S, --sectors-per-track NUM     Specify the number of sectors per track\n"
229 "    -z, --mft-zone-multiplier NUM   Set the MFT zone multiplier\n"
230 "    -T, --zero-time                 Fake the time to be 00:00 UTC, Jan 1, 1970\n"
231 "    -F, --force                     Force execution despite errors\n"
232 "\n"
233 "Output options:\n"
234 "    -q, --quiet                     Quiet execution\n"
235 "    -v, --verbose                   Verbose execution\n"
236 "        --debug                     Very verbose execution\n"
237 "\n"
238 "Help options:\n"
239 "    -V, --version                   Display version\n"
240 "    -l, --license                   Display licensing information\n"
241 "    -h, --help                      Display this help\n"
242 "\n", basename(EXEC_NAME));
243 	ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
244 }
245 
246 /**
247  * mkntfs_version
248  */
mkntfs_version(void)249 static void mkntfs_version(void)
250 {
251 	ntfs_log_info("\n%s v%s (libntfs %s)\n\n", EXEC_NAME, VERSION,
252 			ntfs_libntfs_version());
253 	ntfs_log_info("Create an NTFS volume on a user specified (block) "
254 			"device.\n\n");
255 	ntfs_log_info("Copyright (c) 2000-2007 Anton Altaparmakov\n");
256 	ntfs_log_info("Copyright (c) 2001-2005 Richard Russon\n");
257 	ntfs_log_info("Copyright (c) 2002-2006 Szabolcs Szakacsits\n");
258 	ntfs_log_info("Copyright (c) 2005      Erik Sornes\n");
259 	ntfs_log_info("Copyright (c) 2007      Yura Pakhuchiy\n");
260 	ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
261 }
262 
263 
264 /**
265  * mkntfs_parse_long
266  */
mkntfs_parse_long(const char * string,const char * name,long * num)267 static BOOL mkntfs_parse_long(const char *string, const char *name, long *num)
268 {
269 	char *end = NULL;
270 	long tmp;
271 
272 	if (!string || !name || !num)
273 		return FALSE;
274 
275 	if (*num >= 0) {
276 		ntfs_log_error("You may only specify the %s once.\n", name);
277 		return FALSE;
278 	}
279 
280 	tmp = strtol(string, &end, 0);
281 	if (end && *end) {
282 		ntfs_log_error("Cannot understand the %s '%s'.\n", name, string);
283 		return FALSE;
284 	} else {
285 		*num = tmp;
286 		return TRUE;
287 	}
288 }
289 
290 /**
291  * mkntfs_parse_llong
292  */
mkntfs_parse_llong(const char * string,const char * name,long long * num)293 static BOOL mkntfs_parse_llong(const char *string, const char *name,
294 		long long *num)
295 {
296 	char *end = NULL;
297 	long long tmp;
298 
299 	if (!string || !name || !num)
300 		return FALSE;
301 
302 	if (*num >= 0) {
303 		ntfs_log_error("You may only specify the %s once.\n", name);
304 		return FALSE;
305 	}
306 
307 	tmp = strtoll(string, &end, 0);
308 	if (end && *end) {
309 		ntfs_log_error("Cannot understand the %s '%s'.\n", name,
310 				string);
311 		return FALSE;
312 	} else {
313 		*num = tmp;
314 		return TRUE;
315 	}
316 }
317 
318 /**
319  * mkntfs_init_options
320  */
mkntfs_init_options(struct mkntfs_options * opts2)321 static void mkntfs_init_options(struct mkntfs_options *opts2)
322 {
323 	if (!opts2)
324 		return;
325 
326 	memset(opts2, 0, sizeof(*opts2));
327 
328 	/* Mark all the numeric options as "unset". */
329 	opts2->cluster_size		= -1;
330 	opts2->heads			= -1;
331 	opts2->mft_zone_multiplier	= -1;
332 	opts2->num_sectors		= -1;
333 	opts2->part_start_sect		= -1;
334 	opts2->sector_size		= -1;
335 	opts2->sectors_per_track	= -1;
336 }
337 
338 /**
339  * mkntfs_parse_options
340  */
mkntfs_parse_options(int argc,char * argv[],struct mkntfs_options * opts2)341 static BOOL mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *opts2)
342 {
343 	static const char *sopt = "-c:CfFhH:IlL:np:qQs:S:TvVz:";
344 	static const struct option lopt[] = {
345 		{ "cluster-size",	required_argument,	NULL, 'c' },
346 		{ "debug",		no_argument,		NULL, 'Z' },
347 		{ "enable-compression",	no_argument,		NULL, 'C' },
348 		{ "fast",		no_argument,		NULL, 'f' },
349 		{ "force",		no_argument,		NULL, 'F' },
350 		{ "heads",		required_argument,	NULL, 'H' },
351 		{ "help",		no_argument,		NULL, 'h' },
352 		{ "label",		required_argument,	NULL, 'L' },
353 		{ "license",		no_argument,		NULL, 'l' },
354 		{ "mft-zone-multiplier",required_argument,	NULL, 'z' },
355 		{ "no-action",		no_argument,		NULL, 'n' },
356 		{ "no-indexing",	no_argument,		NULL, 'I' },
357 		{ "partition-start",	required_argument,	NULL, 'p' },
358 		{ "quick",		no_argument,		NULL, 'Q' },
359 		{ "quiet",		no_argument,		NULL, 'q' },
360 		{ "sector-size",	required_argument,	NULL, 's' },
361 		{ "sectors-per-track",	required_argument,	NULL, 'S' },
362 		{ "verbose",		no_argument,		NULL, 'v' },
363 		{ "version",		no_argument,		NULL, 'V' },
364 		{ "zero-time",		no_argument,		NULL, 'T' },
365 		{ NULL, 0, NULL, 0 }
366 	};
367 
368 	int c = -1;
369 	int lic = 0;
370 	int err = 0;
371 	int ver = 0;
372 
373 	if (!argv || !opts2) {
374 		ntfs_log_error("Internal error: invalid parameters to "
375 				"mkntfs_options.\n");
376 		return FALSE;
377 	}
378 
379 	opterr = 0; /* We'll handle the errors, thank you. */
380 
381 	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
382 		switch (c) {
383 		case 1:		/* A device, or a number of sectors */
384 			if (!opts2->dev_name)
385 				opts2->dev_name = argv[optind - 1];
386 			else if (!mkntfs_parse_llong(optarg,
387 					"number of sectors",
388 					&opts2->num_sectors))
389 				err++;
390 			break;
391 		case 'C':
392 			opts2->enable_compression = TRUE;
393 			break;
394 		case 'c':
395 			if (!mkntfs_parse_long(optarg, "cluster size",
396 					&opts2->cluster_size))
397 				err++;
398 			break;
399 		case 'F':
400 			opts2->force = TRUE;
401 			break;
402 		case 'f':	/* fast */
403 		case 'Q':	/* quick */
404 			opts2->quick_format = TRUE;
405 			break;
406 		case 'H':
407 			if (!mkntfs_parse_long(optarg, "heads", &opts2->heads))
408 				err++;
409 			break;
410 		case 'h':
411 			err++;	/* display help */
412 			break;
413 		case 'I':
414 			opts2->disable_indexing = TRUE;
415 			break;
416 		case 'L':
417 			if (!opts2->label) {
418 				opts2->label = argv[optind-1];
419 			} else {
420 				ntfs_log_error("You may only specify the label "
421 						"once.\n");
422 				err++;
423 			}
424 			break;
425 		case 'l':
426 			lic++;	/* display the license */
427 			break;
428 		case 'n':
429 			opts2->no_action = TRUE;
430 			break;
431 		case 'p':
432 			if (!mkntfs_parse_llong(optarg, "partition start",
433 						&opts2->part_start_sect))
434 				err++;
435 			break;
436 		case 'q':
437 			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET |
438 					NTFS_LOG_LEVEL_VERBOSE |
439 					NTFS_LOG_LEVEL_PROGRESS);
440 			break;
441 		case 's':
442 			if (!mkntfs_parse_long(optarg, "sector size",
443 						&opts2->sector_size))
444 				err++;
445 			break;
446 		case 'S':
447 			if (!mkntfs_parse_long(optarg, "sectors per track",
448 						&opts2->sectors_per_track))
449 				err++;
450 			break;
451 		case 'T':
452 			opts2->use_epoch_time = TRUE;
453 			break;
454 		case 'v':
455 			ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET |
456 					NTFS_LOG_LEVEL_VERBOSE |
457 					NTFS_LOG_LEVEL_PROGRESS);
458 			break;
459 		case 'V':
460 			ver++;	/* display version info */
461 			break;
462 		case 'Z':	/* debug - turn on everything */
463 			ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG |
464 					NTFS_LOG_LEVEL_TRACE |
465 					NTFS_LOG_LEVEL_VERBOSE |
466 					NTFS_LOG_LEVEL_QUIET);
467 			break;
468 		case 'z':
469 			if (!mkntfs_parse_long(optarg, "mft zone multiplier",
470 						&opts2->mft_zone_multiplier))
471 				err++;
472 			break;
473 		default:
474 			if (ntfs_log_parse_option (argv[optind-1]))
475 				break;
476 			if (((optopt == 'c') || (optopt == 'H') ||
477 			     (optopt == 'L') || (optopt == 'p') ||
478 			     (optopt == 's') || (optopt == 'S') ||
479 			     (optopt == 'N') || (optopt == 'z')) &&
480 			     (!optarg)) {
481 				ntfs_log_error("Option '%s' requires an "
482 						"argument.\n", argv[optind-1]);
483 			} else if (optopt != '?') {
484 				ntfs_log_error("Unknown option '%s'.\n",
485 						argv[optind - 1]);
486 			}
487 			err++;
488 			break;
489 		}
490 	}
491 
492 	if (!err && !ver && !lic) {
493 		if (opts2->dev_name == NULL) {
494 			if (argc > 1)
495 				ntfs_log_error("You must specify a device.\n");
496 			err++;
497 		}
498 	}
499 
500 	if (ver)
501 		mkntfs_version();
502 	if (lic)
503 		mkntfs_license();
504 	if (err)
505 		mkntfs_usage();
506 
507 	return (!err && !ver && !lic);
508 }
509 
510 
511 /**
512  * mkntfs_time
513  */
mkntfs_time(void)514 static time_t mkntfs_time(void)
515 {
516 	if (!opts.use_epoch_time)
517 		return time(NULL);
518 	return 0;
519 }
520 
521 /**
522  * append_to_bad_blocks
523  */
append_to_bad_blocks(unsigned long long block)524 static BOOL append_to_bad_blocks(unsigned long long block)
525 {
526 	long long *new_buf;
527 
528 	if (!(g_num_bad_blocks & 15)) {
529 		new_buf = realloc(g_bad_blocks, (g_num_bad_blocks + 16) *
530 							sizeof(long long));
531 		if (!new_buf) {
532 			ntfs_log_perror("Reallocating memory for bad blocks "
533 				"list failed");
534 			return FALSE;
535 		}
536 		g_bad_blocks = new_buf;
537 	}
538 	g_bad_blocks[g_num_bad_blocks++] = block;
539 	return TRUE;
540 }
541 
542 /**
543  * mkntfs_write
544  */
mkntfs_write(struct ntfs_device * dev,const void * b,long long count)545 static long long mkntfs_write(struct ntfs_device *dev,
546 		const void *b, long long count)
547 {
548 	long long bytes_written, total;
549 	int retry;
550 
551 	if (opts.no_action)
552 		return count;
553 	total = 0LL;
554 	retry = 0;
555 	do {
556 		bytes_written = dev->d_ops->write(dev, b, count);
557 		if (bytes_written == -1LL) {
558 			retry = errno;
559 			ntfs_log_perror("Error writing to %s", dev->d_name);
560 			errno = retry;
561 			return bytes_written;
562 		} else if (!bytes_written) {
563 			retry++;
564 		} else {
565 			count -= bytes_written;
566 			total += bytes_written;
567 		}
568 	} while (count && retry < 3);
569 	if (count)
570 		ntfs_log_error("Failed to complete writing to %s after three retries."
571 			"\n", dev->d_name);
572 	return total;
573 }
574 
575 /**
576  * ntfs_rlwrite - Write data to disk on clusters found in a runlist.
577  *
578  * Write to disk the clusters contained in the runlist @rl taking the data
579  * from @val.  Take @val_len bytes from @val and pad the rest with zeroes.
580  *
581  * If the @rl specifies a completely sparse file, @val is allowed to be NULL.
582  *
583  * @inited_size if not NULL points to an output variable which will contain
584  * the actual number of bytes written to disk. I.e. this will not include
585  * sparse bytes for example.
586  *
587  * Return the number of bytes written (minus padding) or -1 on error. Errno
588  * will be set to the error code.
589  */
ntfs_rlwrite(struct ntfs_device * dev,const runlist * rl,const u8 * val,const s64 val_len,s64 * inited_size)590 static s64 ntfs_rlwrite(struct ntfs_device *dev, const runlist *rl,
591 		const u8 *val, const s64 val_len, s64 *inited_size)
592 {
593 	s64 bytes_written, total, length, delta;
594 	int retry, i;
595 
596 	if (inited_size)
597 		*inited_size = 0LL;
598 	if (opts.no_action)
599 		return val_len;
600 	total = 0LL;
601 	delta = 0LL;
602 	for (i = 0; rl[i].length; i++) {
603 		length = rl[i].length * g_vol->cluster_size;
604 		/* Don't write sparse runs. */
605 		if (rl[i].lcn == -1) {
606 			total += length;
607 			if (!val)
608 				continue;
609 			/* TODO: Check that *val is really zero at pos and len. */
610 			continue;
611 		}
612 		/*
613 		 * Break up the write into the real data write and then a write
614 		 * of zeroes between the end of the real data and the end of
615 		 * the (last) run.
616 		 */
617 		if (total + length > val_len) {
618 			delta = length;
619 			length = val_len - total;
620 			delta -= length;
621 		}
622 		if (dev->d_ops->seek(dev, rl[i].lcn * g_vol->cluster_size,
623 				SEEK_SET) == (off_t)-1)
624 			return -1LL;
625 		retry = 0;
626 		do {
627 			bytes_written = dev->d_ops->write(dev, val + total,
628 					length);
629 			if (bytes_written == -1LL) {
630 				retry = errno;
631 				ntfs_log_perror("Error writing to %s",
632 					dev->d_name);
633 				errno = retry;
634 				return bytes_written;
635 			}
636 			if (bytes_written) {
637 				length -= bytes_written;
638 				total += bytes_written;
639 				if (inited_size)
640 					*inited_size += bytes_written;
641 			} else {
642 				retry++;
643 			}
644 		} while (length && retry < 3);
645 		if (length) {
646 			ntfs_log_error("Failed to complete writing to %s after three "
647 					"retries.\n", dev->d_name);
648 			return total;
649 		}
650 	}
651 	if (delta) {
652 		int eo;
653 		char *b = ntfs_calloc(delta);
654 		if (!b)
655 			return -1;
656 		bytes_written = mkntfs_write(dev, b, delta);
657 		eo = errno;
658 		free(b);
659 		errno = eo;
660 		if (bytes_written == -1LL)
661 			return bytes_written;
662 	}
663 	return total;
664 }
665 
666 /**
667  * make_room_for_attribute - make room for an attribute inside an mft record
668  * @m:		mft record
669  * @pos:	position at which to make space
670  * @size:	byte size to make available at this position
671  *
672  * @pos points to the attribute in front of which we want to make space.
673  *
674  * Return 0 on success or -errno on error. Possible error codes are:
675  *
676  *	-ENOSPC		There is not enough space available to complete
677  *			operation. The caller has to make space before calling
678  *			this.
679  *	-EINVAL		Can only occur if mkntfs was compiled with -DDEBUG. Means
680  *			the input parameters were faulty.
681  */
make_room_for_attribute(MFT_RECORD * m,char * pos,const u32 size)682 static int make_room_for_attribute(MFT_RECORD *m, char *pos, const u32 size)
683 {
684 	u32 biu;
685 
686 	if (!size)
687 		return 0;
688 #ifdef DEBUG
689 	/*
690 	 * Rigorous consistency checks. Always return -EINVAL even if more
691 	 * appropriate codes exist for simplicity of parsing the return value.
692 	 */
693 	if (size != ((size + 7) & ~7)) {
694 		ntfs_log_error("make_room_for_attribute() received non 8-byte aligned "
695 				"size.\n");
696 		return -EINVAL;
697 	}
698 	if (!m || !pos)
699 		return -EINVAL;
700 	if (pos < (char*)m || pos + size < (char*)m ||
701 			pos > (char*)m + le32_to_cpu(m->bytes_allocated) ||
702 			pos + size > (char*)m + le32_to_cpu(m->bytes_allocated))
703 		return -EINVAL;
704 	/* The -8 is for the attribute terminator. */
705 	if (pos - (char*)m > (int)le32_to_cpu(m->bytes_in_use) - 8)
706 		return -EINVAL;
707 #endif
708 	biu = le32_to_cpu(m->bytes_in_use);
709 	/* Do we have enough space? */
710 	if (biu + size > le32_to_cpu(m->bytes_allocated))
711 		return -ENOSPC;
712 	/* Move everything after pos to pos + size. */
713 	memmove(pos + size, pos, biu - (pos - (char*)m));
714 	/* Update mft record. */
715 	m->bytes_in_use = cpu_to_le32(biu + size);
716 	return 0;
717 }
718 
719 /**
720  * deallocate_scattered_clusters
721  */
deallocate_scattered_clusters(const runlist * rl)722 static void deallocate_scattered_clusters(const runlist *rl)
723 {
724 	LCN j;
725 	int i;
726 
727 	if (!rl)
728 		return;
729 	/* Iterate over all runs in the runlist @rl. */
730 	for (i = 0; rl[i].length; i++) {
731 		/* Skip sparse runs. */
732 		if (rl[i].lcn == -1LL)
733 			continue;
734 		/* Deallocate the current run. */
735 		for (j = rl[i].lcn; j < rl[i].lcn + rl[i].length; j++)
736 			ntfs_bit_set(g_lcn_bitmap, j, 0);
737 	}
738 }
739 
740 /**
741  * allocate_scattered_clusters
742  * @clusters: Amount of clusters to allocate.
743  *
744  * Allocate @clusters and create a runlist of the allocated clusters.
745  *
746  * Return the allocated runlist. Caller has to free the runlist when finished
747  * with it.
748  *
749  * On error return NULL and errno is set to the error code.
750  *
751  * TODO: We should be returning the size as well, but for mkntfs this is not
752  * necessary.
753  */
allocate_scattered_clusters(s64 clusters)754 static runlist * allocate_scattered_clusters(s64 clusters)
755 {
756 	runlist *rl = NULL, *rlt;
757 	VCN vcn = 0LL;
758 	LCN lcn, end, prev_lcn = 0LL;
759 	int rlpos = 0;
760 	int rlsize = 0;
761 	s64 prev_run_len = 0LL;
762 	char bit;
763 
764 	end = g_vol->nr_clusters;
765 	/* Loop until all clusters are allocated. */
766 	while (clusters) {
767 		/* Loop in current zone until we run out of free clusters. */
768 		for (lcn = g_mft_zone_end; lcn < end; lcn++) {
769 			bit = ntfs_bit_get_and_set(g_lcn_bitmap, lcn, 1);
770 			if (bit)
771 				continue;
772 			/*
773 			 * Reallocate memory if necessary. Make sure we have
774 			 * enough for the terminator entry as well.
775 			 */
776 			if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
777 				rlsize += 4096; /* PAGE_SIZE */
778 				rlt = realloc(rl, rlsize);
779 				if (!rlt)
780 					goto err_end;
781 				rl = rlt;
782 			}
783 			/* Coalesce with previous run if adjacent LCNs. */
784 			if (prev_lcn == lcn - prev_run_len) {
785 				rl[rlpos - 1].length = ++prev_run_len;
786 				vcn++;
787 			} else {
788 				rl[rlpos].vcn = vcn++;
789 				rl[rlpos].lcn = lcn;
790 				prev_lcn = lcn;
791 				rl[rlpos].length = 1LL;
792 				prev_run_len = 1LL;
793 				rlpos++;
794 			}
795 			/* Done? */
796 			if (!--clusters) {
797 				/* Add terminator element and return. */
798 				rl[rlpos].vcn = vcn;
799 				rl[rlpos].lcn = 0LL;
800 				rl[rlpos].length = 0LL;
801 				return rl;
802 			}
803 
804 		}
805 		/* Switch to next zone, decreasing mft zone by factor 2. */
806 		end = g_mft_zone_end;
807 		g_mft_zone_end >>= 1;
808 		/* Have we run out of space on the volume? */
809 		if (g_mft_zone_end <= 0)
810 			goto err_end;
811 	}
812 	return rl;
813 err_end:
814 	if (rl) {
815 		/* Add terminator element. */
816 		rl[rlpos].vcn = vcn;
817 		rl[rlpos].lcn = -1LL;
818 		rl[rlpos].length = 0LL;
819 		/* Deallocate all allocated clusters. */
820 		deallocate_scattered_clusters(rl);
821 		/* Free the runlist. */
822 		free(rl);
823 	}
824 	return NULL;
825 }
826 
827 /**
828  * ntfs_attr_find - find (next) attribute in mft record
829  * @type:	attribute type to find
830  * @name:	attribute name to find (optional, i.e. NULL means don't care)
831  * @name_len:	attribute name length (only needed if @name present)
832  * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
833  * @val:	attribute value to find (optional, resident attributes only)
834  * @val_len:	attribute value length
835  * @ctx:	search context with mft record and attribute to search from
836  *
837  * You shouldn't need to call this function directly. Use lookup_attr() instead.
838  *
839  * ntfs_attr_find() takes a search context @ctx as parameter and searches the
840  * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
841  * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
842  * returns 0 and @ctx->attr will point to the found attribute.
843  *
844  * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
845  * @ctx->attr will point to the attribute before which the attribute being
846  * searched for would need to be inserted if such an action were to be desired.
847  *
848  * On actual error, ntfs_attr_find() returns -1 with errno set to the error
849  * code but not to ENOENT.  In this case @ctx->attr is undefined and in
850  * particular do not rely on it not changing.
851  *
852  * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
853  * is FALSE, the search begins after @ctx->attr.
854  *
855  * If @type is AT_UNUSED, return the first found attribute, i.e. one can
856  * enumerate all attributes by setting @type to AT_UNUSED and then calling
857  * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
858  * indicate that there are no more entries. During the enumeration, each
859  * successful call of ntfs_attr_find() will return the next attribute in the
860  * mft record @ctx->mrec.
861  *
862  * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
863  * AT_END is not a valid attribute, its length is zero for example, thus it is
864  * safer to return error instead of success in this case. This also allows us
865  * to interoperate cleanly with ntfs_external_attr_find().
866  *
867  * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
868  * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
869  * match both named and unnamed attributes.
870  *
871  * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
872  * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
873  * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
874  * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
875  * sensitive. When @name is present, @name_len is the @name length in Unicode
876  * characters.
877  *
878  * If @name is not present (NULL), we assume that the unnamed attribute is
879  * being searched for.
880  *
881  * Finally, the resident attribute value @val is looked for, if present.
882  * If @val is not present (NULL), @val_len is ignored.
883  *
884  * ntfs_attr_find() only searches the specified mft record and it ignores the
885  * presence of an attribute list attribute (unless it is the one being searched
886  * for, obviously). If you need to take attribute lists into consideration, use
887  * ntfs_attr_lookup() instead (see below). This also means that you cannot use
888  * ntfs_attr_find() to search for extent records of non-resident attributes, as
889  * extents with lowest_vcn != 0 are usually described by the attribute list
890  * attribute only. - Note that it is possible that the first extent is only in
891  * the attribute list while the last extent is in the base mft record, so don't
892  * rely on being able to find the first extent in the base mft record.
893  *
894  * Warning: Never use @val when looking for attribute types which can be
895  *	    non-resident as this most likely will result in a crash!
896  */
mkntfs_attr_find(const ATTR_TYPES type,const ntfschar * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const u8 * val,const u32 val_len,ntfs_attr_search_ctx * ctx)897 static int mkntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
898 		const u32 name_len, const IGNORE_CASE_BOOL ic,
899 		const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
900 {
901 	ATTR_RECORD *a;
902 	ntfschar *upcase = g_vol->upcase;
903 	u32 upcase_len = g_vol->upcase_len;
904 
905 	/*
906 	 * Iterate over attributes in mft record starting at @ctx->attr, or the
907 	 * attribute following that, if @ctx->is_first is TRUE.
908 	 */
909 	if (ctx->is_first) {
910 		a = ctx->attr;
911 		ctx->is_first = FALSE;
912 	} else {
913 		a = (ATTR_RECORD*)((char*)ctx->attr +
914 				le32_to_cpu(ctx->attr->length));
915 	}
916 	for (;;	a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
917 		if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
918 				le32_to_cpu(ctx->mrec->bytes_allocated))
919 			break;
920 		ctx->attr = a;
921 		if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
922 				le32_to_cpu(type))) ||
923 				(a->type == AT_END)) {
924 			errno = ENOENT;
925 			return -1;
926 		}
927 		if (!a->length)
928 			break;
929 		/* If this is an enumeration return this attribute. */
930 		if (type == AT_UNUSED)
931 			return 0;
932 		if (a->type != type)
933 			continue;
934 		/*
935 		 * If @name is AT_UNNAMED we want an unnamed attribute.
936 		 * If @name is present, compare the two names.
937 		 * Otherwise, match any attribute.
938 		 */
939 		if (name == AT_UNNAMED) {
940 			/* The search failed if the found attribute is named. */
941 			if (a->name_length) {
942 				errno = ENOENT;
943 				return -1;
944 			}
945 		} else if (name && !ntfs_names_are_equal(name, name_len,
946 				(ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
947 				a->name_length, ic, upcase, upcase_len)) {
948 			int rc;
949 
950 			rc = ntfs_names_collate(name, name_len,
951 					(ntfschar*)((char*)a +
952 					le16_to_cpu(a->name_offset)),
953 					a->name_length, 1, IGNORE_CASE,
954 					upcase, upcase_len);
955 			/*
956 			 * If @name collates before a->name, there is no
957 			 * matching attribute.
958 			 */
959 			if (rc == -1) {
960 				errno = ENOENT;
961 				return -1;
962 			}
963 			/* If the strings are not equal, continue search. */
964 			if (rc)
965 				continue;
966 			rc = ntfs_names_collate(name, name_len,
967 					(ntfschar*)((char*)a +
968 					le16_to_cpu(a->name_offset)),
969 					a->name_length, 1, CASE_SENSITIVE,
970 					upcase, upcase_len);
971 			if (rc == -1) {
972 				errno = ENOENT;
973 				return -1;
974 			}
975 			if (rc)
976 				continue;
977 		}
978 		/*
979 		 * The names match or @name not present and attribute is
980 		 * unnamed. If no @val specified, we have found the attribute
981 		 * and are done.
982 		 */
983 		if (!val) {
984 			return 0;
985 		/* @val is present; compare values. */
986 		} else {
987 			int rc;
988 
989 			rc = memcmp(val, (char*)a +le16_to_cpu(a->u.res.value_offset),
990 					min(val_len,
991 					le32_to_cpu(a->u.res.value_length)));
992 			/*
993 			 * If @val collates before the current attribute's
994 			 * value, there is no matching attribute.
995 			 */
996 			if (!rc) {
997 				u32 avl;
998 				avl = le32_to_cpu(a->u.res.value_length);
999 				if (val_len == avl)
1000 					return 0;
1001 				if (val_len < avl) {
1002 					errno = ENOENT;
1003 					return -1;
1004 				}
1005 			} else if (rc < 0) {
1006 				errno = ENOENT;
1007 				return -1;
1008 			}
1009 		}
1010 	}
1011 	ntfs_log_trace("File is corrupt. Run chkdsk.\n");
1012 	errno = EIO;
1013 	return -1;
1014 }
1015 
1016 /**
1017  * ntfs_attr_lookup - find an attribute in an ntfs inode
1018  * @type:	attribute type to find
1019  * @name:	attribute name to find (optional, i.e. NULL means don't care)
1020  * @name_len:	attribute name length (only needed if @name present)
1021  * @ic:		IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
1022  * @lowest_vcn:	lowest vcn to find (optional, non-resident attributes only)
1023  * @val:	attribute value to find (optional, resident attributes only)
1024  * @val_len:	attribute value length
1025  * @ctx:	search context with mft record and attribute to search from
1026  *
1027  * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
1028  * be the base mft record and @ctx must have been obtained from a call to
1029  * ntfs_attr_get_search_ctx().
1030  *
1031  * This function transparently handles attribute lists and @ctx is used to
1032  * continue searches where they were left off at.
1033  *
1034  * If @type is AT_UNUSED, return the first found attribute, i.e. one can
1035  * enumerate all attributes by setting @type to AT_UNUSED and then calling
1036  * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
1037  * to indicate that there are no more entries. During the enumeration, each
1038  * successful call of ntfs_attr_lookup() will return the next attribute, with
1039  * the current attribute being described by the search context @ctx.
1040  *
1041  * If @type is AT_END, seek to the end of the base mft record ignoring the
1042  * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
1043  * not a valid attribute, its length is zero for example, thus it is safer to
1044  * return error instead of success in this case.  It should never be needed to
1045  * do this, but we implement the functionality because it allows for simpler
1046  * code inside ntfs_external_attr_find().
1047  *
1048  * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
1049  * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
1050  * match both named and unnamed attributes.
1051  *
1052  * After finishing with the attribute/mft record you need to call
1053  * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
1054  * mapped extent inodes, etc).
1055  *
1056  * Return 0 if the search was successful and -1 if not, with errno set to the
1057  * error code.
1058  *
1059  * On success, @ctx->attr is the found attribute, it is in mft record
1060  * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
1061  * attribute with @ctx->base_* being the base mft record to which @ctx->attr
1062  * belongs.  If no attribute list attribute is present @ctx->al_entry and
1063  * @ctx->base_* are NULL.
1064  *
1065  * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
1066  * attribute which collates just after the attribute being searched for in the
1067  * base ntfs inode, i.e. if one wants to add the attribute to the mft record
1068  * this is the correct place to insert it into, and if there is not enough
1069  * space, the attribute should be placed in an extent mft record.
1070  * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
1071  * at which the new attribute's attribute list entry should be inserted.  The
1072  * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
1073  * The only exception to this is when @type is AT_END, in which case
1074  * @ctx->al_entry is set to NULL also (see above).
1075  *
1076  * The following error codes are defined:
1077  *	ENOENT	Attribute not found, not an error as such.
1078  *	EINVAL	Invalid arguments.
1079  *	EIO	I/O error or corrupt data structures found.
1080  *	ENOMEM	Not enough memory to allocate necessary buffers.
1081  */
mkntfs_attr_lookup(const ATTR_TYPES type,const ntfschar * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const VCN lowest_vcn,const u8 * val,const u32 val_len,ntfs_attr_search_ctx * ctx)1082 static int mkntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
1083 		const u32 name_len, const IGNORE_CASE_BOOL ic,
1084 		const VCN lowest_vcn __attribute__((unused)), const u8 *val,
1085 		const u32 val_len, ntfs_attr_search_ctx *ctx)
1086 {
1087 	ntfs_inode *base_ni;
1088 
1089 	if (!ctx || !ctx->mrec || !ctx->attr) {
1090 		errno = EINVAL;
1091 		return -1;
1092 	}
1093 	if (ctx->base_ntfs_ino)
1094 		base_ni = ctx->base_ntfs_ino;
1095 	else
1096 		base_ni = ctx->ntfs_ino;
1097 	if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
1098 		return mkntfs_attr_find(type, name, name_len, ic, val, val_len,
1099 				ctx);
1100 	errno = EOPNOTSUPP;
1101 	return -1;
1102 }
1103 
1104 /**
1105  * insert_positioned_attr_in_mft_record
1106  *
1107  * Create a non-resident attribute with a predefined on disk location
1108  * specified by the runlist @rl. The clusters specified by @rl are assumed to
1109  * be allocated already.
1110  *
1111  * Return 0 on success and -errno on error.
1112  */
insert_positioned_attr_in_mft_record(MFT_RECORD * m,const ATTR_TYPES type,const char * name,u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_FLAGS flags,const runlist * rl,const u8 * val,const s64 val_len)1113 static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
1114 		const ATTR_TYPES type, const char *name, u32 name_len,
1115 		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1116 		const runlist *rl, const u8 *val, const s64 val_len)
1117 {
1118 	ntfs_attr_search_ctx *ctx;
1119 	ATTR_RECORD *a;
1120 	u16 hdr_size;
1121 	int asize, mpa_size, err, i;
1122 	s64 bw = 0, inited_size;
1123 	VCN highest_vcn;
1124 	ntfschar *uname = NULL;
1125 	int uname_len = 0;
1126 	/*
1127 	if (base record)
1128 		attr_lookup();
1129 	else
1130 	*/
1131 
1132 	uname = ntfs_str2ucs(name, &uname_len);
1133 	if (!uname)
1134 		return -errno;
1135 
1136 	/* Check if the attribute is already there. */
1137 	ctx = ntfs_attr_get_search_ctx(NULL, m);
1138 	if (!ctx) {
1139 		ntfs_log_error("Failed to allocate attribute search context.\n");
1140 		err = -ENOMEM;
1141 		goto err_out;
1142 	}
1143 	if (ic == IGNORE_CASE) {
1144 		ntfs_log_error("FIXME: Hit unimplemented code path #1.\n");
1145 		err = -EOPNOTSUPP;
1146 		goto err_out;
1147 	}
1148 	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
1149 		err = -EEXIST;
1150 		goto err_out;
1151 	}
1152 	if (errno != ENOENT) {
1153 		ntfs_log_error("Corrupt inode.\n");
1154 		err = -errno;
1155 		goto err_out;
1156 	}
1157 	a = ctx->attr;
1158 	if (flags & ATTR_COMPRESSION_MASK) {
1159 		ntfs_log_error("Compressed attributes not supported yet.\n");
1160 		/* FIXME: Compress attribute into a temporary buffer, set */
1161 		/* val accordingly and save the compressed size. */
1162 		err = -EOPNOTSUPP;
1163 		goto err_out;
1164 	}
1165 	if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
1166 		ntfs_log_error("Encrypted/sparse attributes not supported.\n");
1167 		err = -EOPNOTSUPP;
1168 		goto err_out;
1169 	}
1170 	if (flags & ATTR_COMPRESSION_MASK) {
1171 		hdr_size = 72;
1172 		/* FIXME: This compression stuff is all wrong. Never mind for */
1173 		/* now. (AIA) */
1174 		if (val_len)
1175 			mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
1176 		else
1177 			mpa_size = 0;
1178 	} else {
1179 		hdr_size = 64;
1180 		if (val_len) {
1181 			mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0);
1182 			if (mpa_size < 0) {
1183 				err = -errno;
1184 				ntfs_log_error("Failed to get size for mapping "
1185 						"pairs.\n");
1186 				goto err_out;
1187 			}
1188 		} else {
1189 			mpa_size = 0;
1190 		}
1191 	}
1192 	/* Mapping pairs array and next attribute must be 8-byte aligned. */
1193 	asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
1194 	/* Get the highest vcn. */
1195 	for (i = 0, highest_vcn = 0LL; rl[i].length; i++)
1196 		highest_vcn += rl[i].length;
1197 	/* Does the value fit inside the allocated size? */
1198 	if (highest_vcn * g_vol->cluster_size < val_len) {
1199 		ntfs_log_error("BUG: Allocated size is smaller than data size!\n");
1200 		err = -EINVAL;
1201 		goto err_out;
1202 	}
1203 	err = make_room_for_attribute(m, (char*)a, asize);
1204 	if (err == -ENOSPC) {
1205 		/*
1206 		 * FIXME: Make space! (AIA)
1207 		 * can we make it non-resident? if yes, do that.
1208 		 *	does it fit now? yes -> do it.
1209 		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
1210 		 * yes -> make non-resident
1211 		 *	does it fit now? yes -> do it.
1212 		 * make all attributes non-resident
1213 		 *	does it fit now? yes -> do it.
1214 		 * m is a base record? yes -> allocate extension record
1215 		 *	does the new attribute fit in there? yes -> do it.
1216 		 * split up runlist into extents and place each in an extension
1217 		 * record.
1218 		 * FIXME: the check for needing extension records should be
1219 		 * earlier on as it is very quick: asize > m->bytes_allocated?
1220 		 */
1221 		err = -EOPNOTSUPP;
1222 		goto err_out;
1223 #ifdef DEBUG
1224 	} else if (err == -EINVAL) {
1225 		ntfs_log_error("BUG(): in insert_positioned_attribute_in_mft_"
1226 				"record(): make_room_for_attribute() returned "
1227 				"error: EINVAL!\n");
1228 		goto err_out;
1229 #endif
1230 	}
1231 	a->type = type;
1232 	a->length = cpu_to_le32(asize);
1233 	a->non_resident = 1;
1234 	a->name_length = name_len;
1235 	a->name_offset = cpu_to_le16(hdr_size);
1236 	a->flags = flags;
1237 	a->instance = m->next_attr_instance;
1238 	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
1239 			+ 1) & 0xffff);
1240 	a->u.nonres.lowest_vcn = 0;
1241 	a->u.nonres.highest_vcn = cpu_to_sle64(highest_vcn - 1LL);
1242 	a->u.nonres.mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
1243 	memset(a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1));
1244 	/* FIXME: Allocated size depends on compression. */
1245 	a->u.nonres.allocated_size = cpu_to_sle64(highest_vcn * g_vol->cluster_size);
1246 	a->u.nonres.data_size = cpu_to_sle64(val_len);
1247 	if (name_len)
1248 		memcpy((char*)a + hdr_size, uname, name_len << 1);
1249 	if (flags & ATTR_COMPRESSION_MASK) {
1250 		if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
1251 			ntfs_log_error("Unknown compression format. Reverting "
1252 					"to standard compression.\n");
1253 			a->flags &= ~ATTR_COMPRESSION_MASK;
1254 			a->flags |= ATTR_IS_COMPRESSED;
1255 		}
1256 		a->u.nonres.compression_unit = 4;
1257 		inited_size = val_len;
1258 		/* FIXME: Set the compressed size. */
1259 		a->u.nonres.compressed_size = 0;
1260 		/* FIXME: Write out the compressed data. */
1261 		/* FIXME: err = build_mapping_pairs_compressed(); */
1262 		err = -EOPNOTSUPP;
1263 	} else {
1264 		a->u.nonres.compression_unit = 0;
1265 		bw = ntfs_rlwrite(g_vol->u.dev, rl, val, val_len, &inited_size);
1266 		if (bw != val_len) {
1267 			ntfs_log_error("Error writing non-resident attribute "
1268 					"value.\n");
1269 			return -errno;
1270 		}
1271 		err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
1272 				((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
1273 	}
1274 	a->u.nonres.initialized_size = cpu_to_sle64(inited_size);
1275 	if (err < 0 || bw != val_len) {
1276 		/* FIXME: Handle error. */
1277 		/* deallocate clusters */
1278 		/* remove attribute */
1279 		if (err >= 0)
1280 			err = -EIO;
1281 		ntfs_log_error("insert_positioned_attr_in_mft_record failed "
1282 				"with error %i.\n", err < 0 ? err : (int)bw);
1283 	}
1284 err_out:
1285 	if (ctx)
1286 		ntfs_attr_put_search_ctx(ctx);
1287 	ntfs_ucsfree(uname);
1288 	return err;
1289 }
1290 
1291 /**
1292  * insert_non_resident_attr_in_mft_record
1293  *
1294  * Return 0 on success and -errno on error.
1295  */
insert_non_resident_attr_in_mft_record(MFT_RECORD * m,const ATTR_TYPES type,const char * name,u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_FLAGS flags,const u8 * val,const s64 val_len)1296 static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
1297 		const ATTR_TYPES type, const char *name, u32 name_len,
1298 		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1299 		const u8 *val, const s64 val_len)
1300 {
1301 	ntfs_attr_search_ctx *ctx;
1302 	ATTR_RECORD *a;
1303 	u16 hdr_size;
1304 	int asize, mpa_size, err, i;
1305 	runlist *rl = NULL;
1306 	s64 bw = 0;
1307 	ntfschar *uname = NULL;
1308 	int uname_len = 0;
1309 	/*
1310 	if (base record)
1311 		attr_lookup();
1312 	else
1313 	*/
1314 
1315 	uname = ntfs_str2ucs(name, &uname_len);
1316 	if (!uname)
1317 		return -errno;
1318 
1319 	/* Check if the attribute is already there. */
1320 	ctx = ntfs_attr_get_search_ctx(NULL, m);
1321 	if (!ctx) {
1322 		ntfs_log_error("Failed to allocate attribute search context.\n");
1323 		err = -ENOMEM;
1324 		goto err_out;
1325 	}
1326 	if (ic == IGNORE_CASE) {
1327 		ntfs_log_error("FIXME: Hit unimplemented code path #2.\n");
1328 		err = -EOPNOTSUPP;
1329 		goto err_out;
1330 	}
1331 	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
1332 		err = -EEXIST;
1333 		goto err_out;
1334 	}
1335 	if (errno != ENOENT) {
1336 		ntfs_log_error("Corrupt inode.\n");
1337 		err = -errno;
1338 		goto err_out;
1339 	}
1340 	a = ctx->attr;
1341 	if (flags & ATTR_COMPRESSION_MASK) {
1342 		ntfs_log_error("Compressed attributes not supported yet.\n");
1343 		/* FIXME: Compress attribute into a temporary buffer, set */
1344 		/* val accordingly and save the compressed size. */
1345 		err = -EOPNOTSUPP;
1346 		goto err_out;
1347 	}
1348 	if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
1349 		ntfs_log_error("Encrypted/sparse attributes not supported.\n");
1350 		err = -EOPNOTSUPP;
1351 		goto err_out;
1352 	}
1353 	if (val_len) {
1354 		rl = allocate_scattered_clusters((val_len +
1355 				g_vol->cluster_size - 1) / g_vol->cluster_size);
1356 		if (!rl) {
1357 			err = -errno;
1358 			ntfs_log_perror("Failed to allocate scattered clusters");
1359 			goto err_out;
1360 		}
1361 	} else {
1362 		rl = NULL;
1363 	}
1364 	if (flags & ATTR_COMPRESSION_MASK) {
1365 		hdr_size = 72;
1366 		/* FIXME: This compression stuff is all wrong. Never mind for */
1367 		/* now. (AIA) */
1368 		if (val_len)
1369 			mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
1370 		else
1371 			mpa_size = 0;
1372 	} else {
1373 		hdr_size = 64;
1374 		if (val_len) {
1375 			mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0);
1376 			if (mpa_size < 0) {
1377 				err = -errno;
1378 				ntfs_log_error("Failed to get size for mapping "
1379 						"pairs.\n");
1380 				goto err_out;
1381 			}
1382 		} else {
1383 			mpa_size = 0;
1384 		}
1385 	}
1386 	/* Mapping pairs array and next attribute must be 8-byte aligned. */
1387 	asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
1388 	err = make_room_for_attribute(m, (char*)a, asize);
1389 	if (err == -ENOSPC) {
1390 		/*
1391 		 * FIXME: Make space! (AIA)
1392 		 * can we make it non-resident? if yes, do that.
1393 		 *	does it fit now? yes -> do it.
1394 		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
1395 		 * yes -> make non-resident
1396 		 *	does it fit now? yes -> do it.
1397 		 * make all attributes non-resident
1398 		 *	does it fit now? yes -> do it.
1399 		 * m is a base record? yes -> allocate extension record
1400 		 *	does the new attribute fit in there? yes -> do it.
1401 		 * split up runlist into extents and place each in an extension
1402 		 * record.
1403 		 * FIXME: the check for needing extension records should be
1404 		 * earlier on as it is very quick: asize > m->bytes_allocated?
1405 		 */
1406 		err = -EOPNOTSUPP;
1407 		goto err_out;
1408 #ifdef DEBUG
1409 	} else if (err == -EINVAL) {
1410 		ntfs_log_error("BUG(): in insert_non_resident_attribute_in_"
1411 				"mft_record(): make_room_for_attribute() "
1412 				"returned error: EINVAL!\n");
1413 		goto err_out;
1414 #endif
1415 	}
1416 	a->type = type;
1417 	a->length = cpu_to_le32(asize);
1418 	a->non_resident = 1;
1419 	a->name_length = name_len;
1420 	a->name_offset = cpu_to_le16(hdr_size);
1421 	a->flags = flags;
1422 	a->instance = m->next_attr_instance;
1423 	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
1424 			+ 1) & 0xffff);
1425 	a->u.nonres.lowest_vcn = 0;
1426 	for (i = 0; rl[i].length; i++)
1427 		;
1428 	a->u.nonres.highest_vcn = cpu_to_sle64(rl[i].vcn - 1);
1429 	a->u.nonres.mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
1430 	memset(a->u.nonres.reserved1, 0, sizeof(a->u.nonres.reserved1));
1431 	/* FIXME: Allocated size depends on compression. */
1432 	a->u.nonres.allocated_size = cpu_to_sle64((val_len + (g_vol->cluster_size - 1)) &
1433 			~(g_vol->cluster_size - 1));
1434 	a->u.nonres.data_size = cpu_to_sle64(val_len);
1435 	a->u.nonres.initialized_size = cpu_to_sle64(val_len);
1436 	if (name_len)
1437 		memcpy((char*)a + hdr_size, uname, name_len << 1);
1438 	if (flags & ATTR_COMPRESSION_MASK) {
1439 		if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
1440 			ntfs_log_error("Unknown compression format. Reverting "
1441 					"to standard compression.\n");
1442 			a->flags &= ~ATTR_COMPRESSION_MASK;
1443 			a->flags |= ATTR_IS_COMPRESSED;
1444 		}
1445 		a->u.nonres.compression_unit = 4;
1446 		/* FIXME: Set the compressed size. */
1447 		a->u.nonres.compressed_size = 0;
1448 		/* FIXME: Write out the compressed data. */
1449 		/* FIXME: err = build_mapping_pairs_compressed(); */
1450 		err = -EOPNOTSUPP;
1451 	} else {
1452 		a->u.nonres.compression_unit = 0;
1453 		bw = ntfs_rlwrite(g_vol->u.dev, rl, val, val_len, NULL);
1454 		if (bw != val_len) {
1455 			ntfs_log_error("Error writing non-resident attribute "
1456 					"value.\n");
1457 			return -errno;
1458 		}
1459 		err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
1460 				((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
1461 	}
1462 	if (err < 0 || bw != val_len) {
1463 		/* FIXME: Handle error. */
1464 		/* deallocate clusters */
1465 		/* remove attribute */
1466 		if (err >= 0)
1467 			err = -EIO;
1468 		ntfs_log_error("insert_non_resident_attr_in_mft_record failed with "
1469 			"error %lld.\n", (long long) (err < 0 ? err : bw));
1470 	}
1471 err_out:
1472 	if (ctx)
1473 		ntfs_attr_put_search_ctx(ctx);
1474 	ntfs_ucsfree(uname);
1475 	free(rl);
1476 	return err;
1477 }
1478 
1479 /**
1480  * insert_resident_attr_in_mft_record
1481  *
1482  * Return 0 on success and -errno on error.
1483  */
insert_resident_attr_in_mft_record(MFT_RECORD * m,const ATTR_TYPES type,const char * name,u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_FLAGS flags,const RESIDENT_ATTR_FLAGS res_flags,const u8 * val,const u32 val_len)1484 static int insert_resident_attr_in_mft_record(MFT_RECORD *m,
1485 		const ATTR_TYPES type, const char *name, u32 name_len,
1486 		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1487 		const RESIDENT_ATTR_FLAGS res_flags,
1488 		const u8 *val, const u32 val_len)
1489 {
1490 	ntfs_attr_search_ctx *ctx;
1491 	ATTR_RECORD *a;
1492 	int asize, err;
1493 	ntfschar *uname = NULL;
1494 	int uname_len = 0;
1495 	/*
1496 	if (base record)
1497 		mkntfs_attr_lookup();
1498 	else
1499 	*/
1500 
1501 	uname = ntfs_str2ucs(name, &uname_len);
1502 	if (!uname)
1503 		return -errno;
1504 
1505 	/* Check if the attribute is already there. */
1506 	ctx = ntfs_attr_get_search_ctx(NULL, m);
1507 	if (!ctx) {
1508 		ntfs_log_error("Failed to allocate attribute search context.\n");
1509 		err = -ENOMEM;
1510 		goto err_out;
1511 	}
1512 	if (ic == IGNORE_CASE) {
1513 		ntfs_log_error("FIXME: Hit unimplemented code path #3.\n");
1514 		err = -EOPNOTSUPP;
1515 		goto err_out;
1516 	}
1517 	if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, val, val_len,
1518 			ctx)) {
1519 		err = -EEXIST;
1520 		goto err_out;
1521 	}
1522 	if (errno != ENOENT) {
1523 		ntfs_log_error("Corrupt inode.\n");
1524 		err = -errno;
1525 		goto err_out;
1526 	}
1527 	a = ctx->attr;
1528 	/* sizeof(resident attribute record header) == 24 */
1529 	asize = ((24 + ((name_len + 7) & ~7) + val_len) + 7) & ~7;
1530 	err = make_room_for_attribute(m, (char*)a, asize);
1531 	if (err == -ENOSPC) {
1532 		/*
1533 		 * FIXME: Make space! (AIA)
1534 		 * can we make it non-resident? if yes, do that.
1535 		 *	does it fit now? yes -> do it.
1536 		 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
1537 		 * yes -> make non-resident
1538 		 *	does it fit now? yes -> do it.
1539 		 * make all attributes non-resident
1540 		 *	does it fit now? yes -> do it.
1541 		 * m is a base record? yes -> allocate extension record
1542 		 *	does the new attribute fit in there? yes -> do it.
1543 		 * split up runlist into extents and place each in an extension
1544 		 * record.
1545 		 * FIXME: the check for needing extension records should be
1546 		 * earlier on as it is very quick: asize > m->bytes_allocated?
1547 		 */
1548 		err = -EOPNOTSUPP;
1549 		goto err_out;
1550 	}
1551 #ifdef DEBUG
1552 	if (err == -EINVAL) {
1553 		ntfs_log_error("BUG(): in insert_resident_attribute_in_mft_"
1554 				"record(): make_room_for_attribute() returned "
1555 				"error: EINVAL!\n");
1556 		goto err_out;
1557 	}
1558 #endif
1559 	a->type = type;
1560 	a->length = cpu_to_le32(asize);
1561 	a->non_resident = 0;
1562 	a->name_length = name_len;
1563 	if (type == AT_OBJECT_ID)
1564 		a->name_offset = const_cpu_to_le16(0);
1565 	else
1566 		a->name_offset = const_cpu_to_le16(24);
1567 	a->flags = flags;
1568 	a->instance = m->next_attr_instance;
1569 	m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
1570 			+ 1) & 0xffff);
1571 	a->u.res.value_length = cpu_to_le32(val_len);
1572 	a->u.res.value_offset = cpu_to_le16(24 + ((name_len + 7) & ~7));
1573 	a->u.res.resident_flags = res_flags;
1574 	a->u.res.reservedR = 0;
1575 	if (name_len)
1576 		memcpy((char*)a + 24, uname, name_len << 1);
1577 	if (val_len)
1578 		memcpy((char*)a + le16_to_cpu(a->u.res.value_offset), val, val_len);
1579 err_out:
1580 	if (ctx)
1581 		ntfs_attr_put_search_ctx(ctx);
1582 	ntfs_ucsfree(uname);
1583 	return err;
1584 }
1585 
1586 
1587 /**
1588  * add_attr_std_info
1589  *
1590  * Return 0 on success or -errno on error.
1591  */
add_attr_std_info(MFT_RECORD * m,const FILE_ATTR_FLAGS flags,le32 security_id)1592 static int add_attr_std_info(MFT_RECORD *m, const FILE_ATTR_FLAGS flags,
1593 		le32 security_id)
1594 {
1595 	STANDARD_INFORMATION si;
1596 	int err, sd_size;
1597 
1598 	sd_size = 48;
1599 
1600 	si.creation_time = utc2ntfs(mkntfs_time());
1601 	si.last_data_change_time = si.creation_time;
1602 	si.last_mft_change_time = si.creation_time;
1603 	si.last_access_time = si.creation_time;
1604 	si.file_attributes = flags; /* already LE */
1605 	si.u.v30.maximum_versions = cpu_to_le32(0);
1606 	si.u.v30.version_number = cpu_to_le32(0);
1607 	si.u.v30.class_id = cpu_to_le32(0);
1608 	si.u.v30.security_id = security_id;
1609 	if (si.u.v30.security_id != 0)
1610 		sd_size = 72;
1611 	/* FIXME: $Quota support... */
1612 	si.u.v30.owner_id = cpu_to_le32(0);
1613 	si.u.v30.quota_charged = cpu_to_le64(0ULL);
1614 	/* FIXME: $UsnJrnl support... Not needed on fresh w2k3-volume */
1615 	si.u.v30.usn = cpu_to_le64(0ULL);
1616 	/* NTFS 1.2: size of si = 48, NTFS 3.[01]: size of si = 72 */
1617 	err = insert_resident_attr_in_mft_record(m, AT_STANDARD_INFORMATION,
1618 			NULL, 0, 0, 0, 0, (u8*)&si, sd_size);
1619 	if (err < 0)
1620 		ntfs_log_perror("add_attr_std_info failed");
1621 	return err;
1622 }
1623 
1624 /**
1625  * add_attr_file_name
1626  *
1627  * Return 0 on success or -errno on error.
1628  */
add_attr_file_name(MFT_RECORD * m,const leMFT_REF parent_dir,const s64 allocated_size,const s64 data_size,const FILE_ATTR_FLAGS flags,const u16 packed_ea_size,const u32 reparse_point_tag,const char * file_name,const FILE_NAME_TYPE_FLAGS file_name_type)1629 static int add_attr_file_name(MFT_RECORD *m, const leMFT_REF parent_dir,
1630 		const s64 allocated_size, const s64 data_size,
1631 		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
1632 		const u32 reparse_point_tag, const char *file_name,
1633 		const FILE_NAME_TYPE_FLAGS file_name_type)
1634 {
1635 	ntfs_attr_search_ctx *ctx;
1636 	STANDARD_INFORMATION *si;
1637 	FILE_NAME_ATTR *fn;
1638 	int i, fn_size;
1639 	ntfschar *uname;
1640 
1641 	/* Check if the attribute is already there. */
1642 	ctx = ntfs_attr_get_search_ctx(NULL, m);
1643 	if (!ctx) {
1644 		ntfs_log_error("Failed to get attribute search context.\n");
1645 		return -ENOMEM;
1646 	}
1647 	if (mkntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, 0, 0,
1648 				NULL, 0, ctx)) {
1649 		int eo = errno;
1650 		ntfs_log_error("BUG: Standard information attribute not "
1651 				"present in file record.\n");
1652 		ntfs_attr_put_search_ctx(ctx);
1653 		return -eo;
1654 	}
1655 	si = (STANDARD_INFORMATION*)((char*)ctx->attr +
1656 			le16_to_cpu(ctx->attr->u.res.value_offset));
1657 	i = (strlen(file_name) + 1) * sizeof(ntfschar);
1658 	fn_size = sizeof(FILE_NAME_ATTR) + i;
1659 	fn = ntfs_malloc(fn_size);
1660 	if (!fn) {
1661 		ntfs_attr_put_search_ctx(ctx);
1662 		return -errno;
1663 	}
1664 	fn->parent_directory = parent_dir;
1665 
1666 	fn->creation_time = si->creation_time;
1667 	fn->last_data_change_time = si->last_data_change_time;
1668 	fn->last_mft_change_time = si->last_mft_change_time;
1669 	fn->last_access_time = si->last_access_time;
1670 	ntfs_attr_put_search_ctx(ctx);
1671 
1672 	fn->allocated_size = cpu_to_sle64(allocated_size);
1673 	fn->data_size = cpu_to_sle64(data_size);
1674 	fn->file_attributes = flags;
1675 	/* These are in a union so can't have both. */
1676 	if (packed_ea_size && reparse_point_tag) {
1677 		free(fn);
1678 		return -EINVAL;
1679 	}
1680 	if (packed_ea_size) {
1681 		fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size);
1682 		fn->u.s.reserved = cpu_to_le16(0);
1683 	} else {
1684 		fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag);
1685 	}
1686 	fn->file_name_type = file_name_type;
1687 	uname = fn->file_name;
1688 	i = ntfs_mbstoucs(file_name, &uname, i);
1689 	if (i < 1) {
1690 		free(fn);
1691 		return -EINVAL;
1692 	}
1693 	if (i > 0xff) {
1694 		free(fn);
1695 		return -ENAMETOOLONG;
1696 	}
1697 	/* No terminating null in file names. */
1698 	fn->file_name_length = i;
1699 	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
1700 	i = insert_resident_attr_in_mft_record(m, AT_FILE_NAME, NULL, 0, 0,
1701 			0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
1702 	free(fn);
1703 	if (i < 0)
1704 		ntfs_log_error("add_attr_file_name failed: %s\n", strerror(-i));
1705 	return i;
1706 }
1707 
1708 #ifdef ENABLE_UUID
1709 
1710 /**
1711  * add_attr_object_id -
1712  *
1713  * Note we insert only a basic object id which only has the GUID and none of
1714  * the extended fields.  This is because we currently only use this function
1715  * when creating the object id for the volume.
1716  *
1717  * Return 0 on success or -errno on error.
1718  */
add_attr_object_id(MFT_RECORD * m,const GUID * object_id)1719 static int add_attr_object_id(MFT_RECORD *m, const GUID *object_id)
1720 {
1721 	OBJECT_ID_ATTR oi;
1722 	int err;
1723 
1724 	oi = (OBJECT_ID_ATTR) {
1725 		.object_id = *object_id,
1726 	};
1727 	err = insert_resident_attr_in_mft_record(m, AT_OBJECT_ID, NULL,
1728 			0, 0, 0, 0, (u8*)&oi, sizeof(oi.object_id));
1729 	if (err < 0)
1730 		ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
1731 	return err;
1732 }
1733 
1734 #endif
1735 
1736 /**
1737  * add_attr_sd
1738  *
1739  * Create the security descriptor attribute adding the security descriptor @sd
1740  * of length @sd_len to the mft record @m.
1741  *
1742  * Return 0 on success or -errno on error.
1743  */
add_attr_sd(MFT_RECORD * m,const u8 * sd,const s64 sd_len)1744 static int add_attr_sd(MFT_RECORD *m, const u8 *sd, const s64 sd_len)
1745 {
1746 	int err;
1747 
1748 	/* Does it fit? NO: create non-resident. YES: create resident. */
1749 	if (le32_to_cpu(m->bytes_in_use) + 24 + sd_len >
1750 						le32_to_cpu(m->bytes_allocated))
1751 		err = insert_non_resident_attr_in_mft_record(m,
1752 				AT_SECURITY_DESCRIPTOR, NULL, 0, 0, 0, sd,
1753 				sd_len);
1754 	else
1755 		err = insert_resident_attr_in_mft_record(m,
1756 				AT_SECURITY_DESCRIPTOR, NULL, 0, 0, 0, 0, sd,
1757 				sd_len);
1758 	if (err < 0)
1759 		ntfs_log_error("add_attr_sd failed: %s\n", strerror(-err));
1760 	return err;
1761 }
1762 
1763 /**
1764  * add_attr_data
1765  *
1766  * Return 0 on success or -errno on error.
1767  */
add_attr_data(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_FLAGS flags,const u8 * val,const s64 val_len)1768 static int add_attr_data(MFT_RECORD *m, const char *name, const u32 name_len,
1769 		const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1770 		const u8 *val, const s64 val_len)
1771 {
1772 	int err;
1773 
1774 	/*
1775 	 * Does it fit? NO: create non-resident. YES: create resident.
1776 	 *
1777 	 * FIXME: Introduced arbitrary limit of mft record allocated size - 512.
1778 	 * This is to get around the problem that if $Bitmap/$DATA becomes too
1779 	 * big, but is just small enough to be resident, we would make it
1780 	 * resident, and later run out of space when creating the other
1781 	 * attributes and this would cause us to abort as making resident
1782 	 * attributes non-resident is not supported yet.
1783 	 * The proper fix is to support making resident attribute non-resident.
1784 	 */
1785 	if (le32_to_cpu(m->bytes_in_use) + 24 + val_len >
1786 			min(le32_to_cpu(m->bytes_allocated),
1787 			le32_to_cpu(m->bytes_allocated) - 512))
1788 		err = insert_non_resident_attr_in_mft_record(m, AT_DATA, name,
1789 				name_len, ic, flags, val, val_len);
1790 	else
1791 		err = insert_resident_attr_in_mft_record(m, AT_DATA, name,
1792 				name_len, ic, flags, 0, val, val_len);
1793 
1794 	if (err < 0)
1795 		ntfs_log_error("add_attr_data failed: %s\n", strerror(-err));
1796 	return err;
1797 }
1798 
1799 /**
1800  * add_attr_data_positioned
1801  *
1802  * Create a non-resident data attribute with a predefined on disk location
1803  * specified by the runlist @rl. The clusters specified by @rl are assumed to
1804  * be allocated already.
1805  *
1806  * Return 0 on success or -errno on error.
1807  */
add_attr_data_positioned(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_FLAGS flags,const runlist * rl,const u8 * val,const s64 val_len)1808 static int add_attr_data_positioned(MFT_RECORD *m, const char *name,
1809 		const u32 name_len, const IGNORE_CASE_BOOL ic,
1810 		const ATTR_FLAGS flags, const runlist *rl,
1811 		const u8 *val, const s64 val_len)
1812 {
1813 	int err;
1814 
1815 	err = insert_positioned_attr_in_mft_record(m, AT_DATA, name, name_len,
1816 			ic, flags, rl, val, val_len);
1817 	if (err < 0)
1818 		ntfs_log_error("add_attr_data_positioned failed: %s\n",
1819 				strerror(-err));
1820 	return err;
1821 }
1822 
1823 /**
1824  * add_attr_vol_name
1825  *
1826  * Create volume name attribute specifying the volume name @vol_name as a null
1827  * terminated char string of length @vol_name_len (number of characters not
1828  * including the terminating null), which is converted internally to a little
1829  * endian ntfschar string. The name is at least 1 character long and at most
1830  * 0xff characters long (not counting the terminating null).
1831  *
1832  * Return 0 on success or -errno on error.
1833  */
add_attr_vol_name(MFT_RECORD * m,const char * vol_name,const int vol_name_len)1834 static int add_attr_vol_name(MFT_RECORD *m, const char *vol_name,
1835 		const int vol_name_len __attribute__((unused)))
1836 {
1837 	ntfschar *uname = NULL;
1838 	int uname_len = 0;
1839 	int i;
1840 
1841 	if (vol_name) {
1842 		uname_len = ntfs_mbstoucs(vol_name, &uname, 0);
1843 		if (uname_len < 0)
1844 			return -errno;
1845 		if (uname_len > 0xff) {
1846 			free(uname);
1847 			return -ENAMETOOLONG;
1848 		}
1849 	}
1850 	i = insert_resident_attr_in_mft_record(m, AT_VOLUME_NAME, NULL, 0, 0,
1851 			0, 0, (u8*)uname, uname_len*sizeof(ntfschar));
1852 	free(uname);
1853 	if (i < 0)
1854 		ntfs_log_error("add_attr_vol_name failed: %s\n", strerror(-i));
1855 	return i;
1856 }
1857 
1858 /**
1859  * add_attr_vol_info
1860  *
1861  * Return 0 on success or -errno on error.
1862  */
add_attr_vol_info(MFT_RECORD * m,const VOLUME_FLAGS flags,const u8 major_ver,const u8 minor_ver)1863 static int add_attr_vol_info(MFT_RECORD *m, const VOLUME_FLAGS flags,
1864 		const u8 major_ver, const u8 minor_ver)
1865 {
1866 	VOLUME_INFORMATION vi;
1867 	int err;
1868 
1869 	memset(&vi, 0, sizeof(vi));
1870 	vi.major_ver = major_ver;
1871 	vi.minor_ver = minor_ver;
1872 	vi.flags = flags & VOLUME_FLAGS_MASK;
1873 	err = insert_resident_attr_in_mft_record(m, AT_VOLUME_INFORMATION, NULL,
1874 			0, 0, 0, 0, (u8*)&vi, sizeof(vi));
1875 	if (err < 0)
1876 		ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
1877 	return err;
1878 }
1879 
1880 /**
1881  * add_attr_index_root
1882  *
1883  * Return 0 on success or -errno on error.
1884  */
add_attr_index_root(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const ATTR_TYPES indexed_attr_type,const COLLATION_RULES collation_rule,const u32 index_block_size)1885 static int add_attr_index_root(MFT_RECORD *m, const char *name,
1886 		const u32 name_len, const IGNORE_CASE_BOOL ic,
1887 		const ATTR_TYPES indexed_attr_type,
1888 		const COLLATION_RULES collation_rule,
1889 		const u32 index_block_size)
1890 {
1891 	INDEX_ROOT *r;
1892 	INDEX_ENTRY_HEADER *e;
1893 	int err, val_len;
1894 
1895 	val_len = sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER);
1896 	r = ntfs_malloc(val_len);
1897 	if (!r)
1898 		return -errno;
1899 	r->type = (indexed_attr_type == AT_FILE_NAME) ? AT_FILE_NAME : 0;
1900 	if (indexed_attr_type == AT_FILE_NAME &&
1901 			collation_rule != COLLATION_FILE_NAME) {
1902 		free(r);
1903 		ntfs_log_error("add_attr_index_root: indexed attribute is $FILE_NAME "
1904 			"but collation rule is not COLLATION_FILE_NAME.\n");
1905 		return -EINVAL;
1906 	}
1907 	r->collation_rule = collation_rule;
1908 	r->index_block_size = cpu_to_le32(index_block_size);
1909 	if (index_block_size >= g_vol->cluster_size) {
1910 		if (index_block_size % g_vol->cluster_size) {
1911 			ntfs_log_error("add_attr_index_root: index block size is not "
1912 					"a multiple of the cluster size.\n");
1913 			free(r);
1914 			return -EINVAL;
1915 		}
1916 		r->clusters_per_index_block = index_block_size /
1917 				g_vol->cluster_size;
1918 	} else { /* if (g_vol->cluster_size > index_block_size) */
1919 		if (index_block_size & (index_block_size - 1)) {
1920 			ntfs_log_error("add_attr_index_root: index block size is not "
1921 					"a power of 2.\n");
1922 			free(r);
1923 			return -EINVAL;
1924 		}
1925 		if (index_block_size < (u32)opts.sector_size) {
1926 			 ntfs_log_error("add_attr_index_root: index block size "
1927 					 "is smaller than the sector size.\n");
1928 			 free(r);
1929 			 return -EINVAL;
1930 		}
1931 		r->clusters_per_index_block = index_block_size /
1932 				opts.sector_size;
1933 	}
1934 	memset(&r->reserved, 0, sizeof(r->reserved));
1935 	r->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER));
1936 	r->index.index_length = const_cpu_to_le32(sizeof(INDEX_HEADER) +
1937 			sizeof(INDEX_ENTRY_HEADER));
1938 	r->index.allocated_size = r->index.index_length;
1939 	r->index.flags = SMALL_INDEX;
1940 	memset(&r->index.reserved, 0, sizeof(r->index.reserved));
1941 	e = (INDEX_ENTRY_HEADER*)((u8*)&r->index +
1942 			le32_to_cpu(r->index.entries_offset));
1943 	/*
1944 	 * No matter whether this is a file index or a view as this is a
1945 	 * termination entry, hence no key value / data is associated with it
1946 	 * at all. Thus, we just need the union to be all zero.
1947 	 */
1948 	e->u.indexed_file = const_cpu_to_le64(0LL);
1949 	e->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
1950 	e->key_length = const_cpu_to_le16(0);
1951 	e->flags = INDEX_ENTRY_END;
1952 	e->reserved = const_cpu_to_le16(0);
1953 	err = insert_resident_attr_in_mft_record(m, AT_INDEX_ROOT, name,
1954 				name_len, ic, 0, 0, (u8*)r, val_len);
1955 	free(r);
1956 	if (err < 0)
1957 		ntfs_log_error("add_attr_index_root failed: %s\n", strerror(-err));
1958 	return err;
1959 }
1960 
1961 /**
1962  * add_attr_index_alloc
1963  *
1964  * Return 0 on success or -errno on error.
1965  */
add_attr_index_alloc(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const u8 * index_alloc_val,const u32 index_alloc_val_len)1966 static int add_attr_index_alloc(MFT_RECORD *m, const char *name,
1967 		const u32 name_len, const IGNORE_CASE_BOOL ic,
1968 		const u8 *index_alloc_val, const u32 index_alloc_val_len)
1969 {
1970 	int err;
1971 
1972 	err = insert_non_resident_attr_in_mft_record(m, AT_INDEX_ALLOCATION,
1973 			name, name_len, ic, 0, index_alloc_val,
1974 			index_alloc_val_len);
1975 	if (err < 0)
1976 		ntfs_log_error("add_attr_index_alloc failed: %s\n", strerror(-err));
1977 	return err;
1978 }
1979 
1980 /**
1981  * add_attr_bitmap
1982  *
1983  * Return 0 on success or -errno on error.
1984  */
add_attr_bitmap(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const u8 * bitmap,const u32 bitmap_len)1985 static int add_attr_bitmap(MFT_RECORD *m, const char *name, const u32 name_len,
1986 		const IGNORE_CASE_BOOL ic, const u8 *bitmap,
1987 		const u32 bitmap_len)
1988 {
1989 	int err;
1990 
1991 	/* Does it fit? NO: create non-resident. YES: create resident. */
1992 	if (le32_to_cpu(m->bytes_in_use) + 24 + bitmap_len >
1993 						le32_to_cpu(m->bytes_allocated))
1994 		err = insert_non_resident_attr_in_mft_record(m, AT_BITMAP, name,
1995 				name_len, ic, 0, bitmap, bitmap_len);
1996 	else
1997 		err = insert_resident_attr_in_mft_record(m, AT_BITMAP, name,
1998 				name_len, ic, 0, 0, bitmap, bitmap_len);
1999 
2000 	if (err < 0)
2001 		ntfs_log_error("add_attr_bitmap failed: %s\n", strerror(-err));
2002 	return err;
2003 }
2004 
2005 /**
2006  * add_attr_bitmap_positioned
2007  *
2008  * Create a non-resident bitmap attribute with a predefined on disk location
2009  * specified by the runlist @rl. The clusters specified by @rl are assumed to
2010  * be allocated already.
2011  *
2012  * Return 0 on success or -errno on error.
2013  */
add_attr_bitmap_positioned(MFT_RECORD * m,const char * name,const u32 name_len,const IGNORE_CASE_BOOL ic,const runlist * rl,const u8 * bitmap,const u32 bitmap_len)2014 static int add_attr_bitmap_positioned(MFT_RECORD *m, const char *name,
2015 		const u32 name_len, const IGNORE_CASE_BOOL ic,
2016 		const runlist *rl, const u8 *bitmap, const u32 bitmap_len)
2017 {
2018 	int err;
2019 
2020 	err = insert_positioned_attr_in_mft_record(m, AT_BITMAP, name, name_len,
2021 			ic, 0, rl, bitmap, bitmap_len);
2022 	if (err < 0)
2023 		ntfs_log_error("add_attr_bitmap_positioned failed: %s\n",
2024 				strerror(-err));
2025 	return err;
2026 }
2027 
2028 
2029 /**
2030  * upgrade_to_large_index
2031  *
2032  * Create bitmap and index allocation attributes, modify index root
2033  * attribute accordingly and move all of the index entries from the index root
2034  * into the index allocation.
2035  *
2036  * Return 0 on success or -errno on error.
2037  */
upgrade_to_large_index(MFT_RECORD * m,const char * name,u32 name_len,const IGNORE_CASE_BOOL ic,INDEX_ALLOCATION ** idx)2038 static int upgrade_to_large_index(MFT_RECORD *m, const char *name,
2039 		u32 name_len, const IGNORE_CASE_BOOL ic,
2040 		INDEX_ALLOCATION **idx)
2041 {
2042 	ntfs_attr_search_ctx *ctx;
2043 	ATTR_RECORD *a;
2044 	INDEX_ROOT *r;
2045 	INDEX_ENTRY *re;
2046 	INDEX_ALLOCATION *ia_val = NULL;
2047 	ntfschar *uname = NULL;
2048 	int uname_len = 0;
2049 	u8 bmp[8];
2050 	char *re_start, *re_end;
2051 	int i, err, index_block_size;
2052 
2053 	uname = ntfs_str2ucs(name, &uname_len);
2054 	if (!uname)
2055 		return -errno;
2056 
2057 	/* Find the index root attribute. */
2058 	ctx = ntfs_attr_get_search_ctx(NULL, m);
2059 	if (!ctx) {
2060 		ntfs_log_error("Failed to allocate attribute search context.\n");
2061 		ntfs_ucsfree(uname);
2062 		return -ENOMEM;
2063 	}
2064 	if (ic == IGNORE_CASE) {
2065 		ntfs_log_error("FIXME: Hit unimplemented code path #4.\n");
2066 		err = -EOPNOTSUPP;
2067 		ntfs_ucsfree(uname);
2068 		goto err_out;
2069 	}
2070 	err = mkntfs_attr_lookup(AT_INDEX_ROOT, uname, uname_len, ic, 0, NULL, 0,
2071 			ctx);
2072 	ntfs_ucsfree(uname);
2073 	if (err) {
2074 		err = -ENOTDIR;
2075 		goto err_out;
2076 	}
2077 	a = ctx->attr;
2078 	if (a->non_resident || a->flags) {
2079 		err = -EINVAL;
2080 		goto err_out;
2081 	}
2082 	r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->u.res.value_offset));
2083 	re_end = (char*)r + le32_to_cpu(a->u.res.value_length);
2084 	re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
2085 	re = (INDEX_ENTRY*)re_start;
2086 	index_block_size = le32_to_cpu(r->index_block_size);
2087 	memset(bmp, 0, sizeof(bmp));
2088 	ntfs_bit_set(bmp, 0ULL, 1);
2089 	/* Bitmap has to be at least 8 bytes in size. */
2090 	err = add_attr_bitmap(m, name, name_len, ic, bmp, sizeof(bmp));
2091 	if (err)
2092 		goto err_out;
2093 	ia_val = ntfs_calloc(index_block_size);
2094 	if (!ia_val) {
2095 		err = -errno;
2096 		goto err_out;
2097 	}
2098 	/* Setup header. */
2099 	ia_val->magic = magic_INDX;
2100 	ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION));
2101 	if (index_block_size >= NTFS_BLOCK_SIZE) {
2102 		ia_val->usa_count = cpu_to_le16(index_block_size /
2103 				NTFS_BLOCK_SIZE + 1);
2104 	} else {
2105 		ia_val->usa_count = cpu_to_le16(1);
2106 		ntfs_log_error("Sector size is bigger than index block size. "
2107 				"Setting usa_count to 1. If Windows chkdsk "
2108 				"reports this as corruption, please email %s "
2109 				"stating that you saw this message and that "
2110 				"the filesystem created was corrupt.  "
2111 				"Thank you.", NTFS_DEV_LIST);
2112 	}
2113 	/* Set USN to 1. */
2114 	*(le16*)((char*)ia_val + le16_to_cpu(ia_val->usa_ofs)) =
2115 			cpu_to_le16(1);
2116 	ia_val->lsn = 0;
2117 	ia_val->index_block_vcn = 0;
2118 	ia_val->index.flags = LEAF_NODE;
2119 	/* Align to 8-byte boundary. */
2120 	ia_val->index.entries_offset = cpu_to_le32((sizeof(INDEX_HEADER) +
2121 			le16_to_cpu(ia_val->usa_count) * 2 + 7) & ~7);
2122 	ia_val->index.allocated_size = cpu_to_le32(index_block_size -
2123 			(sizeof(INDEX_ALLOCATION) - sizeof(INDEX_HEADER)));
2124 	/* Find the last entry in the index root and save it in re. */
2125 	while ((char*)re < re_end && !(re->flags & INDEX_ENTRY_END)) {
2126 		/* Next entry in index root. */
2127 		re = (INDEX_ENTRY*)((char*)re + le16_to_cpu(re->length));
2128 	}
2129 	/* Copy all the entries including the termination entry. */
2130 	i = (char*)re - re_start + le16_to_cpu(re->length);
2131 	memcpy((char*)&ia_val->index +
2132 			le32_to_cpu(ia_val->index.entries_offset), re_start, i);
2133 	/* Finish setting up index allocation. */
2134 	ia_val->index.index_length = cpu_to_le32(i +
2135 			le32_to_cpu(ia_val->index.entries_offset));
2136 	/* Move the termination entry forward to the beginning if necessary. */
2137 	if ((char*)re > re_start) {
2138 		memmove(re_start, (char*)re, le16_to_cpu(re->length));
2139 		re = (INDEX_ENTRY*)re_start;
2140 	}
2141 	/* Now fixup empty index root with pointer to index allocation VCN 0. */
2142 	r->index.flags = LARGE_INDEX;
2143 	re->flags |= INDEX_ENTRY_NODE;
2144 	if (le16_to_cpu(re->length) < sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN))
2145 		re->length = cpu_to_le16(le16_to_cpu(re->length) + sizeof(VCN));
2146 	r->index.index_length = cpu_to_le32(le32_to_cpu(r->index.entries_offset)
2147 			+ le16_to_cpu(re->length));
2148 	r->index.allocated_size = r->index.index_length;
2149 	/* Resize index root attribute. */
2150 	if (ntfs_resident_attr_value_resize(m, a, sizeof(INDEX_ROOT) -
2151 			sizeof(INDEX_HEADER) +
2152 			le32_to_cpu(r->index.allocated_size))) {
2153 		/* TODO: Remove the added bitmap! */
2154 		/* Revert index root from index allocation. */
2155 		err = -errno;
2156 		goto err_out;
2157 	}
2158 	/* Set VCN pointer to 0LL. */
2159 	*(leVCN*)((char*)re + le16_to_cpu(re->length) - sizeof(VCN)) = 0;
2160 	err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)ia_val, index_block_size);
2161 	if (err) {
2162 		err = -errno;
2163 		ntfs_log_error("ntfs_mst_pre_write_fixup() failed in "
2164 				"upgrade_to_large_index.\n");
2165 		goto err_out;
2166 	}
2167 	err = add_attr_index_alloc(m, name, name_len, ic, (u8*)ia_val,
2168 			index_block_size);
2169 	ntfs_mst_post_write_fixup((NTFS_RECORD*)ia_val);
2170 	if (err) {
2171 		/* TODO: Remove the added bitmap! */
2172 		/* Revert index root from index allocation. */
2173 		goto err_out;
2174 	}
2175 	*idx = ia_val;
2176 	ntfs_attr_put_search_ctx(ctx);
2177 	return 0;
2178 err_out:
2179 	ntfs_attr_put_search_ctx(ctx);
2180 	free(ia_val);
2181 	return err;
2182 }
2183 
2184 /**
2185  * make_room_for_index_entry_in_index_block
2186  *
2187  * Create space of @size bytes at position @pos inside the index block @idx.
2188  *
2189  * Return 0 on success or -errno on error.
2190  */
make_room_for_index_entry_in_index_block(INDEX_BLOCK * idx,INDEX_ENTRY * pos,u32 size)2191 static int make_room_for_index_entry_in_index_block(INDEX_BLOCK *idx,
2192 		INDEX_ENTRY *pos, u32 size)
2193 {
2194 	u32 biu;
2195 
2196 	if (!size)
2197 		return 0;
2198 #ifdef DEBUG
2199 	/*
2200 	 * Rigorous consistency checks. Always return -EINVAL even if more
2201 	 * appropriate codes exist for simplicity of parsing the return value.
2202 	 */
2203 	if (size != ((size + 7) & ~7)) {
2204 		ntfs_log_error("make_room_for_index_entry_in_index_block() received "
2205 				"non 8-byte aligned size.\n");
2206 		return -EINVAL;
2207 	}
2208 	if (!idx || !pos)
2209 		return -EINVAL;
2210 	if ((char*)pos < (char*)idx || (char*)pos + size < (char*)idx ||
2211 			(char*)pos > (char*)idx + sizeof(INDEX_BLOCK) -
2212 				sizeof(INDEX_HEADER) +
2213 				le32_to_cpu(idx->index.allocated_size) ||
2214 			(char*)pos + size > (char*)idx + sizeof(INDEX_BLOCK) -
2215 				sizeof(INDEX_HEADER) +
2216 				le32_to_cpu(idx->index.allocated_size))
2217 		return -EINVAL;
2218 	/* The - sizeof(INDEX_ENTRY_HEADER) is for the index terminator. */
2219 	if ((char*)pos - (char*)&idx->index >
2220 			(int)le32_to_cpu(idx->index.index_length)
2221 			- (int)sizeof(INDEX_ENTRY_HEADER))
2222 		return -EINVAL;
2223 #endif
2224 	biu = le32_to_cpu(idx->index.index_length);
2225 	/* Do we have enough space? */
2226 	if (biu + size > le32_to_cpu(idx->index.allocated_size))
2227 		return -ENOSPC;
2228 	/* Move everything after pos to pos + size. */
2229 	memmove((char*)pos + size, (char*)pos, biu - ((char*)pos -
2230 			(char*)&idx->index));
2231 	/* Update index block. */
2232 	idx->index.index_length = cpu_to_le32(biu + size);
2233 	return 0;
2234 }
2235 
2236 /**
2237  * ntfs_index_keys_compare
2238  *
2239  * not all types of COLLATION_RULES supported yet...
2240  * added as needed.. (remove this comment when all are added)
2241  */
ntfs_index_keys_compare(u8 * key1,u8 * key2,int key1_length,int key2_length,COLLATION_RULES collation_rule)2242 static int ntfs_index_keys_compare(u8 *key1, u8 *key2, int key1_length,
2243 		int key2_length, COLLATION_RULES collation_rule)
2244 {
2245 	u32 u1, u2;
2246 	int i;
2247 
2248 	if (collation_rule == COLLATION_NTOFS_ULONG) {
2249 		/* i.e. $SII or $QUOTA-$Q */
2250 		u1 = le32_to_cpup(key1);
2251 		u2 = le32_to_cpup(key2);
2252 		if (u1 < u2)
2253 			return -1;
2254 		if (u1 > u2)
2255 			return 1;
2256 		/* u1 == u2 */
2257 		return 0;
2258 	}
2259 	if (collation_rule == COLLATION_NTOFS_ULONGS) {
2260 		/* i.e $OBJID-$O */
2261 		i = 0;
2262 		while (i < min(key1_length, key2_length)) {
2263 			u1 = le32_to_cpup(key1 + i);
2264 			u2 = le32_to_cpup(key2 + i);
2265 			if (u1 < u2)
2266 				return -1;
2267 			if (u1 > u2)
2268 				return 1;
2269 			/* u1 == u2 */
2270 			i += sizeof(u32);
2271 		}
2272 		if (key1_length < key2_length)
2273 			return -1;
2274 		if (key1_length > key2_length)
2275 			return 1;
2276 		return 0;
2277 	}
2278 	if (collation_rule == COLLATION_NTOFS_SECURITY_HASH) {
2279 		/* i.e. $SDH */
2280 		u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->hash);
2281 		u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->hash);
2282 		if (u1 < u2)
2283 			return -1;
2284 		if (u1 > u2)
2285 			return 1;
2286 		/* u1 == u2 */
2287 		u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->security_id);
2288 		u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->security_id);
2289 		if (u1 < u2)
2290 			return -1;
2291 		if (u1 > u2)
2292 			return 1;
2293 		return 0;
2294 	}
2295 	if (collation_rule == COLLATION_NTOFS_SID) {
2296 		/* i.e. $QUOTA-O */
2297 		i = memcmp(key1, key2, min(key1_length, key2_length));
2298 		if (!i) {
2299 			if (key1_length < key2_length)
2300 				return -1;
2301 			if (key1_length > key2_length)
2302 				return 1;
2303 		}
2304 		return i;
2305 	}
2306 	ntfs_log_critical("ntfs_index_keys_compare called without supported "
2307 			"collation rule.\n");
2308 	return 0;	/* Claim they're equal.  What else can we do? */
2309 }
2310 
2311 /**
2312  * insert_index_entry_in_res_dir_index
2313  *
2314  * i.e. insert an index_entry in some named index_root
2315  * simplified search method, works for mkntfs
2316  */
insert_index_entry_in_res_dir_index(INDEX_ENTRY * idx,u32 idx_size,MFT_RECORD * m,ntfschar * name,u32 name_size,ATTR_TYPES type)2317 static int insert_index_entry_in_res_dir_index(INDEX_ENTRY *idx, u32 idx_size,
2318 		MFT_RECORD *m, ntfschar *name, u32 name_size, ATTR_TYPES type)
2319 {
2320 	ntfs_attr_search_ctx *ctx;
2321 	INDEX_HEADER *idx_header;
2322 	INDEX_ENTRY *idx_entry, *idx_end;
2323 	ATTR_RECORD *a;
2324 	COLLATION_RULES collation_rule;
2325 	int err, i;
2326 
2327 	err = 0;
2328 	/* does it fit ?*/
2329 	if (g_vol->mft_record_size > idx_size + le32_to_cpu(m->bytes_allocated))
2330 		return -ENOSPC;
2331 	/* find the INDEX_ROOT attribute:*/
2332 	ctx = ntfs_attr_get_search_ctx(NULL, m);
2333 	if (!ctx) {
2334 		ntfs_log_error("Failed to allocate attribute search "
2335 				"context.\n");
2336 		err = -ENOMEM;
2337 		goto err_out;
2338 	}
2339 	if (mkntfs_attr_lookup(AT_INDEX_ROOT, name, name_size, 0, 0, NULL, 0,
2340 			ctx)) {
2341 		err = -EEXIST;
2342 		goto err_out;
2343 	}
2344 	/* found attribute */
2345 	a = (ATTR_RECORD*)ctx->attr;
2346 	collation_rule = ((INDEX_ROOT*)((u8*)a +
2347 			le16_to_cpu(a->u.res.value_offset)))->collation_rule;
2348 	idx_header = (INDEX_HEADER*)((u8*)a + le16_to_cpu(a->u.res.value_offset)
2349 			+ 0x10);
2350 	idx_entry = (INDEX_ENTRY*)((u8*)idx_header +
2351 			le32_to_cpu(idx_header->entries_offset));
2352 	idx_end = (INDEX_ENTRY*)((u8*)idx_entry +
2353 			le32_to_cpu(idx_header->index_length));
2354 	/*
2355 	 * Loop until we exceed valid memory (corruption case) or until we
2356 	 * reach the last entry.
2357 	 */
2358 	if (type == AT_FILE_NAME) {
2359 		while (((u8*)idx_entry < (u8*)idx_end) &&
2360 				!(idx_entry->flags & INDEX_ENTRY_END)) {
2361 			i = ntfs_file_values_compare(&idx->key.file_name,
2362 					&idx_entry->key.file_name, 1,
2363 					IGNORE_CASE, g_vol->upcase,
2364 					g_vol->upcase_len);
2365 			/*
2366 			 * If @file_name collates before ie->key.file_name,
2367 			 * there is no matching index entry.
2368 			 */
2369 			if (i == -1)
2370 				break;
2371 			/* If file names are not equal, continue search. */
2372 			if (i)
2373 				goto do_next;
2374 			if (idx->key.file_name.file_name_type !=
2375 					FILE_NAME_POSIX ||
2376 					idx_entry->key.file_name.file_name_type
2377 					!= FILE_NAME_POSIX)
2378 				return -EEXIST;
2379 			i = ntfs_file_values_compare(&idx->key.file_name,
2380 					&idx_entry->key.file_name, 1,
2381 					CASE_SENSITIVE, g_vol->upcase,
2382 					g_vol->upcase_len);
2383 			if (!i)
2384 				return -EEXIST;
2385 			if (i == -1)
2386 				break;
2387 do_next:
2388 			idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
2389 					le16_to_cpu(idx_entry->length));
2390 		}
2391 	} else if (type == AT_UNUSED) {  /* case view */
2392 		while (((u8*)idx_entry < (u8*)idx_end) &&
2393 				!(idx_entry->flags & INDEX_ENTRY_END)) {
2394 			i = ntfs_index_keys_compare((u8*)idx + 0x10,
2395 					(u8*)idx_entry + 0x10,
2396 					le16_to_cpu(idx->key_length),
2397 					le16_to_cpu(idx_entry->key_length),
2398 					collation_rule);
2399 			if (!i)
2400 				return -EEXIST;
2401 			if (i == -1)
2402 				break;
2403 			idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
2404 					le16_to_cpu(idx_entry->length));
2405 		}
2406 	} else
2407 		return -EINVAL;
2408 	memmove((u8*)idx_entry + idx_size, (u8*)idx_entry,
2409 			le32_to_cpu(m->bytes_in_use) -
2410 			((u8*)idx_entry - (u8*)m));
2411 	memcpy((u8*)idx_entry, (u8*)idx, idx_size);
2412 	/* Adjust various offsets, etc... */
2413 	m->bytes_in_use = cpu_to_le32(le32_to_cpu(m->bytes_in_use) + idx_size);
2414 	a->length = cpu_to_le32(le32_to_cpu(a->length) + idx_size);
2415 	a->u.res.value_length = cpu_to_le32(le32_to_cpu(a->u.res.value_length) + idx_size);
2416 	idx_header->index_length = cpu_to_le32(
2417 			le32_to_cpu(idx_header->index_length) + idx_size);
2418 	idx_header->allocated_size = cpu_to_le32(
2419 			le32_to_cpu(idx_header->allocated_size) + idx_size);
2420 err_out:
2421 	if (ctx)
2422 		ntfs_attr_put_search_ctx(ctx);
2423 	return err;
2424 }
2425 
2426 /**
2427  * initialize_secure
2428  *
2429  * initializes $Secure's $SDH and $SII indexes from $SDS datastream
2430  */
initialize_secure(char * sds,u32 sds_size,MFT_RECORD * m)2431 static int initialize_secure(char *sds, u32 sds_size, MFT_RECORD *m)
2432 {
2433 	int err, sdh_size, sii_size;
2434 	SECURITY_DESCRIPTOR_HEADER *sds_header;
2435 	INDEX_ENTRY *idx_entry_sdh, *idx_entry_sii;
2436 	SDH_INDEX_DATA *sdh_data;
2437 	SII_INDEX_DATA *sii_data;
2438 
2439 	sds_header = (SECURITY_DESCRIPTOR_HEADER*)sds;
2440 	sdh_size  = sizeof(INDEX_ENTRY_HEADER);
2441 	sdh_size += sizeof(SDH_INDEX_KEY) + sizeof(SDH_INDEX_DATA);
2442 	sii_size  = sizeof(INDEX_ENTRY_HEADER);
2443 	sii_size += sizeof(SII_INDEX_KEY) + sizeof(SII_INDEX_DATA);
2444 	idx_entry_sdh = ntfs_calloc(sizeof(INDEX_ENTRY));
2445 	if (!idx_entry_sdh)
2446 		return -errno;
2447 	idx_entry_sii = ntfs_calloc(sizeof(INDEX_ENTRY));
2448 	if (!idx_entry_sii) {
2449 		free(idx_entry_sdh);
2450 		return -errno;
2451 	}
2452 	err = 0;
2453 
2454 	while ((char*)sds_header < (char*)sds + sds_size) {
2455 		if (!sds_header->length)
2456 			break;
2457 		/* SDH index entry */
2458 		idx_entry_sdh->u.s.data_offset = const_cpu_to_le16(0x18);
2459 		idx_entry_sdh->u.s.data_length = const_cpu_to_le16(0x14);
2460 		idx_entry_sdh->u.s.reservedV = const_cpu_to_le32(0x00);
2461 		idx_entry_sdh->length = const_cpu_to_le16(0x30);
2462 		idx_entry_sdh->key_length = const_cpu_to_le16(0x08);
2463 		idx_entry_sdh->flags = const_cpu_to_le16(0x00);
2464 		idx_entry_sdh->reserved = const_cpu_to_le16(0x00);
2465 		idx_entry_sdh->key.sdh.hash = sds_header->hash;
2466 		idx_entry_sdh->key.sdh.security_id = sds_header->security_id;
2467 		sdh_data = (SDH_INDEX_DATA*)((u8*)idx_entry_sdh +
2468 				le16_to_cpu(idx_entry_sdh->u.s.data_offset));
2469 		sdh_data->hash = sds_header->hash;
2470 		sdh_data->security_id = sds_header->security_id;
2471 		sdh_data->offset = sds_header->offset;
2472 		sdh_data->length = sds_header->length;
2473 		sdh_data->reserved_II = const_cpu_to_le32(0x00490049);
2474 
2475 		/* SII index entry */
2476 		idx_entry_sii->u.s.data_offset = const_cpu_to_le16(0x14);
2477 		idx_entry_sii->u.s.data_length = const_cpu_to_le16(0x14);
2478 		idx_entry_sii->u.s.reservedV = const_cpu_to_le32(0x00);
2479 		idx_entry_sii->length = const_cpu_to_le16(0x28);
2480 		idx_entry_sii->key_length = const_cpu_to_le16(0x04);
2481 		idx_entry_sii->flags = const_cpu_to_le16(0x00);
2482 		idx_entry_sii->reserved = const_cpu_to_le16(0x00);
2483 		idx_entry_sii->key.sii.security_id = sds_header->security_id;
2484 		sii_data = (SII_INDEX_DATA*)((u8*)idx_entry_sii +
2485 				le16_to_cpu(idx_entry_sii->u.s.data_offset));
2486 		sii_data->hash = sds_header->hash;
2487 		sii_data->security_id = sds_header->security_id;
2488 		sii_data->offset = sds_header->offset;
2489 		sii_data->length = sds_header->length;
2490 		if ((err = insert_index_entry_in_res_dir_index(idx_entry_sdh,
2491 				sdh_size, m, NTFS_INDEX_SDH, 4, AT_UNUSED)))
2492 			break;
2493 		if ((err = insert_index_entry_in_res_dir_index(idx_entry_sii,
2494 				sii_size, m, NTFS_INDEX_SII, 4, AT_UNUSED)))
2495 			break;
2496 		sds_header = (SECURITY_DESCRIPTOR_HEADER*)((u8*)sds_header +
2497 				((le32_to_cpu(sds_header->length) + 15) & ~15));
2498 	}
2499 	free(idx_entry_sdh);
2500 	free(idx_entry_sii);
2501 	return err;
2502 }
2503 
2504 /**
2505  * initialize_quota
2506  *
2507  * initialize $Quota with the default quota index-entries.
2508  */
initialize_quota(MFT_RECORD * m)2509 static int initialize_quota(MFT_RECORD *m)
2510 {
2511 	int o_size, q1_size, q2_size, err, i;
2512 	INDEX_ENTRY *idx_entry_o, *idx_entry_q1, *idx_entry_q2;
2513 	QUOTA_O_INDEX_DATA *idx_entry_o_data;
2514 	QUOTA_CONTROL_ENTRY *idx_entry_q1_data, *idx_entry_q2_data;
2515 
2516 	err = 0;
2517 	/* q index entry num 1 */
2518 	q1_size = 0x48;
2519 	idx_entry_q1 = ntfs_calloc(q1_size);
2520 	if (!idx_entry_q1)
2521 		return errno;
2522 	idx_entry_q1->u.s.data_offset = const_cpu_to_le16(0x14);
2523 	idx_entry_q1->u.s.data_length = const_cpu_to_le16(0x30);
2524 	idx_entry_q1->u.s.reservedV = const_cpu_to_le32(0x00);
2525 	idx_entry_q1->length = const_cpu_to_le16(0x48);
2526 	idx_entry_q1->key_length = const_cpu_to_le16(0x04);
2527 	idx_entry_q1->flags = const_cpu_to_le16(0x00);
2528 	idx_entry_q1->reserved = const_cpu_to_le16(0x00);
2529 	idx_entry_q1->key.owner_id = const_cpu_to_le32(0x01);
2530 	idx_entry_q1_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q1
2531 			+ le16_to_cpu(idx_entry_q1->u.s.data_offset));
2532 	idx_entry_q1_data->version = const_cpu_to_le32(0x02);
2533 	idx_entry_q1_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
2534 	idx_entry_q1_data->bytes_used = const_cpu_to_le64(0x00);
2535 	idx_entry_q1_data->change_time = utc2ntfs(mkntfs_time());
2536 	idx_entry_q1_data->threshold = cpu_to_sle64(-1);
2537 	idx_entry_q1_data->limit = cpu_to_sle64(-1);
2538 	idx_entry_q1_data->exceeded_time = 0;
2539 	err = insert_index_entry_in_res_dir_index(idx_entry_q1, q1_size, m,
2540 			NTFS_INDEX_Q, 2, AT_UNUSED);
2541 	free(idx_entry_q1);
2542 	if (err)
2543 		return err;
2544 	/* q index entry num 2 */
2545 	q2_size = 0x58;
2546 	idx_entry_q2 = ntfs_calloc(q2_size);
2547 	if (!idx_entry_q2)
2548 		return errno;
2549 	idx_entry_q2->u.s.data_offset = const_cpu_to_le16(0x14);
2550 	idx_entry_q2->u.s.data_length = const_cpu_to_le16(0x40);
2551 	idx_entry_q2->u.s.reservedV = const_cpu_to_le32(0x00);
2552 	idx_entry_q2->length = const_cpu_to_le16(0x58);
2553 	idx_entry_q2->key_length = const_cpu_to_le16(0x04);
2554 	idx_entry_q2->flags = const_cpu_to_le16(0x00);
2555 	idx_entry_q2->reserved = const_cpu_to_le16(0x00);
2556 	idx_entry_q2->key.owner_id = QUOTA_FIRST_USER_ID;
2557 	idx_entry_q2_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q2
2558 			+ le16_to_cpu(idx_entry_q2->u.s.data_offset));
2559 	idx_entry_q2_data->version = const_cpu_to_le32(0x02);
2560 	idx_entry_q2_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
2561 	idx_entry_q2_data->bytes_used = const_cpu_to_le64(0x00);
2562 	idx_entry_q2_data->change_time = utc2ntfs(mkntfs_time());;
2563 	idx_entry_q2_data->threshold = cpu_to_sle64(-1);
2564 	idx_entry_q2_data->limit = cpu_to_sle64(-1);
2565 	idx_entry_q2_data->exceeded_time = 0;
2566 	idx_entry_q2_data->sid.revision = 1;
2567 	idx_entry_q2_data->sid.sub_authority_count = 2;
2568 	for (i = 0; i < 5; i++)
2569 		idx_entry_q2_data->sid.identifier_authority.value[i] = 0;
2570 	idx_entry_q2_data->sid.identifier_authority.value[5] = 0x05;
2571 	idx_entry_q2_data->sid.sub_authority[0] =
2572 			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
2573 	idx_entry_q2_data->sid.sub_authority[1] =
2574 			const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
2575 	err = insert_index_entry_in_res_dir_index(idx_entry_q2, q2_size, m,
2576 			NTFS_INDEX_Q, 2, AT_UNUSED);
2577 	free(idx_entry_q2);
2578 	if (err)
2579 		return err;
2580 	o_size = 0x28;
2581 	idx_entry_o = ntfs_calloc(o_size);
2582 	if (!idx_entry_o)
2583 		return errno;
2584 	idx_entry_o->u.s.data_offset = const_cpu_to_le16(0x20);
2585 	idx_entry_o->u.s.data_length = const_cpu_to_le16(0x04);
2586 	idx_entry_o->u.s.reservedV = const_cpu_to_le32(0x00);
2587 	idx_entry_o->length = const_cpu_to_le16(0x28);
2588 	idx_entry_o->key_length = const_cpu_to_le16(0x10);
2589 	idx_entry_o->flags = const_cpu_to_le16(0x00);
2590 	idx_entry_o->reserved = const_cpu_to_le16(0x00);
2591 	idx_entry_o->key.sid.revision = 0x01;
2592 	idx_entry_o->key.sid.sub_authority_count = 0x02;
2593 	for (i = 0; i < 5; i++)
2594 		idx_entry_o->key.sid.identifier_authority.value[i] = 0;
2595 	idx_entry_o->key.sid.identifier_authority.value[5] = 0x05;
2596 	idx_entry_o->key.sid.sub_authority[0] =
2597 			const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
2598 	idx_entry_o->key.sid.sub_authority[1] =
2599 			const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
2600 	idx_entry_o_data = (QUOTA_O_INDEX_DATA*)((char*)idx_entry_o
2601 			+ le16_to_cpu(idx_entry_o->u.s.data_offset));
2602 	idx_entry_o_data->owner_id  = QUOTA_FIRST_USER_ID;
2603 	/* 20 00 00 00 padding after here on ntfs 3.1. 3.0 is unchecked. */
2604 	idx_entry_o_data->unknown = const_cpu_to_le32(32);
2605 	err = insert_index_entry_in_res_dir_index(idx_entry_o, o_size, m,
2606 			NTFS_INDEX_O, 2, AT_UNUSED);
2607 	free(idx_entry_o);
2608 
2609 	return err;
2610 }
2611 
2612 /**
2613  * insert_file_link_in_dir_index
2614  *
2615  * Insert the fully completed FILE_NAME_ATTR @file_name which is inside
2616  * the file with mft reference @file_ref into the index (allocation) block
2617  * @idx (which belongs to @file_ref's parent directory).
2618  *
2619  * Return 0 on success or -errno on error.
2620  */
insert_file_link_in_dir_index(INDEX_BLOCK * idx,leMFT_REF file_ref,FILE_NAME_ATTR * file_name,u32 file_name_size)2621 static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, leMFT_REF file_ref,
2622 		FILE_NAME_ATTR *file_name, u32 file_name_size)
2623 {
2624 	int err, i;
2625 	INDEX_ENTRY *ie;
2626 	char *index_end;
2627 
2628 	/*
2629 	 * Lookup dir entry @file_name in dir @idx to determine correct
2630 	 * insertion location. FIXME: Using a very oversimplified lookup
2631 	 * method which is sufficient for mkntfs but no good whatsoever in
2632 	 * real world scenario. (AIA)
2633 	 */
2634 
2635 	index_end = (char*)&idx->index + le32_to_cpu(idx->index.index_length);
2636 	ie = (INDEX_ENTRY*)((char*)&idx->index +
2637 			le32_to_cpu(idx->index.entries_offset));
2638 	/*
2639 	 * Loop until we exceed valid memory (corruption case) or until we
2640 	 * reach the last entry.
2641 	 */
2642 	while ((char*)ie < index_end && !(ie->flags & INDEX_ENTRY_END)) {
2643 #if 0
2644 #ifdef DEBUG
2645 		ntfs_log_debug("file_name_attr1->file_name_length = %i\n",
2646 				file_name->file_name_length);
2647 		if (file_name->file_name_length) {
2648 			char *__buf = NULL;
2649 			i = ntfs_ucstombs((ntfschar*)&file_name->file_name,
2650 				file_name->file_name_length, &__buf, 0);
2651 			if (i < 0)
2652 				ntfs_log_debug("Name contains non-displayable "
2653 						"Unicode characters.\n");
2654 			ntfs_log_debug("file_name_attr1->file_name = %s\n",
2655 					__buf);
2656 			free(__buf);
2657 		}
2658 		ntfs_log_debug("file_name_attr2->file_name_length = %i\n",
2659 				ie->key.file_name.file_name_length);
2660 		if (ie->key.file_name.file_name_length) {
2661 			char *__buf = NULL;
2662 			i = ntfs_ucstombs(ie->key.file_name.file_name,
2663 				ie->key.file_name.file_name_length + 1, &__buf,
2664 				0);
2665 			if (i < 0)
2666 				ntfs_log_debug("Name contains non-displayable "
2667 						"Unicode characters.\n");
2668 			ntfs_log_debug("file_name_attr2->file_name = %s\n",
2669 					__buf);
2670 			free(__buf);
2671 		}
2672 #endif
2673 #endif
2674 		i = ntfs_file_values_compare(file_name,
2675 				(FILE_NAME_ATTR*)&ie->key.file_name, 1,
2676 				IGNORE_CASE, g_vol->upcase, g_vol->upcase_len);
2677 		/*
2678 		 * If @file_name collates before ie->key.file_name, there is no
2679 		 * matching index entry.
2680 		 */
2681 		if (i == -1)
2682 			break;
2683 		/* If file names are not equal, continue search. */
2684 		if (i)
2685 			goto do_next;
2686 		/* File names are equal when compared ignoring case. */
2687 		/*
2688 		 * If BOTH file names are in the POSIX namespace, do a case
2689 		 * sensitive comparison as well. Otherwise the names match so
2690 		 * we return -EEXIST. FIXME: There are problems with this in a
2691 		 * real world scenario, when one is POSIX and one isn't, but
2692 		 * fine for mkntfs where we don't use POSIX namespace at all
2693 		 * and hence this following code is luxury. (AIA)
2694 		 */
2695 		if (file_name->file_name_type != FILE_NAME_POSIX ||
2696 		    ie->key.file_name.file_name_type != FILE_NAME_POSIX)
2697 			return -EEXIST;
2698 		i = ntfs_file_values_compare(file_name,
2699 				(FILE_NAME_ATTR*)&ie->key.file_name, 1,
2700 				CASE_SENSITIVE, g_vol->upcase,
2701 				g_vol->upcase_len);
2702 		if (i == -1)
2703 			break;
2704 		/* Complete match. Bugger. Can't insert. */
2705 		if (!i)
2706 			return -EEXIST;
2707 do_next:
2708 #ifdef DEBUG
2709 		/* Next entry. */
2710 		if (!ie->length) {
2711 			ntfs_log_debug("BUG: ie->length is zero, breaking out "
2712 					"of loop.\n");
2713 			break;
2714 		}
2715 #endif
2716 		ie = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length));
2717 	};
2718 	i = (sizeof(INDEX_ENTRY_HEADER) + file_name_size + 7) & ~7;
2719 	err = make_room_for_index_entry_in_index_block(idx, ie, i);
2720 	if (err) {
2721 		ntfs_log_error("make_room_for_index_entry_in_index_block "
2722 				"failed: %s\n", strerror(-err));
2723 		return err;
2724 	}
2725 	/* Create entry in place and copy file name attribute value. */
2726 	ie->u.indexed_file = file_ref;
2727 	ie->length = cpu_to_le16(i);
2728 	ie->key_length = cpu_to_le16(file_name_size);
2729 	ie->flags = cpu_to_le16(0);
2730 	ie->reserved = cpu_to_le16(0);
2731 	memcpy((char*)&ie->key.file_name, (char*)file_name, file_name_size);
2732 	return 0;
2733 }
2734 
2735 /**
2736  * create_hardlink_res
2737  *
2738  * Create a file_name_attribute in the mft record @m_file which points to the
2739  * parent directory with mft reference @ref_parent.
2740  *
2741  * Then, insert an index entry with this file_name_attribute in the index
2742  * root @idx of the index_root attribute of the parent directory.
2743  *
2744  * @ref_file is the mft reference of @m_file.
2745  *
2746  * Return 0 on success or -errno on error.
2747  */
create_hardlink_res(MFT_RECORD * m_parent,const leMFT_REF ref_parent,MFT_RECORD * m_file,const leMFT_REF ref_file,const s64 allocated_size,const s64 data_size,const FILE_ATTR_FLAGS flags,const u16 packed_ea_size,const u32 reparse_point_tag,const char * file_name,const FILE_NAME_TYPE_FLAGS file_name_type)2748 static int create_hardlink_res(MFT_RECORD *m_parent, const leMFT_REF ref_parent,
2749 		MFT_RECORD *m_file, const leMFT_REF ref_file,
2750 		const s64 allocated_size, const s64 data_size,
2751 		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
2752 		const u32 reparse_point_tag, const char *file_name,
2753 		const FILE_NAME_TYPE_FLAGS file_name_type)
2754 {
2755 	FILE_NAME_ATTR *fn;
2756 	int i, fn_size, idx_size;
2757 	INDEX_ENTRY *idx_entry_new;
2758 	ntfschar *uname;
2759 
2760 	/* Create the file_name attribute. */
2761 	i = (strlen(file_name) + 1) * sizeof(ntfschar);
2762 	fn_size = sizeof(FILE_NAME_ATTR) + i;
2763 	fn = ntfs_malloc(fn_size);
2764 	if (!fn)
2765 		return -errno;
2766 	fn->parent_directory = ref_parent;
2767 	/* FIXME: copy the creation_time from the std info */
2768 	fn->creation_time = utc2ntfs(mkntfs_time());
2769 	fn->last_data_change_time = fn->creation_time;
2770 	fn->last_mft_change_time = fn->creation_time;
2771 	fn->last_access_time = fn->creation_time;
2772 	fn->allocated_size = cpu_to_sle64(allocated_size);
2773 	fn->data_size = cpu_to_sle64(data_size);
2774 	fn->file_attributes = flags;
2775 	/* These are in a union so can't have both. */
2776 	if (packed_ea_size && reparse_point_tag) {
2777 		free(fn);
2778 		return -EINVAL;
2779 	}
2780 	if (packed_ea_size) {
2781 		free(fn);
2782 		return -EINVAL;
2783 	}
2784 	if (packed_ea_size) {
2785 		fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size);
2786 		fn->u.s.reserved = cpu_to_le16(0);
2787 	} else {
2788 		fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag);
2789 	}
2790 	fn->file_name_type = file_name_type;
2791 	uname = fn->file_name;
2792 	i = ntfs_mbstoucs(file_name, &uname, i);
2793 	if (i < 1) {
2794 		free(fn);
2795 		return -EINVAL;
2796 	}
2797 	if (i > 0xff) {
2798 		free(fn);
2799 		return -ENAMETOOLONG;
2800 	}
2801 	/* No terminating null in file names. */
2802 	fn->file_name_length = i;
2803 	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
2804 	/* Increment the link count of @m_file. */
2805 	i = le16_to_cpu(m_file->link_count);
2806 	if (i == 0xffff) {
2807 		ntfs_log_error("Too many hardlinks present already.\n");
2808 		free(fn);
2809 		return -EINVAL;
2810 	}
2811 	m_file->link_count = cpu_to_le16(i + 1);
2812 	/* Add the file_name to @m_file. */
2813 	i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0, 0,
2814 			0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
2815 	if (i < 0) {
2816 		ntfs_log_error("create_hardlink failed adding file name "
2817 				"attribute: %s\n", strerror(-i));
2818 		free(fn);
2819 		/* Undo link count increment. */
2820 		m_file->link_count = cpu_to_le16(
2821 				le16_to_cpu(m_file->link_count) - 1);
2822 		return i;
2823 	}
2824 	/* Insert the index entry for file_name in @idx. */
2825 	idx_size = (fn_size + 7)  & ~7;
2826 	idx_entry_new = ntfs_calloc(idx_size + 0x10);
2827 	if (!idx_entry_new)
2828 		return -errno;
2829 	idx_entry_new->u.indexed_file = ref_file;
2830 	idx_entry_new->length = cpu_to_le16(idx_size + 0x10);
2831 	idx_entry_new->key_length = cpu_to_le16(fn_size);
2832 	memcpy((u8*)idx_entry_new + 0x10, (u8*)fn, fn_size);
2833 	i = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size + 0x10,
2834 			m_parent, NTFS_INDEX_I30, 4, AT_FILE_NAME);
2835 	if (i < 0) {
2836 		ntfs_log_error("create_hardlink failed inserting index entry: "
2837 				"%s\n", strerror(-i));
2838 		/* FIXME: Remove the file name attribute from @m_file. */
2839 		free(idx_entry_new);
2840 		free(fn);
2841 		/* Undo link count increment. */
2842 		m_file->link_count = cpu_to_le16(
2843 				le16_to_cpu(m_file->link_count) - 1);
2844 		return i;
2845 	}
2846 	free(idx_entry_new);
2847 	free(fn);
2848 	return 0;
2849 }
2850 
2851 /**
2852  * create_hardlink
2853  *
2854  * Create a file_name_attribute in the mft record @m_file which points to the
2855  * parent directory with mft reference @ref_parent.
2856  *
2857  * Then, insert an index entry with this file_name_attribute in the index
2858  * block @idx of the index allocation attribute of the parent directory.
2859  *
2860  * @ref_file is the mft reference of @m_file.
2861  *
2862  * Return 0 on success or -errno on error.
2863  */
create_hardlink(INDEX_BLOCK * idx,const leMFT_REF ref_parent,MFT_RECORD * m_file,const leMFT_REF ref_file,const s64 allocated_size,const s64 data_size,const FILE_ATTR_FLAGS flags,const u16 packed_ea_size,const u32 reparse_point_tag,const char * file_name,const FILE_NAME_TYPE_FLAGS file_name_type)2864 static int create_hardlink(INDEX_BLOCK *idx, const leMFT_REF ref_parent,
2865 		MFT_RECORD *m_file, const leMFT_REF ref_file,
2866 		const s64 allocated_size, const s64 data_size,
2867 		const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
2868 		const u32 reparse_point_tag, const char *file_name,
2869 		const FILE_NAME_TYPE_FLAGS file_name_type)
2870 {
2871 	FILE_NAME_ATTR *fn;
2872 	int i, fn_size;
2873 	ntfschar *uname;
2874 
2875 	/* Create the file_name attribute. */
2876 	i = (strlen(file_name) + 1) * sizeof(ntfschar);
2877 	fn_size = sizeof(FILE_NAME_ATTR) + i;
2878 	fn = ntfs_malloc(fn_size);
2879 	if (!fn)
2880 		return -errno;
2881 	fn->parent_directory = ref_parent;
2882 	/* FIXME: Is this correct? Or do we have to copy the creation_time */
2883 	/* from the std info? */
2884 	fn->creation_time = utc2ntfs(mkntfs_time());
2885 	fn->last_data_change_time = fn->creation_time;
2886 	fn->last_mft_change_time = fn->creation_time;
2887 	fn->last_access_time = fn->creation_time;
2888 	fn->allocated_size = cpu_to_sle64(allocated_size);
2889 	fn->data_size = cpu_to_sle64(data_size);
2890 	fn->file_attributes = flags;
2891 	/* These are in a union so can't have both. */
2892 	if (packed_ea_size && reparse_point_tag) {
2893 		free(fn);
2894 		return -EINVAL;
2895 	}
2896 	if (packed_ea_size) {
2897 		fn->u.s.packed_ea_size = cpu_to_le16(packed_ea_size);
2898 		fn->u.s.reserved = cpu_to_le16(0);
2899 	} else {
2900 		fn->u.reparse_point_tag = cpu_to_le32(reparse_point_tag);
2901 	}
2902 	fn->file_name_type = file_name_type;
2903 	uname = fn->file_name;
2904 	i = ntfs_mbstoucs(file_name, &uname, i);
2905 	if (i < 1) {
2906 		free(fn);
2907 		return -EINVAL;
2908 	}
2909 	if (i > 0xff) {
2910 		free(fn);
2911 		return -ENAMETOOLONG;
2912 	}
2913 	/* No terminating null in file names. */
2914 	fn->file_name_length = i;
2915 	fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
2916 	/* Increment the link count of @m_file. */
2917 	i = le16_to_cpu(m_file->link_count);
2918 	if (i == 0xffff) {
2919 		ntfs_log_error("Too many hardlinks present already.\n");
2920 		free(fn);
2921 		return -EINVAL;
2922 	}
2923 	m_file->link_count = cpu_to_le16(i + 1);
2924 	/* Add the file_name to @m_file. */
2925 	i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0, 0,
2926 			0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
2927 	if (i < 0) {
2928 		ntfs_log_error("create_hardlink failed adding file name attribute: "
2929 				"%s\n", strerror(-i));
2930 		free(fn);
2931 		/* Undo link count increment. */
2932 		m_file->link_count = cpu_to_le16(
2933 				le16_to_cpu(m_file->link_count) - 1);
2934 		return i;
2935 	}
2936 	/* Insert the index entry for file_name in @idx. */
2937 	i = insert_file_link_in_dir_index(idx, ref_file, fn, fn_size);
2938 	if (i < 0) {
2939 		ntfs_log_error("create_hardlink failed inserting index entry: %s\n",
2940 				strerror(-i));
2941 		/* FIXME: Remove the file name attribute from @m_file. */
2942 		free(fn);
2943 		/* Undo link count increment. */
2944 		m_file->link_count = cpu_to_le16(
2945 				le16_to_cpu(m_file->link_count) - 1);
2946 		return i;
2947 	}
2948 	free(fn);
2949 	return 0;
2950 }
2951 
2952 #ifdef ENABLE_UUID
2953 
2954 /**
2955  * index_obj_id_insert
2956  *
2957  * Insert an index entry with the key @guid and data pointing to the mft record
2958  * @ref in the $O index root of the mft record @m (which must be the mft record
2959  * for $ObjId).
2960  *
2961  * Return 0 on success or -errno on error.
2962  */
index_obj_id_insert(MFT_RECORD * m,const GUID * guid,const leMFT_REF ref)2963 static int index_obj_id_insert(MFT_RECORD *m, const GUID *guid,
2964 		const leMFT_REF ref)
2965 {
2966 	INDEX_ENTRY *idx_entry_new;
2967 	int data_ofs, idx_size, err;
2968 	OBJ_ID_INDEX_DATA *oi;
2969 
2970 	/*
2971 	 * Insert the index entry for the object id in the index.
2972 	 *
2973 	 * First determine the size of the index entry to be inserted.  This
2974 	 * consists of the index entry header, followed by the index key, i.e.
2975 	 * the GUID, followed by the index data, i.e. OBJ_ID_INDEX_DATA.
2976 	 */
2977 	data_ofs = (sizeof(INDEX_ENTRY_HEADER) + sizeof(GUID) + 7) & ~7;
2978 	idx_size = (data_ofs + sizeof(OBJ_ID_INDEX_DATA) + 7) & ~7;
2979 	idx_entry_new = ntfs_calloc(idx_size);
2980 	if (!idx_entry_new)
2981 		return -errno;
2982 	idx_entry_new->u.s.data_offset = cpu_to_le16(data_ofs);
2983 	idx_entry_new->u.s.data_length = cpu_to_le16(sizeof(OBJ_ID_INDEX_DATA));
2984 	idx_entry_new->length = cpu_to_le16(idx_size);
2985 	idx_entry_new->key_length = cpu_to_le16(sizeof(GUID));
2986 	idx_entry_new->key.object_id = *guid;
2987 	oi = (OBJ_ID_INDEX_DATA*)((u8*)idx_entry_new + data_ofs);
2988 	oi->mft_reference = ref;
2989 	err = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size, m,
2990 			NTFS_INDEX_O, 2, AT_UNUSED);
2991 	free(idx_entry_new);
2992 	if (err < 0) {
2993 		ntfs_log_error("index_obj_id_insert failed inserting index "
2994 				"entry: %s\n", strerror(-err));
2995 		return err;
2996 	}
2997 	return 0;
2998 }
2999 
3000 #endif
3001 
3002 /**
3003  * mkntfs_cleanup
3004  */
mkntfs_cleanup(void)3005 static void mkntfs_cleanup(void)
3006 {
3007 	/* Close the volume */
3008 	if (g_vol) {
3009 		if (g_vol->u.dev) {
3010 			if (NDevOpen(g_vol->u.dev) && g_vol->u.dev->d_ops->close(g_vol->u.dev))
3011 				ntfs_log_perror("Warning: Could not close %s", g_vol->u.dev->d_name);
3012 			ntfs_device_free(g_vol->u.dev);
3013 		}
3014 		free(g_vol->vol_name);
3015 		free(g_vol->attrdef);
3016 		free(g_vol->upcase);
3017 		free(g_vol);
3018 		g_vol = NULL;
3019 	}
3020 
3021 	/* Free any memory we've used */
3022 	free(g_bad_blocks);	g_bad_blocks	= NULL;
3023 	free(g_buf);		g_buf		= NULL;
3024 	free(g_index_block);	g_index_block	= NULL;
3025 	free(g_lcn_bitmap);	g_lcn_bitmap	= NULL;
3026 	free(g_mft_bitmap);	g_mft_bitmap	= NULL;
3027 	free(g_rl_bad);		g_rl_bad	= NULL;
3028 	free(g_rl_boot);	g_rl_boot	= NULL;
3029 	free(g_rl_logfile);	g_rl_logfile	= NULL;
3030 	free(g_rl_mft);		g_rl_mft	= NULL;
3031 	free(g_rl_mft_bmp);	g_rl_mft_bmp	= NULL;
3032 	free(g_rl_mftmirr);	g_rl_mftmirr	= NULL;
3033 }
3034 
3035 
3036 /**
3037  * mkntfs_open_partition -
3038  */
mkntfs_open_partition(ntfs_volume * vol)3039 static BOOL mkntfs_open_partition(ntfs_volume *vol)
3040 {
3041 	BOOL result = FALSE;
3042 	int i;
3043 	struct stat sbuf;
3044 	unsigned long mnt_flags;
3045 
3046 	/*
3047 	 * Allocate and initialize an ntfs device structure and attach it to
3048 	 * the volume.
3049 	 */
3050 	vol->u.dev = ntfs_device_alloc(opts.dev_name, 0, &ntfs_device_default_io_ops, NULL);
3051 	if (!vol->u.dev) {
3052 		ntfs_log_perror("Could not create device");
3053 		goto done;
3054 	}
3055 
3056 	/* Open the device for reading or reading and writing. */
3057 	if (opts.no_action) {
3058 		ntfs_log_quiet("Running in READ-ONLY mode!\n");
3059 		i = O_RDONLY;
3060 	} else {
3061 		i = O_RDWR;
3062 	}
3063 	if (vol->u.dev->d_ops->open(vol->u.dev, i)) {
3064 		if (errno == ENOENT)
3065 			ntfs_log_error("The device doesn't exist; did you specify it correctly?\n");
3066 		else
3067 			ntfs_log_perror("Could not open %s", vol->u.dev->d_name);
3068 		goto done;
3069 	}
3070 	/* Verify we are dealing with a block device. */
3071 	if (vol->u.dev->d_ops->stat(vol->u.dev, &sbuf)) {
3072 		ntfs_log_perror("Error getting information about %s", vol->u.dev->d_name);
3073 		goto done;
3074 	}
3075 
3076 	if (!S_ISBLK(sbuf.st_mode)) {
3077 		ntfs_log_error("%s is not a block device.\n", vol->u.dev->d_name);
3078 		if (!opts.force) {
3079 			ntfs_log_error("Refusing to make a filesystem here!\n");
3080 			goto done;
3081 		}
3082 		if (!opts.num_sectors) {
3083 			if (!sbuf.st_size && !sbuf.st_blocks) {
3084 				ntfs_log_error("You must specify the number of sectors.\n");
3085 				goto done;
3086 			}
3087 			if (opts.sector_size) {
3088 				if (sbuf.st_size)
3089 					opts.num_sectors = sbuf.st_size / opts.sector_size;
3090 				else
3091 					opts.num_sectors = ((s64)sbuf.st_blocks << 9) / opts.sector_size;
3092 			} else {
3093 				if (sbuf.st_size)
3094 					opts.num_sectors = sbuf.st_size / 512;
3095 				else
3096 					opts.num_sectors = sbuf.st_blocks;
3097 				opts.sector_size = 512;
3098 			}
3099 		}
3100 		ntfs_log_warning("mkntfs forced anyway.\n");
3101 #ifdef HAVE_LINUX_MAJOR_H
3102 	} else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
3103 			MINOR(sbuf.st_rdev) % 64 == 0) ||
3104 			(SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
3105 			MINOR(sbuf.st_rdev) % 16 == 0)) {
3106 		ntfs_log_error("%s is entire device, not just one partition.\n", vol->u.dev->d_name);
3107 		if (!opts.force) {
3108 			ntfs_log_error("Refusing to make a filesystem here!\n");
3109 			goto done;
3110 		}
3111 		ntfs_log_warning("mkntfs forced anyway.\n");
3112 #endif
3113 	}
3114 	/* Make sure the file system is not mounted. */
3115 	if (ntfs_check_if_mounted(vol->u.dev->d_name, &mnt_flags)) {
3116 		ntfs_log_perror("Failed to determine whether %s is mounted", vol->u.dev->d_name);
3117 	} else if (mnt_flags & NTFS_MF_MOUNTED) {
3118 		ntfs_log_error("%s is mounted.\n", vol->u.dev->d_name);
3119 		if (!opts.force) {
3120 			ntfs_log_error("Refusing to make a filesystem here!\n");
3121 			goto done;
3122 		}
3123 		ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is incorrect.\n");
3124 	}
3125 	result = TRUE;
3126 done:
3127 	return result;
3128 }
3129 
3130 /**
3131  * mkntfs_get_page_size - detect the system's memory page size.
3132  */
mkntfs_get_page_size(void)3133 static long mkntfs_get_page_size(void)
3134 {
3135 	long page_size;
3136 #ifdef _SC_PAGESIZE
3137 	page_size = sysconf(_SC_PAGESIZE);
3138 	if (page_size < 0)
3139 #endif
3140 #ifdef _SC_PAGE_SIZE
3141 		page_size = sysconf(_SC_PAGE_SIZE);
3142 	if (page_size < 0)
3143 #endif
3144 	{
3145 		ntfs_log_warning("Failed to determine system page size.  "
3146 				"Assuming safe default of 4096 bytes.\n");
3147 		return 4096;
3148 	}
3149 	ntfs_log_debug("System page size is %li bytes.\n", page_size);
3150 	return page_size;
3151 }
3152 
3153 /**
3154  * mkntfs_override_vol_params -
3155  */
mkntfs_override_vol_params(ntfs_volume * vol)3156 static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
3157 {
3158 	s64 volume_size;
3159 	long page_size;
3160 	int i;
3161 	BOOL winboot = TRUE;
3162 
3163 	/* If user didn't specify the sector size, determine it now. */
3164 	if (opts.sector_size < 0) {
3165 		opts.sector_size = ntfs_device_sector_size_get(vol->u.dev);
3166 		if (opts.sector_size < 0) {
3167 			ntfs_log_warning("The sector size was not specified "
3168 				"for %s and it could not be obtained "
3169 				"automatically.  It has been set to 512 "
3170 				"bytes.\n", vol->u.dev->d_name);
3171 			opts.sector_size = 512;
3172 		}
3173 	}
3174 	/* Validate sector size. */
3175 	if ((opts.sector_size - 1) & opts.sector_size) {
3176 		ntfs_log_error("The sector size is invalid.  It must be a "
3177 			"power of two, e.g. 512, 1024.\n");
3178 		return FALSE;
3179 	}
3180 	if (opts.sector_size < 256 || opts.sector_size > 4096) {
3181 		ntfs_log_error("The sector size is invalid.  The minimum size "
3182 			"is 256 bytes and the maximum is 4096 bytes.\n");
3183 		return FALSE;
3184 	}
3185 	ntfs_log_debug("sector size = %ld bytes\n", opts.sector_size);
3186 	/* Now set the device block size to the sector size. */
3187 	if (ntfs_device_block_size_set(vol->u.dev, opts.sector_size))
3188 		ntfs_log_debug("Failed to set the device block size to the "
3189 				"sector size.  This may cause problems when "
3190 				"creating the backup boot sector and also may "
3191 				"affect performance but should be harmless "
3192 				"otherwise.  Error: %s\n", strerror(errno));
3193 	/* If user didn't specify the number of sectors, determine it now. */
3194 	if (opts.num_sectors < 0) {
3195 		opts.num_sectors = ntfs_device_size_get(vol->u.dev,
3196 				opts.sector_size);
3197 		if (opts.num_sectors <= 0) {
3198 			ntfs_log_error("Couldn't determine the size of %s.  "
3199 				"Please specify the number of sectors "
3200 				"manually.\n", vol->u.dev->d_name);
3201 			return FALSE;
3202 		}
3203 	}
3204 	ntfs_log_debug("number of sectors = %lld (0x%llx)\n", opts.num_sectors,
3205 			opts.num_sectors);
3206 	/*
3207 	 * Reserve the last sector for the backup boot sector unless the
3208 	 * sector size is less than 512 bytes in which case reserve 512 bytes
3209 	 * worth of sectors.
3210 	 */
3211 	i = 1;
3212 	if (opts.sector_size < 512)
3213 		i = 512 / opts.sector_size;
3214 	opts.num_sectors -= i;
3215 	/* If user didn't specify the partition start sector, determine it. */
3216 	if (opts.part_start_sect < 0) {
3217 		opts.part_start_sect = ntfs_device_partition_start_sector_get(
3218 				vol->u.dev);
3219 		if (opts.part_start_sect < 0) {
3220 			ntfs_log_warning("The partition start sector was not "
3221 				"specified for %s and it could not be obtained "
3222 				"automatically.  It has been set to 0.\n",
3223 				vol->u.dev->d_name);
3224 			opts.part_start_sect = 0;
3225 			winboot = FALSE;
3226 		} else if (opts.part_start_sect >> 32) {
3227 			ntfs_log_warning("The partition start sector specified "
3228 				"for %s and the automatically determined value "
3229 				"is too large.  It has been set to 0.\n",
3230 				vol->u.dev->d_name);
3231 			opts.part_start_sect = 0;
3232 			winboot = FALSE;
3233 		}
3234 	} else if (opts.part_start_sect >> 32) {
3235 		ntfs_log_error("Invalid partition start sector.  Maximum is "
3236 			"4294967295 (2^32-1).\n");
3237 		return FALSE;
3238 	}
3239 	/* If user didn't specify the sectors per track, determine it now. */
3240 	if (opts.sectors_per_track < 0) {
3241 		opts.sectors_per_track = ntfs_device_sectors_per_track_get(
3242 				vol->u.dev);
3243 		if (opts.sectors_per_track < 0) {
3244 			ntfs_log_warning("The number of sectors per track was "
3245 				"not specified for %s and it could not be "
3246 				"obtained automatically.  It has been set to "
3247 				"0.\n", vol->u.dev->d_name);
3248 			opts.sectors_per_track = 0;
3249 			winboot = FALSE;
3250 		} else if (opts.sectors_per_track > 65535) {
3251 			ntfs_log_warning("The number of sectors per track was "
3252 				"not specified for %s and the automatically "
3253 				"determined value is too large.  It has been "
3254 				"set to 0.\n", vol->u.dev->d_name);
3255 			opts.sectors_per_track = 0;
3256 			winboot = FALSE;
3257 		}
3258 	} else if (opts.sectors_per_track > 65535) {
3259 		ntfs_log_error("Invalid number of sectors per track.  Maximum "
3260 			"is 65535.\n");
3261 		return FALSE;
3262 	}
3263 	/* If user didn't specify the number of heads, determine it now. */
3264 	if (opts.heads < 0) {
3265 		opts.heads = ntfs_device_heads_get(vol->u.dev);
3266 		if (opts.heads < 0) {
3267 			ntfs_log_warning("The number of heads was not "
3268 				"specified for %s and it could not be obtained "
3269 				"automatically.  It has been set to 0.\n",
3270 				vol->u.dev->d_name);
3271 			opts.heads = 0;
3272 			winboot = FALSE;
3273 		} else if (opts.heads > 65535) {
3274 			ntfs_log_warning("The number of heads was not "
3275 				"specified for %s and the automatically "
3276 				"determined value is too large.  It has been "
3277 				"set to 0.\n", vol->u.dev->d_name);
3278 			opts.heads = 0;
3279 			winboot = FALSE;
3280 		}
3281 	} else if (opts.heads > 65535) {
3282 		ntfs_log_error("Invalid number of heads.  Maximum is 65535.\n");
3283 		return FALSE;
3284 	}
3285 	volume_size = opts.num_sectors * opts.sector_size;
3286 	/* Validate volume size. */
3287 	if (volume_size < (1 << 20)) {			/* 1MiB */
3288 		ntfs_log_error("Device is too small (%llikiB).  Minimum NTFS "
3289 				"volume size is 1MiB.\n", volume_size / 1024);
3290 		return FALSE;
3291 	}
3292 	ntfs_log_debug("volume size = %llikiB\n", volume_size / 1024);
3293 	/* If user didn't specify the cluster size, determine it now. */
3294 	if (!vol->cluster_size) {
3295 		/*
3296 		 * Windows Vista always uses 4096 bytes as the default cluster
3297 		 * size regardless of the volume size so we do it, too.
3298 		 */
3299 		vol->cluster_size = 4096;
3300 		/* For small volumes on devices with large sector sizes. */
3301 		if (vol->cluster_size < (u32)opts.sector_size)
3302 			vol->cluster_size = opts.sector_size;
3303 		/*
3304 		 * For huge volumes, grow the cluster size until the number of
3305 		 * clusters fits into 32 bits or the cluster size exceeds the
3306 		 * maximum limit of 64kiB.
3307 		 */
3308 		while (volume_size >> (ffs(vol->cluster_size) - 1 + 32)) {
3309 			vol->cluster_size <<= 1;
3310 			if (vol->cluster_size > 65535) {
3311 				ntfs_log_error("Device is too large to hold an "
3312 						"NTFS volume (maximum size is "
3313 						"256TiB).\n");
3314 				return FALSE;
3315 			}
3316 		}
3317 		ntfs_log_quiet("Cluster size has been automatically set to %u "
3318 				"bytes.\n", (unsigned)vol->cluster_size);
3319 	}
3320 	/* Validate cluster size. */
3321 	if (vol->cluster_size & (vol->cluster_size - 1)) {
3322 		ntfs_log_error("The cluster size is invalid.  It must be a "
3323 				"power of two, e.g. 1024, 4096.\n");
3324 		return FALSE;
3325 	}
3326 	if (vol->cluster_size < (u32)opts.sector_size) {
3327 		ntfs_log_error("The cluster size is invalid.  It must be equal "
3328 				"to, or larger than, the sector size.\n");
3329 		return FALSE;
3330 	}
3331 	if (vol->cluster_size > 128 * (u32)opts.sector_size) {
3332 		ntfs_log_error("The cluster size is invalid.  It cannot be "
3333 				"more that 128 times the size of the sector "
3334 				"size.\n");
3335 		return FALSE;
3336 	}
3337 	if (vol->cluster_size > 65536) {
3338 		ntfs_log_error("The cluster size is invalid.  The maximum "
3339 			"cluster size is 65536 bytes (64kiB).\n");
3340 		return FALSE;
3341 	}
3342 	vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
3343 	ntfs_log_debug("cluster size = %u bytes\n",
3344 			(unsigned int)vol->cluster_size);
3345 	if (vol->cluster_size > 4096) {
3346 		if (opts.enable_compression) {
3347 			if (!opts.force) {
3348 				ntfs_log_error("Windows cannot use compression "
3349 						"when the cluster size is "
3350 						"larger than 4096 bytes.\n");
3351 				return FALSE;
3352 			}
3353 			opts.enable_compression = 0;
3354 		}
3355 		ntfs_log_warning("Windows cannot use compression when the "
3356 				"cluster size is larger than 4096 bytes.  "
3357 				"Compression has been disabled for this "
3358 				"volume.\n");
3359 	}
3360 	vol->nr_clusters = volume_size / vol->cluster_size;
3361 	/*
3362 	 * Check the cluster_size and num_sectors for consistency with
3363 	 * sector_size and num_sectors. And check both of these for consistency
3364 	 * with volume_size.
3365 	 */
3366 	if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) /
3367 			vol->cluster_size) ||
3368 			(volume_size / opts.sector_size) != opts.num_sectors ||
3369 			(volume_size / vol->cluster_size) !=
3370 			vol->nr_clusters)) {
3371 		/* XXX is this code reachable? */
3372 		ntfs_log_error("Illegal combination of volume/cluster/sector "
3373 				"size and/or cluster/sector number.\n");
3374 		return FALSE;
3375 	}
3376 	ntfs_log_debug("number of clusters = %llu (0x%llx)\n",
3377 			vol->nr_clusters, vol->nr_clusters);
3378 	/* Number of clusters must fit within 32 bits (Win2k limitation). */
3379 	if (vol->nr_clusters >> 32) {
3380 		if (vol->cluster_size >= 65536) {
3381 			ntfs_log_error("Device is too large to hold an NTFS "
3382 					"volume (maximum size is 256TiB).\n");
3383 			return FALSE;
3384 		}
3385 		ntfs_log_error("Number of clusters exceeds 32 bits.  Please "
3386 				"try again with a larger\ncluster size or "
3387 				"leave the cluster size unspecified and the "
3388 				"smallest possible cluster size for the size "
3389 				"of the device will be used.\n");
3390 		return FALSE;
3391 	}
3392 	page_size = mkntfs_get_page_size();
3393 	/*
3394 	 * Set the mft record size.  By default this is 1024 but it has to be
3395 	 * at least as big as a sector and not bigger than a page on the system
3396 	 * or the NTFS kernel driver will not be able to mount the volume.
3397 	 * TODO: The mft record size should be user specifiable just like the
3398 	 * "inode size" can be specified on other Linux/Unix file systems.
3399 	 */
3400 	vol->mft_record_size = 1024;
3401 	if (vol->mft_record_size < (u32)opts.sector_size)
3402 		vol->mft_record_size = opts.sector_size;
3403 	if (vol->mft_record_size > (unsigned long)page_size)
3404 		ntfs_log_warning("Mft record size (%u bytes) exceeds system "
3405 				"page size (%li bytes).  You will not be able "
3406 				"to mount this volume using the NTFS kernel "
3407 				"driver.\n", (unsigned)vol->mft_record_size,
3408 				page_size);
3409 	vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
3410 	ntfs_log_debug("mft record size = %u bytes\n",
3411 			(unsigned)vol->mft_record_size);
3412 	/*
3413 	 * Set the index record size.  By default this is 4096 but it has to be
3414 	 * at least as big as a sector and not bigger than a page on the system
3415 	 * or the NTFS kernel driver will not be able to mount the volume.
3416 	 * FIXME: Should we make the index record size to be user specifiable?
3417 	 */
3418 	vol->indx_record_size = 4096;
3419 	if (vol->indx_record_size < (u32)opts.sector_size)
3420 		vol->indx_record_size = opts.sector_size;
3421 	if (vol->indx_record_size > (unsigned long)page_size)
3422 		ntfs_log_warning("Index record size (%u bytes) exceeds system "
3423 				"page size (%li bytes).  You will not be able "
3424 				"to mount this volume using the NTFS kernel "
3425 				"driver.\n", (unsigned)vol->indx_record_size,
3426 				page_size);
3427 	vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
3428 	ntfs_log_debug("index record size = %u bytes\n",
3429 			(unsigned)vol->indx_record_size);
3430 	if (!winboot) {
3431 		ntfs_log_warning("To boot from a device, Windows needs the "
3432 				"'partition start sector', the 'sectors per "
3433 				"track' and the 'number of heads' to be "
3434 				"set.\n");
3435 		ntfs_log_warning("Windows will not be able to boot from this "
3436 				"device.\n");
3437 	}
3438 	return TRUE;
3439 }
3440 
3441 /**
3442  * mkntfs_initialize_bitmaps -
3443  */
mkntfs_initialize_bitmaps(void)3444 static BOOL mkntfs_initialize_bitmaps(void)
3445 {
3446 	u64 i;
3447 	int mft_bitmap_size;
3448 
3449 	/* Determine lcn bitmap byte size and allocate it. */
3450 	g_lcn_bitmap_byte_size = (g_vol->nr_clusters + 7) >> 3;
3451 	/* Needs to be multiple of 8 bytes. */
3452 	g_lcn_bitmap_byte_size = (g_lcn_bitmap_byte_size + 7) & ~7;
3453 	i = (g_lcn_bitmap_byte_size + g_vol->cluster_size - 1) &
3454 			~(g_vol->cluster_size - 1);
3455 	ntfs_log_debug("g_lcn_bitmap_byte_size = %i, allocated = %llu\n",
3456 			g_lcn_bitmap_byte_size, i);
3457 	g_lcn_bitmap = ntfs_calloc(g_lcn_bitmap_byte_size);
3458 	if (!g_lcn_bitmap)
3459 		return FALSE;
3460 	/*
3461 	 * $Bitmap can overlap the end of the volume. Any bits in this region
3462 	 * must be set. This region also encompasses the backup boot sector.
3463 	 */
3464 	for (i = g_vol->nr_clusters; i < (u64)g_lcn_bitmap_byte_size << 3; i++)
3465 		ntfs_bit_set(g_lcn_bitmap, i, 1);
3466 	/*
3467 	 * Mft size is 27 (NTFS 3.0+) mft records or one cluster, whichever is
3468 	 * bigger.
3469 	 */
3470 	g_mft_size = 27;
3471 	g_mft_size *= g_vol->mft_record_size;
3472 	if (g_mft_size < (s32)g_vol->cluster_size)
3473 		g_mft_size = g_vol->cluster_size;
3474 	ntfs_log_debug("MFT size = %i (0x%x) bytes\n", g_mft_size, g_mft_size);
3475 	/* Determine mft bitmap size and allocate it. */
3476 	mft_bitmap_size = g_mft_size / g_vol->mft_record_size;
3477 	/* Convert to bytes, at least one. */
3478 	g_mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
3479 	/* Mft bitmap is allocated in multiples of 8 bytes. */
3480 	g_mft_bitmap_byte_size = (g_mft_bitmap_byte_size + 7) & ~7;
3481 	ntfs_log_debug("mft_bitmap_size = %i, g_mft_bitmap_byte_size = %i\n",
3482 			mft_bitmap_size, g_mft_bitmap_byte_size);
3483 	g_mft_bitmap = ntfs_calloc(g_mft_bitmap_byte_size);
3484 	if (!g_mft_bitmap)
3485 		return FALSE;
3486 	/* Create runlist for mft bitmap. */
3487 	g_rl_mft_bmp = ntfs_malloc(2 * sizeof(runlist));
3488 	if (!g_rl_mft_bmp)
3489 		return FALSE;
3490 
3491 	g_rl_mft_bmp[0].vcn = 0LL;
3492 	/* Mft bitmap is right after $Boot's data. */
3493 	i = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
3494 	g_rl_mft_bmp[0].lcn = i;
3495 	/*
3496 	 * Size is always one cluster, even though valid data size and
3497 	 * initialized data size are only 8 bytes.
3498 	 */
3499 	g_rl_mft_bmp[1].vcn = 1LL;
3500 	g_rl_mft_bmp[0].length = 1LL;
3501 	g_rl_mft_bmp[1].lcn = -1LL;
3502 	g_rl_mft_bmp[1].length = 0LL;
3503 	/* Allocate cluster for mft bitmap. */
3504 	ntfs_bit_set(g_lcn_bitmap, i, 1);
3505 	return TRUE;
3506 }
3507 
3508 /**
3509  * mkntfs_initialize_rl_mft -
3510  */
mkntfs_initialize_rl_mft(void)3511 static BOOL mkntfs_initialize_rl_mft(void)
3512 {
3513 	int i, j;
3514 
3515 	/* If user didn't specify the mft lcn, determine it now. */
3516 	if (!g_mft_lcn) {
3517 		/*
3518 		 * We start at the higher value out of 16kiB and just after the
3519 		 * mft bitmap.
3520 		 */
3521 		g_mft_lcn = g_rl_mft_bmp[0].lcn + g_rl_mft_bmp[0].length;
3522 		if (g_mft_lcn * g_vol->cluster_size < 16 * 1024)
3523 			g_mft_lcn = (16 * 1024 + g_vol->cluster_size - 1) /
3524 					g_vol->cluster_size;
3525 	}
3526 	ntfs_log_debug("$MFT logical cluster number = 0x%llx\n", g_mft_lcn);
3527 	/* Determine MFT zone size. */
3528 	g_mft_zone_end = g_vol->nr_clusters;
3529 	switch (opts.mft_zone_multiplier) {  /* % of volume size in clusters */
3530 	case 4:
3531 		g_mft_zone_end = g_mft_zone_end >> 1;	/* 50%   */
3532 		break;
3533 	case 3:
3534 		g_mft_zone_end = g_mft_zone_end * 3 >> 3;/* 37.5% */
3535 		break;
3536 	case 2:
3537 		g_mft_zone_end = g_mft_zone_end >> 2;	/* 25%   */
3538 		break;
3539 	case 1:
3540 	default:
3541 		g_mft_zone_end = g_mft_zone_end >> 3;	/* 12.5% */
3542 		break;
3543 	}
3544 	ntfs_log_debug("MFT zone size = %lldkiB\n", g_mft_zone_end <<
3545 			g_vol->cluster_size_bits >> 10 /* >> 10 == / 1024 */);
3546 	/*
3547 	 * The mft zone begins with the mft data attribute, not at the beginning
3548 	 * of the device.
3549 	 */
3550 	g_mft_zone_end += g_mft_lcn;
3551 	/* Create runlist for mft. */
3552 	g_rl_mft = ntfs_malloc(2 * sizeof(runlist));
3553 	if (!g_rl_mft)
3554 		return FALSE;
3555 
3556 	g_rl_mft[0].vcn = 0LL;
3557 	g_rl_mft[0].lcn = g_mft_lcn;
3558 	/* rounded up division by cluster size */
3559 	j = (g_mft_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
3560 	g_rl_mft[1].vcn = j;
3561 	g_rl_mft[0].length = j;
3562 	g_rl_mft[1].lcn = -1LL;
3563 	g_rl_mft[1].length = 0LL;
3564 	/* Allocate clusters for mft. */
3565 	for (i = 0; i < j; i++)
3566 		ntfs_bit_set(g_lcn_bitmap, g_mft_lcn + i, 1);
3567 	/* Determine mftmirr_lcn (middle of volume). */
3568 	g_mftmirr_lcn = (opts.num_sectors * opts.sector_size >> 1)
3569 			/ g_vol->cluster_size;
3570 	ntfs_log_debug("$MFTMirr logical cluster number = 0x%llx\n",
3571 			g_mftmirr_lcn);
3572 	/* Create runlist for mft mirror. */
3573 	g_rl_mftmirr = ntfs_malloc(2 * sizeof(runlist));
3574 	if (!g_rl_mftmirr)
3575 		return FALSE;
3576 
3577 	g_rl_mftmirr[0].vcn = 0LL;
3578 	g_rl_mftmirr[0].lcn = g_mftmirr_lcn;
3579 	/*
3580 	 * The mft mirror is either 4kb (the first four records) or one cluster
3581 	 * in size, which ever is bigger. In either case, it contains a
3582 	 * byte-for-byte identical copy of the beginning of the mft (i.e. either
3583 	 * the first four records (4kb) or the first cluster worth of records,
3584 	 * whichever is bigger).
3585 	 */
3586 	j = (4 * g_vol->mft_record_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
3587 	g_rl_mftmirr[1].vcn = j;
3588 	g_rl_mftmirr[0].length = j;
3589 	g_rl_mftmirr[1].lcn = -1LL;
3590 	g_rl_mftmirr[1].length = 0LL;
3591 	/* Allocate clusters for mft mirror. */
3592 	for (i = 0; i < j; i++)
3593 		ntfs_bit_set(g_lcn_bitmap, g_mftmirr_lcn + i, 1);
3594 	g_logfile_lcn = g_mftmirr_lcn + j;
3595 	ntfs_log_debug("$LogFile logical cluster number = 0x%llx\n",
3596 			g_logfile_lcn);
3597 	return TRUE;
3598 }
3599 
3600 /**
3601  * mkntfs_initialize_rl_logfile -
3602  */
mkntfs_initialize_rl_logfile(void)3603 static BOOL mkntfs_initialize_rl_logfile(void)
3604 {
3605 	int i, j;
3606 	u64 volume_size;
3607 
3608 	/* Create runlist for log file. */
3609 	g_rl_logfile = ntfs_malloc(2 * sizeof(runlist));
3610 	if (!g_rl_logfile)
3611 		return FALSE;
3612 
3613 
3614 	volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
3615 
3616 	g_rl_logfile[0].vcn = 0LL;
3617 	g_rl_logfile[0].lcn = g_logfile_lcn;
3618 	/*
3619 	 * Determine logfile_size from volume_size (rounded up to a cluster),
3620 	 * making sure it does not overflow the end of the volume.
3621 	 */
3622 	if (volume_size < 2048LL * 1024)		/* < 2MiB	*/
3623 		g_logfile_size = 256LL * 1024;		/*   -> 256kiB	*/
3624 	else if (volume_size < 4000000LL)		/* < 4MB	*/
3625 		g_logfile_size = 512LL * 1024;		/*   -> 512kiB	*/
3626 	else if (volume_size <= 200LL * 1024 * 1024)	/* < 200MiB	*/
3627 		g_logfile_size = 2048LL * 1024;		/*   -> 2MiB	*/
3628 	else	{
3629 		/*
3630 		 * FIXME: The $LogFile size is 64 MiB upwards from 12GiB but
3631 		 * the "200" divider below apparently approximates "100" or
3632 		 * some other value as the volume size decreases. For example:
3633 		 *      Volume size   LogFile size    Ratio
3634 		 *	  8799808        46048       191.100
3635 		 *	  8603248        45072       190.877
3636 		 *	  7341704        38768       189.375
3637 		 *	  6144828        32784       187.433
3638 		 *	  4192932        23024       182.111
3639 		 */
3640 		if (volume_size >= 12LL << 30)		/* > 12GiB	*/
3641 			g_logfile_size = 64 << 20;	/*   -> 64MiB	*/
3642 		else
3643 			g_logfile_size = (volume_size / 200) &
3644 					~(g_vol->cluster_size - 1);
3645 	}
3646 	j = g_logfile_size / g_vol->cluster_size;
3647 	while (g_rl_logfile[0].lcn + j >= g_vol->nr_clusters) {
3648 		/*
3649 		 * $Logfile would overflow volume. Need to make it smaller than
3650 		 * the standard size. It's ok as we are creating a non-standard
3651 		 * volume anyway if it is that small.
3652 		 */
3653 		g_logfile_size >>= 1;
3654 		j = g_logfile_size / g_vol->cluster_size;
3655 	}
3656 	g_logfile_size = (g_logfile_size + g_vol->cluster_size - 1) &
3657 			~(g_vol->cluster_size - 1);
3658 	ntfs_log_debug("$LogFile (journal) size = %ikiB\n",
3659 			g_logfile_size / 1024);
3660 	/*
3661 	 * FIXME: The 256kiB limit is arbitrary. Should find out what the real
3662 	 * minimum requirement for Windows is so it doesn't blue screen.
3663 	 */
3664 	if (g_logfile_size < 256 << 10) {
3665 		ntfs_log_error("$LogFile would be created with invalid size. "
3666 				"This is not allowed as it would cause Windows "
3667 				"to blue screen and during boot.\n");
3668 		return FALSE;
3669 	}
3670 	g_rl_logfile[1].vcn = j;
3671 	g_rl_logfile[0].length = j;
3672 	g_rl_logfile[1].lcn = -1LL;
3673 	g_rl_logfile[1].length = 0LL;
3674 	/* Allocate clusters for log file. */
3675 	for (i = 0; i < j; i++)
3676 		ntfs_bit_set(g_lcn_bitmap, g_logfile_lcn + i, 1);
3677 	return TRUE;
3678 }
3679 
3680 /**
3681  * mkntfs_initialize_rl_boot -
3682  */
mkntfs_initialize_rl_boot(void)3683 static BOOL mkntfs_initialize_rl_boot(void)
3684 {
3685 	int i, j;
3686 	/* Create runlist for $Boot. */
3687 	g_rl_boot = ntfs_malloc(2 * sizeof(runlist));
3688 	if (!g_rl_boot)
3689 		return FALSE;
3690 
3691 	g_rl_boot[0].vcn = 0LL;
3692 	g_rl_boot[0].lcn = 0LL;
3693 	/*
3694 	 * $Boot is always 8192 (0x2000) bytes or 1 cluster, whichever is
3695 	 * bigger.
3696 	 */
3697 	j = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
3698 	g_rl_boot[1].vcn = j;
3699 	g_rl_boot[0].length = j;
3700 	g_rl_boot[1].lcn = -1LL;
3701 	g_rl_boot[1].length = 0LL;
3702 	/* Allocate clusters for $Boot. */
3703 	for (i = 0; i < j; i++)
3704 		ntfs_bit_set(g_lcn_bitmap, 0LL + i, 1);
3705 	return TRUE;
3706 }
3707 
3708 /**
3709  * mkntfs_initialize_rl_bad -
3710  */
mkntfs_initialize_rl_bad(void)3711 static BOOL mkntfs_initialize_rl_bad(void)
3712 {
3713 	/* Create runlist for $BadClus, $DATA named stream $Bad. */
3714 	g_rl_bad = ntfs_malloc(2 * sizeof(runlist));
3715 	if (!g_rl_bad)
3716 		return FALSE;
3717 
3718 	g_rl_bad[0].vcn = 0LL;
3719 	g_rl_bad[0].lcn = -1LL;
3720 	/*
3721 	 * $BadClus named stream $Bad contains the whole volume as a single
3722 	 * sparse runlist entry.
3723 	 */
3724 	g_rl_bad[1].vcn = g_vol->nr_clusters;
3725 	g_rl_bad[0].length = g_vol->nr_clusters;
3726 	g_rl_bad[1].lcn = -1LL;
3727 	g_rl_bad[1].length = 0LL;
3728 
3729 	/* TODO: Mark bad blocks as such. */
3730 	return TRUE;
3731 }
3732 
3733 /**
3734  * mkntfs_fill_device_with_zeroes -
3735  */
mkntfs_fill_device_with_zeroes(void)3736 static BOOL mkntfs_fill_device_with_zeroes(void)
3737 {
3738 	/*
3739 	 * If not quick format, fill the device with 0s.
3740 	 * FIXME: Except bad blocks! (AIA)
3741 	 */
3742 	int i;
3743 	ssize_t bw;
3744 	unsigned long long position;
3745 	float progress_inc = (float)g_vol->nr_clusters / 100;
3746 	u64 volume_size;
3747 
3748 	volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
3749 
3750 	ntfs_log_progress("Initializing device with zeroes:   0%%");
3751 	for (position = 0; position < (unsigned long long)g_vol->nr_clusters;
3752 			position++) {
3753 		if (!(position % (int)(progress_inc+1))) {
3754 			ntfs_log_progress("\b\b\b\b%3.0f%%", position /
3755 					progress_inc);
3756 		}
3757 		bw = mkntfs_write(g_vol->u.dev, g_buf, g_vol->cluster_size);
3758 		if (bw != (ssize_t)g_vol->cluster_size) {
3759 			if (bw != -1 || errno != EIO) {
3760 				ntfs_log_error("This should not happen.\n");
3761 				return FALSE;
3762 			}
3763 			if (!position) {
3764 				ntfs_log_error("Error: Cluster zero is bad. "
3765 					"Cannot create NTFS file "
3766 					"system.\n");
3767 				return FALSE;
3768 			}
3769 			/* Add the baddie to our bad blocks list. */
3770 			if (!append_to_bad_blocks(position))
3771 				return FALSE;
3772 			ntfs_log_quiet("\nFound bad cluster (%lld). Adding to "
3773 				"list of bad blocks.\nInitializing "
3774 				"device with zeroes: %3.0f%%", position,
3775 				position / progress_inc);
3776 			/* Seek to next cluster. */
3777 			g_vol->u.dev->d_ops->seek(g_vol->u.dev,
3778 					((off_t)position + 1) *
3779 					g_vol->cluster_size, SEEK_SET);
3780 		}
3781 	}
3782 	ntfs_log_progress("\b\b\b\b100%%");
3783 	position = (volume_size & (g_vol->cluster_size - 1)) /
3784 			opts.sector_size;
3785 	for (i = 0; (unsigned long)i < position; i++) {
3786 		bw = mkntfs_write(g_vol->u.dev, g_buf, opts.sector_size);
3787 		if (bw != opts.sector_size) {
3788 			if (bw != -1 || errno != EIO) {
3789 				ntfs_log_error("This should not happen.\n");
3790 				return FALSE;
3791 			} else if (i + 1ull == position) {
3792 				ntfs_log_error("Error: Bad cluster found in "
3793 					"location reserved for system "
3794 					"file $Boot.\n");
3795 				return FALSE;
3796 			}
3797 			/* Seek to next sector. */
3798 			g_vol->u.dev->d_ops->seek(g_vol->u.dev,
3799 					opts.sector_size, SEEK_CUR);
3800 		}
3801 	}
3802 	ntfs_log_progress(" - Done.\n");
3803 	return TRUE;
3804 }
3805 
3806 /**
3807  * mkntfs_sync_index_record
3808  *
3809  * (ERSO) made a function out of this, but the reason for doing that
3810  * disappeared during coding....
3811  */
mkntfs_sync_index_record(INDEX_ALLOCATION * idx,MFT_RECORD * m,ntfschar * name,u32 name_len)3812 static BOOL mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m,
3813 		ntfschar* name, u32 name_len)
3814 {
3815 	int i, err;
3816 	ntfs_attr_search_ctx *ctx;
3817 	ATTR_RECORD *a;
3818 	long long lw;
3819 	runlist	*rl_index = NULL;
3820 
3821 	i = 5 * sizeof(ntfschar);
3822 	ctx = ntfs_attr_get_search_ctx(NULL, m);
3823 	if (!ctx) {
3824 		ntfs_log_perror("Failed to allocate attribute search context");
3825 		return FALSE;
3826 	}
3827 	/* FIXME: This should be IGNORE_CASE! */
3828 	if (mkntfs_attr_lookup(AT_INDEX_ALLOCATION, name, name_len, 0, 0,
3829 			NULL, 0, ctx)) {
3830 		ntfs_attr_put_search_ctx(ctx);
3831 		ntfs_log_error("BUG: $INDEX_ALLOCATION attribute not found.\n");
3832 		return FALSE;
3833 	}
3834 	a = ctx->attr;
3835 	rl_index = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
3836 	if (!rl_index) {
3837 		ntfs_attr_put_search_ctx(ctx);
3838 		ntfs_log_error("Failed to decompress runlist of $INDEX_ALLOCATION "
3839 				"attribute.\n");
3840 		return FALSE;
3841 	}
3842 	if (sle64_to_cpu(a->u.nonres.initialized_size) < i) {
3843 		ntfs_attr_put_search_ctx(ctx);
3844 		free(rl_index);
3845 		ntfs_log_error("BUG: $INDEX_ALLOCATION attribute too short.\n");
3846 		return FALSE;
3847 	}
3848 	ntfs_attr_put_search_ctx(ctx);
3849 	i = sizeof(INDEX_BLOCK) - sizeof(INDEX_HEADER) +
3850 			le32_to_cpu(idx->index.allocated_size);
3851 	err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)idx, i);
3852 	if (err) {
3853 		free(rl_index);
3854 		ntfs_log_error("ntfs_mst_pre_write_fixup() failed while "
3855 			"syncing index block.\n");
3856 		return FALSE;
3857 	}
3858 	lw = ntfs_rlwrite(g_vol->u.dev, rl_index, (u8*)idx, i, NULL);
3859 	free(rl_index);
3860 	if (lw != i) {
3861 		ntfs_log_error("Error writing $INDEX_ALLOCATION.\n");
3862 		return FALSE;
3863 	}
3864 	/* No more changes to @idx below here so no need for fixup: */
3865 	/* ntfs_mst_post_write_fixup((NTFS_RECORD*)idx); */
3866 	return TRUE;
3867 }
3868 
3869 /**
3870  * create_file_volume -
3871  */
create_file_volume(MFT_RECORD * m,leMFT_REF root_ref,VOLUME_FLAGS fl,const GUID * volume_guid)3872 static BOOL create_file_volume(MFT_RECORD *m, leMFT_REF root_ref,
3873 		VOLUME_FLAGS fl, const GUID *volume_guid
3874 #ifndef ENABLE_UUID
3875 		__attribute__((unused))
3876 #endif
3877 		)
3878 {
3879 	int i, err;
3880 	u8 *sd;
3881 
3882 	ntfs_log_verbose("Creating $Volume (mft record 3)\n");
3883 	m = (MFT_RECORD*)(g_buf + 3 * g_vol->mft_record_size);
3884 	err = create_hardlink(g_index_block, root_ref, m,
3885 			MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL,
3886 			FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
3887 			"$Volume", FILE_NAME_WIN32_AND_DOS);
3888 	if (!err) {
3889 		init_system_file_sd(FILE_Volume, &sd, &i);
3890 		err = add_attr_sd(m, sd, i);
3891 	}
3892 	if (!err)
3893 		err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
3894 	if (!err)
3895 		err = add_attr_vol_name(m, g_vol->vol_name, g_vol->vol_name ?
3896 				strlen(g_vol->vol_name) : 0);
3897 	if (!err) {
3898 		if (fl & VOLUME_IS_DIRTY)
3899 			ntfs_log_quiet("Setting the volume dirty so check "
3900 					"disk runs on next reboot into "
3901 					"Windows.\n");
3902 		err = add_attr_vol_info(m, fl, g_vol->major_ver,
3903 				g_vol->minor_ver);
3904 	}
3905 #ifdef ENABLE_UUID
3906 	if (!err)
3907 		err = add_attr_object_id(m, volume_guid);
3908 #endif
3909 	if (err < 0) {
3910 		ntfs_log_error("Couldn't create $Volume: %s\n",
3911 				strerror(-err));
3912 		return FALSE;
3913 	}
3914 	return TRUE;
3915 }
3916 
3917 /**
3918  * create_backup_boot_sector
3919  *
3920  * Return 0 on success or -1 if it couldn't be created.
3921  */
create_backup_boot_sector(u8 * buff)3922 static int create_backup_boot_sector(u8 *buff)
3923 {
3924 	const char *s;
3925 	ssize_t bw;
3926 	int size, e;
3927 
3928 	ntfs_log_verbose("Creating backup boot sector.\n");
3929 	/*
3930 	 * Write the first max(512, opts.sector_size) bytes from buf to the
3931 	 * last sector, but limit that to 8192 bytes of written data since that
3932 	 * is how big $Boot is (and how big our buffer is)..
3933 	 */
3934 	size = 512;
3935 	if (size < opts.sector_size)
3936 		size = opts.sector_size;
3937 	if (size < opts.cluster_size)
3938 		size = opts.cluster_size;
3939 	if (g_vol->u.dev->d_ops->seek(g_vol->u.dev, (opts.num_sectors + 1) *
3940 			opts.sector_size - size, SEEK_SET) == (off_t)-1) {
3941 		ntfs_log_perror("Seek failed");
3942 		goto bb_err;
3943 	}
3944 	if (size > 8192)
3945 		size = 8192;
3946 	bw = mkntfs_write(g_vol->u.dev, buff, size);
3947 	if (bw == size)
3948 		return 0;
3949 	e = errno;
3950 	if (bw == -1LL)
3951 		s = strerror(e);
3952 	else
3953 		s = "unknown error";
3954 	/* At least some 2.4 kernels return EIO instead of ENOSPC. */
3955 	if (bw != -1LL || (bw == -1LL && e != ENOSPC && e != EIO)) {
3956 		ntfs_log_critical("Couldn't write backup boot sector: %s\n", s);
3957 		return -1;
3958 	}
3959 bb_err:
3960 	ntfs_log_error("Couldn't write backup boot sector. This is due to a "
3961 			"limitation in the\nLinux kernel. This is not a major "
3962 			"problem as Windows check disk will create the\n"
3963 			"backup boot sector when it is run on your next boot "
3964 			"into Windows.\n");
3965 	return -1;
3966 }
3967 
3968 /**
3969  * mkntfs_create_root_structures -
3970  */
mkntfs_create_root_structures(void)3971 static BOOL mkntfs_create_root_structures(void)
3972 {
3973 	NTFS_BOOT_SECTOR *bs;
3974 	MFT_RECORD *m;
3975 	leMFT_REF root_ref;
3976 	leMFT_REF extend_ref;
3977 	int i;
3978 	int j;
3979 	int err;
3980 	u8 *sd;
3981 	FILE_ATTR_FLAGS extend_flags;
3982 	VOLUME_FLAGS volume_flags = 0;
3983 	int nr_sysfiles;
3984 	u8 *buf_log = NULL;
3985 	int buf_sds_first_size;
3986 	char *buf_sds;
3987 
3988 	ntfs_log_quiet("Creating NTFS volume structures.\n");
3989 	nr_sysfiles = 27;
3990 	/*
3991 	 * Setup an empty mft record.  Note, we can just give 0 as the mft
3992 	 * reference as we are creating an NTFS 1.2 volume for which the mft
3993 	 * reference is ignored by ntfs_mft_record_layout().
3994 	 *
3995 	 * Copy the mft record onto all 16 records in the buffer and setup the
3996 	 * sequence numbers of each system file to equal the mft record number
3997 	 * of that file (only for $MFT is the sequence number 1 rather than 0).
3998 	 */
3999 	for (i = 0; i < nr_sysfiles; i++) {
4000 		if (ntfs_mft_record_layout(g_vol, 0, m = (MFT_RECORD *)(g_buf +
4001 				i * g_vol->mft_record_size))) {
4002 			ntfs_log_error("Failed to layout system mft records."
4003 					"\n");
4004 			return FALSE;
4005 		}
4006 		if (i == 0 || i > 23)
4007 			m->sequence_number = cpu_to_le16(1);
4008 		else
4009 			m->sequence_number = cpu_to_le16(i);
4010 	}
4011 	/*
4012 	 * If only one cluster contains all system files then
4013 	 * fill the rest of it with empty, formatted records.
4014 	 */
4015 	if (nr_sysfiles * (s32)g_vol->mft_record_size < g_mft_size) {
4016 		for (i = nr_sysfiles;
4017 		      i * (s32)g_vol->mft_record_size < g_mft_size; i++) {
4018 			m = (MFT_RECORD *)(g_buf + i * g_vol->mft_record_size);
4019 			if (ntfs_mft_record_layout(g_vol, 0, m)) {
4020 				ntfs_log_error("Failed to layout mft record."
4021 						"\n");
4022 				return FALSE;
4023 			}
4024 			m->flags = cpu_to_le16(0);
4025 			m->sequence_number = cpu_to_le16(i);
4026 		}
4027 	}
4028 	/*
4029 	 * Create the 16 system files, adding the system information attribute
4030 	 * to each as well as marking them in use in the mft bitmap.
4031 	 */
4032 	for (i = 0; i < nr_sysfiles; i++) {
4033 		le32 file_attrs;
4034 
4035 		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
4036 		if (i < 16 || i > 23) {
4037 			m->mft_record_number = cpu_to_le32(i);
4038 			m->flags |= MFT_RECORD_IN_USE;
4039 			ntfs_bit_set(g_mft_bitmap, 0LL + i, 1);
4040 		}
4041 		file_attrs = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM;
4042 		if (i == FILE_root) {
4043 			file_attrs |= FILE_ATTR_ARCHIVE;
4044 			if (opts.disable_indexing)
4045 				file_attrs |= FILE_ATTR_NOT_CONTENT_INDEXED;
4046 			if (opts.enable_compression)
4047 				file_attrs |= FILE_ATTR_COMPRESSED;
4048 		}
4049 		/* setting specific security_id flag and */
4050 		/* file permissions for ntfs 3.x */
4051 		if (i == 0 || i == 1 || i == 2 || i == 6 || i == 8 ||
4052 				i == 10) {
4053 			add_attr_std_info(m, file_attrs,
4054 				cpu_to_le32(0x0100));
4055 		} else if (i == 9) {
4056 			file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
4057 			add_attr_std_info(m, file_attrs,
4058 				cpu_to_le32(0x0101));
4059 		} else if (i == 11) {
4060 			add_attr_std_info(m, file_attrs,
4061 				cpu_to_le32(0x0101));
4062 		} else if (i == 24 || i == 25 || i == 26) {
4063 			file_attrs |= FILE_ATTR_ARCHIVE;
4064 			file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
4065 			add_attr_std_info(m, file_attrs,
4066 				cpu_to_le32(0x0101));
4067 		} else {
4068 			add_attr_std_info(m, file_attrs,
4069 				cpu_to_le32(0x00));
4070 		}
4071 	}
4072 	/* The root directory mft reference. */
4073 	root_ref = MK_LE_MREF(FILE_root, FILE_root);
4074 	extend_ref = MK_LE_MREF(11,11);
4075 	ntfs_log_verbose("Creating root directory (mft record 5)\n");
4076 	m = (MFT_RECORD*)(g_buf + 5 * g_vol->mft_record_size);
4077 	m->flags |= MFT_RECORD_IS_DIRECTORY;
4078 	m->link_count = cpu_to_le16(le16_to_cpu(m->link_count) + 1);
4079 	err = add_attr_file_name(m, root_ref, 0LL, 0LL,
4080 			FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
4081 			FILE_ATTR_I30_INDEX_PRESENT, 0, 0, ".",
4082 			FILE_NAME_WIN32_AND_DOS);
4083 	if (!err) {
4084 		init_root_sd(&sd, &i);
4085 		err = add_attr_sd(m, sd, i);
4086 	}
4087 	/* FIXME: This should be IGNORE_CASE */
4088 	if (!err)
4089 		err = add_attr_index_root(m, "$I30", 4, 0, AT_FILE_NAME,
4090 				COLLATION_FILE_NAME, g_vol->indx_record_size);
4091 	/* FIXME: This should be IGNORE_CASE */
4092 	if (!err)
4093 		err = upgrade_to_large_index(m, "$I30", 4, 0, &g_index_block);
4094 	if (!err) {
4095 		ntfs_attr_search_ctx *ctx;
4096 		ATTR_RECORD *a;
4097 		ctx = ntfs_attr_get_search_ctx(NULL, m);
4098 		if (!ctx) {
4099 			ntfs_log_perror("Failed to allocate attribute search "
4100 					"context");
4101 			return FALSE;
4102 		}
4103 		/* There is exactly one file name so this is ok. */
4104 		if (mkntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL,
4105 				0, ctx)) {
4106 			ntfs_attr_put_search_ctx(ctx);
4107 			ntfs_log_error("BUG: $FILE_NAME attribute not found."
4108 					"\n");
4109 			return FALSE;
4110 		}
4111 		a = ctx->attr;
4112 		err = insert_file_link_in_dir_index(g_index_block, root_ref,
4113 				(FILE_NAME_ATTR*)((char*)a +
4114 				le16_to_cpu(a->u.res.value_offset)),
4115 				le32_to_cpu(a->u.res.value_length));
4116 		ntfs_attr_put_search_ctx(ctx);
4117 	}
4118 	if (err) {
4119 		ntfs_log_error("Couldn't create root directory: %s\n",
4120 			strerror(-err));
4121 		return FALSE;
4122 	}
4123 	/* Add all other attributes, on a per-file basis for clarity. */
4124 	ntfs_log_verbose("Creating $MFT (mft record 0)\n");
4125 	m = (MFT_RECORD*)g_buf;
4126 	err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_mft, g_buf,
4127 			g_mft_size);
4128 	if (!err)
4129 		err = create_hardlink(g_index_block, root_ref, m,
4130 				MK_LE_MREF(FILE_MFT, 1), g_mft_size,
4131 				g_mft_size, FILE_ATTR_HIDDEN |
4132 				FILE_ATTR_SYSTEM, 0, 0, "$MFT",
4133 				FILE_NAME_WIN32_AND_DOS);
4134 	/* mft_bitmap is not modified in mkntfs; no need to sync it later. */
4135 	if (!err)
4136 		err = add_attr_bitmap_positioned(m, NULL, 0, 0, g_rl_mft_bmp,
4137 				g_mft_bitmap, g_mft_bitmap_byte_size);
4138 	if (err < 0) {
4139 		ntfs_log_error("Couldn't create $MFT: %s\n", strerror(-err));
4140 		return FALSE;
4141 	}
4142 	ntfs_log_verbose("Creating $MFTMirr (mft record 1)\n");
4143 	m = (MFT_RECORD*)(g_buf + 1 * g_vol->mft_record_size);
4144 	err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_mftmirr, g_buf,
4145 			g_rl_mftmirr[0].length * g_vol->cluster_size);
4146 	if (!err)
4147 		err = create_hardlink(g_index_block, root_ref, m,
4148 				MK_LE_MREF(FILE_MFTMirr, FILE_MFTMirr),
4149 				g_rl_mftmirr[0].length * g_vol->cluster_size,
4150 				g_rl_mftmirr[0].length * g_vol->cluster_size,
4151 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4152 				"$MFTMirr", FILE_NAME_WIN32_AND_DOS);
4153 	if (err < 0) {
4154 		ntfs_log_error("Couldn't create $MFTMirr: %s\n",
4155 				strerror(-err));
4156 		return FALSE;
4157 	}
4158 	ntfs_log_verbose("Creating $LogFile (mft record 2)\n");
4159 	m = (MFT_RECORD*)(g_buf + 2 * g_vol->mft_record_size);
4160 	buf_log = ntfs_malloc(g_logfile_size);
4161 	if (!buf_log)
4162 		return FALSE;
4163 	memset(buf_log, -1, g_logfile_size);
4164 	err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_logfile, buf_log,
4165 			g_logfile_size);
4166 	free(buf_log);
4167 	buf_log = NULL;
4168 	if (!err)
4169 		err = create_hardlink(g_index_block, root_ref, m,
4170 				MK_LE_MREF(FILE_LogFile, FILE_LogFile),
4171 				g_logfile_size, g_logfile_size,
4172 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4173 				"$LogFile", FILE_NAME_WIN32_AND_DOS);
4174 	if (err < 0) {
4175 		ntfs_log_error("Couldn't create $LogFile: %s\n",
4176 				strerror(-err));
4177 		return FALSE;
4178 	}
4179 	ntfs_log_verbose("Creating $AttrDef (mft record 4)\n");
4180 	m = (MFT_RECORD*)(g_buf + 4 * g_vol->mft_record_size);
4181 	err = add_attr_data(m, NULL, 0, 0, 0, (u8*)g_vol->attrdef,
4182 			g_vol->attrdef_len);
4183 	if (!err)
4184 		err = create_hardlink(g_index_block, root_ref, m,
4185 				MK_LE_MREF(FILE_AttrDef, FILE_AttrDef),
4186 				(g_vol->attrdef_len + g_vol->cluster_size - 1) &
4187 				~(g_vol->cluster_size - 1), g_vol->attrdef_len,
4188 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4189 				"$AttrDef", FILE_NAME_WIN32_AND_DOS);
4190 	if (!err) {
4191 		init_system_file_sd(FILE_AttrDef, &sd, &i);
4192 		err = add_attr_sd(m, sd, i);
4193 	}
4194 	if (err < 0) {
4195 		ntfs_log_error("Couldn't create $AttrDef: %s\n",
4196 				strerror(-err));
4197 		return FALSE;
4198 	}
4199 	ntfs_log_verbose("Creating $Bitmap (mft record 6)\n");
4200 	m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
4201 	/* the data attribute of $Bitmap must be non-resident or otherwise */
4202 	/* windows 2003 will regard the volume as corrupt (ERSO) */
4203 	if (!err)
4204 		err = insert_non_resident_attr_in_mft_record(m,
4205 			AT_DATA,  NULL, 0, 0, 0,
4206 			g_lcn_bitmap, g_lcn_bitmap_byte_size);
4207 
4208 
4209 	if (!err)
4210 		err = create_hardlink(g_index_block, root_ref, m,
4211 				MK_LE_MREF(FILE_Bitmap, FILE_Bitmap),
4212 				(g_lcn_bitmap_byte_size + g_vol->cluster_size -
4213 				1) & ~(g_vol->cluster_size - 1),
4214 				g_lcn_bitmap_byte_size,
4215 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4216 				"$Bitmap", FILE_NAME_WIN32_AND_DOS);
4217 	if (err < 0) {
4218 		ntfs_log_error("Couldn't create $Bitmap: %s\n", strerror(-err));
4219 		return FALSE;
4220 	}
4221 	ntfs_log_verbose("Creating $Boot (mft record 7)\n");
4222 	m = (MFT_RECORD*)(g_buf + 7 * g_vol->mft_record_size);
4223 	bs = ntfs_calloc(8192);
4224 	if (!bs)
4225 		return FALSE;
4226 	memcpy(bs, boot_array, sizeof(boot_array));
4227 	/*
4228 	 * Create the boot sector in bs. Note, that bs is already zeroed
4229 	 * in the boot sector section and that it has the NTFS OEM id/magic
4230 	 * already inserted, so no need to worry about these things.
4231 	 */
4232 	bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size);
4233 	bs->bpb.sectors_per_cluster = (u8)(g_vol->cluster_size /
4234 			opts.sector_size);
4235 	bs->bpb.media_type = 0xf8; /* hard disk */
4236 	bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
4237 	ntfs_log_debug("sectors per track = %ld (0x%lx)\n",
4238 			opts.sectors_per_track, opts.sectors_per_track);
4239 	bs->bpb.heads = cpu_to_le16(opts.heads);
4240 	ntfs_log_debug("heads = %ld (0x%lx)\n", opts.heads, opts.heads);
4241 	bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect);
4242 	ntfs_log_debug("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
4243 			opts.part_start_sect);
4244 	bs->physical_drive = 0x80;  	    /* boot from hard disk */
4245 	bs->extended_boot_signature = 0x80; /* everybody sets this, so we do */
4246 	bs->number_of_sectors = cpu_to_sle64(opts.num_sectors);
4247 	bs->mft_lcn = cpu_to_sle64(g_mft_lcn);
4248 	bs->mftmirr_lcn = cpu_to_sle64(g_mftmirr_lcn);
4249 	if (g_vol->mft_record_size >= g_vol->cluster_size) {
4250 		bs->clusters_per_mft_record = g_vol->mft_record_size /
4251 			g_vol->cluster_size;
4252 	} else {
4253 		bs->clusters_per_mft_record = -(ffs(g_vol->mft_record_size) -
4254 				1);
4255 		if ((u32)(1 << -bs->clusters_per_mft_record) !=
4256 				g_vol->mft_record_size) {
4257 			free(bs);
4258 			ntfs_log_error("BUG: calculated clusters_per_mft_record"
4259 					" is wrong (= 0x%x)\n",
4260 					bs->clusters_per_mft_record);
4261 			return FALSE;
4262 		}
4263 	}
4264 	ntfs_log_debug("clusters per mft record = %i (0x%x)\n",
4265 			bs->clusters_per_mft_record,
4266 			bs->clusters_per_mft_record);
4267 	if (g_vol->indx_record_size >= g_vol->cluster_size) {
4268 		bs->clusters_per_index_record = g_vol->indx_record_size /
4269 			g_vol->cluster_size;
4270 	} else {
4271 		bs->clusters_per_index_record = -g_vol->indx_record_size_bits;
4272 		if ((1 << -bs->clusters_per_index_record) !=
4273 				(s32)g_vol->indx_record_size) {
4274 			free(bs);
4275 			ntfs_log_error("BUG: calculated "
4276 					"clusters_per_index_record is wrong "
4277 					"(= 0x%x)\n",
4278 					bs->clusters_per_index_record);
4279 			return FALSE;
4280 		}
4281 	}
4282 	ntfs_log_debug("clusters per index block = %i (0x%x)\n",
4283 			bs->clusters_per_index_record,
4284 			bs->clusters_per_index_record);
4285 	/* Generate a 64-bit random number for the serial number. */
4286 	bs->volume_serial_number = cpu_to_le64(((u64)random() << 32) |
4287 			((u64)random() & 0xffffffff));
4288 	/*
4289 	 * Leave zero for now as NT4 leaves it zero, too. If want it later, see
4290 	 * ../libntfs/bootsect.c for how to calculate it.
4291 	 */
4292 	bs->checksum = cpu_to_le32(0);
4293 	/* Make sure the bootsector is ok. */
4294 	if (!ntfs_boot_sector_is_ntfs(bs, TRUE)) {
4295 		free(bs);
4296 		ntfs_log_error("FATAL: Generated boot sector is invalid!\n");
4297 		return FALSE;
4298 	}
4299 	err = add_attr_data_positioned(m, NULL, 0, 0, 0, g_rl_boot, (u8*)bs,
4300 			8192);
4301 	if (!err)
4302 		err = create_hardlink(g_index_block, root_ref, m,
4303 				MK_LE_MREF(FILE_Boot, FILE_Boot),
4304 				(8192 + g_vol->cluster_size - 1) &
4305 				~(g_vol->cluster_size - 1), 8192,
4306 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4307 				"$Boot", FILE_NAME_WIN32_AND_DOS);
4308 	if (!err) {
4309 		init_system_file_sd(FILE_Boot, &sd, &i);
4310 		err = add_attr_sd(m, sd, i);
4311 	}
4312 	if (err < 0) {
4313 		free(bs);
4314 		ntfs_log_error("Couldn't create $Boot: %s\n", strerror(-err));
4315 		return FALSE;
4316 	}
4317 	if (create_backup_boot_sector((u8*)bs)) {
4318 		/*
4319 		 * Pre-2.6 kernels couldn't access the last sector if it was
4320 		 * odd and we failed to set the device block size to the sector
4321 		 * size, hence we schedule chkdsk to create it.
4322 		 */
4323 		volume_flags |= VOLUME_IS_DIRTY;
4324 	}
4325 	free(bs);
4326 #ifdef ENABLE_UUID
4327 	/*
4328 	 * We cheat a little here and if the user has requested all times to be
4329 	 * set to zero then we set the GUID to zero as well.  This options is
4330 	 * only used for development purposes so that should be fine.
4331 	 */
4332 	if (!opts.use_epoch_time) {
4333 		/* Generate a GUID for the volume. */
4334 		uuid_generate((void*)&g_vol->guid);
4335 	} else
4336 		memset(&g_vol->guid, 0, sizeof(g_vol->guid));
4337 #endif
4338 	if (!create_file_volume(m, root_ref, volume_flags, &g_vol->guid))
4339 		return FALSE;
4340 	ntfs_log_verbose("Creating $BadClus (mft record 8)\n");
4341 	m = (MFT_RECORD*)(g_buf + 8 * g_vol->mft_record_size);
4342 	/* FIXME: This should be IGNORE_CASE */
4343 	/* Create a sparse named stream of size equal to the volume size. */
4344 	err = add_attr_data_positioned(m, "$Bad", 4, 0, 0, g_rl_bad, NULL,
4345 			g_vol->nr_clusters * g_vol->cluster_size);
4346 	if (!err) {
4347 		err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
4348 	}
4349 	if (!err) {
4350 		err = create_hardlink(g_index_block, root_ref, m,
4351 				MK_LE_MREF(FILE_BadClus, FILE_BadClus),
4352 				0LL, 0LL, FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM,
4353 				0, 0, "$BadClus", FILE_NAME_WIN32_AND_DOS);
4354 	}
4355 	if (err < 0) {
4356 		ntfs_log_error("Couldn't create $BadClus: %s\n",
4357 				strerror(-err));
4358 		return FALSE;
4359 	}
4360 	/* create $Secure (NTFS 3.0+) */
4361 	ntfs_log_verbose("Creating $Secure (mft record 9)\n");
4362 	m = (MFT_RECORD*)(g_buf + 9 * g_vol->mft_record_size);
4363 	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
4364 	if (!err)
4365 		err = create_hardlink(g_index_block, root_ref, m,
4366 				MK_LE_MREF(9, 9), 0LL, 0LL,
4367 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
4368 				FILE_ATTR_VIEW_INDEX_PRESENT, 0, 0,
4369 				"$Secure", FILE_NAME_WIN32_AND_DOS);
4370 	buf_sds = NULL;
4371 	buf_sds_first_size = 0;
4372 	if (!err) {
4373 		int buf_sds_size;
4374 
4375 		buf_sds_first_size = 0xfc;
4376 		buf_sds_size = 0x40000 + buf_sds_first_size;
4377 		buf_sds = ntfs_calloc(buf_sds_size);
4378 		if (!buf_sds)
4379 			return FALSE;
4380 		init_secure_sds(buf_sds);
4381 		memcpy(buf_sds + 0x40000, buf_sds, buf_sds_first_size);
4382 		err = add_attr_data(m, "$SDS", 4, 0, 0, (u8*)buf_sds,
4383 				buf_sds_size);
4384 	}
4385 	/* FIXME: This should be IGNORE_CASE */
4386 	if (!err)
4387 		err = add_attr_index_root(m, "$SDH", 4, 0, AT_UNUSED,
4388 			COLLATION_NTOFS_SECURITY_HASH,
4389 			g_vol->indx_record_size);
4390 	/* FIXME: This should be IGNORE_CASE */
4391 	if (!err)
4392 		err = add_attr_index_root(m, "$SII", 4, 0, AT_UNUSED,
4393 			COLLATION_NTOFS_ULONG, g_vol->indx_record_size);
4394 	if (!err)
4395 		err = initialize_secure(buf_sds, buf_sds_first_size, m);
4396 	free(buf_sds);
4397 	if (err < 0) {
4398 		ntfs_log_error("Couldn't create $Secure: %s\n",
4399 			strerror(-err));
4400 		return FALSE;
4401 	}
4402 	ntfs_log_verbose("Creating $UpCase (mft record 0xa)\n");
4403 	m = (MFT_RECORD*)(g_buf + 0xa * g_vol->mft_record_size);
4404 	err = add_attr_data(m, NULL, 0, 0, 0, (u8*)g_vol->upcase,
4405 			g_vol->upcase_len << 1);
4406 	if (!err)
4407 		err = create_hardlink(g_index_block, root_ref, m,
4408 				MK_LE_MREF(FILE_UpCase, FILE_UpCase),
4409 				((g_vol->upcase_len << 1) +
4410 				g_vol->cluster_size - 1) &
4411 				~(g_vol->cluster_size - 1),
4412 				g_vol->upcase_len << 1,
4413 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
4414 				"$UpCase", FILE_NAME_WIN32_AND_DOS);
4415 	if (err < 0) {
4416 		ntfs_log_error("Couldn't create $UpCase: %s\n", strerror(-err));
4417 		return FALSE;
4418 	}
4419 	ntfs_log_verbose("Creating $Extend (mft record 11)\n");
4420 	/*
4421 	 * $Extend index must be resident.  Otherwise, w2k3 will regard the
4422 	 * volume as corrupt. (ERSO)
4423 	 */
4424 	m = (MFT_RECORD*)(g_buf + 11 * g_vol->mft_record_size);
4425 	m->flags |= MFT_RECORD_IS_DIRECTORY;
4426 	if (!err)
4427 		err = create_hardlink(g_index_block, root_ref, m,
4428 				MK_LE_MREF(11, 11), 0LL, 0LL,
4429 				FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
4430 				FILE_ATTR_I30_INDEX_PRESENT, 0, 0,
4431 				"$Extend", FILE_NAME_WIN32_AND_DOS);
4432 	/* FIXME: This should be IGNORE_CASE */
4433 	if (!err)
4434 		err = add_attr_index_root(m, "$I30", 4, 0, AT_FILE_NAME,
4435 			COLLATION_FILE_NAME, g_vol->indx_record_size);
4436 	if (err < 0) {
4437 		ntfs_log_error("Couldn't create $Extend: %s\n",
4438 			strerror(-err));
4439 		return FALSE;
4440 	}
4441 	/* NTFS reserved system files (mft records 0xc-0xf) */
4442 	for (i = 0xc; i < 0x10; i++) {
4443 		ntfs_log_verbose("Creating system file (mft record 0x%x)\n", i);
4444 		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
4445 		err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
4446 		if (!err) {
4447 			init_system_file_sd(i, &sd, &j);
4448 			err = add_attr_sd(m, sd, j);
4449 		}
4450 		if (err < 0) {
4451 			ntfs_log_error("Couldn't create system file %i (0x%x): "
4452 					"%s\n", i, i, strerror(-err));
4453 			return FALSE;
4454 		}
4455 	}
4456 	/* create systemfiles for ntfs volumes (3.1) */
4457 	/* starting with file 24 (ignoring file 16-23) */
4458 	extend_flags = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
4459 		FILE_ATTR_ARCHIVE | FILE_ATTR_VIEW_INDEX_PRESENT;
4460 	ntfs_log_verbose("Creating $Quota (mft record 24)\n");
4461 	m = (MFT_RECORD*)(g_buf + 24 * g_vol->mft_record_size);
4462 	m->flags |= MFT_RECORD_IS_4;
4463 	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
4464 	if (!err)
4465 		err = create_hardlink_res((MFT_RECORD*)(g_buf +
4466 			11 * g_vol->mft_record_size), extend_ref, m,
4467 			MK_LE_MREF(24, 1), 0LL, 0LL, extend_flags,
4468 			0, 0, "$Quota", FILE_NAME_WIN32_AND_DOS);
4469 	/* FIXME: This should be IGNORE_CASE */
4470 	if (!err)
4471 		err = add_attr_index_root(m, "$Q", 2, 0, AT_UNUSED,
4472 			COLLATION_NTOFS_ULONG, g_vol->indx_record_size);
4473 	/* FIXME: This should be IGNORE_CASE */
4474 	if (!err)
4475 		err = add_attr_index_root(m, "$O", 2, 0, AT_UNUSED,
4476 			COLLATION_NTOFS_SID, g_vol->indx_record_size);
4477 	if (!err)
4478 		err = initialize_quota(m);
4479 	if (err < 0) {
4480 		ntfs_log_error("Couldn't create $Quota: %s\n", strerror(-err));
4481 		return FALSE;
4482 	}
4483 	ntfs_log_verbose("Creating $ObjId (mft record 25)\n");
4484 	m = (MFT_RECORD*)(g_buf + 25 * g_vol->mft_record_size);
4485 	m->flags |= MFT_RECORD_IS_4;
4486 	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
4487 	if (!err)
4488 		err = create_hardlink_res((MFT_RECORD*)(g_buf +
4489 				11 * g_vol->mft_record_size), extend_ref,
4490 				m, MK_LE_MREF(25, 1), 0LL, 0LL,
4491 				extend_flags, 0, 0, "$ObjId",
4492 				FILE_NAME_WIN32_AND_DOS);
4493 
4494 	/* FIXME: This should be IGNORE_CASE */
4495 	if (!err)
4496 		err = add_attr_index_root(m, "$O", 2, 0, AT_UNUSED,
4497 			COLLATION_NTOFS_ULONGS,
4498 			g_vol->indx_record_size);
4499 #ifdef ENABLE_UUID
4500 	if (!err)
4501 		err = index_obj_id_insert(m, &g_vol->guid,
4502 				MK_LE_MREF(FILE_Volume, FILE_Volume));
4503 #endif
4504 	if (err < 0) {
4505 		ntfs_log_error("Couldn't create $ObjId: %s\n",
4506 				strerror(-err));
4507 		return FALSE;
4508 	}
4509 	ntfs_log_verbose("Creating $Reparse (mft record 26)\n");
4510 	m = (MFT_RECORD*)(g_buf + 26 * g_vol->mft_record_size);
4511 	m->flags |= MFT_RECORD_IS_4;
4512 	m->flags |= MFT_RECORD_IS_VIEW_INDEX;
4513 	if (!err)
4514 		err = create_hardlink_res((MFT_RECORD*)(g_buf +
4515 				11 * g_vol->mft_record_size),
4516 				extend_ref, m, MK_LE_MREF(26, 1),
4517 				0LL, 0LL, extend_flags, 0, 0,
4518 				"$Reparse", FILE_NAME_WIN32_AND_DOS);
4519 	/* FIXME: This should be IGNORE_CASE */
4520 	if (!err)
4521 		err = add_attr_index_root(m, "$R", 2, 0, AT_UNUSED,
4522 			COLLATION_NTOFS_ULONGS, g_vol->indx_record_size);
4523 	if (err < 0) {
4524 		ntfs_log_error("Couldn't create $Reparse: %s\n",
4525 			strerror(-err));
4526 		return FALSE;
4527 	}
4528 	return TRUE;
4529 }
4530 
4531 /**
4532  * mkntfs_redirect
4533  */
mkntfs_redirect(struct mkntfs_options * opts2)4534 static int mkntfs_redirect(struct mkntfs_options *opts2)
4535 {
4536 	int result = 1;
4537 	ntfs_attr_search_ctx *ctx = NULL;
4538 	long long lw, pos;
4539 	ATTR_RECORD *a;
4540 	MFT_RECORD *m;
4541 	int i, err;
4542 
4543 	if (!opts2) {
4544 		ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n");
4545 		goto done;
4546 	}
4547 	/* Initialize the random number generator with the current time. */
4548 	srandom(mkntfs_time());
4549 	/* Allocate and initialize ntfs_volume structure g_vol. */
4550 	g_vol = ntfs_volume_alloc();
4551 	if (!g_vol) {
4552 		ntfs_log_perror("Could not create volume");
4553 		goto done;
4554 	}
4555 	/* Create NTFS 3.1 (Windows XP/Vista) volumes. */
4556 	g_vol->major_ver = 3;
4557 	g_vol->minor_ver = 1;
4558 	/* Transfer some options to the volume. */
4559 	if (opts.label) {
4560 		g_vol->vol_name = strdup(opts.label);
4561 		if (!g_vol->vol_name) {
4562 			ntfs_log_perror("Could not copy volume name");
4563 			goto done;
4564 		}
4565 	}
4566 	if (opts.cluster_size >= 0)
4567 		g_vol->cluster_size = opts.cluster_size;
4568 	/* Length is in unicode characters. */
4569 	g_vol->upcase_len = 65536;
4570 	g_vol->upcase = ntfs_malloc(g_vol->upcase_len * sizeof(ntfschar));
4571 	if (!g_vol->upcase)
4572 		goto done;
4573 	ntfs_upcase_table_build(g_vol->upcase,
4574 			g_vol->upcase_len * sizeof(ntfschar));
4575 	g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array));
4576 	if (!g_vol->attrdef) {
4577 		ntfs_log_perror("Could not create attrdef structure");
4578 		goto done;
4579 	}
4580 	memcpy(g_vol->attrdef, attrdef_ntfs3x_array,
4581 			sizeof(attrdef_ntfs3x_array));
4582 	g_vol->attrdef_len = sizeof(attrdef_ntfs3x_array);
4583 	/* Open the partition. */
4584 	if (!mkntfs_open_partition(g_vol))
4585 		goto done;
4586 	/*
4587 	 * Decide on the sector size, cluster size, mft record and index record
4588 	 * sizes as well as the number of sectors/tracks/heads/size, etc.
4589 	 */
4590 	if (!mkntfs_override_vol_params(g_vol))
4591 		goto done;
4592 	/* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
4593 	if (!mkntfs_initialize_bitmaps())
4594 		goto done;
4595 	/* Initialize MFT & set g_logfile_lcn. */
4596 	if (!mkntfs_initialize_rl_mft())
4597 		goto done;
4598 	/* Initialize $LogFile. */
4599 	if (!mkntfs_initialize_rl_logfile())
4600 		goto done;
4601 	/* Initialize $Boot. */
4602 	if (!mkntfs_initialize_rl_boot())
4603 		goto done;
4604 	/* Allocate a buffer large enough to hold the mft. */
4605 	g_buf = ntfs_calloc(g_mft_size);
4606 	if (!g_buf)
4607 		goto done;
4608 	/* Create runlist for $BadClus, $DATA named stream $Bad. */
4609 	if (!mkntfs_initialize_rl_bad())
4610 		goto done;
4611 	/* If not quick format, fill the device with 0s. */
4612 	if (!opts.quick_format) {
4613 		if (!mkntfs_fill_device_with_zeroes())
4614 			goto done;
4615 	}
4616 	/* Create NTFS volume structures. */
4617 	if (!mkntfs_create_root_structures())
4618 		goto done;
4619 	/*
4620 	 * - Do not step onto bad blocks!!!
4621 	 * - If any bad blocks were specified or found, modify $BadClus,
4622 	 *   allocating the bad clusters in $Bitmap.
4623 	 * - C&w bootsector backup bootsector (backup in last sector of the
4624 	 *   partition).
4625 	 * - If NTFS 3.0+, c&w $Secure file and $Extend directory with the
4626 	 *   corresponding special files in it, i.e. $ObjId, $Quota, $Reparse,
4627 	 *   and $UsnJrnl. And others? Or not all necessary?
4628 	 * - RE: Populate $root with the system files (and $Extend directory if
4629 	 *   applicable). Possibly should move this as far to the top as
4630 	 *   possible and update during each subsequent c&w of each system file.
4631 	 */
4632 	ntfs_log_verbose("Syncing root directory index record.\n");
4633 	if (!mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 *
4634 			g_vol->mft_record_size), NTFS_INDEX_I30, 4))
4635 		goto done;
4636 
4637 	ntfs_log_verbose("Syncing $Bitmap.\n");
4638 	m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
4639 
4640 	ctx = ntfs_attr_get_search_ctx(NULL, m);
4641 	if (!ctx) {
4642 		ntfs_log_perror("Could not create an attribute search context");
4643 		goto done;
4644 	}
4645 
4646 	if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
4647 		ntfs_log_error("BUG: $DATA attribute not found.\n");
4648 		goto done;
4649 	}
4650 
4651 	a = ctx->attr;
4652 	if (a->non_resident) {
4653 		runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
4654 		if (!rl) {
4655 			ntfs_log_error("ntfs_mapping_pairs_decompress() failed\n");
4656 			goto done;
4657 		}
4658 		lw = ntfs_rlwrite(g_vol->u.dev, rl, g_lcn_bitmap, g_lcn_bitmap_byte_size, NULL);
4659 		err = errno;
4660 		free(rl);
4661 		if (lw != g_lcn_bitmap_byte_size) {
4662 			ntfs_log_error("ntfs_rlwrite: %s\n", lw == -1 ?
4663 				       strerror(err) : "unknown error");
4664 			goto done;
4665 		}
4666 	} else {
4667 		memcpy((char*)a + le16_to_cpu(a->u.res.value_offset), g_lcn_bitmap, le32_to_cpu(a->u.res.value_length));
4668 	}
4669 
4670 	/*
4671 	 * No need to sync $MFT/$BITMAP as that has never been modified since
4672 	 * its creation.
4673 	 */
4674 	ntfs_log_verbose("Syncing $MFT.\n");
4675 	pos = g_mft_lcn * g_vol->cluster_size;
4676 	lw = 1;
4677 	for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) {
4678 		if (!opts.no_action)
4679 			lw = ntfs_mst_pwrite(g_vol->u.dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
4680 		if (lw != 1) {
4681 			ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
4682 				       strerror(errno) : "unknown error");
4683 			goto done;
4684 		}
4685 		pos += g_vol->mft_record_size;
4686 	}
4687 	ntfs_log_verbose("Updating $MFTMirr.\n");
4688 	pos = g_mftmirr_lcn * g_vol->cluster_size;
4689 	lw = 1;
4690 	for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size / g_vol->mft_record_size; i++) {
4691 		m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
4692 		/*
4693 		 * Decrement the usn by one, so it becomes the same as the one
4694 		 * in $MFT once it is mst protected. - This is as we need the
4695 		 * $MFTMirr to have the exact same byte by byte content as
4696 		 * $MFT, rather than just equivalent meaning content.
4697 		 */
4698 		if (ntfs_mft_usn_dec(m)) {
4699 			ntfs_log_error("ntfs_mft_usn_dec");
4700 			goto done;
4701 		}
4702 		if (!opts.no_action)
4703 			lw = ntfs_mst_pwrite(g_vol->u.dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
4704 		if (lw != 1) {
4705 			ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
4706 				       strerror(errno) : "unknown error");
4707 			goto done;
4708 		}
4709 		pos += g_vol->mft_record_size;
4710 	}
4711 	ntfs_log_verbose("Syncing device.\n");
4712 	if (g_vol->u.dev->d_ops->sync(g_vol->u.dev)) {
4713 		ntfs_log_error("Syncing device. FAILED");
4714 		goto done;
4715 	}
4716 	ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n");
4717 	result = 0;
4718 done:
4719 	ntfs_attr_put_search_ctx(ctx);
4720 	mkntfs_cleanup();	/* Device is unlocked and closed here */
4721 	return result;
4722 }
4723 
4724 
4725 /**
4726  * main - Begin here
4727  *
4728  * Start from here.
4729  *
4730  * Return:  0  Success, the program worked
4731  *	    1  Error, something went wrong
4732  */
main(int argc,char * argv[])4733 int main(int argc, char *argv[])
4734 {
4735 	int result = 1;
4736 
4737 	ntfs_log_set_handler(ntfs_log_handler_outerr);
4738 	utils_set_locale();
4739 
4740 	mkntfs_init_options(&opts);			/* Set up the options */
4741 
4742 	if (!mkntfs_parse_options(argc, argv, &opts))	/* Read the command line options */
4743 		goto done;
4744 
4745 	result = mkntfs_redirect(&opts);
4746 done:
4747 	return result;
4748 }
4749