• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * ntfsresize - Part of the Linux-NTFS project.
3  *
4  * Copyright (c) 2002-2006 Szabolcs Szakacsits
5  * Copyright (c) 2002-2005 Anton Altaparmakov
6  * Copyright (c) 2002-2003 Richard Russon
7  * Copyright (c) 2007      Yura Pakhuchiy
8  * Copyright (c) 2011-2018 Jean-Pierre Andre
9  *
10  * This utility will resize an NTFS volume without data loss.
11  *
12  * WARNING FOR DEVELOPERS!!! Several external tools grep for text messages
13  * to control execution thus if you would like to change any message
14  * then PLEASE think twice before doing so then don't modify it. Thanks!
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program (in the main directory of the Linux-NTFS
28  * distribution in the file COPYING); if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
30  */
31 
32 #include "config.h"
33 
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40 #ifdef HAVE_STDIO_H
41 #include <stdio.h>
42 #endif
43 #ifdef HAVE_STDARG_H
44 #include <stdarg.h>
45 #endif
46 #ifdef HAVE_STRING_H
47 #include <string.h>
48 #endif
49 #ifdef HAVE_ERRNO_H
50 #include <errno.h>
51 #endif
52 #ifdef HAVE_LIMITS_H
53 #include <limits.h>
54 #endif
55 #ifdef HAVE_GETOPT_H
56 #include <getopt.h>
57 #endif
58 #ifdef HAVE_FCNTL_H
59 #include <fcntl.h>
60 #endif
61 
62 #include "param.h"
63 #include "debug.h"
64 #include "types.h"
65 #include "support.h"
66 #include "endians.h"
67 #include "bootsect.h"
68 #include "device.h"
69 #include "attrib.h"
70 #include "volume.h"
71 #include "mft.h"
72 #include "bitmap.h"
73 #include "inode.h"
74 #include "runlist.h"
75 #include "utils.h"
76 /* #include "version.h" */
77 #include "misc.h"
78 
79 #define BAN_NEW_TEXT 1	/* Respect the ban on new messages */
80 #define CLEAN_EXIT 0	/* traditionnally volume is not closed, there must be a reason */
81 
82 static const char *EXEC_NAME = "ntfsresize";
83 
84 static const char *resize_warning_msg =
85 "WARNING: Every sanity check passed and only the dangerous operations left.\n"
86 "Make sure that important data has been backed up! Power outage or computer\n"
87 "crash may result major data loss!\n";
88 
89 static const char *resize_important_msg =
90 "You can go on to shrink the device for example with Linux fdisk.\n"
91 "IMPORTANT: When recreating the partition, make sure that you\n"
92 "  1)  create it at the same disk sector (use sector as the unit!)\n"
93 "  2)  create it with the same partition type (usually 7, HPFS/NTFS)\n"
94 "  3)  do not make it smaller than the new NTFS filesystem size\n"
95 "  4)  set the bootable flag for the partition if it existed before\n"
96 "Otherwise you won't be able to access NTFS or can't boot from the disk!\n"
97 "If you make a mistake and don't have a partition table backup then you\n"
98 "can recover the partition table by TestDisk or Parted's rescue mode.\n";
99 
100 static const char *invalid_ntfs_msg =
101 "The device '%s' doesn't have a valid NTFS.\n"
102 "Maybe you selected the wrong partition? Or the whole disk instead of a\n"
103 "partition (e.g. /dev/hda, not /dev/hda1)? This error might also occur\n"
104 "if the disk was incorrectly repartitioned (see the ntfsresize FAQ).\n";
105 
106 static const char *corrupt_volume_msg =
107 "NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n"
108 "The usage of the /f parameter is very IMPORTANT! No modification was\n"
109 "and will be made to NTFS by this software until it gets repaired.\n";
110 
111 static const char *hibernated_volume_msg =
112 "The NTFS partition is hibernated. Windows must be resumed and turned off\n"
113 "properly, so resizing could be done safely.\n";
114 
115 static const char *unclean_journal_msg =
116 "The NTFS journal file is unclean. Please shutdown Windows properly before\n"
117 "using this software! Note, if you have run chkdsk previously then boot\n"
118 "Windows again which will automatically initialize the journal correctly.\n";
119 
120 static const char *opened_volume_msg =
121 "This software has detected that the NTFS volume is already opened by another\n"
122 "software thus it refuses to progress to preserve data consistency.\n";
123 
124 static const char *bad_sectors_warning_msg =
125 "****************************************************************************\n"
126 "* WARNING: The disk has bad sector. This means physical damage on the disk *\n"
127 "* surface caused by deterioration, manufacturing faults or other reason.   *\n"
128 "* The reliability of the disk may stay stable or degrade fast. We suggest  *\n"
129 "* making a full backup urgently by running 'ntfsclone --rescue ...' then   *\n"
130 "* run 'chkdsk /f /r' on Windows and rebooot it TWICE! Then you can resize  *\n"
131 "* NTFS safely by additionally using the --bad-sectors option of ntfsresize.*\n"
132 "****************************************************************************\n";
133 
134 static const char *many_bad_sectors_msg =
135 "***************************************************************************\n"
136 "* WARNING: The disk has many bad sectors. This means physical damage      *\n"
137 "* on the disk surface caused by deterioration, manufacturing faults or    *\n"
138 "* other reason. We suggest to get a replacement disk as soon as possible. *\n"
139 "***************************************************************************\n";
140 
141 enum mirror_source { MIRR_OLD, MIRR_NEWMFT, MIRR_MFT };
142 
143 static struct {
144 	int verbose;
145 	int debug;
146 	int ro_flag;
147 	int force;
148 	int info;
149 	int infombonly;
150 	int expand;
151 	int reliable_size;
152 	int show_progress;
153 	int badsectors;
154 	int check;
155 	s64 bytes;
156 	char *volume;
157 } opt;
158 
159 struct bitmap {
160 	s64 size;
161 	u8 *bm;
162 };
163 
164 #define NTFS_PROGBAR		0x0001
165 #define NTFS_PROGBAR_SUPPRESS	0x0002
166 
167 struct progress_bar {
168 	u64 start;
169 	u64 stop;
170 	int resolution;
171 	int flags;
172 	float unit;
173 };
174 
175 struct llcn_t {
176 	s64 lcn;	/* last used LCN for a "special" file/attr type */
177 	s64 inode;	/* inode using it */
178 };
179 
180 #define NTFSCK_PROGBAR		0x0001
181 
182 			/* runlists which have to be processed later */
183 struct DELAYED {
184 	struct DELAYED *next;
185 	ATTR_TYPES type;
186 	MFT_REF mref;
187 	VCN lowest_vcn;
188 	int name_len;
189 	ntfschar *attr_name;
190 	runlist_element *rl;
191 	runlist *head_rl;
192 } ;
193 
194 typedef struct {
195 	ntfs_inode *ni;		     /* inode being processed */
196 	ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
197 	s64 inuse;		     /* num of clusters in use */
198 	int multi_ref;		     /* num of clusters referenced many times */
199 	int outsider;		     /* num of clusters outside the volume */
200 	int show_outsider;	     /* controls showing the above information */
201 	int flags;
202 	struct bitmap lcn_bitmap;
203 } ntfsck_t;
204 
205 typedef struct {
206 	ntfs_volume *vol;
207 	ntfs_inode *ni;		     /* inode being processed */
208 	s64 new_volume_size;	     /* in clusters; 0 = --info w/o --size */
209 	MFT_REF mref;                /* mft reference */
210 	MFT_RECORD *mrec;            /* mft record */
211 	ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
212 	u64 relocations;	     /* num of clusters to relocate */
213 	s64 inuse;		     /* num of clusters in use */
214 	runlist mftmir_rl;	     /* $MFTMirr AT_DATA's new position */
215 	s64 mftmir_old;		     /* $MFTMirr AT_DATA's old LCN */
216 	int dirty_inode;	     /* some inode data got relocated */
217 	int shrink;		     /* shrink = 1, enlarge = 0 */
218 	s64 badclusters;	     /* num of physically dead clusters */
219 	VCN mft_highest_vcn;	     /* used for relocating the $MFT */
220 	runlist_element *new_mft_start; /* new first run for $MFT:$DATA */
221 	struct DELAYED *delayed_runlists; /* runlists to process later */
222 	struct progress_bar progress;
223 	struct bitmap lcn_bitmap;
224 	/* Temporary statistics until all case is supported */
225 	struct llcn_t last_mft;
226 	struct llcn_t last_mftmir;
227 	struct llcn_t last_multi_mft;
228 	struct llcn_t last_sparse;
229 	struct llcn_t last_compressed;
230 	struct llcn_t last_lcn;
231 	s64 last_unsupp;	     /* last unsupported cluster */
232 	enum mirror_source mirr_from;
233 } ntfs_resize_t;
234 
235 /* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster
236    allocation related structure, attached to ntfs_resize_t */
237 static s64 max_free_cluster_range = 0;
238 
239 #define NTFS_MBYTE (1000 * 1000)
240 
241 /* WARNING: don't modify the text, external tools grep for it */
242 #define ERR_PREFIX   "ERROR"
243 #define PERR_PREFIX  ERR_PREFIX "(%d): "
244 #define NERR_PREFIX  ERR_PREFIX ": "
245 
246 #define DIRTY_NONE		(0)
247 #define DIRTY_INODE		(1)
248 #define DIRTY_ATTRIB		(2)
249 
rounded_up_division(s64 numer,s64 denom)250 static s64 rounded_up_division(s64 numer, s64 denom)
251 {
252 	return (numer + (denom - 1)) / denom;
253 }
254 
255 /**
256  * perr_printf
257  *
258  * Print an error message.
259  */
260 __attribute__((format(printf, 1, 2)))
perr_printf(const char * fmt,...)261 static void perr_printf(const char *fmt, ...)
262 {
263 	va_list ap;
264 	int eo = errno;
265 
266 	fprintf(stdout, PERR_PREFIX, eo);
267 	va_start(ap, fmt);
268 	vfprintf(stdout, fmt, ap);
269 	va_end(ap);
270 	fprintf(stdout, ": %s\n", strerror(eo));
271 	fflush(stdout);
272 	fflush(stderr);
273 }
274 
275 __attribute__((format(printf, 1, 2)))
err_printf(const char * fmt,...)276 static void err_printf(const char *fmt, ...)
277 {
278 	va_list ap;
279 
280 	fprintf(stdout, NERR_PREFIX);
281 	va_start(ap, fmt);
282 	vfprintf(stdout, fmt, ap);
283 	va_end(ap);
284 	fflush(stdout);
285 	fflush(stderr);
286 }
287 
288 /**
289  * err_exit
290  *
291  * Print and error message and exit the program.
292  */
293 __attribute__((noreturn))
294 __attribute__((format(printf, 1, 2)))
err_exit(const char * fmt,...)295 static void err_exit(const char *fmt, ...)
296 {
297 	va_list ap;
298 
299 	fprintf(stdout, NERR_PREFIX);
300 	va_start(ap, fmt);
301 	vfprintf(stdout, fmt, ap);
302 	va_end(ap);
303 	fflush(stdout);
304 	fflush(stderr);
305 	exit(1);
306 }
307 
308 /**
309  * perr_exit
310  *
311  * Print and error message and exit the program
312  */
313 __attribute__((noreturn))
314 __attribute__((format(printf, 1, 2)))
perr_exit(const char * fmt,...)315 static void perr_exit(const char *fmt, ...)
316 {
317 	va_list ap;
318 	int eo = errno;
319 
320 	fprintf(stdout, PERR_PREFIX, eo);
321 	va_start(ap, fmt);
322 	vfprintf(stdout, fmt, ap);
323 	va_end(ap);
324 	printf(": %s\n", strerror(eo));
325 	fflush(stdout);
326 	fflush(stderr);
327 	exit(1);
328 }
329 
330 /**
331  * usage - Print a list of the parameters to the program
332  *
333  * Print a list of the parameters and options for the program.
334  *
335  * Return:  none
336  */
337 __attribute__((noreturn))
usage(int ret)338 static void usage(int ret)
339 {
340 
341 	printf("\nUsage: %s [OPTIONS] DEVICE\n"
342 		"    Resize an NTFS volume non-destructively, safely move any data if needed.\n"
343 		"\n"
344 		"    -c, --check            Check to ensure that the device is ready for resize\n"
345 		"    -i, --info             Estimate the smallest shrunken size or the smallest\n"
346 		"                                expansion size\n"
347 		"    -m, --info-mb-only     Estimate the smallest shrunken size possible,\n"
348 		"                                output size in MB only\n"
349 		"    -s, --size SIZE        Resize volume to SIZE[k|M|G] bytes\n"
350 		"    -x, --expand           Expand to full partition\n"
351 		"\n"
352 		"    -n, --no-action        Do not write to disk\n"
353 		"    -b, --bad-sectors      Support disks having bad sectors\n"
354 		"    -f, --force            Force to progress\n"
355 		"    -P, --no-progress-bar  Don't show progress bar\n"
356 		"    -v, --verbose          More output\n"
357 		"    -V, --version          Display version information\n"
358 		"    -h, --help             Display this help\n"
359 #ifdef DEBUG
360 		"    -d, --debug            Show debug information\n"
361 #endif
362 		"\n"
363 		"    The options -i and -x are exclusive of option -s, and -m is exclusive\n"
364 		"    of option -x. If options -i, -m, -s and -x are are all omitted\n"
365 		"    then the NTFS volume will be enlarged to the DEVICE size.\n"
366 		"\n", EXEC_NAME);
367 	printf("%s%s", ntfs_bugs, ntfs_home);
368 	printf("Ntfsresize FAQ: http://linux-ntfs.sourceforge.net/info/ntfsresize.html\n");
369 	exit(ret);
370 }
371 
372 /**
373  * proceed_question
374  *
375  * Force the user to confirm an action before performing it.
376  * Copy-paste from e2fsprogs
377  */
proceed_question(void)378 static void proceed_question(void)
379 {
380 	char buf[256];
381 	const char *short_yes = "yY";
382 
383 	fflush(stdout);
384 	fflush(stderr);
385 	printf("Are you sure you want to proceed (y/[n])? ");
386 	buf[0] = 0;
387 	if (fgets(buf, sizeof(buf), stdin)
388 	    && !strchr(short_yes, buf[0])) {
389 		printf("OK quitting. NO CHANGES have been made to your "
390 				"NTFS volume.\n");
391 		exit(1);
392 	}
393 }
394 
395 /**
396  * version - Print version information about the program
397  *
398  * Print a copyright statement and a brief description of the program.
399  *
400  * Return:  none
401  */
version(void)402 static void version(void)
403 {
404 	printf("\nResize an NTFS Volume, without data loss.\n\n");
405 	printf("Copyright (c) 2002-2006  Szabolcs Szakacsits\n");
406 	printf("Copyright (c) 2002-2005  Anton Altaparmakov\n");
407 	printf("Copyright (c) 2002-2003  Richard Russon\n");
408 	printf("Copyright (c) 2007       Yura Pakhuchiy\n");
409 	printf("Copyright (c) 2011-2018  Jean-Pierre Andre\n");
410 	printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
411 }
412 
413 /**
414  * get_new_volume_size
415  *
416  * Convert a user-supplied string into a size.  Without any suffix the number
417  * will be assumed to be in bytes.  If the number has a suffix of k, M or G it
418  * will be scaled up by 1000, 1000000, or 1000000000.
419  */
get_new_volume_size(char * s)420 static s64 get_new_volume_size(char *s)
421 {
422 	s64 size;
423 	char *suffix;
424 	int prefix_kind = 1000;
425 
426 	size = strtoll(s, &suffix, 10);
427 	if (size <= 0 || errno == ERANGE)
428 		err_exit("Illegal new volume size\n");
429 
430 	if (!*suffix) {
431 		opt.reliable_size = 1;
432 		return size;
433 	}
434 
435 	if (strlen(suffix) == 2 && suffix[1] == 'i')
436 		prefix_kind = 1024;
437 	else if (strlen(suffix) > 1)
438 		usage(1);
439 
440 	/* We follow the SI prefixes:
441 	   http://physics.nist.gov/cuu/Units/prefixes.html
442 	   http://physics.nist.gov/cuu/Units/binary.html
443 	   Disk partitioning tools use prefixes as,
444 	                       k        M          G
445 	   fdisk 2.11x-      2^10     2^20      10^3*2^20
446 	   fdisk 2.11y+     10^3     10^6       10^9
447 	   cfdisk           10^3     10^6       10^9
448 	   sfdisk            2^10     2^20
449 	   parted            2^10     2^20  (may change)
450 	   fdisk (DOS)       2^10     2^20
451 	*/
452 	/* FIXME: check for overflow */
453 	switch (*suffix) {
454 	case 'G':
455 		size *= prefix_kind;
456 		/* FALLTHRU */
457 	case 'M':
458 		size *= prefix_kind;
459 		/* FALLTHRU */
460 	case 'k':
461 		size *= prefix_kind;
462 		break;
463 	default:
464 		usage(1);
465 	}
466 
467 	return size;
468 }
469 
470 /**
471  * parse_options - Read and validate the programs command line
472  *
473  * Read the command line, verify the syntax and parse the options.
474  * This function is very long, but quite simple.
475  *
476  * Return:  1 Success
477  *	    0 Error, one or more problems
478  */
parse_options(int argc,char ** argv)479 static int parse_options(int argc, char **argv)
480 {
481 	static const char *sopt = "-bcdfhimnPs:vVx";
482 	static const struct option lopt[] = {
483 		{ "bad-sectors",no_argument,		NULL, 'b' },
484 		{ "check",	no_argument,		NULL, 'c' },
485 #ifdef DEBUG
486 		{ "debug",	no_argument,		NULL, 'd' },
487 #endif
488 		{ "force",	no_argument,		NULL, 'f' },
489 		{ "help",	no_argument,		NULL, 'h' },
490 		{ "info",	no_argument,		NULL, 'i' },
491 		{ "info-mb-only", no_argument,		NULL, 'm' },
492 		{ "no-action",	no_argument,		NULL, 'n' },
493 		{ "no-progress-bar", no_argument,	NULL, 'P' },
494 		{ "size",	required_argument,	NULL, 's' },
495 		{ "expand",	no_argument,		NULL, 'x' },
496 		{ "verbose",	no_argument,		NULL, 'v' },
497 		{ "version",	no_argument,		NULL, 'V' },
498 		{ NULL, 0, NULL, 0 }
499 	};
500 
501 	int c;
502 	int err  = 0;
503 	int ver  = 0;
504 	int help = 0;
505 
506 	memset(&opt, 0, sizeof(opt));
507 	opt.show_progress = 1;
508 
509 	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
510 		switch (c) {
511 		case 1:	/* A non-option argument */
512 			if (!err && !opt.volume)
513 				opt.volume = argv[optind-1];
514 			else
515 				err++;
516 			break;
517 		case 'b':
518 			opt.badsectors++;
519 			break;
520 		case 'c':
521 			opt.check++;
522 			break;
523 		case 'd':
524 			opt.debug++;
525 			break;
526 		case 'f':
527 			opt.force++;
528 			break;
529 		case 'h':
530 			help++;
531 			break;
532 		case 'i':
533 			opt.info++;
534 			break;
535 		case 'm':
536 			opt.infombonly++;
537 			break;
538 		case 'n':
539 			opt.ro_flag = NTFS_MNT_RDONLY;
540 			break;
541 		case 'P':
542 			opt.show_progress = 0;
543 			break;
544 		case 's':
545 			if (!err && (opt.bytes == 0))
546 				opt.bytes = get_new_volume_size(optarg);
547 			else
548 				err++;
549 			break;
550 		case 'v':
551 			opt.verbose++;
552 			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
553 			break;
554 		case 'V':
555 			ver++;
556 			break;
557 		case 'x':
558 			opt.expand++;
559 			break;
560 		case '?':
561 		default:
562 			if (optopt == 's') {
563 				printf("Option '%s' requires an argument.\n", argv[optind-1]);
564 			} else {
565 				printf("Unknown option '%s'.\n", argv[optind-1]);
566 			}
567 			err++;
568 			break;
569 		}
570 	}
571 
572 	if (!help && !ver) {
573 		if (opt.volume == NULL) {
574 			if (argc > 1)
575 				printf("You must specify exactly one device.\n");
576 			err++;
577 		}
578 		if (opt.info || opt.infombonly) {
579 			opt.ro_flag = NTFS_MNT_RDONLY;
580 		}
581 		if (opt.bytes
582 		    && (opt.expand || opt.info || opt.infombonly)) {
583 			printf(NERR_PREFIX "Options --info(-mb-only) and --expand "
584 					"cannot be used with --size.\n");
585 			usage(1);
586 		}
587 		if (opt.expand && opt.infombonly) {
588 			printf(NERR_PREFIX "Options --info-mb-only "
589 					"cannot be used with --expand.\n");
590 			usage(1);
591 		}
592 	}
593 
594 	/* Redirect stderr to stdout, note fflush()es are essential! */
595 	fflush(stdout);
596 	fflush(stderr);
597 	if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
598 		perr_exit("Failed to redirect stderr to stdout");
599 	fflush(stdout);
600 	fflush(stderr);
601 
602 #ifdef DEBUG
603 	if (!opt.debug)
604 		if (!freopen("/dev/null", "w", stderr))
605 			perr_exit("Failed to redirect stderr to /dev/null");
606 #endif
607 
608 	if (ver)
609 		version();
610 	if (help || err)
611 		usage(err > 0);
612 
613 		/* tri-state 0 : done, 1 : error, -1 : proceed */
614 	return (err ? 1 : (help || ver ? 0 : -1));
615 }
616 
print_advise(ntfs_volume * vol,s64 supp_lcn)617 static void print_advise(ntfs_volume *vol, s64 supp_lcn)
618 {
619 	s64 old_b, new_b, freed_b, old_mb, new_mb, freed_mb;
620 
621 	old_b = vol->nr_clusters * vol->cluster_size;
622 	old_mb = rounded_up_division(old_b, NTFS_MBYTE);
623 
624 	/* Take the next supported cluster (free or relocatable)
625 	   plus reserve a cluster for the backup boot sector */
626 	supp_lcn += 2;
627 
628 	if (supp_lcn > vol->nr_clusters) {
629 		err_printf("Very rare fragmentation type detected. "
630 			   "Sorry, it's not supported yet.\n"
631 			   "Try to defragment your NTFS, perhaps it helps.\n");
632 		exit(1);
633 	}
634 
635 	new_b = supp_lcn * vol->cluster_size;
636 	new_mb = rounded_up_division(new_b, NTFS_MBYTE);
637 	freed_b = (vol->nr_clusters - supp_lcn + 1) * vol->cluster_size;
638 	freed_mb = freed_b / NTFS_MBYTE;
639 
640 	/* WARNING: don't modify the text, external tools grep for it */
641 	if (!opt.infombonly)
642 		printf("You might resize at %lld bytes ", (long long)new_b);
643 	if ((new_mb * NTFS_MBYTE) < old_b) {
644 		if (!opt.infombonly)
645 			printf("or %lld MB ", (long long)new_mb);
646 		else
647 			printf("Minsize (in MB): %lld\n", (long long)new_mb);
648 	}
649 
650 	if (!opt.infombonly) {
651 		printf("(freeing ");
652 		if (freed_mb && (old_mb - new_mb))
653 			printf("%lld MB", (long long)(old_mb - new_mb));
654 		else
655 		        printf("%lld bytes", (long long)freed_b);
656 		printf(").\n");
657 
658 		printf("Please make a test run using both the -n and -s "
659 			"options before real resizing!\n");
660 	}
661 }
662 
rl_set(runlist * rl,VCN vcn,LCN lcn,s64 len)663 static void rl_set(runlist *rl, VCN vcn, LCN lcn, s64 len)
664 {
665 	rl->vcn = vcn;
666 	rl->lcn = lcn;
667 	rl->length = len;
668 }
669 
rl_items(runlist * rl)670 static int rl_items(runlist *rl)
671 {
672 	int i = 0;
673 
674 	while (rl[i++].length)
675 		;
676 
677 	return i;
678 }
679 
dump_run(runlist_element * r)680 static void dump_run(runlist_element *r)
681 {
682 	ntfs_log_verbose(" %8lld  %8lld (0x%08llx)  %lld\n", (long long)r->vcn,
683 			 (long long)r->lcn, (long long)r->lcn,
684 			 (long long)r->length);
685 }
686 
dump_runlist(runlist * rl)687 static void dump_runlist(runlist *rl)
688 {
689 	while (rl->length)
690 		dump_run(rl++);
691 }
692 
693 /**
694  * nr_clusters_to_bitmap_byte_size
695  *
696  * Take the number of clusters in the volume and calculate the size of $Bitmap.
697  * The size must be always a multiple of 8 bytes.
698  */
nr_clusters_to_bitmap_byte_size(s64 nr_clusters)699 static s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters)
700 {
701 	s64 bm_bsize;
702 
703 	bm_bsize = rounded_up_division(nr_clusters, 8);
704 	bm_bsize = (bm_bsize + 7) & ~7;
705 
706 	return bm_bsize;
707 }
708 
collect_resize_constraints(ntfs_resize_t * resize,runlist * rl)709 static void collect_resize_constraints(ntfs_resize_t *resize, runlist *rl)
710 {
711 	s64 inode, last_lcn;
712 	ATTR_FLAGS flags;
713 	ATTR_TYPES atype;
714 	struct llcn_t *llcn = NULL;
715 	int ret, supported = 0;
716 
717 	last_lcn = rl->lcn + (rl->length - 1);
718 
719 	inode = resize->ni->mft_no;
720 	flags = resize->ctx->attr->flags;
721 	atype = resize->ctx->attr->type;
722 
723 	if ((ret = ntfs_inode_badclus_bad(inode, resize->ctx->attr)) != 0) {
724 		if (ret == -1)
725 			perr_exit("Bad sector list check failed");
726 		return;
727 	}
728 
729 	if (inode == FILE_Bitmap) {
730 		llcn = &resize->last_lcn;
731 		if (atype == AT_DATA && NInoAttrList(resize->ni))
732 		    err_exit("Highly fragmented $Bitmap isn't supported yet.");
733 
734 		supported = 1;
735 
736 	} else if (NInoAttrList(resize->ni)) {
737 		llcn = &resize->last_multi_mft;
738 
739 		if (inode != FILE_MFTMirr)
740 			supported = 1;
741 
742 	} else if (flags & ATTR_IS_SPARSE) {
743 		llcn = &resize->last_sparse;
744 		supported = 1;
745 
746 	} else if (flags & ATTR_IS_COMPRESSED) {
747 		llcn = &resize->last_compressed;
748 		supported = 1;
749 
750 	} else if (inode == FILE_MFTMirr) {
751 		llcn = &resize->last_mftmir;
752 		supported = 1;
753 
754 		/* Fragmented $MFTMirr DATA attribute isn't supported yet */
755 		if (atype == AT_DATA)
756 			if (rl[1].length != 0 || rl->vcn)
757 				supported = 0;
758 	} else {
759 		llcn = &resize->last_lcn;
760 		supported = 1;
761 	}
762 
763 	if (llcn->lcn < last_lcn) {
764 		llcn->lcn = last_lcn;
765 		llcn->inode = inode;
766 	}
767 
768 	if (supported)
769 		return;
770 
771 	if (resize->last_unsupp < last_lcn)
772 		resize->last_unsupp = last_lcn;
773 }
774 
775 
collect_relocation_info(ntfs_resize_t * resize,runlist * rl)776 static void collect_relocation_info(ntfs_resize_t *resize, runlist *rl)
777 {
778 	s64 lcn, lcn_length, start, len, inode;
779 	s64 new_vol_size;	/* (last LCN on the volume) + 1 */
780 
781 	lcn = rl->lcn;
782 	lcn_length = rl->length;
783 	inode = resize->ni->mft_no;
784 	new_vol_size = resize->new_volume_size;
785 
786 	if (lcn + lcn_length <= new_vol_size)
787 		return;
788 
789 	if (inode == FILE_Bitmap && resize->ctx->attr->type == AT_DATA)
790 		return;
791 
792 	start = lcn;
793 	len = lcn_length;
794 
795 	if (lcn < new_vol_size) {
796 		start = new_vol_size;
797 		len = lcn_length - (new_vol_size - lcn);
798 
799 		if ((!opt.info && !opt.infombonly) && (inode == FILE_MFTMirr)) {
800 			err_printf("$MFTMirr can't be split up yet. Please try "
801 				   "a different size.\n");
802 			print_advise(resize->vol, lcn + lcn_length - 1);
803 			exit(1);
804 		}
805 	}
806 
807 	resize->relocations += len;
808 
809 	if ((!opt.info && !opt.infombonly) || !resize->new_volume_size)
810 		return;
811 
812 	printf("Relocation needed for inode %8lld attr 0x%x LCN 0x%08llx "
813 			"length %6lld\n", (long long)inode,
814 			(unsigned int)le32_to_cpu(resize->ctx->attr->type),
815 			(unsigned long long)start, (long long)len);
816 }
817 
818 /**
819  * build_lcn_usage_bitmap
820  *
821  * lcn_bitmap has one bit for each cluster on the disk.  Initially, lcn_bitmap
822  * has no bits set.  As each attribute record is read the bits in lcn_bitmap are
823  * checked to ensure that no other file already references that cluster.
824  *
825  * This serves as a rudimentary "chkdsk" operation.
826  */
build_lcn_usage_bitmap(ntfs_volume * vol,ntfsck_t * fsck)827 static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
828 {
829 	s64 inode;
830 	ATTR_RECORD *a;
831 	runlist *rl;
832 	int i, j;
833 	struct bitmap *lcn_bitmap = &fsck->lcn_bitmap;
834 
835 	a = fsck->ctx->attr;
836 	inode = fsck->ni->mft_no;
837 
838 	if (!a->non_resident)
839 		return;
840 
841 	if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) {
842 		int err = errno;
843 		perr_printf("ntfs_decompress_mapping_pairs");
844 		if (err == EIO)
845 			printf("%s", corrupt_volume_msg);
846 		exit(1);
847 	}
848 
849 
850 	for (i = 0; rl[i].length; i++) {
851 		s64 lcn = rl[i].lcn;
852 		s64 lcn_length = rl[i].length;
853 
854 		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
855 		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
856 			continue;
857 
858 		/* FIXME: ntfs_mapping_pairs_decompress should return error */
859 		if (lcn < 0 || lcn_length <= 0)
860 			err_exit("Corrupt runlist in inode %lld attr %x LCN "
861 				 "%llx length %llx\n", (long long)inode,
862 				 (unsigned int)le32_to_cpu(a->type),
863 				 (long long)lcn, (long long)lcn_length);
864 
865 		for (j = 0; j < lcn_length; j++) {
866 			u64 k = (u64)lcn + j;
867 
868 			if (k >= (u64)vol->nr_clusters) {
869 				long long outsiders = lcn_length - j;
870 
871 				fsck->outsider += outsiders;
872 
873 				if (++fsck->show_outsider <= 10 || opt.verbose)
874 					printf("Outside of the volume reference"
875 					       " for inode %lld at %lld:%lld\n",
876 					       (long long)inode, (long long)k,
877 					       (long long)outsiders);
878 
879 				break;
880 			}
881 
882 			if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) {
883 				if (++fsck->multi_ref <= 10 || opt.verbose)
884 					printf("Cluster %lld is referenced "
885 					       "multiple times!\n",
886 					       (long long)k);
887 				continue;
888 			}
889 		}
890 		fsck->inuse += lcn_length;
891 	}
892 	free(rl);
893 }
894 
895 
attr_get_search_ctx(ntfs_inode * ni,MFT_RECORD * mrec)896 static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
897 {
898 	ntfs_attr_search_ctx *ret;
899 
900 	if ((ret = ntfs_attr_get_search_ctx(ni, mrec)) == NULL)
901 		perr_printf("ntfs_attr_get_search_ctx");
902 
903 	return ret;
904 }
905 
906 /**
907  * walk_attributes
908  *
909  * For a given MFT Record, iterate through all its attributes.  Any non-resident
910  * data runs will be marked in lcn_bitmap.
911  */
walk_attributes(ntfs_volume * vol,ntfsck_t * fsck)912 static int walk_attributes(ntfs_volume *vol, ntfsck_t *fsck)
913 {
914 	if (!(fsck->ctx = attr_get_search_ctx(fsck->ni, NULL)))
915 		return -1;
916 
917 	while (!ntfs_attrs_walk(fsck->ctx)) {
918 		if (fsck->ctx->attr->type == AT_END)
919 			break;
920 		build_lcn_usage_bitmap(vol, fsck);
921 	}
922 
923 	ntfs_attr_put_search_ctx(fsck->ctx);
924 	return 0;
925 }
926 
927 /**
928  * compare_bitmaps
929  *
930  * Compare two bitmaps.  In this case, $Bitmap as read from the disk and
931  * lcn_bitmap which we built from the MFT Records.
932  */
compare_bitmaps(ntfs_volume * vol,struct bitmap * a)933 static void compare_bitmaps(ntfs_volume *vol, struct bitmap *a)
934 {
935 	s64 i, pos, count;
936 	int mismatch = 0;
937 	int backup_boot = 0;
938 	u8 bm[NTFS_BUF_SIZE];
939 
940         if (!opt.infombonly)
941 		printf("Accounting clusters ...\n");
942 
943 	pos = 0;
944 	while (1) {
945 		count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);
946 		if (count == -1)
947 			perr_exit("Couldn't get $Bitmap $DATA");
948 
949 		if (count == 0) {
950 			if (a->size > pos)
951 				err_exit("$Bitmap size is smaller than expected"
952 					 " (%lld != %lld)\n",
953 					 (long long)a->size, (long long)pos);
954 			break;
955 		}
956 
957 		for (i = 0; i < count; i++, pos++) {
958 			s64 cl;  /* current cluster */
959 
960 			if (a->size <= pos)
961 				goto done;
962 
963 			if (a->bm[pos] == bm[i])
964 				continue;
965 
966 			for (cl = pos * 8; cl < (pos + 1) * 8; cl++) {
967 				char bit;
968 
969 				bit = ntfs_bit_get(a->bm, cl);
970 				if (bit == ntfs_bit_get(bm, i * 8 + cl % 8))
971 					continue;
972 
973 				if (!mismatch && !bit && !backup_boot &&
974 						cl == vol->nr_clusters / 2) {
975 					/* FIXME: call also boot sector check */
976 					backup_boot = 1;
977 					printf("Found backup boot sector in "
978 					       "the middle of the volume.\n");
979 					continue;
980 				}
981 
982 				if (++mismatch > 10 && !opt.verbose)
983 					continue;
984 
985 				printf("Cluster accounting failed at %lld "
986 						"(0x%llx): %s cluster in "
987 						"$Bitmap\n", (long long)cl,
988 						(unsigned long long)cl,
989 						bit ? "missing" : "extra");
990 			}
991 		}
992 	}
993 done:
994 	if (mismatch) {
995 		printf("Filesystem check failed! Totally %d cluster "
996 		       "accounting mismatches.\n", mismatch);
997 		err_printf("%s", corrupt_volume_msg);
998 		exit(1);
999 	}
1000 }
1001 
1002 /**
1003  * progress_init
1004  *
1005  * Create and scale our progress bar.
1006  */
progress_init(struct progress_bar * p,u64 start,u64 stop,int flags)1007 static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags)
1008 {
1009 	p->start = start;
1010 	p->stop = stop;
1011 	p->unit = 100.0 / (stop - start);
1012 	p->resolution = 100;
1013 	p->flags = flags;
1014 }
1015 
1016 /**
1017  * progress_update
1018  *
1019  * Update the progress bar and tell the user.
1020  */
progress_update(struct progress_bar * p,u64 current)1021 static void progress_update(struct progress_bar *p, u64 current)
1022 {
1023 	float percent;
1024 
1025 	if (!(p->flags & NTFS_PROGBAR))
1026 		return;
1027 	if (p->flags & NTFS_PROGBAR_SUPPRESS)
1028 		return;
1029 
1030 	/* WARNING: don't modify the texts, external tools grep for them */
1031 	percent = p->unit * current;
1032 	if (current != p->stop) {
1033 		if ((current - p->start) % p->resolution)
1034 			return;
1035 		printf("%6.2f percent completed\r", percent);
1036 	} else
1037 		printf("100.00 percent completed\n");
1038 	fflush(stdout);
1039 }
1040 
inode_close(ntfs_inode * ni)1041 static int inode_close(ntfs_inode *ni)
1042 {
1043 	if (ntfs_inode_close(ni)) {
1044 		perr_printf("ntfs_inode_close for inode %llu",
1045 			    (unsigned long long)ni->mft_no);
1046 		return -1;
1047 	}
1048 	return 0;
1049 }
1050 
1051 /**
1052  * walk_inodes
1053  *
1054  * Read each record in the MFT, skipping the unused ones, and build up a bitmap
1055  * from all the non-resident attributes.
1056  */
build_allocation_bitmap(ntfs_volume * vol,ntfsck_t * fsck)1057 static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
1058 {
1059 	s64 nr_mft_records, inode = 0;
1060 	ntfs_inode *ni;
1061 	struct progress_bar progress;
1062 	int pb_flags = 0;	/* progress bar flags */
1063 
1064 	/* WARNING: don't modify the text, external tools grep for it */
1065         if (!opt.infombonly)
1066 		printf("Checking filesystem consistency ...\n");
1067 
1068 	if (fsck->flags & NTFSCK_PROGBAR)
1069 		pb_flags |= NTFS_PROGBAR;
1070 
1071 	nr_mft_records = vol->mft_na->initialized_size >>
1072 			vol->mft_record_size_bits;
1073 
1074 	progress_init(&progress, inode, nr_mft_records - 1, pb_flags);
1075 
1076 	for (; inode < nr_mft_records; inode++) {
1077         	if (!opt.infombonly)
1078 			progress_update(&progress, inode);
1079 
1080 		if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) {
1081 			/* FIXME: continue only if it make sense, e.g.
1082 			   MFT record not in use based on $MFT bitmap */
1083 			if (errno == EIO || errno == ENOENT)
1084 				continue;
1085 			perr_printf("Reading inode %lld failed",
1086 					(long long)inode);
1087 			return -1;
1088 		}
1089 
1090 		if (ni->mrec->base_mft_record)
1091 			goto close_inode;
1092 
1093 		fsck->ni = ni;
1094 		if (walk_attributes(vol, fsck) != 0) {
1095 			inode_close(ni);
1096 			return -1;
1097 		}
1098 close_inode:
1099 		if (inode_close(ni) != 0)
1100 			return -1;
1101 	}
1102 	return 0;
1103 }
1104 
build_resize_constraints(ntfs_resize_t * resize)1105 static void build_resize_constraints(ntfs_resize_t *resize)
1106 {
1107 	s64 i;
1108 	runlist *rl;
1109 
1110 	if (!resize->ctx->attr->non_resident)
1111 		return;
1112 
1113 	if (!(rl = ntfs_mapping_pairs_decompress(resize->vol,
1114 						 resize->ctx->attr, NULL)))
1115 		perr_exit("ntfs_decompress_mapping_pairs");
1116 
1117 	for (i = 0; rl[i].length; i++) {
1118 		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
1119 		if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
1120 			continue;
1121 
1122 		collect_resize_constraints(resize, rl + i);
1123 		if (resize->shrink)
1124 			collect_relocation_info(resize, rl + i);
1125 	}
1126 	free(rl);
1127 }
1128 
resize_constraints_by_attributes(ntfs_resize_t * resize)1129 static void resize_constraints_by_attributes(ntfs_resize_t *resize)
1130 {
1131 	if (!(resize->ctx = attr_get_search_ctx(resize->ni, NULL)))
1132 		exit(1);
1133 
1134 	while (!ntfs_attrs_walk(resize->ctx)) {
1135 		if (resize->ctx->attr->type == AT_END)
1136 			break;
1137 		build_resize_constraints(resize);
1138 	}
1139 
1140 	ntfs_attr_put_search_ctx(resize->ctx);
1141 }
1142 
set_resize_constraints(ntfs_resize_t * resize)1143 static void set_resize_constraints(ntfs_resize_t *resize)
1144 {
1145 	s64 nr_mft_records, inode;
1146 	ntfs_inode *ni;
1147 
1148         if (!opt.infombonly)
1149 		printf("Collecting resizing constraints ...\n");
1150 
1151 	nr_mft_records = resize->vol->mft_na->initialized_size >>
1152 			resize->vol->mft_record_size_bits;
1153 
1154 	for (inode = 0; inode < nr_mft_records; inode++) {
1155 
1156 		ni = ntfs_inode_open(resize->vol, (MFT_REF)inode);
1157 		if (ni == NULL) {
1158 			if (errno == EIO || errno == ENOENT)
1159 				continue;
1160 			perr_exit("Reading inode %lld failed",
1161 					(long long)inode);
1162 		}
1163 
1164 		if (ni->mrec->base_mft_record)
1165 			goto close_inode;
1166 
1167 		resize->ni = ni;
1168 		resize_constraints_by_attributes(resize);
1169 close_inode:
1170 		if (inode_close(ni) != 0)
1171 			exit(1);
1172 	}
1173 }
1174 
rl_fixup(runlist ** rl)1175 static void rl_fixup(runlist **rl)
1176 {
1177 	runlist *tmp = *rl;
1178 
1179 	if (tmp->lcn == LCN_RL_NOT_MAPPED) {
1180 		s64 unmapped_len = tmp->length;
1181 
1182 		ntfs_log_verbose("Skip unmapped run at the beginning ...\n");
1183 
1184 		if (!tmp->length)
1185 			err_exit("Empty unmapped runlist! Please report!\n");
1186 		(*rl)++;
1187 		for (tmp = *rl; tmp->length; tmp++)
1188 			tmp->vcn -= unmapped_len;
1189 	}
1190 
1191 	for (tmp = *rl; tmp->length; tmp++) {
1192 		if (tmp->lcn == LCN_RL_NOT_MAPPED) {
1193 			ntfs_log_verbose("Skip unmapped run at the end  ...\n");
1194 
1195 			if (tmp[1].length)
1196 				err_exit("Unmapped runlist in the middle! "
1197 					 "Please report!\n");
1198 			tmp->lcn = LCN_ENOENT;
1199 			tmp->length = 0;
1200 		}
1201 	}
1202 }
1203 
1204 /*
1205  *		Plug a replacement (partial) runlist into full runlist
1206  *
1207  *	Returns 0 if successful
1208  *		-1 if failed
1209  */
1210 
replace_runlist(ntfs_attr * na,const runlist_element * reprl,VCN lowest_vcn)1211 static int replace_runlist(ntfs_attr *na, const runlist_element *reprl,
1212 				VCN lowest_vcn)
1213 {
1214 	const runlist_element *prep;
1215 	const runlist_element *pold;
1216 	runlist_element *pnew;
1217 	runlist_element *newrl;
1218 	VCN nextvcn;
1219 	s32 oldcnt, newcnt;
1220 	s32 newsize;
1221 	int r;
1222 
1223 	r = -1; /* default return */
1224 		/* allocate a new runlist able to hold both */
1225 	oldcnt = 0;
1226 	while (na->rl[oldcnt].length)
1227 		oldcnt++;
1228 	newcnt = 0;
1229 	while (reprl[newcnt].length)
1230 		newcnt++;
1231 	newsize = ((oldcnt + newcnt)*sizeof(runlist_element) + 4095) & -4096;
1232 	newrl = (runlist_element*)malloc(newsize);
1233 	if (newrl) {
1234 		/* copy old runs until reaching replaced ones */
1235 		pnew = newrl;
1236 		pold = na->rl;
1237 		while (pold->length
1238 		    && ((pold->vcn + pold->length)
1239 				 <= (reprl[0].vcn + lowest_vcn))) {
1240 			*pnew = *pold;
1241 			pnew++;
1242 			pold++;
1243 		}
1244 		/* split a possible old run partially overlapped */
1245 		if (pold->length
1246 		    && (pold->vcn < (reprl[0].vcn + lowest_vcn))) {
1247 			pnew->vcn = pold->vcn;
1248 			pnew->lcn = pold->lcn;
1249 			pnew->length = reprl[0].vcn + lowest_vcn - pold->vcn;
1250 			pnew++;
1251 		}
1252 		/* copy new runs */
1253 		prep = reprl;
1254 		nextvcn = prep->vcn + lowest_vcn;
1255 		while (prep->length) {
1256 			pnew->vcn = prep->vcn + lowest_vcn;
1257 			pnew->lcn = prep->lcn;
1258 			pnew->length = prep->length;
1259 			nextvcn = pnew->vcn + pnew->length;
1260 			pnew++;
1261 			prep++;
1262 		}
1263 		/* locate the first fully replaced old run */
1264 		while (pold->length
1265 		    && ((pold->vcn + pold->length) <= nextvcn)) {
1266 			pold++;
1267 		}
1268 		/* split a possible old run partially overlapped */
1269 		if (pold->length
1270 		    && (pold->vcn < nextvcn)) {
1271 			pnew->vcn = nextvcn;
1272 			pnew->lcn = pold->lcn + nextvcn - pold->vcn;
1273 			pnew->length = pold->length - nextvcn + pold->vcn;
1274 			pnew++;
1275 		}
1276 		/* copy old runs beyond replaced ones */
1277 		while (pold->length) {
1278 			*pnew = *pold;
1279 			pnew++;
1280 			pold++;
1281 		}
1282 		/* the terminator is same as the old one */
1283 		*pnew = *pold;
1284 		/* deallocate the old runlist and replace */
1285 		free(na->rl);
1286 		na->rl = newrl;
1287 		r = 0;
1288 	}
1289 	return (r);
1290 }
1291 
1292 /*
1293  *		Expand the new runlist in new extent(s)
1294  *
1295  *	This implies allocating inode extents and, generally, creating
1296  *	an attribute list and allocating clusters for the list, and
1297  *	shuffle the existing attributes accordingly.
1298  *
1299  *	Sometimes the runlist being reallocated is within an extent,
1300  *	so we have a partial runlist to plug into an existing one
1301  *	whose other parts have already been processed or will have
1302  *	to be processed later, and we must not interfere with the
1303  *	processing of these parts.
1304  *
1305  *	This cannot be done on the runlist part stored in a single
1306  *	extent, it has to be done globally for the file.
1307  *
1308  *	We use the standard library functions, so we must wait until
1309  *	the new global bitmap and the new MFT bitmap are saved to
1310  *	disk and usable for the allocation of a new extent and creation
1311  *	of an attribute list.
1312  *
1313  *	Aborts if something goes wrong. There should be no data damage,
1314  *	because the old runlist is still in use and the bootsector has
1315  *	not been updated yet, so the initial clusters can be accessed.
1316  */
1317 
expand_attribute_runlist(ntfs_volume * vol,struct DELAYED * delayed)1318 static void expand_attribute_runlist(ntfs_volume *vol, struct DELAYED *delayed)
1319 {
1320 	ntfs_inode *ni;
1321 	ntfs_attr *na;
1322 	ATTR_TYPES type;
1323 	MFT_REF mref;
1324 	runlist_element *rl;
1325 
1326 		/* open the inode */
1327 	mref = delayed->mref;
1328 #ifndef BAN_NEW_TEXT
1329 	ntfs_log_verbose("Processing a delayed update for inode %lld\n",
1330 					(long long)mref);
1331 #endif
1332 	type = delayed->type;
1333 	rl = delayed->rl;
1334 
1335 	/* The MFT inode is permanently open, do not reopen or close */
1336 	if (mref == FILE_MFT)
1337 		ni = vol->mft_ni;
1338 	else
1339 		ni = ntfs_inode_open(vol,mref);
1340 	if (ni) {
1341 		if (mref == FILE_MFT)
1342 			na = (type == AT_DATA ? vol->mft_na : vol->mftbmp_na);
1343 		else
1344 			na = ntfs_attr_open(ni, type,
1345 					delayed->attr_name, delayed->name_len);
1346 		if (na) {
1347 			/*
1348 			 * The runlist is first updated in memory, and
1349 			 * the updated one is used for updating on device
1350 			 */
1351 			if (!ntfs_attr_map_whole_runlist(na)) {
1352 				if (replace_runlist(na,rl,delayed->lowest_vcn)
1353 				    || ntfs_attr_update_mapping_pairs(na,0))
1354 					perr_exit("Could not update runlist "
1355 						"for attribute 0x%lx in inode %lld",
1356 						(long)le32_to_cpu(type),(long long)mref);
1357 			} else
1358 				perr_exit("Could not map attribute 0x%lx in inode %lld",
1359 					(long)le32_to_cpu(type),(long long)mref);
1360 			if (mref != FILE_MFT)
1361 				ntfs_attr_close(na);
1362 		} else
1363 			perr_exit("Could not open attribute 0x%lx in inode %lld",
1364 				(long)le32_to_cpu(type),(long long)mref);
1365 		ntfs_inode_mark_dirty(ni);
1366 		if ((mref != FILE_MFT) && ntfs_inode_close(ni))
1367 			perr_exit("Failed to close inode %lld through the library",
1368 				(long long)mref);
1369 	} else
1370 		perr_exit("Could not open inode %lld through the library",
1371 			(long long)mref);
1372 }
1373 
1374 /*
1375  *		Reload the MFT before merging delayed updates of runlist
1376  *
1377  *	The delayed updates of runlists are those which imply updating
1378  *	the runlists which overflow from their original MFT record.
1379  *	Such updates must be done in the new location of the MFT and
1380  *	the allocations must be recorded in the new location of the
1381  *	MFT bitmap.
1382  *	The MFT data and MFT bitmap may themselves have delayed parts
1383  *	of their runlists, and at this stage, their runlists may have
1384  *	been partially updated on disk, and partially to be updated.
1385  *	Their in-memory runlists still point at the old location, they
1386  *	are obsolete, and we have to read the partially updated runlist
1387  *	from the device before merging the delayed updates.
1388  *
1389  *	Returns 0 if successful
1390  *		-1 otherwise
1391  */
1392 
reload_mft(ntfs_resize_t * resize)1393 static int reload_mft(ntfs_resize_t *resize)
1394 {
1395 	ntfs_inode *ni;
1396 	ntfs_attr *na;
1397 	int r;
1398 	int xi;
1399 
1400 	r = 0;
1401 		/* get the base inode */
1402 	ni = resize->vol->mft_ni;
1403 	if (!ntfs_file_record_read(resize->vol, FILE_MFT, &ni->mrec, NULL)) {
1404 		for (xi=0; !r && xi<resize->vol->mft_ni->nr_extents; xi++) {
1405 			r = ntfs_file_record_read(resize->vol,
1406 					ni->extent_nis[xi]->mft_no,
1407 					&ni->extent_nis[xi]->mrec, NULL);
1408 		}
1409 
1410 		if (!r) {
1411 			/* reopen the MFT bitmap, and swap vol->mftbmp_na */
1412 			na = ntfs_attr_open(resize->vol->mft_ni,
1413 						AT_BITMAP, NULL, 0);
1414 			if (na && !ntfs_attr_map_whole_runlist(na)) {
1415 				ntfs_attr_close(resize->vol->mftbmp_na);
1416 				resize->vol->mftbmp_na = na;
1417 			} else
1418 				r = -1;
1419 		}
1420 
1421 		if (!r) {
1422 			/* reopen the MFT data, and swap vol->mft_na */
1423 			na = ntfs_attr_open(resize->vol->mft_ni,
1424 						AT_DATA, NULL, 0);
1425 			if (na && !ntfs_attr_map_whole_runlist(na)) {
1426 				ntfs_attr_close(resize->vol->mft_na);
1427 				resize->vol->mft_na = na;
1428 			} else
1429 				r = -1;
1430 		}
1431 	} else
1432 		r = -1;
1433 	return (r);
1434 }
1435 
1436 /*
1437  *		Re-record the MFT extents in MFT bitmap
1438  *
1439  *	When both MFT data and MFT bitmap have delayed runlists, MFT data
1440  *	is updated first, and the extents may be recorded at old location.
1441  */
1442 
record_mft_in_bitmap(ntfs_resize_t * resize)1443 static int record_mft_in_bitmap(ntfs_resize_t *resize)
1444 {
1445 	ntfs_inode *ni;
1446 	int r;
1447 	int xi;
1448 
1449 	r = 0;
1450 		/* get the base inode */
1451 	ni = resize->vol->mft_ni;
1452 	for (xi=0; !r && xi<resize->vol->mft_ni->nr_extents; xi++) {
1453 		r = ntfs_bitmap_set_run(resize->vol->mftbmp_na,
1454 					ni->extent_nis[xi]->mft_no, 1);
1455 	}
1456 	return (r);
1457 }
1458 
1459 /*
1460  *		Process delayed runlist updates
1461  */
1462 
delayed_updates(ntfs_resize_t * resize)1463 static void delayed_updates(ntfs_resize_t *resize)
1464 {
1465 	struct DELAYED *delayed;
1466 	struct DELAYED *delayed_mft_data;
1467 	int nr_extents;
1468 
1469 	if (ntfs_volume_get_free_space(resize->vol))
1470 		err_exit("Failed to determine free space\n");
1471 
1472 	delayed_mft_data = (struct DELAYED*)NULL;
1473 	if (resize->delayed_runlists && reload_mft(resize))
1474 		err_exit("Failed to reload the MFT for delayed updates\n");
1475 
1476 		/*
1477 		 * Important : updates to MFT must come first, so that
1478 		 * the new location of MFT is used for adding needed extents.
1479 		 * Now, there are runlists in the MFT bitmap and MFT data.
1480 		 * Extents to MFT bitmap have to be stored in the new MFT
1481 		 * data, and extents to MFT data have to be recorded in
1482 		 * the MFT bitmap.
1483 		 * So we update MFT data first, and we record the MFT
1484 		 * extents again in the MFT bitmap if they were recorded
1485 		 * in the old location.
1486 		 *
1487 		 * However, if we are operating in "no action" mode, the
1488 		 * MFT records to update are not written to their new location
1489 		 * and the MFT data runlist has to be updated last in order
1490 		 * to have the entries read from their old location.
1491 		 * In this situation the MFT bitmap is never written to
1492 		 * disk, so the same extents are reallocated repeatedly,
1493 		 * which is not what would be done in a real resizing.
1494 		 */
1495 
1496 	if (opt.ro_flag
1497 	    && resize->delayed_runlists
1498 	    && (resize->delayed_runlists->mref == FILE_MFT)
1499 	    && (resize->delayed_runlists->type == AT_DATA)) {
1500 			/* Update the MFT data runlist later */
1501 		delayed_mft_data = resize->delayed_runlists;
1502 		resize->delayed_runlists = resize->delayed_runlists->next;
1503 	}
1504 
1505 	while (resize->delayed_runlists) {
1506 		delayed = resize->delayed_runlists;
1507 		expand_attribute_runlist(resize->vol, delayed);
1508 		if (delayed->mref == FILE_MFT) {
1509 			if (delayed->type == AT_BITMAP)
1510 				record_mft_in_bitmap(resize);
1511 			if (delayed->type == AT_DATA)
1512 				resize->mirr_from = MIRR_MFT;
1513 		}
1514 		resize->delayed_runlists = resize->delayed_runlists->next;
1515 		if (delayed->attr_name)
1516 			free(delayed->attr_name);
1517 		free(delayed->head_rl);
1518 		free(delayed);
1519 	}
1520 	if (opt.ro_flag && delayed_mft_data) {
1521 		/* in "no action" mode, check updating the MFT runlist now */
1522 		expand_attribute_runlist(resize->vol, delayed_mft_data);
1523 		resize->mirr_from = MIRR_MFT;
1524 		if (delayed_mft_data->attr_name)
1525 			free(delayed_mft_data->attr_name);
1526 		free(delayed_mft_data->head_rl);
1527 		free(delayed_mft_data);
1528 	}
1529 	/* Beware of MFT fragmentation when the target size is too small */
1530 	nr_extents = resize->vol->mft_ni->nr_extents;
1531 	if (nr_extents > 2) {
1532 		printf("WARNING: The MFT is now severely fragmented"
1533 			" (%d extents)\n", nr_extents);
1534 	}
1535 }
1536 
1537 /*
1538  *		Queue a runlist replacement for later update
1539  *
1540  *	Store the attribute identification relative to base inode
1541  */
1542 
replace_later(ntfs_resize_t * resize,runlist * rl,runlist * head_rl)1543 static void replace_later(ntfs_resize_t *resize, runlist *rl, runlist *head_rl)
1544 {
1545 	struct DELAYED *delayed;
1546 	struct DELAYED *previous;
1547 	ATTR_RECORD *a;
1548 	MFT_REF mref;
1549 	leMFT_REF lemref;
1550 	int name_len;
1551 	ntfschar *attr_name;
1552 
1553 		/* save the attribute parameters, to be able to find it later */
1554 	a = resize->ctx->attr;
1555 	name_len = a->name_length;
1556 	attr_name = (ntfschar*)NULL;
1557 	if (name_len) {
1558 		attr_name = (ntfschar*)ntfs_malloc(name_len*sizeof(ntfschar));
1559 		if (attr_name)
1560 			memcpy(attr_name,(u8*)a + le16_to_cpu(a->name_offset),
1561 					name_len*sizeof(ntfschar));
1562 	}
1563 	delayed = (struct DELAYED*)ntfs_malloc(sizeof(struct DELAYED));
1564 	if (delayed && (attr_name || !name_len)) {
1565 		lemref = resize->ctx->mrec->base_mft_record;
1566 		if (lemref)
1567 			mref = le64_to_cpu(lemref);
1568 		else
1569 			mref = resize->mref;
1570 		delayed->mref = MREF(mref);
1571 		delayed->type = a->type;
1572 		delayed->attr_name = attr_name;
1573 		delayed->name_len = name_len;
1574 		delayed->lowest_vcn = sle64_to_cpu(a->lowest_vcn);
1575 		delayed->rl = rl;
1576 		delayed->head_rl = head_rl;
1577 		/* Queue ahead of list if this is MFT or head is not MFT */
1578 		if ((delayed->mref == FILE_MFT)
1579 		    || !resize->delayed_runlists
1580 		    || (resize->delayed_runlists->mref != FILE_MFT)) {
1581 			delayed->next = resize->delayed_runlists;
1582 			resize->delayed_runlists = delayed;
1583 		} else {
1584 			/* Queue after all MFTs is this is not MFT */
1585 			previous = resize->delayed_runlists;
1586 			while (previous->next
1587 			    && (previous->next->mref == FILE_MFT))
1588 				previous = previous->next;
1589 			delayed->next = previous->next;
1590 			previous->next = delayed;
1591 		}
1592 	} else
1593 		perr_exit("Could not store delayed update data");
1594 }
1595 
1596 /*
1597  *		Replace the runlist in an attribute
1598  *
1599  *	This sometimes requires expanding the runlist into another extent,
1600  *	which has to be done globally on the attribute. Is so, the action
1601  *	is put in a delay queue, and the caller must not free the runlist.
1602  *
1603  *	Returns 0 if the replacement could be done
1604  *		1 when it has been put in the delay queue.
1605  */
1606 
replace_attribute_runlist(ntfs_resize_t * resize,runlist * rl)1607 static int replace_attribute_runlist(ntfs_resize_t *resize, runlist *rl)
1608 {
1609 	int mp_size, l;
1610 	int must_delay;
1611 	void *mp;
1612 	runlist *head_rl;
1613 	ntfs_volume *vol;
1614 	ntfs_attr_search_ctx *ctx;
1615 	ATTR_RECORD *a;
1616 
1617 	vol = resize->vol;
1618 	ctx = resize->ctx;
1619 	a = ctx->attr;
1620 	head_rl = rl;
1621 	rl_fixup(&rl);
1622 
1623 	if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0, INT_MAX)) == -1)
1624 		perr_exit("ntfs_get_size_for_mapping_pairs");
1625 
1626 	if (a->name_length) {
1627 		u16 name_offs = le16_to_cpu(a->name_offset);
1628 		u16 mp_offs = le16_to_cpu(a->mapping_pairs_offset);
1629 
1630 		if (name_offs >= mp_offs)
1631 			err_exit("Attribute name is after mapping pairs! "
1632 				 "Please report!\n");
1633 	}
1634 
1635 	/* CHECKME: don't trust mapping_pairs is always the last item in the
1636 	   attribute, instead check for the real size/space */
1637 	l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->mapping_pairs_offset);
1638 	must_delay = 0;
1639 	if (mp_size > l) {
1640 		s32 remains_size;
1641 		char *next_attr;
1642 
1643 		ntfs_log_verbose("Enlarging attribute header ...\n");
1644 
1645 		mp_size = (mp_size + 7) & ~7;
1646 
1647 		ntfs_log_verbose("Old mp size      : %d\n", l);
1648 		ntfs_log_verbose("New mp size      : %d\n", mp_size);
1649 		ntfs_log_verbose("Bytes in use     : %u\n", (unsigned int)
1650 				 le32_to_cpu(ctx->mrec->bytes_in_use));
1651 
1652 		next_attr = (char *)a + le32_to_cpu(a->length);
1653 		l = mp_size - l;
1654 
1655 		ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
1656 				 le32_to_cpu(ctx->mrec->bytes_in_use));
1657 		ntfs_log_verbose("Bytes allocated  : %u\n", (unsigned int)
1658 				 le32_to_cpu(ctx->mrec->bytes_allocated));
1659 
1660 		remains_size = le32_to_cpu(ctx->mrec->bytes_in_use);
1661 		remains_size -= (next_attr - (char *)ctx->mrec);
1662 
1663 		ntfs_log_verbose("increase         : %d\n", l);
1664 		ntfs_log_verbose("shift            : %lld\n",
1665 				 (long long)remains_size);
1666 		if (le32_to_cpu(ctx->mrec->bytes_in_use) + l >
1667 				le32_to_cpu(ctx->mrec->bytes_allocated)) {
1668 #ifndef BAN_NEW_TEXT
1669 			ntfs_log_verbose("Queuing expansion for later processing\n");
1670 #endif
1671 			must_delay = 1;
1672 			replace_later(resize,rl,head_rl);
1673 		} else {
1674 			memmove(next_attr + l, next_attr, remains_size);
1675 			ctx->mrec->bytes_in_use = cpu_to_le32(l +
1676 					le32_to_cpu(ctx->mrec->bytes_in_use));
1677 			a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
1678 		}
1679 	}
1680 
1681 	if (!must_delay) {
1682 		mp = ntfs_calloc(mp_size);
1683 		if (!mp)
1684 			perr_exit("ntfsc_calloc couldn't get memory");
1685 
1686 		if (ntfs_mapping_pairs_build(vol, (u8*)mp, mp_size, rl, 0, NULL))
1687 			perr_exit("ntfs_mapping_pairs_build");
1688 
1689 		memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size);
1690 
1691 		free(mp);
1692 	}
1693 	return (must_delay);
1694 }
1695 
set_bitmap_range(struct bitmap * bm,s64 pos,s64 length,u8 bit)1696 static void set_bitmap_range(struct bitmap *bm, s64 pos, s64 length, u8 bit)
1697 {
1698 	while (length--)
1699 		ntfs_bit_set(bm->bm, pos++, bit);
1700 }
1701 
set_bitmap_clusters(struct bitmap * bm,runlist * rl,u8 bit)1702 static void set_bitmap_clusters(struct bitmap *bm, runlist *rl, u8 bit)
1703 {
1704 	for (; rl->length; rl++)
1705 		set_bitmap_range(bm, rl->lcn, rl->length, bit);
1706 }
1707 
release_bitmap_clusters(struct bitmap * bm,runlist * rl)1708 static void release_bitmap_clusters(struct bitmap *bm, runlist *rl)
1709 {
1710 	max_free_cluster_range = 0;
1711 	set_bitmap_clusters(bm, rl, 0);
1712 }
1713 
set_max_free_zone(s64 length,s64 end,runlist_element * rle)1714 static void set_max_free_zone(s64 length, s64 end, runlist_element *rle)
1715 {
1716 	if (length > rle->length) {
1717 		rle->lcn = end - length;
1718 		rle->length = length;
1719 	}
1720 }
1721 
find_free_cluster(struct bitmap * bm,runlist_element * rle,s64 nr_vol_clusters,int hint)1722 static int find_free_cluster(struct bitmap *bm,
1723 			     runlist_element *rle,
1724 			     s64 nr_vol_clusters,
1725 			     int hint)
1726 {
1727 	/* FIXME: get rid of this 'static' variable */
1728 	static s64 pos = 0;
1729 	s64 i, items = rle->length;
1730 	s64 free_zone = 0;
1731 
1732 	if (pos >= nr_vol_clusters)
1733 		pos = 0;
1734 	if (!max_free_cluster_range)
1735 		max_free_cluster_range = nr_vol_clusters;
1736 	rle->lcn = rle->length = 0;
1737 	if (hint)
1738 		pos = nr_vol_clusters / 2;
1739 	i = pos;
1740 
1741 	do {
1742 		if (!ntfs_bit_get(bm->bm, i)) {
1743 			if (++free_zone == items) {
1744 				set_max_free_zone(free_zone, i + 1, rle);
1745 				break;
1746 			}
1747 		} else {
1748 			set_max_free_zone(free_zone, i, rle);
1749 			free_zone = 0;
1750 		}
1751 		if (++i == nr_vol_clusters) {
1752 			set_max_free_zone(free_zone, i, rle);
1753 			i = free_zone = 0;
1754 		}
1755 		if (rle->length == max_free_cluster_range)
1756 			break;
1757 	} while (i != pos);
1758 
1759 	if (i)
1760 		set_max_free_zone(free_zone, i, rle);
1761 
1762 	if (!rle->lcn) {
1763 		errno = ENOSPC;
1764 		return -1;
1765 	}
1766 	if (rle->length < items && rle->length < max_free_cluster_range) {
1767 		max_free_cluster_range = rle->length;
1768 		ntfs_log_verbose("Max free range: %7lld     \n",
1769 				 (long long)max_free_cluster_range);
1770 	}
1771 	pos = rle->lcn + items;
1772 	if (pos == nr_vol_clusters)
1773 		pos = 0;
1774 
1775 	set_bitmap_range(bm, rle->lcn, rle->length, 1);
1776 	return 0;
1777 }
1778 
alloc_cluster(struct bitmap * bm,s64 items,s64 nr_vol_clusters,int hint)1779 static runlist *alloc_cluster(struct bitmap *bm,
1780 			      s64 items,
1781 			      s64 nr_vol_clusters,
1782 			      int hint)
1783 {
1784 	runlist_element rle;
1785 	runlist *rl = NULL;
1786 	int rl_size, runs = 0;
1787 	s64 vcn = 0;
1788 
1789 	if (items <= 0) {
1790 		errno = EINVAL;
1791 		return NULL;
1792 	}
1793 
1794 	while (items > 0) {
1795 
1796 		if (runs)
1797 			hint = 0;
1798 		rle.length = items;
1799 		if (find_free_cluster(bm, &rle, nr_vol_clusters, hint) == -1)
1800 			return NULL;
1801 
1802 		rl_size = (runs + 2) * sizeof(runlist_element);
1803 		if (!(rl = (runlist *)realloc(rl, rl_size)))
1804 			return NULL;
1805 
1806 		rl_set(rl + runs, vcn, rle.lcn, rle.length);
1807 
1808 		vcn += rle.length;
1809 		items -= rle.length;
1810 		runs++;
1811 	}
1812 
1813 	rl_set(rl + runs, vcn, -1LL, 0LL);
1814 
1815 	if (runs > 1) {
1816 		ntfs_log_verbose("Multi-run allocation:    \n");
1817 		dump_runlist(rl);
1818 	}
1819 	return rl;
1820 }
1821 
read_all(struct ntfs_device * dev,void * buf,int count)1822 static int read_all(struct ntfs_device *dev, void *buf, int count)
1823 {
1824 	int i;
1825 
1826 	while (count > 0) {
1827 
1828 		i = count;
1829 		if (!NDevReadOnly(dev))
1830 			i = dev->d_ops->read(dev, buf, count);
1831 
1832 		if (i < 0) {
1833 			if (errno != EAGAIN && errno != EINTR)
1834 				return -1;
1835 		} else if (i > 0) {
1836 			count -= i;
1837 			buf = i + (char *)buf;
1838 		} else
1839 			err_exit("Unexpected end of file!\n");
1840 	}
1841 	return 0;
1842 }
1843 
write_all(struct ntfs_device * dev,void * buf,int count)1844 static int write_all(struct ntfs_device *dev, void *buf, int count)
1845 {
1846 	int i;
1847 
1848 	while (count > 0) {
1849 
1850 		i = count;
1851 		if (!NDevReadOnly(dev))
1852 			i = dev->d_ops->write(dev, buf, count);
1853 
1854 		if (i < 0) {
1855 			if (errno != EAGAIN && errno != EINTR)
1856 				return -1;
1857 		} else {
1858 			count -= i;
1859 			buf = i + (char *)buf;
1860 		}
1861 	}
1862 	return 0;
1863 }
1864 
1865 /**
1866  * write_mft_record
1867  *
1868  * Write an MFT Record back to the disk.  If the read-only command line option
1869  * was given, this function will do nothing.
1870  */
write_mft_record(ntfs_volume * v,const MFT_REF mref,MFT_RECORD * buf)1871 static int write_mft_record(ntfs_volume *v, const MFT_REF mref, MFT_RECORD *buf)
1872 {
1873 	if (ntfs_mft_record_write(v, mref, buf))
1874 		perr_exit("ntfs_mft_record_write");
1875 
1876 //	if (v->dev->d_ops->sync(v->dev) == -1)
1877 //		perr_exit("Failed to sync device");
1878 
1879 	return 0;
1880 }
1881 
lseek_to_cluster(ntfs_volume * vol,s64 lcn)1882 static void lseek_to_cluster(ntfs_volume *vol, s64 lcn)
1883 {
1884 	off_t pos;
1885 
1886 	pos = (off_t)(lcn * vol->cluster_size);
1887 
1888 	if (vol->dev->d_ops->seek(vol->dev, pos, SEEK_SET) == (off_t)-1)
1889 		perr_exit("seek failed to position %lld", (long long)lcn);
1890 }
1891 
copy_clusters(ntfs_resize_t * resize,s64 dest,s64 src,s64 len)1892 static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len)
1893 {
1894 	s64 i;
1895 	char *buff;
1896 	ntfs_volume *vol = resize->vol;
1897 
1898 	buff = (char*)ntfs_malloc(vol->cluster_size);
1899 	if (!buff)
1900 		perr_exit("ntfs_malloc");
1901 
1902 	for (i = 0; i < len; i++) {
1903 
1904 		lseek_to_cluster(vol, src + i);
1905 
1906 		if (read_all(vol->dev, buff, vol->cluster_size) == -1) {
1907 			perr_printf("Failed to read from the disk");
1908 			if (errno == EIO)
1909 				printf("%s", bad_sectors_warning_msg);
1910 			exit(1);
1911 		}
1912 
1913 		lseek_to_cluster(vol, dest + i);
1914 
1915 		if (write_all(vol->dev, buff, vol->cluster_size) == -1) {
1916 			perr_printf("Failed to write to the disk");
1917 			if (errno == EIO)
1918 				printf("%s", bad_sectors_warning_msg);
1919 			exit(1);
1920 		}
1921 
1922 		resize->relocations++;
1923 		progress_update(&resize->progress, resize->relocations);
1924 	}
1925 	free(buff);
1926 }
1927 
relocate_clusters(ntfs_resize_t * r,runlist * dest_rl,s64 src_lcn)1928 static void relocate_clusters(ntfs_resize_t *r, runlist *dest_rl, s64 src_lcn)
1929 {
1930 	/* collect_shrink_constraints() ensured $MFTMir DATA is one run */
1931 	if (r->mref == FILE_MFTMirr && r->ctx->attr->type == AT_DATA) {
1932 		if (!r->mftmir_old) {
1933 			r->mftmir_rl.lcn = dest_rl->lcn;
1934 			r->mftmir_rl.length = dest_rl->length;
1935 			r->mftmir_old = src_lcn;
1936 		} else
1937 			err_exit("Multi-run $MFTMirr. Please report!\n");
1938 	}
1939 
1940 	for (; dest_rl->length; src_lcn += dest_rl->length, dest_rl++)
1941 		copy_clusters(r, dest_rl->lcn, src_lcn, dest_rl->length);
1942 }
1943 
rl_split_run(runlist ** rl,int run,s64 pos)1944 static void rl_split_run(runlist **rl, int run, s64 pos)
1945 {
1946 	runlist *rl_new, *rle_new, *rle;
1947 	int items, new_size, size_head, size_tail;
1948 	s64 len_head, len_tail;
1949 
1950 	items = rl_items(*rl);
1951 	new_size = (items + 1) * sizeof(runlist_element);
1952 	size_head = run * sizeof(runlist_element);
1953 	size_tail = (items - run - 1) * sizeof(runlist_element);
1954 
1955 	rl_new = ntfs_malloc(new_size);
1956 	if (!rl_new)
1957 		perr_exit("ntfs_malloc");
1958 
1959 	rle_new = rl_new + run;
1960 	rle = *rl + run;
1961 
1962 	memmove(rl_new, *rl, size_head);
1963 	memmove(rle_new + 2, rle + 1, size_tail);
1964 
1965 	len_tail = rle->length - (pos - rle->lcn);
1966 	len_head = rle->length - len_tail;
1967 
1968 	rl_set(rle_new, rle->vcn, rle->lcn, len_head);
1969 	rl_set(rle_new + 1, rle->vcn + len_head, rle->lcn + len_head, len_tail);
1970 
1971 	ntfs_log_verbose("Splitting run at cluster %lld:\n", (long long)pos);
1972 	dump_run(rle); dump_run(rle_new); dump_run(rle_new + 1);
1973 
1974 	free(*rl);
1975 	*rl = rl_new;
1976 }
1977 
rl_insert_at_run(runlist ** rl,int run,runlist * ins)1978 static void rl_insert_at_run(runlist **rl, int run, runlist *ins)
1979 {
1980 	int items, ins_items;
1981 	int new_size, size_tail;
1982 	runlist *rle;
1983 	s64 vcn;
1984 
1985 	items  = rl_items(*rl);
1986 	ins_items = rl_items(ins) - 1;
1987 	new_size = ((items - 1) + ins_items) * sizeof(runlist_element);
1988 	size_tail = (items - run - 1) * sizeof(runlist_element);
1989 
1990 	if (!(*rl = (runlist *)realloc(*rl, new_size)))
1991 		perr_exit("realloc");
1992 
1993 	rle = *rl + run;
1994 
1995 	memmove(rle + ins_items, rle + 1, size_tail);
1996 
1997 	for (vcn = rle->vcn; ins->length; rle++, vcn += ins->length, ins++) {
1998 		rl_set(rle, vcn, ins->lcn, ins->length);
1999 //		dump_run(rle);
2000 	}
2001 
2002 	return;
2003 
2004 	/* FIXME: fast path if ins_items = 1 */
2005 //	(*rl + run)->lcn = ins->lcn;
2006 }
2007 
relocate_run(ntfs_resize_t * resize,runlist ** rl,int run)2008 static void relocate_run(ntfs_resize_t *resize, runlist **rl, int run)
2009 {
2010 	s64 lcn, lcn_length;
2011 	s64 new_vol_size;	/* (last LCN on the volume) + 1 */
2012 	runlist *relocate_rl;	/* relocate runlist to relocate_rl */
2013 	int hint;
2014 
2015 	lcn = (*rl + run)->lcn;
2016 	lcn_length = (*rl + run)->length;
2017 	new_vol_size = resize->new_volume_size;
2018 
2019 	if (lcn + lcn_length <= new_vol_size)
2020 		return;
2021 
2022 	if (lcn < new_vol_size) {
2023 		rl_split_run(rl, run, new_vol_size);
2024 		return;
2025 	}
2026 
2027 	hint = (resize->mref == FILE_MFTMirr) ? 1 : 0;
2028 	if ((resize->mref == FILE_MFT)
2029 	    && (resize->ctx->attr->type == AT_DATA)
2030 	    && !run
2031 	    && resize->new_mft_start) {
2032 		relocate_rl = resize->new_mft_start;
2033 	} else
2034 		if (!(relocate_rl = alloc_cluster(&resize->lcn_bitmap,
2035 					lcn_length, new_vol_size, hint)))
2036 			perr_exit("Cluster allocation failed for %llu:%lld",
2037 				  (unsigned long long)resize->mref,
2038 				  (long long)lcn_length);
2039 
2040 	/* FIXME: check $MFTMirr DATA isn't multi-run (or support it) */
2041 	ntfs_log_verbose("Relocate record %7llu:0x%x:%08lld:0x%08llx:0x%08llx "
2042 			 "--> 0x%08llx\n", (unsigned long long)resize->mref,
2043 			 (unsigned int)le32_to_cpu(resize->ctx->attr->type),
2044 			 (long long)lcn_length,
2045 			 (unsigned long long)(*rl + run)->vcn,
2046 			 (unsigned long long)lcn,
2047 			 (unsigned long long)relocate_rl->lcn);
2048 
2049 	relocate_clusters(resize, relocate_rl, lcn);
2050 	rl_insert_at_run(rl, run, relocate_rl);
2051 
2052 	/* We don't release old clusters in the bitmap, that area isn't
2053 	   used by the allocator and will be truncated later on */
2054 
2055 		/* Do not free the relocated MFT start */
2056 	if ((resize->mref != FILE_MFT)
2057 	    || (resize->ctx->attr->type != AT_DATA)
2058 	    || run
2059 	    || !resize->new_mft_start)
2060 		free(relocate_rl);
2061 
2062 	resize->dirty_inode = DIRTY_ATTRIB;
2063 }
2064 
relocate_attribute(ntfs_resize_t * resize)2065 static void relocate_attribute(ntfs_resize_t *resize)
2066 {
2067 	ATTR_RECORD *a;
2068 	runlist *rl;
2069 	int i;
2070 
2071 	a = resize->ctx->attr;
2072 
2073 	if (!a->non_resident)
2074 		return;
2075 
2076 	if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, a, NULL)))
2077 		perr_exit("ntfs_decompress_mapping_pairs");
2078 
2079 	for (i = 0; rl[i].length; i++) {
2080 		s64 lcn = rl[i].lcn;
2081 		s64 lcn_length = rl[i].length;
2082 
2083 		if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
2084 			continue;
2085 
2086 		/* FIXME: ntfs_mapping_pairs_decompress should return error */
2087 		if (lcn < 0 || lcn_length <= 0)
2088 			err_exit("Corrupt runlist in MTF %llu attr %x LCN "
2089 				 "%llx length %llx\n",
2090 				 (unsigned long long)resize->mref,
2091 				 (unsigned int)le32_to_cpu(a->type),
2092 				 (long long)lcn, (long long)lcn_length);
2093 
2094 		relocate_run(resize, &rl, i);
2095 	}
2096 
2097 	if (resize->dirty_inode == DIRTY_ATTRIB) {
2098 		if (!replace_attribute_runlist(resize, rl))
2099 			free(rl);
2100 		resize->dirty_inode = DIRTY_INODE;
2101 	} else
2102 		free(rl);
2103 }
2104 
is_mftdata(ntfs_resize_t * resize)2105 static int is_mftdata(ntfs_resize_t *resize)
2106 {
2107 	/*
2108 	 * We must update the MFT own DATA record at the end of the second
2109 	 * step, because the old MFT must be kept available for processing
2110 	 * the other files.
2111 	 */
2112 
2113 	if (resize->ctx->attr->type != AT_DATA)
2114 		return 0;
2115 
2116 	if (resize->mref == 0)
2117 		return 1;
2118 
2119 	if (MREF_LE(resize->mrec->base_mft_record) == 0 &&
2120 	    MSEQNO_LE(resize->mrec->base_mft_record) != 0)
2121 		return 1;
2122 
2123 	return 0;
2124 }
2125 
handle_mftdata(ntfs_resize_t * resize,int do_mftdata)2126 static int handle_mftdata(ntfs_resize_t *resize, int do_mftdata)
2127 {
2128 	ATTR_RECORD *attr = resize->ctx->attr;
2129 	VCN highest_vcn, lowest_vcn;
2130 
2131 	if (do_mftdata) {
2132 
2133 		if (!is_mftdata(resize))
2134 			return 0;
2135 
2136 		highest_vcn = sle64_to_cpu(attr->highest_vcn);
2137 		lowest_vcn  = sle64_to_cpu(attr->lowest_vcn);
2138 
2139 		if (resize->mft_highest_vcn != highest_vcn)
2140 			return 0;
2141 
2142 		if (lowest_vcn == 0)
2143 			resize->mft_highest_vcn = lowest_vcn;
2144 		else
2145 			resize->mft_highest_vcn = lowest_vcn - 1;
2146 
2147 	} else if (is_mftdata(resize)) {
2148 
2149 		highest_vcn = sle64_to_cpu(attr->highest_vcn);
2150 
2151 		if (resize->mft_highest_vcn < highest_vcn)
2152 			resize->mft_highest_vcn = highest_vcn;
2153 
2154 		return 0;
2155 	}
2156 
2157 	return 1;
2158 }
2159 
relocate_attributes(ntfs_resize_t * resize,int do_mftdata)2160 static void relocate_attributes(ntfs_resize_t *resize, int do_mftdata)
2161 {
2162 	int ret;
2163 	leMFT_REF lemref;
2164 	MFT_REF base_mref;
2165 
2166 	if (!(resize->ctx = attr_get_search_ctx(NULL, resize->mrec)))
2167 		exit(1);
2168 
2169 	lemref = resize->mrec->base_mft_record;
2170 	if (lemref)
2171 		base_mref = MREF(le64_to_cpu(lemref));
2172 	else
2173 		base_mref = resize->mref;
2174 	while (!ntfs_attrs_walk(resize->ctx)) {
2175 		if (resize->ctx->attr->type == AT_END)
2176 			break;
2177 
2178 		if (handle_mftdata(resize, do_mftdata) == 0)
2179 			continue;
2180 
2181 		ret = ntfs_inode_badclus_bad(resize->mref, resize->ctx->attr);
2182 		if (ret == -1)
2183 			perr_exit("Bad sector list check failed");
2184 		else if (ret == 1)
2185 			continue;
2186 
2187 		if (resize->mref == FILE_Bitmap &&
2188 		    resize->ctx->attr->type == AT_DATA)
2189 			continue;
2190 
2191 		/* Do not relocate bad clusters */
2192 		if ((base_mref == FILE_BadClus)
2193 		    && (resize->ctx->attr->type == AT_DATA))
2194 			continue;
2195 
2196 		relocate_attribute(resize);
2197 	}
2198 
2199 	ntfs_attr_put_search_ctx(resize->ctx);
2200 }
2201 
relocate_inode(ntfs_resize_t * resize,MFT_REF mref,int do_mftdata)2202 static void relocate_inode(ntfs_resize_t *resize, MFT_REF mref, int do_mftdata)
2203 {
2204 	ntfs_volume *vol = resize->vol;
2205 
2206 	if (ntfs_file_record_read(vol, mref, &resize->mrec, NULL)) {
2207 		/* FIXME: continue only if it make sense, e.g.
2208 		   MFT record not in use based on $MFT bitmap */
2209 		if (errno == EIO || errno == ENOENT)
2210 			return;
2211 		perr_exit("ntfs_file_record_record");
2212 	}
2213 
2214 	if (!(resize->mrec->flags & MFT_RECORD_IN_USE))
2215 		return;
2216 
2217 	resize->mref = mref;
2218 	resize->dirty_inode = DIRTY_NONE;
2219 
2220 	relocate_attributes(resize, do_mftdata);
2221 
2222 //		if (vol->dev->d_ops->sync(vol->dev) == -1)
2223 //			perr_exit("Failed to sync device");
2224 		/* relocate MFT during second step, even if not dirty */
2225 	if ((mref == FILE_MFT) && do_mftdata && resize->new_mft_start) {
2226 		s64 pos;
2227 
2228 			/* write the MFT own record at its new location */
2229 		pos = (resize->new_mft_start->lcn
2230 					<< vol->cluster_size_bits)
2231 			+ (FILE_MFT << vol->mft_record_size_bits);
2232 		if (!opt.ro_flag
2233 		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
2234 				vol->mft_record_size, resize->mrec) != 1))
2235 			perr_exit("Couldn't update MFT own record");
2236 	} else {
2237 		if ((resize->dirty_inode == DIRTY_INODE)
2238 		   && write_mft_record(vol, mref, resize->mrec)) {
2239 			perr_exit("Couldn't update record %llu",
2240 						(unsigned long long)mref);
2241 		}
2242 	}
2243 }
2244 
relocate_inodes(ntfs_resize_t * resize)2245 static void relocate_inodes(ntfs_resize_t *resize)
2246 {
2247 	s64 nr_mft_records;
2248 	MFT_REF mref;
2249 	VCN highest_vcn;
2250 	s64 length;
2251 
2252 	printf("Relocating needed data ...\n");
2253 
2254 	progress_init(&resize->progress, 0, resize->relocations, resize->progress.flags);
2255 	resize->relocations = 0;
2256 
2257 	resize->mrec = ntfs_malloc(resize->vol->mft_record_size);
2258 	if (!resize->mrec)
2259 		perr_exit("ntfs_malloc failed");
2260 
2261 	nr_mft_records = resize->vol->mft_na->initialized_size >>
2262 			resize->vol->mft_record_size_bits;
2263 
2264 		/*
2265 		 * If we need to relocate the first run of the MFT DATA,
2266 		 * do it now, to have a better chance of getting at least
2267 		 * 16 records in the first chunk. This is mandatory to be
2268 		 * later able to read an MFT extent in record 15.
2269 		 * Should this fail, we can stop with no damage, the volume
2270 		 * is still in its initial state.
2271 		 */
2272 	if (!resize->vol->mft_na->rl)
2273 		err_exit("Internal error : no runlist for $MFT\n");
2274 
2275 	if ((resize->vol->mft_na->rl->lcn + resize->vol->mft_na->rl->length)
2276 			>= resize->new_volume_size) {
2277 		/*
2278 		 * The length of the first run is normally found in
2279 		 * mft_na. However in some rare circumstance, this is
2280 		 * merged with the first run of an extent of MFT,
2281 		 * which implies there is a single run in the base record.
2282 		 * So we have to make sure not to overflow from the
2283 		 * runs present in the base extent.
2284 		 */
2285 		length = resize->vol->mft_na->rl->length;
2286 		if (ntfs_file_record_read(resize->vol, FILE_MFT,
2287 				&resize->mrec, NULL)
2288 		    || !(resize->ctx = attr_get_search_ctx(NULL,
2289 				resize->mrec))) {
2290 			err_exit("Could not read the base record of MFT\n");
2291 		}
2292 		while (!ntfs_attrs_walk(resize->ctx)
2293 		   && (resize->ctx->attr->type != AT_DATA)) { }
2294 		if (resize->ctx->attr->type == AT_DATA) {
2295 			sle64 high_le;
2296 
2297 			high_le = resize->ctx->attr->highest_vcn;
2298 			if (sle64_to_cpu(high_le) < length)
2299 				length = sle64_to_cpu(high_le) + 1;
2300 		} else {
2301 			err_exit("Could not find the DATA of MFT\n");
2302 		}
2303 		ntfs_attr_put_search_ctx(resize->ctx);
2304 		resize->new_mft_start = alloc_cluster(&resize->lcn_bitmap,
2305 				length, resize->new_volume_size, 0);
2306 		if (!resize->new_mft_start
2307 		    || (((resize->new_mft_start->length
2308 			<< resize->vol->cluster_size_bits)
2309 			    >> resize->vol->mft_record_size_bits) < 16)) {
2310 			err_exit("Could not allocate 16 records in"
2311 					" the first MFT chunk\n");
2312 		}
2313 		resize->mirr_from = MIRR_NEWMFT;
2314 	}
2315 
2316 	for (mref = 0; mref < (MFT_REF)nr_mft_records; mref++)
2317 		relocate_inode(resize, mref, 0);
2318 
2319 	while (1) {
2320 		highest_vcn = resize->mft_highest_vcn;
2321 		mref = nr_mft_records;
2322 		do {
2323 			relocate_inode(resize, --mref, 1);
2324 			if (resize->mft_highest_vcn == 0)
2325 				goto done;
2326 		} while (mref);
2327 
2328 		if (highest_vcn == resize->mft_highest_vcn)
2329 			err_exit("Sanity check failed! Highest_vcn = %lld. "
2330 				 "Please report!\n", (long long)highest_vcn);
2331 	}
2332 done:
2333 	free(resize->mrec);
2334 }
2335 
print_hint(ntfs_volume * vol,const char * s,struct llcn_t llcn)2336 static void print_hint(ntfs_volume *vol, const char *s, struct llcn_t llcn)
2337 {
2338 	s64 runs_b, runs_mb;
2339 
2340 	if (llcn.lcn == 0)
2341 		return;
2342 
2343 	runs_b = llcn.lcn * vol->cluster_size;
2344 	runs_mb = rounded_up_division(runs_b, NTFS_MBYTE);
2345 	printf("%-19s: %9lld MB      %8lld\n", s, (long long)runs_mb,
2346 			(long long)llcn.inode);
2347 }
2348 
2349 /**
2350  * advise_on_resize
2351  *
2352  * The metadata file $Bitmap has one bit for each cluster on disk.  This has
2353  * already been read into lcn_bitmap.  By looking for the last used cluster on
2354  * the disk, we can work out by how much we can shrink the volume.
2355  */
advise_on_resize(ntfs_resize_t * resize)2356 static void advise_on_resize(ntfs_resize_t *resize)
2357 {
2358 	ntfs_volume *vol = resize->vol;
2359 
2360 	if (opt.verbose) {
2361 		printf("Estimating smallest shrunken size supported ...\n");
2362 		printf("File feature         Last used at      By inode\n");
2363 		print_hint(vol, "$MFT",		resize->last_mft);
2364 		print_hint(vol, "Multi-Record", resize->last_multi_mft);
2365 		print_hint(vol, "$MFTMirr",	resize->last_mftmir);
2366 		print_hint(vol, "Compressed",	resize->last_compressed);
2367 		print_hint(vol, "Sparse",	resize->last_sparse);
2368 		print_hint(vol, "Ordinary",	resize->last_lcn);
2369 	}
2370 
2371 	print_advise(vol, resize->last_unsupp);
2372 }
2373 
2374 /**
2375  * bitmap_file_data_fixup
2376  *
2377  * $Bitmap can overlap the end of the volume. Any bits in this region
2378  * must be set. This region also encompasses the backup boot sector.
2379  */
bitmap_file_data_fixup(s64 cluster,struct bitmap * bm)2380 static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm)
2381 {
2382 	for (; cluster < bm->size << 3; cluster++)
2383 		ntfs_bit_set(bm->bm, (u64)cluster, 1);
2384 }
2385 
2386 /*
2387  *		Open the attribute $BadClust:$Bad and get its runlist
2388  */
2389 
open_badclust_bad_attr(ntfs_attr_search_ctx * ctx)2390 static ntfs_attr *open_badclust_bad_attr(ntfs_attr_search_ctx *ctx)
2391 {
2392 	ntfs_inode *base_ni;
2393 	ntfs_attr *na;
2394 	static ntfschar Bad[4] = {
2395 		const_cpu_to_le16('$'), const_cpu_to_le16('B'),
2396 		const_cpu_to_le16('a'), const_cpu_to_le16('d')
2397 	} ;
2398 
2399 	base_ni = ctx->base_ntfs_ino;
2400 	if (!base_ni)
2401 		base_ni = ctx->ntfs_ino;
2402 
2403 	na = ntfs_attr_open(base_ni, AT_DATA, Bad, 4);
2404 	if (!na) {
2405 		err_printf("Could not access the bad sector list\n");
2406 	} else {
2407 		if (ntfs_attr_map_whole_runlist(na) || !na->rl) {
2408 			err_printf("Could not decode the bad sector list\n");
2409 			ntfs_attr_close(na);
2410 			ntfs_inode_close(base_ni);
2411 			na = (ntfs_attr*)NULL;
2412 		}
2413 	}
2414 	return (na);
2415 }
2416 
2417 /**
2418  * truncate_badclust_bad_attr
2419  *
2420  * The metadata file $BadClus needs to be shrunk.
2421  *
2422  * FIXME: this function should go away and instead using a generalized
2423  * "truncate_bitmap_data_attr()"
2424  */
truncate_badclust_bad_attr(ntfs_resize_t * resize)2425 static void truncate_badclust_bad_attr(ntfs_resize_t *resize)
2426 {
2427 	ntfs_inode *base_ni;
2428 	ntfs_attr *na;
2429 	ntfs_attr_search_ctx *ctx;
2430 	s64 nr_clusters = resize->new_volume_size;
2431 	ntfs_volume *vol = resize->vol;
2432 
2433 	na = open_badclust_bad_attr(resize->ctx);
2434 	if (!na) {
2435 		err_printf("Could not access the bad sector list\n");
2436 		exit(1);
2437 	}
2438 	base_ni = na->ni;
2439 	if (ntfs_attr_truncate(na,nr_clusters << vol->cluster_size_bits)) {
2440 		err_printf("Could not adjust the bad sector list\n");
2441 		exit(1);
2442 	}
2443 		/* Clear the sparse flags, even if there are bad clusters */
2444 	na->ni->flags &= ~FILE_ATTR_SPARSE_FILE;
2445 	na->data_flags &= ~ATTR_IS_SPARSE;
2446 	ctx = resize->ctx;
2447 	ctx->attr->data_size = cpu_to_sle64(na->data_size);
2448 	ctx->attr->initialized_size = cpu_to_sle64(na->initialized_size);
2449 	ctx->attr->flags = na->data_flags;
2450 	ctx->attr->compression_unit = 0;
2451 	ntfs_inode_mark_dirty(ctx->ntfs_ino);
2452 	NInoFileNameSetDirty(na->ni);
2453 	NInoFileNameSetDirty(na->ni);
2454 
2455 	ntfs_attr_close(na);
2456 	ntfs_inode_mark_dirty(base_ni);
2457 }
2458 
2459 /**
2460  * realloc_bitmap_data_attr
2461  *
2462  * Reallocate the metadata file $Bitmap.  It must be large enough for one bit
2463  * per cluster of the shrunken volume.  Also it must be a of 8 bytes in size.
2464  */
realloc_bitmap_data_attr(ntfs_resize_t * resize,runlist ** rl,s64 nr_bm_clusters)2465 static void realloc_bitmap_data_attr(ntfs_resize_t *resize,
2466 				     runlist **rl,
2467 				     s64 nr_bm_clusters)
2468 {
2469 	s64 i;
2470 	ntfs_volume *vol = resize->vol;
2471 	ATTR_RECORD *a = resize->ctx->attr;
2472 	s64 new_size = resize->new_volume_size;
2473 	struct bitmap *bm = &resize->lcn_bitmap;
2474 
2475 	if (!(*rl = ntfs_mapping_pairs_decompress(vol, a, NULL)))
2476 		perr_exit("ntfs_mapping_pairs_decompress");
2477 
2478 	release_bitmap_clusters(bm, *rl);
2479 	free(*rl);
2480 
2481 	for (i = vol->nr_clusters; i < new_size; i++)
2482 		ntfs_bit_set(bm->bm, i, 0);
2483 
2484 	if (!(*rl = alloc_cluster(bm, nr_bm_clusters, new_size, 0)))
2485 		perr_exit("Couldn't allocate $Bitmap clusters");
2486 }
2487 
realloc_lcn_bitmap(ntfs_resize_t * resize,s64 bm_bsize)2488 static void realloc_lcn_bitmap(ntfs_resize_t *resize, s64 bm_bsize)
2489 {
2490 	u8 *tmp;
2491 
2492 	if (!(tmp = realloc(resize->lcn_bitmap.bm, bm_bsize)))
2493 		perr_exit("realloc");
2494 
2495 	resize->lcn_bitmap.bm = tmp;
2496 	resize->lcn_bitmap.size = bm_bsize;
2497 	bitmap_file_data_fixup(resize->new_volume_size, &resize->lcn_bitmap);
2498 }
2499 
2500 /**
2501  * truncate_bitmap_data_attr
2502  */
truncate_bitmap_data_attr(ntfs_resize_t * resize)2503 static void truncate_bitmap_data_attr(ntfs_resize_t *resize)
2504 {
2505 	ATTR_RECORD *a;
2506 	runlist *rl;
2507 	ntfs_attr *lcnbmp_na;
2508 	s64 bm_bsize, size;
2509 	s64 nr_bm_clusters;
2510 	int truncated;
2511 	ntfs_volume *vol = resize->vol;
2512 
2513 	a = resize->ctx->attr;
2514 	if (!a->non_resident)
2515 		/* FIXME: handle resident attribute value */
2516 		err_exit("Resident attribute in $Bitmap isn't supported!\n");
2517 
2518 	bm_bsize = nr_clusters_to_bitmap_byte_size(resize->new_volume_size);
2519 	nr_bm_clusters = rounded_up_division(bm_bsize, vol->cluster_size);
2520 
2521 	if (resize->shrink) {
2522 		realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
2523 		realloc_lcn_bitmap(resize, bm_bsize);
2524 	} else {
2525 		realloc_lcn_bitmap(resize, bm_bsize);
2526 		realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
2527 	}
2528 		/*
2529 		 * Delayed relocations may require cluster allocations
2530 		 * through the library, to hold added attribute lists,
2531 		 * be sure they will be within the new limits.
2532 		 */
2533 	lcnbmp_na = resize->vol->lcnbmp_na;
2534 	lcnbmp_na->data_size = bm_bsize;
2535 	lcnbmp_na->initialized_size = bm_bsize;
2536 	lcnbmp_na->allocated_size = nr_bm_clusters << vol->cluster_size_bits;
2537 	vol->lcnbmp_ni->data_size = bm_bsize;
2538 	vol->lcnbmp_ni->allocated_size = lcnbmp_na->allocated_size;
2539 	a->highest_vcn = cpu_to_sle64(nr_bm_clusters - 1LL);
2540 	a->allocated_size = cpu_to_sle64(nr_bm_clusters * vol->cluster_size);
2541 	a->data_size = cpu_to_sle64(bm_bsize);
2542 	a->initialized_size = cpu_to_sle64(bm_bsize);
2543 
2544 	truncated = !replace_attribute_runlist(resize, rl);
2545 
2546 	/*
2547 	 * FIXME: update allocated/data sizes and timestamps in $FILE_NAME
2548 	 * attribute too, for now chkdsk will do this for us.
2549 	 */
2550 
2551 	size = ntfs_rl_pwrite(vol, rl, 0, 0, bm_bsize, resize->lcn_bitmap.bm);
2552 	if (bm_bsize != size) {
2553 		if (size == -1)
2554 			perr_exit("Couldn't write $Bitmap");
2555 		err_exit("Couldn't write full $Bitmap file (%lld from %lld)\n",
2556 				(long long)size, (long long)bm_bsize);
2557 	}
2558 
2559 	if (truncated) {
2560 			/* switch to the new bitmap runlist */
2561 		free(lcnbmp_na->rl);
2562 		lcnbmp_na->rl = rl;
2563 	}
2564 }
2565 
2566 /**
2567  * lookup_data_attr
2568  *
2569  * Find the $DATA attribute (with or without a name) for the given MFT reference
2570  * (inode number).
2571  */
lookup_data_attr(ntfs_volume * vol,MFT_REF mref,const char * aname,ntfs_attr_search_ctx ** ctx)2572 static void lookup_data_attr(ntfs_volume *vol,
2573 			     MFT_REF mref,
2574 			     const char *aname,
2575 			     ntfs_attr_search_ctx **ctx)
2576 {
2577 	ntfs_inode *ni;
2578 	ntfschar *ustr;
2579 	int len = 0;
2580 
2581 	if (!(ni = ntfs_inode_open(vol, mref)))
2582 		perr_exit("ntfs_open_inode");
2583 
2584 	if (!(*ctx = attr_get_search_ctx(ni, NULL)))
2585 		exit(1);
2586 
2587 	if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) {
2588 		perr_printf("Couldn't convert '%s' to Unicode", aname);
2589 		exit(1);
2590 	}
2591 
2592 	if (ntfs_attr_lookup(AT_DATA, ustr, len, CASE_SENSITIVE,
2593 			 0, NULL, 0, *ctx))
2594 		perr_exit("ntfs_lookup_attr");
2595 
2596 	ntfs_ucsfree(ustr);
2597 }
2598 
close_inode_and_context(ntfs_attr_search_ctx * ctx)2599 static void close_inode_and_context(ntfs_attr_search_ctx *ctx)
2600 {
2601 	ntfs_inode *ni;
2602 
2603 	ni = ctx->base_ntfs_ino;
2604 	if (!ni)
2605 		ni = ctx->ntfs_ino;
2606 	ntfs_attr_put_search_ctx(ctx);
2607 	if (ni)
2608 		ntfs_inode_close(ni);
2609 }
2610 
check_bad_sectors(ntfs_volume * vol)2611 static int check_bad_sectors(ntfs_volume *vol)
2612 {
2613 	ntfs_attr_search_ctx *ctx;
2614 	ntfs_attr *na;
2615 	runlist *rl;
2616 	s64 i, badclusters = 0;
2617 
2618 	ntfs_log_verbose("Checking for bad sectors ...\n");
2619 
2620 	lookup_data_attr(vol, FILE_BadClus, "$Bad", &ctx);
2621 
2622 	na = open_badclust_bad_attr(ctx);
2623 	if (!na) {
2624 		err_printf("Could not access the bad sector list\n");
2625 		exit(1);
2626 	}
2627 	rl = na->rl;
2628 	for (i = 0; rl[i].length; i++) {
2629 		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
2630 		if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
2631 			continue;
2632 
2633 		badclusters += rl[i].length;
2634 		ntfs_log_verbose("Bad cluster: %#8llx - %#llx    (%lld)\n",
2635 				 (long long)rl[i].lcn,
2636 				 (long long)rl[i].lcn + rl[i].length - 1,
2637 				 (long long)rl[i].length);
2638 	}
2639 
2640 	if (badclusters) {
2641 		printf("%sThis software has detected that the disk has at least"
2642 		       " %lld bad sector%s.\n",
2643 		       !opt.badsectors ? NERR_PREFIX : "WARNING: ",
2644 		       (long long)badclusters, badclusters - 1 ? "s" : "");
2645 		if (!opt.badsectors) {
2646 			printf("%s", bad_sectors_warning_msg);
2647 			exit(1);
2648 		} else
2649 			printf("WARNING: Bad sectors can cause reliability "
2650 			       "problems and massive data loss!!!\n");
2651 	}
2652 
2653 	ntfs_attr_close(na);
2654 #if CLEAN_EXIT
2655 	close_inode_and_context(ctx);
2656 #else
2657 	ntfs_attr_put_search_ctx(ctx);
2658 #endif
2659 
2660 	return badclusters;
2661 }
2662 
2663 /**
2664  * truncate_badclust_file
2665  *
2666  * Shrink the $BadClus file to match the new volume size.
2667  */
truncate_badclust_file(ntfs_resize_t * resize)2668 static void truncate_badclust_file(ntfs_resize_t *resize)
2669 {
2670 	printf("Updating $BadClust file ...\n");
2671 
2672 	lookup_data_attr(resize->vol, FILE_BadClus, "$Bad", &resize->ctx);
2673 	/* FIXME: sanity_check_attr(ctx->attr); */
2674 	resize->mref = FILE_BadClus;
2675 	truncate_badclust_bad_attr(resize);
2676 
2677 	close_inode_and_context(resize->ctx);
2678 }
2679 
2680 /**
2681  * truncate_bitmap_file
2682  *
2683  * Shrink the $Bitmap file to match the new volume size.
2684  */
truncate_bitmap_file(ntfs_resize_t * resize)2685 static void truncate_bitmap_file(ntfs_resize_t *resize)
2686 {
2687 	ntfs_volume *vol = resize->vol;
2688 
2689 	printf("Updating $Bitmap file ...\n");
2690 
2691 	lookup_data_attr(resize->vol, FILE_Bitmap, NULL, &resize->ctx);
2692 	resize->mref = FILE_Bitmap;
2693 	truncate_bitmap_data_attr(resize);
2694 
2695 	if (resize->new_mft_start) {
2696 		s64 pos;
2697 
2698 			/* write the MFT record at its new location */
2699 		pos = (resize->new_mft_start->lcn << vol->cluster_size_bits)
2700 			+ (FILE_Bitmap << vol->mft_record_size_bits);
2701 		if (!opt.ro_flag
2702 		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
2703 				vol->mft_record_size, resize->ctx->mrec) != 1))
2704 			perr_exit("Couldn't update $Bitmap at new location");
2705 	} else {
2706 		if (write_mft_record(vol, resize->ctx->ntfs_ino->mft_no,
2707 			     resize->ctx->mrec))
2708 			perr_exit("Couldn't update $Bitmap");
2709 	}
2710 
2711 		/* If successful, update cache and sync $Bitmap */
2712 	memcpy(vol->lcnbmp_ni->mrec,resize->ctx->mrec,vol->mft_record_size);
2713 	ntfs_inode_mark_dirty(vol->lcnbmp_ni);
2714 	NInoFileNameSetDirty(vol->lcnbmp_ni);
2715 	ntfs_inode_sync(vol->lcnbmp_ni);
2716 
2717 #if CLEAN_EXIT
2718 	close_inode_and_context(resize->ctx);
2719 #else
2720 	ntfs_attr_put_search_ctx(resize->ctx);
2721 #endif
2722 }
2723 
2724 /**
2725  * setup_lcn_bitmap
2726  *
2727  * Allocate a block of memory with one bit for each cluster of the disk.
2728  * All the bits are set to 0, except those representing the region beyond the
2729  * end of the disk.
2730  */
setup_lcn_bitmap(struct bitmap * bm,s64 nr_clusters)2731 static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters)
2732 {
2733 	/* Determine lcn bitmap byte size and allocate it. */
2734 	bm->size = rounded_up_division(nr_clusters, 8);
2735 
2736 	bm->bm = ntfs_calloc(bm->size);
2737 	if (!bm->bm)
2738 		return -1;
2739 
2740 	bitmap_file_data_fixup(nr_clusters, bm);
2741 	return 0;
2742 }
2743 
2744 /**
2745  * update_bootsector
2746  *
2747  * FIXME: should be done using ntfs_* functions
2748  */
update_bootsector(ntfs_resize_t * r)2749 static void update_bootsector(ntfs_resize_t *r)
2750 {
2751 	NTFS_BOOT_SECTOR *bs;
2752 	ntfs_volume *vol = r->vol;
2753 	s64  bs_size = vol->sector_size;
2754 
2755 	printf("Updating Boot record ...\n");
2756 
2757 	bs = (NTFS_BOOT_SECTOR*)ntfs_malloc(vol->sector_size);
2758 	if (!bs)
2759 		perr_exit("ntfs_malloc");
2760 
2761 	if (vol->dev->d_ops->seek(vol->dev, 0, SEEK_SET) == (off_t)-1)
2762 		perr_exit("lseek");
2763 
2764 	if (vol->dev->d_ops->read(vol->dev, bs, bs_size) == -1)
2765 		perr_exit("read() error");
2766 
2767 	if (bs->bpb.sectors_per_cluster > 128)
2768 		bs->number_of_sectors = cpu_to_sle64(r->new_volume_size
2769 				<< (256 - bs->bpb.sectors_per_cluster));
2770 	else
2771 		bs->number_of_sectors = cpu_to_sle64(r->new_volume_size *
2772 				bs->bpb.sectors_per_cluster);
2773 
2774 	if (r->mftmir_old || (r->mirr_from == MIRR_MFT)) {
2775 		r->progress.flags |= NTFS_PROGBAR_SUPPRESS;
2776 		/* Be sure the MFTMirr holds the updated MFT runlist */
2777 		switch (r->mirr_from) {
2778 		case MIRR_MFT :
2779 			/* The late updates of MFT have not been synced */
2780 			ntfs_inode_sync(vol->mft_ni);
2781 			copy_clusters(r, r->mftmir_rl.lcn,
2782 				vol->mft_na->rl->lcn, r->mftmir_rl.length);
2783 			break;
2784 		case MIRR_NEWMFT :
2785 			copy_clusters(r, r->mftmir_rl.lcn,
2786 				 r->new_mft_start->lcn, r->mftmir_rl.length);
2787 			break;
2788 		default :
2789 			copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old,
2790 				      r->mftmir_rl.length);
2791 			break;
2792 		}
2793 		if (r->mftmir_old)
2794 			bs->mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
2795 		r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS;
2796 	}
2797 		/* Set the start of the relocated MFT */
2798 	if (r->new_mft_start) {
2799 		bs->mft_lcn = cpu_to_sle64(r->new_mft_start->lcn);
2800 			/* no more need for the new MFT start */
2801 		free(r->new_mft_start);
2802 		r->new_mft_start = (runlist_element*)NULL;
2803 	}
2804 
2805 	if (vol->dev->d_ops->seek(vol->dev, 0, SEEK_SET) == (off_t)-1)
2806 		perr_exit("lseek");
2807 
2808 	if (!opt.ro_flag)
2809 		if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1)
2810 			perr_exit("write() error");
2811 		/*
2812 		 * Set the backup boot sector, if the target size is
2813 		 * either not defined or is defined with no multiplier
2814 		 * suffix and is a multiple of the sector size.
2815 		 * With these conditions we can be confident enough that
2816 		 * the partition size is already defined or it will be
2817 		 * later defined with the same exact value.
2818 		 */
2819 	if (!opt.ro_flag && opt.reliable_size
2820 	    && !(opt.bytes % vol->sector_size)) {
2821 		if (vol->dev->d_ops->seek(vol->dev, opt.bytes
2822 				- vol->sector_size, SEEK_SET) == (off_t)-1)
2823 			perr_exit("lseek");
2824 		if (vol->dev->d_ops->write(vol->dev, bs, bs_size) == -1)
2825 			perr_exit("write() error");
2826 	}
2827 	free(bs);
2828 }
2829 
2830 /**
2831  * vol_size
2832  */
vol_size(ntfs_volume * v,s64 nr_clusters)2833 static s64 vol_size(ntfs_volume *v, s64 nr_clusters)
2834 {
2835 	/* add one sector_size for the backup boot sector */
2836 	return nr_clusters * v->cluster_size + v->sector_size;
2837 }
2838 
2839 /**
2840  * print_vol_size
2841  *
2842  * Print the volume size in bytes and decimal megabytes.
2843  */
print_vol_size(const char * str,s64 bytes)2844 static void print_vol_size(const char *str, s64 bytes)
2845 {
2846 	printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes,
2847 			(long long)rounded_up_division(bytes, NTFS_MBYTE));
2848 }
2849 
2850 /**
2851  * print_disk_usage
2852  *
2853  * Display the amount of disk space in use.
2854  */
print_disk_usage(ntfs_volume * vol,s64 nr_used_clusters)2855 static void print_disk_usage(ntfs_volume *vol, s64 nr_used_clusters)
2856 {
2857 	s64 total, used;
2858 
2859 	total = vol->nr_clusters * vol->cluster_size;
2860 	used = nr_used_clusters * vol->cluster_size;
2861 
2862 	/* WARNING: don't modify the text, external tools grep for it */
2863         if (!opt.infombonly) {
2864 		printf("Space in use       : %lld MB (%.1f%%)\n",
2865 	        	(long long)rounded_up_division(used, NTFS_MBYTE),
2866 	        	100.0 * ((float)used / total));
2867 	}
2868 }
2869 
print_num_of_relocations(ntfs_resize_t * resize)2870 static void print_num_of_relocations(ntfs_resize_t *resize)
2871 {
2872 	s64 relocations = resize->relocations * resize->vol->cluster_size;
2873 
2874 	printf("Needed relocations : %lld (%lld MB)\n",
2875 			(long long)resize->relocations, (long long)
2876 			rounded_up_division(relocations, NTFS_MBYTE));
2877 }
2878 
check_volume(void)2879 static ntfs_volume *check_volume(void)
2880 {
2881 	ntfs_volume *myvol = NULL;
2882 
2883 	/*
2884 	 * Pass NTFS_MNT_FORENSIC so that the mount process does not modify the
2885 	 * volume at all.  We will do the logfile emptying and dirty setting
2886 	 * later if needed.
2887 	 */
2888 	if (!(myvol = ntfs_mount(opt.volume, opt.ro_flag | NTFS_MNT_FORENSIC)))
2889 	{
2890 		int err = errno;
2891 
2892 		perr_printf("Opening '%s' as NTFS failed", opt.volume);
2893 		switch (err) {
2894 		case EINVAL :
2895 			printf(invalid_ntfs_msg, opt.volume);
2896 			break;
2897 		case EIO :
2898 			printf("%s", corrupt_volume_msg);
2899 			break;
2900 		case EPERM :
2901 			printf("%s", hibernated_volume_msg);
2902 			break;
2903 		case EOPNOTSUPP :
2904 			printf("%s", unclean_journal_msg);
2905 			break;
2906 		case EBUSY :
2907 			printf("%s", opened_volume_msg);
2908 			break;
2909 		default :
2910 			break;
2911 		}
2912 		exit(1);
2913 	}
2914 	return myvol;
2915 }
2916 
2917 
2918 /**
2919  * mount_volume
2920  *
2921  * First perform some checks to determine if the volume is already mounted, or
2922  * is dirty (Windows wasn't shutdown properly).  If everything is OK, then mount
2923  * the volume (load the metadata into memory).
2924  */
mount_volume(void)2925 static ntfs_volume *mount_volume(void)
2926 {
2927 	unsigned long mntflag;
2928 	ntfs_volume *vol = NULL;
2929 
2930 	if (ntfs_check_if_mounted(opt.volume, &mntflag)) {
2931 		perr_printf("Failed to check '%s' mount state", opt.volume);
2932 		printf("Probably /etc/mtab is missing. It's too risky to "
2933 		       "continue. You might try\nan another Linux distro.\n");
2934 		exit(1);
2935 	}
2936 	if (mntflag & NTFS_MF_MOUNTED) {
2937 		if (!(mntflag & NTFS_MF_READONLY))
2938 			err_exit("Device '%s' is mounted read-write. "
2939 				 "You must 'umount' it first.\n", opt.volume);
2940 		if (!opt.ro_flag)
2941 			err_exit("Device '%s' is mounted. "
2942 				 "You must 'umount' it first.\n", opt.volume);
2943 	}
2944 	vol = check_volume();
2945 
2946 	if (vol->flags & VOLUME_IS_DIRTY)
2947 		if (opt.force-- <= 0)
2948 			err_exit("Volume is scheduled for check.\nRun chkdsk /f"
2949 				 " and please try again, or see option -f.\n");
2950 
2951 	if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size)
2952 		err_exit("Cluster size %u is too large!\n",
2953 			(unsigned int)vol->cluster_size);
2954 
2955 	if (ntfs_volume_get_free_space(vol))
2956 		err_exit("Failed to update the free space\n");
2957 
2958 	if (!opt.infombonly) {
2959 		printf("Device name        : %s\n", opt.volume);
2960 		printf("NTFS volume version: %d.%d\n",
2961 				vol->major_ver, vol->minor_ver);
2962 	}
2963 	if (ntfs_version_is_supported(vol))
2964 		perr_exit("Unknown NTFS version");
2965 
2966 	if (!opt.infombonly) {
2967 		printf("Cluster size       : %u bytes\n",
2968 			(unsigned int)vol->cluster_size);
2969 		print_vol_size("Current volume size",
2970 			vol_size(vol, vol->nr_clusters));
2971 	}
2972 
2973 	return vol;
2974 }
2975 
2976 /**
2977  * prepare_volume_fixup
2978  *
2979  * Set the volume's dirty flag and wipe the filesystem journal.  When Windows
2980  * boots it will automatically run chkdsk to check for any problems.  If the
2981  * read-only command line option was given, this function will do nothing.
2982  */
prepare_volume_fixup(ntfs_volume * vol)2983 static void prepare_volume_fixup(ntfs_volume *vol)
2984 {
2985 	printf("Schedule chkdsk for NTFS consistency check at Windows boot "
2986 			"time ...\n");
2987 	vol->flags |= VOLUME_IS_DIRTY;
2988 	if (ntfs_volume_write_flags(vol, vol->flags))
2989 		perr_exit("Failed to set the volume dirty");
2990 
2991 	/* Porting note: This flag does not exist in libntfs-3g. The dirty flag
2992 	 * is never modified by libntfs-3g on unmount and we set it above. We
2993 	 * can safely comment out this statement. */
2994 	/* NVolSetWasDirty(vol); */
2995 
2996 	if (vol->dev->d_ops->sync(vol->dev) == -1)
2997 		perr_exit("Failed to sync device");
2998 	printf("Resetting $LogFile ... (this might take a while)\n");
2999 	if (ntfs_logfile_reset(vol))
3000 		perr_exit("Failed to reset $LogFile");
3001 	if (vol->dev->d_ops->sync(vol->dev) == -1)
3002 		perr_exit("Failed to sync device");
3003 }
3004 
set_disk_usage_constraint(ntfs_resize_t * resize)3005 static void set_disk_usage_constraint(ntfs_resize_t *resize)
3006 {
3007 	/* last lcn for a filled up volume (no empty space) */
3008 	s64 last = resize->inuse - 1;
3009 
3010 	if (resize->last_unsupp < last)
3011 		resize->last_unsupp = last;
3012 }
3013 
check_resize_constraints(ntfs_resize_t * resize)3014 static void check_resize_constraints(ntfs_resize_t *resize)
3015 {
3016 	s64 new_size = resize->new_volume_size;
3017 
3018 	/* FIXME: resize.shrink true also if only -i is used */
3019 	if (!resize->shrink)
3020 		return;
3021 
3022 	if (resize->inuse == resize->vol->nr_clusters)
3023 		err_exit("Volume is full. To shrink it, "
3024 			 "delete unused files.\n");
3025 
3026 	if (opt.info || opt.infombonly)
3027 		return;
3028 
3029 	/* FIXME: reserve some extra space so Windows can boot ... */
3030 	if (new_size < resize->inuse)
3031 		err_exit("New size can't be less than the space already"
3032 			 " occupied by data.\nYou either need to delete unused"
3033 			 " files or see the -i option.\n");
3034 
3035 	if (new_size <= resize->last_unsupp)
3036 		err_exit("The fragmentation type, you have, isn't "
3037 			 "supported yet. Rerun ntfsresize\nwith "
3038 			 "the -i option to estimate the smallest "
3039 			 "shrunken volume size supported.\n");
3040 
3041 	print_num_of_relocations(resize);
3042 }
3043 
check_cluster_allocation(ntfs_volume * vol,ntfsck_t * fsck)3044 static void check_cluster_allocation(ntfs_volume *vol, ntfsck_t *fsck)
3045 {
3046 	memset(fsck, 0, sizeof(ntfsck_t));
3047 
3048 	if (opt.show_progress)
3049 		fsck->flags |= NTFSCK_PROGBAR;
3050 
3051 	if (setup_lcn_bitmap(&fsck->lcn_bitmap, vol->nr_clusters) != 0)
3052 		perr_exit("Failed to setup allocation bitmap");
3053 	if (build_allocation_bitmap(vol, fsck) != 0)
3054 		exit(1);
3055 	if (fsck->outsider || fsck->multi_ref) {
3056 		err_printf("Filesystem check failed!\n");
3057 		if (fsck->outsider)
3058 			err_printf("%d clusters are referenced outside "
3059 				   "of the volume.\n", fsck->outsider);
3060 		if (fsck->multi_ref)
3061 			err_printf("%d clusters are referenced multiple"
3062 				   " times.\n", fsck->multi_ref);
3063 		printf("%s", corrupt_volume_msg);
3064 		exit(1);
3065 	}
3066 
3067 	compare_bitmaps(vol, &fsck->lcn_bitmap);
3068 }
3069 
3070 /*
3071  *		Following are functions to expand an NTFS file system
3072  *	to the beginning of a partition. The old metadata can be
3073  *	located according to the backup bootsector, provided it can
3074  *	still be found at the end of the partition.
3075  *
3076  *	The data itself is kept in place, and this is only possible
3077  *	if the expanded size is a multiple of cluster size, and big
3078  *	enough to hold the new $Boot, $Bitmap and $MFT
3079  *
3080  *	The volume cannot be mounted because the layout of data does
3081  *	not match the volume parameters. The alignments of MFT entries
3082  *	and index blocks may be different in the new volume and the old
3083  *	one. The "ntfs_volume" structure is only partially usable,
3084  *	"ntfs_inode" and "search_context" cannot be used until the
3085  *	metadata has been moved and the volume is opened.
3086  *
3087  *	Currently, no part of this new code is called from old code,
3088  *	and the only change in old code is the processing of options.
3089  *	Deduplication of code should be done later when the code is
3090  *	proved safe.
3091  *
3092  */
3093 
3094 typedef struct EXPAND {
3095 	ntfs_volume *vol;
3096 	u64 original_sectors;
3097 	u64 new_sectors;
3098 	u64 bitmap_allocated;
3099 	u64 bitmap_size;
3100 	u64 boot_size;
3101 	u64 mft_size;
3102 	LCN mft_lcn;
3103 	s64 byte_increment;
3104 	s64 sector_increment;
3105 	s64 cluster_increment;
3106 	u8 *bitmap;
3107 	u8 *mft_bitmap;
3108 	char *bootsector;
3109 	MFT_RECORD *mrec;
3110 	struct progress_bar *progress;
3111 	struct DELAYED *delayed_runlists; /* runlists to process later */
3112 } expand_t;
3113 
3114 /*
3115  *		Locate an attribute in an MFT record
3116  *
3117  *	Returns NULL if not found (with no error message)
3118  */
3119 
find_attr(MFT_RECORD * mrec,ATTR_TYPES type,ntfschar * name,int namelen)3120 static ATTR_RECORD *find_attr(MFT_RECORD *mrec, ATTR_TYPES type,
3121 					ntfschar *name, int namelen)
3122 {
3123 	ATTR_RECORD *a;
3124 	u32 offset;
3125 	ntfschar *attrname;
3126 
3127 			/* fetch the requested attribute */
3128 	offset = le16_to_cpu(mrec->attrs_offset);
3129 	a = (ATTR_RECORD*)((char*)mrec + offset);
3130 	attrname = (ntfschar*)((char*)a + le16_to_cpu(a->name_offset));
3131 	while ((a->type != AT_END)
3132 	    && ((a->type != type)
3133 		|| (a->name_length != namelen)
3134 		|| (namelen && memcmp(attrname,name,2*namelen)))
3135 	    && (offset < le32_to_cpu(mrec->bytes_in_use))) {
3136 		offset += le32_to_cpu(a->length);
3137 		a = (ATTR_RECORD*)((char*)mrec + offset);
3138 		if (namelen)
3139 			attrname = (ntfschar*)((char*)a
3140 				+ le16_to_cpu(a->name_offset));
3141 	}
3142 	if ((a->type != type)
3143 	    || (a->name_length != namelen)
3144 	    || (namelen && memcmp(attrname,name,2*namelen)))
3145 		a = (ATTR_RECORD*)NULL;
3146 	return (a);
3147 }
3148 
3149 /*
3150  *		Read an MFT record and find an unnamed attribute
3151  *
3152  *	Returns NULL if fails to read or attribute is not found
3153  */
3154 
get_unnamed_attr(expand_t * expand,ATTR_TYPES type,s64 inum)3155 static ATTR_RECORD *get_unnamed_attr(expand_t *expand, ATTR_TYPES type,
3156 							s64 inum)
3157 {
3158 	ntfs_volume *vol;
3159 	ATTR_RECORD *a;
3160 	MFT_RECORD *mrec;
3161 	s64 pos;
3162 	BOOL found;
3163 	int got;
3164 
3165 	found = FALSE;
3166 	a = (ATTR_RECORD*)NULL;
3167 	mrec = expand->mrec;
3168 	vol = expand->vol;
3169 	pos = (vol->mft_lcn << vol->cluster_size_bits)
3170 		+ (inum << vol->mft_record_size_bits)
3171 		+ expand->byte_increment;
3172 	got = ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size, mrec);
3173 	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
3174 		a = find_attr(expand->mrec, type, NULL, 0);
3175 		found = a && (a->type == type) && !a->name_length;
3176 	}
3177 		/* not finding the attribute list is not an error */
3178 	if (!found && (type != AT_ATTRIBUTE_LIST)) {
3179 		err_printf("Could not find attribute 0x%lx in inode %lld\n",
3180 				(long)le32_to_cpu(type), (long long)inum);
3181 		a = (ATTR_RECORD*)NULL;
3182 	}
3183 	return (a);
3184 }
3185 
3186 /*
3187  *		Read an MFT record and find an unnamed attribute
3188  *
3189  *	Returns NULL if fails
3190  */
3191 
read_and_get_attr(expand_t * expand,ATTR_TYPES type,s64 inum,ntfschar * name,int namelen)3192 static ATTR_RECORD *read_and_get_attr(expand_t *expand, ATTR_TYPES type,
3193 				s64 inum, ntfschar *name, int namelen)
3194 {
3195 	ntfs_volume *vol;
3196 	ATTR_RECORD *a;
3197 	MFT_RECORD *mrec;
3198 	s64 pos;
3199 	int got;
3200 
3201 	a = (ATTR_RECORD*)NULL;
3202 	mrec = expand->mrec;
3203 	vol = expand->vol;
3204 	pos = (vol->mft_lcn << vol->cluster_size_bits)
3205 		+ (inum << vol->mft_record_size_bits)
3206 		+ expand->byte_increment;
3207 	got = ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size, mrec);
3208 	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
3209 		a = find_attr(expand->mrec, type, name, namelen);
3210 	}
3211 	if (!a) {
3212 		err_printf("Could not find attribute 0x%lx in inode %lld\n",
3213 				(long)le32_to_cpu(type), (long long)inum);
3214 	}
3215 	return (a);
3216 }
3217 
3218 /*
3219  *		Get the size allocated to the unnamed data of some inode
3220  *
3221  *	Returns zero if fails.
3222  */
3223 
get_data_size(expand_t * expand,s64 inum)3224 static s64 get_data_size(expand_t *expand, s64 inum)
3225 {
3226 	ATTR_RECORD *a;
3227 	s64 size;
3228 
3229 	size = 0;
3230 			/* get the size of unnamed $DATA */
3231 	a = get_unnamed_attr(expand, AT_DATA, inum);
3232 	if (a && a->non_resident)
3233 		size = sle64_to_cpu(a->allocated_size);
3234 	if (!size) {
3235 		err_printf("Bad record %lld, could not get its size\n",
3236 					(long long)inum);
3237 	}
3238 	return (size);
3239 }
3240 
3241 /*
3242  *		Get the MFT bitmap
3243  *
3244  *	Returns NULL if fails.
3245  */
3246 
get_mft_bitmap(expand_t * expand)3247 static u8 *get_mft_bitmap(expand_t *expand)
3248 {
3249 	ATTR_RECORD *a;
3250 	ntfs_volume *vol;
3251 	runlist_element *rl;
3252 	runlist_element *prl;
3253 	u32 bitmap_size;
3254 	BOOL ok;
3255 
3256 	expand->mft_bitmap = (u8*)NULL;
3257 	vol = expand->vol;
3258 			/* get the runlist of unnamed bitmap */
3259 	a = get_unnamed_attr(expand, AT_BITMAP, FILE_MFT);
3260 	ok = TRUE;
3261 	bitmap_size = sle64_to_cpu(a->allocated_size);
3262 	if (a
3263 	    && a->non_resident
3264 	    && ((bitmap_size << (vol->mft_record_size_bits + 3))
3265 			>= expand->mft_size)) {
3266 // rl in extent not implemented
3267 		rl = ntfs_mapping_pairs_decompress(expand->vol, a,
3268 						(runlist_element*)NULL);
3269 		expand->mft_bitmap = (u8*)ntfs_calloc(bitmap_size);
3270 		if (rl && expand->mft_bitmap) {
3271 			for (prl=rl; prl->length && ok; prl++) {
3272 				lseek_to_cluster(vol,
3273 					prl->lcn + expand->cluster_increment);
3274 				ok = !read_all(vol->dev, expand->mft_bitmap
3275 					+ (prl->vcn << vol->cluster_size_bits),
3276 					prl->length << vol->cluster_size_bits);
3277 			}
3278 			if (!ok) {
3279 				err_printf("Could not read the MFT bitmap\n");
3280 				free(expand->mft_bitmap);
3281 				expand->mft_bitmap = (u8*)NULL;
3282 			}
3283 			free(rl);
3284 		} else {
3285 			err_printf("Could not get the MFT bitmap\n");
3286 		}
3287 	} else
3288 		err_printf("Invalid MFT bitmap\n");
3289 	return (expand->mft_bitmap);
3290 }
3291 
3292 /*
3293  *		Check for bad sectors
3294  *
3295  *	Deduplication to be done when proved safe
3296  */
3297 
check_expand_bad_sectors(expand_t * expand,ATTR_RECORD * a)3298 static int check_expand_bad_sectors(expand_t *expand, ATTR_RECORD *a)
3299 {
3300 	runlist *rl;
3301 	int res;
3302 	s64 i, badclusters = 0;
3303 
3304 	res = 0;
3305 	ntfs_log_verbose("Checking for bad sectors ...\n");
3306 
3307 	if (find_attr(expand->mrec, AT_ATTRIBUTE_LIST, NULL, 0)) {
3308 		err_printf("Hopelessly many bad sectors have been detected!\n");
3309 		err_printf("%s", many_bad_sectors_msg);
3310 		res = -1;
3311 	} else {
3312 
3313 	/*
3314 	 * FIXME: The below would be partial for non-base records in the
3315 	 * not yet supported multi-record case. Alternatively use audited
3316 	 * ntfs_attr_truncate after an umount & mount.
3317 	 */
3318 		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
3319 		if (!rl) {
3320 			perr_printf("Decompressing $BadClust:"
3321 					"$Bad mapping pairs failed");
3322 			res = -1;
3323 		} else {
3324 			for (i = 0; rl[i].length; i++) {
3325 		/* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
3326 				if (rl[i].lcn == LCN_HOLE
3327 				    || rl[i].lcn == LCN_RL_NOT_MAPPED)
3328 					continue;
3329 
3330 				badclusters += rl[i].length;
3331 				ntfs_log_verbose("Bad cluster: %#8llx - %#llx"
3332 						"    (%lld)\n",
3333 						(long long)rl[i].lcn,
3334 						(long long)rl[i].lcn
3335 							+ rl[i].length - 1,
3336 						(long long)rl[i].length);
3337 			}
3338 
3339 			if (badclusters) {
3340 				err_printf("%sThis software has detected that"
3341 					" the disk has at least"
3342 					" %lld bad sector%s.\n",
3343 					!opt.badsectors ? NERR_PREFIX
3344 							: "WARNING: ",
3345 					(long long)badclusters,
3346 					badclusters - 1 ? "s" : "");
3347 				if (!opt.badsectors) {
3348 					err_printf("%s", bad_sectors_warning_msg);
3349 					res = -1;
3350 				} else
3351 					err_printf("WARNING: Bad sectors can cause"
3352 						" reliability problems"
3353 						" and massive data loss!!!\n");
3354 			}
3355 		free(rl);
3356 		}
3357 	}
3358 	return (res);
3359 }
3360 
3361 /*
3362  *		Check miscellaneous expansion constraints
3363  */
3364 
check_expand_constraints(expand_t * expand)3365 static int check_expand_constraints(expand_t *expand)
3366 {
3367 	static ntfschar bad[] = {
3368 			const_cpu_to_le16('$'), const_cpu_to_le16('B'),
3369 			const_cpu_to_le16('a'), const_cpu_to_le16('d')
3370 	} ;
3371 	ATTR_RECORD *a;
3372 	runlist_element *rl;
3373 	VOLUME_INFORMATION *volinfo;
3374 	VOLUME_FLAGS flags;
3375 	int res;
3376 
3377 	if (opt.verbose)
3378 		ntfs_log_verbose("Checking for expansion constraints...\n");
3379 	res = 0;
3380 		/* extents for $MFT are not supported */
3381 	if (get_unnamed_attr(expand, AT_ATTRIBUTE_LIST, FILE_MFT)) {
3382 		err_printf("The $MFT is too much fragmented\n");
3383 		res = -1;
3384 	}
3385 		/* fragmented $MFTMirr is not supported */
3386 	a = get_unnamed_attr(expand, AT_DATA, FILE_MFTMirr);
3387 	if (a) {
3388 		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
3389 		if (!rl || !rl[0].length || rl[1].length) {
3390 			err_printf("$MFTMirr is bad or fragmented\n");
3391 			res = -1;
3392 		}
3393 		free(rl);
3394 	}
3395 		/* fragmented $Boot is not supported */
3396 	a = get_unnamed_attr(expand, AT_DATA, FILE_Boot);
3397 	if (a) {
3398 		rl = ntfs_mapping_pairs_decompress(expand->vol, a, NULL);
3399 		if (!rl || !rl[0].length || rl[1].length) {
3400 			err_printf("$Boot is bad or fragmented\n");
3401 			res = -1;
3402 		}
3403 		free(rl);
3404 	}
3405 		/* Volume should not be marked dirty */
3406 	a = get_unnamed_attr(expand, AT_VOLUME_INFORMATION, FILE_Volume);
3407 	if (a) {
3408 		volinfo = (VOLUME_INFORMATION*)
3409 				(le16_to_cpu(a->value_offset) + (char*)a);
3410 		flags = volinfo->flags;
3411 		if ((flags & VOLUME_IS_DIRTY) && (opt.force-- <= 0)) {
3412 			err_printf("Volume is scheduled for check.\nRun chkdsk /f"
3413 			 " and please try again, or see option -f.\n");
3414 			res = -1;
3415 		}
3416 	} else {
3417 		err_printf("Could not get Volume flags\n");
3418 		res = -1;
3419 	}
3420 
3421 		/* There should not be too many bad clusters */
3422 	a = read_and_get_attr(expand, AT_DATA, FILE_BadClus, bad, 4);
3423 	if (!a || !a->non_resident) {
3424 		err_printf("Resident attribute in $BadClust! Please report to "
3425 			 	"%s\n", NTFS_DEV_LIST);
3426 		res = -1;
3427 	} else
3428 		if (check_expand_bad_sectors(expand,a))
3429 			res = -1;
3430 	return (res);
3431 }
3432 
3433 /*
3434  *		Compute the new sizes and check whether the NTFS file
3435  *	system can be expanded
3436  *
3437  *	The partition has to have been expanded,
3438  *	the extra space must be able to hold the $MFT, $Boot, and $Bitmap
3439  *	the extra space must be a multiple of cluster size
3440  *
3441  *	Returns TRUE if the partition can be expanded,
3442  *		FALSE if it canno be expanded or option --info was set
3443  */
3444 
can_expand(expand_t * expand,ntfs_volume * vol)3445 static BOOL can_expand(expand_t *expand, ntfs_volume *vol)
3446 {
3447 	s64 old_sector_count;
3448 	s64 sectors_needed;
3449 	s64 clusters;
3450 	s64 minimum_size;
3451 	s64 got;
3452 	s64 advice;
3453 	s64 bitmap_bits;
3454 	BOOL ok;
3455 
3456 	ok = TRUE;
3457 	old_sector_count = vol->nr_clusters
3458 			<< (vol->cluster_size_bits - vol->sector_size_bits);
3459 		/* do not include the space lost near the end */
3460 	expand->cluster_increment = (expand->new_sectors
3461 			 >> (vol->cluster_size_bits - vol->sector_size_bits))
3462 				- vol->nr_clusters;
3463 	expand->byte_increment = expand->cluster_increment
3464 					<< vol->cluster_size_bits;
3465 	expand->sector_increment = expand->byte_increment
3466 					>> vol->sector_size_bits;
3467 	printf("Sectors allocated to volume :  old %lld current %lld difference %lld\n",
3468 			(long long)old_sector_count,
3469 			(long long)(old_sector_count + expand->sector_increment),
3470 			(long long)expand->sector_increment);
3471 	printf("Clusters allocated to volume : old %lld current %lld difference %lld\n",
3472 			(long long)vol->nr_clusters,
3473 			(long long)(vol->nr_clusters
3474 					+ expand->cluster_increment),
3475 			(long long)expand->cluster_increment);
3476 		/* the new size must be bigger */
3477 	if ((expand->sector_increment < 0)
3478 	    || (!expand->sector_increment && !opt.info)) {
3479 		err_printf("Cannot expand volume : the partition has not been expanded\n");
3480 		ok = FALSE;
3481 	}
3482 			/* the old bootsector must match the backup */
3483 	got = ntfs_pread(expand->vol->dev, expand->byte_increment,
3484 				vol->sector_size, expand->mrec);
3485 	if ((got != vol->sector_size)
3486 	    || memcmp(expand->bootsector,expand->mrec,vol->sector_size)) {
3487 		err_printf("The backup bootsector does not match the old bootsector\n");
3488 		ok = FALSE;
3489 	}
3490 	if (ok) {
3491 			/* read the first MFT record, to get the MFT size */
3492 		expand->mft_size = get_data_size(expand, FILE_MFT);
3493 			/* read the 6th MFT record, to get the $Boot size */
3494 		expand->boot_size = get_data_size(expand, FILE_Boot);
3495 		if (!expand->mft_size || !expand->boot_size) {
3496 			ok = FALSE;
3497 		} else {
3498 			/*
3499 			 * The bitmap is one bit per full cluster,
3500 			 * accounting for the backup bootsector.
3501 			 * When evaluating the minimal size, the bitmap
3502 			 * size must be adapted to the minimal size :
3503 			 *  bits = clusters + ceil(clusters/clustersize)
3504 			 */
3505 			if (opt.info) {
3506 				clusters = (((expand->original_sectors + 1)
3507 						<< vol->sector_size_bits)
3508 						+ expand->mft_size
3509 						+ expand->boot_size)
3510 						    >> vol->cluster_size_bits;
3511 				bitmap_bits = ((clusters + 1)
3512 						    << vol->cluster_size_bits)
3513 						/ (vol->cluster_size + 1);
3514 			} else {
3515 				bitmap_bits = (expand->new_sectors + 1)
3516 			    		>> (vol->cluster_size_bits
3517 						- vol->sector_size_bits);
3518 			}
3519 			/* byte size must be a multiple of 8 */
3520 			expand->bitmap_size = ((bitmap_bits + 63) >> 3) & -8;
3521 			expand->bitmap_allocated = ((expand->bitmap_size - 1)
3522 				| (vol->cluster_size - 1)) + 1;
3523 			expand->mft_lcn = (expand->boot_size
3524 					+ expand->bitmap_allocated)
3525 						>> vol->cluster_size_bits;
3526 			/*
3527 			 * Check whether $Boot, $Bitmap and $MFT can fit
3528 			 * into the expanded space.
3529 			 */
3530 			sectors_needed = (expand->boot_size + expand->mft_size
3531 					 + expand->bitmap_allocated)
3532 						>> vol->sector_size_bits;
3533 			if (!opt.info
3534 			    && (sectors_needed >= expand->sector_increment)) {
3535 				err_printf("The expanded space cannot hold the new metadata\n");
3536 				err_printf("   expanded space %lld sectors\n",
3537 					(long long)expand->sector_increment);
3538 				err_printf("   needed space %lld sectors\n",
3539 					(long long)sectors_needed);
3540 				ok = FALSE;
3541 			}
3542 		}
3543 	}
3544 	if (ok) {
3545 		advice = expand->byte_increment;
3546 		/* the increment must be an integral number of clusters */
3547 		if (expand->byte_increment & (vol->cluster_size - 1)) {
3548 			err_printf("Cannot expand volume without copying the data :\n");
3549 			err_printf("There are %d sectors in a cluster,\n",
3550 				(int)(vol->cluster_size/vol->sector_size));
3551 			err_printf("  and the sector difference is not a multiple of %d\n",
3552 				(int)(vol->cluster_size/vol->sector_size));
3553 			advice = expand->byte_increment & ~vol->cluster_size;
3554 			ok = FALSE;
3555 		}
3556 		if (!ok)
3557 			err_printf("You should increase the beginning of partition by %d sectors\n",
3558 				(int)((expand->byte_increment - advice)
3559 					>> vol->sector_size_bits));
3560 	}
3561 	if (ok)
3562 		ok = !check_expand_constraints(expand);
3563 	if (ok && opt.info) {
3564 		minimum_size = (expand->original_sectors
3565 						<< vol->sector_size_bits)
3566 					+ expand->boot_size
3567 					+ expand->mft_size
3568 					+ expand->bitmap_allocated;
3569 
3570 		printf("You must expand the partition to at least %lld bytes,\n",
3571 			(long long)(minimum_size + vol->sector_size));
3572 		printf("and you may add a multiple of %ld bytes to this size.\n",
3573 			(long)vol->cluster_size);
3574 		printf("The minimum NTFS volume size is %lld bytes\n",
3575 			(long long)minimum_size);
3576 		ok = FALSE;
3577 	}
3578 	return (ok);
3579 }
3580 
set_bitmap(expand_t * expand,runlist_element * rl)3581 static int set_bitmap(expand_t *expand, runlist_element *rl)
3582 {
3583 	int res;
3584 	s64 lcn;
3585 	s64 lcn_end;
3586 	BOOL reallocated;
3587 
3588 	res = -1;
3589 	reallocated = FALSE;
3590 	if ((rl->lcn >= 0)
3591 	    && (rl->length > 0)
3592 	    && ((rl->lcn + rl->length)
3593 		    <= (expand->vol->nr_clusters + expand->cluster_increment))) {
3594 		lcn = rl->lcn;
3595 		lcn_end = lcn + rl->length;
3596 		while ((lcn & 7) && (lcn < lcn_end)) {
3597 			if (expand->bitmap[lcn >> 3] & 1 << (lcn & 7))
3598 				reallocated = TRUE;
3599 			expand->bitmap[lcn >> 3] |= 1 << (lcn & 7);
3600 			lcn++;
3601 		}
3602 		while ((lcn_end - lcn) >= 8) {
3603 			if (expand->bitmap[lcn >> 3])
3604 				reallocated = TRUE;
3605 			expand->bitmap[lcn >> 3] = 255;
3606 			lcn += 8;
3607 		}
3608 		while (lcn < lcn_end) {
3609 			if (expand->bitmap[lcn >> 3] & 1 << (lcn & 7))
3610 				reallocated = TRUE;
3611 			expand->bitmap[lcn >> 3] |= 1 << (lcn & 7);
3612 			lcn++;
3613 		}
3614 		if (reallocated)
3615 			err_printf("Reallocated cluster found in run"
3616 				" lcn 0x%llx length %lld\n",
3617 				(long long)rl->lcn,(long long)rl->length);
3618 		else
3619 			res = 0;
3620 	} else {
3621 		err_printf("Bad run : lcn 0x%llx length %lld\n",
3622 			(long long)rl->lcn,(long long)rl->length);
3623 	}
3624 	return (res);
3625 }
3626 
3627 /*
3628  *		Write the backup bootsector
3629  *
3630  *	When this has been done, the resizing cannot be done again
3631  */
3632 
write_bootsector(expand_t * expand)3633 static int write_bootsector(expand_t *expand)
3634 {
3635 	ntfs_volume *vol;
3636 	s64 bw;
3637 	int res;
3638 
3639 	res = -1;
3640 	vol = expand->vol;
3641 	if (opt.verbose)
3642 		ntfs_log_verbose("Rewriting the backup bootsector\n");
3643 	if (opt.ro_flag)
3644 		bw = vol->sector_size;
3645 	else
3646 		bw = ntfs_pwrite(vol->dev,
3647 				expand->new_sectors*vol->sector_size,
3648 				vol->sector_size, expand->bootsector);
3649 	if (bw == vol->sector_size)
3650 		res = 0;
3651 	else {
3652 		if (bw != -1)
3653 			errno = EINVAL;
3654 		if (!bw)
3655 			err_printf("Failed to rewrite the bootsector (size=0)\n");
3656 		else
3657 			err_printf("Error rewriting the bootsector");
3658 	}
3659 	return (res);
3660 }
3661 
3662 /*
3663  *		Write the new main bitmap
3664  */
3665 
write_bitmap(expand_t * expand)3666 static int write_bitmap(expand_t *expand)
3667 {
3668 	ntfs_volume *vol;
3669 	s64 bw;
3670 	u64 cluster;
3671 	int res;
3672 
3673 	res = -1;
3674 	vol = expand->vol;
3675 	cluster = vol->nr_clusters + expand->cluster_increment;
3676 	while (cluster < (expand->bitmap_size << 3)) {
3677 		expand->bitmap[cluster >> 3] |= 1 << (cluster & 7);
3678 		cluster++;
3679 	}
3680 	if (opt.verbose)
3681 		ntfs_log_verbose("Writing the new bitmap...\n");
3682 		/* write the full allocation (to avoid having to read) */
3683 	if (opt.ro_flag)
3684 		bw = expand->bitmap_allocated;
3685 	else
3686 		bw = ntfs_pwrite(vol->dev, expand->boot_size,
3687 					expand->bitmap_allocated, expand->bitmap);
3688 	if (bw == (s64)expand->bitmap_allocated)
3689 		res = 0;
3690 	else {
3691 		if (bw != -1)
3692 			errno = EINVAL;
3693 		if (!bw)
3694 			err_printf("Failed to write the bitmap (size=0)\n");
3695 		else
3696 			err_printf("Error rewriting the bitmap");
3697 	}
3698 	return (res);
3699 }
3700 
3701 /*
3702  *		Copy the $MFT to $MFTMirr
3703  *
3704  *	The $MFTMirr is not relocated as it should be kept away from $MFT.
3705  *	Apart from the backup bootsector, this is the only part which is
3706  *	overwritten. This has no effect on being able to redo the resizing
3707  *	if something goes wrong, as the $MFTMirr is never read. However
3708  *	this is done near the end of the resizing.
3709  */
3710 
copy_mftmirr(expand_t * expand)3711 static int copy_mftmirr(expand_t *expand)
3712 {
3713 	ntfs_volume *vol;
3714 	s64 pos;
3715 	s64 inum;
3716 	int res;
3717 	u16 usa_ofs;
3718 	le16 *pusn;
3719 	u16 usn;
3720 
3721 	if (opt.verbose)
3722 		ntfs_log_verbose("Copying $MFT to $MFTMirr...\n");
3723 	vol = expand->vol;
3724 	res = 0;
3725 	for (inum=FILE_MFT; !res && (inum<=FILE_Volume); inum++) {
3726 			/* read the new $MFT */
3727 		pos = (expand->mft_lcn << vol->cluster_size_bits)
3728 			+ (inum << vol->mft_record_size_bits);
3729 		if (ntfs_mst_pread(vol->dev, pos, 1, vol->mft_record_size,
3730 				expand->mrec) == 1) {
3731 				/* overwrite the old $MFTMirr */
3732 			pos = (vol->mftmirr_lcn << vol->cluster_size_bits)
3733 				+ (inum << vol->mft_record_size_bits)
3734 				+ expand->byte_increment;
3735 			usa_ofs = le16_to_cpu(expand->mrec->usa_ofs);
3736 			pusn = (le16*)((u8*)expand->mrec + usa_ofs);
3737 			usn = le16_to_cpu(*pusn) - 1;
3738 			if (!usn || (usn == 0xffff))
3739 				usn = -2;
3740 			*pusn = cpu_to_le16(usn);
3741 			if (!opt.ro_flag
3742 			    && (ntfs_mst_pwrite(vol->dev, pos, 1,
3743 				    vol->mft_record_size, expand->mrec) != 1)) {
3744 				err_printf("Failed to overwrite the old $MFTMirr\n");
3745 				res = -1;
3746 			}
3747 		} else {
3748 			err_printf("Failed to write the new $MFT\n");
3749 			res = -1;
3750 		}
3751 	}
3752 	return (res);
3753 }
3754 
3755 /*
3756  *		Copy the $Boot, including the bootsector
3757  *
3758  *	When the bootsector has been copied, repair tools are able to
3759  *	fix things, but this is dangerous if the other metadata do
3760  *	not point to actual user data. So this must be done near the end
3761  *	of resizing.
3762  */
3763 
copy_boot(expand_t * expand)3764 static int copy_boot(expand_t *expand)
3765 {
3766 	NTFS_BOOT_SECTOR *bs;
3767 	char *buf;
3768 	ntfs_volume *vol;
3769 	s64 mftmirr_lcn;
3770 	s64 written;
3771 	u32 boot_cnt;
3772 	u32 hidden_sectors;
3773 	le32 hidden_sectors_le;
3774 	int res;
3775 
3776 	if (opt.verbose)
3777 		ntfs_log_verbose("Copying $Boot...\n");
3778 	vol = expand->vol;
3779 	res = 0;
3780 	buf = (char*)ntfs_malloc(vol->cluster_size);
3781 	if (buf) {
3782 			/* set the new volume parameters in the bootsector */
3783 		bs = (NTFS_BOOT_SECTOR*)expand->bootsector;
3784 		bs->number_of_sectors = cpu_to_sle64(expand->new_sectors);
3785 		bs->mft_lcn = cpu_to_sle64(expand->mft_lcn);
3786 		mftmirr_lcn = vol->mftmirr_lcn + expand->cluster_increment;
3787 		bs->mftmirr_lcn = cpu_to_sle64(mftmirr_lcn);
3788 			/* the hidden sectors are needed to boot into windows */
3789 		memcpy(&hidden_sectors_le,&bs->bpb.hidden_sectors,4);
3790 				/* alignment messed up on the Sparc */
3791 		if (hidden_sectors_le) {
3792 			hidden_sectors = le32_to_cpu(hidden_sectors_le);
3793 			if (hidden_sectors >= expand->sector_increment)
3794 				hidden_sectors -= expand->sector_increment;
3795 			else
3796 				hidden_sectors = 0;
3797 			hidden_sectors_le = cpu_to_le32(hidden_sectors);
3798 			memcpy(&bs->bpb.hidden_sectors,&hidden_sectors_le,4);
3799 		}
3800 		written = 0;
3801 		boot_cnt = expand->boot_size >> vol->cluster_size_bits;
3802 		while (!res && (written < boot_cnt)) {
3803 			lseek_to_cluster(vol, expand->cluster_increment + written);
3804 			if (!read_all(vol->dev, buf, vol->cluster_size)) {
3805 				if (!written)
3806 					memcpy(buf, expand->bootsector, vol->sector_size);
3807 				lseek_to_cluster(vol, written);
3808 				if (!opt.ro_flag
3809 				    && write_all(vol->dev, buf, vol->cluster_size)) {
3810 					err_printf("Failed to write the new $Boot\n");
3811 					res = -1;
3812 				} else
3813 					written++;
3814 			} else {
3815 				err_printf("Failed to read the old $Boot\n");
3816 				res = -1;
3817 			}
3818 		}
3819 		free(buf);
3820 	} else {
3821 		err_printf("Failed to allocate buffer\n");
3822 		res = -1;
3823 	}
3824 	return (res);
3825 }
3826 
3827 /*
3828  *		Process delayed runlist updates
3829  *
3830  *	This is derived from delayed_updates() and they should
3831  *	both be merged when the new code is considered safe.
3832  */
3833 
delayed_expand(ntfs_volume * vol,struct DELAYED * delayed,struct progress_bar * progress)3834 static void delayed_expand(ntfs_volume *vol, struct DELAYED *delayed,
3835 			struct progress_bar *progress)
3836 {
3837 	unsigned long count;
3838 	struct DELAYED *current;
3839 	int step = 100;
3840 
3841 	if (delayed) {
3842 		if (opt.verbose)
3843 			ntfs_log_verbose("Delayed updating of overflowing runlists...\n");
3844 		count = 0;
3845 			/* count by steps because of inappropriate resolution */
3846 		for (current=delayed; current; current=current->next)
3847 			count += step;
3848 		progress_init(progress, 0, count,
3849 					(opt.show_progress ? NTFS_PROGBAR : 0));
3850 		current = delayed;
3851 		count = 0;
3852 		while (current) {
3853 			delayed = current;
3854 			if (!opt.ro_flag)
3855 				expand_attribute_runlist(vol, delayed);
3856 			count += step;
3857 			progress_update(progress, count);
3858 			current = current->next;
3859 			if (delayed->attr_name)
3860 				free(delayed->attr_name);
3861 			free(delayed->head_rl);
3862 			free(delayed);
3863 		}
3864 	}
3865 }
3866 
3867 /*
3868  *		Expand the sizes in indexes for inodes which were expanded
3869  *
3870  *	Only the new $Bitmap sizes are identified as needed to be
3871  *	adjusted in index. The $BadClus is only expanded in an
3872  *	alternate data stream, whose sizes are not present in the index.
3873  *
3874  *	This is modifying the initial data, and can only be done when
3875  *	the volume has been reopened after expanding.
3876  */
3877 
expand_index_sizes(expand_t * expand)3878 static int expand_index_sizes(expand_t *expand)
3879 {
3880 	ntfs_inode *ni;
3881 	int res;
3882 
3883 	res = -1;
3884 	ni = ntfs_inode_open(expand->vol, FILE_Bitmap);
3885 	if (ni) {
3886 		NInoSetDirty(ni);
3887 		NInoFileNameSetDirty(ni);
3888 		ntfs_inode_close(ni);
3889 		res = 0;
3890 	}
3891 	return (res);
3892 }
3893 
3894 /*
3895  *		Update a runlist into an attribute
3896  *
3897  *	This is derived from replace_attribute_runlist() and they should
3898  *	both be merged when the new code is considered safe.
3899  */
3900 
update_runlist(expand_t * expand,s64 inum,ATTR_RECORD * a,runlist_element * rl)3901 static int update_runlist(expand_t *expand, s64 inum,
3902 				ATTR_RECORD *a, runlist_element *rl)
3903 {
3904 	ntfs_resize_t resize;
3905 	ntfs_attr_search_ctx ctx;
3906 	ntfs_volume *vol;
3907 	MFT_RECORD *mrec;
3908 	runlist *head_rl;
3909 	int mp_size;
3910 	int l;
3911 	int must_delay;
3912 	void *mp;
3913 
3914 	vol = expand->vol;
3915 	mrec = expand->mrec;
3916 	head_rl = rl;
3917 	rl_fixup(&rl);
3918 	if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl,
3919 				0, INT_MAX)) == -1)
3920 		perr_exit("ntfs_get_size_for_mapping_pairs");
3921 
3922 	if (a->name_length) {
3923 		u16 name_offs = le16_to_cpu(a->name_offset);
3924 		u16 mp_offs = le16_to_cpu(a->mapping_pairs_offset);
3925 
3926 		if (name_offs >= mp_offs)
3927 			err_exit("Attribute name is after mapping pairs! "
3928 				 "Please report!\n");
3929 	}
3930 
3931 	/* CHECKME: don't trust mapping_pairs is always the last item in the
3932 	   attribute, instead check for the real size/space */
3933 	l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->mapping_pairs_offset);
3934 	must_delay = 0;
3935 	if (mp_size > l) {
3936 		s32 remains_size;
3937 		char *next_attr;
3938 
3939 		ntfs_log_verbose("Enlarging attribute header ...\n");
3940 
3941 		mp_size = (mp_size + 7) & ~7;
3942 
3943 		ntfs_log_verbose("Old mp size      : %d\n", l);
3944 		ntfs_log_verbose("New mp size      : %d\n", mp_size);
3945 		ntfs_log_verbose("Bytes in use     : %u\n", (unsigned int)
3946 				 le32_to_cpu(mrec->bytes_in_use));
3947 
3948 		next_attr = (char *)a + le32_to_cpu(a->length);
3949 		l = mp_size - l;
3950 
3951 		ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
3952 				 le32_to_cpu(mrec->bytes_in_use));
3953 		ntfs_log_verbose("Bytes allocated  : %u\n", (unsigned int)
3954 				 le32_to_cpu(mrec->bytes_allocated));
3955 
3956 		remains_size = le32_to_cpu(mrec->bytes_in_use);
3957 		remains_size -= (next_attr - (char *)mrec);
3958 
3959 		ntfs_log_verbose("increase         : %d\n", l);
3960 		ntfs_log_verbose("shift            : %lld\n",
3961 				 (long long)remains_size);
3962 		if (le32_to_cpu(mrec->bytes_in_use) + l >
3963 				le32_to_cpu(mrec->bytes_allocated)) {
3964 			ntfs_log_verbose("Queuing expansion for later processing\n");
3965 				/* hack for reusing unmodified old code ! */
3966 			resize.ctx = &ctx;
3967 			ctx.attr = a;
3968 			ctx.mrec = mrec;
3969 			resize.mref = inum;
3970 			resize.delayed_runlists = expand->delayed_runlists;
3971 			resize.mirr_from = MIRR_OLD;
3972 			must_delay = 1;
3973 			replace_later(&resize,rl,head_rl);
3974 			expand->delayed_runlists = resize.delayed_runlists;
3975 		} else {
3976 			memmove(next_attr + l, next_attr, remains_size);
3977 			mrec->bytes_in_use = cpu_to_le32(l +
3978 					le32_to_cpu(mrec->bytes_in_use));
3979 			a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
3980 		}
3981 	}
3982 
3983 	if (!must_delay) {
3984 		mp = ntfs_calloc(mp_size);
3985 		if (!mp)
3986 			perr_exit("ntfsc_calloc couldn't get memory");
3987 
3988 		if (ntfs_mapping_pairs_build(vol, (u8*)mp, mp_size, rl, 0, NULL))
3989 			perr_exit("ntfs_mapping_pairs_build");
3990 
3991 		memmove((u8*)a + le16_to_cpu(a->mapping_pairs_offset), mp, mp_size);
3992 
3993 		free(mp);
3994 	}
3995 	return (must_delay);
3996 }
3997 
3998 /*
3999  *		Create a minimal valid MFT record
4000  */
4001 
minimal_record(expand_t * expand,MFT_RECORD * mrec)4002 static int minimal_record(expand_t *expand, MFT_RECORD *mrec)
4003 {
4004 	int usa_count;
4005 	u32 bytes_in_use;
4006 
4007 	memset(mrec,0,expand->vol->mft_record_size);
4008 	mrec->magic = magic_FILE;
4009 	mrec->usa_ofs = const_cpu_to_le16(sizeof(MFT_RECORD));
4010 	usa_count = expand->vol->mft_record_size / NTFS_BLOCK_SIZE + 1;
4011 	mrec->usa_count = cpu_to_le16(usa_count);
4012 	bytes_in_use = (sizeof(MFT_RECORD) + 2*usa_count + 7) & -8;
4013 	memset(((char*)mrec) + bytes_in_use, 255, 4);  /* AT_END */
4014 	bytes_in_use += 8;
4015 	mrec->bytes_in_use = cpu_to_le32(bytes_in_use);
4016 	mrec->bytes_allocated = cpu_to_le32(expand->vol->mft_record_size);
4017 	return (0);
4018 }
4019 
4020 /*
4021  *		Rebase all runlists of an MFT record
4022  *
4023  *	Iterate through all its attributes and offset the non resident ones
4024  */
4025 
rebase_runlists(expand_t * expand,s64 inum)4026 static int rebase_runlists(expand_t *expand, s64 inum)
4027 {
4028 	MFT_RECORD *mrec;
4029 	ATTR_RECORD *a;
4030 	runlist_element *rl;
4031 	runlist_element *prl;
4032 	u32 offset;
4033 	int res;
4034 
4035 	res = 0;
4036 	mrec = expand->mrec;
4037 	offset = le16_to_cpu(mrec->attrs_offset);
4038 	a = (ATTR_RECORD*)((char*)mrec + offset);
4039 	while (!res && (a->type != AT_END)
4040 			&& (offset < le32_to_cpu(mrec->bytes_in_use))) {
4041 		if (a->non_resident) {
4042 			rl = ntfs_mapping_pairs_decompress(expand->vol, a,
4043 						(runlist_element*)NULL);
4044 			if (rl) {
4045 				for (prl=rl; prl->length; prl++)
4046 					if (prl->lcn >= 0) {
4047 						prl->lcn += expand->cluster_increment;
4048 						if (set_bitmap(expand,prl))
4049 							res = -1;
4050 						}
4051 				if (update_runlist(expand,inum,a,rl)) {
4052 					ntfs_log_verbose("Runlist updating has to be delayed\n");
4053 				} else
4054 					free(rl);
4055 			} else {
4056 				err_printf("Could not get a runlist of inode %lld\n",
4057 						(long long)inum);
4058 				res = -1;
4059 			}
4060 		}
4061 		offset += le32_to_cpu(a->length);
4062 		a = (ATTR_RECORD*)((char*)mrec + offset);
4063 	}
4064 	return (res);
4065 }
4066 
4067 /*
4068  *		Rebase the runlists present in records with relocated $DATA
4069  *
4070  *	The returned runlist is the old rebased runlist for $DATA,
4071  *	which is generally different from the new computed runlist.
4072  */
4073 
rebase_runlists_meta(expand_t * expand,s64 inum)4074 static runlist_element *rebase_runlists_meta(expand_t *expand, s64 inum)
4075 {
4076 	MFT_RECORD *mrec;
4077 	ATTR_RECORD *a;
4078 	ntfs_volume *vol;
4079 	runlist_element *rl;
4080 	runlist_element *old_rl;
4081 	runlist_element *prl;
4082 	runlist_element new_rl[2];
4083 	s64 data_size;
4084 	s64 allocated_size;
4085 	s64 lcn;
4086 	u64 lth;
4087 	u32 offset;
4088 	BOOL keeprl;
4089 	int res;
4090 
4091 	res = 0;
4092 	old_rl = (runlist_element*)NULL;
4093 	vol = expand->vol;
4094 	mrec = expand->mrec;
4095 	switch (inum) {
4096 	case FILE_Boot :
4097 		lcn = 0;
4098 		lth = expand->boot_size >> vol->cluster_size_bits;
4099 		data_size = expand->boot_size;
4100 		break;
4101 	case FILE_Bitmap :
4102 		lcn = expand->boot_size >> vol->cluster_size_bits;
4103 		lth = expand->bitmap_allocated >> vol->cluster_size_bits;
4104 		data_size = expand->bitmap_size;
4105 		break;
4106 	case FILE_MFT :
4107 		lcn = (expand->boot_size + expand->bitmap_allocated)
4108 				>> vol->cluster_size_bits;
4109 		lth = expand->mft_size >> vol->cluster_size_bits;
4110 		data_size = expand->mft_size;
4111 		break;
4112 	case FILE_BadClus :
4113 		lcn = 0; /* not used */
4114 		lth = vol->nr_clusters + expand->cluster_increment;
4115 		data_size = lth << vol->cluster_size_bits;
4116 		break;
4117 	default :
4118 		lcn = lth = data_size = 0;
4119 		res = -1;
4120 	}
4121 	allocated_size = lth << vol->cluster_size_bits;
4122 	offset = le16_to_cpu(mrec->attrs_offset);
4123 	a = (ATTR_RECORD*)((char*)mrec + offset);
4124 	while (!res && (a->type != AT_END)
4125 			&& (offset < le32_to_cpu(mrec->bytes_in_use))) {
4126 		if (a->non_resident) {
4127 			keeprl = FALSE;
4128 			rl = ntfs_mapping_pairs_decompress(vol, a,
4129 						(runlist_element*)NULL);
4130 			if (rl) {
4131 				/* rebase the old runlist */
4132 				for (prl=rl; prl->length; prl++)
4133 					if (prl->lcn >= 0) {
4134 						prl->lcn += expand->cluster_increment;
4135 						if ((a->type != AT_DATA)
4136 						    && set_bitmap(expand,prl))
4137 							res = -1;
4138 					}
4139 				/* relocated unnamed data (not $BadClus) */
4140 				if ((a->type == AT_DATA)
4141 				    && !a->name_length
4142 				    && (inum != FILE_BadClus)) {
4143 					old_rl = rl;
4144 					rl = new_rl;
4145 					keeprl = TRUE;
4146 					rl[0].vcn = 0;
4147 					rl[0].lcn = lcn;
4148 					rl[0].length = lth;
4149 					rl[1].vcn = lth;
4150 					rl[1].lcn = LCN_ENOENT;
4151 					rl[1].length = 0;
4152 					if (set_bitmap(expand,rl))
4153 						res = -1;
4154 					a->data_size = cpu_to_sle64(data_size);
4155 					a->initialized_size = a->data_size;
4156 					a->allocated_size
4157 						= cpu_to_sle64(allocated_size);
4158 					a->highest_vcn = cpu_to_sle64(lth - 1);
4159 				}
4160 				/* expand the named data for $BadClus */
4161 				if ((a->type == AT_DATA)
4162 				    && a->name_length
4163 				    && (inum == FILE_BadClus)) {
4164 					old_rl = rl;
4165 					keeprl = TRUE;
4166 					prl = rl;
4167 					if (prl->length) {
4168 						while (prl[1].length)
4169 							prl++;
4170 						prl->length = lth - prl->vcn;
4171 						prl[1].vcn = lth;
4172 					} else
4173 						prl->vcn = lth;
4174 					a->data_size = cpu_to_sle64(data_size);
4175 					/* do not change the initialized size */
4176 					a->allocated_size
4177 						= cpu_to_sle64(allocated_size);
4178 					a->highest_vcn = cpu_to_sle64(lth - 1);
4179 				}
4180 				if (!res && update_runlist(expand,inum,a,rl))
4181 					res = -1;
4182 				if (!keeprl)
4183 					free(rl);
4184 			} else {
4185 				err_printf("Could not get the data runlist of inode %lld\n",
4186 						(long long)inum);
4187 				res = -1;
4188 			}
4189 		}
4190 		offset += le32_to_cpu(a->length);
4191 		a = (ATTR_RECORD*)((char*)mrec + offset);
4192 	}
4193 	if (res && old_rl) {
4194 		free(old_rl);
4195 		old_rl = (runlist_element*)NULL;
4196 	}
4197 	return (old_rl);
4198 }
4199 
4200 /*
4201  *		Rebase all runlists in an MFT record
4202  *
4203  *	Read from the old $MFT, rebase the runlists,
4204  *	and write to the new $MFT
4205  */
4206 
rebase_inode(expand_t * expand,const runlist_element * prl,s64 inum,s64 jnum)4207 static int rebase_inode(expand_t *expand, const runlist_element *prl,
4208 		s64 inum, s64 jnum)
4209 {
4210 	MFT_RECORD *mrec;
4211 	runlist_element *rl;
4212 	ntfs_volume *vol;
4213 	s64 pos;
4214 	int res;
4215 
4216 	res = 0;
4217 	vol = expand->vol;
4218 	mrec = expand->mrec;
4219 	if (expand->mft_bitmap[inum >> 3] & (1 << (inum & 7))) {
4220 		pos = (prl->lcn << vol->cluster_size_bits)
4221 			+ ((inum - jnum) << vol->mft_record_size_bits);
4222 		if ((ntfs_mst_pread(vol->dev, pos, 1,
4223 					vol->mft_record_size, mrec) == 1)
4224 		    && (mrec->flags & MFT_RECORD_IN_USE)) {
4225 			switch (inum) {
4226 			case FILE_Bitmap :
4227 			case FILE_Boot :
4228 			case FILE_BadClus :
4229 				rl = rebase_runlists_meta(expand, inum);
4230 				if (rl)
4231 					free(rl);
4232 				else
4233 					res = -1;
4234 				break;
4235 			default :
4236 			   	res = rebase_runlists(expand, inum);
4237 				break;
4238 			}
4239 		} else {
4240 			err_printf("Could not read the $MFT entry %lld\n",
4241 					(long long)inum);
4242 			res = -1;
4243 		}
4244 	} else {
4245 			/*
4246 			 * Replace unused records (possibly uninitialized)
4247 			 * by minimal valid records, not marked in use
4248 			 */
4249 		res = minimal_record(expand,mrec);
4250 	}
4251 	if (!res) {
4252 		pos = (expand->mft_lcn << vol->cluster_size_bits)
4253 			+ (inum << vol->mft_record_size_bits);
4254 		if (opt.verbose)
4255 			ntfs_log_verbose("Rebasing inode %lld cluster 0x%llx\n",
4256 				(long long)inum,
4257 				(long long)(pos >> vol->cluster_size_bits));
4258 		if (!opt.ro_flag
4259 		    && (ntfs_mst_pwrite(vol->dev, pos, 1,
4260 				vol->mft_record_size, mrec) != 1)) {
4261 			err_printf("Could not write the $MFT entry %lld\n",
4262 					(long long)inum);
4263 			res = -1;
4264 		}
4265 	}
4266 	return (res);
4267 }
4268 
4269 /*
4270  *		Rebase all runlists
4271  *
4272  *	First get the $MFT and define its location in the expanded space,
4273  *	then rebase the other inodes and write them to the new $MFT
4274  */
4275 
rebase_all_inodes(expand_t * expand)4276 static int rebase_all_inodes(expand_t *expand)
4277 {
4278 	ntfs_volume *vol;
4279 	MFT_RECORD *mrec;
4280 	s64 inum;
4281 	s64 jnum;
4282 	s64 inodecnt;
4283 	s64 pos;
4284 	s64 got;
4285 	int res;
4286 	runlist_element *mft_rl;
4287 	runlist_element *prl;
4288 
4289 	res = 0;
4290 	mft_rl = (runlist_element*)NULL;
4291 	vol = expand->vol;
4292 	mrec = expand->mrec;
4293 	inum = 0;
4294 	pos = (vol->mft_lcn + expand->cluster_increment)
4295 				<< vol->cluster_size_bits;
4296 	got = ntfs_mst_pread(vol->dev, pos, 1,
4297 			vol->mft_record_size, mrec);
4298 	if ((got == 1) && (mrec->flags & MFT_RECORD_IN_USE)) {
4299 		pos = expand->mft_lcn << vol->cluster_size_bits;
4300 		if (opt.verbose)
4301 			ntfs_log_verbose("Rebasing inode %lld cluster 0x%llx\n",
4302 				(long long)inum,
4303 				(long long)(pos >> vol->cluster_size_bits));
4304 		mft_rl = rebase_runlists_meta(expand, FILE_MFT);
4305 		if (!mft_rl
4306 		    || (!opt.ro_flag
4307 			&& (ntfs_mst_pwrite(vol->dev, pos, 1,
4308 				vol->mft_record_size, mrec) != 1)))
4309 			res = -1;
4310 		else {
4311 			for (prl=mft_rl; prl->length; prl++) { }
4312 			inodecnt = (prl->vcn << vol->cluster_size_bits)
4313 				>> vol->mft_record_size_bits;
4314 			progress_init(expand->progress, 0, inodecnt,
4315 				(opt.show_progress ? NTFS_PROGBAR : 0));
4316 			prl = mft_rl;
4317 			jnum = 0;
4318 			do {
4319 				inum++;
4320 				while (prl->length
4321 				    && ((inum << vol->mft_record_size_bits)
4322 					>= ((prl->vcn + prl->length)
4323 						<< vol->cluster_size_bits))) {
4324 					prl++;
4325 					jnum = inum;
4326 				}
4327 				progress_update(expand->progress, inum);
4328 				if (prl->length) {
4329 					res = rebase_inode(expand,
4330 						prl,inum,jnum);
4331 				}
4332 			} while (!res && prl->length);
4333 			free(mft_rl);
4334 		}
4335 	} else {
4336 		err_printf("Could not read the old $MFT\n");
4337 		res = -1;
4338 	}
4339 	return (res);
4340 }
4341 
4342 
4343 
4344 /*
4345  *		Get the old volume parameters from the backup bootsector
4346  *
4347  */
4348 
get_volume_data(expand_t * expand,struct ntfs_device * dev,s32 sector_size)4349 static ntfs_volume *get_volume_data(expand_t *expand, struct ntfs_device *dev,
4350 			s32 sector_size)
4351 {
4352 	s64 br;
4353 	ntfs_volume *vol;
4354 	le16 sector_size_le;
4355 	NTFS_BOOT_SECTOR *bs;
4356 	BOOL ok;
4357 
4358 	ok = FALSE;
4359 	vol = (ntfs_volume*)ntfs_malloc(sizeof(ntfs_volume));
4360 	expand->bootsector = (char*)ntfs_malloc(sector_size);
4361 	if (vol && expand->bootsector) {
4362 		expand->vol = vol;
4363 		vol->dev = dev;
4364 		br = ntfs_pread(dev, expand->new_sectors*sector_size,
4365 				 sector_size, expand->bootsector);
4366 		if (br != sector_size) {
4367 			if (br != -1)
4368 				errno = EINVAL;
4369 			if (!br)
4370 				err_printf("Failed to read the backup bootsector (size=0)\n");
4371 			else
4372 				err_printf("Error reading the backup bootsector");
4373 		} else {
4374 			bs = (NTFS_BOOT_SECTOR*)expand->bootsector;
4375 		/* alignment problem on Sparc, even doing memcpy() */
4376 			sector_size_le = cpu_to_le16(sector_size);
4377 			if (!memcmp(&sector_size_le,
4378 						&bs->bpb.bytes_per_sector,2)
4379 			    && ntfs_boot_sector_is_ntfs(bs)
4380 			    && !ntfs_boot_sector_parse(vol, bs)) {
4381 				expand->original_sectors
4382 				    = sle64_to_cpu(bs->number_of_sectors);
4383 				expand->mrec = (MFT_RECORD*)
4384 					ntfs_malloc(vol->mft_record_size);
4385 				if (expand->mrec
4386 				    && can_expand(expand,vol)) {
4387 					ntfs_log_verbose("Resizing is possible\n");
4388 					ok = TRUE;
4389 				}
4390 			} else
4391 				err_printf("Could not get the old volume parameters "
4392 					"from the backup bootsector\n");
4393 		}
4394 		if (!ok) {
4395 			free(vol);
4396 			free(expand->bootsector);
4397 		}
4398 	}
4399 	return (ok ? vol : (ntfs_volume*)NULL);
4400 }
4401 
really_expand(expand_t * expand)4402 static int really_expand(expand_t *expand)
4403 {
4404 	ntfs_volume *vol;
4405 	struct ntfs_device *dev;
4406 	int res;
4407 
4408 	res = -1;
4409 
4410 	expand->bitmap = (u8*)ntfs_calloc(expand->bitmap_allocated);
4411 	if (expand->bitmap
4412 	    && get_mft_bitmap(expand)) {
4413 		printf("\n*** WARNING ***\n\n");
4414 		printf("Expanding a volume is an experimental new feature\n");
4415 		if (!opt.ro_flag)
4416 			printf("A first check with option -n is recommended\n");
4417 		printf("\nShould something go wrong during the actual"
4418 			 " resizing (power outage, etc.),\n");
4419 		printf("just restart the procedure, but DO NOT TRY to repair"
4420 			" with chkdsk or similar,\n");
4421 		printf("until the resizing is over,"
4422 			" you would LOSE YOUR DATA !\n");
4423 		printf("\nYou have been warned !\n\n");
4424 		if (!opt.ro_flag && (opt.force-- <= 0))
4425 			proceed_question();
4426 		if (!rebase_all_inodes(expand)
4427 		    && !write_bitmap(expand)
4428 		    && !copy_mftmirr(expand)
4429 		    && !copy_boot(expand)) {
4430 			free(expand->vol);
4431 			expand->vol = (ntfs_volume*)NULL;
4432 			free(expand->mft_bitmap);
4433 			expand->mft_bitmap = (u8*)NULL;
4434 			if (!opt.ro_flag) {
4435 				/* the volume must be dirty, do not check */
4436 				opt.force++;
4437 				vol = mount_volume();
4438 				if (vol) {
4439 					dev = vol->dev;
4440 					ntfs_log_verbose("Remounting the updated volume\n");
4441 					expand->vol = vol;
4442 					ntfs_log_verbose("Delayed runlist updatings\n");
4443 					delayed_expand(vol, expand->delayed_runlists,
4444 						expand->progress);
4445 					expand->delayed_runlists
4446 						= (struct DELAYED*)NULL;
4447 					expand_index_sizes(expand);
4448 		/* rewriting the backup bootsector, no return ticket now ! */
4449 					res = write_bootsector(expand);
4450 					if (dev->d_ops->sync(dev) == -1) {
4451 						printf("Could not sync\n");
4452 						res = -1;
4453 					}
4454 					ntfs_umount(vol,0);
4455 					if (!res)
4456 						printf("\nResizing completed successfully\n");
4457 				}
4458 			} else {
4459 				ntfs_log_verbose("Delayed runlist updatings\n");
4460 				delayed_expand(expand->vol,
4461 						expand->delayed_runlists,
4462 						expand->progress);
4463 				expand->delayed_runlists
4464 						= (struct DELAYED*)NULL;
4465 				printf("\nAll checks have been completed successfully\n");
4466 				printf("Cannot check further in no-action mode\n");
4467 			}
4468 			free(expand->bootsector);
4469 			free(expand->mrec);
4470 		}
4471 		free(expand->bitmap);
4472 	} else {
4473 		err_printf("Failed to allocate memory\n");
4474 	}
4475 	return (res);
4476 }
4477 
4478 /*
4479  *		Expand a volume to beginning of partition
4480  *
4481  *	We rely on the backup bootsector to determine the original
4482  *	volume size and metadata.
4483  */
4484 
expand_to_beginning(void)4485 static int expand_to_beginning(void)
4486 {
4487 	expand_t expand;
4488 	struct progress_bar progress;
4489 	int ret;
4490 	ntfs_volume *vol;
4491 	struct ntfs_device *dev;
4492 	int sector_size;
4493 	s64 new_sectors;
4494 
4495 	ret = -1;
4496 	dev = ntfs_device_alloc(opt.volume, 0, &ntfs_device_default_io_ops,
4497 			NULL);
4498 	if (dev) {
4499 	        if (!(*dev->d_ops->open)(dev,
4500 				(opt.ro_flag ? O_RDONLY : O_RDWR))) {
4501 			sector_size = ntfs_device_sector_size_get(dev);
4502 			if (sector_size <= 0) {
4503 				sector_size = 512;
4504 				new_sectors = ntfs_device_size_get(dev,
4505 								sector_size);
4506 				if (!new_sectors) {
4507 					sector_size = 4096;
4508 					new_sectors = ntfs_device_size_get(dev,
4509 								sector_size);
4510 				}
4511 			} else
4512 				new_sectors = ntfs_device_size_get(dev,
4513 								sector_size);
4514 			if (new_sectors) {
4515 				new_sectors--; /* last sector not counted */
4516 				expand.new_sectors = new_sectors;
4517 				expand.progress = &progress;
4518 				expand.delayed_runlists = (struct DELAYED*)NULL;
4519 				vol = get_volume_data(&expand,dev,sector_size);
4520 				if (vol) {
4521 					expand.vol = vol;
4522 					ret = really_expand(&expand);
4523 				}
4524 			}
4525 			(*dev->d_ops->close)(dev);
4526 		} else {
4527 			err_exit("Couldn't open volume '%s'!\n", opt.volume);
4528 		}
4529 		ntfs_device_free(dev);
4530 	}
4531 	return (ret);
4532 }
4533 
4534 
main(int argc,char ** argv)4535 int main(int argc, char **argv)
4536 {
4537 	ntfsck_t fsck;
4538 	ntfs_resize_t resize;
4539 	s64 new_size = 0;	/* in clusters; 0 = --info w/o --size */
4540 	s64 device_size;        /* in bytes */
4541 	ntfs_volume *vol = NULL;
4542 	int res;
4543 
4544 	ntfs_log_set_handler(ntfs_log_handler_outerr);
4545 
4546 	printf("%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
4547 
4548 	res = parse_options(argc, argv);
4549 	if (res >= 0)
4550 		return (res);
4551 
4552 	utils_set_locale();
4553 
4554 		/*
4555 		 * If we're just checking the device, we'll do it first,
4556 		 * and exit out, no matter what we find.
4557 		 */
4558 	if (opt.check) {
4559 		vol = check_volume();
4560 #if CLEAN_EXIT
4561 		if (vol)
4562 			ntfs_umount(vol,0);
4563 #endif
4564 		exit(0);
4565 	} else {
4566 		if (opt.expand) {
4567 			/*
4568 			 * If we are to expand to beginning of partition, do
4569 			 * not try to mount : when merging two partitions,
4570 			 * the beginning of the partition would contain an
4571 			 * old filesystem which is not the one to expand.
4572 			 */
4573 			if (expand_to_beginning() && !opt.info)
4574 				exit(1);
4575 			return (0);
4576 		}
4577 	}
4578 
4579 	if (!(vol = mount_volume()))
4580 		err_exit("Couldn't open volume '%s'!\n", opt.volume);
4581 
4582 	device_size = ntfs_device_size_get(vol->dev, vol->sector_size);
4583 	device_size *= vol->sector_size;
4584 	if (device_size <= 0)
4585 		err_exit("Couldn't get device size (%lld)!\n",
4586 			(long long)device_size);
4587 
4588 	if (!opt.infombonly)
4589 		print_vol_size("Current device size", device_size);
4590 
4591 	if (device_size < vol->nr_clusters * vol->cluster_size)
4592 		err_exit("Current NTFS volume size is bigger than the device "
4593 			 "size!\nCorrupt partition table or incorrect device "
4594 			 "partitioning?\n");
4595 
4596 	if (!opt.bytes && !opt.info && !opt.infombonly) {
4597 		opt.bytes = device_size;
4598 		opt.reliable_size = 1;
4599 	}
4600 
4601 	/* Backup boot sector at the end of device isn't counted in NTFS
4602 	   volume size thus we have to reserve space for it. */
4603 	if (opt.bytes > vol->sector_size)
4604 		new_size = (opt.bytes - vol->sector_size) / vol->cluster_size;
4605 	else
4606 		new_size = 0;
4607 
4608 	if (!opt.info && !opt.infombonly) {
4609 		print_vol_size("New volume size    ", vol_size(vol, new_size));
4610 		if (device_size < opt.bytes)
4611 			err_exit("New size can't be bigger than the device size"
4612 				 ".\nIf you want to enlarge NTFS then first "
4613 				 "enlarge the device size by e.g. fdisk.\n");
4614 	}
4615 
4616 	if (!opt.info && !opt.infombonly && (new_size == vol->nr_clusters ||
4617 			  (opt.bytes == device_size &&
4618 			   new_size == vol->nr_clusters - 1))) {
4619 		printf("Nothing to do: NTFS volume size is already OK.\n");
4620 		exit(0);
4621 	}
4622 
4623 	memset(&resize, 0, sizeof(resize));
4624 	resize.vol = vol;
4625 	resize.new_volume_size = new_size;
4626 	/* This is also true if --info was used w/o --size (new_size = 0) */
4627 	if (new_size < vol->nr_clusters)
4628 		resize.shrink = 1;
4629 	if (opt.show_progress)
4630 		resize.progress.flags |= NTFS_PROGBAR;
4631 	/*
4632 	 * Checking and __reporting__ of bad sectors must be done before cluster
4633 	 * allocation check because chkdsk doesn't fix $Bitmap's w/ bad sectors
4634 	 * thus users would (were) quite confused why chkdsk doesn't work.
4635 	 */
4636 	resize.badclusters = check_bad_sectors(vol);
4637 
4638 	NVolSetNoFixupWarn(vol);
4639 	check_cluster_allocation(vol, &fsck);
4640 
4641 	print_disk_usage(vol, fsck.inuse);
4642 
4643 	resize.inuse = fsck.inuse;
4644 	resize.lcn_bitmap = fsck.lcn_bitmap;
4645 	resize.mirr_from = MIRR_OLD;
4646 
4647 	set_resize_constraints(&resize);
4648 	set_disk_usage_constraint(&resize);
4649 	check_resize_constraints(&resize);
4650 
4651 	if (opt.info || opt.infombonly) {
4652 		advise_on_resize(&resize);
4653 		exit(0);
4654 	}
4655 
4656 	if (opt.force-- <= 0 && !opt.ro_flag) {
4657 		printf("%s", resize_warning_msg);
4658 		proceed_question();
4659 	}
4660 
4661 	/* FIXME: performance - relocate logfile here if it's needed */
4662 	prepare_volume_fixup(vol);
4663 
4664 	if (resize.relocations)
4665 		relocate_inodes(&resize);
4666 
4667 	truncate_badclust_file(&resize);
4668 	truncate_bitmap_file(&resize);
4669 	delayed_updates(&resize);
4670 	update_bootsector(&resize);
4671 
4672 	/* We don't create backup boot sector because we don't know where the
4673 	   partition will be split. The scheduled chkdsk will fix it */
4674 
4675 	if (opt.ro_flag) {
4676 		printf("The read-only test run ended successfully.\n");
4677 		exit(0);
4678 	}
4679 
4680 	/* WARNING: don't modify the texts, external tools grep for them */
4681 	printf("Syncing device ...\n");
4682 	if (vol->dev->d_ops->sync(vol->dev) == -1)
4683 		perr_exit("fsync");
4684 
4685 	printf("Successfully resized NTFS on device '%s'.\n", vol->dev->d_name);
4686 	if (resize.shrink)
4687 		printf("%s", resize_important_msg);
4688 	if (resize.lcn_bitmap.bm)
4689 		free(resize.lcn_bitmap.bm);
4690 	if (vol)
4691 		ntfs_umount(vol,0);
4692 	return 0;
4693 }
4694