inode.c revision 9663:ace9a2ac3683
1/** 2 * inode.c - Inode handling code. Part of the Linux-NTFS project. 3 * 4 * Copyright (c) 2002-2005 Anton Altaparmakov 5 * Copyright (c) 2004-2007 Yura Pakhuchiy 6 * Copyright (c) 2004-2005 Richard Russon 7 * 8 * This program/include file is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as published 10 * by the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program/include file is distributed in the hope that it will be 14 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program (in the main directory of the Linux-NTFS 20 * distribution in the file COPYING); if not, write to the Free Software 21 * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#ifdef HAVE_STDLIB_H 29#include <stdlib.h> 30#endif 31#ifdef HAVE_STRING_H 32#include <string.h> 33#endif 34#ifdef HAVE_ERRNO_H 35#include <errno.h> 36#endif 37 38#include "compat.h" 39#include "types.h" 40#include "attrib.h" 41#include "inode.h" 42#include "debug.h" 43#include "mft.h" 44#include "attrlist.h" 45#include "runlist.h" 46#include "lcnalloc.h" 47#include "index.h" 48#include "dir.h" 49#include "ntfstime.h" 50#include "logging.h" 51 52/** 53 * __ntfs_inode_allocate - Create and initialise an NTFS inode object 54 * @vol: 55 * 56 * Description... 57 * 58 * Returns: 59 */ 60static ntfs_inode *__ntfs_inode_allocate(ntfs_volume *vol) 61{ 62 ntfs_inode *ni; 63 64 ni = (ntfs_inode*)calloc(1, sizeof(ntfs_inode)); 65 if (ni) { 66 ni->vol = vol; 67 INIT_LIST_HEAD(&ni->attr_cache); 68 } 69 return ni; 70} 71 72/** 73 * ntfs_inode_allocate - Create an NTFS inode object 74 * @vol: 75 * 76 * Description... 77 * 78 * Returns: 79 */ 80ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol) 81{ 82 return __ntfs_inode_allocate(vol); 83} 84 85/** 86 * __ntfs_inode_release - Destroy an NTFS inode object 87 * @ni: 88 * 89 * Description... 90 * 91 * Returns: 92 */ 93static int __ntfs_inode_release(ntfs_inode *ni) 94{ 95 if (NInoDirty(ni)) 96 ntfs_log_debug("Eeek. Discarding dirty inode!\n"); 97 if (NInoAttrList(ni) && ni->attr_list) 98 free(ni->attr_list); 99 free(ni->mrec); 100 free(ni); 101 return 0; 102} 103 104/** 105 * __ntfs_inode_add_to_cache - do not use me! Only for internal library use. 106 */ 107void __ntfs_inode_add_to_cache(ntfs_inode *ni) 108{ 109 list_add_tail(&ni->list_entry, &ni->vol->inode_cache[ 110 ni->mft_no & NTFS_INODE_CACHE_SIZE_BITS]); 111 ni->nr_references = 1; 112} 113 114/** 115 * ntfs_inode_open - open an inode ready for access 116 * @vol: volume to get the inode from 117 * @mref: inode number / mft record number to open 118 * 119 * Allocate an ntfs_inode structure and initialize it for the given inode 120 * specified by @mref. @mref specifies the inode number / mft record to read, 121 * including the sequence number, which can be 0 if no sequence number checking 122 * is to be performed. 123 * 124 * Then, allocate a buffer for the mft record, read the mft record from the 125 * volume @vol, and attach it to the ntfs_inode structure (->mrec). The 126 * mft record is mst deprotected and sanity checked for validity and we abort 127 * if deprotection or checks fail. 128 * 129 * Finally, search for an attribute list attribute in the mft record and if one 130 * is found, load the attribute list attribute value and attach it to the 131 * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate 132 * this. 133 * 134 * Return a pointer to the ntfs_inode structure on success or NULL on error, 135 * with errno set to the error code. 136 */ 137ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref) 138{ 139 s64 l; 140 ntfs_inode *ni; 141 ntfs_attr_search_ctx *ctx; 142 int err = 0; 143 STANDARD_INFORMATION *std_info; 144 struct list_head *pos; 145 146 ntfs_log_trace("Entering for inode 0x%llx.\n", MREF(mref)); 147 if (!vol) { 148 errno = EINVAL; 149 return NULL; 150 } 151 /* Check cache, maybe this inode already opened? */ 152 list_for_each(pos, &vol->inode_cache[MREF(mref) & 153 NTFS_INODE_CACHE_SIZE_BITS]) { 154 ntfs_inode *tmp_ni; 155 156 tmp_ni = list_entry(pos, ntfs_inode, list_entry); 157 if (tmp_ni->mft_no == MREF(mref)) { 158 ntfs_log_trace("Found this inode in cache, increment " 159 "reference count and return it.\n"); 160 tmp_ni->nr_references++; 161 return tmp_ni; 162 } 163 } 164 /* Search failed. Properly open inode. */ 165 ni = __ntfs_inode_allocate(vol); 166 if (!ni) 167 return NULL; 168 if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL)) 169 goto err_out; 170 if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) { 171 err = ENOENT; 172 goto err_out; 173 } 174 ni->mft_no = MREF(mref); 175 ctx = ntfs_attr_get_search_ctx(ni, NULL); 176 if (!ctx) 177 goto err_out; 178 /* Receive some basic information about inode. */ 179 if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 180 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { 181 err = errno; 182 ntfs_log_trace("Failed to receive STANDARD_INFORMATION " 183 "attribute.\n"); 184 goto put_err_out; 185 } 186 std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + 187 le16_to_cpu(ctx->attr->u.res.value_offset)); 188 ni->flags = std_info->file_attributes; 189 ni->creation_time = ntfs2utc(std_info->creation_time); 190 ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time); 191 ni->last_mft_change_time = ntfs2utc(std_info->last_mft_change_time); 192 ni->last_access_time = ntfs2utc(std_info->last_access_time); 193 /* Set attribute list information. */ 194 if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, 195 ctx)) { 196 if (errno != ENOENT) 197 goto put_err_out; 198 /* Attribute list attribute does not present. */ 199 goto get_size; 200 } 201 NInoSetAttrList(ni); 202 l = ntfs_get_attribute_value_length(ctx->attr); 203 if (!l) 204 goto put_err_out; 205 if (l > 0x40000) { 206 err = EIO; 207 goto put_err_out; 208 } 209 ni->attr_list_size = l; 210 ni->attr_list = ntfs_malloc(ni->attr_list_size); 211 if (!ni->attr_list) 212 goto put_err_out; 213 l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list); 214 if (!l) 215 goto put_err_out; 216 if (l != ni->attr_list_size) { 217 err = EIO; 218 goto put_err_out; 219 } 220get_size: 221 if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { 222 if (errno != ENOENT) 223 goto put_err_out; 224 /* Directory or special file. */ 225 ni->data_size = ni->allocated_size = 0; 226 } else { 227 if (ctx->attr->non_resident) { 228 ni->data_size = sle64_to_cpu(ctx->attr->u.nonres.data_size); 229 if (ctx->attr->flags & 230 (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE)) 231 ni->allocated_size = sle64_to_cpu( 232 ctx->attr->u.nonres.compressed_size); 233 else 234 ni->allocated_size = sle64_to_cpu( 235 ctx->attr->u.nonres.allocated_size); 236 } else { 237 ni->data_size = le32_to_cpu(ctx->attr->u.res.value_length); 238 ni->allocated_size = (ni->data_size + 7) & ~7; 239 } 240 } 241 ntfs_attr_put_search_ctx(ctx); 242 __ntfs_inode_add_to_cache(ni); 243 return ni; 244put_err_out: 245 if (!err) 246 err = errno; 247 ntfs_attr_put_search_ctx(ctx); 248err_out: 249 if (!err) 250 err = errno; 251 __ntfs_inode_release(ni); 252 errno = err; 253 return NULL; 254} 255 256/** 257 * ntfs_inode_close - close an ntfs inode and free all associated memory 258 * @ni: ntfs inode to close 259 * 260 * Make sure the ntfs inode @ni is clean. 261 * 262 * If the ntfs inode @ni is a base inode, close all associated extent inodes, 263 * then deallocate all memory attached to it, and finally free the ntfs inode 264 * structure itself. 265 * 266 * If it is an extent inode, we disconnect it from its base inode before we 267 * destroy it. 268 * 269 * It is OK to pass NULL to this function, it is just noop in this case. 270 * 271 * Return 0 on success or -1 on error with errno set to the error code. On 272 * error, @ni has not been freed. The user should attempt to handle the error 273 * and call ntfs_inode_close() again. The following error codes are defined: 274 * 275 * EBUSY @ni and/or its attribute list runlist is/are dirty and the 276 * attempt to write it/them to disk failed. 277 * EINVAL @ni is invalid (probably it is an extent inode). 278 * EIO I/O error while trying to write inode to disk. 279 */ 280int ntfs_inode_close(ntfs_inode *ni) 281{ 282 if (!ni) 283 return 0; 284 285 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 286 287 /* Decrement number of users. If there are left then just return. */ 288 if (ni->nr_extents != -1) { 289 ni->nr_references--; 290 if (ni->nr_references) { 291 ntfs_log_trace("There are %d more references left to " 292 "this inode.\n", 293 ni->nr_references); 294 return 0; 295 } else 296 ntfs_log_trace("There are no more references left to " 297 "this inode.\n"); 298 } 299 /* Check whether all attributes of this inode are closed. */ 300 if (!list_empty(&ni->attr_cache)) 301 ntfs_log_error("%s(): Not all attributes are closed. " 302 "We definitely have memory leak. " 303 "Continue anyway.\n", "ntfs_inode_close"); 304 /* If we have dirty metadata, write it out. */ 305 if (NInoDirty(ni) || NInoAttrListDirty(ni)) { 306 if (ntfs_inode_sync(ni)) { 307 if (errno != EIO) 308 errno = EBUSY; 309 return -1; 310 } 311 } 312 /* Is this a base inode with mapped extent inodes? */ 313 if (ni->nr_extents > 0) { 314 while (ni->nr_extents > 0) { 315 if (ntfs_inode_close(ni->u.extent_nis[0])) { 316 if (errno != EIO) 317 errno = EBUSY; 318 return -1; 319 } 320 } 321 } else if (ni->nr_extents == -1) { 322 ntfs_inode **tmp_nis; 323 ntfs_inode *base_ni; 324 s32 i; 325 326 /* 327 * If the inode is an extent inode, disconnect it from the 328 * base inode before destroying it. 329 */ 330 base_ni = ni->u.base_ni; 331 for (i = 0; i < base_ni->nr_extents; ++i) { 332 tmp_nis = base_ni->u.extent_nis; 333 if (tmp_nis[i] != ni) 334 continue; 335 /* Found it. Disconnect. */ 336 memmove(tmp_nis + i, tmp_nis + i + 1, 337 (base_ni->nr_extents - i - 1) * 338 sizeof(ntfs_inode *)); 339 /* Buffer should be for multiple of four extents. */ 340 if ((--base_ni->nr_extents) & 3) { 341 i = -1; 342 break; 343 } 344 /* 345 * ElectricFence is unhappy with realloc(x,0) as free(x) 346 * thus we explicitly separate these two cases. 347 */ 348 if (base_ni->nr_extents) { 349 /* Resize the memory buffer. */ 350 tmp_nis = realloc(tmp_nis, base_ni->nr_extents * 351 sizeof(ntfs_inode *)); 352 /* Ignore errors, they don't really matter. */ 353 if (tmp_nis) 354 base_ni->u.extent_nis = tmp_nis; 355 } else if (tmp_nis) 356 free(tmp_nis); 357 /* Allow for error checking. */ 358 i = -1; 359 break; 360 } 361 if (i != -1) 362 ntfs_log_debug("Extent inode was not attached to base " 363 "inode! Continuing regardless.\n"); 364 } 365 /* Remove inode from the list of opened inodes. */ 366 if (ni->nr_extents != -1) 367 list_del(&ni->list_entry); 368 return __ntfs_inode_release(ni); 369} 370 371/** 372 * ntfs_extent_inode_open - load an extent inode and attach it to its base 373 * @base_ni: base ntfs inode 374 * @mref: mft reference of the extent inode to load (in little endian) 375 * 376 * First check if the extent inode @mref is already attached to the base ntfs 377 * inode @base_ni, and if so, return a pointer to the attached extent inode. 378 * 379 * If the extent inode is not already attached to the base inode, allocate an 380 * ntfs_inode structure and initialize it for the given inode @mref. @mref 381 * specifies the inode number / mft record to read, including the sequence 382 * number, which can be 0 if no sequence number checking is to be performed. 383 * 384 * Then, allocate a buffer for the mft record, read the mft record from the 385 * volume @base_ni->vol, and attach it to the ntfs_inode structure (->mrec). 386 * The mft record is mst deprotected and sanity checked for validity and we 387 * abort if deprotection or checks fail. 388 * 389 * Finally attach the ntfs inode to its base inode @base_ni and return a 390 * pointer to the ntfs_inode structure on success or NULL on error, with errno 391 * set to the error code. 392 * 393 * Note, extent inodes are never closed directly. They are automatically 394 * disposed off by the closing of the base inode. 395 */ 396ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const leMFT_REF mref) 397{ 398 u64 mft_no = MREF_LE(mref); 399 ntfs_inode *ni; 400 ntfs_inode **extent_nis; 401 int i; 402 403 if (!base_ni) { 404 errno = EINVAL; 405 return NULL; 406 } 407 ntfs_log_trace("Opening extent inode 0x%llx " 408 "(base MFT record 0x%llx).\n", 409 (unsigned long long)mft_no, 410 (unsigned long long)base_ni->mft_no); 411 /* Is the extent inode already open and attached to the base inode? */ 412 if (base_ni->nr_extents > 0) { 413 extent_nis = base_ni->u.extent_nis; 414 for (i = 0; i < base_ni->nr_extents; i++) { 415 u16 seq_no; 416 417 ni = extent_nis[i]; 418 if (mft_no != ni->mft_no) 419 continue; 420 /* Verify the sequence number if given. */ 421 seq_no = MSEQNO_LE(mref); 422 if (seq_no && seq_no != le16_to_cpu( 423 ni->mrec->sequence_number)) { 424 ntfs_log_debug("Found stale extent mft " 425 "reference! Corrupt file " 426 "system. Run chkdsk.\n"); 427 errno = EIO; 428 return NULL; 429 } 430 /* We are done, return the extent inode. */ 431 return ni; 432 } 433 } 434 /* Wasn't there, we need to load the extent inode. */ 435 ni = __ntfs_inode_allocate(base_ni->vol); 436 if (!ni) 437 return NULL; 438 if (ntfs_file_record_read(base_ni->vol, le64_to_cpu(mref), &ni->mrec, 439 NULL)) 440 goto err_out; 441 ni->mft_no = mft_no; 442 ni->nr_extents = -1; 443 ni->u.base_ni = base_ni; 444 /* Attach extent inode to base inode, reallocating memory if needed. */ 445 if (!(base_ni->nr_extents & 3)) { 446 i = (base_ni->nr_extents + 4) * sizeof(ntfs_inode *); 447 448 extent_nis = (ntfs_inode**)ntfs_malloc(i); 449 if (!extent_nis) 450 goto err_out; 451 if (base_ni->nr_extents) { 452 memcpy(extent_nis, base_ni->u.extent_nis, 453 i - 4 * sizeof(ntfs_inode *)); 454 free(base_ni->u.extent_nis); 455 } 456 base_ni->u.extent_nis = extent_nis; 457 } 458 base_ni->u.extent_nis[base_ni->nr_extents++] = ni; 459 return ni; 460err_out: 461 i = errno; 462 __ntfs_inode_release(ni); 463 errno = i; 464 ntfs_log_perror("Failed to open extent inode"); 465 return NULL; 466} 467 468/** 469 * ntfs_inode_attach_all_extents - attach all extents for target inode 470 * @ni: opened ntfs inode for which perform attach 471 * 472 * Return 0 on success and -1 on error with errno set to the error code. 473 */ 474int ntfs_inode_attach_all_extents(ntfs_inode *ni) 475{ 476 ATTR_LIST_ENTRY *ale; 477 u64 prev_attached = 0; 478 479 if (!ni) { 480 ntfs_log_trace("Invalid arguments.\n"); 481 errno = EINVAL; 482 return -1; 483 } 484 485 if (ni->nr_extents == -1) 486 ni = ni->u.base_ni; 487 488 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 489 490 /* Inode haven't got attribute list, thus nothing to attach. */ 491 if (!NInoAttrList(ni)) 492 return 0; 493 494 if (!ni->attr_list) { 495 ntfs_log_trace("Corrupted in-memory structure.\n"); 496 errno = EINVAL; 497 return -1; 498 } 499 500 /* Walk through attribute list and attach all extents. */ 501 errno = 0; 502 ale = (ATTR_LIST_ENTRY *)ni->attr_list; 503 while ((u8*)ale < ni->attr_list + ni->attr_list_size) { 504 if (ni->mft_no != MREF_LE(ale->mft_reference) && 505 prev_attached != MREF_LE(ale->mft_reference)) { 506 if (!ntfs_extent_inode_open(ni, ale->mft_reference)) { 507 ntfs_log_trace("Couldn't attach extent " 508 "inode (attr type 0x%x " 509 "references to it).\n", 510 le32_to_cpu(ale->type)); 511 return -1; 512 } 513 prev_attached = MREF_LE(ale->mft_reference); 514 } 515 ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length)); 516 } 517 return 0; 518} 519 520/** 521 * ntfs_inode_sync_standard_information - update standard information attribute 522 * @ni: ntfs inode to update standard information 523 * 524 * Return 0 on success or -1 on error with errno set to the error code. 525 */ 526static int ntfs_inode_sync_standard_information(ntfs_inode *ni) 527{ 528 ntfs_attr_search_ctx *ctx; 529 STANDARD_INFORMATION *std_info; 530 int err; 531 532 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 533 534 ctx = ntfs_attr_get_search_ctx(ni, NULL); 535 if (!ctx) 536 return -1; 537 if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 538 0, CASE_SENSITIVE, 0, NULL, 0, ctx)) { 539 err = errno; 540 ntfs_log_trace("Failed to receive STANDARD_INFORMATION " 541 "attribute.\n"); 542 ntfs_attr_put_search_ctx(ctx); 543 errno = err; 544 return -1; 545 } 546 std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr + 547 le16_to_cpu(ctx->attr->u.res.value_offset)); 548 std_info->file_attributes = ni->flags; 549 std_info->creation_time = utc2ntfs(ni->creation_time); 550 std_info->last_data_change_time = utc2ntfs(ni->last_data_change_time); 551 std_info->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); 552 std_info->last_access_time = utc2ntfs(ni->last_access_time); 553 ntfs_attr_put_search_ctx(ctx); 554 return 0; 555} 556 557/** 558 * ntfs_inode_sync_file_name - update FILE_NAME attributes 559 * @ni: ntfs inode to update FILE_NAME attributes 560 * 561 * Update all FILE_NAME attributes for inode @ni in the index. 562 * 563 * Return 0 on success or -1 on error with errno set to the error code. 564 */ 565static int ntfs_inode_sync_file_name(ntfs_inode *ni) 566{ 567 ntfs_attr_search_ctx *ctx = NULL; 568 ntfs_index_context *ictx; 569 ntfs_inode *index_ni; 570 FILE_NAME_ATTR *fn; 571 int err = 0; 572 573 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 574 575 ctx = ntfs_attr_get_search_ctx(ni, NULL); 576 if (!ctx) { 577 err = errno; 578 ntfs_log_trace("Failed to get attribute search context.\n"); 579 goto err_out; 580 } 581 /* Walk through all FILE_NAME attributes and update them. */ 582 while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) { 583 fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr + 584 le16_to_cpu(ctx->attr->u.res.value_offset)); 585 if (MREF_LE(fn->parent_directory) == ni->mft_no) { 586 /* 587 * WARNING: We cheater here and obtain 2 attribute 588 * search contexts for one inode (first we obtained 589 * above, second will be obtained inside 590 * ntfs_index_lookup), it's acceptable for library, 591 * but will lock kernel. 592 */ 593 index_ni = ni; 594 } else 595 index_ni = ntfs_inode_open(ni->vol, 596 le64_to_cpu(fn->parent_directory)); 597 if (!index_ni) { 598 if (!err) 599 err = errno; 600 ntfs_log_trace("Failed to open inode with index.\n"); 601 continue; 602 } 603 ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4); 604 if (!ictx) { 605 if (!err) 606 err = errno; 607 ntfs_log_trace("Failed to get index context.\n"); 608 ntfs_inode_close(index_ni); 609 continue; 610 } 611 if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) { 612 if (!err) { 613 if (errno == ENOENT) 614 err = EIO; 615 else 616 err = errno; 617 } 618 ntfs_log_trace("Index lookup failed.\n"); 619 ntfs_index_ctx_put(ictx); 620 ntfs_inode_close(index_ni); 621 continue; 622 } 623 /* Update flags and file size. */ 624 fn = (FILE_NAME_ATTR *)ictx->data; 625 fn->file_attributes = 626 (fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) | 627 (ni->flags & FILE_ATTR_VALID_FLAGS); 628 fn->allocated_size = cpu_to_sle64(ni->allocated_size); 629 fn->data_size = cpu_to_sle64(ni->data_size); 630 fn->creation_time = utc2ntfs(ni->creation_time); 631 fn->last_data_change_time = utc2ntfs(ni->last_data_change_time); 632 fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time); 633 fn->last_access_time = utc2ntfs(ni->last_access_time); 634 ntfs_index_entry_mark_dirty(ictx); 635 ntfs_index_ctx_put(ictx); 636 if (ni != index_ni) 637 ntfs_inode_close(index_ni); 638 } 639 /* Check for real error occurred. */ 640 if (errno != ENOENT) { 641 err = errno; 642 ntfs_log_trace("Attribute lookup failed.\n"); 643 goto err_out; 644 } 645 ntfs_attr_put_search_ctx(ctx); 646 if (err) { 647 errno = err; 648 return -1; 649 } 650 return 0; 651err_out: 652 if (ctx) 653 ntfs_attr_put_search_ctx(ctx); 654 errno = err; 655 return -1; 656} 657 658/** 659 * ntfs_inode_sync - write the inode (and its dirty extents) to disk 660 * @ni: ntfs inode to write 661 * 662 * Write the inode @ni to disk as well as its dirty extent inodes if such 663 * exist and @ni is a base inode. If @ni is an extent inode, only @ni is 664 * written completely disregarding its base inode and any other extent inodes. 665 * 666 * For a base inode with dirty extent inodes if any writes fail for whatever 667 * reason, the failing inode is skipped and the sync process is continued. At 668 * the end the error condition that brought about the failure is returned. Thus 669 * the smallest amount of data loss possible occurs. 670 * 671 * Return 0 on success or -1 on error with errno set to the error code. 672 * The following error codes are defined: 673 * EINVAL - Invalid arguments were passed to the function. 674 * EBUSY - Inode and/or one of its extents is busy, try again later. 675 * EIO - I/O error while writing the inode (or one of its extents). 676 */ 677int ntfs_inode_sync(ntfs_inode *ni) 678{ 679 int err = 0; 680 681 if (!ni) { 682 errno = EINVAL; 683 return -1; 684 } 685 686 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 687 688 /* Update FILE_NAME's in the index. */ 689 if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && 690 NInoFileNameTestAndClearDirty(ni) && 691 ntfs_inode_sync_file_name(ni)) { 692 if (!err || errno == EIO) { 693 err = errno; 694 if (err != EIO) 695 err = EBUSY; 696 } 697 ntfs_log_trace("Failed to sync FILE_NAME attributes.\n"); 698 NInoFileNameSetDirty(ni); 699 } 700 701 /* Write out attribute list from cache to disk. */ 702 if ((ni->mrec->flags & MFT_RECORD_IN_USE) && ni->nr_extents != -1 && 703 NInoAttrList(ni) && NInoAttrListTestAndClearDirty(ni)) { 704 ntfs_attr *na; 705 706 na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); 707 if (!na) { 708 if (!err || errno == EIO) { 709 err = errno; 710 if (err != EIO) 711 err = EBUSY; 712 ntfs_log_trace("Attribute list sync failed " 713 "(open failed).\n"); 714 } 715 NInoAttrListSetDirty(ni); 716 } else { 717 if (na->data_size == ni->attr_list_size) { 718 if (ntfs_attr_pwrite(na, 0, ni->attr_list_size, 719 ni->attr_list) != 720 ni->attr_list_size) { 721 if (!err || errno == EIO) { 722 err = errno; 723 if (err != EIO) 724 err = EBUSY; 725 ntfs_log_trace("Attribute list " 726 "sync failed " 727 "(write).\n"); 728 } 729 NInoAttrListSetDirty(ni); 730 } 731 } else { 732 err = EIO; 733 ntfs_log_trace("Attribute list sync failed " 734 "(invalid size).\n"); 735 NInoAttrListSetDirty(ni); 736 } 737 ntfs_attr_close(na); 738 } 739 } 740 741 /* Write this inode out to the $MFT (and $MFTMirr if applicable). */ 742 if (NInoTestAndClearDirty(ni)) { 743 /* Update STANDARD_INFORMATION. */ 744 if ((ni->mrec->flags & MFT_RECORD_IN_USE) && 745 ni->nr_extents != -1 && 746 ntfs_inode_sync_standard_information(ni)) { 747 if (!err || errno == EIO) { 748 err = errno; 749 if (err != EIO) 750 err = EBUSY; 751 } 752 ntfs_log_trace("Failed to sync standard " 753 "information.\n"); 754 } 755 /* Write MFT record. */ 756 if (ntfs_mft_record_write(ni->vol, ni->mft_no, ni->mrec)) { 757 if (!err || errno == EIO) { 758 err = errno; 759 if (err != EIO) 760 err = EBUSY; 761 } 762 NInoSetDirty(ni); 763 ntfs_log_trace("Base MFT record sync failed.\n"); 764 } 765 } 766 767 /* If this is a base inode with extents write all dirty extents, too. */ 768 if (ni->nr_extents > 0) { 769 s32 i; 770 771 for (i = 0; i < ni->nr_extents; ++i) { 772 ntfs_inode *eni; 773 774 eni = ni->u.extent_nis[i]; 775 if (NInoTestAndClearDirty(eni)) { 776 if (ntfs_mft_record_write(eni->vol, eni->mft_no, 777 eni->mrec)) { 778 if (!err || errno == EIO) { 779 err = errno; 780 if (err != EIO) 781 err = EBUSY; 782 } 783 NInoSetDirty(eni); 784 ntfs_log_trace("Extent MFT record sync " 785 "failed.\n"); 786 } 787 } 788 } 789 } 790 791 if (!err) 792 return 0; 793 errno = err; 794 return -1; 795} 796 797/** 798 * ntfs_inode_add_attrlist - add attribute list to inode and fill it 799 * @ni: opened ntfs inode to which add attribute list 800 * 801 * Return 0 on success or -1 on error with errno set to the error code. 802 * The following error codes are defined: 803 * EINVAL - Invalid arguments were passed to the function. 804 * EEXIST - Attribute list already exist. 805 * EIO - Input/Ouput error occurred. 806 * ENOMEM - Not enough memory to perform add. 807 */ 808int ntfs_inode_add_attrlist(ntfs_inode *ni) 809{ 810 int err; 811 ntfs_attr_search_ctx *ctx; 812 u8 *al, *aln; 813 int al_len, al_allocated; 814 ATTR_LIST_ENTRY *ale; 815 ntfs_attr *na; 816 817 if (!ni) { 818 ntfs_log_trace("Invalid arguments.\n"); 819 errno = EINVAL; 820 return -1; 821 } 822 823 ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no); 824 825 if (NInoAttrList(ni) || ni->nr_extents) { 826 ntfs_log_trace("Inode already has got attribute list.\n"); 827 errno = EEXIST; 828 return -1; 829 } 830 831 al_allocated = 0x40; 832 al_len = 0; 833 al = malloc(al_allocated); 834 NTFS_ON_DEBUG(memset(al, 0, 0x40)); /* Valgrind. */ 835 ale = (ATTR_LIST_ENTRY *) al; 836 if (!al) { 837 ntfs_log_trace("Not enough memory.\n"); 838 errno = ENOMEM; 839 return -1; 840 } 841 842 /* Form attribute list. */ 843 ctx = ntfs_attr_get_search_ctx(ni, NULL); 844 if (!ctx) { 845 err = errno; 846 ntfs_log_trace("Couldn't get search context.\n"); 847 goto err_out; 848 } 849 /* Walk through all attributes. */ 850 while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { 851 if (ctx->attr->type == AT_ATTRIBUTE_LIST) { 852 err = EIO; 853 ntfs_log_trace("Attribute list already present.\n"); 854 goto put_err_out; 855 } 856 /* Calculate new length of attribute list. */ 857 al_len += (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * 858 ctx->attr->name_length + 7) & ~7; 859 /* Allocate more memory if needed. */ 860 while (al_len > al_allocated) { 861 al_allocated += 0x40; 862 aln = realloc(al, al_allocated); 863 NTFS_ON_DEBUG(memset(aln + al_allocated - 0x40, 0, 864 0x40)); /* Valgrind. */ 865 if (!aln) { 866 ntfs_log_trace("Not enough memory.\n"); 867 err = ENOMEM; 868 goto put_err_out; 869 } 870 ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al)); 871 al = aln; 872 } 873 /* Add attribute to attribute list. */ 874 ale->type = ctx->attr->type; 875 ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) + 876 sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7); 877 ale->name_length = ctx->attr->name_length; 878 ale->name_offset = (u8 *)ale->name - (u8 *)ale; 879 if (ctx->attr->non_resident) 880 ale->lowest_vcn = ctx->attr->u.nonres.lowest_vcn; 881 else 882 ale->lowest_vcn = 0; 883 ale->mft_reference = MK_LE_MREF(ni->mft_no, 884 le16_to_cpu(ni->mrec->sequence_number)); 885 ale->instance = ctx->attr->instance; 886 memcpy(ale->name, (u8 *)ctx->attr + 887 le16_to_cpu(ctx->attr->name_offset), 888 ctx->attr->name_length * sizeof(ntfschar)); 889 ale = (ATTR_LIST_ENTRY *)(al + al_len); 890 } 891 /* Check for real error occurred. */ 892 if (errno != ENOENT) { 893 err = errno; 894 ntfs_log_trace("Attribute lookup failed.\n"); 895 goto put_err_out; 896 } 897 /* Deallocate trailing memory. */ 898 aln = realloc(al, al_len); 899 if (!aln) { 900 err = errno; 901 ntfs_log_trace("realloc() failed.\n"); 902 goto put_err_out; 903 } 904 al = aln; 905 906 /* Set in-memory attribute list. */ 907 ni->attr_list = al; 908 ni->attr_list_size = al_len; 909 NInoSetAttrList(ni); 910 NInoAttrListSetDirty(ni); 911 912 /* Free space if there is not enough it for $ATTRIBUTE_LIST. */ 913 if (le32_to_cpu(ni->mrec->bytes_allocated) - 914 le32_to_cpu(ni->mrec->bytes_in_use) < 915 offsetof(ATTR_RECORD, u.res.resident_end)) { 916 if (ntfs_inode_free_space(ni, 917 offsetof(ATTR_RECORD, u.res.resident_end))) { 918 /* Failed to free space. */ 919 err = errno; 920 ntfs_log_trace("Failed to free space for " 921 "$ATTRIBUTE_LIST.\n"); 922 goto rollback; 923 } 924 } 925 926 /* Add $ATTRIBUTE_LIST to mft record. */ 927 if (ntfs_resident_attr_record_add(ni, 928 AT_ATTRIBUTE_LIST, NULL, 0, NULL, 0, 0) < 0) { 929 err = errno; 930 ntfs_log_trace("Couldn't add $ATTRIBUTE_LIST to MFT record.\n"); 931 goto rollback; 932 } 933 934 /* Resize it. */ 935 na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0); 936 if (!na) { 937 err = errno; 938 ntfs_log_trace("Failed to open just added $ATTRIBUTE_LIST.\n"); 939 goto remove_attrlist_record; 940 } 941 if (ntfs_attr_truncate(na, al_len)) { 942 err = errno; 943 ntfs_log_trace("Failed to resize just added $ATTRIBUTE_LIST.\n"); 944 ntfs_attr_close(na); 945 goto remove_attrlist_record;; 946 } 947 /* Done! */ 948 ntfs_attr_put_search_ctx(ctx); 949 ntfs_attr_close(na); 950 return 0; 951remove_attrlist_record: 952 /* Prevent ntfs_attr_recorm_rm from freeing attribute list. */ 953 ni->attr_list = NULL; 954 NInoClearAttrList(ni); 955 /* Remove $ATTRIBUTE_LIST record. */ 956 ntfs_attr_reinit_search_ctx(ctx); 957 if (!ntfs_attr_lookup(AT_ATTRIBUTE_LIST, NULL, 0, 958 CASE_SENSITIVE, 0, NULL, 0, ctx)) { 959 if (ntfs_attr_record_rm(ctx)) 960 ntfs_log_trace("Rollback failed. Failed to remove attribute " 961 "list record.\n"); 962 } else 963 ntfs_log_trace("Rollback failed. Couldn't find attribute list " 964 "record.\n"); 965 /* Setup back in-memory runlist. */ 966 ni->attr_list = al; 967 ni->attr_list_size = al_len; 968 NInoSetAttrList(ni); 969rollback: 970 /* 971 * Scan attribute list for attributes that placed not in the base MFT 972 * record and move them to it. 973 */ 974 ntfs_attr_reinit_search_ctx(ctx); 975 ale = (ATTR_LIST_ENTRY*)al; 976 while ((u8*)ale < al + al_len) { 977 if (MREF_LE(ale->mft_reference) != ni->mft_no) { 978 if (!ntfs_attr_lookup(ale->type, ale->name, 979 ale->name_length, 980 CASE_SENSITIVE, 981 sle64_to_cpu(ale->lowest_vcn), 982 NULL, 0, ctx)) { 983 if (ntfs_attr_record_move_to(ctx, ni)) 984 ntfs_log_trace("Rollback failed. Couldn't " 985 "back attribute to base MFT record.\n"); 986 } else 987 ntfs_log_trace("Rollback failed. ntfs_attr_lookup " 988 "failed.\n"); 989 ntfs_attr_reinit_search_ctx(ctx); 990 } 991 ale = (ATTR_LIST_ENTRY*)((u8*)ale + le16_to_cpu(ale->length)); 992 } 993 /* Remove in-memory attribute list. */ 994 ni->attr_list = NULL; 995 ni->attr_list_size = 0; 996 NInoClearAttrList(ni); 997 NInoAttrListClearDirty(ni); 998put_err_out: 999 ntfs_attr_put_search_ctx(ctx); 1000err_out: 1001 free(al); 1002 errno = err; 1003 return -1; 1004} 1005 1006/** 1007 * ntfs_inode_free_space - free space in the MFT record of inode 1008 * @ni: ntfs inode in which MFT record free space 1009 * @size: amount of space needed to free 1010 * 1011 * Return 0 on success or -1 on error with errno set to the error code. 1012 */ 1013int ntfs_inode_free_space(ntfs_inode *ni, int size) 1014{ 1015 ntfs_attr_search_ctx *ctx; 1016 int freed, err; 1017 1018 if (!ni || size < 0) { 1019 ntfs_log_trace("Invalid arguments.\n"); 1020 errno = EINVAL; 1021 return -1; 1022 } 1023 1024 ntfs_log_trace("Entering for inode 0x%llx, size %d.\n", 1025 (long long) ni->mft_no, size); 1026 1027 freed = (le32_to_cpu(ni->mrec->bytes_allocated) - 1028 le32_to_cpu(ni->mrec->bytes_in_use)); 1029 1030 if (size <= freed) 1031 return 0; 1032 1033 ctx = ntfs_attr_get_search_ctx(ni, NULL); 1034 if (!ctx) { 1035 ntfs_log_trace("Failed to get attribute search context.\n"); 1036 return -1; 1037 } 1038 1039 /* 1040 * Chkdsk complain if $STANDARD_INFORMATION is not in the base MFT 1041 * record. FIXME: I'm not sure in this, need to recheck. For now simply 1042 * do not move $STANDARD_INFORMATION at all. 1043 * 1044 * Also we can't move $ATTRIBUTE_LIST from base MFT_RECORD, so position 1045 * search context on first attribute after $STANDARD_INFORMATION and 1046 * $ATTRIBUTE_LIST. 1047 * 1048 * Why we reposition instead of simply skip this attributes during 1049 * enumeration? Because in case we have got only in-memory attribute 1050 * list ntfs_attr_lookup will fail when it will try to find 1051 * $ATTRIBUTE_LIST. 1052 */ 1053 if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, NULL, 1054 0, ctx)) { 1055 if (errno != ENOENT) { 1056 err = errno; 1057 ntfs_log_trace("Attribute lookup failed.\n"); 1058 goto put_err_out; 1059 } 1060 if (ctx->attr->type == AT_END) { 1061 err = ENOSPC; 1062 goto put_err_out; 1063 } 1064 } 1065 1066 while (1) { 1067 int record_size; 1068 1069 /* 1070 * Check whether attribute is from different MFT record. If so, 1071 * find next, because we don't need such. 1072 */ 1073 while (ctx->ntfs_ino->mft_no != ni->mft_no) { 1074 if (ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 1075 0, NULL, 0, ctx)) { 1076 err = errno; 1077 if (errno != ENOENT) { 1078 ntfs_log_trace("Attribute lookup failed.\n"); 1079 } else 1080 err = ENOSPC; 1081 goto put_err_out; 1082 } 1083 } 1084 1085 record_size = le32_to_cpu(ctx->attr->length); 1086 1087 /* Move away attribute. */ 1088 if (ntfs_attr_record_move_away(ctx, 0)) { 1089 err = errno; 1090 ntfs_log_trace("Failed to move out attribute.\n"); 1091 break; 1092 } 1093 freed += record_size; 1094 1095 /* Check whether we done. */ 1096 if (size <= freed) { 1097 ntfs_attr_put_search_ctx(ctx); 1098 return 0; 1099 } 1100 1101 /* 1102 * Reposition to first attribute after $STANDARD_INFORMATION and 1103 * $ATTRIBUTE_LIST (see comments upwards). 1104 */ 1105 ntfs_attr_reinit_search_ctx(ctx); 1106 if (ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, CASE_SENSITIVE, 0, 1107 NULL, 0, ctx)) { 1108 if (errno != ENOENT) { 1109 err = errno; 1110 ntfs_log_trace("Attribute lookup failed.\n"); 1111 break; 1112 } 1113 if (ctx->attr->type == AT_END) { 1114 err = ENOSPC; 1115 break; 1116 } 1117 } 1118 } 1119put_err_out: 1120 ntfs_attr_put_search_ctx(ctx); 1121 if (err == ENOSPC) 1122 ntfs_log_trace("No attributes left that can be moved out.\n"); 1123 errno = err; 1124 return -1; 1125} 1126 1127/** 1128 * ntfs_inode_update_times - update selected time fields for ntfs inode 1129 * @ni: ntfs inode for which update time fields 1130 * @mask: select which time fields should be updated 1131 * 1132 * This function updates time fields to current time. Fields to update are 1133 * selected using @mask (see enum @ntfs_time_update_flags for posssible values). 1134 */ 1135void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask) 1136{ 1137 time_t now; 1138 1139 if (!ni) { 1140 ntfs_log_error("%s(): Invalid arguments.\n", "ntfs_inode_update_times"); 1141 return; 1142 } 1143 if ((ni->mft_no < FILE_first_user && ni->mft_no != FILE_root) || 1144 NVolReadOnly(ni->vol) || !mask) 1145 return; 1146 1147 now = time(NULL); 1148 if (mask & NTFS_UPDATE_ATIME) 1149 ni->last_access_time = now; 1150 if (mask & NTFS_UPDATE_MTIME) 1151 ni->last_data_change_time = now; 1152 if (mask & NTFS_UPDATE_CTIME) 1153 ni->last_mft_change_time = now; 1154 NInoFileNameSetDirty(ni); 1155 NInoSetDirty(ni); 1156} 1157 1158/** 1159 * ntfs_inode_badclus_bad - check for $Badclus:$Bad data attribute 1160 * @mft_no: mft record number where @attr is present 1161 * @attr: attribute record used to check for the $Bad attribute 1162 * 1163 * Check if the mft record given by @mft_no and @attr contains the bad sector 1164 * list. Please note that mft record numbers describing $Badclus extent inodes 1165 * will not match the current $Badclus:$Bad check. 1166 * 1167 * On success return 1 if the file is $Badclus:$Bad, otherwise return 0. 1168 * On error return -1 with errno set to the error code. 1169 */ 1170int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr) 1171{ 1172 int len, ret = 0; 1173 ntfschar *ustr; 1174 1175 if (!attr) { 1176 ntfs_log_error("Invalid argument.\n"); 1177 errno = EINVAL; 1178 return -1; 1179 } 1180 1181 if (mft_no != FILE_BadClus) 1182 return 0; 1183 1184 if (attr->type != AT_DATA) 1185 return 0; 1186 1187 if ((ustr = ntfs_str2ucs("$Bad", &len)) == NULL) { 1188 ntfs_log_perror("Couldn't convert '$Bad' to Unicode"); 1189 return -1; 1190 } 1191 1192 if (ustr && ntfs_names_are_equal(ustr, len, 1193 (ntfschar *)((u8 *)attr + le16_to_cpu( 1194 attr->name_offset)), attr->name_length, 0, NULL, 0)) 1195 ret = 1; 1196 1197 ntfs_ucsfree(ustr); 1198 1199 return ret; 1200} 1201