1 /** 2 * index.c - NTFS index handling. Originated from the Linux-NTFS project. 3 * 4 * Copyright (c) 2004-2005 Anton Altaparmakov 5 * Copyright (c) 2004-2005 Richard Russon 6 * Copyright (c) 2005-2006 Yura Pakhuchiy 7 * Copyright (c) 2005-2008 Szabolcs Szakacsits 8 * Copyright (c) 2007-2021 Jean-Pierre Andre 9 * 10 * This program/include file is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as published 12 * by the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program/include file is distributed in the hope that it will be 16 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 17 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program (in the main directory of the NTFS-3G 22 * distribution in the file COPYING); if not, write to the Free Software 23 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 */ 25 26 #ifdef HAVE_CONFIG_H 27 #include "config.h" 28 #endif 29 30 #ifdef HAVE_STDLIB_H 31 #include <stdlib.h> 32 #endif 33 #ifdef HAVE_STRING_H 34 #include <string.h> 35 #endif 36 #ifdef HAVE_ERRNO_H 37 #include <errno.h> 38 #endif 39 40 #include "attrib.h" 41 #include "debug.h" 42 #include "index.h" 43 #include "collate.h" 44 #include "mst.h" 45 #include "dir.h" 46 #include "logging.h" 47 #include "bitmap.h" 48 #include "reparse.h" 49 #include "misc.h" 50 51 /** 52 * ntfs_index_entry_mark_dirty - mark an index entry dirty 53 * @ictx: ntfs index context describing the index entry 54 * 55 * Mark the index entry described by the index entry context @ictx dirty. 56 * 57 * If the index entry is in the index root attribute, simply mark the inode 58 * containing the index root attribute dirty. This ensures the mftrecord, and 59 * hence the index root attribute, will be written out to disk later. 60 * 61 * If the index entry is in an index block belonging to the index allocation 62 * attribute, set ib_dirty to TRUE, thus index block will be updated during 63 * ntfs_index_ctx_put. 64 */ 65 void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx) 66 { 67 if (ictx->is_in_root) 68 ntfs_inode_mark_dirty(ictx->actx->ntfs_ino); 69 else 70 ictx->ib_dirty = TRUE; 71 } 72 73 static s64 ntfs_ib_vcn_to_pos(ntfs_index_context *icx, VCN vcn) 74 { 75 return vcn << icx->vcn_size_bits; 76 } 77 78 static VCN ntfs_ib_pos_to_vcn(ntfs_index_context *icx, s64 pos) 79 { 80 return pos >> icx->vcn_size_bits; 81 } 82 83 static int ntfs_ib_write(ntfs_index_context *icx, INDEX_BLOCK *ib) 84 { 85 s64 ret, vcn = sle64_to_cpu(ib->index_block_vcn); 86 87 ntfs_log_trace("vcn: %lld\n", (long long)vcn); 88 89 ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn), 90 1, icx->block_size, ib); 91 if (ret != 1) { 92 ntfs_log_perror("Failed to write index block %lld, inode %llu", 93 (long long)vcn, (unsigned long long)icx->ni->mft_no); 94 return STATUS_ERROR; 95 } 96 97 return STATUS_OK; 98 } 99 100 static int ntfs_icx_ib_write(ntfs_index_context *icx) 101 { 102 if (ntfs_ib_write(icx, icx->ib)) 103 return STATUS_ERROR; 104 105 icx->ib_dirty = FALSE; 106 107 return STATUS_OK; 108 } 109 110 /** 111 * ntfs_index_ctx_get - allocate and initialize a new index context 112 * @ni: ntfs inode with which to initialize the context 113 * @name: name of the which context describes 114 * @name_len: length of the index name 115 * 116 * Allocate a new index context, initialize it with @ni and return it. 117 * Return NULL if allocation failed. 118 */ 119 ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, 120 ntfschar *name, u32 name_len) 121 { 122 ntfs_index_context *icx; 123 124 ntfs_log_trace("Entering\n"); 125 126 if (!ni) { 127 errno = EINVAL; 128 return NULL; 129 } 130 if (ni->nr_extents == -1) 131 ni = ni->base_ni; 132 icx = ntfs_calloc(sizeof(ntfs_index_context)); 133 if (icx) 134 *icx = (ntfs_index_context) { 135 .ni = ni, 136 .name = name, 137 .name_len = name_len, 138 }; 139 return icx; 140 } 141 142 static void ntfs_index_ctx_free(ntfs_index_context *icx) 143 { 144 ntfs_log_trace("Entering\n"); 145 146 if (!icx->bad_index && !icx->entry) 147 return; 148 149 if (icx->actx) 150 ntfs_attr_put_search_ctx(icx->actx); 151 152 if (!icx->is_in_root) { 153 if (icx->ib_dirty) { 154 /* FIXME: Error handling!!! */ 155 ntfs_ib_write(icx, icx->ib); 156 } 157 free(icx->ib); 158 } 159 160 ntfs_attr_close(icx->ia_na); 161 } 162 163 /** 164 * ntfs_index_ctx_put - release an index context 165 * @icx: index context to free 166 * 167 * Release the index context @icx, releasing all associated resources. 168 */ 169 void ntfs_index_ctx_put(ntfs_index_context *icx) 170 { 171 ntfs_index_ctx_free(icx); 172 free(icx); 173 } 174 175 /** 176 * ntfs_index_ctx_reinit - reinitialize an index context 177 * @icx: index context to reinitialize 178 * 179 * Reinitialize the index context @icx so it can be used for ntfs_index_lookup. 180 */ 181 void ntfs_index_ctx_reinit(ntfs_index_context *icx) 182 { 183 ntfs_log_trace("Entering\n"); 184 185 ntfs_index_ctx_free(icx); 186 187 *icx = (ntfs_index_context) { 188 .ni = icx->ni, 189 .name = icx->name, 190 .name_len = icx->name_len, 191 }; 192 } 193 194 static leVCN *ntfs_ie_get_vcn_addr(INDEX_ENTRY *ie) 195 { 196 return (leVCN *)((u8 *)ie + le16_to_cpu(ie->length) - sizeof(leVCN)); 197 } 198 199 /** 200 * Get the subnode vcn to which the index entry refers. 201 */ 202 VCN ntfs_ie_get_vcn(INDEX_ENTRY *ie) 203 { 204 return sle64_to_cpup(ntfs_ie_get_vcn_addr(ie)); 205 } 206 207 static INDEX_ENTRY *ntfs_ie_get_first(INDEX_HEADER *ih) 208 { 209 return (INDEX_ENTRY *)((u8 *)ih + le32_to_cpu(ih->entries_offset)); 210 } 211 212 static INDEX_ENTRY *ntfs_ie_get_next(INDEX_ENTRY *ie) 213 { 214 return (INDEX_ENTRY *)((char *)ie + le16_to_cpu(ie->length)); 215 } 216 217 static u8 *ntfs_ie_get_end(INDEX_HEADER *ih) 218 { 219 /* FIXME: check if it isn't overflowing the index block size */ 220 return (u8 *)ih + le32_to_cpu(ih->index_length); 221 } 222 223 static int ntfs_ie_end(INDEX_ENTRY *ie) 224 { 225 return ie->ie_flags & INDEX_ENTRY_END || !ie->length; 226 } 227 228 /** 229 * Find the last entry in the index block 230 */ 231 static INDEX_ENTRY *ntfs_ie_get_last(INDEX_ENTRY *ie, char *ies_end) 232 { 233 ntfs_log_trace("Entering\n"); 234 235 while ((char *)ie < ies_end && !ntfs_ie_end(ie)) 236 ie = ntfs_ie_get_next(ie); 237 238 return ie; 239 } 240 241 static INDEX_ENTRY *ntfs_ie_get_by_pos(INDEX_HEADER *ih, int pos) 242 { 243 INDEX_ENTRY *ie; 244 245 ntfs_log_trace("pos: %d\n", pos); 246 247 ie = ntfs_ie_get_first(ih); 248 249 while (pos-- > 0) 250 ie = ntfs_ie_get_next(ie); 251 252 return ie; 253 } 254 255 static INDEX_ENTRY *ntfs_ie_prev(INDEX_HEADER *ih, INDEX_ENTRY *ie) 256 { 257 INDEX_ENTRY *ie_prev = NULL; 258 INDEX_ENTRY *tmp; 259 260 ntfs_log_trace("Entering\n"); 261 262 tmp = ntfs_ie_get_first(ih); 263 264 while (tmp != ie) { 265 ie_prev = tmp; 266 tmp = ntfs_ie_get_next(tmp); 267 } 268 269 return ie_prev; 270 } 271 272 char *ntfs_ie_filename_get(INDEX_ENTRY *ie) 273 { 274 FILE_NAME_ATTR *fn; 275 276 fn = (FILE_NAME_ATTR *)&ie->key; 277 return ntfs_attr_name_get(fn->file_name, fn->file_name_length); 278 } 279 280 void ntfs_ie_filename_dump(INDEX_ENTRY *ie) 281 { 282 char *s; 283 284 s = ntfs_ie_filename_get(ie); 285 ntfs_log_debug("'%s' ", s); 286 ntfs_attr_name_free(&s); 287 } 288 289 void ntfs_ih_filename_dump(INDEX_HEADER *ih) 290 { 291 INDEX_ENTRY *ie; 292 293 ntfs_log_trace("Entering\n"); 294 295 ie = ntfs_ie_get_first(ih); 296 while (!ntfs_ie_end(ie)) { 297 ntfs_ie_filename_dump(ie); 298 ie = ntfs_ie_get_next(ie); 299 } 300 } 301 302 static int ntfs_ih_numof_entries(INDEX_HEADER *ih) 303 { 304 int n; 305 INDEX_ENTRY *ie; 306 u8 *end; 307 308 ntfs_log_trace("Entering\n"); 309 310 end = ntfs_ie_get_end(ih); 311 ie = ntfs_ie_get_first(ih); 312 for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++) 313 ie = ntfs_ie_get_next(ie); 314 return n; 315 } 316 317 static int ntfs_ih_one_entry(INDEX_HEADER *ih) 318 { 319 return (ntfs_ih_numof_entries(ih) == 1); 320 } 321 322 static int ntfs_ih_zero_entry(INDEX_HEADER *ih) 323 { 324 return (ntfs_ih_numof_entries(ih) == 0); 325 } 326 327 static void ntfs_ie_delete(INDEX_HEADER *ih, INDEX_ENTRY *ie) 328 { 329 u32 new_size; 330 331 ntfs_log_trace("Entering\n"); 332 333 new_size = le32_to_cpu(ih->index_length) - le16_to_cpu(ie->length); 334 ih->index_length = cpu_to_le32(new_size); 335 memmove(ie, (u8 *)ie + le16_to_cpu(ie->length), 336 new_size - ((u8 *)ie - (u8 *)ih)); 337 } 338 339 static void ntfs_ie_set_vcn(INDEX_ENTRY *ie, VCN vcn) 340 { 341 *ntfs_ie_get_vcn_addr(ie) = cpu_to_sle64(vcn); 342 } 343 344 /** 345 * Insert @ie index entry at @pos entry. Used @ih values should be ok already. 346 */ 347 static void ntfs_ie_insert(INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_ENTRY *pos) 348 { 349 int ie_size = le16_to_cpu(ie->length); 350 351 ntfs_log_trace("Entering\n"); 352 353 ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) + ie_size); 354 memmove((u8 *)pos + ie_size, pos, 355 le32_to_cpu(ih->index_length) - ((u8 *)pos - (u8 *)ih) - ie_size); 356 memcpy(pos, ie, ie_size); 357 } 358 359 static INDEX_ENTRY *ntfs_ie_dup(INDEX_ENTRY *ie) 360 { 361 INDEX_ENTRY *dup; 362 363 ntfs_log_trace("Entering\n"); 364 365 dup = ntfs_malloc(le16_to_cpu(ie->length)); 366 if (dup) 367 memcpy(dup, ie, le16_to_cpu(ie->length)); 368 369 return dup; 370 } 371 372 static INDEX_ENTRY *ntfs_ie_dup_novcn(INDEX_ENTRY *ie) 373 { 374 INDEX_ENTRY *dup; 375 int size = le16_to_cpu(ie->length); 376 377 ntfs_log_trace("Entering\n"); 378 379 if (ie->ie_flags & INDEX_ENTRY_NODE) 380 size -= sizeof(VCN); 381 382 dup = ntfs_malloc(size); 383 if (dup) { 384 memcpy(dup, ie, size); 385 dup->ie_flags &= ~INDEX_ENTRY_NODE; 386 dup->length = cpu_to_le16(size); 387 } 388 return dup; 389 } 390 391 static INDEX_ROOT *ntfs_ir_lookup(ntfs_inode *ni, ntfschar *name, 392 u32 name_len, ntfs_attr_search_ctx **ctx) 393 { 394 ATTR_RECORD *a; 395 INDEX_ROOT *ir = NULL; 396 397 ntfs_log_trace("Entering\n"); 398 399 *ctx = ntfs_attr_get_search_ctx(ni, NULL); 400 if (!*ctx) 401 return NULL; 402 403 if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, 404 0, NULL, 0, *ctx)) { 405 ntfs_log_perror("Failed to lookup $INDEX_ROOT"); 406 goto err_out; 407 } 408 409 a = (*ctx)->attr; 410 if (a->non_resident) { 411 errno = EINVAL; 412 ntfs_log_perror("Non-resident $INDEX_ROOT detected"); 413 goto err_out; 414 } 415 416 ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->value_offset)); 417 err_out: 418 if (!ir) { 419 ntfs_attr_put_search_ctx(*ctx); 420 *ctx = NULL; 421 } 422 return ir; 423 } 424 425 static INDEX_ROOT *ntfs_ir_lookup2(ntfs_inode *ni, ntfschar *name, u32 len) 426 { 427 ntfs_attr_search_ctx *ctx; 428 INDEX_ROOT *ir; 429 430 ir = ntfs_ir_lookup(ni, name, len, &ctx); 431 if (ir) 432 ntfs_attr_put_search_ctx(ctx); 433 return ir; 434 } 435 436 /* 437 * Check the consistency of an index block 438 * 439 * Make sure the index block does not overflow from the index record. 440 * The size of block is assumed to have been checked to be what is 441 * defined in the index root. 442 * 443 * Returns 0 if no error was found 444 * -1 otherwise (with errno unchanged) 445 * 446 * |<--->| offsetof(INDEX_BLOCK, index) 447 * | |<--->| sizeof(INDEX_HEADER) 448 * | | | 449 * | | | seq index entries unused 450 * |=====|=====|=====|===========================|==============| 451 * | | | | | 452 * | |<--------->| entries_offset | | 453 * | |<---------------- index_length ------->| | 454 * | |<--------------------- allocated_size --------------->| 455 * |<--------------------------- block_size ------------------->| 456 * 457 * size(INDEX_HEADER) <= ent_offset < ind_length <= alloc_size < bk_size 458 */ 459 460 int ntfs_index_block_inconsistent(const INDEX_BLOCK *ib, u32 block_size, 461 u64 inum, VCN vcn) 462 { 463 u32 ib_size = (unsigned)le32_to_cpu(ib->index.allocated_size) 464 + offsetof(INDEX_BLOCK, index); 465 466 if (!ntfs_is_indx_record(ib->magic)) { 467 ntfs_log_error("Corrupt index block signature: vcn %lld inode " 468 "%llu\n", (long long)vcn, 469 (unsigned long long)inum); 470 return -1; 471 } 472 473 if (sle64_to_cpu(ib->index_block_vcn) != vcn) { 474 ntfs_log_error("Corrupt index block: VCN (%lld) is different " 475 "from expected VCN (%lld) in inode %llu\n", 476 (long long)sle64_to_cpu(ib->index_block_vcn), 477 (long long)vcn, 478 (unsigned long long)inum); 479 return -1; 480 } 481 482 if (ib_size != block_size) { 483 ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu " 484 "has a size (%u) differing from the index " 485 "specified size (%u)\n", (long long)vcn, 486 (unsigned long long)inum, ib_size, 487 (unsigned int)block_size); 488 return -1; 489 } 490 if (le32_to_cpu(ib->index.entries_offset) < sizeof(INDEX_HEADER)) { 491 ntfs_log_error("Invalid index entry offset in inode %lld\n", 492 (unsigned long long)inum); 493 return -1; 494 } 495 if (le32_to_cpu(ib->index.index_length) 496 <= le32_to_cpu(ib->index.entries_offset)) { 497 ntfs_log_error("No space for index entries in inode %lld\n", 498 (unsigned long long)inum); 499 return -1; 500 } 501 if (le32_to_cpu(ib->index.allocated_size) 502 < le32_to_cpu(ib->index.index_length)) { 503 ntfs_log_error("Index entries overflow in inode %lld\n", 504 (unsigned long long)inum); 505 return -1; 506 } 507 508 return (0); 509 } 510 511 512 /* 513 * Check the consistency of an index entry 514 * 515 * Make sure data and key do not overflow from entry. 516 * As a side effect, an entry with zero length is rejected. 517 * This entry must be a full one (no INDEX_ENTRY_END flag), and its 518 * length must have been checked beforehand to not overflow from the 519 * index record. 520 * 521 * Returns 0 if no error was found 522 * -1 otherwise (with errno unchanged) 523 */ 524 525 int ntfs_index_entry_inconsistent(const INDEX_ENTRY *ie, 526 COLLATION_RULES collation_rule, u64 inum) 527 { 528 int ret; 529 530 ret = 0; 531 if (ie->key_length 532 && ((le16_to_cpu(ie->key_length) + offsetof(INDEX_ENTRY, key)) 533 > le16_to_cpu(ie->length))) { 534 ntfs_log_error("Overflow from index entry in inode %lld\n", 535 (long long)inum); 536 ret = -1; 537 538 } else 539 if (collation_rule == COLLATION_FILE_NAME) { 540 if ((offsetof(INDEX_ENTRY, key.file_name.file_name) 541 + ie->key.file_name.file_name_length 542 * sizeof(ntfschar)) 543 > le16_to_cpu(ie->length)) { 544 ntfs_log_error("File name overflow from index" 545 " entry in inode %lld\n", 546 (long long)inum); 547 ret = -1; 548 } 549 } else { 550 if (ie->data_length 551 && ((le16_to_cpu(ie->data_offset) 552 + le16_to_cpu(ie->data_length)) 553 > le16_to_cpu(ie->length))) { 554 ntfs_log_error("Data overflow from index" 555 " entry in inode %lld\n", 556 (long long)inum); 557 ret = -1; 558 } 559 } 560 return (ret); 561 } 562 563 /** 564 * Find a key in the index block. 565 * 566 * Return values: 567 * STATUS_OK with errno set to ESUCCESS if we know for sure that the 568 * entry exists and @ie_out points to this entry. 569 * STATUS_NOT_FOUND with errno set to ENOENT if we know for sure the 570 * entry doesn't exist and @ie_out is the insertion point. 571 * STATUS_KEEP_SEARCHING if we can't answer the above question and 572 * @vcn will contain the node index block. 573 * STATUS_ERROR with errno set if on unexpected error during lookup. 574 */ 575 static int ntfs_ie_lookup(const void *key, const int key_len, 576 ntfs_index_context *icx, INDEX_HEADER *ih, 577 VCN *vcn, INDEX_ENTRY **ie_out) 578 { 579 INDEX_ENTRY *ie; 580 u8 *index_end; 581 int rc, item = 0; 582 583 ntfs_log_trace("Entering\n"); 584 585 index_end = ntfs_ie_get_end(ih); 586 587 /* 588 * Loop until we exceed valid memory (corruption case) or until we 589 * reach the last entry. 590 */ 591 for (ie = ntfs_ie_get_first(ih); ; ie = ntfs_ie_get_next(ie)) { 592 /* Bounds checks. */ 593 if ((u8 *)ie + sizeof(INDEX_ENTRY_HEADER) > index_end || 594 (u8 *)ie + le16_to_cpu(ie->length) > index_end) { 595 errno = ERANGE; 596 ntfs_log_error("Index entry out of bounds in inode " 597 "%llu.\n", 598 (unsigned long long)icx->ni->mft_no); 599 return STATUS_ERROR; 600 } 601 /* 602 * The last entry cannot contain a key. It can however contain 603 * a pointer to a child node in the B+tree so we just break out. 604 */ 605 if (ntfs_ie_end(ie)) 606 break; 607 /* 608 * Not a perfect match, need to do full blown collation so we 609 * know which way in the B+tree we have to go. 610 */ 611 if (!icx->collate) { 612 ntfs_log_error("Collation function not defined\n"); 613 errno = EOPNOTSUPP; 614 return STATUS_ERROR; 615 } 616 /* Make sure key and data do not overflow from entry */ 617 if (ntfs_index_entry_inconsistent(ie, icx->ir->collation_rule, 618 icx->ni->mft_no)) { 619 errno = EIO; 620 return STATUS_ERROR; 621 } 622 rc = icx->collate(icx->ni->vol, key, key_len, 623 &ie->key, le16_to_cpu(ie->key_length)); 624 if (rc == NTFS_COLLATION_ERROR) { 625 ntfs_log_error("Collation error. Perhaps a filename " 626 "contains invalid characters?\n"); 627 errno = ERANGE; 628 return STATUS_ERROR; 629 } 630 /* 631 * If @key collates before the key of the current entry, there 632 * is definitely no such key in this index but we might need to 633 * descend into the B+tree so we just break out of the loop. 634 */ 635 if (rc == -1) 636 break; 637 638 if (!rc) { 639 *ie_out = ie; 640 errno = 0; 641 icx->parent_pos[icx->pindex] = item; 642 return STATUS_OK; 643 } 644 645 item++; 646 } 647 /* 648 * We have finished with this index block without success. Check for the 649 * presence of a child node and if not present return with errno ENOENT, 650 * otherwise we will keep searching in another index block. 651 */ 652 if (!(ie->ie_flags & INDEX_ENTRY_NODE)) { 653 ntfs_log_debug("Index entry wasn't found.\n"); 654 *ie_out = ie; 655 errno = ENOENT; 656 return STATUS_NOT_FOUND; 657 } 658 659 /* Get the starting vcn of the index_block holding the child node. */ 660 *vcn = ntfs_ie_get_vcn(ie); 661 if (*vcn < 0) { 662 errno = EINVAL; 663 ntfs_log_perror("Negative vcn in inode %llu", 664 (unsigned long long)icx->ni->mft_no); 665 return STATUS_ERROR; 666 } 667 668 ntfs_log_trace("Parent entry number %d\n", item); 669 icx->parent_pos[icx->pindex] = item; 670 671 return STATUS_KEEP_SEARCHING; 672 } 673 674 static ntfs_attr *ntfs_ia_open(ntfs_index_context *icx, ntfs_inode *ni) 675 { 676 ntfs_attr *na; 677 678 na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len); 679 if (!na) { 680 ntfs_log_perror("Failed to open index allocation of inode " 681 "%llu", (unsigned long long)ni->mft_no); 682 return NULL; 683 } 684 685 return na; 686 } 687 688 static int ntfs_ib_read(ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst) 689 { 690 s64 pos, ret; 691 692 ntfs_log_trace("vcn: %lld\n", (long long)vcn); 693 694 pos = ntfs_ib_vcn_to_pos(icx, vcn); 695 696 ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst); 697 if (ret != 1) { 698 if (ret == -1) 699 ntfs_log_perror("Failed to read index block"); 700 else 701 ntfs_log_error("Failed to read full index block at " 702 "%lld\n", (long long)pos); 703 return -1; 704 } 705 706 if (ntfs_index_block_inconsistent((INDEX_BLOCK*)dst, icx->block_size, 707 icx->ia_na->ni->mft_no, vcn)) { 708 errno = EIO; 709 return -1; 710 } 711 712 return 0; 713 } 714 715 static int ntfs_icx_parent_inc(ntfs_index_context *icx) 716 { 717 icx->pindex++; 718 if (icx->pindex >= MAX_PARENT_VCN) { 719 errno = EOPNOTSUPP; 720 ntfs_log_perror("Index is over %d level deep", MAX_PARENT_VCN); 721 return STATUS_ERROR; 722 } 723 return STATUS_OK; 724 } 725 726 static int ntfs_icx_parent_dec(ntfs_index_context *icx) 727 { 728 icx->pindex--; 729 if (icx->pindex < 0) { 730 errno = EINVAL; 731 ntfs_log_perror("Corrupt index pointer (%d)", icx->pindex); 732 return STATUS_ERROR; 733 } 734 return STATUS_OK; 735 } 736 737 /** 738 * ntfs_index_lookup - find a key in an index and return its index entry 739 * @key: [IN] key for which to search in the index 740 * @key_len: [IN] length of @key in bytes 741 * @icx: [IN/OUT] context describing the index and the returned entry 742 * 743 * Before calling ntfs_index_lookup(), @icx must have been obtained from a 744 * call to ntfs_index_ctx_get(). 745 * 746 * Look for the @key in the index specified by the index lookup context @icx. 747 * ntfs_index_lookup() walks the contents of the index looking for the @key. 748 * 749 * If the @key is found in the index, 0 is returned and @icx is setup to 750 * describe the index entry containing the matching @key. @icx->entry is the 751 * index entry and @icx->data and @icx->data_len are the index entry data and 752 * its length in bytes, respectively. 753 * 754 * If the @key is not found in the index, -1 is returned, errno = ENOENT and 755 * @icx is setup to describe the index entry whose key collates immediately 756 * after the search @key, i.e. this is the position in the index at which 757 * an index entry with a key of @key would need to be inserted. 758 * 759 * If an error occurs return -1, set errno to error code and @icx is left 760 * untouched. 761 * 762 * When finished with the entry and its data, call ntfs_index_ctx_put() to free 763 * the context and other associated resources. 764 * 765 * If the index entry was modified, call ntfs_index_entry_mark_dirty() before 766 * the call to ntfs_index_ctx_put() to ensure that the changes are written 767 * to disk. 768 */ 769 int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *icx) 770 { 771 VCN old_vcn, vcn; 772 ntfs_inode *ni = icx->ni; 773 INDEX_ROOT *ir; 774 INDEX_ENTRY *ie; 775 INDEX_BLOCK *ib = NULL; 776 int ret, err = 0; 777 778 ntfs_log_trace("Entering\n"); 779 780 if (!key || key_len <= 0) { 781 errno = EINVAL; 782 ntfs_log_perror("key: %p key_len: %d", key, key_len); 783 return -1; 784 } 785 786 ir = ntfs_ir_lookup(ni, icx->name, icx->name_len, &icx->actx); 787 if (!ir) { 788 if (errno == ENOENT) 789 errno = EIO; 790 return -1; 791 } 792 793 icx->block_size = le32_to_cpu(ir->index_block_size); 794 if (icx->block_size < NTFS_BLOCK_SIZE) { 795 errno = EINVAL; 796 ntfs_log_perror("Index block size (%d) is smaller than the " 797 "sector size (%d)", icx->block_size, NTFS_BLOCK_SIZE); 798 goto err_out; 799 } 800 801 if (ni->vol->cluster_size <= icx->block_size) 802 icx->vcn_size_bits = ni->vol->cluster_size_bits; 803 else 804 icx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS; 805 /* get the appropriate collation function */ 806 icx->ir = ir; 807 icx->collate = ntfs_get_collate_function(ir->collation_rule); 808 if (!icx->collate) { 809 err = errno = EOPNOTSUPP; 810 ntfs_log_perror("Unknown collation rule 0x%x", 811 (unsigned)le32_to_cpu(ir->collation_rule)); 812 goto err_out; 813 } 814 815 old_vcn = VCN_INDEX_ROOT_PARENT; 816 ret = ntfs_ie_lookup(key, key_len, icx, &ir->index, &vcn, &ie); 817 if (ret == STATUS_ERROR) { 818 err = errno; 819 goto err_lookup; 820 } 821 822 icx->ir = ir; 823 824 if (ret != STATUS_KEEP_SEARCHING) { 825 /* STATUS_OK or STATUS_NOT_FOUND */ 826 err = errno; 827 icx->is_in_root = TRUE; 828 icx->parent_vcn[icx->pindex] = old_vcn; 829 goto done; 830 } 831 832 /* Child node present, descend into it. */ 833 834 icx->ia_na = ntfs_ia_open(icx, ni); 835 if (!icx->ia_na) 836 goto err_out; 837 838 ib = ntfs_malloc(icx->block_size); 839 if (!ib) { 840 err = errno; 841 goto err_out; 842 } 843 844 descend_into_child_node: 845 846 icx->parent_vcn[icx->pindex] = old_vcn; 847 if (ntfs_icx_parent_inc(icx)) { 848 err = errno; 849 goto err_out; 850 } 851 old_vcn = vcn; 852 853 ntfs_log_debug("Descend into node with VCN %lld\n", (long long)vcn); 854 855 if (ntfs_ib_read(icx, vcn, ib)) 856 goto err_out; 857 858 ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie); 859 if (ret != STATUS_KEEP_SEARCHING) { 860 err = errno; 861 if (ret == STATUS_ERROR) 862 goto err_out; 863 864 /* STATUS_OK or STATUS_NOT_FOUND */ 865 icx->is_in_root = FALSE; 866 icx->ib = ib; 867 icx->parent_vcn[icx->pindex] = vcn; 868 goto done; 869 } 870 871 if ((ib->index.ih_flags & NODE_MASK) == LEAF_NODE) { 872 ntfs_log_error("Index entry with child node found in a leaf " 873 "node in inode 0x%llx.\n", 874 (unsigned long long)ni->mft_no); 875 goto err_out; 876 } 877 878 goto descend_into_child_node; 879 err_out: 880 icx->bad_index = TRUE; /* Force icx->* to be freed */ 881 err_lookup: 882 if (icx->actx) { 883 ntfs_attr_put_search_ctx(icx->actx); 884 icx->actx = NULL; 885 } 886 free(ib); 887 if (!err) 888 err = EIO; 889 errno = err; 890 return -1; 891 done: 892 icx->entry = ie; 893 icx->data = (u8 *)ie + offsetof(INDEX_ENTRY, key); 894 icx->data_len = le16_to_cpu(ie->key_length); 895 ntfs_log_trace("Done.\n"); 896 if (err) { 897 errno = err; 898 return -1; 899 } 900 return 0; 901 902 } 903 904 static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, 905 INDEX_HEADER_FLAGS node_type) 906 { 907 INDEX_BLOCK *ib; 908 int ih_size = sizeof(INDEX_HEADER); 909 910 ntfs_log_trace("ib_vcn: %lld ib_size: %u\n", (long long)ib_vcn, ib_size); 911 912 ib = ntfs_calloc(ib_size); 913 if (!ib) 914 return NULL; 915 916 ib->magic = magic_INDX; 917 ib->usa_ofs = const_cpu_to_le16(sizeof(INDEX_BLOCK)); 918 ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1); 919 /* Set USN to 1 */ 920 *(le16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = const_cpu_to_le16(1); 921 ib->lsn = const_cpu_to_sle64(0); 922 923 ib->index_block_vcn = cpu_to_sle64(ib_vcn); 924 925 ib->index.entries_offset = cpu_to_le32((ih_size + 926 le16_to_cpu(ib->usa_count) * 2 + 7) & ~7); 927 ib->index.index_length = const_cpu_to_le32(0); 928 ib->index.allocated_size = cpu_to_le32(ib_size - 929 (sizeof(INDEX_BLOCK) - ih_size)); 930 ib->index.ih_flags = node_type; 931 932 return ib; 933 } 934 935 /** 936 * Find the median by going through all the entries 937 */ 938 static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih) 939 { 940 INDEX_ENTRY *ie, *ie_start; 941 u8 *ie_end; 942 int i = 0, median; 943 944 ntfs_log_trace("Entering\n"); 945 946 ie = ie_start = ntfs_ie_get_first(ih); 947 ie_end = (u8 *)ntfs_ie_get_end(ih); 948 949 while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) { 950 ie = ntfs_ie_get_next(ie); 951 i++; 952 } 953 /* 954 * NOTE: this could be also the entry at the half of the index block. 955 */ 956 median = i / 2 - 1; 957 958 ntfs_log_trace("Entries: %d median: %d\n", i, median); 959 960 for (i = 0, ie = ie_start; i <= median; i++) 961 ie = ntfs_ie_get_next(ie); 962 963 return ie; 964 } 965 966 static s64 ntfs_ibm_vcn_to_pos(ntfs_index_context *icx, VCN vcn) 967 { 968 return ntfs_ib_vcn_to_pos(icx, vcn) / icx->block_size; 969 } 970 971 static s64 ntfs_ibm_pos_to_vcn(ntfs_index_context *icx, s64 pos) 972 { 973 return ntfs_ib_pos_to_vcn(icx, pos * icx->block_size); 974 } 975 976 static int ntfs_ibm_add(ntfs_index_context *icx) 977 { 978 u8 bmp[8]; 979 980 ntfs_log_trace("Entering\n"); 981 982 if (ntfs_attr_exist(icx->ni, AT_BITMAP, icx->name, icx->name_len)) 983 return STATUS_OK; 984 /* 985 * AT_BITMAP must be at least 8 bytes. 986 */ 987 memset(bmp, 0, sizeof(bmp)); 988 if (ntfs_attr_add(icx->ni, AT_BITMAP, icx->name, icx->name_len, 989 bmp, sizeof(bmp))) { 990 ntfs_log_perror("Failed to add AT_BITMAP"); 991 return STATUS_ERROR; 992 } 993 994 return STATUS_OK; 995 } 996 997 static int ntfs_ibm_modify(ntfs_index_context *icx, VCN vcn, int set) 998 { 999 u8 byte; 1000 s64 pos = ntfs_ibm_vcn_to_pos(icx, vcn); 1001 u32 bpos = pos / 8; 1002 u32 bit = 1 << (pos % 8); 1003 ntfs_attr *na; 1004 int ret = STATUS_ERROR; 1005 1006 ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", (long long)vcn); 1007 1008 na = ntfs_attr_open(icx->ni, AT_BITMAP, icx->name, icx->name_len); 1009 if (!na) { 1010 ntfs_log_perror("Failed to open $BITMAP attribute"); 1011 return -1; 1012 } 1013 1014 if (set) { 1015 if (na->data_size < bpos + 1) { 1016 if (ntfs_attr_truncate(na, (na->data_size + 8) & ~7)) { 1017 ntfs_log_perror("Failed to truncate AT_BITMAP"); 1018 goto err_na; 1019 } 1020 } 1021 } 1022 1023 if (ntfs_attr_pread(na, bpos, 1, &byte) != 1) { 1024 ntfs_log_perror("Failed to read $BITMAP"); 1025 goto err_na; 1026 } 1027 1028 if (set) 1029 byte |= bit; 1030 else 1031 byte &= ~bit; 1032 1033 if (ntfs_attr_pwrite(na, bpos, 1, &byte) != 1) { 1034 ntfs_log_perror("Failed to write $Bitmap"); 1035 goto err_na; 1036 } 1037 1038 ret = STATUS_OK; 1039 err_na: 1040 ntfs_attr_close(na); 1041 return ret; 1042 } 1043 1044 1045 static int ntfs_ibm_set(ntfs_index_context *icx, VCN vcn) 1046 { 1047 return ntfs_ibm_modify(icx, vcn, 1); 1048 } 1049 1050 static int ntfs_ibm_clear(ntfs_index_context *icx, VCN vcn) 1051 { 1052 return ntfs_ibm_modify(icx, vcn, 0); 1053 } 1054 1055 static VCN ntfs_ibm_get_free(ntfs_index_context *icx) 1056 { 1057 u8 *bm; 1058 int bit; 1059 s64 vcn, byte, size; 1060 1061 ntfs_log_trace("Entering\n"); 1062 1063 bm = ntfs_attr_readall(icx->ni, AT_BITMAP, icx->name, icx->name_len, 1064 &size); 1065 if (!bm) 1066 return (VCN)-1; 1067 1068 for (byte = 0; byte < size; byte++) { 1069 1070 if (bm[byte] == 255) 1071 continue; 1072 1073 for (bit = 0; bit < 8; bit++) { 1074 if (!(bm[byte] & (1 << bit))) { 1075 vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); 1076 goto out; 1077 } 1078 } 1079 } 1080 1081 vcn = ntfs_ibm_pos_to_vcn(icx, size * 8); 1082 out: 1083 ntfs_log_trace("allocated vcn: %lld\n", (long long)vcn); 1084 1085 if (ntfs_ibm_set(icx, vcn)) 1086 vcn = (VCN)-1; 1087 1088 free(bm); 1089 return vcn; 1090 } 1091 1092 static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn) 1093 { 1094 INDEX_BLOCK *ib; 1095 INDEX_ENTRY *ie_last; 1096 char *ies_start, *ies_end; 1097 int i; 1098 1099 ntfs_log_trace("Entering\n"); 1100 1101 ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), LEAF_NODE); 1102 if (!ib) 1103 return NULL; 1104 1105 ies_start = (char *)ntfs_ie_get_first(&ir->index); 1106 ies_end = (char *)ntfs_ie_get_end(&ir->index); 1107 ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); 1108 /* 1109 * Copy all entries, including the termination entry 1110 * as well, which can never have any data. 1111 */ 1112 i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length); 1113 memcpy(ntfs_ie_get_first(&ib->index), ies_start, i); 1114 1115 ib->index.ih_flags = ir->index.ih_flags; 1116 ib->index.index_length = cpu_to_le32(i + 1117 le32_to_cpu(ib->index.entries_offset)); 1118 return ib; 1119 } 1120 1121 static void ntfs_ir_nill(INDEX_ROOT *ir) 1122 { 1123 INDEX_ENTRY *ie_last; 1124 char *ies_start, *ies_end; 1125 1126 ntfs_log_trace("Entering\n"); 1127 /* 1128 * TODO: This function could be much simpler. 1129 */ 1130 ies_start = (char *)ntfs_ie_get_first(&ir->index); 1131 ies_end = (char *)ntfs_ie_get_end(&ir->index); 1132 ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); 1133 /* 1134 * Move the index root termination entry forward 1135 */ 1136 if ((char *)ie_last > ies_start) { 1137 memmove(ies_start, (char *)ie_last, le16_to_cpu(ie_last->length)); 1138 ie_last = (INDEX_ENTRY *)ies_start; 1139 } 1140 } 1141 1142 static int ntfs_ib_copy_tail(ntfs_index_context *icx, INDEX_BLOCK *src, 1143 INDEX_ENTRY *median, VCN new_vcn) 1144 { 1145 u8 *ies_end; 1146 INDEX_ENTRY *ie_head; /* first entry after the median */ 1147 int tail_size, ret; 1148 INDEX_BLOCK *dst; 1149 1150 ntfs_log_trace("Entering\n"); 1151 1152 dst = ntfs_ib_alloc(new_vcn, icx->block_size, 1153 src->index.ih_flags & NODE_MASK); 1154 if (!dst) 1155 return STATUS_ERROR; 1156 1157 ie_head = ntfs_ie_get_next(median); 1158 1159 ies_end = (u8 *)ntfs_ie_get_end(&src->index); 1160 tail_size = ies_end - (u8 *)ie_head; 1161 memcpy(ntfs_ie_get_first(&dst->index), ie_head, tail_size); 1162 1163 dst->index.index_length = cpu_to_le32(tail_size + 1164 le32_to_cpu(dst->index.entries_offset)); 1165 ret = ntfs_ib_write(icx, dst); 1166 1167 free(dst); 1168 return ret; 1169 } 1170 1171 static int ntfs_ib_cut_tail(ntfs_index_context *icx, INDEX_BLOCK *ib, 1172 INDEX_ENTRY *ie) 1173 { 1174 char *ies_start, *ies_end; 1175 INDEX_ENTRY *ie_last; 1176 1177 ntfs_log_trace("Entering\n"); 1178 1179 ies_start = (char *)ntfs_ie_get_first(&ib->index); 1180 ies_end = (char *)ntfs_ie_get_end(&ib->index); 1181 1182 ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); 1183 if (ie_last->ie_flags & INDEX_ENTRY_NODE) 1184 ntfs_ie_set_vcn(ie_last, ntfs_ie_get_vcn(ie)); 1185 1186 memcpy(ie, ie_last, le16_to_cpu(ie_last->length)); 1187 1188 ib->index.index_length = cpu_to_le32(((char *)ie - ies_start) + 1189 le16_to_cpu(ie->length) + le32_to_cpu(ib->index.entries_offset)); 1190 1191 if (ntfs_ib_write(icx, ib)) 1192 return STATUS_ERROR; 1193 1194 return STATUS_OK; 1195 } 1196 1197 static int ntfs_ia_add(ntfs_index_context *icx) 1198 { 1199 ntfs_log_trace("Entering\n"); 1200 1201 if (ntfs_ibm_add(icx)) 1202 return -1; 1203 1204 if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) { 1205 1206 if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name, 1207 icx->name_len, NULL, 0)) { 1208 ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION"); 1209 return -1; 1210 } 1211 } 1212 1213 icx->ia_na = ntfs_ia_open(icx, icx->ni); 1214 if (!icx->ia_na) 1215 return -1; 1216 1217 return 0; 1218 } 1219 1220 static int ntfs_ir_reparent(ntfs_index_context *icx) 1221 { 1222 ntfs_attr_search_ctx *ctx = NULL; 1223 INDEX_ROOT *ir; 1224 INDEX_ENTRY *ie; 1225 INDEX_BLOCK *ib = NULL; 1226 VCN new_ib_vcn; 1227 int ix_root_size; 1228 int ret = STATUS_ERROR; 1229 1230 ntfs_log_trace("Entering\n"); 1231 1232 ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); 1233 if (!ir) 1234 goto out; 1235 1236 if ((ir->index.ih_flags & NODE_MASK) == SMALL_INDEX) 1237 if (ntfs_ia_add(icx)) 1238 goto out; 1239 1240 new_ib_vcn = ntfs_ibm_get_free(icx); 1241 if (new_ib_vcn == -1) 1242 goto out; 1243 1244 ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); 1245 if (!ir) 1246 goto clear_bmp; 1247 1248 ib = ntfs_ir_to_ib(ir, new_ib_vcn); 1249 if (ib == NULL) { 1250 ntfs_log_perror("Failed to move index root to index block"); 1251 goto clear_bmp; 1252 } 1253 1254 if (ntfs_ib_write(icx, ib)) 1255 goto clear_bmp; 1256 1257 retry : 1258 ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, &ctx); 1259 if (!ir) 1260 goto clear_bmp; 1261 1262 ntfs_ir_nill(ir); 1263 1264 ie = ntfs_ie_get_first(&ir->index); 1265 ie->ie_flags |= INDEX_ENTRY_NODE; 1266 ie->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)); 1267 1268 ir->index.ih_flags = LARGE_INDEX; 1269 ir->index.index_length = cpu_to_le32(le32_to_cpu(ir->index.entries_offset) 1270 + le16_to_cpu(ie->length)); 1271 ir->index.allocated_size = ir->index.index_length; 1272 ix_root_size = sizeof(INDEX_ROOT) - sizeof(INDEX_HEADER) 1273 + le32_to_cpu(ir->index.allocated_size); 1274 if (ntfs_resident_attr_value_resize(ctx->mrec, ctx->attr, 1275 ix_root_size)) { 1276 /* 1277 * When there is no space to build a non-resident 1278 * index, we may have to move the root to an extent 1279 */ 1280 if ((errno == ENOSPC) 1281 && (ctx->al_entry || !ntfs_inode_add_attrlist(icx->ni))) { 1282 ntfs_attr_put_search_ctx(ctx); 1283 ctx = (ntfs_attr_search_ctx*)NULL; 1284 ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, 1285 &ctx); 1286 if (ir 1287 && !ntfs_attr_record_move_away(ctx, ix_root_size 1288 - le32_to_cpu(ctx->attr->value_length))) { 1289 ntfs_attr_put_search_ctx(ctx); 1290 ctx = (ntfs_attr_search_ctx*)NULL; 1291 goto retry; 1292 } 1293 } 1294 /* FIXME: revert index root */ 1295 goto clear_bmp; 1296 } 1297 /* 1298 * FIXME: do it earlier if we have enough space in IR (should always), 1299 * so in error case we wouldn't lose the IB. 1300 */ 1301 ntfs_ie_set_vcn(ie, new_ib_vcn); 1302 1303 ret = STATUS_OK; 1304 err_out: 1305 free(ib); 1306 ntfs_attr_put_search_ctx(ctx); 1307 out: 1308 return ret; 1309 clear_bmp: 1310 ntfs_ibm_clear(icx, new_ib_vcn); 1311 goto err_out; 1312 } 1313 1314 /** 1315 * ntfs_ir_truncate - Truncate index root attribute 1316 * 1317 * Returns STATUS_OK, STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT or STATUS_ERROR. 1318 */ 1319 static int ntfs_ir_truncate(ntfs_index_context *icx, int data_size) 1320 { 1321 ntfs_attr *na; 1322 int ret; 1323 1324 ntfs_log_trace("Entering\n"); 1325 1326 na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len); 1327 if (!na) { 1328 ntfs_log_perror("Failed to open INDEX_ROOT"); 1329 return STATUS_ERROR; 1330 } 1331 /* 1332 * INDEX_ROOT must be resident and its entries can be moved to 1333 * INDEX_BLOCK, so ENOSPC isn't a real error. 1334 */ 1335 ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index)); 1336 if (ret == STATUS_OK) { 1337 1338 icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); 1339 if (!icx->ir) 1340 return STATUS_ERROR; 1341 1342 icx->ir->index.allocated_size = cpu_to_le32(data_size); 1343 1344 } else if (ret == STATUS_ERROR) 1345 ntfs_log_perror("Failed to truncate INDEX_ROOT"); 1346 1347 ntfs_attr_close(na); 1348 return ret; 1349 } 1350 1351 /** 1352 * ntfs_ir_make_space - Make more space for the index root attribute 1353 * 1354 * On success return STATUS_OK or STATUS_KEEP_SEARCHING. 1355 * On error return STATUS_ERROR. 1356 */ 1357 static int ntfs_ir_make_space(ntfs_index_context *icx, int data_size) 1358 { 1359 int ret; 1360 1361 ntfs_log_trace("Entering\n"); 1362 1363 ret = ntfs_ir_truncate(icx, data_size); 1364 if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) { 1365 1366 ret = ntfs_ir_reparent(icx); 1367 if (ret == STATUS_OK) 1368 ret = STATUS_KEEP_SEARCHING; 1369 else 1370 ntfs_log_perror("Failed to nodify INDEX_ROOT"); 1371 } 1372 1373 return ret; 1374 } 1375 1376 /* 1377 * NOTE: 'ie' must be a copy of a real index entry. 1378 */ 1379 static int ntfs_ie_add_vcn(INDEX_ENTRY **ie) 1380 { 1381 INDEX_ENTRY *p, *old = *ie; 1382 1383 old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN)); 1384 p = realloc(old, le16_to_cpu(old->length)); 1385 if (!p) 1386 return STATUS_ERROR; 1387 1388 p->ie_flags |= INDEX_ENTRY_NODE; 1389 *ie = p; 1390 1391 return STATUS_OK; 1392 } 1393 1394 static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, 1395 int pos) 1396 { 1397 INDEX_ENTRY *ie_node, *ie; 1398 int ret = STATUS_ERROR; 1399 VCN old_vcn; 1400 1401 ntfs_log_trace("Entering\n"); 1402 1403 ie = ntfs_ie_dup(orig_ie); 1404 if (!ie) 1405 return STATUS_ERROR; 1406 1407 if (!(ie->ie_flags & INDEX_ENTRY_NODE)) 1408 if (ntfs_ie_add_vcn(&ie)) 1409 goto out; 1410 1411 ie_node = ntfs_ie_get_by_pos(ih, pos); 1412 old_vcn = ntfs_ie_get_vcn(ie_node); 1413 ntfs_ie_set_vcn(ie_node, new_vcn); 1414 1415 ntfs_ie_insert(ih, ie, ie_node); 1416 ntfs_ie_set_vcn(ie_node, old_vcn); 1417 ret = STATUS_OK; 1418 out: 1419 free(ie); 1420 1421 return ret; 1422 } 1423 1424 static VCN ntfs_icx_parent_vcn(ntfs_index_context *icx) 1425 { 1426 return icx->parent_vcn[icx->pindex]; 1427 } 1428 1429 static VCN ntfs_icx_parent_pos(ntfs_index_context *icx) 1430 { 1431 return icx->parent_pos[icx->pindex]; 1432 } 1433 1434 1435 static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median, 1436 VCN new_vcn) 1437 { 1438 u32 new_size; 1439 int ret; 1440 1441 ntfs_log_trace("Entering\n"); 1442 1443 icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); 1444 if (!icx->ir) 1445 return STATUS_ERROR; 1446 1447 new_size = le32_to_cpu(icx->ir->index.index_length) + 1448 le16_to_cpu(median->length); 1449 if (!(median->ie_flags & INDEX_ENTRY_NODE)) 1450 new_size += sizeof(VCN); 1451 1452 ret = ntfs_ir_make_space(icx, new_size); 1453 if (ret != STATUS_OK) 1454 return ret; 1455 1456 icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); 1457 if (!icx->ir) 1458 return STATUS_ERROR; 1459 1460 return ntfs_ih_insert(&icx->ir->index, median, new_vcn, 1461 ntfs_icx_parent_pos(icx)); 1462 } 1463 1464 static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib); 1465 1466 /** 1467 * On success return STATUS_OK or STATUS_KEEP_SEARCHING. 1468 * On error return STATUS_ERROR. 1469 */ 1470 static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn) 1471 { 1472 INDEX_BLOCK *ib; 1473 u32 idx_size, allocated_size; 1474 int err = STATUS_ERROR; 1475 VCN old_vcn; 1476 1477 ntfs_log_trace("Entering\n"); 1478 1479 ib = ntfs_malloc(icx->block_size); 1480 if (!ib) 1481 return -1; 1482 1483 old_vcn = ntfs_icx_parent_vcn(icx); 1484 1485 if (ntfs_ib_read(icx, old_vcn, ib)) 1486 goto err_out; 1487 1488 idx_size = le32_to_cpu(ib->index.index_length); 1489 allocated_size = le32_to_cpu(ib->index.allocated_size); 1490 /* FIXME: sizeof(VCN) should be included only if ie has no VCN */ 1491 if (idx_size + le16_to_cpu(ie->length) + sizeof(VCN) > allocated_size) { 1492 err = ntfs_ib_split(icx, ib); 1493 if (err == STATUS_OK) 1494 err = STATUS_KEEP_SEARCHING; 1495 goto err_out; 1496 } 1497 1498 if (ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx))) 1499 goto err_out; 1500 1501 if (ntfs_ib_write(icx, ib)) 1502 goto err_out; 1503 1504 err = STATUS_OK; 1505 err_out: 1506 free(ib); 1507 return err; 1508 } 1509 1510 /** 1511 * ntfs_ib_split - Split an index block 1512 * 1513 * On success return STATUS_OK or STATUS_KEEP_SEARCHING. 1514 * On error return is STATUS_ERROR. 1515 */ 1516 static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib) 1517 { 1518 INDEX_ENTRY *median; 1519 VCN new_vcn; 1520 int ret; 1521 1522 ntfs_log_trace("Entering\n"); 1523 1524 if (ntfs_icx_parent_dec(icx)) 1525 return STATUS_ERROR; 1526 1527 median = ntfs_ie_get_median(&ib->index); 1528 new_vcn = ntfs_ibm_get_free(icx); 1529 if (new_vcn == -1) 1530 return STATUS_ERROR; 1531 1532 if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) { 1533 ntfs_ibm_clear(icx, new_vcn); 1534 return STATUS_ERROR; 1535 } 1536 1537 if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) 1538 ret = ntfs_ir_insert_median(icx, median, new_vcn); 1539 else 1540 ret = ntfs_ib_insert(icx, median, new_vcn); 1541 1542 if (ret != STATUS_OK) { 1543 ntfs_ibm_clear(icx, new_vcn); 1544 return ret; 1545 } 1546 1547 ret = ntfs_ib_cut_tail(icx, ib, median); 1548 1549 return ret; 1550 } 1551 1552 /* JPA static */ 1553 int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) 1554 { 1555 INDEX_HEADER *ih; 1556 int allocated_size, new_size; 1557 int ret = STATUS_ERROR; 1558 1559 #ifdef DEBUG 1560 /* removed by JPA to make function usable for security indexes 1561 char *fn; 1562 fn = ntfs_ie_filename_get(ie); 1563 ntfs_log_trace("file: '%s'\n", fn); 1564 ntfs_attr_name_free(&fn); 1565 */ 1566 #endif 1567 1568 while (1) { 1569 1570 if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) { 1571 errno = EEXIST; 1572 ntfs_log_perror("Index already have such entry"); 1573 goto err_out; 1574 } 1575 if (errno != ENOENT) { 1576 ntfs_log_perror("Failed to find place for new entry"); 1577 goto err_out; 1578 } 1579 1580 if (icx->is_in_root) 1581 ih = &icx->ir->index; 1582 else 1583 ih = &icx->ib->index; 1584 1585 allocated_size = le32_to_cpu(ih->allocated_size); 1586 new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length); 1587 1588 if (new_size <= allocated_size) 1589 break; 1590 1591 ntfs_log_trace("index block sizes: allocated: %d needed: %d\n", 1592 allocated_size, new_size); 1593 1594 if (icx->is_in_root) { 1595 if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR) 1596 goto err_out; 1597 } else { 1598 if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR) 1599 goto err_out; 1600 } 1601 1602 ntfs_inode_mark_dirty(icx->actx->ntfs_ino); 1603 ntfs_index_ctx_reinit(icx); 1604 } 1605 1606 ntfs_ie_insert(ih, ie, icx->entry); 1607 ntfs_index_entry_mark_dirty(icx); 1608 1609 ret = STATUS_OK; 1610 err_out: 1611 ntfs_log_trace("%s\n", ret ? "Failed" : "Done"); 1612 return ret; 1613 } 1614 1615 /** 1616 * ntfs_index_add_filename - add filename to directory index 1617 * @ni: ntfs inode describing directory to which index add filename 1618 * @fn: FILE_NAME attribute to add 1619 * @mref: reference of the inode which @fn describes 1620 * 1621 * Return 0 on success or -1 on error with errno set to the error code. 1622 */ 1623 int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref) 1624 { 1625 INDEX_ENTRY *ie; 1626 ntfs_index_context *icx; 1627 int fn_size, ie_size, err, ret = -1; 1628 1629 ntfs_log_trace("Entering\n"); 1630 1631 if (!ni || !fn) { 1632 ntfs_log_error("Invalid arguments.\n"); 1633 errno = EINVAL; 1634 return -1; 1635 } 1636 1637 fn_size = (fn->file_name_length * sizeof(ntfschar)) + 1638 sizeof(FILE_NAME_ATTR); 1639 ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7; 1640 1641 ie = ntfs_calloc(ie_size); 1642 if (!ie) 1643 return -1; 1644 1645 ie->indexed_file = cpu_to_le64(mref); 1646 ie->length = cpu_to_le16(ie_size); 1647 ie->key_length = cpu_to_le16(fn_size); 1648 memcpy(&ie->key, fn, fn_size); 1649 1650 icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4); 1651 if (!icx) 1652 goto out; 1653 1654 ret = ntfs_ie_add(icx, ie); 1655 err = errno; 1656 ntfs_index_ctx_put(icx); 1657 errno = err; 1658 out: 1659 free(ie); 1660 return ret; 1661 } 1662 1663 static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, 1664 INDEX_ENTRY *ie, INDEX_BLOCK *ib) 1665 { 1666 INDEX_ENTRY *ie_roam; 1667 int freed_space; 1668 BOOL full; 1669 int ret = STATUS_ERROR; 1670 1671 ntfs_log_trace("Entering\n"); 1672 1673 full = ih->index_length == ih->allocated_size; 1674 ie_roam = ntfs_ie_dup_novcn(ie); 1675 if (!ie_roam) 1676 return STATUS_ERROR; 1677 1678 ntfs_ie_delete(ih, ie); 1679 1680 if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { 1681 /* 1682 * Recover the space which may have been freed 1683 * while deleting an entry from root index 1684 */ 1685 freed_space = le32_to_cpu(ih->allocated_size) 1686 - le32_to_cpu(ih->index_length); 1687 if (full && (freed_space > 0) && !(freed_space & 7)) { 1688 ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 1689 /* do nothing if truncation fails */ 1690 } 1691 ntfs_inode_mark_dirty(icx->actx->ntfs_ino); 1692 } else 1693 if (ntfs_ib_write(icx, ib)) 1694 goto out; 1695 1696 ntfs_index_ctx_reinit(icx); 1697 1698 ret = ntfs_ie_add(icx, ie_roam); 1699 out: 1700 free(ie_roam); 1701 return ret; 1702 } 1703 1704 /** 1705 * Used if an empty index block to be deleted has END entry as the parent 1706 * in the INDEX_ROOT which is the only one there. 1707 */ 1708 static void ntfs_ir_leafify(ntfs_index_context *icx, INDEX_HEADER *ih) 1709 { 1710 INDEX_ENTRY *ie; 1711 1712 ntfs_log_trace("Entering\n"); 1713 1714 ie = ntfs_ie_get_first(ih); 1715 ie->ie_flags &= ~INDEX_ENTRY_NODE; 1716 ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(VCN)); 1717 1718 ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - sizeof(VCN)); 1719 ih->ih_flags &= ~LARGE_INDEX; 1720 1721 /* Not fatal error */ 1722 ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 1723 } 1724 1725 /** 1726 * Used if an empty index block to be deleted has END entry as the parent 1727 * in the INDEX_ROOT which is not the only one there. 1728 */ 1729 static int ntfs_ih_reparent_end(ntfs_index_context *icx, INDEX_HEADER *ih, 1730 INDEX_BLOCK *ib) 1731 { 1732 INDEX_ENTRY *ie, *ie_prev; 1733 1734 ntfs_log_trace("Entering\n"); 1735 1736 ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx)); 1737 ie_prev = ntfs_ie_prev(ih, ie); 1738 1739 ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev)); 1740 1741 return ntfs_ih_takeout(icx, ih, ie_prev, ib); 1742 } 1743 1744 static int ntfs_index_rm_leaf(ntfs_index_context *icx) 1745 { 1746 INDEX_BLOCK *ib = NULL; 1747 INDEX_HEADER *parent_ih; 1748 INDEX_ENTRY *ie; 1749 int ret = STATUS_ERROR; 1750 1751 ntfs_log_trace("pindex: %d\n", icx->pindex); 1752 1753 if (ntfs_icx_parent_dec(icx)) 1754 return STATUS_ERROR; 1755 1756 if (ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1])) 1757 return STATUS_ERROR; 1758 1759 if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) 1760 parent_ih = &icx->ir->index; 1761 else { 1762 ib = ntfs_malloc(icx->block_size); 1763 if (!ib) 1764 return STATUS_ERROR; 1765 1766 if (ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib)) 1767 goto out; 1768 1769 parent_ih = &ib->index; 1770 } 1771 1772 ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx)); 1773 if (!ntfs_ie_end(ie)) { 1774 ret = ntfs_ih_takeout(icx, parent_ih, ie, ib); 1775 goto out; 1776 } 1777 1778 if (ntfs_ih_zero_entry(parent_ih)) { 1779 1780 if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { 1781 ntfs_ir_leafify(icx, parent_ih); 1782 goto ok; 1783 } 1784 1785 ret = ntfs_index_rm_leaf(icx); 1786 goto out; 1787 } 1788 1789 if (ntfs_ih_reparent_end(icx, parent_ih, ib)) 1790 goto out; 1791 ok: 1792 ret = STATUS_OK; 1793 out: 1794 free(ib); 1795 return ret; 1796 } 1797 1798 static int ntfs_index_rm_node(ntfs_index_context *icx) 1799 { 1800 int entry_pos, pindex; 1801 VCN vcn; 1802 INDEX_BLOCK *ib = NULL; 1803 INDEX_ENTRY *ie_succ, *ie, *entry = icx->entry; 1804 INDEX_HEADER *ih; 1805 u32 new_size; 1806 int delta, ret = STATUS_ERROR; 1807 1808 ntfs_log_trace("Entering\n"); 1809 1810 if (!icx->ia_na) { 1811 icx->ia_na = ntfs_ia_open(icx, icx->ni); 1812 if (!icx->ia_na) 1813 return STATUS_ERROR; 1814 } 1815 1816 ib = ntfs_malloc(icx->block_size); 1817 if (!ib) 1818 return STATUS_ERROR; 1819 1820 ie_succ = ntfs_ie_get_next(icx->entry); 1821 entry_pos = icx->parent_pos[icx->pindex]++; 1822 pindex = icx->pindex; 1823 descend: 1824 vcn = ntfs_ie_get_vcn(ie_succ); 1825 if (ntfs_ib_read(icx, vcn, ib)) 1826 goto out; 1827 1828 ie_succ = ntfs_ie_get_first(&ib->index); 1829 1830 if (ntfs_icx_parent_inc(icx)) 1831 goto out; 1832 1833 icx->parent_vcn[icx->pindex] = vcn; 1834 icx->parent_pos[icx->pindex] = 0; 1835 1836 if ((ib->index.ih_flags & NODE_MASK) == INDEX_NODE) 1837 goto descend; 1838 1839 if (ntfs_ih_zero_entry(&ib->index)) { 1840 errno = EIO; 1841 ntfs_log_perror("Empty index block"); 1842 goto out; 1843 } 1844 1845 ie = ntfs_ie_dup(ie_succ); 1846 if (!ie) 1847 goto out; 1848 1849 if (ntfs_ie_add_vcn(&ie)) 1850 goto out2; 1851 1852 ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(icx->entry)); 1853 1854 if (icx->is_in_root) 1855 ih = &icx->ir->index; 1856 else 1857 ih = &icx->ib->index; 1858 1859 delta = le16_to_cpu(ie->length) - le16_to_cpu(icx->entry->length); 1860 new_size = le32_to_cpu(ih->index_length) + delta; 1861 if (delta > 0) { 1862 if (icx->is_in_root) { 1863 ret = ntfs_ir_make_space(icx, new_size); 1864 if (ret != STATUS_OK) 1865 goto out2; 1866 1867 ih = &icx->ir->index; 1868 entry = ntfs_ie_get_by_pos(ih, entry_pos); 1869 1870 } else if (new_size > le32_to_cpu(ih->allocated_size)) { 1871 icx->pindex = pindex; 1872 ret = ntfs_ib_split(icx, icx->ib); 1873 if (ret == STATUS_OK) 1874 ret = STATUS_KEEP_SEARCHING; 1875 goto out2; 1876 } 1877 } 1878 1879 ntfs_ie_delete(ih, entry); 1880 ntfs_ie_insert(ih, ie, entry); 1881 1882 if (icx->is_in_root) { 1883 if (ntfs_ir_truncate(icx, new_size)) 1884 goto out2; 1885 } else 1886 if (ntfs_icx_ib_write(icx)) 1887 goto out2; 1888 1889 ntfs_ie_delete(&ib->index, ie_succ); 1890 1891 if (ntfs_ih_zero_entry(&ib->index)) { 1892 if (ntfs_index_rm_leaf(icx)) 1893 goto out2; 1894 } else 1895 if (ntfs_ib_write(icx, ib)) 1896 goto out2; 1897 1898 ret = STATUS_OK; 1899 out2: 1900 free(ie); 1901 out: 1902 free(ib); 1903 return ret; 1904 } 1905 1906 /** 1907 * ntfs_index_rm - remove entry from the index 1908 * @icx: index context describing entry to delete 1909 * 1910 * Delete entry described by @icx from the index. Index context is always 1911 * reinitialized after use of this function, so it can be used for index 1912 * lookup once again. 1913 * 1914 * Return 0 on success or -1 on error with errno set to the error code. 1915 */ 1916 /*static JPA*/ 1917 int ntfs_index_rm(ntfs_index_context *icx) 1918 { 1919 INDEX_HEADER *ih; 1920 int err, ret = STATUS_OK; 1921 1922 ntfs_log_trace("Entering\n"); 1923 1924 if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) { 1925 ntfs_log_error("Invalid arguments.\n"); 1926 errno = EINVAL; 1927 goto err_out; 1928 } 1929 if (icx->is_in_root) 1930 ih = &icx->ir->index; 1931 else 1932 ih = &icx->ib->index; 1933 1934 if (icx->entry->ie_flags & INDEX_ENTRY_NODE) { 1935 1936 ret = ntfs_index_rm_node(icx); 1937 1938 } else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) { 1939 1940 ntfs_ie_delete(ih, icx->entry); 1941 1942 if (icx->is_in_root) { 1943 err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); 1944 if (err != STATUS_OK) 1945 goto err_out; 1946 } else 1947 if (ntfs_icx_ib_write(icx)) 1948 goto err_out; 1949 } else { 1950 if (ntfs_index_rm_leaf(icx)) 1951 goto err_out; 1952 } 1953 out: 1954 return ret; 1955 err_out: 1956 ret = STATUS_ERROR; 1957 goto out; 1958 } 1959 1960 int ntfs_index_remove(ntfs_inode *dir_ni, 1961 ntfs_inode *ni __attribute__((unused)), 1962 const void *key, const int keylen) 1963 { 1964 int ret = STATUS_ERROR; 1965 ntfs_index_context *icx; 1966 1967 icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); 1968 if (!icx) 1969 return -1; 1970 1971 while (1) { 1972 1973 if (ntfs_index_lookup(key, keylen, icx)) 1974 goto err_out; 1975 1976 ret = ntfs_index_rm(icx); 1977 if (ret == STATUS_ERROR) 1978 goto err_out; 1979 else if (ret == STATUS_OK) 1980 break; 1981 1982 ntfs_inode_mark_dirty(icx->actx->ntfs_ino); 1983 ntfs_index_ctx_reinit(icx); 1984 } 1985 1986 ntfs_inode_mark_dirty(icx->actx->ntfs_ino); 1987 out: 1988 ntfs_index_ctx_put(icx); 1989 return ret; 1990 err_out: 1991 ret = STATUS_ERROR; 1992 ntfs_log_perror("Delete failed"); 1993 goto out; 1994 } 1995 1996 /** 1997 * ntfs_index_root_get - read the index root of an attribute 1998 * @ni: open ntfs inode in which the ntfs attribute resides 1999 * @attr: attribute for which we want its index root 2000 * 2001 * This function will read the related index root an ntfs attribute. 2002 * 2003 * On success a buffer is allocated with the content of the index root 2004 * and which needs to be freed when it's not needed anymore. 2005 * 2006 * On error NULL is returned with errno set to the error code. 2007 */ 2008 INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr) 2009 { 2010 ntfs_attr_search_ctx *ctx; 2011 ntfschar *name; 2012 INDEX_ROOT *root = NULL; 2013 2014 name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset)); 2015 2016 if (!ntfs_ir_lookup(ni, name, attr->name_length, &ctx)) 2017 return NULL; 2018 2019 root = ntfs_malloc(sizeof(INDEX_ROOT)); 2020 if (!root) 2021 goto out; 2022 2023 *root = *((INDEX_ROOT *)((u8 *)ctx->attr + 2024 le16_to_cpu(ctx->attr->value_offset))); 2025 out: 2026 ntfs_attr_put_search_ctx(ctx); 2027 return root; 2028 } 2029 2030 2031 /* 2032 * Walk down the index tree (leaf bound) 2033 * until there are no subnode in the first index entry 2034 * returns the entry at the bottom left in subnode 2035 */ 2036 2037 static INDEX_ENTRY *ntfs_index_walk_down(INDEX_ENTRY *ie, 2038 ntfs_index_context *ictx) 2039 { 2040 INDEX_ENTRY *entry; 2041 s64 vcn; 2042 2043 entry = ie; 2044 do { 2045 vcn = ntfs_ie_get_vcn(entry); 2046 if (ictx->is_in_root) { 2047 2048 /* down from level zero */ 2049 2050 ictx->ir = (INDEX_ROOT*)NULL; 2051 ictx->ib = (INDEX_BLOCK*)ntfs_malloc(ictx->block_size); 2052 ictx->pindex = 1; 2053 ictx->is_in_root = FALSE; 2054 } else { 2055 2056 /* down from non-zero level */ 2057 2058 ictx->pindex++; 2059 } 2060 ictx->parent_pos[ictx->pindex] = 0; 2061 ictx->parent_vcn[ictx->pindex] = vcn; 2062 if (!ntfs_ib_read(ictx,vcn,ictx->ib)) { 2063 ictx->entry = ntfs_ie_get_first(&ictx->ib->index); 2064 entry = ictx->entry; 2065 } else 2066 entry = (INDEX_ENTRY*)NULL; 2067 } while (entry && (entry->ie_flags & INDEX_ENTRY_NODE)); 2068 return (entry); 2069 } 2070 2071 /* 2072 * Walk up the index tree (root bound) 2073 * until there is a valid data entry in parent 2074 * returns the parent entry or NULL if no more parent 2075 */ 2076 2077 static INDEX_ENTRY *ntfs_index_walk_up(INDEX_ENTRY *ie, 2078 ntfs_index_context *ictx) 2079 { 2080 INDEX_ENTRY *entry; 2081 s64 vcn; 2082 2083 entry = ie; 2084 if (ictx->pindex > 0) { 2085 do { 2086 ictx->pindex--; 2087 if (!ictx->pindex) { 2088 2089 /* we have reached the root */ 2090 2091 free(ictx->ib); 2092 ictx->ib = (INDEX_BLOCK*)NULL; 2093 ictx->is_in_root = TRUE; 2094 /* a new search context is to be allocated */ 2095 if (ictx->actx) 2096 free(ictx->actx); 2097 ictx->ir = ntfs_ir_lookup(ictx->ni, 2098 ictx->name, ictx->name_len, 2099 &ictx->actx); 2100 if (ictx->ir) 2101 entry = ntfs_ie_get_by_pos( 2102 &ictx->ir->index, 2103 ictx->parent_pos[ictx->pindex]); 2104 else 2105 entry = (INDEX_ENTRY*)NULL; 2106 } else { 2107 /* up into non-root node */ 2108 vcn = ictx->parent_vcn[ictx->pindex]; 2109 if (!ntfs_ib_read(ictx,vcn,ictx->ib)) { 2110 entry = ntfs_ie_get_by_pos( 2111 &ictx->ib->index, 2112 ictx->parent_pos[ictx->pindex]); 2113 } else 2114 entry = (INDEX_ENTRY*)NULL; 2115 } 2116 ictx->entry = entry; 2117 } while (entry && (ictx->pindex > 0) 2118 && (entry->ie_flags & INDEX_ENTRY_END)); 2119 } else 2120 entry = (INDEX_ENTRY*)NULL; 2121 return (entry); 2122 } 2123 2124 /* 2125 * Get next entry in an index according to collating sequence. 2126 * Must be initialized through a ntfs_index_lookup() 2127 * 2128 * Returns next entry or NULL if none 2129 * 2130 * Sample layout : 2131 * 2132 * +---+---+---+---+---+---+---+---+ n ptrs to subnodes 2133 * | | | 10| 25| 33| | | | n-1 keys in between 2134 * +---+---+---+---+---+---+---+---+ no key in last entry 2135 * | A | A 2136 * | | | +-------------------------------+ 2137 * +--------------------------+ | +-----+ | 2138 * | +--+ | | 2139 * V | V | 2140 * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ 2141 * | 11| 12| 13| 14| 15| 16| 17| | | | 26| 27| 28| 29| 30| 31| 32| | 2142 * +---+---+---+---+---+---+---+---+ | +---+---+---+---+---+---+---+---+ 2143 * | | 2144 * +-----------------------+ | 2145 * | | 2146 * +---+---+---+---+---+---+---+---+ 2147 * | 18| 19| 20| 21| 22| 23| 24| | 2148 * +---+---+---+---+---+---+---+---+ 2149 */ 2150 2151 INDEX_ENTRY *ntfs_index_next(INDEX_ENTRY *ie, ntfs_index_context *ictx) 2152 { 2153 INDEX_ENTRY *next; 2154 le16 flags; 2155 2156 /* 2157 * lookup() may have returned an invalid node 2158 * when searching for a partial key 2159 * if this happens, walk up 2160 */ 2161 2162 if (ie->ie_flags & INDEX_ENTRY_END) 2163 next = ntfs_index_walk_up(ie, ictx); 2164 else { 2165 /* 2166 * get next entry in same node 2167 * there is always one after any entry with data 2168 */ 2169 2170 next = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length)); 2171 ++ictx->parent_pos[ictx->pindex]; 2172 flags = next->ie_flags; 2173 2174 /* walk down if it has a subnode */ 2175 2176 if (flags & INDEX_ENTRY_NODE) { 2177 next = ntfs_index_walk_down(next,ictx); 2178 } else { 2179 2180 /* walk up it has no subnode, nor data */ 2181 2182 if (flags & INDEX_ENTRY_END) { 2183 next = ntfs_index_walk_up(next, ictx); 2184 } 2185 } 2186 } 2187 /* return NULL if stuck at end of a block */ 2188 2189 if (next && (next->ie_flags & INDEX_ENTRY_END)) 2190 next = (INDEX_ENTRY*)NULL; 2191 return (next); 2192 } 2193 2194 2195