"Fossies" - the Fresh Open Source Software Archive

Member "ntfs-3g_ntfsprogs-2017.3.23/ntfsprogs/ntfsresize.c" (23 Mar 2017, 123226 Bytes) of package /linux/misc/ntfs-3g_ntfsprogs-2017.3.23.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ntfsresize.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3g_ntfsprogs-2016.2.22_vs_3g_ntfsprogs-2017.3.23.

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