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