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