1 /**
   2  * runlist.c - Run list handling code. Part of the Linux-NTFS project.
   3  *
   4  * Copyright (c) 2002-2005 Anton Altaparmakov
   5  * Copyright (c) 2002-2005 Richard Russon
   6  * Copyright (c) 2002-2006 Szabolcs Szakacsits
   7  * Copyright (c) 2004-2007 Yura Pakhuchiy
   8  *
   9  * This program/include file is free software; you can redistribute it and/or
  10  * modify it under the terms of the GNU General Public License as published
  11  * by the Free Software Foundation; either version 2 of the License, or
  12  * (at your option) any later version.
  13  *
  14  * This program/include file is distributed in the hope that it will be
  15  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
  16  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17  * GNU General Public License for more details.
  18  *
  19  * You should have received a copy of the GNU General Public License
  20  * along with this program (in the main directory of the Linux-NTFS
  21  * distribution in the file COPYING); if not, write to the Free Software
  22  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  23  */
  24 
  25 #ifdef HAVE_CONFIG_H
  26 #include "config.h"
  27 #endif
  28 
  29 #ifdef HAVE_STDIO_H
  30 #include <stdio.h>
  31 #endif
  32 #ifdef HAVE_STRING_H
  33 #include <string.h>
  34 #endif
  35 #ifdef HAVE_STDLIB_H
  36 #include <stdlib.h>
  37 #endif
  38 #ifdef HAVE_ERRNO_H
  39 #include <errno.h>
  40 #endif
  41 
  42 #include "compat.h"
  43 #include "types.h"
  44 #include "volume.h"
  45 #include "layout.h"
  46 #include "debug.h"
  47 #include "device.h"
  48 #include "logging.h"
  49 
  50 /**
  51  * ntfs_rl_mm - runlist memmove
  52  * @base:
  53  * @dst:
  54  * @src:
  55  * @size:
  56  *
  57  * Description...
  58  *
  59  * Returns:
  60  */
  61 static __inline__ void ntfs_rl_mm(runlist_element *base, int dst, int src,
  62                 int size)
  63 {
  64         if ((dst != src) && (size > 0))
  65                 memmove(base + dst, base + src, size * sizeof(*base));
  66 }
  67 
  68 /**
  69  * ntfs_rl_mc - runlist memory copy
  70  * @dstbase:
  71  * @dst:
  72  * @srcbase:
  73  * @src:
  74  * @size:
  75  *
  76  * Description...
  77  *
  78  * Returns:
  79  */
  80 static __inline__ void ntfs_rl_mc(runlist_element *dstbase, int dst,
  81                 runlist_element *srcbase, int src, int size)
  82 {
  83         if (size > 0)
  84                 memcpy(dstbase + dst, srcbase + src, size * sizeof(*dstbase));
  85 }
  86 
  87 /**
  88  * ntfs_rl_realloc - Reallocate memory for runlists
  89  * @rl:         original runlist
  90  * @old_size:   number of runlist elements in the original runlist @rl
  91  * @new_size:   number of runlist elements we need space for
  92  *
  93  * As the runlists grow, more memory will be required. To prevent large
  94  * numbers of small reallocations of memory, this function returns a 4kiB block
  95  * of memory.
  96  *
  97  * N.B. If the new allocation doesn't require a different number of 4kiB
  98  *      blocks in memory, the function will return the original pointer.
  99  *
 100  * On success, return a pointer to the newly allocated, or recycled, memory.
 101  * On error, return NULL with errno set to the error code.
 102  */
 103 static runlist_element *ntfs_rl_realloc(runlist_element *rl,
 104                 int old_size, int new_size)
 105 {
 106         old_size = (old_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
 107         new_size = (new_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
 108         if (old_size == new_size)
 109                 return rl;
 110         return realloc(rl, new_size);
 111 }
 112 
 113 /**
 114  * ntfs_rl_are_mergeable - test if two runlists can be joined together
 115  * @dst:        original runlist
 116  * @src:        new runlist to test for mergeability with @dst
 117  *
 118  * Test if two runlists can be joined together. For this, their VCNs and LCNs
 119  * must be adjacent.
 120  *
 121  * Return: TRUE   Success, the runlists can be merged.
 122  *         FALSE  Failure, the runlists cannot be merged.
 123  */
 124 static BOOL ntfs_rl_are_mergeable(runlist_element *dst,
 125                 runlist_element *src)
 126 {
 127         if (!dst || !src) {
 128                 ntfs_log_debug("Eeek. ntfs_rl_are_mergeable() invoked with NULL "
 129                                 "pointer!\n");
 130                 return FALSE;
 131         }
 132 
 133         /* We can merge unmapped regions even if they are misaligned. */
 134         if ((dst->lcn == LCN_RL_NOT_MAPPED) && (src->lcn == LCN_RL_NOT_MAPPED))
 135                 return TRUE;
 136         /* If the runs are misaligned, we cannot merge them. */
 137         if ((dst->vcn + dst->length) != src->vcn)
 138                 return FALSE;
 139         /* If both runs are non-sparse and contiguous, we can merge them. */
 140         if ((dst->lcn >= 0) && (src->lcn >= 0) &&
 141                 ((dst->lcn + dst->length) == src->lcn))
 142                 return TRUE;
 143         /* If we are merging two holes, we can merge them. */
 144         if ((dst->lcn == LCN_HOLE) && (src->lcn == LCN_HOLE))
 145                 return TRUE;
 146         /* Cannot merge. */
 147         return FALSE;
 148 }
 149 
 150 /**
 151  * __ntfs_rl_merge - merge two runlists without testing if they can be merged
 152  * @dst:        original, destination runlist
 153  * @src:        new runlist to merge with @dst
 154  *
 155  * Merge the two runlists, writing into the destination runlist @dst. The
 156  * caller must make sure the runlists can be merged or this will corrupt the
 157  * destination runlist.
 158  */
 159 static __inline__ void __ntfs_rl_merge(runlist_element *dst,
 160                 runlist_element *src)
 161 {
 162         dst->length += src->length;
 163 }
 164 
 165 /**
 166  * ntfs_rl_append - append a runlist after a given element
 167  * @dst:        original runlist to be worked on
 168  * @dsize:      number of elements in @dst (including end marker)
 169  * @src:        runlist to be inserted into @dst
 170  * @ssize:      number of elements in @src (excluding end marker)
 171  * @loc:        append the new runlist @src after this element in @dst
 172  *
 173  * Append the runlist @src after element @loc in @dst.  Merge the right end of
 174  * the new runlist, if necessary. Adjust the size of the hole before the
 175  * appended runlist.
 176  *
 177  * On success, return a pointer to the new, combined, runlist. Note, both
 178  * runlists @dst and @src are deallocated before returning so you cannot use
 179  * the pointers for anything any more. (Strictly speaking the returned runlist
 180  * may be the same as @dst but this is irrelevant.)
 181  *
 182  * On error, return NULL, with errno set to the error code. Both runlists are
 183  * left unmodified.
 184  */
 185 static runlist_element *ntfs_rl_append(runlist_element *dst,
 186                 int dsize, runlist_element *src, int ssize, int loc)
 187 {
 188         BOOL right = FALSE;     /* Right end of @src needs merging */
 189         int marker;             /* End of the inserted runs */
 190 
 191         if (!dst || !src) {
 192                 ntfs_log_debug("Eeek. ntfs_rl_append() invoked with NULL "
 193                                 "pointer!\n");
 194                 errno = EINVAL;
 195                 return NULL;
 196         }
 197 
 198         /* First, check if the right hand end needs merging. */
 199         if ((loc + 1) < dsize)
 200                 right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1);
 201 
 202         /* Space required: @dst size + @src size, less one if we merged. */
 203         dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - right);
 204         if (!dst)
 205                 return NULL;
 206         /*
 207          * We are guaranteed to succeed from here so can start modifying the
 208          * original runlists.
 209          */
 210 
 211         /* First, merge the right hand end, if necessary. */
 212         if (right)
 213                 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
 214 
 215         /* marker - First run after the @src runs that have been inserted */
 216         marker = loc + ssize + 1;
 217 
 218         /* Move the tail of @dst out of the way, then copy in @src. */
 219         ntfs_rl_mm(dst, marker, loc + 1 + right, dsize - loc - 1 - right);
 220         ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
 221 
 222         /* Adjust the size of the preceding hole. */
 223         dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
 224 
 225         /* We may have changed the length of the file, so fix the end marker */
 226         if (dst[marker].lcn == LCN_ENOENT)
 227                 dst[marker].vcn = dst[marker-1].vcn + dst[marker-1].length;
 228 
 229         return dst;
 230 }
 231 
 232 /**
 233  * ntfs_rl_insert - insert a runlist into another
 234  * @dst:        original runlist to be worked on
 235  * @dsize:      number of elements in @dst (including end marker)
 236  * @src:        new runlist to be inserted
 237  * @ssize:      number of elements in @src (excluding end marker)
 238  * @loc:        insert the new runlist @src before this element in @dst
 239  *
 240  * Insert the runlist @src before element @loc in the runlist @dst. Merge the
 241  * left end of the new runlist, if necessary. Adjust the size of the hole
 242  * after the inserted runlist.
 243  *
 244  * On success, return a pointer to the new, combined, runlist. Note, both
 245  * runlists @dst and @src are deallocated before returning so you cannot use
 246  * the pointers for anything any more. (Strictly speaking the returned runlist
 247  * may be the same as @dst but this is irrelevant.)
 248  *
 249  * On error, return NULL, with errno set to the error code. Both runlists are
 250  * left unmodified.
 251  */
 252 static runlist_element *ntfs_rl_insert(runlist_element *dst,
 253                 int dsize, runlist_element *src, int ssize, int loc)
 254 {
 255         BOOL left = FALSE;      /* Left end of @src needs merging */
 256         BOOL disc = FALSE;      /* Discontinuity between @dst and @src */
 257         int marker;             /* End of the inserted runs */
 258 
 259         if (!dst || !src) {
 260                 ntfs_log_debug("Eeek. ntfs_rl_insert() invoked with NULL "
 261                                 "pointer!\n");
 262                 errno = EINVAL;
 263                 return NULL;
 264         }
 265 
 266         /* disc => Discontinuity between the end of @dst and the start of @src.
 267          *         This means we might need to insert a "notmapped" run.
 268          */
 269         if (loc == 0)
 270                 disc = (src[0].vcn > 0);
 271         else {
 272                 s64 merged_length;
 273 
 274                 left = ntfs_rl_are_mergeable(dst + loc - 1, src);
 275 
 276                 merged_length = dst[loc - 1].length;
 277                 if (left)
 278                         merged_length += src->length;
 279 
 280                 disc = (src[0].vcn > dst[loc - 1].vcn + merged_length);
 281         }
 282 
 283         /* Space required: @dst size + @src size, less one if we merged, plus
 284          * one if there was a discontinuity.
 285          */
 286         dst = ntfs_rl_realloc(dst, dsize, dsize + ssize - left + disc);
 287         if (!dst)
 288                 return NULL;
 289         /*
 290          * We are guaranteed to succeed from here so can start modifying the
 291          * original runlist.
 292          */
 293 
 294         if (left)
 295                 __ntfs_rl_merge(dst + loc - 1, src);
 296 
 297         /*
 298          * marker - First run after the @src runs that have been inserted
 299          * Nominally: marker = @loc + @ssize (location + number of runs in @src)
 300          * If "left", then the first run in @src has been merged with one in @dst.
 301          * If "disc", then @dst and @src don't meet and we need an extra run to fill the gap.
 302          */
 303         marker = loc + ssize - left + disc;
 304 
 305         /* Move the tail of @dst out of the way, then copy in @src. */
 306         ntfs_rl_mm(dst, marker, loc, dsize - loc);
 307         ntfs_rl_mc(dst, loc + disc, src, left, ssize - left);
 308 
 309         /* Adjust the VCN of the first run after the insertion ... */
 310         dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
 311         /* ... and the length. */
 312         if (dst[marker].lcn == LCN_HOLE || dst[marker].lcn == LCN_RL_NOT_MAPPED)
 313                 dst[marker].length = dst[marker + 1].vcn - dst[marker].vcn;
 314 
 315         /* Writing beyond the end of the file and there's a discontinuity. */
 316         if (disc) {
 317                 if (loc > 0) {
 318                         dst[loc].vcn = dst[loc - 1].vcn + dst[loc - 1].length;
 319                         dst[loc].length = dst[loc + 1].vcn - dst[loc].vcn;
 320                 } else {
 321                         dst[loc].vcn = 0;
 322                         dst[loc].length = dst[loc + 1].vcn;
 323                 }
 324                 dst[loc].lcn = LCN_RL_NOT_MAPPED;
 325         }
 326         return dst;
 327 }
 328 
 329 /**
 330  * ntfs_rl_replace - overwrite a runlist element with another runlist
 331  * @dst:        original runlist to be worked on
 332  * @dsize:      number of elements in @dst (including end marker)
 333  * @src:        new runlist to be inserted
 334  * @ssize:      number of elements in @src (excluding end marker)
 335  * @loc:        index in runlist @dst to overwrite with @src
 336  *
 337  * Replace the runlist element @dst at @loc with @src. Merge the left and
 338  * right ends of the inserted runlist, if necessary.
 339  *
 340  * On success, return a pointer to the new, combined, runlist. Note, both
 341  * runlists @dst and @src are deallocated before returning so you cannot use
 342  * the pointers for anything any more. (Strictly speaking the returned runlist
 343  * may be the same as @dst but this is irrelevant.)
 344  *
 345  * On error, return NULL, with errno set to the error code. Both runlists are
 346  * left unmodified.
 347  */
 348 static runlist_element *ntfs_rl_replace(runlist_element *dst,
 349                 int dsize, runlist_element *src, int ssize, int loc)
 350 {
 351         signed delta;
 352         BOOL left  = FALSE;     /* Left end of @src needs merging */
 353         BOOL right = FALSE;     /* Right end of @src needs merging */
 354         int tail;               /* Start of tail of @dst */
 355         int marker;             /* End of the inserted runs */
 356 
 357         if (!dst || !src) {
 358                 ntfs_log_debug("Eeek. ntfs_rl_replace() invoked with NULL "
 359                                 "pointer!\n");
 360                 errno = EINVAL;
 361                 return NULL;
 362         }
 363 
 364         /* First, see if the left and right ends need merging. */
 365         if ((loc + 1) < dsize)
 366                 right = ntfs_rl_are_mergeable(src + ssize - 1, dst + loc + 1);
 367         if (loc > 0)
 368                 left = ntfs_rl_are_mergeable(dst + loc - 1, src);
 369 
 370         /* Allocate some space. We'll need less if the left, right, or both
 371          * ends get merged.  The -1 accounts for the run being replaced.
 372          */
 373         delta = ssize - 1 - left - right;
 374         if (delta > 0) {
 375                 dst = ntfs_rl_realloc(dst, dsize, dsize + delta);
 376                 if (!dst)
 377                         return NULL;
 378         }
 379         /*
 380          * We are guaranteed to succeed from here so can start modifying the
 381          * original runlists.
 382          */
 383 
 384         /* First, merge the left and right ends, if necessary. */
 385         if (right)
 386                 __ntfs_rl_merge(src + ssize - 1, dst + loc + 1);
 387         if (left)
 388                 __ntfs_rl_merge(dst + loc - 1, src);
 389 
 390         /*
 391          * tail - Offset of the tail of @dst
 392          * Nominally: @tail = @loc + 1 (location, skipping the replaced run)
 393          * If "right", then one of @dst's runs is already merged into @src.
 394          */
 395         tail = loc + right + 1;
 396 
 397         /*
 398          * marker - First run after the @src runs that have been inserted
 399          * Nominally: @marker = @loc + @ssize (location + number of runs in @src)
 400          * If "left", then the first run in @src has been merged with one in @dst.
 401          */
 402         marker = loc + ssize - left;
 403 
 404         /* Move the tail of @dst out of the way, then copy in @src. */
 405         ntfs_rl_mm(dst, marker, tail, dsize - tail);
 406         ntfs_rl_mc(dst, loc, src, left, ssize - left);
 407 
 408         /* We may have changed the length of the file, so fix the end marker */
 409         if (((dsize - tail) > 0) && (dst[marker].lcn == LCN_ENOENT))
 410                 dst[marker].vcn = dst[marker - 1].vcn + dst[marker - 1].length;
 411 
 412         return dst;
 413 }
 414 
 415 /**
 416  * ntfs_rl_split - insert a runlist into the centre of a hole
 417  * @dst:        original runlist to be worked on
 418  * @dsize:      number of elements in @dst (including end marker)
 419  * @src:        new runlist to be inserted
 420  * @ssize:      number of elements in @src (excluding end marker)
 421  * @loc:        index in runlist @dst at which to split and insert @src
 422  *
 423  * Split the runlist @dst at @loc into two and insert @new in between the two
 424  * fragments. No merging of runlists is necessary. Adjust the size of the
 425  * holes either side.
 426  *
 427  * On success, return a pointer to the new, combined, runlist. Note, both
 428  * runlists @dst and @src are deallocated before returning so you cannot use
 429  * the pointers for anything any more. (Strictly speaking the returned runlist
 430  * may be the same as @dst but this is irrelevant.)
 431  *
 432  * On error, return NULL, with errno set to the error code. Both runlists are
 433  * left unmodified.
 434  */
 435 static runlist_element *ntfs_rl_split(runlist_element *dst,
 436                 int dsize, runlist_element *src, int ssize, int loc)
 437 {
 438         if (!dst || !src) {
 439                 ntfs_log_trace("Invoked with NULL pointer!\n");
 440                 errno = EINVAL;
 441                 return NULL;
 442         }
 443 
 444         /* Space required: @dst size + @src size + one new hole. */
 445         dst = ntfs_rl_realloc(dst, dsize, dsize + ssize + 1);
 446         if (!dst)
 447                 return dst;
 448         /*
 449          * We are guaranteed to succeed from here so can start modifying the
 450          * original runlists.
 451          */
 452 
 453         /* Move the tail of @dst out of the way, then copy in @src. */
 454         ntfs_rl_mm(dst, loc + 1 + ssize, loc, dsize - loc);
 455         ntfs_rl_mc(dst, loc + 1, src, 0, ssize);
 456 
 457         /* Adjust the size of the holes either size of @src. */
 458         dst[loc].length         = dst[loc+1].vcn       - dst[loc].vcn;
 459         dst[loc+ssize+1].vcn    = dst[loc+ssize].vcn   + dst[loc+ssize].length;
 460         dst[loc+ssize+1].length = dst[loc+ssize+2].vcn - dst[loc+ssize+1].vcn;
 461 
 462         return dst;
 463 }
 464 
 465 
 466 /**
 467  * ntfs_runlists_merge - merge two runlists into one
 468  * @drl:        original runlist to be worked on
 469  * @srl:        new runlist to be merged into @drl
 470  *
 471  * First we sanity check the two runlists @srl and @drl to make sure that they
 472  * are sensible and can be merged. The runlist @srl must be either after the
 473  * runlist @drl or completely within a hole (or unmapped region) in @drl.
 474  *
 475  * Merging of runlists is necessary in two cases:
 476  *   1. When attribute lists are used and a further extent is being mapped.
 477  *   2. When new clusters are allocated to fill a hole or extend a file.
 478  *
 479  * There are four possible ways @srl can be merged. It can:
 480  *      - be inserted at the beginning of a hole,
 481  *      - split the hole in two and be inserted between the two fragments,
 482  *      - be appended at the end of a hole, or it can
 483  *      - replace the whole hole.
 484  * It can also be appended to the end of the runlist, which is just a variant
 485  * of the insert case.
 486  *
 487  * On success, return a pointer to the new, combined, runlist. Note, both
 488  * runlists @drl and @srl are deallocated before returning so you cannot use
 489  * the pointers for anything any more. (Strictly speaking the returned runlist
 490  * may be the same as @dst but this is irrelevant.)
 491  *
 492  * On error, return NULL, with errno set to the error code. Both runlists are
 493  * left unmodified. The following error codes are defined:
 494  *      ENOMEM          Not enough memory to allocate runlist array.
 495  *      EINVAL          Invalid parameters were passed in.
 496  *      ERANGE          The runlists overlap and cannot be merged.
 497  */
 498 runlist_element *ntfs_runlists_merge(runlist_element *drl,
 499                 runlist_element *srl)
 500 {
 501         int di, si;             /* Current index into @[ds]rl. */
 502         int sstart;             /* First index with lcn > LCN_RL_NOT_MAPPED. */
 503         int dins;               /* Index into @drl at which to insert @srl. */
 504         int dend, send;         /* Last index into @[ds]rl. */
 505         int dfinal, sfinal;     /* The last index into @[ds]rl with
 506                                    lcn >= LCN_HOLE. */
 507         int marker = 0;
 508         VCN marker_vcn = 0;
 509 
 510         ntfs_log_debug("dst:\n");
 511         ntfs_debug_runlist_dump(drl);
 512         ntfs_log_debug("src:\n");
 513         ntfs_debug_runlist_dump(srl);
 514 
 515         /* Check for silly calling... */
 516         if (!srl)
 517                 return drl;
 518 
 519         /* Check for the case where the first mapping is being done now. */
 520         if (!drl) {
 521                 drl = srl;
 522                 /* Complete the source runlist if necessary. */
 523                 if (drl[0].vcn) {
 524                         /* Scan to the end of the source runlist. */
 525                         for (dend = 0; drl[dend].length; dend++)
 526                                 ;
 527                         dend++;
 528                         drl = ntfs_rl_realloc(drl, dend, dend + 1);
 529                         if (!drl)
 530                                 return drl;
 531                         /* Insert start element at the front of the runlist. */
 532                         ntfs_rl_mm(drl, 1, 0, dend);
 533                         drl[0].vcn = 0;
 534                         drl[0].lcn = LCN_RL_NOT_MAPPED;
 535                         drl[0].length = drl[1].vcn;
 536                 }
 537                 goto finished;
 538         }
 539 
 540         si = di = 0;
 541 
 542         /* Skip any unmapped start element(s) in the source runlist. */
 543         while (srl[si].length && srl[si].lcn < (LCN)LCN_HOLE)
 544                 si++;
 545 
 546         /* Can't have an entirely unmapped source runlist. */
 547         if (!srl[si].length) {
 548                 ntfs_log_debug("Eeek! ntfs_runlists_merge() received entirely "
 549                                 "unmapped source runlist.\n");
 550                 errno = EINVAL;
 551                 return NULL;
 552         }
 553 
 554         /* Record the starting points. */
 555         sstart = si;
 556 
 557         /*
 558          * Skip forward in @drl until we reach the position where @srl needs to
 559          * be inserted. If we reach the end of @drl, @srl just needs to be
 560          * appended to @drl.
 561          */
 562         for (; drl[di].length; di++) {
 563                 if (drl[di].vcn + drl[di].length > srl[sstart].vcn)
 564                         break;
 565         }
 566         dins = di;
 567 
 568         /* Sanity check for illegal overlaps. */
 569         if ((drl[di].vcn == srl[si].vcn) && (drl[di].lcn >= 0) &&
 570                         (srl[si].lcn >= 0)) {
 571                 ntfs_log_debug("Run lists overlap. Cannot merge!\n");
 572                 errno = ERANGE;
 573                 return NULL;
 574         }
 575 
 576         /* Scan to the end of both runlists in order to know their sizes. */
 577         for (send = si; srl[send].length; send++)
 578                 ;
 579         for (dend = di; drl[dend].length; dend++)
 580                 ;
 581 
 582         if (srl[send].lcn == (LCN)LCN_ENOENT)
 583                 marker_vcn = srl[marker = send].vcn;
 584 
 585         /* Scan to the last element with lcn >= LCN_HOLE. */
 586         for (sfinal = send; sfinal >= 0 && srl[sfinal].lcn < LCN_HOLE; sfinal--)
 587                 ;
 588         for (dfinal = dend; dfinal >= 0 && drl[dfinal].lcn < LCN_HOLE; dfinal--)
 589                 ;
 590 
 591         {
 592         BOOL start;
 593         BOOL finish;
 594         int ds = dend + 1;              /* Number of elements in drl & srl */
 595         int ss = sfinal - sstart + 1;
 596 
 597         start  = ((drl[dins].lcn <  LCN_RL_NOT_MAPPED) ||    /* End of file   */
 598                   (drl[dins].vcn == srl[sstart].vcn));       /* Start of hole */
 599         finish = ((drl[dins].lcn >= LCN_RL_NOT_MAPPED) &&    /* End of file   */
 600                  ((drl[dins].vcn + drl[dins].length) <=      /* End of hole   */
 601                   (srl[send - 1].vcn + srl[send - 1].length)));
 602 
 603         /* Or we'll lose an end marker */
 604         if (finish && !drl[dins].length)
 605                 ss++;
 606         if (marker && (drl[dins].vcn + drl[dins].length > srl[send - 1].vcn))
 607                 finish = FALSE;
 608 
 609         ntfs_log_debug("dfinal = %i, dend = %i\n", dfinal, dend);
 610         ntfs_log_debug("sstart = %i, sfinal = %i, send = %i\n", sstart, sfinal, send);
 611         ntfs_log_debug("start = %i, finish = %i\n", start, finish);
 612         ntfs_log_debug("ds = %i, ss = %i, dins = %i\n", ds, ss, dins);
 613 
 614         if (start) {
 615                 if (finish)
 616                         drl = ntfs_rl_replace(drl, ds, srl + sstart, ss, dins);
 617                 else
 618                         drl = ntfs_rl_insert(drl, ds, srl + sstart, ss, dins);
 619         } else {
 620                 if (finish)
 621                         drl = ntfs_rl_append(drl, ds, srl + sstart, ss, dins);
 622                 else
 623                         drl = ntfs_rl_split(drl, ds, srl + sstart, ss, dins);
 624         }
 625         if (!drl) {
 626                 ntfs_log_perror("Merge failed");
 627                 return drl;
 628         }
 629         free(srl);
 630         if (marker) {
 631                 ntfs_log_debug("Triggering marker code.\n");
 632                 for (ds = dend; drl[ds].length; ds++)
 633                         ;
 634                 /* We only need to care if @srl ended after @drl. */
 635                 if (drl[ds].vcn <= marker_vcn) {
 636                         int slots = 0;
 637 
 638                         if (drl[ds].vcn == marker_vcn) {
 639                                 ntfs_log_debug("Old marker = %lli, replacing with "
 640                                                 "LCN_ENOENT.\n",
 641                                                 (long long)drl[ds].lcn);
 642                                 drl[ds].lcn = (LCN)LCN_ENOENT;
 643                                 goto finished;
 644                         }
 645                         /*
 646                          * We need to create an unmapped runlist element in
 647                          * @drl or extend an existing one before adding the
 648                          * ENOENT terminator.
 649                          */
 650                         if (drl[ds].lcn == (LCN)LCN_ENOENT) {
 651                                 ds--;
 652                                 slots = 1;
 653                         }
 654                         if (drl[ds].lcn != (LCN)LCN_RL_NOT_MAPPED) {
 655                                 /* Add an unmapped runlist element. */
 656                                 if (!slots) {
 657                                         /* FIXME/TODO: We need to have the
 658                                          * extra memory already! (AIA)
 659                                          */
 660                                         drl = ntfs_rl_realloc(drl, ds, ds + 2);
 661                                         if (!drl)
 662                                                 goto critical_error;
 663                                         slots = 2;
 664                                 }
 665                                 ds++;
 666                                 /* Need to set vcn if it isn't set already. */
 667                                 if (slots != 1)
 668                                         drl[ds].vcn = drl[ds - 1].vcn +
 669                                                         drl[ds - 1].length;
 670                                 drl[ds].lcn = (LCN)LCN_RL_NOT_MAPPED;
 671                                 /* We now used up a slot. */
 672                                 slots--;
 673                         }
 674                         drl[ds].length = marker_vcn - drl[ds].vcn;
 675                         /* Finally add the ENOENT terminator. */
 676                         ds++;
 677                         if (!slots) {
 678                                 /* FIXME/TODO: We need to have the extra
 679                                  * memory already! (AIA)
 680                                  */
 681                                 drl = ntfs_rl_realloc(drl, ds, ds + 1);
 682                                 if (!drl)
 683                                         goto critical_error;
 684                         }
 685                         drl[ds].vcn = marker_vcn;
 686                         drl[ds].lcn = (LCN)LCN_ENOENT;
 687                         drl[ds].length = (s64)0;
 688                 }
 689         }
 690         }
 691 
 692 finished:
 693         /* The merge was completed successfully. */
 694         ntfs_log_debug("Merged runlist:\n");
 695         ntfs_debug_runlist_dump(drl);
 696         return drl;
 697 
 698 critical_error:
 699         /* Critical error! We cannot afford to fail here. */
 700         ntfs_log_perror("libntfs: Critical error");
 701         ntfs_log_debug("Forcing segmentation fault!\n");
 702         marker_vcn = ((runlist*)NULL)->lcn;
 703         return drl;
 704 }
 705 
 706 /**
 707  * ntfs_mapping_pairs_decompress - convert mapping pairs array to runlist
 708  * @vol:        ntfs volume on which the attribute resides
 709  * @attr:       attribute record whose mapping pairs array to decompress
 710  * @old_rl:     optional runlist in which to insert @attr's runlist
 711  *
 712  * Decompress the attribute @attr's mapping pairs array into a runlist. On
 713  * success, return the decompressed runlist.
 714  *
 715  * If @old_rl is not NULL, decompressed runlist is inserted into the
 716  * appropriate place in @old_rl and the resultant, combined runlist is
 717  * returned. The original @old_rl is deallocated.
 718  *
 719  * On error, return NULL with errno set to the error code. @old_rl is left
 720  * unmodified in that case.
 721  *
 722  * The following error codes are defined:
 723  *      ENOMEM          Not enough memory to allocate runlist array.
 724  *      EIO             Corrupt runlist.
 725  *      EINVAL          Invalid parameters were passed in.
 726  *      ERANGE          The two runlists overlap.
 727  *
 728  * FIXME: For now we take the conceptionally simplest approach of creating the
 729  * new runlist disregarding the already existing one and then splicing the
 730  * two into one, if that is possible (we check for overlap and discard the new
 731  * runlist if overlap present before returning NULL, with errno = ERANGE).
 732  */
 733 runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
 734                 const ATTR_RECORD *attr, runlist_element *old_rl)
 735 {
 736         VCN vcn;                /* Current vcn. */
 737         LCN lcn;                /* Current lcn. */
 738         s64 deltaxcn;           /* Change in [vl]cn. */
 739         runlist_element *rl;    /* The output runlist. */
 740         const u8 *buf;          /* Current position in mapping pairs array. */
 741         const u8 *attr_end;     /* End of attribute. */
 742         int err, rlsize;        /* Size of runlist buffer. */
 743         u16 rlpos;              /* Current runlist position in units of
 744                                    runlist_elements. */
 745         u8 b;                   /* Current byte offset in buf. */
 746 
 747         ntfs_log_trace("Entering for attr 0x%x.\n",
 748                         (unsigned)le32_to_cpu(attr->type));
 749         /* Make sure attr exists and is non-resident. */
 750         if (!attr || !attr->non_resident ||
 751                         sle64_to_cpu(attr->u.nonres.lowest_vcn) < (VCN)0) {
 752                 errno = EINVAL;
 753                 return NULL;
 754         }
 755         /* Start at vcn = lowest_vcn and lcn 0. */
 756         vcn = sle64_to_cpu(attr->u.nonres.lowest_vcn);
 757         lcn = 0;
 758         /* Get start of the mapping pairs array. */
 759         buf = (const u8*)attr + le16_to_cpu(attr->u.nonres.mapping_pairs_offset);
 760         attr_end = (const u8*)attr + le32_to_cpu(attr->length);
 761         if (buf < (const u8*)attr || buf > attr_end) {
 762                 ntfs_log_debug("Corrupt attribute.\n");
 763                 errno = EIO;
 764                 return NULL;
 765         }
 766         /* Current position in runlist array. */
 767         rlpos = 0;
 768         /* Allocate first 4kiB block and set current runlist size to 4kiB. */
 769         rlsize = 0x1000;
 770         rl = ntfs_malloc(rlsize);
 771         if (!rl)
 772                 return NULL;
 773         /* Insert unmapped starting element if necessary. */
 774         if (vcn) {
 775                 rl->vcn = (VCN)0;
 776                 rl->lcn = (LCN)LCN_RL_NOT_MAPPED;
 777                 rl->length = vcn;
 778                 rlpos++;
 779         }
 780         while (buf < attr_end && *buf) {
 781                 /*
 782                  * Allocate more memory if needed, including space for the
 783                  * not-mapped and terminator elements.
 784                  */
 785                 if ((int)((rlpos + 3) * sizeof(*old_rl)) > rlsize) {
 786                         runlist_element *rl2;
 787 
 788                         rlsize += 0x1000;
 789                         rl2 = realloc(rl, rlsize);
 790                         if (!rl2) {
 791                                 int eo = errno;
 792                                 free(rl);
 793                                 errno = eo;
 794                                 return NULL;
 795                         }
 796                         rl = rl2;
 797                 }
 798                 /* Enter the current vcn into the current runlist element. */
 799                 rl[rlpos].vcn = vcn;
 800                 /*
 801                  * Get the change in vcn, i.e. the run length in clusters.
 802                  * Doing it this way ensures that we signextend negative values.
 803                  * A negative run length doesn't make any sense, but hey, I
 804                  * didn't make up the NTFS specs and Windows NT4 treats the run
 805                  * length as a signed value so that's how it is...
 806                  */
 807                 b = *buf & 0xf;
 808                 if (b) {
 809                         if (buf + b > attr_end)
 810                                 goto io_error;
 811                         for (deltaxcn = (s8)buf[b--]; b; b--)
 812                                 deltaxcn = (deltaxcn << 8) + buf[b];
 813                 } else { /* The length entry is compulsory. */
 814                         ntfs_log_debug("Missing length entry in mapping pairs "
 815                                         "array.\n");
 816                         deltaxcn = (s64)-1;
 817                 }
 818                 /*
 819                  * Assume a negative length to indicate data corruption and
 820                  * hence clean-up and return NULL.
 821                  */
 822                 if (deltaxcn < 0) {
 823                         ntfs_log_debug("Invalid length in mapping pairs array.\n");
 824                         goto err_out;
 825                 }
 826                 /*
 827                  * Enter the current run length into the current runlist
 828                  * element.
 829                  */
 830                 rl[rlpos].length = deltaxcn;
 831                 /* Increment the current vcn by the current run length. */
 832                 vcn += deltaxcn;
 833                 /*
 834                  * There might be no lcn change at all, as is the case for
 835                  * sparse clusters on NTFS 3.0+, in which case we set the lcn
 836                  * to LCN_HOLE.
 837                  */
 838                 if (!(*buf & 0xf0))
 839                         rl[rlpos].lcn = (LCN)LCN_HOLE;
 840                 else {
 841                         /* Get the lcn change which really can be negative. */
 842                         u8 b2 = *buf & 0xf;
 843                         b = b2 + ((*buf >> 4) & 0xf);
 844                         if (buf + b > attr_end)
 845                                 goto io_error;
 846                         for (deltaxcn = (s8)buf[b--]; b > b2; b--)
 847                                 deltaxcn = (deltaxcn << 8) + buf[b];
 848                         /* Change the current lcn to it's new value. */
 849                         lcn += deltaxcn;
 850 #ifdef DEBUG
 851                         /*
 852                          * On NTFS 1.2-, apparently can have lcn == -1 to
 853                          * indicate a hole. But we haven't verified ourselves
 854                          * whether it is really the lcn or the deltaxcn that is
 855                          * -1. So if either is found give us a message so we
 856                          * can investigate it further!
 857                          */
 858                         if (vol->major_ver < 3) {
 859                                 if (deltaxcn == (LCN)-1)
 860                                         ntfs_log_debug("lcn delta == -1\n");
 861                                 if (lcn == (LCN)-1)
 862                                         ntfs_log_debug("lcn == -1\n");
 863                         }
 864 #endif
 865                         /* Check lcn is not below -1. */
 866                         if (lcn < (LCN)-1) {
 867                                 ntfs_log_debug("Invalid LCN < -1 in mapping pairs "
 868                                                 "array.\n");
 869                                 goto err_out;
 870                         }
 871                         /* Enter the current lcn into the runlist element. */
 872                         rl[rlpos].lcn = lcn;
 873                 }
 874                 /* Get to the next runlist element. */
 875                 rlpos++;
 876                 /* Increment the buffer position to the next mapping pair. */
 877                 buf += (*buf & 0xf) + ((*buf >> 4) & 0xf) + 1;
 878         }
 879         if (buf >= attr_end)
 880                 goto io_error;
 881         /*
 882          * If there is a highest_vcn specified, it must be equal to the final
 883          * vcn in the runlist - 1, or something has gone badly wrong.
 884          */
 885         deltaxcn = sle64_to_cpu(attr->u.nonres.highest_vcn);
 886         if (deltaxcn && vcn - 1 != deltaxcn) {
 887 mpa_err:
 888                 ntfs_log_debug("Corrupt mapping pairs array in non-resident "
 889                                 "attribute.\n");
 890                 goto err_out;
 891         }
 892         /* Setup not mapped runlist element if this is the base extent. */
 893         if (!attr->u.nonres.lowest_vcn) {
 894                 VCN max_cluster;
 895 
 896                 max_cluster = ((sle64_to_cpu(attr->u.nonres.allocated_size) +
 897                                 vol->cluster_size - 1) >>
 898                                 vol->cluster_size_bits) - 1;
 899                 /*
 900                  * A highest_vcn of zero means this is a single extent
 901                  * attribute so simply terminate the runlist with LCN_ENOENT).
 902                  */
 903                 if (deltaxcn) {
 904                         /*
 905                          * If there is a difference between the highest_vcn and
 906                          * the highest cluster, the runlist is either corrupt
 907                          * or, more likely, there are more extents following
 908                          * this one.
 909                          */
 910                         if (deltaxcn < max_cluster) {
 911                                 ntfs_log_debug("More extents to follow; deltaxcn = "
 912                                                 "0x%llx, max_cluster = 0x%llx\n",
 913                                                 (long long)deltaxcn,
 914                                                 (long long)max_cluster);
 915                                 rl[rlpos].vcn = vcn;
 916                                 vcn += rl[rlpos].length = max_cluster - deltaxcn;
 917                                 rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
 918                                 rlpos++;
 919                         } else if (deltaxcn > max_cluster) {
 920                                 ntfs_log_debug("Corrupt attribute. deltaxcn = "
 921                                                 "0x%llx, max_cluster = 0x%llx\n",
 922                                                 (long long)deltaxcn,
 923                                                 (long long)max_cluster);
 924                                 goto mpa_err;
 925                         }
 926                 }
 927                 rl[rlpos].lcn = (LCN)LCN_ENOENT;
 928         } else /* Not the base extent. There may be more extents to follow. */
 929                 rl[rlpos].lcn = (LCN)LCN_RL_NOT_MAPPED;
 930 
 931         /* Setup terminating runlist element. */
 932         rl[rlpos].vcn = vcn;
 933         rl[rlpos].length = (s64)0;
 934         /* If no existing runlist was specified, we are done. */
 935         if (!old_rl) {
 936                 ntfs_log_debug("Mapping pairs array successfully decompressed:\n");
 937                 ntfs_debug_runlist_dump(rl);
 938                 return rl;
 939         }
 940         /* Now combine the new and old runlists checking for overlaps. */
 941         old_rl = ntfs_runlists_merge(old_rl, rl);
 942         if (old_rl)
 943                 return old_rl;
 944         err = errno;
 945         free(rl);
 946         ntfs_log_debug("Failed to merge runlists.\n");
 947         errno = err;
 948         return NULL;
 949 io_error:
 950         ntfs_log_debug("Corrupt attribute.\n");
 951 err_out:
 952         free(rl);
 953         errno = EIO;
 954         return NULL;
 955 }
 956 
 957 /**
 958  * ntfs_rl_vcn_to_lcn - convert a vcn into a lcn given a runlist
 959  * @rl:         runlist to use for conversion
 960  * @vcn:        vcn to convert
 961  *
 962  * Convert the virtual cluster number @vcn of an attribute into a logical
 963  * cluster number (lcn) of a device using the runlist @rl to map vcns to their
 964  * corresponding lcns.
 965  *
 966  * Since lcns must be >= 0, we use negative return values with special meaning:
 967  *
 968  * Return value                 Meaning / Description
 969  * ==================================================
 970  *  -1 = LCN_HOLE               Hole / not allocated on disk.
 971  *  -2 = LCN_RL_NOT_MAPPED      This is part of the runlist which has not been
 972  *                              inserted into the runlist yet.
 973  *  -3 = LCN_ENOENT             There is no such vcn in the attribute.
 974  *  -4 = LCN_EINVAL             Input parameter error.
 975  */
 976 LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn)
 977 {
 978         int i;
 979 
 980         if (vcn < (VCN)0)
 981                 return (LCN)LCN_EINVAL;
 982         /*
 983          * If rl is NULL, assume that we have found an unmapped runlist. The
 984          * caller can then attempt to map it and fail appropriately if
 985          * necessary.
 986          */
 987         if (!rl)
 988                 return (LCN)LCN_RL_NOT_MAPPED;
 989 
 990         /* Catch out of lower bounds vcn. */
 991         if (vcn < rl[0].vcn)
 992                 return (LCN)LCN_ENOENT;
 993 
 994         for (i = 0; rl[i].length; i++) {
 995                 if (vcn < rl[i+1].vcn) {
 996                         if (rl[i].lcn >= (LCN)0)
 997                                 return rl[i].lcn + (vcn - rl[i].vcn);
 998                         return rl[i].lcn;
 999                 }
1000         }
1001         /*
1002          * The terminator element is setup to the correct value, i.e. one of
1003          * LCN_HOLE, LCN_RL_NOT_MAPPED, or LCN_ENOENT.
1004          */
1005         if (rl[i].lcn < (LCN)0)
1006                 return rl[i].lcn;
1007         /* Just in case... We could replace this with BUG() some day. */
1008         return (LCN)LCN_ENOENT;
1009 }
1010 
1011 /**
1012  * ntfs_rl_pread - gather read from disk
1013  * @vol:        ntfs volume to read from
1014  * @rl:         runlist specifying where to read the data from
1015  * @pos:        byte position within runlist @rl at which to begin the read
1016  * @count:      number of bytes to read
1017  * @b:          data buffer into which to read from disk
1018  *
1019  * This function will read @count bytes from the volume @vol to the data buffer
1020  * @b gathering the data as specified by the runlist @rl. The read begins at
1021  * offset @pos into the runlist @rl.
1022  *
1023  * On success, return the number of successfully read bytes. If this number is
1024  * lower than @count this means that the read reached end of file or that an
1025  * error was encountered during the read so that the read is partial. 0 means
1026  * nothing was read (also return 0 when @count is 0).
1027  *
1028  * On error and nothing has been read, return -1 with errno set appropriately
1029  * to the return code of ntfs_pread(), or to EINVAL in case of invalid
1030  * arguments.
1031  *
1032  * NOTE: If we encounter EOF while reading we return EIO because we assume that
1033  * the run list must point to valid locations within the ntfs volume.
1034  */
1035 s64 ntfs_rl_pread(const ntfs_volume *vol, const runlist_element *rl,
1036                 const s64 pos, s64 count, void *b)
1037 {
1038         s64 bytes_read, to_read, ofs, total;
1039         int err = EIO;
1040 
1041         if (!vol || !rl || pos < 0 || count < 0) {
1042                 errno = EINVAL;
1043                 return -1;
1044         }
1045         if (!count)
1046                 return count;
1047         /* Seek in @rl to the run containing @pos. */
1048         for (ofs = 0; rl->length && (ofs + (rl->length <<
1049                         vol->cluster_size_bits) <= pos); rl++)
1050                 ofs += (rl->length << vol->cluster_size_bits);
1051         /* Offset in the run at which to begin reading. */
1052         ofs = pos - ofs;
1053         for (total = 0LL; count; rl++, ofs = 0) {
1054                 if (!rl->length)
1055                         goto rl_err_out;
1056                 if (rl->lcn < (LCN)0) {
1057                         if (rl->lcn != (LCN)LCN_HOLE)
1058                                 goto rl_err_out;
1059                         /* It is a hole. Just fill buffer @b with zeroes. */
1060                         to_read = min(count, (rl->length <<
1061                                         vol->cluster_size_bits) - ofs);
1062                         memset(b, 0, to_read);
1063                         /* Update counters and proceed with next run. */
1064                         total += to_read;
1065                         count -= to_read;
1066                         b = (u8*)b + to_read;
1067                         continue;
1068                 }
1069                 /* It is a real lcn, read it from the volume. */
1070                 to_read = min(count, (rl->length << vol->cluster_size_bits) -
1071                                 ofs);
1072 retry:
1073                 bytes_read = ntfs_pread(vol->u.dev, (rl->lcn <<
1074                                 vol->cluster_size_bits) + ofs, to_read, b);
1075                 /* If everything ok, update progress counters and continue. */
1076                 if (bytes_read > 0) {
1077                         total += bytes_read;
1078                         count -= bytes_read;
1079                         b = (u8*)b + bytes_read;
1080                         continue;
1081                 }
1082                 /* If the syscall was interrupted, try again. */
1083                 if (bytes_read == (s64)-1 && errno == EINTR)
1084                         goto retry;
1085                 if (bytes_read == (s64)-1)
1086                         err = errno;
1087                 goto rl_err_out;
1088         }
1089         /* Finally, return the number of bytes read. */
1090         return total;
1091 rl_err_out:
1092         if (total)
1093                 return total;
1094         errno = err;
1095         return -1;
1096 }
1097 
1098 /**
1099  * ntfs_rl_pwrite - scatter write to disk
1100  * @vol:        ntfs volume to write to
1101  * @rl:         runlist specifying where to write the data to
1102  * @pos:        byte position within runlist @rl at which to begin the write
1103  * @count:      number of bytes to write
1104  * @b:          data buffer to write to disk
1105  *
1106  * This function will write @count bytes from data buffer @b to the volume @vol
1107  * scattering the data as specified by the runlist @rl. The write begins at
1108  * offset @pos into the runlist @rl.
1109  *
1110  * On success, return the number of successfully written bytes. If this number
1111  * is lower than @count this means that the write has been interrupted in
1112  * flight or that an error was encountered during the write so that the write
1113  * is partial. 0 means nothing was written (also return 0 when @count is 0).
1114  *
1115  * On error and nothing has been written, return -1 with errno set
1116  * appropriately to the return code of ntfs_pwrite(), or to to EINVAL in case
1117  * of invalid arguments.
1118  */
1119 s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
1120                 const s64 pos, s64 count, void *b)
1121 {
1122         s64 written, to_write, ofs, total;
1123         int err = EIO;
1124 
1125         if (!vol || !rl || pos < 0 || count < 0) {
1126                 errno = EINVAL;
1127                 return -1;
1128         }
1129         if (!count)
1130                 return count;
1131         /* Seek in @rl to the run containing @pos. */
1132         for (ofs = 0; rl->length && (ofs + (rl->length <<
1133                         vol->cluster_size_bits) <= pos); rl++)
1134                 ofs += (rl->length << vol->cluster_size_bits);
1135         /* Offset in the run at which to begin writing. */
1136         ofs = pos - ofs;
1137         for (total = 0LL; count; rl++, ofs = 0) {
1138                 if (!rl->length)
1139                         goto rl_err_out;
1140                 if (rl->lcn < (LCN)0) {
1141                         s64 t;
1142                         int cnt;
1143 
1144                         if (rl->lcn != (LCN)LCN_HOLE)
1145                                 goto rl_err_out;
1146                         /*
1147                          * It is a hole. Check if the buffer is zero in this
1148                          * region and if not abort with error.
1149                          */
1150                         to_write = min(count, (rl->length <<
1151                                         vol->cluster_size_bits) - ofs);
1152                         written = to_write / sizeof(unsigned long);
1153                         for (t = 0; t < written; t++) {
1154                                 if (((unsigned long*)b)[t])
1155                                         goto rl_err_out;
1156                         }
1157                         cnt = to_write & (sizeof(unsigned long) - 1);
1158                         if (cnt) {
1159                                 int i;
1160                                 u8 *b2;
1161 
1162                                 b2 = (u8*)b + (to_write &
1163                                                 ~(sizeof(unsigned long) - 1));
1164                                 for (i = 0; i < cnt; i++) {
1165                                         if (b2[i])
1166                                                 goto rl_err_out;
1167                                 }
1168                         }
1169                         /*
1170                          * The buffer region is zero, update progress counters
1171                          * and proceed with next run.
1172                          */
1173                         total += to_write;
1174                         count -= to_write;
1175                         b = (u8*)b + to_write;
1176                         continue;
1177                 }
1178                 /* It is a real lcn, write it to the volume. */
1179                 to_write = min(count, (rl->length << vol->cluster_size_bits) -
1180                                 ofs);
1181 retry:
1182                 if (!NVolReadOnly(vol))
1183                         written = ntfs_pwrite(vol->u.dev, (rl->lcn <<
1184                                         vol->cluster_size_bits) + ofs,
1185                                         to_write, b);
1186                 else
1187                         written = to_write;
1188                 /* If everything ok, update progress counters and continue. */
1189                 if (written > 0) {
1190                         total += written;
1191                         count -= written;
1192                         b = (u8*)b + written;
1193                         continue;
1194                 }
1195                 /* If the syscall was interrupted, try again. */
1196                 if (written == (s64)-1 && errno == EINTR)
1197                         goto retry;
1198                 if (written == (s64)-1)
1199                         err = errno;
1200                 goto rl_err_out;
1201         }
1202         /* Finally, return the number of bytes written. */
1203         return total;
1204 rl_err_out:
1205         if (total)
1206                 return total;
1207         errno = err;
1208         return -1;
1209 }
1210 
1211 /**
1212  * ntfs_rl_fill_zero - fill given region with zeroes
1213  * @vol:        ntfs volume to write to
1214  * @rl:         runlist specifying where to write zeroes to
1215  * @pos:        byte position within runlist @rl at which to begin the zeroing
1216  * @count:      number of bytes to fill with zeros
1217  *
1218  * Return 0 on success and -1 on error with errno set to the error code.
1219  */
1220 int ntfs_rl_fill_zero(const ntfs_volume *vol, const runlist *rl, s64 pos,
1221                 const s64 count)
1222 {
1223         char *buf;
1224         s64 written, size, end = pos + count;
1225         int ret = 0;
1226 
1227         ntfs_log_trace("pos %lld, count %lld\n", (long long)pos,
1228                         (long long)count);
1229 
1230         if (!vol || !rl || pos < 0 || count < 0) {
1231                 errno = EINVAL;
1232                 return -1;
1233         }
1234 
1235         buf = ntfs_calloc(NTFS_BUF_SIZE);
1236         if (!buf)
1237                 return -1;
1238 
1239         while (pos < end) {
1240                 size = min(end - pos, NTFS_BUF_SIZE);
1241                 written = ntfs_rl_pwrite(vol, rl, pos, size, buf);
1242                 if (written <= 0) {
1243                         ntfs_log_perror("Failed to zero space");
1244                         ret = -1;
1245                         break;
1246                 }
1247                 pos += written;
1248         }
1249         free(buf);
1250         return ret;
1251 }
1252 
1253 /**
1254  * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number
1255  * @n:          number for which to get the number of bytes for
1256  *
1257  * Return the number of bytes required to store @n unambiguously as
1258  * a signed number.
1259  *
1260  * This is used in the context of the mapping pairs array to determine how
1261  * many bytes will be needed in the array to store a given logical cluster
1262  * number (lcn) or a specific run length.
1263  *
1264  * Return the number of bytes written. This function cannot fail.
1265  */
1266 int ntfs_get_nr_significant_bytes(const s64 n)
1267 {
1268         s64 l = n;
1269         int i;
1270         s8 j;
1271 
1272         i = 0;
1273         do {
1274                 l >>= 8;
1275                 i++;
1276         } while (l != 0LL && l != -1LL);
1277         j = (n >> 8 * (i - 1)) & 0xff;
1278         /* If the sign bit is wrong, we need an extra byte. */
1279         if ((n < 0LL && j >= 0) || (n > 0LL && j < 0))
1280                 i++;
1281         return i;
1282 }
1283 
1284 /**
1285  * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array
1286  * @vol:        ntfs volume (needed for the ntfs version)
1287  * @rl:         runlist for which to determine the size of the mapping pairs
1288  * @start_vcn:  vcn at which to start the mapping pairs array
1289  *
1290  * Walk the runlist @rl and calculate the size in bytes of the mapping pairs
1291  * array corresponding to the runlist @rl, starting at vcn @start_vcn.  This
1292  * for example allows us to allocate a buffer of the right size when building
1293  * the mapping pairs array.
1294  *
1295  * If @rl is NULL, just return 1 (for the single terminator byte).
1296  *
1297  * Return the calculated size in bytes on success.  On error, return -1 with
1298  * errno set to the error code.  The following error codes are defined:
1299  *      EINVAL  - Run list contains unmapped elements. Make sure to only pass
1300  *                fully mapped runlists to this function.
1301  *              - @start_vcn is invalid.
1302  *      EIO     - The runlist is corrupt.
1303  */
1304 int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1305                 const runlist_element *rl, const VCN start_vcn)
1306 {
1307         LCN prev_lcn;
1308         int rls;
1309 
1310         if (start_vcn < 0) {
1311                 ntfs_log_trace("start_vcn %lld (should be >= 0)\n",
1312                                 (long long) start_vcn);
1313                 errno = EINVAL;
1314                 return -1;
1315         }
1316         if (!rl) {
1317                 if (start_vcn) {
1318                         ntfs_log_trace("rl NULL, start_vcn %lld (should be > 0)\n",
1319                                         (long long) start_vcn);
1320                         errno = EINVAL;
1321                         return -1;
1322                 }
1323                 return 1;
1324         }
1325         /* Skip to runlist element containing @start_vcn. */
1326         while (rl->length && start_vcn >= rl[1].vcn)
1327                 rl++;
1328         if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) {
1329                 errno = EINVAL;
1330                 return -1;
1331         }
1332         prev_lcn = 0;
1333         /* Always need the terminating zero byte. */
1334         rls = 1;
1335         /* Do the first partial run if present. */
1336         if (start_vcn > rl->vcn) {
1337                 s64 delta;
1338 
1339                 /* We know rl->length != 0 already. */
1340                 if (rl->length < 0 || rl->lcn < LCN_HOLE)
1341                         goto err_out;
1342                 delta = start_vcn - rl->vcn;
1343                 /* Header byte + length. */
1344                 rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta);
1345                 /*
1346                  * If the logical cluster number (lcn) denotes a hole and we
1347                  * are on NTFS 3.0+, we don't store it at all, i.e. we need
1348                  * zero space. On earlier NTFS versions we just store the lcn.
1349                  * Note: this assumes that on NTFS 1.2-, holes are stored with
1350                  * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
1351                  */
1352                 if (rl->lcn >= 0 || vol->major_ver < 3) {
1353                         prev_lcn = rl->lcn;
1354                         if (rl->lcn >= 0)
1355                                 prev_lcn += delta;
1356                         /* Change in lcn. */
1357                         rls += ntfs_get_nr_significant_bytes(prev_lcn);
1358                 }
1359                 /* Go to next runlist element. */
1360                 rl++;
1361         }
1362         /* Do the full runs. */
1363         for (; rl->length; rl++) {
1364                 if (rl->length < 0 || rl->lcn < LCN_HOLE)
1365                         goto err_out;
1366                 /* Header byte + length. */
1367                 rls += 1 + ntfs_get_nr_significant_bytes(rl->length);
1368                 /*
1369                  * If the logical cluster number (lcn) denotes a hole and we
1370                  * are on NTFS 3.0+, we don't store it at all, i.e. we need
1371                  * zero space. On earlier NTFS versions we just store the lcn.
1372                  * Note: this assumes that on NTFS 1.2-, holes are stored with
1373                  * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
1374                  */
1375                 if (rl->lcn >= 0 || vol->major_ver < 3) {
1376                         /* Change in lcn. */
1377                         rls += ntfs_get_nr_significant_bytes(rl->lcn -
1378                                         prev_lcn);
1379                         prev_lcn = rl->lcn;
1380                 }
1381         }
1382         return rls;
1383 err_out:
1384         if (rl->lcn == LCN_RL_NOT_MAPPED)
1385                 errno = EINVAL;
1386         else
1387                 errno = EIO;
1388         return -1;
1389 }
1390 
1391 /**
1392  * ntfs_write_significant_bytes - write the significant bytes of a number
1393  * @dst:        destination buffer to write to
1394  * @dst_max:    pointer to last byte of destination buffer for bounds checking
1395  * @n:          number whose significant bytes to write
1396  *
1397  * Store in @dst, the minimum bytes of the number @n which are required to
1398  * identify @n unambiguously as a signed number, taking care not to exceed
1399  * @dest_max, the maximum position within @dst to which we are allowed to
1400  * write.
1401  *
1402  * This is used when building the mapping pairs array of a runlist to compress
1403  * a given logical cluster number (lcn) or a specific run length to the minimum
1404  * size possible.
1405  *
1406  * Return the number of bytes written on success. On error, i.e. the
1407  * destination buffer @dst is too small, return -1 with errno set ENOSPC.
1408  */
1409 int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, const s64 n)
1410 {
1411         s64 l = n;
1412         int i;
1413         s8 j;
1414 
1415         i = 0;
1416         do {
1417                 if (dst > dst_max)
1418                         goto err_out;
1419                 *dst++ = l & 0xffLL;
1420                 l >>= 8;
1421                 i++;
1422         } while (l != 0LL && l != -1LL);
1423         j = (n >> 8 * (i - 1)) & 0xff;
1424         /* If the sign bit is wrong, we need an extra byte. */
1425         if (n < 0LL && j >= 0) {
1426                 if (dst > dst_max)
1427                         goto err_out;
1428                 i++;
1429                 *dst = (u8)-1;
1430         } else if (n > 0LL && j < 0) {
1431                 if (dst > dst_max)
1432                         goto err_out;
1433                 i++;
1434                 *dst = 0;
1435         }
1436         return i;
1437 err_out:
1438         errno = ENOSPC;
1439         return -1;
1440 }
1441 
1442 /**
1443  * ntfs_mapping_pairs_build - build the mapping pairs array from a runlist
1444  * @vol:        ntfs volume (needed for the ntfs version)
1445  * @dst:        destination buffer to which to write the mapping pairs array
1446  * @dst_len:    size of destination buffer @dst in bytes
1447  * @rl:         runlist for which to build the mapping pairs array
1448  * @start_vcn:  vcn at which to start the mapping pairs array
1449  * @stop_vcn:   first vcn outside destination buffer on success or ENOSPC error
1450  *
1451  * Create the mapping pairs array from the runlist @rl, starting at vcn
1452  * @start_vcn and save the array in @dst.  @dst_len is the size of @dst in
1453  * bytes and it should be at least equal to the value obtained by calling
1454  * ntfs_get_size_for_mapping_pairs().
1455  *
1456  * If @rl is NULL, just write a single terminator byte to @dst.
1457  *
1458  * On success or ENOSPC error, if @stop_vcn is not NULL, *@stop_vcn is set to
1459  * the first vcn outside the destination buffer. Note that on error @dst has
1460  * been filled with all the mapping pairs that will fit, thus it can be treated
1461  * as partial success, in that a new attribute extent needs to be created or the
1462  * next extent has to be used and the mapping pairs build has to be continued
1463  * with @start_vcn set to *@stop_vcn.
1464  *
1465  * Return 0 on success.  On error, return -1 with errno set to the error code.
1466  * The following error codes are defined:
1467  *      EINVAL  - Run list contains unmapped elements. Make sure to only pass
1468  *                fully mapped runlists to this function.
1469  *              - @start_vcn is invalid.
1470  *      EIO     - The runlist is corrupt.
1471  *      ENOSPC  - The destination buffer is too small.
1472  */
1473 int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
1474                 const int dst_len, const runlist_element *rl,
1475                 const VCN start_vcn, VCN *const stop_vcn)
1476 {
1477         LCN prev_lcn;
1478         u8 *dst_max, *dst_next;
1479         s8 len_len, lcn_len;
1480 
1481         if (start_vcn < 0)
1482                 goto val_err;
1483         if (!rl) {
1484                 if (start_vcn)
1485                         goto val_err;
1486                 if (stop_vcn)
1487                         *stop_vcn = 0;
1488                 if (dst_len < 1) {
1489                         errno = ENOSPC;
1490                         return -1;
1491                 }
1492                 /* Terminator byte. */
1493                 *dst = 0;
1494                 return 0;
1495         }
1496         /* Skip to runlist element containing @start_vcn. */
1497         while (rl->length && start_vcn >= rl[1].vcn)
1498                 rl++;
1499         if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn)
1500                 goto val_err;
1501         /*
1502          * @dst_max is used for bounds checking in
1503          * ntfs_write_significant_bytes().
1504          */
1505         dst_max = dst + dst_len - 1;
1506         prev_lcn = 0;
1507         /* Do the first partial run if present. */
1508         if (start_vcn > rl->vcn) {
1509                 s64 delta;
1510 
1511                 /* We know rl->length != 0 already. */
1512                 if (rl->length < 0 || rl->lcn < LCN_HOLE)
1513                         goto err_out;
1514                 delta = start_vcn - rl->vcn;
1515                 /* Write length. */
1516                 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1517                                 rl->length - delta);
1518                 if (len_len < 0)
1519                         goto size_err;
1520                 /*
1521                  * If the logical cluster number (lcn) denotes a hole and we
1522                  * are on NTFS 3.0+, we don't store it at all, i.e. we need
1523                  * zero space. On earlier NTFS versions we just write the lcn
1524                  * change.  FIXME: Do we need to write the lcn change or just
1525                  * the lcn in that case?  Not sure as I have never seen this
1526                  * case on NT4. - We assume that we just need to write the lcn
1527                  * change until someone tells us otherwise... (AIA)
1528                  */
1529                 if (rl->lcn >= 0 || vol->major_ver < 3) {
1530                         prev_lcn = rl->lcn;
1531                         if (rl->lcn >= 0)
1532                                 prev_lcn += delta;
1533                         /* Write change in lcn. */
1534                         lcn_len = ntfs_write_significant_bytes(dst + 1 +
1535                                         len_len, dst_max, prev_lcn);
1536                         if (lcn_len < 0)
1537                                 goto size_err;
1538                 } else
1539                         lcn_len = 0;
1540                 dst_next = dst + len_len + lcn_len + 1;
1541                 if (dst_next > dst_max)
1542                         goto size_err;
1543                 /* Update header byte. */
1544                 *dst = lcn_len << 4 | len_len;
1545                 /* Position at next mapping pairs array element. */
1546                 dst = dst_next;
1547                 /* Go to next runlist element. */
1548                 rl++;
1549         }
1550         /* Do the full runs. */
1551         for (; rl->length; rl++) {
1552                 if (rl->length < 0 || rl->lcn < LCN_HOLE)
1553                         goto err_out;
1554                 /* Write length. */
1555                 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1556                                 rl->length);
1557                 if (len_len < 0)
1558                         goto size_err;
1559                 /*
1560                  * If the logical cluster number (lcn) denotes a hole and we
1561                  * are on NTFS 3.0+, we don't store it at all, i.e. we need
1562                  * zero space. On earlier NTFS versions we just write the lcn
1563                  * change. FIXME: Do we need to write the lcn change or just
1564                  * the lcn in that case? Not sure as I have never seen this
1565                  * case on NT4. - We assume that we just need to write the lcn
1566                  * change until someone tells us otherwise... (AIA)
1567                  */
1568                 if (rl->lcn >= 0 || vol->major_ver < 3) {
1569                         /* Write change in lcn. */
1570                         lcn_len = ntfs_write_significant_bytes(dst + 1 +
1571                                         len_len, dst_max, rl->lcn - prev_lcn);
1572                         if (lcn_len < 0)
1573                                 goto size_err;
1574                         prev_lcn = rl->lcn;
1575                 } else
1576                         lcn_len = 0;
1577                 dst_next = dst + len_len + lcn_len + 1;
1578                 if (dst_next > dst_max)
1579                         goto size_err;
1580                 /* Update header byte. */
1581                 *dst = lcn_len << 4 | len_len;
1582                 /* Position at next mapping pairs array element. */
1583                 dst += 1 + len_len + lcn_len;
1584         }
1585         /* Set stop vcn. */
1586         if (stop_vcn)
1587                 *stop_vcn = rl->vcn;
1588         /* Add terminator byte. */
1589         *dst = 0;
1590         return 0;
1591 size_err:
1592         /* Set stop vcn. */
1593         if (stop_vcn)
1594                 *stop_vcn = rl->vcn;
1595         /* Add terminator byte. */
1596         *dst = 0;
1597         errno = ENOSPC;
1598         return -1;
1599 val_err:
1600         errno = EINVAL;
1601         return -1;
1602 err_out:
1603         if (rl->lcn == LCN_RL_NOT_MAPPED)
1604                 errno = EINVAL;
1605         else
1606                 errno = EIO;
1607         return -1;
1608 }
1609 
1610 /**
1611  * ntfs_rl_truncate - truncate a runlist starting at a specified vcn
1612  * @arl:        address of runlist to truncate
1613  * @start_vcn:  first vcn which should be cut off
1614  *
1615  * Truncate the runlist *@arl starting at vcn @start_vcn as well as the memory
1616  * buffer holding the runlist.
1617  *
1618  * Return 0 on success and -1 on error with errno set to the error code.
1619  *
1620  * NOTE: @arl is the address of the runlist. We need the address so we can
1621  * modify the pointer to the runlist with the new, reallocated memory buffer.
1622  */
1623 int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
1624 {
1625         runlist *rl;
1626 
1627         if (!arl || !*arl) {
1628                 errno = EINVAL;
1629                 ntfs_log_perror("rl_truncate error: arl: %p *arl: %p", arl, *arl);
1630                 return -1;
1631         }
1632 
1633         rl = *arl;
1634 
1635         if (start_vcn < rl->vcn) {
1636                 errno = EINVAL;
1637                 ntfs_log_perror("Start_vcn lies outside front of runlist");
1638                 return -1;
1639         }
1640 
1641         /* Find the starting vcn in the run list. */
1642         while (rl->length) {
1643                 if (start_vcn < rl[1].vcn)
1644                         break;
1645                 rl++;
1646         }
1647 
1648         if (!rl->length) {
1649                 errno = EIO;
1650                 ntfs_log_trace("Truncating already truncated runlist?\n");
1651                 return -1;
1652         }
1653 
1654         /* Truncate the run. */
1655         rl->length = start_vcn - rl->vcn;
1656 
1657         /*
1658          * If a run was partially truncated, make the following runlist
1659          * element a terminator instead of the truncated runlist
1660          * element itself.
1661          */
1662         if (rl->length) {
1663                 ++rl;
1664                 rl->vcn = start_vcn;
1665                 rl->length = 0;
1666         }
1667         rl->lcn = (LCN)LCN_ENOENT;
1668         return 0;
1669 }
1670 
1671 /**
1672  * ntfs_rl_sparse - check whether runlist have sparse regions or not.
1673  * @rl:         runlist to check
1674  *
1675  * This function just skips not mapped regions assuming they are not sparse,
1676  * so you need to ensure that runlist is fully mapped if you want perform full
1677  * check.
1678  *
1679  * Return 1 if have, 0 if not, -1 on error with errno set to the error code.
1680  */
1681 int ntfs_rl_sparse(runlist *rl)
1682 {
1683         runlist *rlc;
1684 
1685         if (!rl) {
1686                 ntfs_log_trace("Invalid argument passed.\n");
1687                 errno = EINVAL;
1688                 return -1;
1689         }
1690 
1691         for (rlc = rl; rlc->length; rlc++) {
1692                 if (rlc->lcn < 0) {
1693                         if (rlc->lcn == LCN_RL_NOT_MAPPED)
1694                                 continue;
1695                         if (rlc->lcn != LCN_HOLE) {
1696                                 ntfs_log_trace("Bad runlist.\n");
1697                                 errno = EIO;
1698                                 return -1;
1699                         }
1700                         return 1;
1701                 }
1702         }
1703         return 0;
1704 }
1705 
1706 /**
1707  * ntfs_rl_get_compressed_size - calculate length of non sparse regions
1708  * @vol:        ntfs volume (need for cluster size)
1709  * @rl:         runlist to calculate for
1710  *
1711  * Return compressed size or -1 on error with errno set to the error code.
1712  */
1713 s64 ntfs_rl_get_compressed_size(ntfs_volume *vol, runlist *rl)
1714 {
1715         runlist *rlc;
1716         s64 ret = 0;
1717 
1718         if (!rl) {
1719                 ntfs_log_trace("Invalid argument passed.\n");
1720                 errno = EINVAL;
1721                 return -1;
1722         }
1723 
1724         for (rlc = rl; rlc->length; rlc++) {
1725                 if (rlc->lcn < 0) {
1726                         if (rlc->lcn != LCN_HOLE) {
1727                                 ntfs_log_trace("Received unmapped runlist.\n");
1728                                 errno = EINVAL;
1729                                 return -1;
1730                         }
1731                 } else
1732                         ret += rlc->length;
1733         }
1734         return ret << vol->cluster_size_bits;
1735 }
1736 
1737 
1738 #ifdef NTFS_TEST
1739 /**
1740  * test_rl_helper
1741  */
1742 #define MKRL(R,V,L,S)                           \
1743         (R)->vcn = V;                                \
1744         (R)->lcn = L;                                \
1745         (R)->length = S;
1746 /*
1747 }
1748 */
1749 /**
1750  * test_rl_dump_runlist - Runlist test: Display the contents of a runlist
1751  * @rl:
1752  *
1753  * Description...
1754  *
1755  * Returns:
1756  */
1757 static void test_rl_dump_runlist(const runlist_element *rl)
1758 {
1759         int abbr = 0;   /* abbreviate long lists */
1760         int len = 0;
1761         int i;
1762         const char *lcn_str[5] = { "HOLE", "NOTMAP", "ENOENT", "XXXX" };
1763 
1764         if (!rl) {
1765                 printf("    Run list not present.\n");
1766                 return;
1767         }
1768 
1769         if (abbr)
1770                 for (len = 0; rl[len].length; len++) ;
1771 
1772         printf("     VCN      LCN      len\n");
1773         for (i = 0; ; i++, rl++) {
1774                 LCN lcn = rl->lcn;
1775 
1776                 if ((abbr) && (len > 20)) {
1777                         if (i == 4)
1778                                 printf("     ...\n");
1779                         if ((i > 3) && (i < (len - 3)))
1780                                 continue;
1781                 }
1782 
1783                 if (lcn < (LCN)0) {
1784                         int ind = -lcn - 1;
1785 
1786                         if (ind > -LCN_ENOENT - 1)
1787                                 ind = 3;
1788                         printf("%8lld %8s %8lld\n",
1789                                 rl->vcn, lcn_str[ind], rl->length);
1790                 } else
1791                         printf("%8lld %8lld %8lld\n",
1792                                 rl->vcn, rl->lcn, rl->length);
1793                 if (!rl->length)
1794                         break;
1795         }
1796         if ((abbr) && (len > 20))
1797                 printf("    (%d entries)\n", len+1);
1798         printf("\n");
1799 }
1800 
1801 /**
1802  * test_rl_runlists_merge - Runlist test: Merge two runlists
1803  * @drl:
1804  * @srl:
1805  *
1806  * Description...
1807  *
1808  * Returns:
1809  */
1810 static runlist_element * test_rl_runlists_merge(runlist_element *drl, runlist_element *srl)
1811 {
1812         runlist_element *res = NULL;
1813 
1814         printf("dst:\n");
1815         test_rl_dump_runlist(drl);
1816         printf("src:\n");
1817         test_rl_dump_runlist(srl);
1818 
1819         res = ntfs_runlists_merge(drl, srl);
1820 
1821         printf("res:\n");
1822         test_rl_dump_runlist(res);
1823 
1824         return res;
1825 }
1826 
1827 /**
1828  * test_rl_read_buffer - Runlist test: Read a file containing a runlist
1829  * @file:
1830  * @buf:
1831  * @bufsize:
1832  *
1833  * Description...
1834  *
1835  * Returns:
1836  */
1837 static int test_rl_read_buffer(const char *file, u8 *buf, int bufsize)
1838 {
1839         FILE *fptr;
1840 
1841         fptr = fopen(file, "r");
1842         if (!fptr) {
1843                 printf("open %s\n", file);
1844                 return 0;
1845         }
1846 
1847         if (fread(buf, bufsize, 1, fptr) == 99) {
1848                 printf("read %s\n", file);
1849                 return 0;
1850         }
1851 
1852         fclose(fptr);
1853         return 1;
1854 }
1855 
1856 /**
1857  * test_rl_pure_src - Runlist test: Complicate the simple tests a little
1858  * @contig:
1859  * @multi:
1860  * @vcn:
1861  * @len:
1862  *
1863  * Description...
1864  *
1865  * Returns:
1866  */
1867 static runlist_element * test_rl_pure_src(BOOL contig, BOOL multi, int vcn, int len)
1868 {
1869         runlist_element *result;
1870         int fudge;
1871 
1872         if (contig)
1873                 fudge = 0;
1874         else
1875                 fudge = 999;
1876 
1877         result = ntfs_malloc(4096);
1878         if (!result)
1879                 return NULL;
1880 
1881         if (multi) {
1882                 MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4)
1883                 MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4)
1884                 MKRL(result+2, vcn + (2*len/4), fudge + vcn + 1000 + (2*len/4), len / 4)
1885                 MKRL(result+3, vcn + (3*len/4), fudge + vcn + 1000 + (3*len/4), len / 4)
1886                 MKRL(result+4, vcn + (4*len/4), LCN_RL_NOT_MAPPED,              0)
1887         } else {
1888                 MKRL(result+0, vcn,       fudge + vcn + 1000, len)
1889                 MKRL(result+1, vcn + len, LCN_RL_NOT_MAPPED,  0)
1890         }
1891         return result;
1892 }
1893 
1894 /**
1895  * test_rl_pure_test - Runlist test: Perform tests using simple runlists
1896  * @test:
1897  * @contig:
1898  * @multi:
1899  * @vcn:
1900  * @len:
1901  * @file:
1902  * @size:
1903  *
1904  * Description...
1905  *
1906  * Returns:
1907  */
1908 static void test_rl_pure_test(int test, BOOL contig, BOOL multi, int vcn, int len, runlist_element *file, int size)
1909 {
1910         runlist_element *src;
1911         runlist_element *dst;
1912         runlist_element *res;
1913 
1914         src = test_rl_pure_src(contig, multi, vcn, len);
1915         dst = malloc(4096);
1916 
1917         memcpy(dst, file, size);
1918 
1919         printf("Test %2d ----------\n", test);
1920         res = test_rl_runlists_merge(dst, src);
1921 
1922         free(res);
1923 }
1924 
1925 /**
1926  * test_rl_pure - Runlist test: Create tests using simple runlists
1927  * @contig:
1928  * @multi:
1929  *
1930  * Description...
1931  *
1932  * Returns:
1933  */
1934 static void test_rl_pure(char *contig, char *multi)
1935 {
1936                 /* VCN,  LCN, len */
1937         static runlist_element file1[] = {
1938                 {    0,   -1, 100 },    /* HOLE */
1939                 {  100, 1100, 100 },    /* DATA */
1940                 {  200,   -1, 100 },    /* HOLE */
1941                 {  300, 1300, 100 },    /* DATA */
1942                 {  400,   -1, 100 },    /* HOLE */
1943                 {  500,   -3,   0 }     /* NOENT */
1944         };
1945         static runlist_element file2[] = {
1946                 {    0, 1000, 100 },    /* DATA */
1947                 {  100,   -1, 100 },    /* HOLE */
1948                 {  200,   -3,   0 }     /* NOENT */
1949         };
1950         static runlist_element file3[] = {
1951                 {    0, 1000, 100 },    /* DATA */
1952                 {  100,   -3,   0 }     /* NOENT */
1953         };
1954         static runlist_element file4[] = {
1955                 {    0,   -3,   0 }     /* NOENT */
1956         };
1957         static runlist_element file5[] = {
1958                 {    0,   -2, 100 },    /* NOTMAP */
1959                 {  100, 1100, 100 },    /* DATA */
1960                 {  200,   -2, 100 },    /* NOTMAP */
1961                 {  300, 1300, 100 },    /* DATA */
1962                 {  400,   -2, 100 },    /* NOTMAP */
1963                 {  500,   -3,   0 }     /* NOENT */
1964         };
1965         static runlist_element file6[] = {
1966                 {    0, 1000, 100 },    /* DATA */
1967                 {  100,   -2, 100 },    /* NOTMAP */
1968                 {  200,   -3,   0 }     /* NOENT */
1969         };
1970         BOOL c, m;
1971 
1972         if (strcmp(contig, "contig") == 0)
1973                 c = TRUE;
1974         else if (strcmp(contig, "noncontig") == 0)
1975                 c = FALSE;
1976         else {
1977                 printf("rl pure [contig|noncontig] [single|multi]\n");
1978                 return;
1979         }
1980         if (strcmp(multi, "multi") == 0)
1981                 m = TRUE;
1982         else if (strcmp(multi, "single") == 0)
1983                 m = FALSE;
1984         else {
1985                 printf("rl pure [contig|noncontig] [single|multi]\n");
1986                 return;
1987         }
1988 
1989         test_rl_pure_test(1,  c, m,   0,  40, file1, sizeof(file1));
1990         test_rl_pure_test(2,  c, m,  40,  40, file1, sizeof(file1));
1991         test_rl_pure_test(3,  c, m,  60,  40, file1, sizeof(file1));
1992         test_rl_pure_test(4,  c, m,   0, 100, file1, sizeof(file1));
1993         test_rl_pure_test(5,  c, m, 200,  40, file1, sizeof(file1));
1994         test_rl_pure_test(6,  c, m, 240,  40, file1, sizeof(file1));
1995         test_rl_pure_test(7,  c, m, 260,  40, file1, sizeof(file1));
1996         test_rl_pure_test(8,  c, m, 200, 100, file1, sizeof(file1));
1997         test_rl_pure_test(9,  c, m, 400,  40, file1, sizeof(file1));
1998         test_rl_pure_test(10, c, m, 440,  40, file1, sizeof(file1));
1999         test_rl_pure_test(11, c, m, 460,  40, file1, sizeof(file1));
2000         test_rl_pure_test(12, c, m, 400, 100, file1, sizeof(file1));
2001         test_rl_pure_test(13, c, m, 160, 100, file2, sizeof(file2));
2002         test_rl_pure_test(14, c, m, 100, 140, file2, sizeof(file2));
2003         test_rl_pure_test(15, c, m, 200,  40, file2, sizeof(file2));
2004         test_rl_pure_test(16, c, m, 240,  40, file2, sizeof(file2));
2005         test_rl_pure_test(17, c, m, 100,  40, file3, sizeof(file3));
2006         test_rl_pure_test(18, c, m, 140,  40, file3, sizeof(file3));
2007         test_rl_pure_test(19, c, m,   0,  40, file4, sizeof(file4));
2008         test_rl_pure_test(20, c, m,  40,  40, file4, sizeof(file4));
2009         test_rl_pure_test(21, c, m,   0,  40, file5, sizeof(file5));
2010         test_rl_pure_test(22, c, m,  40,  40, file5, sizeof(file5));
2011         test_rl_pure_test(23, c, m,  60,  40, file5, sizeof(file5));
2012         test_rl_pure_test(24, c, m,   0, 100, file5, sizeof(file5));
2013         test_rl_pure_test(25, c, m, 200,  40, file5, sizeof(file5));
2014         test_rl_pure_test(26, c, m, 240,  40, file5, sizeof(file5));
2015         test_rl_pure_test(27, c, m, 260,  40, file5, sizeof(file5));
2016         test_rl_pure_test(28, c, m, 200, 100, file5, sizeof(file5));
2017         test_rl_pure_test(29, c, m, 400,  40, file5, sizeof(file5));
2018         test_rl_pure_test(30, c, m, 440,  40, file5, sizeof(file5));
2019         test_rl_pure_test(31, c, m, 460,  40, file5, sizeof(file5));
2020         test_rl_pure_test(32, c, m, 400, 100, file5, sizeof(file5));
2021         test_rl_pure_test(33, c, m, 160, 100, file6, sizeof(file6));
2022         test_rl_pure_test(34, c, m, 100, 140, file6, sizeof(file6));
2023 }
2024 
2025 /**
2026  * test_rl_zero - Runlist test: Merge a zero-length runlist
2027  *
2028  * Description...
2029  *
2030  * Returns:
2031  */
2032 static void test_rl_zero(void)
2033 {
2034         runlist_element *jim = NULL;
2035         runlist_element *bob = NULL;
2036 
2037         bob = calloc(3, sizeof(runlist_element));
2038         if (!bob)
2039                 return;
2040 
2041         MKRL(bob+0, 10, 99, 5)
2042         MKRL(bob+1, 15, LCN_RL_NOT_MAPPED, 0)
2043 
2044         jim = test_rl_runlists_merge(jim, bob);
2045         if (!jim)
2046                 return;
2047 
2048         free(jim);
2049 }
2050 
2051 /**
2052  * test_rl_frag_combine - Runlist test: Perform tests using fragmented files
2053  * @vol:
2054  * @attr1:
2055  * @attr2:
2056  * @attr3:
2057  *
2058  * Description...
2059  *
2060  * Returns:
2061  */
2062 static void test_rl_frag_combine(ntfs_volume *vol, ATTR_RECORD *attr1, ATTR_RECORD *attr2, ATTR_RECORD *attr3)
2063 {
2064         runlist_element *run1;
2065         runlist_element *run2;
2066         runlist_element *run3;
2067 
2068         run1 = ntfs_mapping_pairs_decompress(vol, attr1, NULL);
2069         if (!run1)
2070                 return;
2071 
2072         run2 = ntfs_mapping_pairs_decompress(vol, attr2, NULL);
2073         if (!run2)
2074                 return;
2075 
2076         run1 = test_rl_runlists_merge(run1, run2);
2077 
2078         run3 = ntfs_mapping_pairs_decompress(vol, attr3, NULL);
2079         if (!run3)
2080                 return;
2081 
2082         run1 = test_rl_runlists_merge(run1, run3);
2083 
2084         free(run1);
2085 }
2086 
2087 /**
2088  * test_rl_frag - Runlist test: Create tests using very fragmented files
2089  * @test:
2090  *
2091  * Description...
2092  *
2093  * Returns:
2094  */
2095 static void test_rl_frag(char *test)
2096 {
2097         ntfs_volume vol;
2098         ATTR_RECORD *attr1 = ntfs_malloc(1024);
2099         ATTR_RECORD *attr2 = ntfs_malloc(1024);
2100         ATTR_RECORD *attr3 = ntfs_malloc(1024);
2101 
2102         if (!attr1 || !attr2 || !attr3)
2103                 goto out;
2104 
2105         vol.sb = NULL;
2106         vol.sector_size_bits = 9;
2107         vol.cluster_size = 2048;
2108         vol.cluster_size_bits = 11;
2109         vol.major_ver = 3;
2110 
2111         if (!test_rl_read_buffer("runlist-data/attr1.bin", (u8*) attr1, 1024))
2112                 goto out;
2113         if (!test_rl_read_buffer("runlist-data/attr2.bin", (u8*) attr2, 1024))
2114                 goto out;
2115         if (!test_rl_read_buffer("runlist-data/attr3.bin", (u8*) attr3, 1024))
2116                 goto out;
2117 
2118         if      (strcmp(test, "123") == 0)  test_rl_frag_combine(&vol, attr1, attr2, attr3);
2119         else if (strcmp(test, "132") == 0)  test_rl_frag_combine(&vol, attr1, attr3, attr2);
2120         else if (strcmp(test, "213") == 0)  test_rl_frag_combine(&vol, attr2, attr1, attr3);
2121         else if (strcmp(test, "231") == 0)  test_rl_frag_combine(&vol, attr2, attr3, attr1);
2122         else if (strcmp(test, "312") == 0)  test_rl_frag_combine(&vol, attr3, attr1, attr2);
2123         else if (strcmp(test, "321") == 0)  test_rl_frag_combine(&vol, attr3, attr2, attr1);
2124         else
2125                 printf("Frag: No such test '%s'\n", test);
2126 
2127 out:
2128         free(attr1);
2129         free(attr2);
2130         free(attr3);
2131 }
2132 
2133 /**
2134  * test_rl_main - Runlist test: Program start (main)
2135  * @argc:
2136  * @argv:
2137  *
2138  * Description...
2139  *
2140  * Returns:
2141  */
2142 int test_rl_main(int argc, char *argv[])
2143 {
2144         if      ((argc == 2) && (strcmp(argv[1], "zero") == 0)) test_rl_zero();
2145         else if ((argc == 3) && (strcmp(argv[1], "frag") == 0)) test_rl_frag(argv[2]);
2146         else if ((argc == 4) && (strcmp(argv[1], "pure") == 0)) test_rl_pure(argv[2], argv[3]);
2147         else
2148                 printf("rl [zero|frag|pure] {args}\n");
2149 
2150         return 0;
2151 }
2152 
2153 #endif
2154