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