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