blob: 4394d5fbb670f9b0ecd860455b381e715d0b27a7 [file] [log] [blame]
Steve Kondik2111ad72013-07-07 12:07:44 -07001/**
2 * ntfsfix - Part of the Linux-NTFS project.
3 *
4 * Copyright (c) 2000-2006 Anton Altaparmakov
5 * Copyright (c) 2002-2006 Szabolcs Szakacsits
6 * Copyright (c) 2007 Yura Pakhuchiy
Steve Kondike68cb602016-08-28 00:45:36 -07007 * Copyright (c) 2011-2015 Jean-Pierre Andre
Steve Kondik2111ad72013-07-07 12:07:44 -07008 *
9 * This utility fixes some common NTFS problems, resets the NTFS journal file
10 * and schedules an NTFS consistency check for the first boot into Windows.
11 *
12 * Anton Altaparmakov <aia21@cantab.net>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program (in the main directory of the Linux-NTFS source
26 * in the file COPYING); if not, write to the Free Software Foundation,
27 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30/*
31 * WARNING: This program might not work on architectures which do not allow
32 * unaligned access. For those, the program would need to start using
33 * get/put_unaligned macros (#include <asm/unaligned.h>), but not doing it yet,
34 * since NTFS really mostly applies to ia32 only, which does allow unaligned
35 * accesses. We might not actually have a problem though, since the structs are
36 * defined as being packed so that might be enough for gcc to insert the
37 * correct code.
38 *
39 * If anyone using a non-little endian and/or an aligned access only CPU tries
40 * this program please let me know whether it works or not!
41 *
42 * Anton Altaparmakov <aia21@cantab.net>
43 */
44
45#include "config.h"
46
47#ifdef HAVE_UNISTD_H
48#include <unistd.h>
49#endif
50#ifdef HAVE_STDLIB_H
51#include <stdlib.h>
52#endif
53#ifdef HAVE_STDIO_H
54#include <stdio.h>
55#endif
56#ifdef HAVE_FCNTL_H
57#include <fcntl.h>
58#endif
59#ifdef HAVE_ERRNO_H
60#include <errno.h>
61#endif
62#ifdef HAVE_STRING_H
63#include <string.h>
64#endif
65#ifdef HAVE_GETOPT_H
66#include <getopt.h>
67#endif
68
69#include "types.h"
70#include "attrib.h"
71#include "volume.h"
72#include "bootsect.h"
73#include "mft.h"
74#include "device.h"
75#include "logfile.h"
76#include "runlist.h"
77#include "mst.h"
78#include "utils.h"
79/* #include "version.h" */
80#include "logging.h"
81#include "misc.h"
82
83#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
84# error "No default device io operations! Cannot build ntfsfix. \
85You need to run ./configure without the --disable-default-device-io-ops \
86switch if you want to be able to build the NTFS utilities."
87#endif
88
89static const char *EXEC_NAME = "ntfsfix";
90static const char OK[] = "OK\n";
91static const char FAILED[] = "FAILED\n";
92static const char FOUND[] = "FOUND\n";
93
94#define DEFAULT_SECTOR_SIZE 512
95
96static struct {
97 char *volume;
98 BOOL no_action;
99 BOOL clear_bad_sectors;
100 BOOL clear_dirty;
101} opt;
102
103/*
104 * Definitions for fixing the self-located MFT bug
105 */
106
107#define SELFLOC_LIMIT 16
108
109struct MFT_SELF_LOCATED {
110 ntfs_volume *vol;
111 MFT_RECORD *mft0;
112 MFT_RECORD *mft1;
113 MFT_RECORD *mft2;
114 ATTR_LIST_ENTRY *attrlist;
115 ATTR_LIST_ENTRY *attrlist_to_ref1;
116 MFT_REF mft_ref0;
117 MFT_REF mft_ref1;
118 LCN attrlist_lcn;
119 BOOL attrlist_resident;
120} ;
121
122/**
123 * usage
124 */
125__attribute__((noreturn))
Steve Kondik79165c32015-11-09 19:43:00 -0800126static void usage(int ret)
Steve Kondik2111ad72013-07-07 12:07:44 -0700127{
128 ntfs_log_info("%s v%s (libntfs-3g)\n"
129 "\n"
130 "Usage: %s [options] device\n"
131 " Attempt to fix an NTFS partition.\n"
132 "\n"
133 " -b, --clear-bad-sectors Clear the bad sector list\n"
134 " -d, --clear-dirty Clear the volume dirty flag\n"
135 " -h, --help Display this help\n"
136 " -n, --no-action Do not write anything\n"
137 " -V, --version Display version information\n"
138 "\n"
139 "For example: %s /dev/hda6\n\n",
140 EXEC_NAME, VERSION, EXEC_NAME,
141 EXEC_NAME);
142 ntfs_log_info("%s%s", ntfs_bugs, ntfs_home);
Steve Kondik79165c32015-11-09 19:43:00 -0800143 exit(ret);
Steve Kondik2111ad72013-07-07 12:07:44 -0700144}
145
146/**
147 * version
148 */
149__attribute__((noreturn))
150static void version(void)
151{
152 ntfs_log_info("%s v%s\n\n"
153 "Attempt to fix an NTFS partition.\n\n"
154 "Copyright (c) 2000-2006 Anton Altaparmakov\n"
155 "Copyright (c) 2002-2006 Szabolcs Szakacsits\n"
Steve Kondik79165c32015-11-09 19:43:00 -0800156 "Copyright (c) 2007 Yura Pakhuchiy\n"
Steve Kondike68cb602016-08-28 00:45:36 -0700157 "Copyright (c) 2011-2015 Jean-Pierre Andre\n\n",
Steve Kondik2111ad72013-07-07 12:07:44 -0700158 EXEC_NAME, VERSION);
159 ntfs_log_info("%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
Steve Kondik79165c32015-11-09 19:43:00 -0800160 exit(0);
Steve Kondik2111ad72013-07-07 12:07:44 -0700161}
162
163/**
164 * parse_options
165 */
166static void parse_options(int argc, char **argv)
167{
168 int c;
169 static const char *sopt = "-bdhnV";
170 static const struct option lopt[] = {
171 { "help", no_argument, NULL, 'h' },
172 { "no-action", no_argument, NULL, 'n' },
173 { "clear-bad-sectors", no_argument, NULL, 'b' },
174 { "clear-dirty", no_argument, NULL, 'd' },
175 { "version", no_argument, NULL, 'V' },
176 { NULL, 0, NULL, 0 }
177 };
178
179 memset(&opt, 0, sizeof(opt));
180
181 while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
182 switch (c) {
183 case 1: /* A non-option argument */
184 if (!opt.volume)
185 opt.volume = argv[optind - 1];
186 else {
187 ntfs_log_info("ERROR: Too many arguments.\n");
Steve Kondik79165c32015-11-09 19:43:00 -0800188 usage(1);
Steve Kondik2111ad72013-07-07 12:07:44 -0700189 }
190 break;
191 case 'b':
192 opt.clear_bad_sectors = TRUE;
193 break;
194 case 'd':
195 opt.clear_dirty = TRUE;
196 break;
197 case 'n':
198 opt.no_action = TRUE;
199 break;
200 case 'h':
Steve Kondik79165c32015-11-09 19:43:00 -0800201 usage(0);
Steve Kondik2111ad72013-07-07 12:07:44 -0700202 case '?':
Steve Kondik79165c32015-11-09 19:43:00 -0800203 usage(1);
Steve Kondik2111ad72013-07-07 12:07:44 -0700204 /* fall through */
205 case 'V':
206 version();
207 default:
208 ntfs_log_info("ERROR: Unknown option '%s'.\n", argv[optind - 1]);
Steve Kondik79165c32015-11-09 19:43:00 -0800209 usage(1);
Steve Kondik2111ad72013-07-07 12:07:44 -0700210 }
211 }
212
213 if (opt.volume == NULL) {
214 ntfs_log_info("ERROR: You must specify a device.\n");
Steve Kondik79165c32015-11-09 19:43:00 -0800215 usage(1);
Steve Kondik2111ad72013-07-07 12:07:44 -0700216 }
217}
218
219/**
220 * OLD_ntfs_volume_set_flags
221 */
222static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const le16 flags)
223{
224 MFT_RECORD *m = NULL;
225 ATTR_RECORD *a;
226 VOLUME_INFORMATION *c;
227 ntfs_attr_search_ctx *ctx;
228 int ret = -1; /* failure */
229
230 if (!vol) {
231 errno = EINVAL;
232 return -1;
233 }
234 if (ntfs_file_record_read(vol, FILE_Volume, &m, NULL)) {
235 ntfs_log_perror("Failed to read $Volume");
236 return -1;
237 }
238 /* Sanity check */
239 if (!(m->flags & MFT_RECORD_IN_USE)) {
240 ntfs_log_error("$Volume has been deleted. Cannot handle this "
241 "yet. Run chkdsk to fix this.\n");
242 errno = EIO;
243 goto err_exit;
244 }
245 /* Get a pointer to the volume information attribute. */
246 ctx = ntfs_attr_get_search_ctx(NULL, m);
247 if (!ctx) {
248 ntfs_log_debug("Failed to allocate attribute search "
249 "context.\n");
250 goto err_exit;
251 }
252 if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0,
253 CASE_SENSITIVE, 0, NULL, 0, ctx)) {
254 ntfs_log_error("Attribute $VOLUME_INFORMATION was not found in "
255 "$Volume!\n");
256 goto err_out;
257 }
258 a = ctx->attr;
259 /* Sanity check. */
260 if (a->non_resident) {
261 ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
262 "(and it isn't)!\n");
263 errno = EIO;
264 goto err_out;
265 }
266 /* Get a pointer to the value of the attribute. */
267 c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
268 /* Sanity checks. */
269 if ((char*)c + le32_to_cpu(a->value_length) >
270 (char*)m + le32_to_cpu(m->bytes_in_use) ||
271 le16_to_cpu(a->value_offset) +
272 le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
273 ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
274 "corrupt!\n");
275 errno = EIO;
276 goto err_out;
277 }
278 /* Set the volume flags. */
279 vol->flags = c->flags = flags;
280 if (ntfs_mft_record_write(vol, FILE_Volume, m)) {
281 ntfs_log_perror("Error writing $Volume");
282 goto err_out;
283 }
284 ret = 0; /* success */
285err_out:
286 ntfs_attr_put_search_ctx(ctx);
287err_exit:
288 free(m);
289 return ret;
290}
291
292/**
293 * set_dirty_flag
294 */
295static int set_dirty_flag(ntfs_volume *vol)
296{
297 le16 flags;
298
299 /* Porting note: We test for the current state of VOLUME_IS_DIRTY. This
300 * should actually be more appropriate than testing for NVolWasDirty. */
301 if (vol->flags & VOLUME_IS_DIRTY)
302 return 0;
303 ntfs_log_info("Setting required flags on partition... ");
304 /*
305 * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run
306 * and fix it for us.
307 */
308 flags = vol->flags | VOLUME_IS_DIRTY;
309 if (!opt.no_action && OLD_ntfs_volume_set_flags(vol, flags)) {
310 ntfs_log_info(FAILED);
311 ntfs_log_error("Error setting volume flags.\n");
312 return -1;
313 }
314 vol->flags = flags;
315
316 /* Porting note: libntfs-3g does not have the 'WasDirty' flag/property,
317 * and never touches the 'dirty' bit except when explicitly told to do
318 * so. Since we just wrote the VOLUME_IS_DIRTY bit to disk, and
319 * vol->flags is up-to-date, we can just ignore the NVolSetWasDirty
320 * statement. */
321 /* NVolSetWasDirty(vol); */
322
323 ntfs_log_info(OK);
324 return 0;
325}
326
327/**
328 * empty_journal
329 */
330static int empty_journal(ntfs_volume *vol)
331{
332 if (NVolLogFileEmpty(vol))
333 return 0;
334 ntfs_log_info("Going to empty the journal ($LogFile)... ");
335 if (ntfs_logfile_reset(vol)) {
336 ntfs_log_info(FAILED);
337 ntfs_log_perror("Failed to reset $LogFile");
338 return -1;
339 }
340 ntfs_log_info(OK);
341 return 0;
342}
343
344/**
345 * Clear the bad cluster marks (option)
346 */
347static int clear_badclus(ntfs_volume *vol)
348{
349 static ntfschar badstream[] = {
350 const_cpu_to_le16('$'), const_cpu_to_le16('B'),
351 const_cpu_to_le16('a'), const_cpu_to_le16('d')
352 } ;
353 ntfs_inode *ni;
354 ntfs_attr *na;
355 BOOL ok;
356
357 ok = FALSE;
358 ntfs_log_info("Going to un-mark the bad clusters ($BadClus)... ");
359 ni = ntfs_inode_open(vol, FILE_BadClus);
360 if (ni) {
361 na = ntfs_attr_open(ni, AT_DATA, badstream, 4);
362 /*
363 * chkdsk does not adjust the data size when
364 * moving clusters to $BadClus, so we have to
365 * check the runlist.
366 */
367 if (na && !ntfs_attr_map_whole_runlist(na)) {
368 if (na->rl
369 && na->rl[0].length && na->rl[1].length) {
370 /*
371 * Truncate the stream to free all its clusters,
372 * (which requires setting the data size according
373 * to allocation), then reallocate a sparse stream
374 * to full size of volume and reset the data size.
375 */
376 na->data_size = na->allocated_size;
377 na->initialized_size = na->allocated_size;
378 if (!ntfs_attr_truncate(na,0)
379 && !ntfs_attr_truncate(na,vol->nr_clusters
380 << vol->cluster_size_bits)) {
381 na->data_size = 0;
382 na->initialized_size = 0;
383 ni->flags |= FILE_ATTR_SPARSE_FILE;
384 NInoFileNameSetDirty(ni);
385 ok = TRUE;
386 } else {
387 ntfs_log_perror("Failed to un-mark the bad clusters");
388 }
389 } else {
390 ntfs_log_info("No bad clusters...");
391 ok = TRUE;
392 }
393 ntfs_attr_close(na);
394 } else {
395 ntfs_log_perror("Failed to open $BadClus::$Bad");
396 }
397 ntfs_inode_close(ni);
398 } else {
399 ntfs_log_perror("Failed to open inode FILE_BadClus");
400 }
401 if (ok)
402 ntfs_log_info(OK);
403 return (ok ? 0 : -1);
404}
405
406/**
407 * fix_mftmirr
408 */
409static int fix_mftmirr(ntfs_volume *vol)
410{
411 s64 l, br;
412 unsigned char *m, *m2;
413 int i, ret = -1; /* failure */
414 BOOL done;
415
416 ntfs_log_info("\nProcessing $MFT and $MFTMirr...\n");
417
418 /* Load data from $MFT and $MFTMirr and compare the contents. */
419 m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
420 if (!m) {
421 ntfs_log_perror("Failed to allocate memory");
422 return -1;
423 }
424 m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits);
425 if (!m2) {
426 ntfs_log_perror("Failed to allocate memory");
427 free(m);
428 return -1;
429 }
430
431 ntfs_log_info("Reading $MFT... ");
432 l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
433 vol->mft_record_size, m);
434 if (l != vol->mftmirr_size) {
435 ntfs_log_info(FAILED);
436 if (l != -1)
437 errno = EIO;
438 ntfs_log_perror("Failed to read $MFT");
439 goto error_exit;
440 }
441 ntfs_log_info(OK);
442
443 ntfs_log_info("Reading $MFTMirr... ");
444 l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
445 vol->mft_record_size, m2);
446 if (l != vol->mftmirr_size) {
447 ntfs_log_info(FAILED);
448 if (l != -1)
449 errno = EIO;
450 ntfs_log_perror("Failed to read $MFTMirr");
451 goto error_exit;
452 }
453 ntfs_log_info(OK);
454
455 /*
456 * FIXME: Need to actually check the $MFTMirr for being real. Otherwise
457 * we might corrupt the partition if someone is experimenting with
458 * software RAID and the $MFTMirr is not actually in the position we
459 * expect it to be... )-:
460 * FIXME: We should emit a warning it $MFTMirr is damaged and ask
461 * user whether to recreate it from $MFT or whether to abort. - The
462 * warning needs to include the danger of software RAID arrays.
463 * Maybe we should go as far as to detect whether we are running on a
464 * MD disk and if yes then bomb out right at the start of the program?
465 */
466
467 ntfs_log_info("Comparing $MFTMirr to $MFT... ");
468 done = FALSE;
469 for (i = 0; i < vol->mftmirr_size; ++i) {
470 MFT_RECORD *mrec, *mrec2;
471 const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
472 "$Volume", "$AttrDef", "root directory", "$Bitmap",
473 "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
474 const char *s;
475 BOOL use_mirr;
476
477 if (i < 12)
478 s = ESTR[i];
479 else if (i < 16)
480 s = "system file";
481 else
482 s = "mft record";
483
484 use_mirr = FALSE;
485 mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
486 if (mrec->flags & MFT_RECORD_IN_USE) {
487 if (ntfs_is_baad_record(mrec->magic)) {
488 ntfs_log_info(FAILED);
489 ntfs_log_error("$MFT error: Incomplete multi "
490 "sector transfer detected in "
491 "%s.\nCannot handle this yet. "
492 ")-:\n", s);
493 goto error_exit;
494 }
495 if (!ntfs_is_mft_record(mrec->magic)) {
496 ntfs_log_info(FAILED);
497 ntfs_log_error("$MFT error: Invalid mft "
498 "record for %s.\nCannot "
499 "handle this yet. )-:\n", s);
500 goto error_exit;
501 }
502 }
503 mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
504 if (mrec2->flags & MFT_RECORD_IN_USE) {
505 if (ntfs_is_baad_record(mrec2->magic)) {
506 ntfs_log_info(FAILED);
507 ntfs_log_error("$MFTMirr error: Incomplete "
508 "multi sector transfer "
509 "detected in %s.\n", s);
510 goto error_exit;
511 }
512 if (!ntfs_is_mft_record(mrec2->magic)) {
513 ntfs_log_info(FAILED);
514 ntfs_log_error("$MFTMirr error: Invalid mft "
515 "record for %s.\n", s);
516 goto error_exit;
517 }
518 /* $MFT is corrupt but $MFTMirr is ok, use $MFTMirr. */
519 if (!(mrec->flags & MFT_RECORD_IN_USE) &&
520 !ntfs_is_mft_record(mrec->magic))
521 use_mirr = TRUE;
522 }
523 if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) {
524 if (!done) {
525 done = TRUE;
526 ntfs_log_info(FAILED);
527 }
528 ntfs_log_info("Correcting differences in $MFT%s "
529 "record %d...", use_mirr ? "" : "Mirr",
530 i);
531 br = ntfs_mft_record_write(vol, i,
532 use_mirr ? mrec2 : mrec);
533 if (br) {
534 ntfs_log_info(FAILED);
535 ntfs_log_perror("Error correcting $MFT%s",
536 use_mirr ? "" : "Mirr");
537 goto error_exit;
538 }
539 ntfs_log_info(OK);
540 }
541 }
542 if (!done)
543 ntfs_log_info(OK);
544 ntfs_log_info("Processing of $MFT and $MFTMirr completed "
545 "successfully.\n");
546 ret = 0;
547error_exit:
548 free(m);
549 free(m2);
550 return ret;
551}
552
553/*
554 * Rewrite the $UpCase file as default
555 *
556 * Returns 0 if could be written
557 */
558
559static int rewrite_upcase(ntfs_volume *vol, ntfs_attr *na)
560{
561 s64 l;
562 int res;
563
564 /* writing the $UpCase may require bitmap updates */
565 res = -1;
566 vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
567 if (!vol->lcnbmp_ni) {
568 ntfs_log_perror("Failed to open bitmap inode");
569 } else {
570 vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA,
571 AT_UNNAMED, 0);
572 if (!vol->lcnbmp_na) {
573 ntfs_log_perror("Failed to open bitmap data attribute");
574 } else {
575 /* minimal consistency check on the bitmap */
576 if (((vol->lcnbmp_na->data_size << 3)
577 < vol->nr_clusters)
578 || ((vol->lcnbmp_na->data_size << 3)
579 >= (vol->nr_clusters << 1))
580 || (vol->lcnbmp_na->data_size
581 > vol->lcnbmp_na->allocated_size)) {
582 ntfs_log_error("Corrupt cluster map size %lld"
583 " (allocated %lld minimum %lld)\n",
584 (long long)vol->lcnbmp_na->data_size,
585 (long long)vol->lcnbmp_na->allocated_size,
586 (long long)(vol->nr_clusters + 7) >> 3);
587 } else {
588 ntfs_log_info("Rewriting $UpCase file\n");
589 l = ntfs_attr_pwrite(na, 0, vol->upcase_len*2,
590 vol->upcase);
591 if (l != vol->upcase_len*2) {
592 ntfs_log_error("Failed to rewrite $UpCase\n");
593 } else {
594 ntfs_log_info("$UpCase has been set to default\n");
595 res = 0;
596 }
597 }
598 ntfs_attr_close(vol->lcnbmp_na);
599 vol->lcnbmp_na = (ntfs_attr*)NULL;
600 }
601 ntfs_inode_close(vol->lcnbmp_ni);
602 vol->lcnbmp_ni = (ntfs_inode*)NULL;
603 }
604 return (res);
605}
606
607/*
608 * Fix the $UpCase file
609 *
610 * Returns 0 if the table is valid or has been fixed
611 */
612
613static int fix_upcase(ntfs_volume *vol)
614{
615 ntfs_inode *ni;
616 ntfs_attr *na;
617 ntfschar *upcase;
618 s64 l;
619 u32 upcase_len;
620 u32 k;
621 int res;
622
623 res = -1;
624 ni = (ntfs_inode*)NULL;
625 na = (ntfs_attr*)NULL;
626 /* Now load the upcase table from $UpCase. */
627 ntfs_log_debug("Loading $UpCase...\n");
628 ni = ntfs_inode_open(vol, FILE_UpCase);
629 if (!ni) {
630 ntfs_log_perror("Failed to open inode FILE_UpCase");
631 goto error_exit;
632 }
633 /* Get an ntfs attribute for $UpCase/$DATA. */
634 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
635 if (!na) {
636 ntfs_log_perror("Failed to open ntfs attribute");
637 goto error_exit;
638 }
639 /*
640 * Note: Normally, the upcase table has a length equal to 65536
641 * 2-byte Unicode characters but allow for different cases, so no
642 * checks done. Just check we don't overflow 32-bits worth of Unicode
643 * characters.
644 */
645 if (na->data_size & ~0x1ffffffffULL) {
646 ntfs_log_error("Error: Upcase table is too big (max 32-bit "
647 "allowed).\n");
648 errno = EINVAL;
649 goto error_exit;
650 }
651 upcase_len = na->data_size >> 1;
652 upcase = (ntfschar*)ntfs_malloc(na->data_size);
653 if (!upcase)
654 goto error_exit;
655 /* Read in the $DATA attribute value into the buffer. */
656 l = ntfs_attr_pread(na, 0, na->data_size, upcase);
657 if (l != na->data_size) {
658 ntfs_log_error("Failed to read $UpCase, unexpected length "
659 "(%lld != %lld).\n", (long long)l,
660 (long long)na->data_size);
661 errno = EIO;
662 goto error_exit;
663 }
664 /* Consistency check of $UpCase, restricted to plain ASCII chars */
665 k = 0x20;
666 while ((k < upcase_len)
667 && (k < 0x7f)
668 && (le16_to_cpu(upcase[k])
669 == ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
670 k++;
671 if (k < 0x7f) {
672 ntfs_log_error("Corrupted file $UpCase\n");
673 if (!opt.no_action) {
674 /* rewrite the $UpCase file from default */
675 res = rewrite_upcase(vol, na);
676 /* free the bad upcase record */
677 if (!res)
678 free(upcase);
679 } else {
680 /* keep the default upcase but return an error */
681 free(upcase);
682 }
683 } else {
684 /* accept the upcase table read from $UpCase */
685 free(vol->upcase);
686 vol->upcase = upcase;
687 vol->upcase_len = upcase_len;
688 res = 0;
689 }
690error_exit :
691 /* Done with the $UpCase mft record. */
692 if (na)
693 ntfs_attr_close(na);
694 if (ni && ntfs_inode_close(ni)) {
695 ntfs_log_perror("Failed to close $UpCase");
696 }
697 return (res);
698}
699
700/*
701 * Rewrite the boot sector
702 *
703 * Returns 0 if successful
704 */
705
706static int rewrite_boot(struct ntfs_device *dev, char *full_bs,
707 s32 sector_size)
708{
709 s64 bw;
710 int res;
711
712 res = -1;
713 ntfs_log_info("Rewriting the bootsector\n");
714 bw = ntfs_pwrite(dev, 0, sector_size, full_bs);
715 if (bw == sector_size)
716 res = 0;
717 else {
718 if (bw != -1)
719 errno = EINVAL;
720 if (!bw)
721 ntfs_log_error("Failed to rewrite the bootsector (size=0)\n");
722 else
723 ntfs_log_perror("Error rewriting the bootsector");
724 }
725 return (res);
726}
727
728/*
729 * Locate an unnamed attribute in an MFT record
730 *
731 * Returns NULL if not found (with no error message)
732 */
733
734static ATTR_RECORD *find_unnamed_attr(MFT_RECORD *mrec, ATTR_TYPES type)
735{
736 ATTR_RECORD *a;
737 u32 offset;
738
739 /* fetch the requested attribute */
740 offset = le16_to_cpu(mrec->attrs_offset);
741 a = (ATTR_RECORD*)((char*)mrec + offset);
Steve Kondike68cb602016-08-28 00:45:36 -0700742 while ((offset < le32_to_cpu(mrec->bytes_in_use))
743 && (a->type != AT_END)
744 && ((a->type != type) || a->name_length)) {
Steve Kondik2111ad72013-07-07 12:07:44 -0700745 offset += le32_to_cpu(a->length);
746 a = (ATTR_RECORD*)((char*)mrec + offset);
747 }
Steve Kondike68cb602016-08-28 00:45:36 -0700748 if ((offset >= le32_to_cpu(mrec->bytes_in_use))
749 || (a->type != type)
Steve Kondik2111ad72013-07-07 12:07:44 -0700750 || a->name_length)
751 a = (ATTR_RECORD*)NULL;
752 return (a);
753}
754
755/*
756 * First condition for having a self-located MFT :
757 * only 16 MFT records are defined in MFT record 0
758 *
759 * Only low-level library functions can be used.
760 *
761 * Returns TRUE if the condition is met.
762 */
763
764static BOOL short_mft_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
765{
766 BOOL ok;
767 ntfs_volume *vol;
768 MFT_RECORD *mft0;
769 ATTR_RECORD *a;
770 runlist_element *rl;
771 u16 seqn;
772
773 ok = FALSE;
774 vol = selfloc->vol;
775 mft0 = selfloc->mft0;
776 if ((ntfs_pread(vol->dev,
777 vol->mft_lcn << vol->cluster_size_bits,
778 vol->mft_record_size, mft0)
779 == vol->mft_record_size)
780 && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft0,
781 vol->mft_record_size)) {
782 a = find_unnamed_attr(mft0,AT_DATA);
783 if (a
784 && a->non_resident
Steve Kondike68cb602016-08-28 00:45:36 -0700785 && (((sle64_to_cpu(a->highest_vcn) + 1)
Steve Kondik2111ad72013-07-07 12:07:44 -0700786 << vol->cluster_size_bits)
787 == (SELFLOC_LIMIT*vol->mft_record_size))) {
788 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
789 if (rl) {
790 /*
791 * The first error condition is having only
792 * 16 entries mapped in the first MFT record.
793 */
794 if ((rl[0].lcn >= 0)
795 && ((rl[0].length << vol->cluster_size_bits)
796 == SELFLOC_LIMIT*vol->mft_record_size)
797 && (rl[1].vcn == rl[0].length)
798 && (rl[1].lcn == LCN_RL_NOT_MAPPED)) {
799 ok = TRUE;
800 seqn = le16_to_cpu(
801 mft0->sequence_number);
802 selfloc->mft_ref0
803 = ((MFT_REF)seqn) << 48;
804 }
805 free(rl);
806 }
807 }
808 }
809 return (ok);
810}
811
812/*
813 * Second condition for having a self-located MFT :
814 * The 16th MFT record is defined in MFT record >= 16
815 *
816 * Only low-level library functions can be used.
817 *
818 * Returns TRUE if the condition is met.
819 */
820
821static BOOL attrlist_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
822{
823 ntfs_volume *vol;
824 ATTR_RECORD *a;
825 ATTR_LIST_ENTRY *attrlist;
826 ATTR_LIST_ENTRY *al;
827 runlist_element *rl;
828 VCN vcn;
829 leVCN levcn;
830 u32 length;
831 int ok;
832
833 ok = FALSE;
834 length = 0;
835 vol = selfloc->vol;
836 a = find_unnamed_attr(selfloc->mft0,AT_ATTRIBUTE_LIST);
837 if (a) {
838 selfloc->attrlist_resident = !a->non_resident;
839 selfloc->attrlist_lcn = 0;
840 if (a->non_resident) {
841 attrlist = selfloc->attrlist;
842 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
843 if (rl
844 && (rl->lcn >= 0)
Steve Kondike68cb602016-08-28 00:45:36 -0700845 && (sle64_to_cpu(a->data_size) < vol->cluster_size)
Steve Kondik2111ad72013-07-07 12:07:44 -0700846 && (ntfs_pread(vol->dev,
847 rl->lcn << vol->cluster_size_bits,
848 vol->cluster_size, attrlist) == vol->cluster_size)) {
849 selfloc->attrlist_lcn = rl->lcn;
850 al = attrlist;
Steve Kondike68cb602016-08-28 00:45:36 -0700851 length = sle64_to_cpu(a->data_size);
Steve Kondik2111ad72013-07-07 12:07:44 -0700852 }
853 } else {
854 al = (ATTR_LIST_ENTRY*)
855 ((char*)a + le16_to_cpu(a->value_offset));
856 length = le32_to_cpu(a->value_length);
857 }
858 if (length) {
859 /* search for a data attribute defining entry 16 */
860 vcn = (SELFLOC_LIMIT*vol->mft_record_size)
861 >> vol->cluster_size_bits;
Steve Kondike68cb602016-08-28 00:45:36 -0700862 levcn = cpu_to_sle64(vcn);
Steve Kondik2111ad72013-07-07 12:07:44 -0700863 while ((length > 0)
864 && al->length
865 && ((al->type != AT_DATA)
866 || ((leVCN)al->lowest_vcn != levcn))) {
867 length -= le16_to_cpu(al->length);
868 al = (ATTR_LIST_ENTRY*)
869 ((char*)al + le16_to_cpu(al->length));
870 }
871 if ((length > 0)
872 && al->length
873 && (al->type == AT_DATA)
874 && !al->name_length
875 && ((leVCN)al->lowest_vcn == levcn)
876 && (MREF_LE(al->mft_reference) >= SELFLOC_LIMIT)) {
877 selfloc->mft_ref1
878 = le64_to_cpu(al->mft_reference);
879 selfloc->attrlist_to_ref1 = al;
880 ok = TRUE;
881 }
882 }
883 }
884 return (ok);
885}
886
887/*
888 * Third condition for having a self-located MFT :
889 * The location of the second part of the MFT is defined in itself
890 *
891 * To locate the second part, we have to assume the first and the
892 * second part of the MFT data are contiguous.
893 *
894 * Only low-level library functions can be used.
895 *
896 * Returns TRUE if the condition is met.
897 */
898
899static BOOL self_mapped_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
900{
901 BOOL ok;
902 s64 inum;
903 u64 offs;
904 VCN lowest_vcn;
905 MFT_RECORD *mft1;
906 ATTR_RECORD *a;
907 ntfs_volume *vol;
908 runlist_element *rl;
909
910 ok = FALSE;
911 vol = selfloc->vol;
912 mft1 = selfloc->mft1;
913 inum = MREF(selfloc->mft_ref1);
914 offs = (vol->mft_lcn << vol->cluster_size_bits)
915 + (inum << vol->mft_record_size_bits);
916 if ((ntfs_pread(vol->dev, offs, vol->mft_record_size,
917 mft1) == vol->mft_record_size)
918 && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft1,
919 vol->mft_record_size)) {
920 lowest_vcn = (SELFLOC_LIMIT*vol->mft_record_size)
921 >> vol->cluster_size_bits;
922 a = find_unnamed_attr(mft1,AT_DATA);
923 if (a
924 && (mft1->flags & MFT_RECORD_IN_USE)
Steve Kondike68cb602016-08-28 00:45:36 -0700925 && ((VCN)sle64_to_cpu(a->lowest_vcn) == lowest_vcn)
Steve Kondik2111ad72013-07-07 12:07:44 -0700926 && (le64_to_cpu(mft1->base_mft_record)
927 == selfloc->mft_ref0)
928 && ((u16)MSEQNO(selfloc->mft_ref1)
929 == le16_to_cpu(mft1->sequence_number))) {
930 rl = ntfs_mapping_pairs_decompress(vol, a, NULL);
931 if ((rl[0].lcn == LCN_RL_NOT_MAPPED)
932 && !rl[0].vcn
933 && (rl[0].length == lowest_vcn)
934 && (rl[1].vcn == lowest_vcn)
935 && ((u64)(rl[1].lcn << vol->cluster_size_bits)
936 <= offs)
937 && ((u64)((rl[1].lcn + rl[1].length)
938 << vol->cluster_size_bits) > offs)) {
939 ok = TRUE;
940 }
941 }
942 }
943 return (ok);
944}
945
946/*
947 * Fourth condition, to be able to fix a self-located MFT :
948 * The MFT record 15 must be available.
949 *
950 * The MFT record 15 is expected to be marked in use, we assume
951 * it is available if it has no parent, no name and no attr list.
952 *
953 * Only low-level library functions can be used.
954 *
955 * Returns TRUE if the condition is met.
956 */
957
958static BOOL spare_record_selfloc_condition(struct MFT_SELF_LOCATED *selfloc)
959{
960 BOOL ok;
961 s64 inum;
962 u64 offs;
963 MFT_RECORD *mft2;
964 ntfs_volume *vol;
965
966 ok = FALSE;
967 vol = selfloc->vol;
968 mft2 = selfloc->mft2;
969 inum = SELFLOC_LIMIT - 1;
970 offs = (vol->mft_lcn << vol->cluster_size_bits)
971 + (inum << vol->mft_record_size_bits);
972 if ((ntfs_pread(vol->dev, offs, vol->mft_record_size,
973 mft2) == vol->mft_record_size)
974 && !ntfs_mst_post_read_fixup((NTFS_RECORD*)mft2,
975 vol->mft_record_size)) {
976 if (!mft2->base_mft_record
977 && (mft2->flags & MFT_RECORD_IN_USE)
978 && !find_unnamed_attr(mft2,AT_ATTRIBUTE_LIST)
979 && !find_unnamed_attr(mft2,AT_FILE_NAME)) {
980 ok = TRUE;
981 }
982 }
983 return (ok);
984}
985
986/*
987 * Fix a self-located MFT by swapping two MFT records
988 *
989 * Only low-level library functions can be used.
990 *
991 * Returns 0 if the MFT corruption could be fixed.
992 */
993static int fix_selfloc_conditions(struct MFT_SELF_LOCATED *selfloc)
994{
995 MFT_RECORD *mft1;
996 MFT_RECORD *mft2;
997 ATTR_RECORD *a;
998 ATTR_LIST_ENTRY *al;
999 ntfs_volume *vol;
1000 s64 offs;
1001 s64 offsm;
1002 s64 offs1;
1003 s64 offs2;
1004 s64 inum;
1005 u16 usa_ofs;
1006 int res;
1007
1008 res = 0;
1009 /*
1010 * In MFT1, we must fix :
1011 * - the self-reference, if present,
1012 * - its own sequence number, must be 15
1013 * - the sizes of the data attribute.
1014 */
1015 vol = selfloc->vol;
1016 mft1 = selfloc->mft1;
1017 mft2 = selfloc->mft2;
1018 usa_ofs = le16_to_cpu(mft1->usa_ofs);
1019 if (usa_ofs >= 48)
1020 mft1->mft_record_number = const_cpu_to_le32(SELFLOC_LIMIT - 1);
1021 mft1->sequence_number = const_cpu_to_le16(SELFLOC_LIMIT - 1);
1022 a = find_unnamed_attr(mft1,AT_DATA);
1023 if (a) {
Steve Kondike68cb602016-08-28 00:45:36 -07001024 a->allocated_size = const_cpu_to_sle64(0);
1025 a->data_size = const_cpu_to_sle64(0);
1026 a->initialized_size = const_cpu_to_sle64(0);
Steve Kondik2111ad72013-07-07 12:07:44 -07001027 } else
1028 res = -1; /* bug : it has been found earlier */
1029
1030 /*
1031 * In MFT2, we must fix :
1032 * - the self-reference, if present
1033 */
1034 usa_ofs = le16_to_cpu(mft2->usa_ofs);
1035 if (usa_ofs >= 48)
1036 mft2->mft_record_number = cpu_to_le32(MREF(selfloc->mft_ref1));
1037
1038 /*
1039 * In the attribute list, we must fix :
1040 * - the reference to MFT1
1041 */
1042 al = selfloc->attrlist_to_ref1;
1043 al->mft_reference = MK_LE_MREF(SELFLOC_LIMIT - 1, SELFLOC_LIMIT - 1);
1044
1045 /*
1046 * All fixes done, we can write all if allowed
1047 */
1048 if (!res && !opt.no_action) {
1049 inum = SELFLOC_LIMIT - 1;
1050 offs2 = (vol->mft_lcn << vol->cluster_size_bits)
1051 + (inum << vol->mft_record_size_bits);
1052 inum = MREF(selfloc->mft_ref1);
1053 offs1 = (vol->mft_lcn << vol->cluster_size_bits)
1054 + (inum << vol->mft_record_size_bits);
1055
1056 /* rewrite the attribute list */
1057 if (selfloc->attrlist_resident) {
1058 /* write mft0 and mftmirr if it is resident */
1059 offs = vol->mft_lcn << vol->cluster_size_bits;
1060 offsm = vol->mftmirr_lcn << vol->cluster_size_bits;
1061 if (ntfs_mst_pre_write_fixup(
1062 (NTFS_RECORD*)selfloc->mft0,
1063 vol->mft_record_size)
1064 || (ntfs_pwrite(vol->dev, offs, vol->mft_record_size,
1065 selfloc->mft0) != vol->mft_record_size)
1066 || (ntfs_pwrite(vol->dev, offsm, vol->mft_record_size,
1067 selfloc->mft0) != vol->mft_record_size))
1068 res = -1;
1069 } else {
1070 /* write a full cluster if non resident */
1071 offs = selfloc->attrlist_lcn << vol->cluster_size_bits;
1072 if (ntfs_pwrite(vol->dev, offs, vol->cluster_size,
1073 selfloc->attrlist) != vol->cluster_size)
1074 res = -1;
1075 }
1076 /* replace MFT2 by MFT1 and replace MFT1 by MFT2 */
1077 if (!res
1078 && (ntfs_mst_pre_write_fixup((NTFS_RECORD*)selfloc->mft1,
1079 vol->mft_record_size)
1080 || ntfs_mst_pre_write_fixup((NTFS_RECORD*)selfloc->mft2,
1081 vol->mft_record_size)
1082 || (ntfs_pwrite(vol->dev, offs2, vol->mft_record_size,
1083 mft1) != vol->mft_record_size)
1084 || (ntfs_pwrite(vol->dev, offs1, vol->mft_record_size,
1085 mft2) != vol->mft_record_size)))
1086 res = -1;
1087 }
1088 return (res);
1089}
1090
1091/*
1092 * Detect and fix a Windows XP bug, leading to a corrupt MFT
1093 *
1094 * Windows cannot boot anymore, so chkdsk cannot be started, which
1095 * is a good point, because chkdsk would have deleted all the files.
1096 * Older ntfs-3g fell into an endless recursion (recent versions
1097 * refuse to mount).
1098 *
1099 * This situation is very rare, but it was fun to fix it.
1100 *
1101 * The corrupted condition is :
1102 * - MFT entry 0 has only the runlist for MFT entries 0-15
1103 * - The attribute list for MFT shows the second part
1104 * in an MFT record beyond 15
1105 * Of course, this record has to be read in order to know where it is.
1106 *
1107 * Sample case, met in 2011 (Windows XP) :
1108 * MFT record 0 has : stdinfo, nonres attrlist, the first
1109 * part of MFT data (entries 0-15), and bitmap
1110 * MFT record 16 has the name
1111 * MFT record 17 has the third part of MFT data (16-117731)
1112 * MFT record 18 has the second part of MFT data (117732-170908)
1113 *
1114 * Assuming the second part of the MFT is contiguous to the first
1115 * part, we can find it, and fix the condition by relocating it
1116 * and swapping it with MFT record 15.
1117 * This record number 15 appears to be hardcoded into Windows NTFS.
1118 *
1119 * Only low-level library functions can be used.
1120 *
Steve Kondike68cb602016-08-28 00:45:36 -07001121 * Returns 0 if the conditions for the error was met and
1122 * this error could be fixed,
1123 * -1 if the condition was not met or some error
1124 * which could not be fixed was encountered.
Steve Kondik2111ad72013-07-07 12:07:44 -07001125 */
1126
1127static int fix_self_located_mft(ntfs_volume *vol)
1128{
1129 struct MFT_SELF_LOCATED selfloc;
1130 BOOL res;
1131
1132 ntfs_log_info("Checking for self-located MFT segment... ");
1133 res = -1;
1134 selfloc.vol = vol;
1135 selfloc.mft0 = (MFT_RECORD*)malloc(vol->mft_record_size);
1136 selfloc.mft1 = (MFT_RECORD*)malloc(vol->mft_record_size);
1137 selfloc.mft2 = (MFT_RECORD*)malloc(vol->mft_record_size);
1138 selfloc.attrlist = (ATTR_LIST_ENTRY*)malloc(vol->cluster_size);
1139 if (selfloc.mft0 && selfloc.mft1 && selfloc.mft2
1140 && selfloc.attrlist) {
1141 if (short_mft_selfloc_condition(&selfloc)
1142 && attrlist_selfloc_condition(&selfloc)
1143 && self_mapped_selfloc_condition(&selfloc)
1144 && spare_record_selfloc_condition(&selfloc)) {
1145 ntfs_log_info(FOUND);
1146 ntfs_log_info("Fixing the self-located MFT segment... ");
1147 res = fix_selfloc_conditions(&selfloc);
1148 ntfs_log_info(res ? FAILED : OK);
1149 } else {
1150 ntfs_log_info(OK);
Steve Kondike68cb602016-08-28 00:45:36 -07001151 res = -1;
Steve Kondik2111ad72013-07-07 12:07:44 -07001152 }
1153 free(selfloc.mft0);
1154 free(selfloc.mft1);
1155 free(selfloc.mft2);
1156 free(selfloc.attrlist);
1157 }
1158 return (res);
1159}
1160
1161/*
1162 * Try an alternate boot sector and fix the real one
1163 *
1164 * Only after successful checks is the boot sector rewritten.
1165 *
1166 * The alternate boot sector is not rewritten, either because it
1167 * was found correct, or because we truncated the file system
1168 * and the last actual sector might be part of some file.
1169 *
1170 * Returns 0 if successful
1171 */
1172
1173static int try_fix_boot(ntfs_volume *vol, char *full_bs,
1174 s64 read_sector, s64 fix_sectors, s32 sector_size)
1175{
1176 s64 br;
1177 int res;
1178 s64 got_sectors;
1179 le16 sector_size_le;
1180 NTFS_BOOT_SECTOR *bs;
1181
1182 res = -1;
1183 br = ntfs_pread(vol->dev, read_sector*sector_size,
1184 sector_size, full_bs);
1185 if (br != sector_size) {
1186 if (br != -1)
1187 errno = EINVAL;
1188 if (!br)
1189 ntfs_log_error("Failed to read alternate bootsector (size=0)\n");
1190 else
1191 ntfs_log_perror("Error reading alternate bootsector");
1192 } else {
1193 bs = (NTFS_BOOT_SECTOR*)full_bs;
Steve Kondike68cb602016-08-28 00:45:36 -07001194 got_sectors = sle64_to_cpu(bs->number_of_sectors);
1195 bs->number_of_sectors = cpu_to_sle64(fix_sectors);
Steve Kondik2111ad72013-07-07 12:07:44 -07001196 /* alignment problem on Sparc, even doing memcpy() */
1197 sector_size_le = cpu_to_le16(sector_size);
1198 if (!memcmp(&sector_size_le, &bs->bpb.bytes_per_sector,2)
1199 && ntfs_boot_sector_is_ntfs(bs)
1200 && !ntfs_boot_sector_parse(vol, bs)) {
1201 ntfs_log_info("The alternate bootsector is usable\n");
1202 if (fix_sectors != got_sectors)
1203 ntfs_log_info("Set sector count to %lld instead of %lld\n",
1204 (long long)fix_sectors,
1205 (long long)got_sectors);
1206 /* fix the normal boot sector */
1207 if (!opt.no_action) {
1208 res = rewrite_boot(vol->dev, full_bs,
1209 sector_size);
1210 } else
1211 res = 0;
1212 }
1213 if (!res && !opt.no_action)
1214 ntfs_log_info("The boot sector has been rewritten\n");
1215 }
1216 return (res);
1217}
1218
1219/*
1220 * Try the alternate boot sector if the normal one is bad
1221 *
1222 * Actually :
1223 * - first try the last sector of the partition (expected location)
1224 * - then try the last sector as shown in the main boot sector,
1225 * (could be meaningful for an undersized partition)
1226 * - finally try truncating the file system actual size of partition
1227 * (could be meaningful for an oversized partition)
1228 *
1229 * if successful, rewrite the normal boot sector accordingly
1230 *
1231 * Returns 0 if successful
1232 */
1233
1234static int try_alternate_boot(ntfs_volume *vol, char *full_bs,
1235 s32 sector_size, s64 shown_sectors)
1236{
1237 s64 actual_sectors;
1238 int res;
1239
1240 res = -1;
1241 ntfs_log_info("Trying the alternate boot sector\n");
1242
1243 /*
1244 * We do not rely on the sector size defined in the
1245 * boot sector, supposed to be corrupt, so we try to get
1246 * the actual sector size and defaulting to 512 if failed
1247 * to get. This value is only used to guess the alternate
1248 * boot sector location and it is checked against the
1249 * value found in the sector itself. It should not damage
1250 * anything if wrong.
1251 *
1252 * Note : the real last sector is not accounted for here.
1253 */
1254 actual_sectors = ntfs_device_size_get(vol->dev,sector_size) - 1;
1255
1256 /* first try the actual last sector */
1257 if ((actual_sectors > 0)
1258 && !try_fix_boot(vol, full_bs, actual_sectors,
1259 actual_sectors, sector_size))
1260 res = 0;
1261
1262 /* then try the shown last sector, if less than actual */
1263 if (res
1264 && (shown_sectors > 0)
1265 && (shown_sectors < actual_sectors)
1266 && !try_fix_boot(vol, full_bs, shown_sectors,
1267 shown_sectors, sector_size))
1268 res = 0;
1269
1270 /* then try reducing the number of sectors to actual value */
1271 if (res
1272 && (shown_sectors > actual_sectors)
1273 && !try_fix_boot(vol, full_bs, 0, actual_sectors, sector_size))
1274 res = 0;
1275
1276 return (res);
1277}
1278
1279/*
1280 * Check and fix the alternate boot sector
1281 *
1282 * The alternate boot sector is usually in the last sector of a
1283 * partition, which should not be used by the file system
1284 * (the sector count in the boot sector should be less than
1285 * the total sector count in the partition).
1286 *
1287 * chkdsk never changes the count in the boot sector.
1288 * - If this is less than the total count, chkdsk place the
1289 * alternate boot sector into the sector,
1290 * - if the count is the same as the total count, chkdsk place
1291 * the alternate boot sector into the middle sector (half
1292 * the total count rounded upwards)
1293 * - if the count is greater than the total count, chkdsk
1294 * declares the file system as raw, and refuses to fix anything.
1295 *
1296 * Here, we check and fix the alternate boot sector, only in the
1297 * first situation where the file system does not overflow on the
1298 * last sector.
1299 *
1300 * Note : when shrinking a partition, ntfsresize cannot determine
1301 * the future size of the partition. As a consequence the number of
1302 * sectors in the boot sectors may be less than the possible size.
1303 *
1304 * Returns 0 if successful
1305 */
1306
1307static int check_alternate_boot(ntfs_volume *vol)
1308{
1309 s64 got_sectors;
1310 s64 actual_sectors;
1311 s64 last_sector_off;
1312 char *full_bs;
1313 char *alt_bs;
1314 NTFS_BOOT_SECTOR *bs;
1315 s64 br;
1316 s64 bw;
1317 int res;
1318
1319 res = -1;
1320 full_bs = (char*)malloc(vol->sector_size);
1321 alt_bs = (char*)malloc(vol->sector_size);
1322 if (!full_bs || !alt_bs) {
1323 ntfs_log_info("Error : failed to allocate memory\n");
1324 goto error_exit;
1325 }
1326 /* Now read both bootsectors. */
1327 br = ntfs_pread(vol->dev, 0, vol->sector_size, full_bs);
1328 if (br == vol->sector_size) {
1329 bs = (NTFS_BOOT_SECTOR*)full_bs;
Steve Kondike68cb602016-08-28 00:45:36 -07001330 got_sectors = sle64_to_cpu(bs->number_of_sectors);
Steve Kondik2111ad72013-07-07 12:07:44 -07001331 actual_sectors = ntfs_device_size_get(vol->dev,
1332 vol->sector_size);
1333 if (actual_sectors > got_sectors) {
1334 last_sector_off = (actual_sectors - 1)
1335 << vol->sector_size_bits;
1336 ntfs_log_info("Checking the alternate boot sector... ");
1337 br = ntfs_pread(vol->dev, last_sector_off,
1338 vol->sector_size, alt_bs);
1339 } else {
1340 ntfs_log_info("Checking file system overflow... ");
1341 br = -1;
1342 }
1343 /* accept getting no byte, needed for short image files */
1344 if (br >= 0) {
1345 if ((br != vol->sector_size)
1346 || memcmp(full_bs, alt_bs, vol->sector_size)) {
1347 if (opt.no_action) {
1348 ntfs_log_info("BAD\n");
1349 } else {
1350 bw = ntfs_pwrite(vol->dev,
1351 last_sector_off,
1352 vol->sector_size, full_bs);
1353 if (bw == vol->sector_size) {
1354 ntfs_log_info("FIXED\n");
1355 res = 0;
1356 } else {
1357 ntfs_log_info(FAILED);
1358 }
1359 }
1360 } else {
1361 ntfs_log_info(OK);
1362 res = 0;
1363 }
1364 } else {
1365 ntfs_log_info(FAILED);
1366 }
1367 } else {
1368 ntfs_log_info("Error : could not read the boot sector again\n");
1369 }
1370 free(full_bs);
1371 free(alt_bs);
1372
1373error_exit :
1374 return (res);
1375}
1376
1377/*
1378 * Try to fix problems which may arise in the start up sequence
1379 *
1380 * This is a replay of the normal start up sequence with fixes when
1381 * some problem arise.
Steve Kondike68cb602016-08-28 00:45:36 -07001382 *
1383 * Returns 0 if there was an error and a fix is available
Steve Kondik2111ad72013-07-07 12:07:44 -07001384 */
1385
1386static int fix_startup(struct ntfs_device *dev, unsigned long flags)
1387{
1388 s64 br;
1389 ntfs_volume *vol;
1390 BOOL dev_open;
1391 s64 shown_sectors;
1392 char *full_bs;
1393 NTFS_BOOT_SECTOR *bs;
1394 s32 sector_size;
1395 int res;
1396 int eo;
1397
1398 errno = 0;
1399 res = -1;
1400 dev_open = FALSE;
1401 full_bs = (char*)NULL;
1402 if (!dev || !dev->d_ops || !dev->d_name) {
1403 errno = EINVAL;
1404 ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
1405 vol = (ntfs_volume*)NULL;
1406 goto error_exit;
1407 }
1408
1409 /* Allocate the volume structure. */
1410 vol = ntfs_volume_alloc();
1411 if (!vol)
1412 goto error_exit;
1413
1414 /* Create the default upcase table. */
1415 vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
1416 if (!vol->upcase_len || !vol->upcase)
1417 goto error_exit;
1418
1419 /* Default with no locase table and case sensitive file names */
1420 vol->locase = (ntfschar*)NULL;
1421 NVolSetCaseSensitive(vol);
1422
1423 /* by default, all files are shown and not marked hidden */
1424 NVolSetShowSysFiles(vol);
1425 NVolSetShowHidFiles(vol);
1426 NVolClearHideDotFiles(vol);
1427 if (flags & NTFS_MNT_RDONLY)
1428 NVolSetReadOnly(vol);
1429
1430 /* ...->open needs bracketing to compile with glibc 2.7 */
1431 if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
1432 ntfs_log_perror("Error opening '%s'", dev->d_name);
1433 goto error_exit;
1434 }
1435 dev_open = TRUE;
1436 /* Attach the device to the volume. */
1437 vol->dev = dev;
1438
1439 sector_size = ntfs_device_sector_size_get(dev);
1440 if (sector_size <= 0)
1441 sector_size = DEFAULT_SECTOR_SIZE;
1442 full_bs = (char*)malloc(sector_size);
1443 if (!full_bs)
1444 goto error_exit;
1445 /* Now read the bootsector. */
1446 br = ntfs_pread(dev, 0, sector_size, full_bs);
1447 if (br != sector_size) {
1448 if (br != -1)
1449 errno = EINVAL;
1450 if (!br)
1451 ntfs_log_error("Failed to read bootsector (size=0)\n");
1452 else
1453 ntfs_log_perror("Error reading bootsector");
1454 goto error_exit;
1455 }
1456 bs = (NTFS_BOOT_SECTOR*)full_bs;
1457 if (!ntfs_boot_sector_is_ntfs(bs)
1458 /* get the bootsector data, only fails when inconsistent */
1459 || (ntfs_boot_sector_parse(vol, bs) < 0)) {
Steve Kondike68cb602016-08-28 00:45:36 -07001460 shown_sectors = sle64_to_cpu(bs->number_of_sectors);
Steve Kondik2111ad72013-07-07 12:07:44 -07001461 /* boot sector is wrong, try the alternate boot sector */
1462 if (try_alternate_boot(vol, full_bs, sector_size,
1463 shown_sectors)) {
1464 errno = EINVAL;
1465 goto error_exit;
1466 }
1467 res = 0;
1468 } else {
1469 res = fix_self_located_mft(vol);
1470 }
1471error_exit:
1472 if (res) {
1473 switch (errno) {
1474 case ENOMEM :
1475 ntfs_log_error("Failed to allocate memory\n");
1476 break;
1477 case EINVAL :
1478 ntfs_log_error("Unrecoverable error\n");
1479 break;
1480 default :
1481 break;
1482 }
1483 }
1484 eo = errno;
1485 free(full_bs);
1486 if (vol) {
1487 free(vol->upcase);
1488 free(vol);
1489 }
1490 if (dev_open) {
1491 (dev->d_ops->close)(dev);
1492 }
1493 errno = eo;
1494 return (res);
1495}
1496
1497/**
1498 * fix_mount
1499 */
1500static int fix_mount(void)
1501{
1502 int ret = 0; /* default success */
1503 ntfs_volume *vol;
1504 struct ntfs_device *dev;
1505 unsigned long flags;
1506
1507 ntfs_log_info("Attempting to correct errors... ");
1508
1509 dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
1510 NULL);
1511 if (!dev) {
1512 ntfs_log_info(FAILED);
1513 ntfs_log_perror("Failed to allocate device");
1514 return -1;
1515 }
1516 flags = (opt.no_action ? NTFS_MNT_RDONLY : 0);
1517 vol = ntfs_volume_startup(dev, flags);
1518 if (!vol) {
1519 ntfs_log_info(FAILED);
1520 ntfs_log_perror("Failed to startup volume");
1521
1522 /* Try fixing the bootsector and MFT, then redo the startup */
1523 if (!fix_startup(dev, flags)) {
1524 if (opt.no_action)
1525 ntfs_log_info("The startup data can be fixed, "
1526 "but no change was requested\n");
1527 else
1528 vol = ntfs_volume_startup(dev, flags);
1529 }
1530 if (!vol) {
1531 ntfs_log_error("Volume is corrupt. You should run chkdsk.\n");
1532 ntfs_device_free(dev);
1533 return -1;
1534 }
1535 if (opt.no_action)
1536 ret = -1; /* error present and not fixed */
1537 }
1538 /* if option -n proceed despite errors, to display them all */
1539 if ((!ret || opt.no_action) && (fix_mftmirr(vol) < 0))
1540 ret = -1;
1541 if ((!ret || opt.no_action) && (fix_upcase(vol) < 0))
1542 ret = -1;
1543 if ((!ret || opt.no_action) && (set_dirty_flag(vol) < 0))
1544 ret = -1;
1545 if ((!ret || opt.no_action) && (empty_journal(vol) < 0))
1546 ret = -1;
1547 /*
1548 * ntfs_umount() will invoke ntfs_device_free() for us.
1549 * Ignore the returned error resulting from partial mounting.
1550 */
1551 ntfs_umount(vol, 1);
1552 return ret;
1553}
1554
1555/**
1556 * main
1557 */
1558int main(int argc, char **argv)
1559{
1560 ntfs_volume *vol;
1561 unsigned long mnt_flags;
1562 unsigned long flags;
1563 int ret = 1; /* failure */
1564 BOOL force = FALSE;
1565
1566 ntfs_log_set_handler(ntfs_log_handler_outerr);
1567
1568 parse_options(argc, argv);
1569
1570 if (!ntfs_check_if_mounted(opt.volume, &mnt_flags)) {
1571 if ((mnt_flags & NTFS_MF_MOUNTED) &&
1572 !(mnt_flags & NTFS_MF_READONLY) && !force) {
1573 ntfs_log_error("Refusing to operate on read-write "
1574 "mounted device %s.\n", opt.volume);
1575 exit(1);
1576 }
1577 } else
1578 ntfs_log_perror("Failed to determine whether %s is mounted",
1579 opt.volume);
1580 /* Attempt a full mount first. */
1581 flags = (opt.no_action ? NTFS_MNT_RDONLY : 0);
1582 ntfs_log_info("Mounting volume... ");
1583 vol = ntfs_mount(opt.volume, flags);
1584 if (vol) {
1585 ntfs_log_info(OK);
1586 ntfs_log_info("Processing of $MFT and $MFTMirr completed "
1587 "successfully.\n");
1588 } else {
1589 ntfs_log_info(FAILED);
1590 if (fix_mount() < 0) {
1591 if (opt.no_action)
1592 ntfs_log_info("No change made\n");
1593 exit(1);
1594 }
Steve Kondik2111ad72013-07-07 12:07:44 -07001595 vol = ntfs_mount(opt.volume, 0);
1596 if (!vol) {
1597 ntfs_log_perror("Remount failed");
1598 exit(1);
1599 }
1600 }
1601 if (check_alternate_boot(vol)) {
1602 ntfs_log_error("Error: Failed to fix the alternate boot sector\n");
1603 exit(1);
1604 }
1605 /* So the unmount does not clear it again. */
1606
1607 /* Porting note: The WasDirty flag was set here to prevent ntfs_unmount
1608 * from clearing the dirty bit (which might have been set in
1609 * fix_mount()). So the intention is to leave the dirty bit set.
1610 *
1611 * libntfs-3g does not automatically set or clear dirty flags on
1612 * mount/unmount, this means that the assumption that the dirty flag is
1613 * now set does not hold. So we need to set it if not already set.
1614 *
1615 * However clear the flag if requested to do so, at this stage
1616 * mounting was successful.
1617 */
1618 if (opt.clear_dirty)
1619 vol->flags &= ~VOLUME_IS_DIRTY;
1620 else
1621 vol->flags |= VOLUME_IS_DIRTY;
1622 if (!opt.no_action && ntfs_volume_write_flags(vol, vol->flags)) {
1623 ntfs_log_error("Error: Failed to set volume dirty flag (%d "
1624 "(%s))!\n", errno, strerror(errno));
1625 }
1626
1627 /* Check NTFS version is ok for us (in $Volume) */
1628 ntfs_log_info("NTFS volume version is %i.%i.\n", vol->major_ver,
1629 vol->minor_ver);
1630 if (ntfs_version_is_supported(vol)) {
1631 ntfs_log_error("Error: Unknown NTFS version.\n");
1632 goto error_exit;
1633 }
1634 if (opt.clear_bad_sectors && !opt.no_action) {
1635 if (clear_badclus(vol)) {
1636 ntfs_log_error("Error: Failed to un-mark bad sectors.\n");
1637 goto error_exit;
1638 }
1639 }
1640 if (vol->major_ver >= 3) {
1641 /*
1642 * FIXME: If on NTFS 3.0+, check for presence of the usn
1643 * journal and stamp it if present.
1644 */
1645 }
1646 /* FIXME: We should be marking the quota out of date, too. */
1647 /* That's all for now! */
1648 ntfs_log_info("NTFS partition %s was processed successfully.\n",
1649 vol->dev->d_name);
1650 /* Set return code to 0. */
1651 ret = 0;
1652error_exit:
Steve Kondike68cb602016-08-28 00:45:36 -07001653 if (ntfs_umount(vol, 1)) {
1654 ntfs_log_info("Failed to unmount partition\n");
1655 ret = 1;
1656 }
Steve Kondik2111ad72013-07-07 12:07:44 -07001657 if (ret)
1658 exit(ret);
1659 return ret;
1660}
1661