1 /** 2 * dir.c - Directory handling code. Originated from the Linux-NTFS project. 3 * 4 * Copyright (c) 2002-2005 Anton Altaparmakov 5 * Copyright (c) 2004-2005 Richard Russon 6 * Copyright (c) 2004-2008 Szabolcs Szakacsits 7 * Copyright (c) 2005-2007 Yura Pakhuchiy 8 * Copyright (c) 2008-2010 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_ERRNO_H 34 #include <errno.h> 35 #endif 36 #ifdef HAVE_STRING_H 37 #include <string.h> 38 #endif 39 #ifdef HAVE_SYS_STAT_H 40 #include <sys/stat.h> 41 #endif 42 43 #ifdef HAVE_SYS_SYSMACROS_H 44 #include <sys/sysmacros.h> 45 #endif 46 47 #include "param.h" 48 #include "types.h" 49 #include "debug.h" 50 #include "attrib.h" 51 #include "inode.h" 52 #include "dir.h" 53 #include "volume.h" 54 #include "mft.h" 55 #include "index.h" 56 #include "ntfstime.h" 57 #include "lcnalloc.h" 58 #include "logging.h" 59 #include "cache.h" 60 #include "misc.h" 61 #include "security.h" 62 #include "reparse.h" 63 #include "object_id.h" 64 65 #ifdef HAVE_SETXATTR 66 #include <sys/xattr.h> 67 #endif 68 69 /* 70 * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O" 71 * and "$Q" as global constants. 72 */ 73 ntfschar NTFS_INDEX_I30[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('I'), 74 const_cpu_to_le16('3'), const_cpu_to_le16('0'), 75 const_cpu_to_le16('\0') }; 76 ntfschar NTFS_INDEX_SII[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'), 77 const_cpu_to_le16('I'), const_cpu_to_le16('I'), 78 const_cpu_to_le16('\0') }; 79 ntfschar NTFS_INDEX_SDH[5] = { const_cpu_to_le16('$'), const_cpu_to_le16('S'), 80 const_cpu_to_le16('D'), const_cpu_to_le16('H'), 81 const_cpu_to_le16('\0') }; 82 ntfschar NTFS_INDEX_O[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('O'), 83 const_cpu_to_le16('\0') }; 84 ntfschar NTFS_INDEX_Q[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('Q'), 85 const_cpu_to_le16('\0') }; 86 ntfschar NTFS_INDEX_R[3] = { const_cpu_to_le16('$'), const_cpu_to_le16('R'), 87 const_cpu_to_le16('\0') }; 88 89 #if CACHE_INODE_SIZE 90 91 /* 92 * Pathname hashing 93 * 94 * Based on first char and second char (which may be '\0') 95 */ 96 97 int ntfs_dir_inode_hash(const struct CACHED_GENERIC *cached) 98 { 99 const char *path; 100 const unsigned char *name; 101 102 path = (const char*)cached->variable; 103 if (!path) { 104 ntfs_log_error("Bad inode cache entry\n"); 105 return (-1); 106 } 107 name = (const unsigned char*)strrchr(path,'/'); 108 if (!name) 109 name = (const unsigned char*)path; 110 return (((name[0] << 1) + name[1] + strlen((const char*)name)) 111 % (2*CACHE_INODE_SIZE)); 112 } 113 114 /* 115 * Pathname comparing for entering/fetching from cache 116 */ 117 118 static int inode_cache_compare(const struct CACHED_GENERIC *cached, 119 const struct CACHED_GENERIC *wanted) 120 { 121 return (!cached->variable 122 || strcmp(cached->variable, wanted->variable)); 123 } 124 125 /* 126 * Pathname comparing for invalidating entries in cache 127 * 128 * A partial path is compared in order to invalidate all paths 129 * related to a renamed directory 130 * inode numbers are also checked, as deleting a long name may 131 * imply deleting a short name and conversely 132 * 133 * Only use associated with a CACHE_NOHASH flag 134 */ 135 136 static int inode_cache_inv_compare(const struct CACHED_GENERIC *cached, 137 const struct CACHED_GENERIC *wanted) 138 { 139 int len; 140 BOOL different; 141 const struct CACHED_INODE *w; 142 const struct CACHED_INODE *c; 143 144 w = (const struct CACHED_INODE*)wanted; 145 c = (const struct CACHED_INODE*)cached; 146 if (w->pathname) { 147 len = strlen(w->pathname); 148 different = !cached->variable 149 || ((w->inum != MREF(c->inum)) 150 && (strncmp(c->pathname, w->pathname, len) 151 || ((c->pathname[len] != '\0') 152 && (c->pathname[len] != '/')))); 153 } else 154 different = !c->pathname 155 || (w->inum != MREF(c->inum)); 156 return (different); 157 } 158 159 #endif 160 161 #if CACHE_LOOKUP_SIZE 162 163 /* 164 * File name comparing for entering/fetching from lookup cache 165 */ 166 167 static int lookup_cache_compare(const struct CACHED_GENERIC *cached, 168 const struct CACHED_GENERIC *wanted) 169 { 170 const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached; 171 const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted; 172 return (!c->name 173 || (c->parent != w->parent) 174 || (c->namesize != w->namesize) 175 || memcmp(c->name, w->name, c->namesize)); 176 } 177 178 /* 179 * Inode number comparing for invalidating lookup cache 180 * 181 * All entries with designated inode number are invalidated 182 * 183 * Only use associated with a CACHE_NOHASH flag 184 */ 185 186 static int lookup_cache_inv_compare(const struct CACHED_GENERIC *cached, 187 const struct CACHED_GENERIC *wanted) 188 { 189 const struct CACHED_LOOKUP *c = (const struct CACHED_LOOKUP*) cached; 190 const struct CACHED_LOOKUP *w = (const struct CACHED_LOOKUP*) wanted; 191 return (!c->name 192 || (c->parent != w->parent) 193 || (MREF(c->inum) != MREF(w->inum))); 194 } 195 196 /* 197 * Lookup hashing 198 * 199 * Based on first, second and and last char 200 */ 201 202 int ntfs_dir_lookup_hash(const struct CACHED_GENERIC *cached) 203 { 204 const unsigned char *name; 205 int count; 206 unsigned int val; 207 208 name = (const unsigned char*)cached->variable; 209 count = cached->varsize; 210 if (!name || !count) { 211 ntfs_log_error("Bad lookup cache entry\n"); 212 return (-1); 213 } 214 val = (name[0] << 2) + (name[1] << 1) + name[count - 1] + count; 215 return (val % (2*CACHE_LOOKUP_SIZE)); 216 } 217 218 #endif 219 220 /** 221 * ntfs_inode_lookup_by_name - find an inode in a directory given its name 222 * @dir_ni: ntfs inode of the directory in which to search for the name 223 * @uname: Unicode name for which to search in the directory 224 * @uname_len: length of the name @uname in Unicode characters 225 * 226 * Look for an inode with name @uname in the directory with inode @dir_ni. 227 * ntfs_inode_lookup_by_name() walks the contents of the directory looking for 228 * the Unicode name. If the name is found in the directory, the corresponding 229 * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it 230 * is a 64-bit number containing the sequence number. 231 * 232 * On error, return -1 with errno set to the error code. If the inode is is not 233 * found errno is ENOENT. 234 * 235 * Note, @uname_len does not include the (optional) terminating NULL character. 236 * 237 * Note, we look for a case sensitive match first but we also look for a case 238 * insensitive match at the same time. If we find a case insensitive match, we 239 * save that for the case that we don't find an exact match, where we return 240 * the mft reference of the case insensitive match. 241 * 242 * If the volume is mounted with the case sensitive flag set, then we only 243 * allow exact matches. 244 */ 245 u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, 246 const ntfschar *uname, const int uname_len) 247 { 248 VCN vcn; 249 u64 mref = 0; 250 s64 br; 251 ntfs_volume *vol = dir_ni->vol; 252 ntfs_attr_search_ctx *ctx; 253 INDEX_ROOT *ir; 254 INDEX_ENTRY *ie; 255 INDEX_ALLOCATION *ia; 256 IGNORE_CASE_BOOL case_sensitivity; 257 u8 *index_end; 258 ntfs_attr *ia_na; 259 int eo, rc; 260 u32 index_block_size; 261 u8 index_vcn_size_bits; 262 263 ntfs_log_trace("Entering\n"); 264 265 if (!dir_ni || !dir_ni->mrec || !uname || uname_len <= 0) { 266 errno = EINVAL; 267 return -1; 268 } 269 270 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL); 271 if (!ctx) 272 return -1; 273 274 /* Find the index root attribute in the mft record. */ 275 if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL, 276 0, ctx)) { 277 ntfs_log_perror("Index root attribute missing in directory inode " 278 "%lld", (unsigned long long)dir_ni->mft_no); 279 goto put_err_out; 280 } 281 case_sensitivity = (NVolCaseSensitive(vol) ? CASE_SENSITIVE : IGNORE_CASE); 282 /* Get to the index root value. */ 283 ir = (INDEX_ROOT*)((u8*)ctx->attr + 284 le16_to_cpu(ctx->attr->value_offset)); 285 index_block_size = le32_to_cpu(ir->index_block_size); 286 if (index_block_size < NTFS_BLOCK_SIZE || 287 index_block_size & (index_block_size - 1)) { 288 ntfs_log_error("Index block size %u is invalid.\n", 289 (unsigned)index_block_size); 290 goto put_err_out; 291 } 292 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); 293 /* The first index entry. */ 294 ie = (INDEX_ENTRY*)((u8*)&ir->index + 295 le32_to_cpu(ir->index.entries_offset)); 296 /* 297 * Loop until we exceed valid memory (corruption case) or until we 298 * reach the last entry. 299 */ 300 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 301 /* Bounds checks. */ 302 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + 303 sizeof(INDEX_ENTRY_HEADER) > index_end || 304 (u8*)ie + le16_to_cpu(ie->key_length) > 305 index_end) { 306 ntfs_log_error("Index entry out of bounds in inode %lld" 307 "\n", (unsigned long long)dir_ni->mft_no); 308 goto put_err_out; 309 } 310 /* 311 * The last entry cannot contain a name. It can however contain 312 * a pointer to a child node in the B+tree so we just break out. 313 */ 314 if (ie->ie_flags & INDEX_ENTRY_END) 315 break; 316 317 if (!le16_to_cpu(ie->length)) { 318 ntfs_log_error("Zero length index entry in inode %lld" 319 "\n", (unsigned long long)dir_ni->mft_no); 320 goto put_err_out; 321 } 322 /* 323 * Not a perfect match, need to do full blown collation so we 324 * know which way in the B+tree we have to go. 325 */ 326 rc = ntfs_names_full_collate(uname, uname_len, 327 (ntfschar*)&ie->key.file_name.file_name, 328 ie->key.file_name.file_name_length, 329 case_sensitivity, vol->upcase, vol->upcase_len); 330 /* 331 * If uname collates before the name of the current entry, there 332 * is definitely no such name in this index but we might need to 333 * descend into the B+tree so we just break out of the loop. 334 */ 335 if (rc == -1) 336 break; 337 /* The names are not equal, continue the search. */ 338 if (rc) 339 continue; 340 /* 341 * Perfect match, this will never happen as the 342 * ntfs_are_names_equal() call will have gotten a match but we 343 * still treat it correctly. 344 */ 345 mref = le64_to_cpu(ie->indexed_file); 346 ntfs_attr_put_search_ctx(ctx); 347 return mref; 348 } 349 /* 350 * We have finished with this index without success. Check for the 351 * presence of a child node and if not present return error code 352 * ENOENT, unless we have got the mft reference of a matching name 353 * cached in mref in which case return mref. 354 */ 355 if (!(ie->ie_flags & INDEX_ENTRY_NODE)) { 356 ntfs_attr_put_search_ctx(ctx); 357 if (mref) 358 return mref; 359 ntfs_log_debug("Entry not found - between root entries.\n"); 360 errno = ENOENT; 361 return -1; 362 } /* Child node present, descend into it. */ 363 364 /* Open the index allocation attribute. */ 365 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); 366 if (!ia_na) { 367 ntfs_log_perror("Failed to open index allocation (inode %lld)", 368 (unsigned long long)dir_ni->mft_no); 369 goto put_err_out; 370 } 371 372 /* Allocate a buffer for the current index block. */ 373 ia = ntfs_malloc(index_block_size); 374 if (!ia) { 375 ntfs_attr_close(ia_na); 376 goto put_err_out; 377 } 378 379 /* Determine the size of a vcn in the directory index. */ 380 if (vol->cluster_size <= index_block_size) { 381 index_vcn_size_bits = vol->cluster_size_bits; 382 } else { 383 index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS; 384 } 385 386 /* Get the starting vcn of the index_block holding the child node. */ 387 vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); 388 389 descend_into_child_node: 390 391 /* Read the index block starting at vcn. */ 392 br = ntfs_attr_mst_pread(ia_na, vcn << index_vcn_size_bits, 1, 393 index_block_size, ia); 394 if (br != 1) { 395 if (br != -1) 396 errno = EIO; 397 ntfs_log_perror("Failed to read vcn 0x%llx", 398 (unsigned long long)vcn); 399 goto close_err_out; 400 } 401 402 if (sle64_to_cpu(ia->index_block_vcn) != vcn) { 403 ntfs_log_error("Actual VCN (0x%llx) of index buffer is different " 404 "from expected VCN (0x%llx).\n", 405 (long long)sle64_to_cpu(ia->index_block_vcn), 406 (long long)vcn); 407 errno = EIO; 408 goto close_err_out; 409 } 410 if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) { 411 ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx " 412 "has a size (%u) differing from the directory " 413 "specified size (%u).\n", (long long)vcn, 414 (unsigned long long)dir_ni->mft_no, 415 (unsigned) le32_to_cpu(ia->index.allocated_size) + 0x18, 416 (unsigned)index_block_size); 417 errno = EIO; 418 goto close_err_out; 419 } 420 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); 421 if (index_end > (u8*)ia + index_block_size) { 422 ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode " 423 "0x%llx exceeds maximum size.\n", 424 (long long)vcn, (unsigned long long)dir_ni->mft_no); 425 errno = EIO; 426 goto close_err_out; 427 } 428 429 /* The first index entry. */ 430 ie = (INDEX_ENTRY*)((u8*)&ia->index + 431 le32_to_cpu(ia->index.entries_offset)); 432 /* 433 * Iterate similar to above big loop but applied to index buffer, thus 434 * loop until we exceed valid memory (corruption case) or until we 435 * reach the last entry. 436 */ 437 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 438 /* Bounds check. */ 439 if ((u8*)ie < (u8*)ia || (u8*)ie + 440 sizeof(INDEX_ENTRY_HEADER) > index_end || 441 (u8*)ie + le16_to_cpu(ie->key_length) > 442 index_end) { 443 ntfs_log_error("Index entry out of bounds in directory " 444 "inode %lld.\n", 445 (unsigned long long)dir_ni->mft_no); 446 errno = EIO; 447 goto close_err_out; 448 } 449 /* 450 * The last entry cannot contain a name. It can however contain 451 * a pointer to a child node in the B+tree so we just break out. 452 */ 453 if (ie->ie_flags & INDEX_ENTRY_END) 454 break; 455 456 if (!le16_to_cpu(ie->length)) { 457 errno = EIO; 458 ntfs_log_error("Zero length index entry in inode %lld" 459 "\n", (unsigned long long)dir_ni->mft_no); 460 goto close_err_out; 461 } 462 /* 463 * Not a perfect match, need to do full blown collation so we 464 * know which way in the B+tree we have to go. 465 */ 466 rc = ntfs_names_full_collate(uname, uname_len, 467 (ntfschar*)&ie->key.file_name.file_name, 468 ie->key.file_name.file_name_length, 469 case_sensitivity, vol->upcase, vol->upcase_len); 470 /* 471 * If uname collates before the name of the current entry, there 472 * is definitely no such name in this index but we might need to 473 * descend into the B+tree so we just break out of the loop. 474 */ 475 if (rc == -1) 476 break; 477 /* The names are not equal, continue the search. */ 478 if (rc) 479 continue; 480 mref = le64_to_cpu(ie->indexed_file); 481 free(ia); 482 ntfs_attr_close(ia_na); 483 ntfs_attr_put_search_ctx(ctx); 484 return mref; 485 } 486 /* 487 * We have finished with this index buffer without success. Check for 488 * the presence of a child node. 489 */ 490 if (ie->ie_flags & INDEX_ENTRY_NODE) { 491 if ((ia->index.ih_flags & NODE_MASK) == LEAF_NODE) { 492 ntfs_log_error("Index entry with child node found in a leaf " 493 "node in directory inode %lld.\n", 494 (unsigned long long)dir_ni->mft_no); 495 errno = EIO; 496 goto close_err_out; 497 } 498 /* Child node present, descend into it. */ 499 vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8); 500 if (vcn >= 0) 501 goto descend_into_child_node; 502 ntfs_log_error("Negative child node vcn in directory inode " 503 "0x%llx.\n", (unsigned long long)dir_ni->mft_no); 504 errno = EIO; 505 goto close_err_out; 506 } 507 free(ia); 508 ntfs_attr_close(ia_na); 509 ntfs_attr_put_search_ctx(ctx); 510 /* 511 * No child node present, return error code ENOENT, unless we have got 512 * the mft reference of a matching name cached in mref in which case 513 * return mref. 514 */ 515 if (mref) 516 return mref; 517 ntfs_log_debug("Entry not found.\n"); 518 errno = ENOENT; 519 return -1; 520 put_err_out: 521 eo = EIO; 522 ntfs_log_debug("Corrupt directory. Aborting lookup.\n"); 523 eo_put_err_out: 524 ntfs_attr_put_search_ctx(ctx); 525 errno = eo; 526 return -1; 527 close_err_out: 528 eo = errno; 529 free(ia); 530 ntfs_attr_close(ia_na); 531 goto eo_put_err_out; 532 } 533 534 /* 535 * Lookup a file in a directory from its UTF-8 name 536 * 537 * The name is first fetched from cache if one is defined 538 * 539 * Returns the inode number 540 * or -1 if not possible (errno tells why) 541 */ 542 543 u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name) 544 { 545 int uname_len; 546 ntfschar *uname = (ntfschar*)NULL; 547 u64 inum; 548 char *cached_name; 549 const char *const_name; 550 551 if (!NVolCaseSensitive(dir_ni->vol)) { 552 cached_name = ntfs_uppercase_mbs(name, 553 dir_ni->vol->upcase, dir_ni->vol->upcase_len); 554 const_name = cached_name; 555 } else { 556 cached_name = (char*)NULL; 557 const_name = name; 558 } 559 if (const_name) { 560 #if CACHE_LOOKUP_SIZE 561 562 /* 563 * fetch inode from cache 564 */ 565 566 if (dir_ni->vol->lookup_cache) { 567 struct CACHED_LOOKUP item; 568 struct CACHED_LOOKUP *cached; 569 570 item.name = const_name; 571 item.namesize = strlen(const_name) + 1; 572 item.parent = dir_ni->mft_no; 573 cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache( 574 dir_ni->vol->lookup_cache, 575 GENERIC(&item), lookup_cache_compare); 576 if (cached) { 577 inum = cached->inum; 578 if (inum == (u64)-1) 579 errno = ENOENT; 580 } else { 581 /* Generate unicode name. */ 582 uname_len = ntfs_mbstoucs(name, &uname); 583 if (uname_len >= 0) { 584 inum = ntfs_inode_lookup_by_name(dir_ni, 585 uname, uname_len); 586 item.inum = inum; 587 /* enter into cache, even if not found */ 588 ntfs_enter_cache(dir_ni->vol->lookup_cache, 589 GENERIC(&item), 590 lookup_cache_compare); 591 free(uname); 592 } else 593 inum = (s64)-1; 594 } 595 } else 596 #endif 597 { 598 /* Generate unicode name. */ 599 uname_len = ntfs_mbstoucs(cached_name, &uname); 600 if (uname_len >= 0) 601 inum = ntfs_inode_lookup_by_name(dir_ni, 602 uname, uname_len); 603 else 604 inum = (s64)-1; 605 } 606 if (cached_name) 607 free(cached_name); 608 } else 609 inum = (s64)-1; 610 return (inum); 611 } 612 613 /* 614 * Update a cache lookup record when a name has been defined 615 * 616 * The UTF-8 name is required 617 */ 618 619 void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, u64 inum) 620 { 621 #if CACHE_LOOKUP_SIZE 622 struct CACHED_LOOKUP item; 623 struct CACHED_LOOKUP *cached; 624 char *cached_name; 625 626 if (dir_ni->vol->lookup_cache) { 627 if (!NVolCaseSensitive(dir_ni->vol)) { 628 cached_name = ntfs_uppercase_mbs(name, 629 dir_ni->vol->upcase, dir_ni->vol->upcase_len); 630 item.name = cached_name; 631 } else { 632 cached_name = (char*)NULL; 633 item.name = name; 634 } 635 if (item.name) { 636 item.namesize = strlen(item.name) + 1; 637 item.parent = dir_ni->mft_no; 638 item.inum = inum; 639 cached = (struct CACHED_LOOKUP*)ntfs_enter_cache( 640 dir_ni->vol->lookup_cache, 641 GENERIC(&item), lookup_cache_compare); 642 if (cached) 643 cached->inum = inum; 644 if (cached_name) 645 free(cached_name); 646 } 647 } 648 #endif 649 } 650 651 /** 652 * ntfs_pathname_to_inode - Find the inode which represents the given pathname 653 * @vol: An ntfs volume obtained from ntfs_mount 654 * @parent: A directory inode to begin the search (may be NULL) 655 * @pathname: Pathname to be located 656 * 657 * Take an ASCII pathname and find the inode that represents it. The function 658 * splits the path and then descends the directory tree. If @parent is NULL, 659 * then the root directory '.' will be used as the base for the search. 660 * 661 * Return: inode Success, the pathname was valid 662 * NULL Error, the pathname was invalid, or some other error occurred 663 */ 664 ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, 665 const char *pathname) 666 { 667 u64 inum; 668 int len, err = 0; 669 char *p, *q; 670 ntfs_inode *ni; 671 ntfs_inode *result = NULL; 672 ntfschar *unicode = NULL; 673 char *ascii = NULL; 674 #if CACHE_INODE_SIZE 675 struct CACHED_INODE item; 676 struct CACHED_INODE *cached; 677 char *fullname; 678 #endif 679 680 if (!vol || !pathname) { 681 errno = EINVAL; 682 return NULL; 683 } 684 685 ntfs_log_trace("path: '%s'\n", pathname); 686 687 ascii = strdup(pathname); 688 if (!ascii) { 689 ntfs_log_error("Out of memory.\n"); 690 err = ENOMEM; 691 goto out; 692 } 693 694 p = ascii; 695 /* Remove leading /'s. */ 696 while (p && *p && *p == PATH_SEP) 697 p++; 698 #if CACHE_INODE_SIZE 699 fullname = p; 700 if (p[0] && (p[strlen(p)-1] == PATH_SEP)) 701 ntfs_log_error("Unnormalized path %s\n",ascii); 702 #endif 703 if (parent) { 704 ni = parent; 705 } else { 706 #if CACHE_INODE_SIZE 707 /* 708 * fetch inode for full path from cache 709 */ 710 if (*fullname) { 711 item.pathname = fullname; 712 item.varsize = strlen(fullname) + 1; 713 cached = (struct CACHED_INODE*)ntfs_fetch_cache( 714 vol->xinode_cache, GENERIC(&item), 715 inode_cache_compare); 716 } else 717 cached = (struct CACHED_INODE*)NULL; 718 if (cached) { 719 /* 720 * return opened inode if found in cache 721 */ 722 inum = MREF(cached->inum); 723 ni = ntfs_inode_open(vol, inum); 724 if (!ni) { 725 ntfs_log_debug("Cannot open inode %llu: %s.\n", 726 (unsigned long long)inum, p); 727 err = EIO; 728 } 729 result = ni; 730 goto out; 731 } 732 #endif 733 ni = ntfs_inode_open(vol, FILE_root); 734 if (!ni) { 735 ntfs_log_debug("Couldn't open the inode of the root " 736 "directory.\n"); 737 err = EIO; 738 result = (ntfs_inode*)NULL; 739 goto out; 740 } 741 } 742 743 while (p && *p) { 744 /* Find the end of the first token. */ 745 q = strchr(p, PATH_SEP); 746 if (q != NULL) { 747 *q = '\0'; 748 } 749 #if CACHE_INODE_SIZE 750 /* 751 * fetch inode for partial path from cache 752 */ 753 cached = (struct CACHED_INODE*)NULL; 754 if (!parent) { 755 item.pathname = fullname; 756 item.varsize = strlen(fullname) + 1; 757 cached = (struct CACHED_INODE*)ntfs_fetch_cache( 758 vol->xinode_cache, GENERIC(&item), 759 inode_cache_compare); 760 if (cached) { 761 inum = cached->inum; 762 } 763 } 764 /* 765 * if not in cache, translate, search, then 766 * insert into cache if found 767 */ 768 if (!cached) { 769 len = ntfs_mbstoucs(p, &unicode); 770 if (len < 0) { 771 ntfs_log_perror("Could not convert filename to Unicode:" 772 " '%s'", p); 773 err = errno; 774 goto close; 775 } else if (len > NTFS_MAX_NAME_LEN) { 776 err = ENAMETOOLONG; 777 goto close; 778 } 779 inum = ntfs_inode_lookup_by_name(ni, unicode, len); 780 if (!parent && (inum != (u64) -1)) { 781 item.inum = inum; 782 ntfs_enter_cache(vol->xinode_cache, 783 GENERIC(&item), 784 inode_cache_compare); 785 } 786 } 787 #else 788 len = ntfs_mbstoucs(p, &unicode); 789 if (len < 0) { 790 ntfs_log_perror("Could not convert filename to Unicode:" 791 " '%s'", p); 792 err = errno; 793 goto close; 794 } else if (len > NTFS_MAX_NAME_LEN) { 795 err = ENAMETOOLONG; 796 goto close; 797 } 798 inum = ntfs_inode_lookup_by_name(ni, unicode, len); 799 #endif 800 if (inum == (u64) -1) { 801 ntfs_log_debug("Couldn't find name '%s' in pathname " 802 "'%s'.\n", p, pathname); 803 err = ENOENT; 804 goto close; 805 } 806 807 if (ni != parent) 808 if (ntfs_inode_close(ni)) { 809 err = errno; 810 goto out; 811 } 812 813 inum = MREF(inum); 814 ni = ntfs_inode_open(vol, inum); 815 if (!ni) { 816 ntfs_log_debug("Cannot open inode %llu: %s.\n", 817 (unsigned long long)inum, p); 818 err = EIO; 819 goto close; 820 } 821 822 free(unicode); 823 unicode = NULL; 824 825 if (q) *q++ = PATH_SEP; /* JPA */ 826 p = q; 827 while (p && *p && *p == PATH_SEP) 828 p++; 829 } 830 831 result = ni; 832 ni = NULL; 833 close: 834 if (ni && (ni != parent)) 835 if (ntfs_inode_close(ni) && !err) 836 err = errno; 837 out: 838 free(ascii); 839 free(unicode); 840 if (err) 841 errno = err; 842 return result; 843 } 844 845 /* 846 * The little endian Unicode string ".." for ntfs_readdir(). 847 */ 848 static const ntfschar dotdot[3] = { const_cpu_to_le16('.'), 849 const_cpu_to_le16('.'), 850 const_cpu_to_le16('\0') }; 851 852 /* 853 * union index_union - 854 * More helpers for ntfs_readdir(). 855 */ 856 typedef union { 857 INDEX_ROOT *ir; 858 INDEX_ALLOCATION *ia; 859 } index_union __attribute__((__transparent_union__)); 860 861 /** 862 * enum INDEX_TYPE - 863 * More helpers for ntfs_readdir(). 864 */ 865 typedef enum { 866 INDEX_TYPE_ROOT, /* index root */ 867 INDEX_TYPE_ALLOCATION, /* index allocation */ 868 } INDEX_TYPE; 869 870 /** 871 * ntfs_filldir - ntfs specific filldir method 872 * @dir_ni: ntfs inode of current directory 873 * @pos: current position in directory 874 * @ivcn_bits: log(2) of index vcn size 875 * @index_type: specifies whether @iu is an index root or an index allocation 876 * @iu: index root or index block to which @ie belongs 877 * @ie: current index entry 878 * @dirent: context for filldir callback supplied by the caller 879 * @filldir: filldir callback supplied by the caller 880 * 881 * Pass information specifying the current directory entry @ie to the @filldir 882 * callback. 883 */ 884 static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits, 885 const INDEX_TYPE index_type, index_union iu, INDEX_ENTRY *ie, 886 void *dirent, ntfs_filldir_t filldir) 887 { 888 FILE_NAME_ATTR *fn = &ie->key.file_name; 889 unsigned dt_type; 890 BOOL metadata; 891 ntfschar *loname; 892 int res; 893 MFT_REF mref; 894 895 ntfs_log_trace("Entering.\n"); 896 897 /* Advance the position even if going to skip the entry. */ 898 if (index_type == INDEX_TYPE_ALLOCATION) 899 *pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu( 900 iu.ia->index_block_vcn) << ivcn_bits) + 901 dir_ni->vol->mft_record_size; 902 else /* if (index_type == INDEX_TYPE_ROOT) */ 903 *pos = (u8*)ie - (u8*)iu.ir; 904 /* Skip root directory self reference entry. */ 905 if (MREF_LE(ie->indexed_file) == FILE_root) 906 return 0; 907 if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT) 908 dt_type = NTFS_DT_DIR; 909 else if (fn->file_attributes & FILE_ATTR_SYSTEM) 910 dt_type = NTFS_DT_UNKNOWN; 911 else 912 dt_type = NTFS_DT_REG; 913 914 /* return metadata files and hidden files if requested */ 915 mref = le64_to_cpu(ie->indexed_file); 916 metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); 917 if ((!metadata && (NVolShowHidFiles(dir_ni->vol) 918 || !(fn->file_attributes & FILE_ATTR_HIDDEN))) 919 || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol) 920 || metadata))) { 921 if (NVolCaseSensitive(dir_ni->vol)) { 922 res = filldir(dirent, fn->file_name, 923 fn->file_name_length, 924 fn->file_name_type, *pos, 925 mref, dt_type); 926 } else { 927 loname = (ntfschar*)ntfs_malloc(2*fn->file_name_length); 928 if (loname) { 929 memcpy(loname, fn->file_name, 930 2*fn->file_name_length); 931 ntfs_name_locase(loname, fn->file_name_length, 932 dir_ni->vol->locase, 933 dir_ni->vol->upcase_len); 934 res = filldir(dirent, loname, 935 fn->file_name_length, 936 fn->file_name_type, *pos, 937 mref, dt_type); 938 free(loname); 939 } else 940 res = -1; 941 } 942 } else 943 res = 0; 944 return (res); 945 } 946 947 /** 948 * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode 949 * @ni: ntfs inode whose parent directory to find 950 * 951 * Find the parent directory of the ntfs inode @ni. To do this, find the first 952 * file name attribute in the mft record of @ni and return the parent mft 953 * reference from that. 954 * 955 * Note this only makes sense for directories, since files can be hard linked 956 * from multiple directories and there is no way for us to tell which one is 957 * being looked for. 958 * 959 * Technically directories can have hard links, too, but we consider that as 960 * illegal as Linux/UNIX do not support directory hard links. 961 * 962 * Return the mft reference of the parent directory on success or -1 on error 963 * with errno set to the error code. 964 */ 965 static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) 966 { 967 MFT_REF mref; 968 ntfs_attr_search_ctx *ctx; 969 FILE_NAME_ATTR *fn; 970 int eo; 971 972 ntfs_log_trace("Entering.\n"); 973 974 if (!ni) { 975 errno = EINVAL; 976 return ERR_MREF(-1); 977 } 978 979 ctx = ntfs_attr_get_search_ctx(ni, NULL); 980 if (!ctx) 981 return ERR_MREF(-1); 982 if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { 983 ntfs_log_error("No file name found in inode %lld\n", 984 (unsigned long long)ni->mft_no); 985 goto err_out; 986 } 987 if (ctx->attr->non_resident) { 988 ntfs_log_error("File name attribute must be resident (inode " 989 "%lld)\n", (unsigned long long)ni->mft_no); 990 goto io_err_out; 991 } 992 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + 993 le16_to_cpu(ctx->attr->value_offset)); 994 if ((u8*)fn + le32_to_cpu(ctx->attr->value_length) > 995 (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) { 996 ntfs_log_error("Corrupt file name attribute in inode %lld.\n", 997 (unsigned long long)ni->mft_no); 998 goto io_err_out; 999 } 1000 mref = le64_to_cpu(fn->parent_directory); 1001 ntfs_attr_put_search_ctx(ctx); 1002 return mref; 1003 io_err_out: 1004 errno = EIO; 1005 err_out: 1006 eo = errno; 1007 ntfs_attr_put_search_ctx(ctx); 1008 errno = eo; 1009 return ERR_MREF(-1); 1010 } 1011 1012 /** 1013 * ntfs_readdir - read the contents of an ntfs directory 1014 * @dir_ni: ntfs inode of current directory 1015 * @pos: current position in directory 1016 * @dirent: context for filldir callback supplied by the caller 1017 * @filldir: filldir callback supplied by the caller 1018 * 1019 * Parse the index root and the index blocks that are marked in use in the 1020 * index bitmap and hand each found directory entry to the @filldir callback 1021 * supplied by the caller. 1022 * 1023 * Return 0 on success or -1 on error with errno set to the error code. 1024 * 1025 * Note: Index blocks are parsed in ascending vcn order, from which follows 1026 * that the directory entries are not returned sorted. 1027 */ 1028 int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, 1029 void *dirent, ntfs_filldir_t filldir) 1030 { 1031 s64 i_size, br, ia_pos, bmp_pos, ia_start; 1032 ntfs_volume *vol; 1033 ntfs_attr *ia_na, *bmp_na = NULL; 1034 ntfs_attr_search_ctx *ctx = NULL; 1035 u8 *index_end, *bmp = NULL; 1036 INDEX_ROOT *ir; 1037 INDEX_ENTRY *ie; 1038 INDEX_ALLOCATION *ia = NULL; 1039 int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo; 1040 u32 index_block_size; 1041 u8 index_block_size_bits, index_vcn_size_bits; 1042 1043 ntfs_log_trace("Entering.\n"); 1044 1045 if (!dir_ni || !pos || !filldir) { 1046 errno = EINVAL; 1047 return -1; 1048 } 1049 1050 if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { 1051 errno = ENOTDIR; 1052 return -1; 1053 } 1054 1055 vol = dir_ni->vol; 1056 1057 ntfs_log_trace("Entering for inode %lld, *pos 0x%llx.\n", 1058 (unsigned long long)dir_ni->mft_no, (long long)*pos); 1059 1060 /* Open the index allocation attribute. */ 1061 ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4); 1062 if (!ia_na) { 1063 if (errno != ENOENT) { 1064 ntfs_log_perror("Failed to open index allocation attribute. " 1065 "Directory inode %lld is corrupt or bug", 1066 (unsigned long long)dir_ni->mft_no); 1067 return -1; 1068 } 1069 i_size = 0; 1070 } else 1071 i_size = ia_na->data_size; 1072 1073 rc = 0; 1074 1075 /* Are we at end of dir yet? */ 1076 if (*pos >= i_size + vol->mft_record_size) 1077 goto done; 1078 1079 /* Emulate . and .. for all directories. */ 1080 if (!*pos) { 1081 rc = filldir(dirent, dotdot, 1, FILE_NAME_POSIX, *pos, 1082 MK_MREF(dir_ni->mft_no, 1083 le16_to_cpu(dir_ni->mrec->sequence_number)), 1084 NTFS_DT_DIR); 1085 if (rc) 1086 goto err_out; 1087 ++*pos; 1088 } 1089 if (*pos == 1) { 1090 MFT_REF parent_mref; 1091 1092 parent_mref = ntfs_mft_get_parent_ref(dir_ni); 1093 if (parent_mref == ERR_MREF(-1)) { 1094 ntfs_log_perror("Parent directory not found"); 1095 goto dir_err_out; 1096 } 1097 1098 rc = filldir(dirent, dotdot, 2, FILE_NAME_POSIX, *pos, 1099 parent_mref, NTFS_DT_DIR); 1100 if (rc) 1101 goto err_out; 1102 ++*pos; 1103 } 1104 1105 ctx = ntfs_attr_get_search_ctx(dir_ni, NULL); 1106 if (!ctx) 1107 goto err_out; 1108 1109 /* Get the offset into the index root attribute. */ 1110 ir_pos = (int)*pos; 1111 /* Find the index root attribute in the mft record. */ 1112 if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL, 1113 0, ctx)) { 1114 ntfs_log_perror("Index root attribute missing in directory inode " 1115 "%lld", (unsigned long long)dir_ni->mft_no); 1116 goto dir_err_out; 1117 } 1118 /* Get to the index root value. */ 1119 ir = (INDEX_ROOT*)((u8*)ctx->attr + 1120 le16_to_cpu(ctx->attr->value_offset)); 1121 1122 /* Determine the size of a vcn in the directory index. */ 1123 index_block_size = le32_to_cpu(ir->index_block_size); 1124 if (index_block_size < NTFS_BLOCK_SIZE || 1125 index_block_size & (index_block_size - 1)) { 1126 ntfs_log_error("Index block size %u is invalid.\n", 1127 (unsigned)index_block_size); 1128 goto dir_err_out; 1129 } 1130 index_block_size_bits = ffs(index_block_size) - 1; 1131 if (vol->cluster_size <= index_block_size) { 1132 index_vcn_size_bits = vol->cluster_size_bits; 1133 } else { 1134 index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS; 1135 } 1136 1137 /* Are we jumping straight into the index allocation attribute? */ 1138 if (*pos >= vol->mft_record_size) { 1139 ntfs_attr_put_search_ctx(ctx); 1140 ctx = NULL; 1141 goto skip_index_root; 1142 } 1143 1144 index_end = (u8*)&ir->index + le32_to_cpu(ir->index.index_length); 1145 /* The first index entry. */ 1146 ie = (INDEX_ENTRY*)((u8*)&ir->index + 1147 le32_to_cpu(ir->index.entries_offset)); 1148 /* 1149 * Loop until we exceed valid memory (corruption case) or until we 1150 * reach the last entry or until filldir tells us it has had enough 1151 * or signals an error (both covered by the rc test). 1152 */ 1153 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 1154 ntfs_log_debug("In index root, offset %d.\n", (int)((u8*)ie - (u8*)ir)); 1155 /* Bounds checks. */ 1156 if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie + 1157 sizeof(INDEX_ENTRY_HEADER) > index_end || 1158 (u8*)ie + le16_to_cpu(ie->key_length) > 1159 index_end) 1160 goto dir_err_out; 1161 /* The last entry cannot contain a name. */ 1162 if (ie->ie_flags & INDEX_ENTRY_END) 1163 break; 1164 1165 if (!le16_to_cpu(ie->length)) 1166 goto dir_err_out; 1167 1168 /* Skip index root entry if continuing previous readdir. */ 1169 if (ir_pos > (u8*)ie - (u8*)ir) 1170 continue; 1171 /* 1172 * Submit the directory entry to ntfs_filldir(), which will 1173 * invoke the filldir() callback as appropriate. 1174 */ 1175 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits, 1176 INDEX_TYPE_ROOT, ir, ie, dirent, filldir); 1177 if (rc) { 1178 ntfs_attr_put_search_ctx(ctx); 1179 ctx = NULL; 1180 goto err_out; 1181 } 1182 } 1183 ntfs_attr_put_search_ctx(ctx); 1184 ctx = NULL; 1185 1186 /* If there is no index allocation attribute we are finished. */ 1187 if (!ia_na) 1188 goto EOD; 1189 1190 /* Advance *pos to the beginning of the index allocation. */ 1191 *pos = vol->mft_record_size; 1192 1193 skip_index_root: 1194 1195 if (!ia_na) 1196 goto done; 1197 1198 /* Allocate a buffer for the current index block. */ 1199 ia = ntfs_malloc(index_block_size); 1200 if (!ia) 1201 goto err_out; 1202 1203 bmp_na = ntfs_attr_open(dir_ni, AT_BITMAP, NTFS_INDEX_I30, 4); 1204 if (!bmp_na) { 1205 ntfs_log_perror("Failed to open index bitmap attribute"); 1206 goto dir_err_out; 1207 } 1208 1209 /* Get the offset into the index allocation attribute. */ 1210 ia_pos = *pos - vol->mft_record_size; 1211 1212 bmp_pos = ia_pos >> index_block_size_bits; 1213 if (bmp_pos >> 3 >= bmp_na->data_size) { 1214 ntfs_log_error("Current index position exceeds index bitmap " 1215 "size.\n"); 1216 goto dir_err_out; 1217 } 1218 1219 bmp_buf_size = min(bmp_na->data_size - (bmp_pos >> 3), 4096); 1220 bmp = ntfs_malloc(bmp_buf_size); 1221 if (!bmp) 1222 goto err_out; 1223 1224 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); 1225 if (br != bmp_buf_size) { 1226 if (br != -1) 1227 errno = EIO; 1228 ntfs_log_perror("Failed to read from index bitmap attribute"); 1229 goto err_out; 1230 } 1231 1232 bmp_buf_pos = 0; 1233 /* If the index block is not in use find the next one that is. */ 1234 while (!(bmp[bmp_buf_pos >> 3] & (1 << (bmp_buf_pos & 7)))) { 1235 find_next_index_buffer: 1236 bmp_pos++; 1237 bmp_buf_pos++; 1238 /* If we have reached the end of the bitmap, we are done. */ 1239 if (bmp_pos >> 3 >= bmp_na->data_size) 1240 goto EOD; 1241 ia_pos = bmp_pos << index_block_size_bits; 1242 if (bmp_buf_pos >> 3 < bmp_buf_size) 1243 continue; 1244 /* Read next chunk from the index bitmap. */ 1245 bmp_buf_pos = 0; 1246 if ((bmp_pos >> 3) + bmp_buf_size > bmp_na->data_size) 1247 bmp_buf_size = bmp_na->data_size - (bmp_pos >> 3); 1248 br = ntfs_attr_pread(bmp_na, bmp_pos >> 3, bmp_buf_size, bmp); 1249 if (br != bmp_buf_size) { 1250 if (br != -1) 1251 errno = EIO; 1252 ntfs_log_perror("Failed to read from index bitmap attribute"); 1253 goto err_out; 1254 } 1255 } 1256 1257 ntfs_log_debug("Handling index block 0x%llx.\n", (long long)bmp_pos); 1258 1259 /* Read the index block starting at bmp_pos. */ 1260 br = ntfs_attr_mst_pread(ia_na, bmp_pos << index_block_size_bits, 1, 1261 index_block_size, ia); 1262 if (br != 1) { 1263 if (br != -1) 1264 errno = EIO; 1265 ntfs_log_perror("Failed to read index block"); 1266 goto err_out; 1267 } 1268 1269 ia_start = ia_pos & ~(s64)(index_block_size - 1); 1270 if (sle64_to_cpu(ia->index_block_vcn) != ia_start >> 1271 index_vcn_size_bits) { 1272 ntfs_log_error("Actual VCN (0x%llx) of index buffer is different " 1273 "from expected VCN (0x%llx) in inode 0x%llx.\n", 1274 (long long)sle64_to_cpu(ia->index_block_vcn), 1275 (long long)ia_start >> index_vcn_size_bits, 1276 (unsigned long long)dir_ni->mft_no); 1277 goto dir_err_out; 1278 } 1279 if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) { 1280 ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode %lld " 1281 "has a size (%u) differing from the directory " 1282 "specified size (%u).\n", (long long)ia_start >> 1283 index_vcn_size_bits, 1284 (unsigned long long)dir_ni->mft_no, 1285 (unsigned) le32_to_cpu(ia->index.allocated_size) 1286 + 0x18, (unsigned)index_block_size); 1287 goto dir_err_out; 1288 } 1289 index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length); 1290 if (index_end > (u8*)ia + index_block_size) { 1291 ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode " 1292 "%lld exceeds maximum size.\n", 1293 (long long)ia_start >> index_vcn_size_bits, 1294 (unsigned long long)dir_ni->mft_no); 1295 goto dir_err_out; 1296 } 1297 /* The first index entry. */ 1298 ie = (INDEX_ENTRY*)((u8*)&ia->index + 1299 le32_to_cpu(ia->index.entries_offset)); 1300 /* 1301 * Loop until we exceed valid memory (corruption case) or until we 1302 * reach the last entry or until ntfs_filldir tells us it has had 1303 * enough or signals an error (both covered by the rc test). 1304 */ 1305 for (;; ie = (INDEX_ENTRY*)((u8*)ie + le16_to_cpu(ie->length))) { 1306 ntfs_log_debug("In index allocation, offset 0x%llx.\n", 1307 (long long)ia_start + ((u8*)ie - (u8*)ia)); 1308 /* Bounds checks. */ 1309 if ((u8*)ie < (u8*)ia || (u8*)ie + 1310 sizeof(INDEX_ENTRY_HEADER) > index_end || 1311 (u8*)ie + le16_to_cpu(ie->key_length) > 1312 index_end) { 1313 ntfs_log_error("Index entry out of bounds in directory inode " 1314 "%lld.\n", (unsigned long long)dir_ni->mft_no); 1315 goto dir_err_out; 1316 } 1317 /* The last entry cannot contain a name. */ 1318 if (ie->ie_flags & INDEX_ENTRY_END) 1319 break; 1320 1321 if (!le16_to_cpu(ie->length)) 1322 goto dir_err_out; 1323 1324 /* Skip index entry if continuing previous readdir. */ 1325 if (ia_pos - ia_start > (u8*)ie - (u8*)ia) 1326 continue; 1327 /* 1328 * Submit the directory entry to ntfs_filldir(), which will 1329 * invoke the filldir() callback as appropriate. 1330 */ 1331 rc = ntfs_filldir(dir_ni, pos, index_vcn_size_bits, 1332 INDEX_TYPE_ALLOCATION, ia, ie, dirent, filldir); 1333 if (rc) 1334 goto err_out; 1335 } 1336 goto find_next_index_buffer; 1337 EOD: 1338 /* We are finished, set *pos to EOD. */ 1339 *pos = i_size + vol->mft_record_size; 1340 done: 1341 free(ia); 1342 free(bmp); 1343 if (bmp_na) 1344 ntfs_attr_close(bmp_na); 1345 if (ia_na) 1346 ntfs_attr_close(ia_na); 1347 ntfs_log_debug("EOD, *pos 0x%llx, returning 0.\n", (long long)*pos); 1348 return 0; 1349 dir_err_out: 1350 errno = EIO; 1351 err_out: 1352 eo = errno; 1353 ntfs_log_trace("failed.\n"); 1354 if (ctx) 1355 ntfs_attr_put_search_ctx(ctx); 1356 free(ia); 1357 free(bmp); 1358 if (bmp_na) 1359 ntfs_attr_close(bmp_na); 1360 if (ia_na) 1361 ntfs_attr_close(ia_na); 1362 errno = eo; 1363 return -1; 1364 } 1365 1366 1367 /** 1368 * __ntfs_create - create object on ntfs volume 1369 * @dir_ni: ntfs inode for directory in which create new object 1370 * @securid: id of inheritable security descriptor, 0 if none 1371 * @name: unicode name of new object 1372 * @name_len: length of the name in unicode characters 1373 * @type: type of the object to create 1374 * @dev: major and minor device numbers (obtained from makedev()) 1375 * @target: target in unicode (only for symlinks) 1376 * @target_len: length of target in unicode characters 1377 * 1378 * Internal, use ntfs_create{,_device,_symlink} wrappers instead. 1379 * 1380 * @type can be: 1381 * S_IFREG to create regular file 1382 * S_IFDIR to create directory 1383 * S_IFBLK to create block device 1384 * S_IFCHR to create character device 1385 * S_IFLNK to create symbolic link 1386 * S_IFIFO to create FIFO 1387 * S_IFSOCK to create socket 1388 * other values are invalid. 1389 * 1390 * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value 1391 * ignored. 1392 * 1393 * @target and @target_len are used only if @type is S_IFLNK, in other cases 1394 * their value ignored. 1395 * 1396 * Return opened ntfs inode that describes created object on success or NULL 1397 * on error with errno set to the error code. 1398 */ 1399 static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid, 1400 ntfschar *name, u8 name_len, mode_t type, dev_t dev, 1401 ntfschar *target, int target_len) 1402 { 1403 ntfs_inode *ni; 1404 int rollback_data = 0, rollback_sd = 0; 1405 FILE_NAME_ATTR *fn = NULL; 1406 STANDARD_INFORMATION *si = NULL; 1407 int err, fn_len, si_len; 1408 1409 ntfs_log_trace("Entering.\n"); 1410 1411 /* Sanity checks. */ 1412 if (!dir_ni || !name || !name_len) { 1413 ntfs_log_error("Invalid arguments.\n"); 1414 errno = EINVAL; 1415 return NULL; 1416 } 1417 1418 if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) { 1419 errno = EOPNOTSUPP; 1420 return NULL; 1421 } 1422 1423 ni = ntfs_mft_record_alloc(dir_ni->vol, NULL); 1424 if (!ni) 1425 return NULL; 1426 #if CACHE_NIDATA_SIZE 1427 ntfs_inode_invalidate(dir_ni->vol, ni->mft_no); 1428 #endif 1429 /* 1430 * Create STANDARD_INFORMATION attribute. 1431 * JPA Depending on available inherited security descriptor, 1432 * Write STANDARD_INFORMATION v1.2 (no inheritance) or v3 1433 */ 1434 if (securid) 1435 si_len = sizeof(STANDARD_INFORMATION); 1436 else 1437 si_len = offsetof(STANDARD_INFORMATION, v1_end); 1438 si = ntfs_calloc(si_len); 1439 if (!si) { 1440 err = errno; 1441 goto err_out; 1442 } 1443 si->creation_time = ni->creation_time; 1444 si->last_data_change_time = ni->last_data_change_time; 1445 si->last_mft_change_time = ni->last_mft_change_time; 1446 si->last_access_time = ni->last_access_time; 1447 if (securid) { 1448 set_nino_flag(ni, v3_Extensions); 1449 ni->owner_id = si->owner_id = 0; 1450 ni->security_id = si->security_id = securid; 1451 ni->quota_charged = si->quota_charged = const_cpu_to_le64(0); 1452 ni->usn = si->usn = const_cpu_to_le64(0); 1453 } else 1454 clear_nino_flag(ni, v3_Extensions); 1455 if (!S_ISREG(type) && !S_ISDIR(type)) { 1456 si->file_attributes = FILE_ATTR_SYSTEM; 1457 ni->flags = FILE_ATTR_SYSTEM; 1458 } 1459 ni->flags |= FILE_ATTR_ARCHIVE; 1460 if (NVolHideDotFiles(dir_ni->vol) 1461 && (name_len > 1) 1462 && (name[0] == const_cpu_to_le16('.')) 1463 && (name[1] != const_cpu_to_le16('.'))) 1464 ni->flags |= FILE_ATTR_HIDDEN; 1465 /* 1466 * Set compression flag according to parent directory 1467 * unless NTFS version < 3.0 or cluster size > 4K 1468 * or compression has been disabled 1469 */ 1470 if ((dir_ni->flags & FILE_ATTR_COMPRESSED) 1471 && (dir_ni->vol->major_ver >= 3) 1472 && NVolCompression(dir_ni->vol) 1473 && (dir_ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE) 1474 && (S_ISREG(type) || S_ISDIR(type))) 1475 ni->flags |= FILE_ATTR_COMPRESSED; 1476 /* Add STANDARD_INFORMATION to inode. */ 1477 if (ntfs_attr_add(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, 1478 (u8*)si, si_len)) { 1479 err = errno; 1480 ntfs_log_error("Failed to add STANDARD_INFORMATION " 1481 "attribute.\n"); 1482 goto err_out; 1483 } 1484 1485 if (!securid) { 1486 if (ntfs_sd_add_everyone(ni)) { 1487 err = errno; 1488 goto err_out; 1489 } 1490 } 1491 rollback_sd = 1; 1492 1493 if (S_ISDIR(type)) { 1494 INDEX_ROOT *ir = NULL; 1495 INDEX_ENTRY *ie; 1496 int ir_len, index_len; 1497 1498 /* Create INDEX_ROOT attribute. */ 1499 index_len = sizeof(INDEX_HEADER) + sizeof(INDEX_ENTRY_HEADER); 1500 ir_len = offsetof(INDEX_ROOT, index) + index_len; 1501 ir = ntfs_calloc(ir_len); 1502 if (!ir) { 1503 err = errno; 1504 goto err_out; 1505 } 1506 ir->type = AT_FILE_NAME; 1507 ir->collation_rule = COLLATION_FILE_NAME; 1508 ir->index_block_size = cpu_to_le32(ni->vol->indx_record_size); 1509 if (ni->vol->cluster_size <= ni->vol->indx_record_size) 1510 ir->clusters_per_index_block = 1511 ni->vol->indx_record_size >> 1512 ni->vol->cluster_size_bits; 1513 else 1514 ir->clusters_per_index_block = 1515 ni->vol->indx_record_size >> 1516 NTFS_BLOCK_SIZE_BITS; 1517 ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER)); 1518 ir->index.index_length = cpu_to_le32(index_len); 1519 ir->index.allocated_size = cpu_to_le32(index_len); 1520 ie = (INDEX_ENTRY*)((u8*)ir + sizeof(INDEX_ROOT)); 1521 ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER)); 1522 ie->key_length = 0; 1523 ie->ie_flags = INDEX_ENTRY_END; 1524 /* Add INDEX_ROOT attribute to inode. */ 1525 if (ntfs_attr_add(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4, 1526 (u8*)ir, ir_len)) { 1527 err = errno; 1528 free(ir); 1529 ntfs_log_error("Failed to add INDEX_ROOT attribute.\n"); 1530 goto err_out; 1531 } 1532 free(ir); 1533 } else { 1534 INTX_FILE *data; 1535 int data_len; 1536 1537 switch (type) { 1538 case S_IFBLK: 1539 case S_IFCHR: 1540 data_len = offsetof(INTX_FILE, device_end); 1541 data = ntfs_malloc(data_len); 1542 if (!data) { 1543 err = errno; 1544 goto err_out; 1545 } 1546 data->major = cpu_to_le64(major(dev)); 1547 data->minor = cpu_to_le64(minor(dev)); 1548 if (type == S_IFBLK) 1549 data->magic = INTX_BLOCK_DEVICE; 1550 if (type == S_IFCHR) 1551 data->magic = INTX_CHARACTER_DEVICE; 1552 break; 1553 case S_IFLNK: 1554 data_len = sizeof(INTX_FILE_TYPES) + 1555 target_len * sizeof(ntfschar); 1556 data = ntfs_malloc(data_len); 1557 if (!data) { 1558 err = errno; 1559 goto err_out; 1560 } 1561 data->magic = INTX_SYMBOLIC_LINK; 1562 memcpy(data->target, target, 1563 target_len * sizeof(ntfschar)); 1564 break; 1565 case S_IFSOCK: 1566 data = NULL; 1567 data_len = 1; 1568 break; 1569 default: /* FIFO or regular file. */ 1570 data = NULL; 1571 data_len = 0; 1572 break; 1573 } 1574 /* Add DATA attribute to inode. */ 1575 if (ntfs_attr_add(ni, AT_DATA, AT_UNNAMED, 0, (u8*)data, 1576 data_len)) { 1577 err = errno; 1578 ntfs_log_error("Failed to add DATA attribute.\n"); 1579 free(data); 1580 goto err_out; 1581 } 1582 rollback_data = 1; 1583 free(data); 1584 } 1585 /* Create FILE_NAME attribute. */ 1586 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); 1587 fn = ntfs_calloc(fn_len); 1588 if (!fn) { 1589 err = errno; 1590 goto err_out; 1591 } 1592 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, 1593 le16_to_cpu(dir_ni->mrec->sequence_number)); 1594 fn->file_name_length = name_len; 1595 fn->file_name_type = FILE_NAME_POSIX; 1596 if (S_ISDIR(type)) 1597 fn->file_attributes = FILE_ATTR_I30_INDEX_PRESENT; 1598 if (!S_ISREG(type) && !S_ISDIR(type)) 1599 fn->file_attributes = FILE_ATTR_SYSTEM; 1600 else 1601 fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED; 1602 fn->file_attributes |= FILE_ATTR_ARCHIVE; 1603 fn->file_attributes |= ni->flags & FILE_ATTR_HIDDEN; 1604 fn->creation_time = ni->creation_time; 1605 fn->last_data_change_time = ni->last_data_change_time; 1606 fn->last_mft_change_time = ni->last_mft_change_time; 1607 fn->last_access_time = ni->last_access_time; 1608 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) 1609 fn->data_size = fn->allocated_size = const_cpu_to_le64(0); 1610 else { 1611 fn->data_size = cpu_to_sle64(ni->data_size); 1612 fn->allocated_size = cpu_to_sle64(ni->allocated_size); 1613 } 1614 memcpy(fn->file_name, name, name_len * sizeof(ntfschar)); 1615 /* Add FILE_NAME attribute to inode. */ 1616 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) { 1617 err = errno; 1618 ntfs_log_error("Failed to add FILE_NAME attribute.\n"); 1619 goto err_out; 1620 } 1621 /* Add FILE_NAME attribute to index. */ 1622 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no, 1623 le16_to_cpu(ni->mrec->sequence_number)))) { 1624 err = errno; 1625 ntfs_log_perror("Failed to add entry to the index"); 1626 goto err_out; 1627 } 1628 /* Set hard links count and directory flag. */ 1629 ni->mrec->link_count = cpu_to_le16(1); 1630 if (S_ISDIR(type)) 1631 ni->mrec->flags |= MFT_RECORD_IS_DIRECTORY; 1632 ntfs_inode_mark_dirty(ni); 1633 /* Done! */ 1634 free(fn); 1635 free(si); 1636 ntfs_log_trace("Done.\n"); 1637 return ni; 1638 err_out: 1639 ntfs_log_trace("Failed.\n"); 1640 1641 if (rollback_sd) 1642 ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); 1643 1644 if (rollback_data) 1645 ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0); 1646 /* 1647 * Free extent MFT records (should not exist any with current 1648 * ntfs_create implementation, but for any case if something will be 1649 * changed in the future). 1650 */ 1651 while (ni->nr_extents) 1652 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) { 1653 err = errno; 1654 ntfs_log_error("Failed to free extent MFT record. " 1655 "Leaving inconsistent metadata.\n"); 1656 } 1657 if (ntfs_mft_record_free(ni->vol, ni)) 1658 ntfs_log_error("Failed to free MFT record. " 1659 "Leaving inconsistent metadata. Run chkdsk.\n"); 1660 free(fn); 1661 free(si); 1662 errno = err; 1663 return NULL; 1664 } 1665 1666 /** 1667 * Some wrappers around __ntfs_create() ... 1668 */ 1669 1670 ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name, 1671 u8 name_len, mode_t type) 1672 { 1673 if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO && 1674 type != S_IFSOCK) { 1675 ntfs_log_error("Invalid arguments.\n"); 1676 return NULL; 1677 } 1678 return __ntfs_create(dir_ni, securid, name, name_len, type, 0, NULL, 0); 1679 } 1680 1681 ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, 1682 ntfschar *name, u8 name_len, mode_t type, dev_t dev) 1683 { 1684 if (type != S_IFCHR && type != S_IFBLK) { 1685 ntfs_log_error("Invalid arguments.\n"); 1686 return NULL; 1687 } 1688 return __ntfs_create(dir_ni, securid, name, name_len, type, dev, NULL, 0); 1689 } 1690 1691 ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, 1692 ntfschar *name, u8 name_len, ntfschar *target, int target_len) 1693 { 1694 if (!target || !target_len) { 1695 ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__, 1696 target, target_len); 1697 return NULL; 1698 } 1699 return __ntfs_create(dir_ni, securid, name, name_len, S_IFLNK, 0, 1700 target, target_len); 1701 } 1702 1703 int ntfs_check_empty_dir(ntfs_inode *ni) 1704 { 1705 ntfs_attr *na; 1706 int ret = 0; 1707 1708 if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) 1709 return 0; 1710 1711 na = ntfs_attr_open(ni, AT_INDEX_ROOT, NTFS_INDEX_I30, 4); 1712 if (!na) { 1713 errno = EIO; 1714 ntfs_log_perror("Failed to open directory"); 1715 return -1; 1716 } 1717 1718 /* Non-empty directory? */ 1719 if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){ 1720 /* Both ENOTEMPTY and EEXIST are ok. We use the more common. */ 1721 errno = ENOTEMPTY; 1722 ntfs_log_debug("Directory is not empty\n"); 1723 ret = -1; 1724 } 1725 1726 ntfs_attr_close(na); 1727 return ret; 1728 } 1729 1730 static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn) 1731 { 1732 int link_count = le16_to_cpu(ni->mrec->link_count); 1733 int ret; 1734 1735 ret = ntfs_check_empty_dir(ni); 1736 if (!ret || errno != ENOTEMPTY) 1737 return ret; 1738 /* 1739 * Directory is non-empty, so we can unlink only if there is more than 1740 * one "real" hard link, i.e. links aren't different DOS and WIN32 names 1741 */ 1742 if ((link_count == 1) || 1743 (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) { 1744 errno = ENOTEMPTY; 1745 ntfs_log_debug("Non-empty directory without hard links\n"); 1746 goto no_hardlink; 1747 } 1748 1749 ret = 0; 1750 no_hardlink: 1751 return ret; 1752 } 1753 1754 /** 1755 * ntfs_delete - delete file or directory from ntfs volume 1756 * @ni: ntfs inode for object to delte 1757 * @dir_ni: ntfs inode for directory in which delete object 1758 * @name: unicode name of the object to delete 1759 * @name_len: length of the name in unicode characters 1760 * 1761 * @ni is always closed after the call to this function (even if it failed), 1762 * user does not need to call ntfs_inode_close himself. 1763 * 1764 * Return 0 on success or -1 on error with errno set to the error code. 1765 */ 1766 int ntfs_delete(ntfs_volume *vol, const char *pathname, 1767 ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) 1768 { 1769 ntfs_attr_search_ctx *actx = NULL; 1770 FILE_NAME_ATTR *fn = NULL; 1771 BOOL looking_for_dos_name = FALSE, looking_for_win32_name = FALSE; 1772 BOOL case_sensitive_match = TRUE; 1773 int err = 0; 1774 #if CACHE_NIDATA_SIZE 1775 int i; 1776 #endif 1777 #if CACHE_INODE_SIZE 1778 struct CACHED_INODE item; 1779 const char *p; 1780 u64 inum = (u64)-1; 1781 int count; 1782 #endif 1783 #if CACHE_LOOKUP_SIZE 1784 struct CACHED_LOOKUP lkitem; 1785 #endif 1786 1787 ntfs_log_trace("Entering.\n"); 1788 1789 if (!ni || !dir_ni || !name || !name_len) { 1790 ntfs_log_error("Invalid arguments.\n"); 1791 errno = EINVAL; 1792 goto err_out; 1793 } 1794 if (ni->nr_extents == -1) 1795 ni = ni->base_ni; 1796 if (dir_ni->nr_extents == -1) 1797 dir_ni = dir_ni->base_ni; 1798 /* 1799 * Search for FILE_NAME attribute with such name. If it's in POSIX or 1800 * WIN32_AND_DOS namespace, then simply remove it from index and inode. 1801 * If filename in DOS or in WIN32 namespace, then remove DOS name first, 1802 * only then remove WIN32 name. 1803 */ 1804 actx = ntfs_attr_get_search_ctx(ni, NULL); 1805 if (!actx) 1806 goto err_out; 1807 search: 1808 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, 1809 0, NULL, 0, actx)) { 1810 char *s; 1811 IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE; 1812 1813 errno = 0; 1814 fn = (FILE_NAME_ATTR*)((u8*)actx->attr + 1815 le16_to_cpu(actx->attr->value_offset)); 1816 s = ntfs_attr_name_get(fn->file_name, fn->file_name_length); 1817 ntfs_log_trace("name: '%s' type: %d dos: %d win32: %d " 1818 "case: %d\n", s, fn->file_name_type, 1819 looking_for_dos_name, looking_for_win32_name, 1820 case_sensitive_match); 1821 ntfs_attr_name_free(&s); 1822 if (looking_for_dos_name) { 1823 if (fn->file_name_type == FILE_NAME_DOS) 1824 break; 1825 else 1826 continue; 1827 } 1828 if (looking_for_win32_name) { 1829 if (fn->file_name_type == FILE_NAME_WIN32) 1830 break; 1831 else 1832 continue; 1833 } 1834 1835 /* Ignore hard links from other directories */ 1836 if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) { 1837 ntfs_log_debug("MFT record numbers don't match " 1838 "(%llu != %llu)\n", 1839 (long long unsigned)dir_ni->mft_no, 1840 (long long unsigned)MREF_LE(fn->parent_directory)); 1841 continue; 1842 } 1843 if (case_sensitive_match 1844 || ((fn->file_name_type == FILE_NAME_POSIX) 1845 && NVolCaseSensitive(ni->vol))) 1846 case_sensitive = CASE_SENSITIVE; 1847 1848 if (ntfs_names_are_equal(fn->file_name, fn->file_name_length, 1849 name, name_len, case_sensitive, 1850 ni->vol->upcase, ni->vol->upcase_len)){ 1851 1852 if (fn->file_name_type == FILE_NAME_WIN32) { 1853 looking_for_dos_name = TRUE; 1854 ntfs_attr_reinit_search_ctx(actx); 1855 continue; 1856 } 1857 if (fn->file_name_type == FILE_NAME_DOS) 1858 looking_for_dos_name = TRUE; 1859 break; 1860 } 1861 } 1862 if (errno) { 1863 /* 1864 * If case sensitive search failed, then try once again 1865 * ignoring case. 1866 */ 1867 if (errno == ENOENT && case_sensitive_match) { 1868 case_sensitive_match = FALSE; 1869 ntfs_attr_reinit_search_ctx(actx); 1870 goto search; 1871 } 1872 goto err_out; 1873 } 1874 1875 if (ntfs_check_unlinkable_dir(ni, fn) < 0) 1876 goto err_out; 1877 1878 if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length))) 1879 goto err_out; 1880 1881 if (ntfs_attr_record_rm(actx)) 1882 goto err_out; 1883 1884 ni->mrec->link_count = cpu_to_le16(le16_to_cpu( 1885 ni->mrec->link_count) - 1); 1886 1887 ntfs_inode_mark_dirty(ni); 1888 if (looking_for_dos_name) { 1889 looking_for_dos_name = FALSE; 1890 looking_for_win32_name = TRUE; 1891 ntfs_attr_reinit_search_ctx(actx); 1892 goto search; 1893 } 1894 /* TODO: Update object id, quota and securiry indexes if required. */ 1895 /* 1896 * If hard link count is not equal to zero then we are done. In other 1897 * case there are no reference to this inode left, so we should free all 1898 * non-resident attributes and mark all MFT record as not in use. 1899 */ 1900 #if CACHE_LOOKUP_SIZE 1901 /* invalidate entry in lookup cache */ 1902 lkitem.name = (const char*)NULL; 1903 lkitem.namesize = 0; 1904 lkitem.inum = ni->mft_no; 1905 lkitem.parent = dir_ni->mft_no; 1906 ntfs_invalidate_cache(vol->lookup_cache, GENERIC(&lkitem), 1907 lookup_cache_inv_compare, CACHE_NOHASH); 1908 #endif 1909 #if CACHE_INODE_SIZE 1910 inum = ni->mft_no; 1911 if (pathname) { 1912 /* invalide cache entry, even if there was an error */ 1913 /* Remove leading /'s. */ 1914 p = pathname; 1915 while (*p == PATH_SEP) 1916 p++; 1917 if (p[0] && (p[strlen(p)-1] == PATH_SEP)) 1918 ntfs_log_error("Unnormalized path %s\n",pathname); 1919 item.pathname = p; 1920 item.varsize = strlen(p); 1921 } else { 1922 item.pathname = (const char*)NULL; 1923 item.varsize = 0; 1924 } 1925 item.inum = inum; 1926 count = ntfs_invalidate_cache(vol->xinode_cache, GENERIC(&item), 1927 inode_cache_inv_compare, CACHE_NOHASH); 1928 if (pathname && !count) 1929 ntfs_log_error("Could not delete inode cache entry for %s\n", 1930 pathname); 1931 #endif 1932 if (ni->mrec->link_count) { 1933 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME); 1934 goto ok; 1935 } 1936 if (ntfs_delete_reparse_index(ni)) { 1937 /* 1938 * Failed to remove the reparse index : proceed anyway 1939 * This is not a critical error, the entry is useless 1940 * because of sequence_number, and stopping file deletion 1941 * would be much worse as the file is not referenced now. 1942 */ 1943 err = errno; 1944 } 1945 if (ntfs_delete_object_id_index(ni)) { 1946 /* 1947 * Failed to remove the object id index : proceed anyway 1948 * This is not a critical error. 1949 */ 1950 err = errno; 1951 } 1952 ntfs_attr_reinit_search_ctx(actx); 1953 while (!ntfs_attrs_walk(actx)) { 1954 if (actx->attr->non_resident) { 1955 runlist *rl; 1956 1957 rl = ntfs_mapping_pairs_decompress(ni->vol, actx->attr, 1958 NULL); 1959 if (!rl) { 1960 err = errno; 1961 ntfs_log_error("Failed to decompress runlist. " 1962 "Leaving inconsistent metadata.\n"); 1963 continue; 1964 } 1965 if (ntfs_cluster_free_from_rl(ni->vol, rl)) { 1966 err = errno; 1967 ntfs_log_error("Failed to free clusters. " 1968 "Leaving inconsistent metadata.\n"); 1969 continue; 1970 } 1971 free(rl); 1972 } 1973 } 1974 if (errno != ENOENT) { 1975 err = errno; 1976 ntfs_log_error("Attribute enumeration failed. " 1977 "Probably leaving inconsistent metadata.\n"); 1978 } 1979 /* All extents should be attached after attribute walk. */ 1980 #if CACHE_NIDATA_SIZE 1981 /* 1982 * Disconnect extents before deleting them, so they are 1983 * not wrongly moved to cache through the chainings 1984 */ 1985 for (i=ni->nr_extents-1; i>=0; i--) { 1986 ni->extent_nis[i]->base_ni = (ntfs_inode*)NULL; 1987 ni->extent_nis[i]->nr_extents = 0; 1988 if (ntfs_mft_record_free(ni->vol, ni->extent_nis[i])) { 1989 err = errno; 1990 ntfs_log_error("Failed to free extent MFT record. " 1991 "Leaving inconsistent metadata.\n"); 1992 } 1993 } 1994 free(ni->extent_nis); 1995 ni->nr_extents = 0; 1996 ni->extent_nis = (ntfs_inode**)NULL; 1997 #else 1998 while (ni->nr_extents) 1999 if (ntfs_mft_record_free(ni->vol, *(ni->extent_nis))) { 2000 err = errno; 2001 ntfs_log_error("Failed to free extent MFT record. " 2002 "Leaving inconsistent metadata.\n"); 2003 } 2004 #endif 2005 if (ntfs_mft_record_free(ni->vol, ni)) { 2006 err = errno; 2007 ntfs_log_error("Failed to free base MFT record. " 2008 "Leaving inconsistent metadata.\n"); 2009 } 2010 ni = NULL; 2011 ok: 2012 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME); 2013 out: 2014 if (actx) 2015 ntfs_attr_put_search_ctx(actx); 2016 if (ntfs_inode_close(dir_ni) && !err) 2017 err = errno; 2018 if (ntfs_inode_close(ni) && !err) 2019 err = errno; 2020 if (err) { 2021 errno = err; 2022 ntfs_log_debug("Could not delete file: %s\n", strerror(errno)); 2023 return -1; 2024 } 2025 ntfs_log_trace("Done.\n"); 2026 return 0; 2027 err_out: 2028 err = errno; 2029 goto out; 2030 } 2031 2032 /** 2033 * ntfs_link - create hard link for file or directory 2034 * @ni: ntfs inode for object to create hard link 2035 * @dir_ni: ntfs inode for directory in which new link should be placed 2036 * @name: unicode name of the new link 2037 * @name_len: length of the name in unicode characters 2038 * 2039 * NOTE: At present we allow creating hardlinks to directories, we use them 2040 * in a temporary state during rename. But it's defenitely bad idea to have 2041 * hard links to directories as a result of operation. 2042 * FIXME: Create internal __ntfs_link that allows hard links to a directories 2043 * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link. 2044 * 2045 * Return 0 on success or -1 on error with errno set to the error code. 2046 */ 2047 static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, 2048 u8 name_len, FILE_NAME_TYPE_FLAGS nametype) 2049 { 2050 FILE_NAME_ATTR *fn = NULL; 2051 int fn_len, err; 2052 2053 ntfs_log_trace("Entering.\n"); 2054 2055 if (!ni || !dir_ni || !name || !name_len || 2056 ni->mft_no == dir_ni->mft_no) { 2057 err = EINVAL; 2058 ntfs_log_perror("ntfs_link wrong arguments"); 2059 goto err_out; 2060 } 2061 2062 if ((ni->flags & FILE_ATTR_REPARSE_POINT) 2063 && !ntfs_possible_symlink(ni)) { 2064 err = EOPNOTSUPP; 2065 goto err_out; 2066 } 2067 2068 /* Create FILE_NAME attribute. */ 2069 fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); 2070 fn = ntfs_calloc(fn_len); 2071 if (!fn) { 2072 err = errno; 2073 goto err_out; 2074 } 2075 fn->parent_directory = MK_LE_MREF(dir_ni->mft_no, 2076 le16_to_cpu(dir_ni->mrec->sequence_number)); 2077 fn->file_name_length = name_len; 2078 fn->file_name_type = nametype; 2079 fn->file_attributes = ni->flags; 2080 if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) { 2081 fn->file_attributes |= FILE_ATTR_I30_INDEX_PRESENT; 2082 fn->data_size = fn->allocated_size = const_cpu_to_le64(0); 2083 } else { 2084 fn->allocated_size = cpu_to_sle64(ni->allocated_size); 2085 fn->data_size = cpu_to_sle64(ni->data_size); 2086 } 2087 fn->creation_time = ni->creation_time; 2088 fn->last_data_change_time = ni->last_data_change_time; 2089 fn->last_mft_change_time = ni->last_mft_change_time; 2090 fn->last_access_time = ni->last_access_time; 2091 memcpy(fn->file_name, name, name_len * sizeof(ntfschar)); 2092 /* Add FILE_NAME attribute to index. */ 2093 if (ntfs_index_add_filename(dir_ni, fn, MK_MREF(ni->mft_no, 2094 le16_to_cpu(ni->mrec->sequence_number)))) { 2095 err = errno; 2096 ntfs_log_perror("Failed to add filename to the index"); 2097 goto err_out; 2098 } 2099 /* Add FILE_NAME attribute to inode. */ 2100 if (ntfs_attr_add(ni, AT_FILE_NAME, AT_UNNAMED, 0, (u8*)fn, fn_len)) { 2101 ntfs_log_error("Failed to add FILE_NAME attribute.\n"); 2102 err = errno; 2103 /* Try to remove just added attribute from index. */ 2104 if (ntfs_index_remove(dir_ni, ni, fn, fn_len)) 2105 goto rollback_failed; 2106 goto err_out; 2107 } 2108 /* Increment hard links count. */ 2109 ni->mrec->link_count = cpu_to_le16(le16_to_cpu( 2110 ni->mrec->link_count) + 1); 2111 /* Done! */ 2112 ntfs_inode_mark_dirty(ni); 2113 free(fn); 2114 ntfs_log_trace("Done.\n"); 2115 return 0; 2116 rollback_failed: 2117 ntfs_log_error("Rollback failed. Leaving inconsistent metadata.\n"); 2118 err_out: 2119 free(fn); 2120 errno = err; 2121 return -1; 2122 } 2123 2124 int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) 2125 { 2126 return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX)); 2127 } 2128 2129 /* 2130 * Get a parent directory from an inode entry 2131 * 2132 * This is only used in situations where the path used to access 2133 * the current file is not known for sure. The result may be different 2134 * from the path when the file is linked in several parent directories. 2135 * 2136 * Currently this is only used for translating ".." in the target 2137 * of a Vista relative symbolic link 2138 */ 2139 2140 ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni) 2141 { 2142 ntfs_inode *dir_ni = (ntfs_inode*)NULL; 2143 u64 inum; 2144 FILE_NAME_ATTR *fn; 2145 ntfs_attr_search_ctx *ctx; 2146 2147 if (ni->mft_no != FILE_root) { 2148 /* find the name in the attributes */ 2149 ctx = ntfs_attr_get_search_ctx(ni, NULL); 2150 if (!ctx) 2151 return ((ntfs_inode*)NULL); 2152 2153 if (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 2154 CASE_SENSITIVE, 0, NULL, 0, ctx)) { 2155 /* We know this will always be resident. */ 2156 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + 2157 le16_to_cpu(ctx->attr->value_offset)); 2158 inum = le64_to_cpu(fn->parent_directory); 2159 if (inum != (u64)-1) { 2160 dir_ni = ntfs_inode_open(ni->vol, MREF(inum)); 2161 } 2162 } 2163 ntfs_attr_put_search_ctx(ctx); 2164 } 2165 return (dir_ni); 2166 } 2167 2168 #ifdef HAVE_SETXATTR 2169 2170 #define MAX_DOS_NAME_LENGTH 12 2171 2172 /* 2173 * Get a DOS name for a file in designated directory 2174 * 2175 * Returns size if found 2176 * 0 if not found 2177 * -1 if there was an error (described by errno) 2178 */ 2179 2180 static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) 2181 { 2182 size_t outsize = 0; 2183 FILE_NAME_ATTR *fn; 2184 ntfs_attr_search_ctx *ctx; 2185 2186 /* find the name in the attributes */ 2187 ctx = ntfs_attr_get_search_ctx(ni, NULL); 2188 if (!ctx) 2189 return -1; 2190 2191 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, 2192 0, NULL, 0, ctx)) { 2193 /* We know this will always be resident. */ 2194 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + 2195 le16_to_cpu(ctx->attr->value_offset)); 2196 2197 if ((fn->file_name_type & FILE_NAME_DOS) 2198 && (MREF_LE(fn->parent_directory) == dnum)) { 2199 /* 2200 * Found a DOS or WIN32+DOS name for the entry 2201 * copy name, after truncation for safety 2202 */ 2203 outsize = fn->file_name_length; 2204 /* TODO : reject if name is too long ? */ 2205 if (outsize > MAX_DOS_NAME_LENGTH) 2206 outsize = MAX_DOS_NAME_LENGTH; 2207 memcpy(dosname,fn->file_name,outsize*sizeof(ntfschar)); 2208 } 2209 } 2210 ntfs_attr_put_search_ctx(ctx); 2211 return (outsize); 2212 } 2213 2214 2215 /* 2216 * Get a long name for a file in designated directory 2217 * 2218 * Returns size if found 2219 * 0 if not found 2220 * -1 if there was an error (described by errno) 2221 */ 2222 2223 static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname) 2224 { 2225 size_t outsize = 0; 2226 FILE_NAME_ATTR *fn; 2227 ntfs_attr_search_ctx *ctx; 2228 2229 /* find the name in the attributes */ 2230 ctx = ntfs_attr_get_search_ctx(ni, NULL); 2231 if (!ctx) 2232 return -1; 2233 2234 /* first search for WIN32 or DOS+WIN32 names */ 2235 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, 2236 0, NULL, 0, ctx)) { 2237 /* We know this will always be resident. */ 2238 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + 2239 le16_to_cpu(ctx->attr->value_offset)); 2240 2241 if ((fn->file_name_type & FILE_NAME_WIN32) 2242 && (MREF_LE(fn->parent_directory) == dnum)) { 2243 /* 2244 * Found a WIN32 or WIN32+DOS name for the entry 2245 * copy name 2246 */ 2247 outsize = fn->file_name_length; 2248 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar)); 2249 } 2250 } 2251 /* if not found search for POSIX names */ 2252 if (!outsize) { 2253 ntfs_attr_reinit_search_ctx(ctx); 2254 while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, 2255 0, NULL, 0, ctx)) { 2256 /* We know this will always be resident. */ 2257 fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + 2258 le16_to_cpu(ctx->attr->value_offset)); 2259 2260 if ((fn->file_name_type == FILE_NAME_POSIX) 2261 && (MREF_LE(fn->parent_directory) == dnum)) { 2262 /* 2263 * Found a POSIX name for the entry 2264 * copy name 2265 */ 2266 outsize = fn->file_name_length; 2267 memcpy(longname,fn->file_name,outsize*sizeof(ntfschar)); 2268 } 2269 } 2270 } 2271 ntfs_attr_put_search_ctx(ctx); 2272 return (outsize); 2273 } 2274 2275 2276 /* 2277 * Get the ntfs DOS name into an extended attribute 2278 */ 2279 2280 int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, 2281 char *value, size_t size) 2282 { 2283 int outsize = 0; 2284 char *outname = (char*)NULL; 2285 u64 dnum; 2286 int doslen; 2287 ntfschar dosname[MAX_DOS_NAME_LENGTH]; 2288 2289 dnum = dir_ni->mft_no; 2290 doslen = get_dos_name(ni, dnum, dosname); 2291 if (doslen > 0) { 2292 /* 2293 * Found a DOS name for the entry, make 2294 * uppercase and encode into the buffer 2295 * if there is enough space 2296 */ 2297 ntfs_name_upcase(dosname, doslen, 2298 ni->vol->upcase, ni->vol->upcase_len); 2299 if (ntfs_ucstombs(dosname, doslen, &outname, size) < 0) { 2300 ntfs_log_error("Cannot represent dosname in current locale.\n"); 2301 outsize = -errno; 2302 } else { 2303 outsize = strlen(outname); 2304 if (value && (outsize <= (int)size)) 2305 memcpy(value, outname, outsize); 2306 else 2307 if (size && (outsize > (int)size)) 2308 outsize = -ERANGE; 2309 free(outname); 2310 } 2311 } else { 2312 if (doslen == 0) 2313 errno = ENODATA; 2314 outsize = -errno; 2315 } 2316 return (outsize); 2317 } 2318 2319 /* 2320 * Change the name space of an existing file or directory 2321 * 2322 * Returns the old namespace if successful 2323 * -1 if an error occurred (described by errno) 2324 */ 2325 2326 static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni, 2327 ntfschar *name, int len, 2328 FILE_NAME_TYPE_FLAGS nametype) 2329 { 2330 ntfs_attr_search_ctx *actx; 2331 ntfs_index_context *icx; 2332 FILE_NAME_ATTR *fnx; 2333 FILE_NAME_ATTR *fn = NULL; 2334 BOOL found; 2335 int lkup; 2336 int ret; 2337 2338 ret = -1; 2339 actx = ntfs_attr_get_search_ctx(ni, NULL); 2340 if (actx) { 2341 found = FALSE; 2342 do { 2343 lkup = ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 2344 CASE_SENSITIVE, 0, NULL, 0, actx); 2345 if (!lkup) { 2346 fn = (FILE_NAME_ATTR*)((u8*)actx->attr + 2347 le16_to_cpu(actx->attr->value_offset)); 2348 found = (MREF_LE(fn->parent_directory) 2349 == dir_ni->mft_no) 2350 && !memcmp(fn->file_name, name, 2351 len*sizeof(ntfschar)); 2352 } 2353 } while (!lkup && !found); 2354 if (found) { 2355 icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4); 2356 if (icx) { 2357 lkup = ntfs_index_lookup((char*)fn, len, icx); 2358 if (!lkup && icx->data && icx->data_len) { 2359 fnx = (FILE_NAME_ATTR*)icx->data; 2360 ret = fn->file_name_type; 2361 fn->file_name_type = nametype; 2362 fnx->file_name_type = nametype; 2363 ntfs_inode_mark_dirty(ni); 2364 ntfs_index_entry_mark_dirty(icx); 2365 } 2366 ntfs_index_ctx_put(icx); 2367 } 2368 } 2369 ntfs_attr_put_search_ctx(actx); 2370 } 2371 return (ret); 2372 } 2373 2374 /* 2375 * Set a DOS name to a file and adjust name spaces 2376 * 2377 * If the new names are collapsible (same uppercased chars) : 2378 * 2379 * - the existing DOS name or DOS+Win32 name is made Posix 2380 * - if it was a real DOS name, the existing long name is made DOS+Win32 2381 * and the existing DOS name is deleted 2382 * - finally the existing long name is made DOS+Win32 unless already done 2383 * 2384 * If the new names are not collapsible : 2385 * 2386 * - insert the short name as a DOS name 2387 * - delete the old long name or existing short name 2388 * - insert the new long name (as a Win32 or DOS+Win32 name) 2389 * 2390 * Deleting the old long name will not delete the file 2391 * provided the old name was in the Posix name space, 2392 * because the alternate name has been set before. 2393 * 2394 * The inodes of file and parent directory are always closed 2395 * 2396 * Returns 0 if successful 2397 * -1 if failed 2398 */ 2399 2400 static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, 2401 ntfschar *shortname, int shortlen, 2402 ntfschar *longname, int longlen, 2403 ntfschar *deletename, int deletelen, BOOL existed) 2404 { 2405 unsigned int linkcount; 2406 ntfs_volume *vol; 2407 BOOL collapsible; 2408 BOOL deleted; 2409 BOOL done; 2410 FILE_NAME_TYPE_FLAGS oldnametype; 2411 u64 dnum; 2412 u64 fnum; 2413 int res; 2414 2415 res = -1; 2416 vol = ni->vol; 2417 dnum = dir_ni->mft_no; 2418 fnum = ni->mft_no; 2419 /* save initial link count */ 2420 linkcount = le16_to_cpu(ni->mrec->link_count); 2421 2422 /* check whether the same name may be used as DOS and WIN32 */ 2423 collapsible = ntfs_collapsible_chars(ni->vol, shortname, shortlen, 2424 longname, longlen); 2425 if (collapsible) { 2426 deleted = FALSE; 2427 done = FALSE; 2428 if (existed) { 2429 oldnametype = set_namespace(ni, dir_ni, deletename, 2430 deletelen, FILE_NAME_POSIX); 2431 if (oldnametype == FILE_NAME_DOS) { 2432 if (set_namespace(ni, dir_ni, longname, longlen, 2433 FILE_NAME_WIN32_AND_DOS) >= 0) { 2434 if (!ntfs_delete(vol, 2435 (const char*)NULL, ni, dir_ni, 2436 deletename, deletelen)) 2437 res = 0; 2438 deleted = TRUE; 2439 } else 2440 done = TRUE; 2441 } 2442 } 2443 if (!deleted) { 2444 if (!done && (set_namespace(ni, dir_ni, 2445 longname, longlen, 2446 FILE_NAME_WIN32_AND_DOS) >= 0)) 2447 res = 0; 2448 ntfs_inode_update_times(ni, NTFS_UPDATE_CTIME); 2449 ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME); 2450 if (ntfs_inode_close_in_dir(ni,dir_ni) && !res) 2451 res = -1; 2452 if (ntfs_inode_close(dir_ni) && !res) 2453 res = -1; 2454 } 2455 } else { 2456 if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, 2457 FILE_NAME_DOS) 2458 /* make sure a new link was recorded */ 2459 && (le16_to_cpu(ni->mrec->link_count) > linkcount)) { 2460 /* delete the existing long name or short name */ 2461 // is it ok to not provide the path ? 2462 if (!ntfs_delete(vol, (char*)NULL, ni, dir_ni, 2463 deletename, deletelen)) { 2464 /* delete closes the inodes, so have to open again */ 2465 dir_ni = ntfs_inode_open(vol, dnum); 2466 if (dir_ni) { 2467 ni = ntfs_inode_open(vol, fnum); 2468 if (ni) { 2469 if (!ntfs_link_i(ni, dir_ni, 2470 longname, longlen, 2471 FILE_NAME_WIN32)) 2472 res = 0; 2473 if (ntfs_inode_close_in_dir(ni, 2474 dir_ni) 2475 && !res) 2476 res = -1; 2477 } 2478 if (ntfs_inode_close(dir_ni) && !res) 2479 res = -1; 2480 } 2481 } 2482 } else { 2483 ntfs_inode_close_in_dir(ni,dir_ni); 2484 ntfs_inode_close(dir_ni); 2485 } 2486 } 2487 return (res); 2488 } 2489 2490 2491 /* 2492 * Set the ntfs DOS name into an extended attribute 2493 * 2494 * The DOS name will be added as another file name attribute 2495 * using the existing file name information from the original 2496 * name or overwriting the DOS Name if one exists. 2497 * 2498 * The inode of the file is always closed 2499 */ 2500 2501 int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, 2502 const char *value, size_t size, int flags) 2503 { 2504 int res = 0; 2505 int longlen = 0; 2506 int shortlen = 0; 2507 char newname[3*MAX_DOS_NAME_LENGTH + 1]; 2508 ntfschar oldname[MAX_DOS_NAME_LENGTH]; 2509 int oldlen; 2510 u64 dnum; 2511 BOOL closed = FALSE; 2512 ntfschar *shortname = NULL; 2513 ntfschar longname[NTFS_MAX_NAME_LEN]; 2514 2515 /* copy the string to insert a null char, and truncate */ 2516 if (size > 3*MAX_DOS_NAME_LENGTH) 2517 size = 3*MAX_DOS_NAME_LENGTH; 2518 strncpy(newname, value, size); 2519 /* a long name may be truncated badly and be untranslatable */ 2520 newname[size] = 0; 2521 /* convert the string to the NTFS wide chars, and truncate */ 2522 shortlen = ntfs_mbstoucs(newname, &shortname); 2523 if (shortlen > MAX_DOS_NAME_LENGTH) 2524 shortlen = MAX_DOS_NAME_LENGTH; 2525 /* make sure the short name has valid chars */ 2526 if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) { 2527 ntfs_inode_close_in_dir(ni,dir_ni); 2528 ntfs_inode_close(dir_ni); 2529 res = -errno; 2530 return res; 2531 } 2532 dnum = dir_ni->mft_no; 2533 longlen = get_long_name(ni, dnum, longname); 2534 if (longlen > 0) { 2535 oldlen = get_dos_name(ni, dnum, oldname); 2536 if ((oldlen >= 0) 2537 && !ntfs_forbidden_chars(longname, longlen)) { 2538 if (oldlen > 0) { 2539 if (flags & XATTR_CREATE) { 2540 res = -1; 2541 errno = EEXIST; 2542 } else 2543 if ((shortlen == oldlen) 2544 && !memcmp(shortname,oldname, 2545 oldlen*sizeof(ntfschar))) 2546 /* already set, done */ 2547 res = 0; 2548 else { 2549 res = set_dos_name(ni, dir_ni, 2550 shortname, shortlen, 2551 longname, longlen, 2552 oldname, oldlen, TRUE); 2553 closed = TRUE; 2554 } 2555 } else { 2556 if (flags & XATTR_REPLACE) { 2557 res = -1; 2558 errno = ENODATA; 2559 } else { 2560 res = set_dos_name(ni, dir_ni, 2561 shortname, shortlen, 2562 longname, longlen, 2563 longname, longlen, FALSE); 2564 closed = TRUE; 2565 } 2566 } 2567 } else 2568 res = -1; 2569 } else { 2570 res = -1; 2571 errno = ENOENT; 2572 } 2573 free(shortname); 2574 if (!closed) { 2575 ntfs_inode_close_in_dir(ni,dir_ni); 2576 ntfs_inode_close(dir_ni); 2577 } 2578 return (res ? -1 : 0); 2579 } 2580 2581 /* 2582 * Delete the ntfs DOS name 2583 */ 2584 2585 int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni) 2586 { 2587 int res; 2588 int oldnametype; 2589 int longlen = 0; 2590 int shortlen; 2591 u64 dnum; 2592 ntfs_volume *vol; 2593 BOOL deleted = FALSE; 2594 ntfschar shortname[MAX_DOS_NAME_LENGTH]; 2595 ntfschar longname[NTFS_MAX_NAME_LEN]; 2596 2597 res = -1; 2598 vol = ni->vol; 2599 dnum = dir_ni->mft_no; 2600 longlen = get_long_name(ni, dnum, longname); 2601 if (longlen > 0) { 2602 shortlen = get_dos_name(ni, dnum, shortname); 2603 if (shortlen >= 0) { 2604 /* migrate the long name as Posix */ 2605 oldnametype = set_namespace(ni,dir_ni,longname,longlen, 2606 FILE_NAME_POSIX); 2607 switch (oldnametype) { 2608 case FILE_NAME_WIN32_AND_DOS : 2609 /* name was Win32+DOS : done */ 2610 res = 0; 2611 break; 2612 case FILE_NAME_DOS : 2613 /* name was DOS, make it back to DOS */ 2614 set_namespace(ni,dir_ni,longname,longlen, 2615 FILE_NAME_DOS); 2616 errno = ENOENT; 2617 break; 2618 case FILE_NAME_WIN32 : 2619 /* name was Win32, make it Posix and delete */ 2620 if (set_namespace(ni,dir_ni,shortname,shortlen, 2621 FILE_NAME_POSIX) >= 0) { 2622 if (!ntfs_delete(vol, 2623 (const char*)NULL, ni, 2624 dir_ni, shortname, 2625 shortlen)) 2626 res = 0; 2627 deleted = TRUE; 2628 } else { 2629 /* 2630 * DOS name has been found, but cannot 2631 * migrate to Posix : something bad 2632 * has happened 2633 */ 2634 errno = EIO; 2635 ntfs_log_error("Could not change" 2636 " DOS name of inode %lld to Posix\n", 2637 (long long)ni->mft_no); 2638 } 2639 break; 2640 default : 2641 /* name was Posix or not found : error */ 2642 errno = ENOENT; 2643 break; 2644 } 2645 } 2646 } else { 2647 errno = ENOENT; 2648 res = -1; 2649 } 2650 if (!deleted) { 2651 ntfs_inode_close_in_dir(ni,dir_ni); 2652 ntfs_inode_close(dir_ni); 2653 } 2654 return (res); 2655 } 2656 2657 #endif 2658