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  *
   9  * This utility will resize an NTFS volume without data loss.
  10  *
  11  * WARNING FOR DEVELOPERS!!! Several external tools grep for text messages
  12  * to control execution thus if you would like to change any message
  13  * then PLEASE think twice before doing so then don't modify it. Thanks!
  14  *
  15  * This program is free software; you can redistribute it and/or modify
  16  * it under the terms of the GNU General Public License as published by
  17  * the Free Software Foundation; either version 2 of the License, or
  18  * (at your option) any later version.
  19  *
  20  * This program is distributed in the hope that it will be useful,
  21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23  * GNU General Public License for more details.
  24  *
  25  * You should have received a copy of the GNU General Public License
  26  * along with this program (in the main directory of the Linux-NTFS
  27  * distribution in the file COPYING); if not, write to the Free Software
  28  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  29  */
  30 
  31 #include "config.h"
  32 
  33 #ifdef HAVE_UNISTD_H
  34 #include <unistd.h>
  35 #endif
  36 #ifdef HAVE_STDLIB_H
  37 #include <stdlib.h>
  38 #endif
  39 #ifdef HAVE_STDIO_H
  40 #include <stdio.h>
  41 #endif
  42 #ifdef HAVE_STDARG_H
  43 #include <stdarg.h>
  44 #endif
  45 #ifdef HAVE_STRING_H
  46 #include <string.h>
  47 #endif
  48 #ifdef HAVE_ERRNO_H
  49 #include <errno.h>
  50 #endif
  51 #ifdef HAVE_GETOPT_H
  52 #include <getopt.h>
  53 #endif
  54 
  55 #include "compat.h"
  56 #include "debug.h"
  57 #include "types.h"
  58 #include "support.h"
  59 #include "endians.h"
  60 #include "bootsect.h"
  61 #include "device.h"
  62 #include "attrib.h"
  63 #include "volume.h"
  64 #include "mft.h"
  65 #include "bitmap.h"
  66 #include "inode.h"
  67 #include "runlist.h"
  68 #include "utils.h"
  69 #include "version.h"
  70 
  71 static const char *EXEC_NAME = "ntfsresize";
  72 
  73 static const char *resize_warning_msg =
  74 "WARNING: Every sanity check passed and only the dangerous operations left.\n"
  75 "Make sure that important data has been backed up! Power outage or computer\n"
  76 "crash may result major data loss!\n";
  77 
  78 static const char *resize_important_msg =
  79 #ifdef __sun
  80 "When booted, Windows will check the file system and may reboot.\n"
  81 "If you are running this from inside parted, STOP reading now.\n"
  82 "Otherwise, you can go on to shrink the device with fdisk or parted.\n"
  83 #else
  84 "You can go on to shrink the device for example with Linux fdisk.\n"
  85 #endif
  86 "IMPORTANT: When recreating the partition, make sure that you\n"
  87 "  1)  create it at the same disk sector (use sector as the unit!)\n"
  88 "  2)  create it with the same partition type (usually 7, HPFS/NTFS)\n"
  89 "  3)  do not make it smaller than the new NTFS filesystem size\n"
  90 "  4)  set the bootable flag for the partition if it existed before\n"
  91 "Otherwise you won't be able to access NTFS or can't boot from the disk!\n"
  92 "If you make a mistake and don't have a partition table backup then you\n"
  93 "can recover the partition table by TestDisk or Parted's rescue mode.\n";
  94 
  95 static const char *invalid_ntfs_msg =
  96 "The device '%s' doesn't have a valid NTFS.\n"
  97 "Maybe you selected the wrong partition? Or the whole disk instead of a\n"
  98 "partition (e.g. /dev/hda, not /dev/hda1)? This error might also occur\n"
  99 "if the disk was incorrectly repartitioned (see the ntfsresize FAQ).\n";
 100 
 101 static const char *corrupt_volume_msg =
 102 "NTFS is inconsistent. Run chkdsk /f on Windows then reboot it TWICE!\n"
 103 "The usage of the /f parameter is very IMPORTANT! No modification was\n"
 104 "and will be made to NTFS by this software until it gets repaired.\n";
 105 
 106 static const char *hibernated_volume_msg =
 107 "The NTFS partition is hibernated. Windows must be resumed and turned off\n"
 108 "properly, so resizing could be done safely.\n";
 109 
 110 static const char *unclean_journal_msg =
 111 "The NTFS journal file is unclean. Please shutdown Windows properly before\n"
 112 "using this software! Note, if you have run chkdsk previously then boot\n"
 113 "Windows again which will automatically initialize the journal correctly.\n";
 114 
 115 static const char *opened_volume_msg =
 116 "This software has detected that the NTFS volume is already opened by another\n"
 117 "software thus it refuses to progress to preserve data consistency.\n";
 118 
 119 static const char *bad_sectors_warning_msg =
 120 "****************************************************************************\n"
 121 "* WARNING: The disk has bad sector. This means physical damage on the disk *\n"
 122 "* surface caused by deterioration, manufacturing faults or other reason.   *\n"
 123 "* The reliability of the disk may stay stable or degrade fast. We suggest  *\n"
 124 "* making a full backup urgently by running 'ntfsclone --rescue ...' then   *\n"
 125 "* run 'chkdsk /f /r' on Windows and rebooot it TWICE! Then you can resize  *\n"
 126 "* NTFS safely by additionally using the --bad-sectors option of ntfsresize.*\n"
 127 "****************************************************************************\n";
 128 
 129 static const char *many_bad_sectors_msg =
 130 "***************************************************************************\n"
 131 "* WARNING: The disk has many bad sectors. This means physical damage      *\n"
 132 "* on the disk surface caused by deterioration, manufacturing faults or    *\n"
 133 "* other reason. We suggest to get a replacement disk as soon as possible. *\n"
 134 "***************************************************************************\n";
 135 
 136 static struct {
 137         int verbose;
 138         int debug;
 139         int ro_flag;
 140         int force;
 141         int info;
 142         int show_progress;
 143         int badsectors;
 144         s64 bytes;
 145         char *volume;
 146 } opt;
 147 
 148 struct bitmap {
 149         s64 size;
 150         u8 *bm;
 151 };
 152 
 153 #define NTFS_PROGBAR            0x0001
 154 #define NTFS_PROGBAR_SUPPRESS   0x0002
 155 
 156 struct progress_bar {
 157         u64 start;
 158         u64 stop;
 159         int resolution;
 160         int flags;
 161         float unit;
 162 };
 163 
 164 struct llcn_t {
 165         s64 lcn;        /* last used LCN for a "special" file/attr type */
 166         s64 inode;      /* inode using it */
 167 };
 168 
 169 #define NTFSCK_PROGBAR          0x0001
 170 
 171 typedef struct {
 172         ntfs_inode *ni;              /* inode being processed */
 173         ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
 174         s64 inuse;                   /* num of clusters in use */
 175         int multi_ref;               /* num of clusters referenced many times */
 176         int outsider;                /* num of clusters outside the volume */
 177         int show_outsider;           /* controls showing the above information */
 178         int flags;
 179         struct bitmap lcn_bitmap;
 180 } ntfsck_t;
 181 
 182 typedef struct {
 183         ntfs_volume *vol;
 184         ntfs_inode *ni;              /* inode being processed */
 185         s64 new_volume_size;         /* in clusters; 0 = --info w/o --size */
 186         MFT_REF mref;                /* mft reference */
 187         MFT_RECORD *mrec;            /* mft record */
 188         ntfs_attr_search_ctx *ctx;   /* inode attribute being processed */
 189         u64 relocations;             /* num of clusters to relocate */
 190         s64 inuse;                   /* num of clusters in use */
 191         runlist mftmir_rl;           /* $MFTMirr AT_DATA's new position */
 192         s64 mftmir_old;              /* $MFTMirr AT_DATA's old LCN */
 193         int dirty_inode;             /* some inode data got relocated */
 194         int shrink;                  /* shrink = 1, enlarge = 0 */
 195         s64 badclusters;             /* num of physically dead clusters */
 196         VCN mft_highest_vcn;         /* used for relocating the $MFT */
 197         struct progress_bar progress;
 198         struct bitmap lcn_bitmap;
 199         /* Temporary statistics until all case is supported */
 200         struct llcn_t last_mft;
 201         struct llcn_t last_mftmir;
 202         struct llcn_t last_multi_mft;
 203         struct llcn_t last_sparse;
 204         struct llcn_t last_compressed;
 205         struct llcn_t last_lcn;
 206         s64 last_unsupp;             /* last unsupported cluster */
 207 } ntfs_resize_t;
 208 
 209 /* FIXME: This, lcn_bitmap and pos from find_free_cluster() will make a cluster
 210    allocation related structure, attached to ntfs_resize_t */
 211 static s64 max_free_cluster_range = 0;
 212 
 213 #define NTFS_MBYTE (1000 * 1000)
 214 
 215 /* WARNING: don't modify the text, external tools grep for it */
 216 #define ERR_PREFIX   "ERROR"
 217 #define PERR_PREFIX  ERR_PREFIX "(%d): "
 218 #define NERR_PREFIX  ERR_PREFIX ": "
 219 
 220 #define DIRTY_NONE              (0)
 221 #define DIRTY_INODE             (1)
 222 #define DIRTY_ATTRIB            (2)
 223 
 224 #define NTFS_MAX_CLUSTER_SIZE   (65536)
 225 
 226 static s64 rounded_up_division(s64 numer, s64 denom)
 227 {
 228         return (numer + (denom - 1)) / denom;
 229 }
 230 
 231 /**
 232  * perr_printf
 233  *
 234  * Print an error message.
 235  */
 236 __attribute__((format(printf, 1, 2)))
 237 static void perr_printf(const char *fmt, ...)
 238 {
 239         va_list ap;
 240         int eo = errno;
 241 
 242         fprintf(stdout, PERR_PREFIX, eo);
 243         va_start(ap, fmt);
 244         vfprintf(stdout, fmt, ap);
 245         va_end(ap);
 246         fprintf(stdout, ": %s\n", strerror(eo));
 247         fflush(stdout);
 248         fflush(stderr);
 249 }
 250 
 251 __attribute__((format(printf, 1, 2)))
 252 static void err_printf(const char *fmt, ...)
 253 {
 254         va_list ap;
 255 
 256         fprintf(stdout, NERR_PREFIX);
 257         va_start(ap, fmt);
 258         vfprintf(stdout, fmt, ap);
 259         va_end(ap);
 260         fflush(stdout);
 261         fflush(stderr);
 262 }
 263 
 264 /**
 265  * err_exit
 266  *
 267  * Print and error message and exit the program.
 268  */
 269 __attribute__((noreturn))
 270 __attribute__((format(printf, 1, 2)))
 271 static int err_exit(const char *fmt, ...)
 272 {
 273         va_list ap;
 274 
 275         fprintf(stdout, NERR_PREFIX);
 276         va_start(ap, fmt);
 277         vfprintf(stdout, fmt, ap);
 278         va_end(ap);
 279         fflush(stdout);
 280         fflush(stderr);
 281         exit(1);
 282 }
 283 
 284 /**
 285  * perr_exit
 286  *
 287  * Print and error message and exit the program
 288  */
 289 __attribute__((noreturn))
 290 __attribute__((format(printf, 1, 2)))
 291 static int perr_exit(const char *fmt, ...)
 292 {
 293         va_list ap;
 294         int eo = errno;
 295 
 296         fprintf(stdout, PERR_PREFIX, eo);
 297         va_start(ap, fmt);
 298         vfprintf(stdout, fmt, ap);
 299         va_end(ap);
 300         printf(": %s\n", strerror(eo));
 301         fflush(stdout);
 302         fflush(stderr);
 303         exit(1);
 304 }
 305 
 306 /**
 307  * usage - Print a list of the parameters to the program
 308  *
 309  * Print a list of the parameters and options for the program.
 310  *
 311  * Return:  none
 312  */
 313 __attribute__((noreturn))
 314 static void usage(void)
 315 {
 316 
 317         printf("\nUsage: %s [OPTIONS] DEVICE\n"
 318                 "    Resize an NTFS volume non-destructively, safely move any data if needed.\n"
 319                 "\n"
 320                 "    -i, --info             Estimate the smallest shrunken size possible\n"
 321                 "    -s, --size SIZE        Resize volume to SIZE[k|M|G] bytes\n"
 322                 "\n"
 323                 "    -n, --no-action        Do not write to disk\n"
 324                 "    -b, --bad-sectors      Support disks having bad sectors\n"
 325                 "    -f, --force            Force to progress\n"
 326                 "    -P, --no-progress-bar  Don't show progress bar\n"
 327                 "    -v, --verbose          More output\n"
 328                 "    -V, --version          Display version information\n"
 329                 "    -h, --help             Display this help\n"
 330 #ifdef DEBUG
 331                 "    -d, --debug            Show debug information\n"
 332 #endif
 333                 "\n"
 334                 "    The options -i and -s are mutually exclusive. If both options are\n"
 335                 "    omitted then the NTFS volume will be enlarged to the DEVICE size.\n"
 336                 "\n", EXEC_NAME);
 337         printf("%s%s", ntfs_bugs, ntfs_home);
 338         printf("Ntfsresize FAQ: http://linux-ntfs.sourceforge.net/info/ntfsresize.html\n");
 339         exit(1);
 340 }
 341 
 342 /**
 343  * proceed_question
 344  *
 345  * Force the user to confirm an action before performing it.
 346  * Copy-paste from e2fsprogs
 347  */
 348 static void proceed_question(void)
 349 {
 350         char buf[256];
 351         const char *short_yes = "yY";
 352 
 353         fflush(stdout);
 354         fflush(stderr);
 355         printf("Are you sure you want to proceed (y/[n])? ");
 356         buf[0] = 0;
 357         fgets(buf, sizeof(buf), stdin);
 358         if (!strchr(short_yes, buf[0])) {
 359                 printf("OK quitting. NO CHANGES have been made to your "
 360                                 "NTFS volume.\n");
 361                 exit(1);
 362         }
 363 }
 364 
 365 /**
 366  * version - Print version information about the program
 367  *
 368  * Print a copyright statement and a brief description of the program.
 369  *
 370  * Return:  none
 371  */
 372 static void version(void)
 373 {
 374         printf("\nResize an NTFS Volume, without data loss.\n\n");
 375         printf("Copyright (c) 2002-2006  Szabolcs Szakacsits\n");
 376         printf("Copyright (c) 2002-2005  Anton Altaparmakov\n");
 377         printf("Copyright (c) 2002-2003  Richard Russon\n");
 378         printf("Copyright (c) 2007       Yura Pakhuchiy\n");
 379         printf("\n%s\n%s%s", ntfs_gpl, ntfs_bugs, ntfs_home);
 380 }
 381 
 382 /**
 383  * get_new_volume_size
 384  *
 385  * Convert a user-supplied string into a size.  Without any suffix the number
 386  * will be assumed to be in bytes.  If the number has a suffix of k, M or G it
 387  * will be scaled up by 1000, 1000000, or 1000000000.
 388  */
 389 static s64 get_new_volume_size(char *s)
 390 {
 391         s64 size;
 392         char *suffix;
 393         int prefix_kind = 1000;
 394 
 395         size = strtoll(s, &suffix, 10);
 396         if (size <= 0 || errno == ERANGE)
 397                 err_exit("Illegal new volume size\n");
 398 
 399         if (!*suffix)
 400                 return size;
 401 
 402         if (strlen(suffix) == 2 && suffix[1] == 'i')
 403                 prefix_kind = 1024;
 404         else if (strlen(suffix) > 1)
 405                 usage();
 406 
 407         /* We follow the SI prefixes:
 408            http://physics.nist.gov/cuu/Units/prefixes.html
 409            http://physics.nist.gov/cuu/Units/binary.html
 410            Disk partitioning tools use prefixes as,
 411                                k        M          G
 412            fdisk 2.11x-      2^10     2^20      10^3*2^20
 413            fdisk 2.11y+     10^3     10^6       10^9
 414            cfdisk           10^3     10^6       10^9
 415            sfdisk            2^10     2^20
 416            parted            2^10     2^20  (may change)
 417            fdisk (DOS)       2^10     2^20
 418         */
 419         /* FIXME: check for overflow */
 420         switch (*suffix) {
 421         case 'G':
 422                 size *= prefix_kind;
 423         case 'M':
 424                 size *= prefix_kind;
 425         case 'k':
 426                 size *= prefix_kind;
 427                 break;
 428         default:
 429                 usage();
 430         }
 431 
 432         return size;
 433 }
 434 
 435 /**
 436  * parse_options - Read and validate the programs command line
 437  *
 438  * Read the command line, verify the syntax and parse the options.
 439  * This function is very long, but quite simple.
 440  *
 441  * Return:  1 Success
 442  *          0 Error, one or more problems
 443  */
 444 static int parse_options(int argc, char **argv)
 445 {
 446         static const char *sopt = "-bdfhinPs:vV";
 447         static const struct option lopt[] = {
 448                 { "bad-sectors",no_argument,            NULL, 'b' },
 449 #ifdef DEBUG
 450                 { "debug",      no_argument,            NULL, 'd' },
 451 #endif
 452                 { "force",      no_argument,            NULL, 'f' },
 453                 { "help",       no_argument,            NULL, 'h' },
 454                 { "info",       no_argument,            NULL, 'i' },
 455                 { "no-action",  no_argument,            NULL, 'n' },
 456                 { "no-progress-bar", no_argument,       NULL, 'P' },
 457                 { "size",       required_argument,      NULL, 's' },
 458                 { "verbose",    no_argument,            NULL, 'v' },
 459                 { "version",    no_argument,            NULL, 'V' },
 460                 { NULL, 0, NULL, 0 }
 461         };
 462 
 463         int c;
 464         int err  = 0;
 465         int ver  = 0;
 466         int help = 0;
 467 
 468         memset(&opt, 0, sizeof(opt));
 469         opt.show_progress = 1;
 470 
 471         while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
 472                 switch (c) {
 473                 case 1: /* A non-option argument */
 474                         if (!err && !opt.volume)
 475                                 opt.volume = argv[optind-1];
 476                         else
 477                                 err++;
 478                         break;
 479                 case 'b':
 480                         opt.badsectors++;
 481                         break;
 482                 case 'd':
 483                         opt.debug++;
 484                         break;
 485                 case 'f':
 486                         opt.force++;
 487                         break;
 488                 case 'h':
 489                 case '?':
 490                         help++;
 491                         break;
 492                 case 'i':
 493                         opt.info++;
 494                         break;
 495                 case 'n':
 496                         opt.ro_flag = NTFS_MNT_RDONLY;
 497                         break;
 498                 case 'P':
 499                         opt.show_progress = 0;
 500                         break;
 501                 case 's':
 502                         if (!err && (opt.bytes == 0))
 503                                 opt.bytes = get_new_volume_size(optarg);
 504                         else
 505                                 err++;
 506                         break;
 507                 case 'v':
 508                         opt.verbose++;
 509                         ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
 510                         break;
 511                 case 'V':
 512                         ver++;
 513                         break;
 514                 default:
 515                         if (optopt == 's') {
 516                                 printf("Option '%s' requires an argument.\n", argv[optind-1]);
 517                         } else {
 518                                 printf("Unknown option '%s'.\n", argv[optind-1]);
 519                         }
 520                         err++;
 521                         break;
 522                 }
 523         }
 524 
 525         if (!help && !ver) {
 526                 if (opt.volume == NULL) {
 527                         if (argc > 1)
 528                                 printf("You must specify exactly one device.\n");
 529                         err++;
 530                 }
 531                 if (opt.info) {
 532                         opt.ro_flag = NTFS_MNT_RDONLY;
 533                         if (opt.bytes) {
 534                                 printf(NERR_PREFIX "Options --info and --size "
 535                                         "can't be used together.\n");
 536                                 usage();
 537                         }
 538                 }
 539         }
 540 
 541         /* Redirect stderr to stdout, note fflush()es are essential! */
 542         fflush(stdout);
 543         fflush(stderr);
 544         if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
 545                 perr_exit("Failed to redirect stderr to stdout");
 546         fflush(stdout);
 547         fflush(stderr);
 548 
 549 #ifdef DEBUG
 550         if (!opt.debug)
 551                 if (!freopen("/dev/null", "w", stderr))
 552                         perr_exit("Failed to redirect stderr to /dev/null");
 553 #endif
 554 
 555         if (ver)
 556                 version();
 557         if (help || err)
 558                 usage();
 559 
 560         return (!err && !help && !ver);
 561 }
 562 
 563 static void print_advise(ntfs_volume *vol, s64 supp_lcn)
 564 {
 565         s64 old_b, new_b, freed_b, old_mb, new_mb, freed_mb;
 566 
 567         old_b = vol->nr_clusters * vol->cluster_size;
 568         old_mb = rounded_up_division(old_b, NTFS_MBYTE);
 569 
 570         /* Take the next supported cluster (free or relocatable)
 571            plus reserve a cluster for the backup boot sector */
 572         supp_lcn += 2;
 573 
 574         if (supp_lcn > vol->nr_clusters) {
 575                 err_printf("Very rare fragmentation type detected. "
 576                            "Sorry, it's not supported yet.\n"
 577                            "Try to defragment your NTFS, perhaps it helps.\n");
 578                 exit(1);
 579         }
 580 
 581         new_b = supp_lcn * vol->cluster_size;
 582         new_mb = rounded_up_division(new_b, NTFS_MBYTE);
 583         freed_b = (vol->nr_clusters - supp_lcn + 1) * vol->cluster_size;
 584         freed_mb = freed_b / NTFS_MBYTE;
 585 
 586         /* WARNING: don't modify the text, external tools grep for it */
 587         printf("You might resize at %lld bytes ", (long long)new_b);
 588         if ((new_mb * NTFS_MBYTE) < old_b)
 589                 printf("or %lld MB ", (long long)new_mb);
 590 
 591         printf("(freeing ");
 592         if (freed_mb && (old_mb - new_mb))
 593             printf("%lld MB", (long long)(old_mb - new_mb));
 594         else
 595             printf("%lld bytes", (long long)freed_b);
 596         printf(").\n");
 597 
 598         printf("Please make a test run using both the -n and -s options "
 599                "before real resizing!\n");
 600 }
 601 
 602 static void rl_set(runlist *rl, VCN vcn, LCN lcn, s64 len)
 603 {
 604         rl->vcn = vcn;
 605         rl->lcn = lcn;
 606         rl->length = len;
 607 }
 608 
 609 static int rl_items(runlist *rl)
 610 {
 611         int i = 0;
 612 
 613         while (rl[i++].length)
 614                 ;
 615 
 616         return i;
 617 }
 618 
 619 static void dump_run(runlist_element *r)
 620 {
 621         ntfs_log_verbose(" %8lld  %8lld (0x%08llx)  %lld\n", (long long)r->vcn,
 622                          (long long)r->lcn, (long long)r->lcn,
 623                          (long long)r->length);
 624 }
 625 
 626 static void dump_runlist(runlist *rl)
 627 {
 628         while (rl->length)
 629                 dump_run(rl++);
 630 }
 631 
 632 /**
 633  * nr_clusters_to_bitmap_byte_size
 634  *
 635  * Take the number of clusters in the volume and calculate the size of $Bitmap.
 636  * The size must be always a multiple of 8 bytes.
 637  */
 638 static s64 nr_clusters_to_bitmap_byte_size(s64 nr_clusters)
 639 {
 640         s64 bm_bsize;
 641 
 642         bm_bsize = rounded_up_division(nr_clusters, 8);
 643         bm_bsize = (bm_bsize + 7) & ~7;
 644 
 645         return bm_bsize;
 646 }
 647 
 648 static void collect_resize_constraints(ntfs_resize_t *resize, runlist *rl)
 649 {
 650         s64 inode, last_lcn;
 651         ATTR_FLAGS flags;
 652         ATTR_TYPES atype;
 653         struct llcn_t *llcn = NULL;
 654         int ret, supported = 0;
 655 
 656         last_lcn = rl->lcn + (rl->length - 1);
 657 
 658         inode = resize->ni->mft_no;
 659         flags = resize->ctx->attr->flags;
 660         atype = resize->ctx->attr->type;
 661 
 662         if ((ret = ntfs_inode_badclus_bad(inode, resize->ctx->attr)) != 0) {
 663                 if (ret == -1)
 664                         perr_exit("Bad sector list check failed");
 665                 return;
 666         }
 667 
 668         if (inode == FILE_Bitmap) {
 669                 llcn = &resize->last_lcn;
 670                 if (atype == AT_DATA && NInoAttrList(resize->ni))
 671                     err_exit("Highly fragmented $Bitmap isn't supported yet.");
 672 
 673                 supported = 1;
 674 
 675         } else if (inode == FILE_MFT) {
 676                 llcn = &resize->last_mft;
 677                 /*
 678                  *  First run of $MFT AT_DATA isn't supported yet.
 679                  */
 680                 if (atype != AT_DATA || rl->vcn)
 681                         supported = 1;
 682 
 683         } else if (NInoAttrList(resize->ni)) {
 684                 llcn = &resize->last_multi_mft;
 685 
 686                 if (inode != FILE_MFTMirr)
 687                         supported = 1;
 688 
 689         } else if (flags & ATTR_IS_SPARSE) {
 690                 llcn = &resize->last_sparse;
 691                 supported = 1;
 692 
 693         } else if (flags & ATTR_IS_COMPRESSED) {
 694                 llcn = &resize->last_compressed;
 695                 supported = 1;
 696 
 697         } else if (inode == FILE_MFTMirr) {
 698                 llcn = &resize->last_mftmir;
 699                 supported = 1;
 700 
 701                 /* Fragmented $MFTMirr DATA attribute isn't supported yet */
 702                 if (atype == AT_DATA)
 703                         if (rl[1].length != 0 || rl->vcn)
 704                                 supported = 0;
 705         } else {
 706                 llcn = &resize->last_lcn;
 707                 supported = 1;
 708         }
 709 
 710         if (llcn->lcn < last_lcn) {
 711                 llcn->lcn = last_lcn;
 712                 llcn->inode = inode;
 713         }
 714 
 715         if (supported)
 716                 return;
 717 
 718         if (resize->last_unsupp < last_lcn)
 719                 resize->last_unsupp = last_lcn;
 720 }
 721 
 722 
 723 static void collect_relocation_info(ntfs_resize_t *resize, runlist *rl)
 724 {
 725         s64 lcn, lcn_length, start, len, inode;
 726         s64 new_vol_size;       /* (last LCN on the volume) + 1 */
 727 
 728         lcn = rl->lcn;
 729         lcn_length = rl->length;
 730         inode = resize->ni->mft_no;
 731         new_vol_size = resize->new_volume_size;
 732 
 733         if (lcn + lcn_length <= new_vol_size)
 734                 return;
 735 
 736         if (inode == FILE_Bitmap && resize->ctx->attr->type == AT_DATA)
 737                 return;
 738 
 739         start = lcn;
 740         len = lcn_length;
 741 
 742         if (lcn < new_vol_size) {
 743                 start = new_vol_size;
 744                 len = lcn_length - (new_vol_size - lcn);
 745 
 746                 if (!opt.info && (inode == FILE_MFTMirr)) {
 747                         err_printf("$MFTMirr can't be split up yet. Please try "
 748                                    "a different size.\n");
 749                         print_advise(resize->vol, lcn + lcn_length - 1);
 750                         exit(1);
 751                 }
 752         }
 753 
 754         resize->relocations += len;
 755 
 756         if (!opt.info || !resize->new_volume_size)
 757                 return;
 758 
 759         printf("Relocation needed for inode %8lld attr 0x%x LCN 0x%08llx "
 760                         "length %6lld\n", (long long)inode,
 761                         (unsigned int)le32_to_cpu(resize->ctx->attr->type),
 762                         (unsigned long long)start, (long long)len);
 763 }
 764 
 765 /**
 766  * build_lcn_usage_bitmap
 767  *
 768  * lcn_bitmap has one bit for each cluster on the disk.  Initially, lcn_bitmap
 769  * has no bits set.  As each attribute record is read the bits in lcn_bitmap are
 770  * checked to ensure that no other file already references that cluster.
 771  *
 772  * This serves as a rudimentary "chkdsk" operation.
 773  */
 774 static void build_lcn_usage_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
 775 {
 776         s64 inode;
 777         ATTR_RECORD *a;
 778         runlist *rl;
 779         int i, j;
 780         struct bitmap *lcn_bitmap = &fsck->lcn_bitmap;
 781 
 782         a = fsck->ctx->attr;
 783         inode = fsck->ni->mft_no;
 784 
 785         if (!a->non_resident)
 786                 return;
 787 
 788         if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL))) {
 789                 int err = errno;
 790                 perr_printf("ntfs_decompress_mapping_pairs");
 791                 if (err == EIO)
 792                         printf("%s", corrupt_volume_msg);
 793                 exit(1);
 794         }
 795 
 796 
 797         for (i = 0; rl[i].length; i++) {
 798                 s64 lcn = rl[i].lcn;
 799                 s64 lcn_length = rl[i].length;
 800 
 801                 /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
 802                 if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
 803                         continue;
 804 
 805                 /* FIXME: ntfs_mapping_pairs_decompress should return error */
 806                 if (lcn < 0 || lcn_length <= 0)
 807                         err_exit("Corrupt runlist in inode %lld attr %x LCN "
 808                                  "%llx length %llx\n", inode,
 809                                  (unsigned int)le32_to_cpu(a->type), lcn,
 810                                  lcn_length);
 811 
 812                 for (j = 0; j < lcn_length; j++) {
 813                         u64 k = (u64)lcn + j;
 814 
 815                         if (k >= (u64)vol->nr_clusters) {
 816                                 long long outsiders = lcn_length - j;
 817 
 818                                 fsck->outsider += outsiders;
 819 
 820                                 if (++fsck->show_outsider <= 10 || opt.verbose)
 821                                         printf("Outside of the volume reference"
 822                                                " for inode %lld at %lld:%lld\n",
 823                                                inode, (long long)k, outsiders);
 824 
 825                                 break;
 826                         }
 827 
 828                         if (ntfs_bit_get_and_set(lcn_bitmap->bm, k, 1)) {
 829                                 if (++fsck->multi_ref <= 10 || opt.verbose)
 830                                         printf("Cluster %lld is referenced "
 831                                                "multiple times!\n",
 832                                                (long long)k);
 833                                 continue;
 834                         }
 835                 }
 836                 fsck->inuse += lcn_length;
 837         }
 838         free(rl);
 839 }
 840 
 841 
 842 static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
 843 {
 844         ntfs_attr_search_ctx *ret;
 845 
 846         if ((ret = ntfs_attr_get_search_ctx(ni, mrec)) == NULL)
 847                 perr_printf("ntfs_attr_get_search_ctx");
 848 
 849         return ret;
 850 }
 851 
 852 /**
 853  * walk_attributes
 854  *
 855  * For a given MFT Record, iterate through all its attributes.  Any non-resident
 856  * data runs will be marked in lcn_bitmap.
 857  */
 858 static int walk_attributes(ntfs_volume *vol, ntfsck_t *fsck)
 859 {
 860         if (!(fsck->ctx = attr_get_search_ctx(fsck->ni, NULL)))
 861                 return -1;
 862 
 863         while (!ntfs_attrs_walk(fsck->ctx)) {
 864                 if (fsck->ctx->attr->type == AT_END)
 865                         break;
 866                 build_lcn_usage_bitmap(vol, fsck);
 867         }
 868 
 869         ntfs_attr_put_search_ctx(fsck->ctx);
 870         return 0;
 871 }
 872 
 873 /**
 874  * compare_bitmaps
 875  *
 876  * Compare two bitmaps.  In this case, $Bitmap as read from the disk and
 877  * lcn_bitmap which we built from the MFT Records.
 878  */
 879 static void compare_bitmaps(ntfs_volume *vol, struct bitmap *a)
 880 {
 881         s64 i, pos, count;
 882         int mismatch = 0;
 883         int backup_boot = 0;
 884         u8 bm[NTFS_BUF_SIZE];
 885 
 886         printf("Accounting clusters ...\n");
 887 
 888         pos = 0;
 889         while (1) {
 890                 count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);
 891                 if (count == -1)
 892                         perr_exit("Couldn't get $Bitmap $DATA");
 893 
 894                 if (count == 0) {
 895                         if (a->size > pos)
 896                                 err_exit("$Bitmap size is smaller than expected"
 897                                          " (%lld != %lld)\n", a->size, pos);
 898                         break;
 899                 }
 900 
 901                 for (i = 0; i < count; i++, pos++) {
 902                         s64 cl;  /* current cluster */
 903 
 904                         if (a->size <= pos)
 905                                 goto done;
 906 
 907                         if (a->bm[pos] == bm[i])
 908                                 continue;
 909 
 910                         for (cl = pos * 8; cl < (pos + 1) * 8; cl++) {
 911                                 char bit;
 912 
 913                                 bit = ntfs_bit_get(a->bm, cl);
 914                                 if (bit == ntfs_bit_get(bm, i * 8 + cl % 8))
 915                                         continue;
 916 
 917                                 if (!mismatch && !bit && !backup_boot &&
 918                                                 cl == vol->nr_clusters / 2) {
 919                                         /* FIXME: call also boot sector check */
 920                                         backup_boot = 1;
 921                                         printf("Found backup boot sector in "
 922                                                "the middle of the volume.\n");
 923                                         continue;
 924                                 }
 925 
 926                                 if (++mismatch > 10 && !opt.verbose)
 927                                         continue;
 928 
 929                                 printf("Cluster accounting failed at %lld "
 930                                                 "(0x%llx): %s cluster in "
 931                                                 "$Bitmap\n", (long long)cl,
 932                                                 (unsigned long long)cl,
 933                                                 bit ? "missing" : "extra");
 934                         }
 935                 }
 936         }
 937 done:
 938         if (mismatch) {
 939                 printf("Filesystem check failed! Totally %d cluster "
 940                        "accounting mismatches.\n", mismatch);
 941                 err_printf("%s", corrupt_volume_msg);
 942                 exit(1);
 943         }
 944 }
 945 
 946 /**
 947  * progress_init
 948  *
 949  * Create and scale our progress bar.
 950  */
 951 static void progress_init(struct progress_bar *p, u64 start, u64 stop, int flags)
 952 {
 953         p->start = start;
 954         p->stop = stop;
 955         p->unit = 100.0 / (stop - start);
 956         p->resolution = 100;
 957         p->flags = flags;
 958 }
 959 
 960 /**
 961  * progress_update
 962  *
 963  * Update the progress bar and tell the user.
 964  */
 965 static void progress_update(struct progress_bar *p, u64 current)
 966 {
 967         float percent;
 968 
 969         if (!(p->flags & NTFS_PROGBAR))
 970                 return;
 971         if (p->flags & NTFS_PROGBAR_SUPPRESS)
 972                 return;
 973 
 974         /* WARNING: don't modify the texts, external tools grep for them */
 975         percent = p->unit * current;
 976         if (current != p->stop) {
 977                 if ((current - p->start) % p->resolution)
 978                         return;
 979                 printf("%6.2f percent completed\r", percent);
 980         } else
 981                 printf("100.00 percent completed\n");
 982         fflush(stdout);
 983 }
 984 
 985 static int inode_close(ntfs_inode *ni)
 986 {
 987         if (ntfs_inode_close(ni)) {
 988                 perr_printf("ntfs_inode_close for inode %llu",
 989                             (unsigned long long)ni->mft_no);
 990                 return -1;
 991         }
 992         return 0;
 993 }
 994 
 995 /**
 996  * walk_inodes
 997  *
 998  * Read each record in the MFT, skipping the unused ones, and build up a bitmap
 999  * from all the non-resident attributes.
1000  */
1001 static int build_allocation_bitmap(ntfs_volume *vol, ntfsck_t *fsck)
1002 {
1003         s64 nr_mft_records, inode = 0;
1004         ntfs_inode *ni;
1005         struct progress_bar progress;
1006         int pb_flags = 0;       /* progress bar flags */
1007 
1008         /* WARNING: don't modify the text, external tools grep for it */
1009         printf("Checking filesystem consistency ...\n");
1010 
1011         if (fsck->flags & NTFSCK_PROGBAR)
1012                 pb_flags |= NTFS_PROGBAR;
1013 
1014         nr_mft_records = vol->mft_na->initialized_size >>
1015                         vol->mft_record_size_bits;
1016 
1017         progress_init(&progress, inode, nr_mft_records - 1, pb_flags);
1018 
1019         for (; inode < nr_mft_records; inode++) {
1020                 progress_update(&progress, inode);
1021 
1022                 if ((ni = ntfs_inode_open(vol, (MFT_REF)inode)) == NULL) {
1023                         /* FIXME: continue only if it make sense, e.g.
1024                            MFT record not in use based on $MFT bitmap */
1025                         if (errno == EIO || errno == ENOENT)
1026                                 continue;
1027                         perr_printf("Reading inode %lld failed", inode);
1028                         return -1;
1029                 }
1030 
1031                 if (ni->mrec->base_mft_record)
1032                         goto close_inode;
1033 
1034                 fsck->ni = ni;
1035                 if (walk_attributes(vol, fsck) != 0) {
1036                         inode_close(ni);
1037                         return -1;
1038                 }
1039 close_inode:
1040                 if (inode_close(ni) != 0)
1041                         return -1;
1042         }
1043         return 0;
1044 }
1045 
1046 static void build_resize_constraints(ntfs_resize_t *resize)
1047 {
1048         s64 i;
1049         runlist *rl;
1050 
1051         if (!resize->ctx->attr->non_resident)
1052                 return;
1053 
1054         if (!(rl = ntfs_mapping_pairs_decompress(resize->vol,
1055                                                  resize->ctx->attr, NULL)))
1056                 perr_exit("ntfs_decompress_mapping_pairs");
1057 
1058         for (i = 0; rl[i].length; i++) {
1059                 /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
1060                 if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
1061                         continue;
1062 
1063                 collect_resize_constraints(resize, rl + i);
1064                 if (resize->shrink)
1065                         collect_relocation_info(resize, rl + i);
1066         }
1067         free(rl);
1068 }
1069 
1070 static void resize_constraints_by_attributes(ntfs_resize_t *resize)
1071 {
1072         if (!(resize->ctx = attr_get_search_ctx(resize->ni, NULL)))
1073                 exit(1);
1074 
1075         while (!ntfs_attrs_walk(resize->ctx)) {
1076                 if (resize->ctx->attr->type == AT_END)
1077                         break;
1078                 build_resize_constraints(resize);
1079         }
1080 
1081         ntfs_attr_put_search_ctx(resize->ctx);
1082 }
1083 
1084 static void set_resize_constraints(ntfs_resize_t *resize)
1085 {
1086         s64 nr_mft_records, inode;
1087         ntfs_inode *ni;
1088 
1089         printf("Collecting resizing constraints ...\n");
1090 
1091         nr_mft_records = resize->vol->mft_na->initialized_size >>
1092                         resize->vol->mft_record_size_bits;
1093 
1094         for (inode = 0; inode < nr_mft_records; inode++) {
1095 
1096                 ni = ntfs_inode_open(resize->vol, (MFT_REF)inode);
1097                 if (ni == NULL) {
1098                         if (errno == EIO || errno == ENOENT)
1099                                 continue;
1100                         perr_exit("Reading inode %lld failed", inode);
1101                 }
1102 
1103                 if (ni->mrec->base_mft_record)
1104                         goto close_inode;
1105 
1106                 resize->ni = ni;
1107                 resize_constraints_by_attributes(resize);
1108 close_inode:
1109                 if (inode_close(ni) != 0)
1110                         exit(1);
1111         }
1112 }
1113 
1114 static void rl_fixup(runlist **rl)
1115 {
1116         runlist *tmp = *rl;
1117 
1118         if (tmp->lcn == LCN_RL_NOT_MAPPED) {
1119                 s64 unmapped_len = tmp->length;
1120 
1121                 ntfs_log_verbose("Skip unmapped run at the beginning ...\n");
1122 
1123                 if (!tmp->length)
1124                         err_exit("Empty unmapped runlist! Please report!\n");
1125                 (*rl)++;
1126                 for (tmp = *rl; tmp->length; tmp++)
1127                         tmp->vcn -= unmapped_len;
1128         }
1129 
1130         for (tmp = *rl; tmp->length; tmp++) {
1131                 if (tmp->lcn == LCN_RL_NOT_MAPPED) {
1132                         ntfs_log_verbose("Skip unmapped run at the end  ...\n");
1133 
1134                         if (tmp[1].length)
1135                                 err_exit("Unmapped runlist in the middle! "
1136                                          "Please report!\n");
1137                         tmp->lcn = LCN_ENOENT;
1138                         tmp->length = 0;
1139                 }
1140         }
1141 }
1142 
1143 static void replace_attribute_runlist(ntfs_volume *vol,
1144                                       ntfs_attr_search_ctx *ctx,
1145                                       runlist *rl)
1146 {
1147         int mp_size, l;
1148         void *mp;
1149         ATTR_RECORD *a = ctx->attr;
1150 
1151         rl_fixup(&rl);
1152 
1153         if ((mp_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0)) == -1)
1154                 perr_exit("ntfs_get_size_for_mapping_pairs");
1155 
1156         if (a->name_length) {
1157                 u16 name_offs = le16_to_cpu(a->name_offset);
1158                 u16 mp_offs = le16_to_cpu(a->u.nonres.mapping_pairs_offset);
1159 
1160                 if (name_offs >= mp_offs)
1161                         err_exit("Attribute name is after mapping pairs! "
1162                                  "Please report!\n");
1163         }
1164 
1165         /* CHECKME: don't trust mapping_pairs is always the last item in the
1166            attribute, instead check for the real size/space */
1167         l = (int)le32_to_cpu(a->length) - le16_to_cpu(a->u.nonres.mapping_pairs_offset);
1168         if (mp_size > l) {
1169                 s64 remains_size;
1170                 char *next_attr;
1171 
1172                 ntfs_log_verbose("Enlarging attribute header ...\n");
1173 
1174                 mp_size = (mp_size + 7) & ~7;
1175 
1176                 ntfs_log_verbose("Old mp size      : %d\n", l);
1177                 ntfs_log_verbose("New mp size      : %d\n", mp_size);
1178                 ntfs_log_verbose("Bytes in use     : %u\n", (unsigned int)
1179                                  le32_to_cpu(ctx->mrec->bytes_in_use));
1180 
1181                 next_attr = (char *)a + le32_to_cpu(a->length);
1182                 l = mp_size - l;
1183 
1184                 ntfs_log_verbose("Bytes in use new : %u\n", l + (unsigned int)
1185                                  le32_to_cpu(ctx->mrec->bytes_in_use));
1186                 ntfs_log_verbose("Bytes allocated  : %u\n", (unsigned int)
1187                                  le32_to_cpu(ctx->mrec->bytes_allocated));
1188 
1189                 remains_size = le32_to_cpu(ctx->mrec->bytes_in_use);
1190                 remains_size -= (next_attr - (char *)ctx->mrec);
1191 
1192                 ntfs_log_verbose("increase         : %d\n", l);
1193                 ntfs_log_verbose("shift            : %lld\n",
1194                                  (long long)remains_size);
1195 
1196                 if (le32_to_cpu(ctx->mrec->bytes_in_use) + l >
1197                                 le32_to_cpu(ctx->mrec->bytes_allocated))
1198                         err_exit("Extended record needed (%u > %u), not yet "
1199                                  "supported!\nPlease try to free less space.\n",
1200                                  (unsigned int)le32_to_cpu(ctx->mrec->
1201                                         bytes_in_use) + l,
1202                                  (unsigned int)le32_to_cpu(ctx->mrec->
1203                                         bytes_allocated));
1204 
1205                 memmove(next_attr + l, next_attr, remains_size);
1206                 ctx->mrec->bytes_in_use = cpu_to_le32(l +
1207                                 le32_to_cpu(ctx->mrec->bytes_in_use));
1208                 a->length = cpu_to_le32(le32_to_cpu(a->length) + l);
1209         }
1210 
1211         mp = ntfs_calloc(mp_size);
1212         if (!mp)
1213                 perr_exit("ntfsc_calloc couldn't get memory");
1214 
1215         if (ntfs_mapping_pairs_build(vol, mp, mp_size, rl, 0, NULL))
1216                 perr_exit("ntfs_mapping_pairs_build");
1217 
1218         memmove((u8*)a + le16_to_cpu(a->u.nonres.mapping_pairs_offset), mp, mp_size);
1219 
1220         free(mp);
1221 }
1222 
1223 static void set_bitmap_range(struct bitmap *bm, s64 pos, s64 length, u8 bit)
1224 {
1225         while (length--)
1226                 ntfs_bit_set(bm->bm, pos++, bit);
1227 }
1228 
1229 static void set_bitmap_clusters(struct bitmap *bm, runlist *rl, u8 bit)
1230 {
1231         for (; rl->length; rl++)
1232                 set_bitmap_range(bm, rl->lcn, rl->length, bit);
1233 }
1234 
1235 static void release_bitmap_clusters(struct bitmap *bm, runlist *rl)
1236 {
1237         max_free_cluster_range = 0;
1238         set_bitmap_clusters(bm, rl, 0);
1239 }
1240 
1241 static void set_max_free_zone(s64 length, s64 end, runlist_element *rle)
1242 {
1243         if (length > rle->length) {
1244                 rle->lcn = end - length;
1245                 rle->length = length;
1246         }
1247 }
1248 
1249 static int find_free_cluster(struct bitmap *bm,
1250                              runlist_element *rle,
1251                              s64 nr_vol_clusters,
1252                              int hint)
1253 {
1254         /* FIXME: get rid of this 'static' variable */
1255         static s64 pos = 0;
1256         s64 i, items = rle->length;
1257         s64 free_zone = 0;
1258 
1259         if (pos >= nr_vol_clusters)
1260                 pos = 0;
1261         if (!max_free_cluster_range)
1262                 max_free_cluster_range = nr_vol_clusters;
1263         rle->lcn = rle->length = 0;
1264         if (hint)
1265                 pos = nr_vol_clusters / 2;
1266         i = pos;
1267 
1268         do {
1269                 if (!ntfs_bit_get(bm->bm, i)) {
1270                         if (++free_zone == items) {
1271                                 set_max_free_zone(free_zone, i + 1, rle);
1272                                 break;
1273                         }
1274                 } else {
1275                         set_max_free_zone(free_zone, i, rle);
1276                         free_zone = 0;
1277                 }
1278                 if (++i == nr_vol_clusters) {
1279                         set_max_free_zone(free_zone, i, rle);
1280                         i = free_zone = 0;
1281                 }
1282                 if (rle->length == max_free_cluster_range)
1283                         break;
1284         } while (i != pos);
1285 
1286         if (i)
1287                 set_max_free_zone(free_zone, i, rle);
1288 
1289         if (!rle->lcn) {
1290                 errno = ENOSPC;
1291                 return -1;
1292         }
1293         if (rle->length < items && rle->length < max_free_cluster_range) {
1294                 max_free_cluster_range = rle->length;
1295                 ntfs_log_verbose("Max free range: %7lld     \n",
1296                                  (long long)max_free_cluster_range);
1297         }
1298         pos = rle->lcn + items;
1299         if (pos == nr_vol_clusters)
1300                 pos = 0;
1301 
1302         set_bitmap_range(bm, rle->lcn, rle->length, 1);
1303         return 0;
1304 }
1305 
1306 static runlist *alloc_cluster(struct bitmap *bm,
1307                               s64 items,
1308                               s64 nr_vol_clusters,
1309                               int hint)
1310 {
1311         runlist_element rle;
1312         runlist *rl = NULL;
1313         int rl_size, runs = 0;
1314         s64 vcn = 0;
1315 
1316         if (items <= 0) {
1317                 errno = EINVAL;
1318                 return NULL;
1319         }
1320 
1321         while (items > 0) {
1322 
1323                 if (runs)
1324                         hint = 0;
1325                 rle.length = items;
1326                 if (find_free_cluster(bm, &rle, nr_vol_clusters, hint) == -1)
1327                         return NULL;
1328 
1329                 rl_size = (runs + 2) * sizeof(runlist_element);
1330                 if (!(rl = (runlist *)realloc(rl, rl_size)))
1331                         return NULL;
1332 
1333                 rl_set(rl + runs, vcn, rle.lcn, rle.length);
1334 
1335                 vcn += rle.length;
1336                 items -= rle.length;
1337                 runs++;
1338         }
1339 
1340         rl_set(rl + runs, vcn, -1LL, 0LL);
1341 
1342         if (runs > 1) {
1343                 ntfs_log_verbose("Multi-run allocation:    \n");
1344                 dump_runlist(rl);
1345         }
1346         return rl;
1347 }
1348 
1349 static int read_all(struct ntfs_device *dev, void *buf, int count)
1350 {
1351         int i;
1352 
1353         while (count > 0) {
1354 
1355                 i = count;
1356                 if (!NDevReadOnly(dev))
1357                         i = dev->d_ops->read(dev, buf, count);
1358 
1359                 if (i < 0) {
1360                         if (errno != EAGAIN && errno != EINTR)
1361                                 return -1;
1362                 } else if (i > 0) {
1363                         count -= i;
1364                         buf = i + (char *)buf;
1365                 } else
1366                         err_exit("Unexpected end of file!\n");
1367         }
1368         return 0;
1369 }
1370 
1371 static int write_all(struct ntfs_device *dev, void *buf, int count)
1372 {
1373         int i;
1374 
1375         while (count > 0) {
1376 
1377                 i = count;
1378                 if (!NDevReadOnly(dev))
1379                         i = dev->d_ops->write(dev, buf, count);
1380 
1381                 if (i < 0) {
1382                         if (errno != EAGAIN && errno != EINTR)
1383                                 return -1;
1384                 } else {
1385                         count -= i;
1386                         buf = i + (char *)buf;
1387                 }
1388         }
1389         return 0;
1390 }
1391 
1392 /**
1393  * write_mft_record
1394  *
1395  * Write an MFT Record back to the disk.  If the read-only command line option
1396  * was given, this function will do nothing.
1397  */
1398 static int write_mft_record(ntfs_volume *v, const MFT_REF mref, MFT_RECORD *buf)
1399 {
1400         if (ntfs_mft_record_write(v, mref, buf))
1401                 perr_exit("ntfs_mft_record_write");
1402 
1403 //      if (v->u.dev->d_ops->sync(v->u.dev) == -1)
1404 //              perr_exit("Failed to sync device");
1405 
1406         return 0;
1407 }
1408 
1409 static void lseek_to_cluster(ntfs_volume *vol, s64 lcn)
1410 {
1411         off_t pos;
1412         pos = (off_t)(lcn * vol->cluster_size);
1413         if (vol->u.dev->d_ops->seek(vol->u.dev, pos, SEEK_SET) == (off_t)-1)
1414                 perr_exit("seek failed to position %lld", lcn);
1415 }
1416 
1417 static void copy_clusters(ntfs_resize_t *resize, s64 dest, s64 src, s64 len)
1418 {
1419         s64 i;
1420         char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
1421         ntfs_volume *vol = resize->vol;
1422 
1423         for (i = 0; i < len; i++) {
1424 
1425                 lseek_to_cluster(vol, src + i);
1426 
1427                 if (read_all(vol->u.dev, buff, vol->cluster_size) == -1) {
1428                         perr_printf("Failed to read from the disk");
1429                         if (errno == EIO)
1430                                 printf("%s", bad_sectors_warning_msg);
1431                         exit(1);
1432                 }
1433 
1434                 lseek_to_cluster(vol, dest + i);
1435 
1436                 if (write_all(vol->u.dev, buff, vol->cluster_size) == -1) {
1437                         perr_printf("Failed to write to the disk");
1438                         if (errno == EIO)
1439                                 printf("%s", bad_sectors_warning_msg);
1440                         exit(1);
1441                 }
1442 
1443                 resize->relocations++;
1444                 progress_update(&resize->progress, resize->relocations);
1445         }
1446 }
1447 
1448 static void relocate_clusters(ntfs_resize_t *r, runlist *dest_rl, s64 src_lcn)
1449 {
1450         /* collect_shrink_constraints() ensured $MFTMir DATA is one run */
1451         if (r->mref == FILE_MFTMirr && r->ctx->attr->type == AT_DATA) {
1452                 if (!r->mftmir_old) {
1453                         r->mftmir_rl.lcn = dest_rl->lcn;
1454                         r->mftmir_rl.length = dest_rl->length;
1455                         r->mftmir_old = src_lcn;
1456                 } else
1457                         err_exit("Multi-run $MFTMirr. Please report!\n");
1458         }
1459 
1460         for (; dest_rl->length; src_lcn += dest_rl->length, dest_rl++)
1461                 copy_clusters(r, dest_rl->lcn, src_lcn, dest_rl->length);
1462 }
1463 
1464 static void rl_split_run(runlist **rl, int run, s64 pos)
1465 {
1466         runlist *rl_new, *rle_new, *rle;
1467         int items, new_size, size_head, size_tail;
1468         s64 len_head, len_tail;
1469 
1470         items = rl_items(*rl);
1471         new_size = (items + 1) * sizeof(runlist_element);
1472         size_head = run * sizeof(runlist_element);
1473         size_tail = (items - run - 1) * sizeof(runlist_element);
1474 
1475         rl_new = ntfs_malloc(new_size);
1476         if (!rl_new)
1477                 perr_exit("ntfs_malloc");
1478 
1479         rle_new = rl_new + run;
1480         rle = *rl + run;
1481 
1482         memmove(rl_new, *rl, size_head);
1483         memmove(rle_new + 2, rle + 1, size_tail);
1484 
1485         len_tail = rle->length - (pos - rle->lcn);
1486         len_head = rle->length - len_tail;
1487 
1488         rl_set(rle_new, rle->vcn, rle->lcn, len_head);
1489         rl_set(rle_new + 1, rle->vcn + len_head, rle->lcn + len_head, len_tail);
1490 
1491         ntfs_log_verbose("Splitting run at cluster %lld:\n", (long long)pos);
1492         dump_run(rle); dump_run(rle_new); dump_run(rle_new + 1);
1493 
1494         free(*rl);
1495         *rl = rl_new;
1496 }
1497 
1498 static void rl_insert_at_run(runlist **rl, int run, runlist *ins)
1499 {
1500         int items, ins_items;
1501         int new_size, size_tail;
1502         runlist *rle;
1503         s64 vcn;
1504 
1505         items  = rl_items(*rl);
1506         ins_items = rl_items(ins) - 1;
1507         new_size = ((items - 1) + ins_items) * sizeof(runlist_element);
1508         size_tail = (items - run - 1) * sizeof(runlist_element);
1509 
1510         if (!(*rl = (runlist *)realloc(*rl, new_size)))
1511                 perr_exit("realloc");
1512 
1513         rle = *rl + run;
1514 
1515         memmove(rle + ins_items, rle + 1, size_tail);
1516 
1517         for (vcn = rle->vcn; ins->length; rle++, vcn += ins->length, ins++) {
1518                 rl_set(rle, vcn, ins->lcn, ins->length);
1519 //              dump_run(rle);
1520         }
1521 
1522         return;
1523 
1524         /* FIXME: fast path if ins_items = 1 */
1525 //      (*rl + run)->lcn = ins->lcn;
1526 }
1527 
1528 static void relocate_run(ntfs_resize_t *resize, runlist **rl, int run)
1529 {
1530         s64 lcn, lcn_length;
1531         s64 new_vol_size;       /* (last LCN on the volume) + 1 */
1532         runlist *relocate_rl;   /* relocate runlist to relocate_rl */
1533         int hint;
1534 
1535         lcn = (*rl + run)->lcn;
1536         lcn_length = (*rl + run)->length;
1537         new_vol_size = resize->new_volume_size;
1538 
1539         if (lcn + lcn_length <= new_vol_size)
1540                 return;
1541 
1542         if (lcn < new_vol_size) {
1543                 rl_split_run(rl, run, new_vol_size);
1544                 return;
1545         }
1546 
1547         hint = (resize->mref == FILE_MFTMirr) ? 1 : 0;
1548         if (!(relocate_rl = alloc_cluster(&resize->lcn_bitmap, lcn_length,
1549                                           new_vol_size, hint)))
1550                 perr_exit("Cluster allocation failed for %llu:%lld",
1551                           resize->mref, lcn_length);
1552 
1553         /* FIXME: check $MFTMirr DATA isn't multi-run (or support it) */
1554         ntfs_log_verbose("Relocate record %7llu:0x%x:%08lld:0x%08llx:0x%08llx "
1555                          "--> 0x%08llx\n", (unsigned long long)resize->mref,
1556                          (unsigned int)le32_to_cpu(resize->ctx->attr->type),
1557                          (long long)lcn_length,
1558                          (unsigned long long)(*rl + run)->vcn,
1559                          (unsigned long long)lcn,
1560                          (unsigned long long)relocate_rl->lcn);
1561 
1562         relocate_clusters(resize, relocate_rl, lcn);
1563         rl_insert_at_run(rl, run, relocate_rl);
1564 
1565         /* We don't release old clusters in the bitmap, that area isn't
1566            used by the allocator and will be truncated later on */
1567         free(relocate_rl);
1568 
1569         resize->dirty_inode = DIRTY_ATTRIB;
1570 }
1571 
1572 static void relocate_attribute(ntfs_resize_t *resize)
1573 {
1574         ATTR_RECORD *a;
1575         runlist *rl;
1576         int i;
1577 
1578         a = resize->ctx->attr;
1579 
1580         if (!a->non_resident)
1581                 return;
1582 
1583         if (!(rl = ntfs_mapping_pairs_decompress(resize->vol, a, NULL)))
1584                 perr_exit("ntfs_decompress_mapping_pairs");
1585 
1586         for (i = 0; rl[i].length; i++) {
1587                 s64 lcn = rl[i].lcn;
1588                 s64 lcn_length = rl[i].length;
1589 
1590                 if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
1591                         continue;
1592 
1593                 /* FIXME: ntfs_mapping_pairs_decompress should return error */
1594                 if (lcn < 0 || lcn_length <= 0)
1595                         err_exit("Corrupt runlist in MTF %llu attr %x LCN "
1596                                  "%llx length %llx\n", resize->mref,
1597                                  (unsigned int)le32_to_cpu(a->type),
1598                                  lcn, lcn_length);
1599 
1600                 relocate_run(resize, &rl, i);
1601         }
1602 
1603         if (resize->dirty_inode == DIRTY_ATTRIB) {
1604                 replace_attribute_runlist(resize->vol, resize->ctx, rl);
1605                 resize->dirty_inode = DIRTY_INODE;
1606         }
1607 
1608         free(rl);
1609 }
1610 
1611 static int is_mftdata(ntfs_resize_t *resize)
1612 {
1613         if (resize->ctx->attr->type != AT_DATA)
1614                 return 0;
1615 
1616         if (resize->mref == 0)
1617                 return 1;
1618 
1619         if (MREF_LE(resize->mrec->base_mft_record) == 0 &&
1620             MSEQNO_LE(resize->mrec->base_mft_record) != 0)
1621                 return 1;
1622 
1623         return 0;
1624 }
1625 
1626 static int handle_mftdata(ntfs_resize_t *resize, int do_mftdata)
1627 {
1628         ATTR_RECORD *attr = resize->ctx->attr;
1629         VCN highest_vcn, lowest_vcn;
1630 
1631         if (do_mftdata) {
1632 
1633                 if (!is_mftdata(resize))
1634                         return 0;
1635 
1636                 highest_vcn = sle64_to_cpu(attr->u.nonres.highest_vcn);
1637                 lowest_vcn  = sle64_to_cpu(attr->u.nonres.lowest_vcn);
1638 
1639                 if (resize->mft_highest_vcn != highest_vcn)
1640                         return 0;
1641 
1642                 if (lowest_vcn == 0)
1643                         resize->mft_highest_vcn = lowest_vcn;
1644                 else
1645                         resize->mft_highest_vcn = lowest_vcn - 1;
1646 
1647         } else if (is_mftdata(resize)) {
1648 
1649                 highest_vcn = sle64_to_cpu(attr->u.nonres.highest_vcn);
1650 
1651                 if (resize->mft_highest_vcn < highest_vcn)
1652                         resize->mft_highest_vcn = highest_vcn;
1653 
1654                 return 0;
1655         }
1656 
1657         return 1;
1658 }
1659 
1660 static void relocate_attributes(ntfs_resize_t *resize, int do_mftdata)
1661 {
1662         int ret;
1663 
1664         if (!(resize->ctx = attr_get_search_ctx(NULL, resize->mrec)))
1665                 exit(1);
1666 
1667         while (!ntfs_attrs_walk(resize->ctx)) {
1668                 if (resize->ctx->attr->type == AT_END)
1669                         break;
1670 
1671                 if (handle_mftdata(resize, do_mftdata) == 0)
1672                         continue;
1673 
1674                 ret = ntfs_inode_badclus_bad(resize->mref, resize->ctx->attr);
1675                 if (ret == -1)
1676                         perr_exit("Bad sector list check failed");
1677                 else if (ret == 1)
1678                         continue;
1679 
1680                 if (resize->mref == FILE_Bitmap &&
1681                     resize->ctx->attr->type == AT_DATA)
1682                         continue;
1683 
1684                 relocate_attribute(resize);
1685         }
1686 
1687         ntfs_attr_put_search_ctx(resize->ctx);
1688 }
1689 
1690 static void relocate_inode(ntfs_resize_t *resize, MFT_REF mref, int do_mftdata)
1691 {
1692         if (ntfs_file_record_read(resize->vol, mref, &resize->mrec, NULL)) {
1693                 /* FIXME: continue only if it make sense, e.g.
1694                    MFT record not in use based on $MFT bitmap */
1695                 if (errno == EIO || errno == ENOENT)
1696                         return;
1697                 perr_exit("ntfs_file_record_record");
1698         }
1699 
1700         if (!(resize->mrec->flags & MFT_RECORD_IN_USE))
1701                 return;
1702 
1703         resize->mref = mref;
1704         resize->dirty_inode = DIRTY_NONE;
1705 
1706         relocate_attributes(resize, do_mftdata);
1707 
1708         if (resize->dirty_inode == DIRTY_INODE) {
1709 //              if (vol->u.dev->d_ops->sync(vol->u.dev) == -1)
1710 //                      perr_exit("Failed to sync device");
1711                 if (write_mft_record(resize->vol, mref, resize->mrec))
1712                         perr_exit("Couldn't update record %llu", mref);
1713         }
1714 }
1715 
1716 static void relocate_inodes(ntfs_resize_t *resize)
1717 {
1718         s64 nr_mft_records;
1719         MFT_REF mref;
1720         VCN highest_vcn;
1721 
1722         printf("Relocating needed data ...\n");
1723 
1724         progress_init(&resize->progress, 0, resize->relocations, resize->progress.flags);
1725         resize->relocations = 0;
1726 
1727         resize->mrec = ntfs_malloc(resize->vol->mft_record_size);
1728         if (!resize->mrec)
1729                 perr_exit("ntfs_malloc failed");
1730 
1731         nr_mft_records = resize->vol->mft_na->initialized_size >>
1732                         resize->vol->mft_record_size_bits;
1733 
1734         for (mref = 0; mref < (MFT_REF)nr_mft_records; mref++)
1735                 relocate_inode(resize, mref, 0);
1736 
1737         while (1) {
1738                 highest_vcn = resize->mft_highest_vcn;
1739                 mref = nr_mft_records;
1740                 do {
1741                         relocate_inode(resize, --mref, 1);
1742                         if (resize->mft_highest_vcn == 0)
1743                                 goto done;
1744                 } while (mref);
1745 
1746                 if (highest_vcn == resize->mft_highest_vcn)
1747                         err_exit("Sanity check failed! Highest_vcn = %lld. "
1748                                  "Please report!\n", highest_vcn);
1749         }
1750 done:
1751         free(resize->mrec);
1752 }
1753 
1754 static void print_hint(ntfs_volume *vol, const char *s, struct llcn_t llcn)
1755 {
1756         s64 runs_b, runs_mb;
1757 
1758         if (llcn.lcn == 0)
1759                 return;
1760 
1761         runs_b = llcn.lcn * vol->cluster_size;
1762         runs_mb = rounded_up_division(runs_b, NTFS_MBYTE);
1763         printf("%-19s: %9lld MB      %8lld\n", s, (long long)runs_mb,
1764                         (long long)llcn.inode);
1765 }
1766 
1767 /**
1768  * advise_on_resize
1769  *
1770  * The metadata file $Bitmap has one bit for each cluster on disk.  This has
1771  * already been read into lcn_bitmap.  By looking for the last used cluster on
1772  * the disk, we can work out by how much we can shrink the volume.
1773  */
1774 static void advise_on_resize(ntfs_resize_t *resize)
1775 {
1776         ntfs_volume *vol = resize->vol;
1777 
1778         if (opt.verbose) {
1779                 printf("Estimating smallest shrunken size supported ...\n");
1780                 printf("File feature         Last used at      By inode\n");
1781                 print_hint(vol, "$MFT",         resize->last_mft);
1782                 print_hint(vol, "Multi-Record", resize->last_multi_mft);
1783                 print_hint(vol, "$MFTMirr",     resize->last_mftmir);
1784                 print_hint(vol, "Compressed",   resize->last_compressed);
1785                 print_hint(vol, "Sparse",       resize->last_sparse);
1786                 print_hint(vol, "Ordinary",     resize->last_lcn);
1787         }
1788 
1789         print_advise(vol, resize->last_unsupp);
1790 }
1791 
1792 
1793 static void rl_expand(runlist **rl, const VCN last_vcn)
1794 {
1795         int len;
1796         runlist *p = *rl;
1797 
1798         len = rl_items(p) - 1;
1799         if (len <= 0)
1800                 err_exit("rl_expand: bad runlist length: %d\n", len);
1801 
1802         if (p[len].vcn > last_vcn)
1803                 err_exit("rl_expand: length is already more than requested "
1804                          "(%lld > %lld)\n", p[len].vcn, last_vcn);
1805 
1806         if (p[len - 1].lcn == LCN_HOLE) {
1807 
1808                 p[len - 1].length += last_vcn - p[len].vcn;
1809                 p[len].vcn = last_vcn;
1810 
1811         } else if (p[len - 1].lcn >= 0) {
1812 
1813                 p = realloc(*rl, (++len + 1) * sizeof(runlist_element));
1814                 if (!p)
1815                         perr_exit("rl_expand: realloc");
1816 
1817                 p[len - 1].lcn = LCN_HOLE;
1818                 p[len - 1].length = last_vcn - p[len - 1].vcn;
1819                 rl_set(p + len, last_vcn, LCN_ENOENT, 0LL);
1820                 *rl = p;
1821 
1822         } else
1823                 err_exit("rl_expand: bad LCN: %lld\n", p[len - 1].lcn);
1824 }
1825 
1826 static void rl_truncate(runlist **rl, const VCN last_vcn)
1827 {
1828         int len;
1829         VCN vcn;
1830 
1831         len = rl_items(*rl) - 1;
1832         if (len <= 0)
1833                 err_exit("rl_truncate: bad runlist length: %d\n", len);
1834 
1835         vcn = (*rl)[len].vcn;
1836 
1837         if (vcn < last_vcn)
1838                 rl_expand(rl, last_vcn);
1839 
1840         else if (vcn > last_vcn)
1841                 if (ntfs_rl_truncate(rl, last_vcn) == -1)
1842                         perr_exit("ntfs_rl_truncate");
1843 }
1844 
1845 /**
1846  * bitmap_file_data_fixup
1847  *
1848  * $Bitmap can overlap the end of the volume. Any bits in this region
1849  * must be set. This region also encompasses the backup boot sector.
1850  */
1851 static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm)
1852 {
1853         for (; cluster < bm->size << 3; cluster++)
1854                 ntfs_bit_set(bm->bm, (u64)cluster, 1);
1855 }
1856 
1857 /**
1858  * truncate_badclust_bad_attr
1859  *
1860  * The metadata file $BadClus needs to be shrunk.
1861  *
1862  * FIXME: this function should go away and instead using a generalized
1863  * "truncate_bitmap_data_attr()"
1864  */
1865 static void truncate_badclust_bad_attr(ntfs_resize_t *resize)
1866 {
1867         ATTR_RECORD *a;
1868         runlist *rl_bad;
1869         s64 nr_clusters = resize->new_volume_size;
1870         ntfs_volume *vol = resize->vol;
1871 
1872         a = resize->ctx->attr;
1873         if (!a->non_resident)
1874                 /* FIXME: handle resident attribute value */
1875                 err_exit("Resident attribute in $BadClust isn't supported!\n");
1876 
1877         if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, a, NULL)))
1878                 perr_exit("ntfs_mapping_pairs_decompress");
1879 
1880         rl_truncate(&rl_bad, nr_clusters);
1881 
1882         a->u.nonres.highest_vcn = cpu_to_sle64(nr_clusters - 1LL);
1883         a->u.nonres.allocated_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
1884         a->u.nonres.data_size = cpu_to_sle64(nr_clusters * vol->cluster_size);
1885 
1886         replace_attribute_runlist(vol, resize->ctx, rl_bad);
1887 
1888         free(rl_bad);
1889 }
1890 
1891 /**
1892  * realloc_bitmap_data_attr
1893  *
1894  * Reallocate the metadata file $Bitmap.  It must be large enough for one bit
1895  * per cluster of the shrunken volume.  Also it must be a of 8 bytes in size.
1896  */
1897 static void realloc_bitmap_data_attr(ntfs_resize_t *resize,
1898                                      runlist **rl,
1899                                      s64 nr_bm_clusters)
1900 {
1901         s64 i;
1902         ntfs_volume *vol = resize->vol;
1903         ATTR_RECORD *a = resize->ctx->attr;
1904         s64 new_size = resize->new_volume_size;
1905         struct bitmap *bm = &resize->lcn_bitmap;
1906 
1907         if (!(*rl = ntfs_mapping_pairs_decompress(vol, a, NULL)))
1908                 perr_exit("ntfs_mapping_pairs_decompress");
1909 
1910         release_bitmap_clusters(bm, *rl);
1911         free(*rl);
1912 
1913         for (i = vol->nr_clusters; i < new_size; i++)
1914                 ntfs_bit_set(bm->bm, i, 0);
1915 
1916         if (!(*rl = alloc_cluster(bm, nr_bm_clusters, new_size, 0)))
1917                 perr_exit("Couldn't allocate $Bitmap clusters");
1918 }
1919 
1920 static void realloc_lcn_bitmap(ntfs_resize_t *resize, s64 bm_bsize)
1921 {
1922         u8 *tmp;
1923 
1924         if (!(tmp = realloc(resize->lcn_bitmap.bm, bm_bsize)))
1925                 perr_exit("realloc");
1926 
1927         resize->lcn_bitmap.bm = tmp;
1928         resize->lcn_bitmap.size = bm_bsize;
1929         bitmap_file_data_fixup(resize->new_volume_size, &resize->lcn_bitmap);
1930 }
1931 
1932 /**
1933  * truncate_bitmap_data_attr
1934  */
1935 static void truncate_bitmap_data_attr(ntfs_resize_t *resize)
1936 {
1937         ATTR_RECORD *a;
1938         runlist *rl;
1939         s64 bm_bsize, size;
1940         s64 nr_bm_clusters;
1941         ntfs_volume *vol = resize->vol;
1942 
1943         a = resize->ctx->attr;
1944         if (!a->non_resident)
1945                 /* FIXME: handle resident attribute value */
1946                 err_exit("Resident attribute in $Bitmap isn't supported!\n");
1947 
1948         bm_bsize = nr_clusters_to_bitmap_byte_size(resize->new_volume_size);
1949         nr_bm_clusters = rounded_up_division(bm_bsize, vol->cluster_size);
1950 
1951         if (resize->shrink) {
1952                 realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
1953                 realloc_lcn_bitmap(resize, bm_bsize);
1954         } else {
1955                 realloc_lcn_bitmap(resize, bm_bsize);
1956                 realloc_bitmap_data_attr(resize, &rl, nr_bm_clusters);
1957         }
1958 
1959         a->u.nonres.highest_vcn = cpu_to_sle64(nr_bm_clusters - 1LL);
1960         a->u.nonres.allocated_size = cpu_to_sle64(nr_bm_clusters * vol->cluster_size);
1961         a->u.nonres.data_size = cpu_to_sle64(bm_bsize);
1962         a->u.nonres.initialized_size = cpu_to_sle64(bm_bsize);
1963 
1964         replace_attribute_runlist(vol, resize->ctx, rl);
1965 
1966         /*
1967          * FIXME: update allocated/data sizes and timestamps in $FILE_NAME
1968          * attribute too, for now chkdsk will do this for us.
1969          */
1970 
1971         size = ntfs_rl_pwrite(vol, rl, 0, bm_bsize, resize->lcn_bitmap.bm);
1972         if (bm_bsize != size) {
1973                 if (size == -1)
1974                         perr_exit("Couldn't write $Bitmap");
1975                 err_exit("Couldn't write full $Bitmap file (%lld from %lld)\n",
1976                                 (long long)size, (long long)bm_bsize);
1977         }
1978 
1979         free(rl);
1980 }
1981 
1982 /**
1983  * lookup_data_attr
1984  *
1985  * Find the $DATA attribute (with or without a name) for the given MFT reference
1986  * (inode number).
1987  */
1988 static void lookup_data_attr(ntfs_volume *vol,
1989                              MFT_REF mref,
1990                              const char *aname,
1991                              ntfs_attr_search_ctx **ctx)
1992 {
1993         ntfs_inode *ni;
1994         ntfschar *ustr;
1995         int len = 0;
1996 
1997         if (!(ni = ntfs_inode_open(vol, mref)))
1998                 perr_exit("ntfs_open_inode");
1999 
2000         if (!(*ctx = attr_get_search_ctx(ni, NULL)))
2001                 exit(1);
2002 
2003         if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) {
2004                 perr_printf("Couldn't convert '%s' to Unicode", aname);
2005                 exit(1);
2006         }
2007 
2008         if (ntfs_attr_lookup(AT_DATA, ustr, len, 0, 0, NULL, 0, *ctx))
2009                 perr_exit("ntfs_lookup_attr");
2010 
2011         ntfs_ucsfree(ustr);
2012 }
2013 
2014 static int check_bad_sectors(ntfs_volume *vol)
2015 {
2016         ntfs_attr_search_ctx *ctx;
2017         ntfs_inode *base_ni;
2018         runlist *rl;
2019         s64 i, badclusters = 0;
2020 
2021         ntfs_log_verbose("Checking for bad sectors ...\n");
2022 
2023         lookup_data_attr(vol, FILE_BadClus, "$Bad", &ctx);
2024 
2025         base_ni = ctx->base_ntfs_ino;
2026         if (!base_ni)
2027                 base_ni = ctx->ntfs_ino;
2028 
2029         if (NInoAttrList(base_ni)) {
2030                 err_printf("Hopelessly many bad sectors has been detected!\n");
2031                 printf("%s", many_bad_sectors_msg);
2032                 exit(1);
2033         }
2034 
2035         if (!ctx->attr->non_resident)
2036                 err_exit("Resident attribute in $BadClust! Please report to "
2037                          "%s\n", NTFS_DEV_LIST);
2038         /*
2039          * FIXME: The below would be partial for non-base records in the
2040          * not yet supported multi-record case. Alternatively use audited
2041          * ntfs_attr_truncate after an umount & mount.
2042          */
2043         if (!(rl = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL)))
2044                 perr_exit("Decompressing $BadClust:$Bad mapping pairs failed");
2045 
2046         for (i = 0; rl[i].length; i++) {
2047                 /* CHECKME: LCN_RL_NOT_MAPPED check isn't needed */
2048                 if (rl[i].lcn == LCN_HOLE || rl[i].lcn == LCN_RL_NOT_MAPPED)
2049                         continue;
2050 
2051                 badclusters += rl[i].length;
2052                 ntfs_log_verbose("Bad cluster: %#8llx - %#llx    (%lld)\n",
2053                                  rl[i].lcn, rl[i].lcn + rl[i].length - 1,
2054                                  rl[i].length);
2055         }
2056 
2057         if (badclusters) {
2058                 printf("%sThis software has detected that the disk has at least"
2059                        " %lld bad sector%s.\n",
2060                        !opt.badsectors ? NERR_PREFIX : "WARNING: ",
2061                        badclusters, badclusters - 1 ? "s" : "");
2062                 if (!opt.badsectors) {
2063                         printf("%s", bad_sectors_warning_msg);
2064                         exit(1);
2065                 } else
2066                         printf("WARNING: Bad sectors can cause reliability "
2067                                "problems and massive data loss!!!\n");
2068         }
2069 
2070         free(rl);
2071         ntfs_attr_put_search_ctx(ctx);
2072 
2073         return badclusters;
2074 }
2075 
2076 /**
2077  * truncate_badclust_file
2078  *
2079  * Shrink the $BadClus file to match the new volume size.
2080  */
2081 static void truncate_badclust_file(ntfs_resize_t *resize)
2082 {
2083         printf("Updating $BadClust file ...\n");
2084 
2085         lookup_data_attr(resize->vol, FILE_BadClus, "$Bad", &resize->ctx);
2086         /* FIXME: sanity_check_attr(ctx->attr); */
2087         truncate_badclust_bad_attr(resize);
2088 
2089         if (write_mft_record(resize->vol, resize->ctx->ntfs_ino->mft_no,
2090                              resize->ctx->mrec))
2091                 perr_exit("Couldn't update $BadClust");
2092 
2093         ntfs_attr_put_search_ctx(resize->ctx);
2094 }
2095 
2096 /**
2097  * truncate_bitmap_file
2098  *
2099  * Shrink the $Bitmap file to match the new volume size.
2100  */
2101 static void truncate_bitmap_file(ntfs_resize_t *resize)
2102 {
2103         printf("Updating $Bitmap file ...\n");
2104 
2105         lookup_data_attr(resize->vol, FILE_Bitmap, NULL, &resize->ctx);
2106         truncate_bitmap_data_attr(resize);
2107 
2108         if (write_mft_record(resize->vol, resize->ctx->ntfs_ino->mft_no,
2109                              resize->ctx->mrec))
2110                 perr_exit("Couldn't update $Bitmap");
2111 
2112         ntfs_attr_put_search_ctx(resize->ctx);
2113 }
2114 
2115 /**
2116  * setup_lcn_bitmap
2117  *
2118  * Allocate a block of memory with one bit for each cluster of the disk.
2119  * All the bits are set to 0, except those representing the region beyond the
2120  * end of the disk.
2121  */
2122 static int setup_lcn_bitmap(struct bitmap *bm, s64 nr_clusters)
2123 {
2124         /* Determine lcn bitmap byte size and allocate it. */
2125         bm->size = rounded_up_division(nr_clusters, 8);
2126 
2127         bm->bm = ntfs_calloc(bm->size);
2128         if (!bm->bm)
2129                 return -1;
2130 
2131         bitmap_file_data_fixup(nr_clusters, bm);
2132         return 0;
2133 }
2134 
2135 /**
2136  * update_bootsector
2137  *
2138  * FIXME: should be done using ntfs_* functions
2139  */
2140 static void update_bootsector(ntfs_resize_t *r)
2141 {
2142         NTFS_BOOT_SECTOR bs;
2143         s64  bs_size = sizeof(NTFS_BOOT_SECTOR);
2144         ntfs_volume *vol = r->vol;
2145 
2146         printf("Updating Boot record ...\n");
2147 
2148         if (vol->u.dev->d_ops->seek(vol->u.dev, 0, SEEK_SET) == (off_t)-1)
2149                 perr_exit("lseek");
2150 
2151         if (vol->u.dev->d_ops->read(vol->u.dev, &bs, bs_size) == -1)
2152                 perr_exit("read() error");
2153 
2154         bs.number_of_sectors = cpu_to_sle64(r->new_volume_size *
2155                         bs.bpb.sectors_per_cluster);
2156 
2157         if (r->mftmir_old) {
2158                 r->progress.flags |= NTFS_PROGBAR_SUPPRESS;
2159                 copy_clusters(r, r->mftmir_rl.lcn, r->mftmir_old,
2160                               r->mftmir_rl.length);
2161                 bs.mftmirr_lcn = cpu_to_sle64(r->mftmir_rl.lcn);
2162                 r->progress.flags &= ~NTFS_PROGBAR_SUPPRESS;
2163         }
2164 
2165         if (vol->u.dev->d_ops->seek(vol->u.dev, 0, SEEK_SET) == (off_t)-1)
2166                 perr_exit("lseek");
2167 
2168         if (!opt.ro_flag)
2169                 if (vol->u.dev->d_ops->write(vol->u.dev, &bs, bs_size) == -1)
2170                         perr_exit("write() error");
2171 }
2172 
2173 /**
2174  * vol_size
2175  */
2176 static s64 vol_size(ntfs_volume *v, s64 nr_clusters)
2177 {
2178         /* add one sector_size for the backup boot sector */
2179         return nr_clusters * v->cluster_size + v->sector_size;
2180 }
2181 
2182 /**
2183  * print_vol_size
2184  *
2185  * Print the volume size in bytes and decimal megabytes.
2186  */
2187 static void print_vol_size(const char *str, s64 bytes)
2188 {
2189         printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes,
2190                         (long long)rounded_up_division(bytes, NTFS_MBYTE));
2191 }
2192 
2193 /**
2194  * print_disk_usage
2195  *
2196  * Display the amount of disk space in use.
2197  */
2198 static void print_disk_usage(ntfs_volume *vol, s64 nr_used_clusters)
2199 {
2200         s64 total, used;
2201 
2202         total = vol->nr_clusters * vol->cluster_size;
2203         used = nr_used_clusters * vol->cluster_size;
2204 
2205         /* WARNING: don't modify the text, external tools grep for it */
2206         printf("Space in use       : %lld MB (%.1f%%)\n",
2207                (long long)rounded_up_division(used, NTFS_MBYTE),
2208                100.0 * ((float)used / total));
2209 }
2210 
2211 static void print_num_of_relocations(ntfs_resize_t *resize)
2212 {
2213         s64 relocations = resize->relocations * resize->vol->cluster_size;
2214 
2215         printf("Needed relocations : %lld (%lld MB)\n",
2216                         (long long)resize->relocations, (long long)
2217                         rounded_up_division(relocations, NTFS_MBYTE));
2218 }
2219 
2220 /**
2221  * mount_volume
2222  *
2223  * First perform some checks to determine if the volume is already mounted, or
2224  * is dirty (Windows wasn't shutdown properly).  If everything is OK, then mount
2225  * the volume (load the metadata into memory).
2226  */
2227 static ntfs_volume *mount_volume(void)
2228 {
2229         unsigned long mntflag;
2230         ntfs_volume *vol = NULL;
2231 
2232         if (ntfs_check_if_mounted(opt.volume, &mntflag)) {
2233                 perr_printf("Failed to check '%s' mount state", opt.volume);
2234                 printf("Probably /etc/mtab is missing. It's too risky to "
2235                        "continue. You might try\nan another Linux distro.\n");
2236                 exit(1);
2237         }
2238         if (mntflag & NTFS_MF_MOUNTED) {
2239                 if (!(mntflag & NTFS_MF_READONLY))
2240                         err_exit("Device '%s' is mounted read-write. "
2241                                  "You must 'umount' it first.\n", opt.volume);
2242                 if (!opt.ro_flag)
2243                         err_exit("Device '%s' is mounted. "
2244                                  "You must 'umount' it first.\n", opt.volume);
2245         }
2246         /*
2247          * Pass NTFS_MNT_FORENSIC so that the mount process does not modify the
2248          * volume at all.  We will do the logfile emptying and dirty setting
2249          * later if needed.
2250          */
2251         if (!(vol = ntfs_mount(opt.volume, opt.ro_flag | NTFS_MNT_FORENSIC))) {
2252                 int err = errno;
2253 
2254                 perr_printf("Opening '%s' as NTFS failed", opt.volume);
2255                 if (err == EINVAL)
2256                         printf(invalid_ntfs_msg, opt.volume);
2257                 else if (err == EIO)
2258                         printf("%s", corrupt_volume_msg);
2259                 else if (err == EPERM)
2260                         printf("%s", hibernated_volume_msg);
2261                 else if (err == EOPNOTSUPP)
2262                         printf("%s", unclean_journal_msg);
2263                 else if (err == EBUSY)
2264                         printf("%s", opened_volume_msg);
2265                 exit(1);
2266         }
2267 
2268         if (NVolWasDirty(vol))
2269                 if (opt.force-- <= 0)
2270                         err_exit("Volume is scheduled for check.\nRun chkdsk /f"
2271                                  " and please try again, or see option -f.\n");
2272 
2273         if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size)
2274                 err_exit("Cluster size %u is too large!\n",
2275                         (unsigned int)vol->cluster_size);
2276 
2277         printf("Device name        : %s\n", opt.volume);
2278         printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver);
2279         if (ntfs_version_is_supported(vol))
2280                 perr_exit("Unknown NTFS version");
2281 
2282         printf("Cluster size       : %u bytes\n",
2283                         (unsigned int)vol->cluster_size);
2284         print_vol_size("Current volume size", vol_size(vol, vol->nr_clusters));
2285 
2286         return vol;
2287 }
2288 
2289 /**
2290  * prepare_volume_fixup
2291  *
2292  * Set the volume's dirty flag and wipe the filesystem journal.  When Windows
2293  * boots it will automatically run chkdsk to check for any problems.  If the
2294  * read-only command line option was given, this function will do nothing.
2295  */
2296 static void prepare_volume_fixup(ntfs_volume *vol)
2297 {
2298         printf("Schedule chkdsk for NTFS consistency check at Windows boot "
2299                         "time ...\n");
2300         vol->flags |= VOLUME_IS_DIRTY;
2301         if (ntfs_volume_write_flags(vol, vol->flags))
2302                 perr_exit("Failed to set the volume dirty");
2303         NVolSetWasDirty(vol);
2304         if (vol->u.dev->d_ops->sync(vol->u.dev) == -1)
2305                 perr_exit("Failed to sync device");
2306         printf("Resetting $LogFile ... (this might take a while)\n");
2307         if (ntfs_logfile_reset(vol))
2308                 perr_exit("Failed to reset $LogFile");
2309         if (vol->u.dev->d_ops->sync(vol->u.dev) == -1)
2310                 perr_exit("Failed to sync device");
2311 }
2312 
2313 static void set_disk_usage_constraint(ntfs_resize_t *resize)
2314 {
2315         /* last lcn for a filled up volume (no empty space) */
2316         s64 last = resize->inuse - 1;
2317 
2318         if (resize->last_unsupp < last)
2319                 resize->last_unsupp = last;
2320 }
2321 
2322 static void check_resize_constraints(ntfs_resize_t *resize)
2323 {
2324         s64 new_size = resize->new_volume_size;
2325 
2326         /* FIXME: resize.shrink true also if only -i is used */
2327         if (!resize->shrink)
2328                 return;
2329 
2330         if (resize->inuse == resize->vol->nr_clusters)
2331                 err_exit("Volume is full. To shrink it, "
2332                          "delete unused files.\n");
2333 
2334         if (opt.info)
2335                 return;
2336 
2337         /* FIXME: reserve some extra space so Windows can boot ... */
2338         if (new_size < resize->inuse)
2339                 err_exit("New size can't be less than the space already"
2340                          " occupied by data.\nYou either need to delete unused"
2341                          " files or see the -i option.\n");
2342 
2343         if (new_size <= resize->last_unsupp)
2344                 err_exit("The fragmentation type, you have, isn't "
2345                          "supported yet. Rerun ntfsresize\nwith "
2346                          "the -i option to estimate the smallest "
2347                          "shrunken volume size supported.\n");
2348 
2349         print_num_of_relocations(resize);
2350 }
2351 
2352 static void check_cluster_allocation(ntfs_volume *vol, ntfsck_t *fsck)
2353 {
2354         memset(fsck, 0, sizeof(ntfsck_t));
2355 
2356         if (opt.show_progress)
2357                 fsck->flags |= NTFSCK_PROGBAR;
2358 
2359         if (setup_lcn_bitmap(&fsck->lcn_bitmap, vol->nr_clusters) != 0)
2360                 perr_exit("Failed to setup allocation bitmap");
2361         if (build_allocation_bitmap(vol, fsck) != 0)
2362                 exit(1);
2363         if (fsck->outsider || fsck->multi_ref) {
2364                 err_printf("Filesystem check failed!\n");
2365                 if (fsck->outsider)
2366                         err_printf("%d clusters are referenced outside "
2367                                    "of the volume.\n", fsck->outsider);
2368                 if (fsck->multi_ref)
2369                         err_printf("%d clusters are referenced multiply"
2370                                    " times.\n", fsck->multi_ref);
2371                 printf("%s", corrupt_volume_msg);
2372                 exit(1);
2373         }
2374 
2375         compare_bitmaps(vol, &fsck->lcn_bitmap);
2376 }
2377 
2378 int main(int argc, char **argv)
2379 {
2380         ntfsck_t fsck;
2381         ntfs_resize_t resize;
2382         s64 new_size = 0;       /* in clusters; 0 = --info w/o --size */
2383         s64 device_size;        /* in bytes */
2384         ntfs_volume *vol;
2385 
2386         ntfs_log_set_handler(ntfs_log_handler_outerr);
2387 
2388         printf("%s v%s (libntfs %s)\n", EXEC_NAME, VERSION,
2389                         ntfs_libntfs_version());
2390 
2391         if (!parse_options(argc, argv))
2392                 return 1;
2393 
2394         utils_set_locale();
2395 
2396         if (!(vol = mount_volume()))
2397                 err_exit("Couldn't open volume '%s'!\n", opt.volume);
2398 
2399         device_size = ntfs_device_size_get(vol->u.dev, vol->sector_size);
2400         device_size *= vol->sector_size;
2401         if (device_size <= 0)
2402                 err_exit("Couldn't get device size (%lld)!\n", device_size);
2403 
2404         print_vol_size("Current device size", device_size);
2405 
2406         if (device_size < vol->nr_clusters * vol->cluster_size)
2407                 err_exit("Current NTFS volume size is bigger than the device "
2408                          "size!\nCorrupt partition table or incorrect device "
2409                          "partitioning?\n");
2410 
2411         if (!opt.bytes && !opt.info)
2412                 opt.bytes = device_size;
2413 
2414         /* Take the integer part: don't make the volume bigger than requested */
2415         new_size = opt.bytes / vol->cluster_size;
2416 
2417         /* Backup boot sector at the end of device isn't counted in NTFS
2418            volume size thus we have to reserve space for it. */
2419         if (new_size)
2420                 --new_size;
2421 
2422         if (!opt.info) {
2423                 print_vol_size("New volume size    ", vol_size(vol, new_size));
2424                 if (device_size < opt.bytes)
2425                         err_exit("New size can't be bigger than the device size"
2426                                  ".\nIf you want to enlarge NTFS then first "
2427                                  "enlarge the device size by e.g. fdisk.\n");
2428         }
2429 
2430         if (!opt.info && (new_size == vol->nr_clusters ||
2431                           (opt.bytes == device_size &&
2432                            new_size == vol->nr_clusters - 1))) {
2433                 printf("Nothing to do: NTFS volume size is already OK.\n");
2434                 exit(0);
2435         }
2436 
2437         memset(&resize, 0, sizeof(resize));
2438         resize.vol = vol;
2439         resize.new_volume_size = new_size;
2440         /* This is also true if --info was used w/o --size (new_size = 0) */
2441         if (new_size < vol->nr_clusters)
2442                 resize.shrink = 1;
2443         if (opt.show_progress)
2444                 resize.progress.flags |= NTFS_PROGBAR;
2445         /*
2446          * Checking and __reporting__ of bad sectors must be done before cluster
2447          * allocation check because chkdsk doesn't fix $Bitmap's w/ bad sectors
2448          * thus users would (were) quite confused why chkdsk doesn't work.
2449          */
2450         resize.badclusters = check_bad_sectors(vol);
2451 
2452         check_cluster_allocation(vol, &fsck);
2453 
2454         print_disk_usage(vol, fsck.inuse);
2455 
2456         resize.inuse = fsck.inuse;
2457         resize.lcn_bitmap = fsck.lcn_bitmap;
2458 
2459         set_resize_constraints(&resize);
2460         set_disk_usage_constraint(&resize);
2461         check_resize_constraints(&resize);
2462 
2463         if (opt.info) {
2464                 advise_on_resize(&resize);
2465                 exit(0);
2466         }
2467 
2468         if (opt.force-- <= 0 && !opt.ro_flag) {
2469                 printf("%s", resize_warning_msg);
2470                 proceed_question();
2471         }
2472 
2473         /* FIXME: performance - relocate logfile here if it's needed */
2474         prepare_volume_fixup(vol);
2475 
2476         if (resize.relocations)
2477                 relocate_inodes(&resize);
2478 
2479         truncate_badclust_file(&resize);
2480         truncate_bitmap_file(&resize);
2481         update_bootsector(&resize);
2482 
2483         /* We don't create backup boot sector because we don't know where the
2484            partition will be split. The scheduled chkdsk will fix it */
2485 
2486         if (opt.ro_flag) {
2487                 printf("The read-only test run ended successfully.\n");
2488                 exit(0);
2489         }
2490 
2491         /* WARNING: don't modify the texts, external tools grep for them */
2492         printf("Syncing device ...\n");
2493         if (vol->u.dev->d_ops->sync(vol->u.dev) == -1)
2494                 perr_exit("fsync");
2495 
2496         printf("Successfully resized NTFS on device '%s'.\n", vol->u.dev->d_name);
2497         if (resize.shrink)
2498                 printf("%s", resize_important_msg);
2499 
2500         return 0;
2501 }