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