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