1 /** 2 * volume.c - NTFS volume handling code. Originated from the Linux-NTFS project. 3 * 4 * Copyright (c) 2000-2006 Anton Altaparmakov 5 * Copyright (c) 2002-2006 Szabolcs Szakacsits 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 NTFS-3G 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_STDIO_H 32 #include <stdio.h> 33 #endif 34 #ifdef HAVE_STRING_H 35 #include <string.h> 36 #endif 37 #ifdef HAVE_FCNTL_H 38 #include <fcntl.h> 39 #endif 40 #ifdef HAVE_UNISTD_H 41 #include <unistd.h> 42 #endif 43 #ifdef HAVE_ERRNO_H 44 #include <errno.h> 45 #endif 46 #ifdef HAVE_SYS_STAT_H 47 #include <sys/stat.h> 48 #endif 49 #ifdef HAVE_LIMITS_H 50 #include <limits.h> 51 #endif 52 53 #include "volume.h" 54 #include "attrib.h" 55 #include "mft.h" 56 #include "bootsect.h" 57 #include "device.h" 58 #include "debug.h" 59 #include "inode.h" 60 #include "runlist.h" 61 #include "logfile.h" 62 #include "dir.h" 63 #include "logging.h" 64 #include "misc.h" 65 66 #ifndef PATH_MAX 67 #define PATH_MAX 4096 68 #endif 69 70 /** 71 * ntfs_volume_alloc - Create an NTFS volume object and initialise it 72 * 73 * Description... 74 * 75 * Returns: 76 */ 77 ntfs_volume *ntfs_volume_alloc(void) 78 { 79 return calloc(1, sizeof(ntfs_volume)); 80 } 81 82 83 static void ntfs_attr_free(ntfs_attr **na) 84 { 85 if (na && *na) { 86 ntfs_attr_close(*na); 87 *na = NULL; 88 } else 89 ntfs_log_error("Tried to free NULL attribute pointer (%p)\n", na); 90 } 91 92 static int ntfs_inode_free(ntfs_inode **ni) 93 { 94 int ret = -1; 95 96 if (ni && *ni) { 97 ret = ntfs_inode_close(*ni); 98 *ni = NULL; 99 } else 100 ntfs_log_error("Tried to free NULL inode pointer (%p)\n", ni); 101 102 return ret; 103 } 104 105 static void ntfs_error_set(int *err) 106 { 107 if (!*err) 108 *err = errno; 109 } 110 111 /** 112 * __ntfs_volume_release - Destroy an NTFS volume object 113 * @v: 114 * 115 * Description... 116 * 117 * Returns: 118 */ 119 static int __ntfs_volume_release(ntfs_volume *v) 120 { 121 int err = 0; 122 123 if (ntfs_inode_free(&v->vol_ni)) 124 ntfs_error_set(&err); 125 /* 126 * FIXME: Inodes must be synced before closing 127 * attributes, otherwise unmount could fail. 128 */ 129 if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni)) 130 ntfs_inode_sync(v->lcnbmp_ni); 131 ntfs_attr_free(&v->lcnbmp_na); 132 if (ntfs_inode_free(&v->lcnbmp_ni)) 133 ntfs_error_set(&err); 134 135 if (v->mft_ni && NInoDirty(v->mft_ni)) 136 ntfs_inode_sync(v->mft_ni); 137 ntfs_attr_free(&v->mftbmp_na); 138 ntfs_attr_free(&v->mft_na); 139 if (ntfs_inode_free(&v->mft_ni)) 140 ntfs_error_set(&err); 141 142 if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni)) 143 ntfs_inode_sync(v->mftmirr_ni); 144 ntfs_attr_free(&v->mftmirr_na); 145 if (ntfs_inode_free(&v->mftmirr_ni)) 146 ntfs_error_set(&err); 147 148 if (v->dev) { 149 struct ntfs_device *dev = v->dev; 150 151 if (dev->d_ops->sync(dev)) 152 ntfs_error_set(&err); 153 if (dev->d_ops->close(dev)) 154 ntfs_error_set(&err); 155 } 156 157 free(v->vol_name); 158 free(v->upcase); 159 free(v->attrdef); 160 free(v); 161 162 errno = err; 163 return errno ? -1 : 0; 164 } 165 166 static void ntfs_attr_setup_flag(ntfs_inode *ni) 167 { 168 STANDARD_INFORMATION *si; 169 170 si = ntfs_attr_readall(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, NULL); 171 if (si) { 172 ni->flags = si->file_attributes; 173 free(si); 174 } 175 } 176 177 /** 178 * ntfs_mft_load - load the $MFT and setup the ntfs volume with it 179 * @vol: ntfs volume whose $MFT to load 180 * 181 * Load $MFT from @vol and setup @vol with it. After calling this function the 182 * volume @vol is ready for use by all read access functions provided by the 183 * ntfs library. 184 * 185 * Return 0 on success and -1 on error with errno set to the error code. 186 */ 187 static int ntfs_mft_load(ntfs_volume *vol) 188 { 189 VCN next_vcn, last_vcn, highest_vcn; 190 s64 l; 191 MFT_RECORD *mb = NULL; 192 ntfs_attr_search_ctx *ctx = NULL; 193 ATTR_RECORD *a; 194 int eo; 195 196 /* Manually setup an ntfs_inode. */ 197 vol->mft_ni = ntfs_inode_allocate(vol); 198 mb = ntfs_malloc(vol->mft_record_size); 199 if (!vol->mft_ni || !mb) { 200 ntfs_log_perror("Error allocating memory for $MFT"); 201 goto error_exit; 202 } 203 vol->mft_ni->mft_no = 0; 204 vol->mft_ni->mrec = mb; 205 /* Can't use any of the higher level functions yet! */ 206 l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1, 207 vol->mft_record_size, mb); 208 if (l != 1) { 209 if (l != -1) 210 errno = EIO; 211 ntfs_log_perror("Error reading $MFT"); 212 goto error_exit; 213 } 214 if (ntfs_is_baad_record(mb->magic)) { 215 ntfs_log_error("Incomplete multi sector transfer detected in " 216 "$MFT.\n"); 217 goto io_error_exit; 218 } 219 if (!ntfs_is_mft_record(mb->magic)) { 220 ntfs_log_error("$MFT has invalid magic.\n"); 221 goto io_error_exit; 222 } 223 ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL); 224 if (!ctx) { 225 ntfs_log_perror("Failed to allocate attribute search context"); 226 goto error_exit; 227 } 228 if (p2n(ctx->attr) < p2n(mb) || 229 (char*)ctx->attr > (char*)mb + vol->mft_record_size) { 230 ntfs_log_error("$MFT is corrupt.\n"); 231 goto io_error_exit; 232 } 233 /* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */ 234 if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0, 235 ctx)) { 236 if (errno != ENOENT) { 237 ntfs_log_error("$MFT has corrupt attribute list.\n"); 238 goto io_error_exit; 239 } 240 goto mft_has_no_attr_list; 241 } 242 NInoSetAttrList(vol->mft_ni); 243 l = ntfs_get_attribute_value_length(ctx->attr); 244 if (l <= 0 || l > 0x40000) { 245 ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n", 246 (long long)l); 247 goto io_error_exit; 248 } 249 vol->mft_ni->attr_list_size = l; 250 vol->mft_ni->attr_list = ntfs_malloc(l); 251 if (!vol->mft_ni->attr_list) 252 goto error_exit; 253 254 l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list); 255 if (!l) { 256 ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n"); 257 goto io_error_exit; 258 } 259 if (l != vol->mft_ni->attr_list_size) { 260 ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != " 261 "%u).\n", (long long)l, 262 vol->mft_ni->attr_list_size); 263 goto io_error_exit; 264 } 265 266 mft_has_no_attr_list: 267 268 ntfs_attr_setup_flag(vol->mft_ni); 269 270 /* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */ 271 272 /* Get an ntfs attribute for $MFT/$DATA and set it up, too. */ 273 vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); 274 if (!vol->mft_na) { 275 ntfs_log_perror("Failed to open ntfs attribute"); 276 goto error_exit; 277 } 278 /* Read all extents from the $DATA attribute in $MFT. */ 279 ntfs_attr_reinit_search_ctx(ctx); 280 last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits; 281 highest_vcn = next_vcn = 0; 282 a = NULL; 283 while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0, 284 ctx)) { 285 runlist_element *nrl; 286 287 a = ctx->attr; 288 /* $MFT must be non-resident. */ 289 if (!a->non_resident) { 290 ntfs_log_error("$MFT must be non-resident.\n"); 291 goto io_error_exit; 292 } 293 /* $MFT must be uncompressed and unencrypted. */ 294 if (a->flags & ATTR_COMPRESSION_MASK || 295 a->flags & ATTR_IS_ENCRYPTED) { 296 ntfs_log_error("$MFT must be uncompressed and " 297 "unencrypted.\n"); 298 goto io_error_exit; 299 } 300 /* 301 * Decompress the mapping pairs array of this extent and merge 302 * the result into the existing runlist. No need for locking 303 * as we have exclusive access to the inode at this time and we 304 * are a mount in progress task, too. 305 */ 306 nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl); 307 if (!nrl) { 308 ntfs_log_perror("ntfs_mapping_pairs_decompress() failed"); 309 goto error_exit; 310 } 311 vol->mft_na->rl = nrl; 312 313 /* Get the lowest vcn for the next extent. */ 314 highest_vcn = sle64_to_cpu(a->highest_vcn); 315 next_vcn = highest_vcn + 1; 316 317 /* Only one extent or error, which we catch below. */ 318 if (next_vcn <= 0) 319 break; 320 321 /* Avoid endless loops due to corruption. */ 322 if (next_vcn < sle64_to_cpu(a->lowest_vcn)) { 323 ntfs_log_error("$MFT has corrupt attribute list.\n"); 324 goto io_error_exit; 325 } 326 } 327 if (!a) { 328 ntfs_log_error("$MFT/$DATA attribute not found.\n"); 329 goto io_error_exit; 330 } 331 if (highest_vcn && highest_vcn != last_vcn - 1) { 332 ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n"); 333 ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n", 334 (long long)highest_vcn, (long long)last_vcn - 1); 335 goto io_error_exit; 336 } 337 /* Done with the $Mft mft record. */ 338 ntfs_attr_put_search_ctx(ctx); 339 ctx = NULL; 340 /* 341 * The volume is now setup so we can use all read access functions. 342 */ 343 vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0); 344 if (!vol->mftbmp_na) { 345 ntfs_log_perror("Failed to open $MFT/$BITMAP"); 346 goto error_exit; 347 } 348 return 0; 349 io_error_exit: 350 errno = EIO; 351 error_exit: 352 eo = errno; 353 if (ctx) 354 ntfs_attr_put_search_ctx(ctx); 355 if (vol->mft_na) { 356 ntfs_attr_close(vol->mft_na); 357 vol->mft_na = NULL; 358 } 359 if (vol->mft_ni) { 360 ntfs_inode_close(vol->mft_ni); 361 vol->mft_ni = NULL; 362 } 363 errno = eo; 364 return -1; 365 } 366 367 /** 368 * ntfs_mftmirr_load - load the $MFTMirr and setup the ntfs volume with it 369 * @vol: ntfs volume whose $MFTMirr to load 370 * 371 * Load $MFTMirr from @vol and setup @vol with it. After calling this function 372 * the volume @vol is ready for use by all write access functions provided by 373 * the ntfs library (assuming ntfs_mft_load() has been called successfully 374 * beforehand). 375 * 376 * Return 0 on success and -1 on error with errno set to the error code. 377 */ 378 static int ntfs_mftmirr_load(ntfs_volume *vol) 379 { 380 int err; 381 382 vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr); 383 if (!vol->mftmirr_ni) { 384 ntfs_log_perror("Failed to open inode $MFTMirr"); 385 return -1; 386 } 387 388 vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0); 389 if (!vol->mftmirr_na) { 390 ntfs_log_perror("Failed to open $MFTMirr/$DATA"); 391 goto error_exit; 392 } 393 394 if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) { 395 ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA"); 396 goto error_exit; 397 } 398 399 return 0; 400 401 error_exit: 402 err = errno; 403 if (vol->mftmirr_na) { 404 ntfs_attr_close(vol->mftmirr_na); 405 vol->mftmirr_na = NULL; 406 } 407 ntfs_inode_close(vol->mftmirr_ni); 408 vol->mftmirr_ni = NULL; 409 errno = err; 410 return -1; 411 } 412 413 /** 414 * ntfs_volume_startup - allocate and setup an ntfs volume 415 * @dev: device to open 416 * @flags: optional mount flags 417 * 418 * Load, verify, and parse bootsector; load and setup $MFT and $MFTMirr. After 419 * calling this function, the volume is setup sufficiently to call all read 420 * and write access functions provided by the library. 421 * 422 * Return the allocated volume structure on success and NULL on error with 423 * errno set to the error code. 424 */ 425 ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags) 426 { 427 LCN mft_zone_size, mft_lcn; 428 s64 br; 429 ntfs_volume *vol; 430 NTFS_BOOT_SECTOR *bs; 431 int eo; 432 #ifdef DEBUG 433 const char *OK = "OK\n"; 434 const char *FAILED = "FAILED\n"; 435 #endif 436 437 if (!dev || !dev->d_ops || !dev->d_name) { 438 errno = EINVAL; 439 return NULL; 440 } 441 442 bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR)); 443 if (!bs) 444 return NULL; 445 446 /* Allocate the volume structure. */ 447 vol = ntfs_volume_alloc(); 448 if (!vol) 449 goto error_exit; 450 /* Create the default upcase table. */ 451 vol->upcase_len = 65536; 452 vol->upcase = ntfs_malloc(vol->upcase_len * sizeof(ntfschar)); 453 if (!vol->upcase) 454 goto error_exit; 455 456 ntfs_upcase_table_build(vol->upcase, 457 vol->upcase_len * sizeof(ntfschar)); 458 if (flags & MS_RDONLY) 459 NVolSetReadOnly(vol); 460 if (flags & MS_NOATIME) 461 NVolSetNoATime(vol); 462 ntfs_log_debug("Reading bootsector... "); 463 if (dev->d_ops->open(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) { 464 ntfs_log_debug(FAILED); 465 ntfs_log_perror("Error opening partition device"); 466 goto error_exit; 467 } 468 /* Attach the device to the volume. */ 469 vol->dev = dev; 470 /* Now read the bootsector. */ 471 br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs); 472 if (br != sizeof(NTFS_BOOT_SECTOR)) { 473 ntfs_log_debug(FAILED); 474 if (br != -1) 475 errno = EINVAL; 476 if (!br) 477 ntfs_log_error("Partition is smaller than bootsector " 478 "size.\n"); 479 else 480 ntfs_log_perror("Error reading bootsector"); 481 goto error_exit; 482 } 483 ntfs_log_debug(OK); 484 if (!ntfs_boot_sector_is_ntfs(bs)) { 485 errno = EINVAL; 486 goto error_exit; 487 } 488 if (ntfs_boot_sector_parse(vol, bs) < 0) 489 goto error_exit; 490 491 free(bs); 492 bs = NULL; 493 /* Now set the device block size to the sector size. */ 494 if (ntfs_device_block_size_set(vol->dev, vol->sector_size)) 495 ntfs_log_debug("Failed to set the device block size to the " 496 "sector size. This may affect performance " 497 "but should be harmless otherwise. Error: " 498 "%s\n", strerror(errno)); 499 500 /* We now initialize the cluster allocator. */ 501 502 mft_zone_size = min(vol->nr_clusters >> 3, /* 12.5% */ 503 200 * 1000 * 1024 >> vol->cluster_size_bits); 504 505 /* Setup the mft zone. */ 506 vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn; 507 ntfs_log_debug("mft_zone_pos = 0x%llx\n", (long long)vol->mft_zone_pos); 508 509 /* 510 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs 511 * source) and if the actual mft_lcn is in the expected place or even 512 * further to the front of the volume, extend the mft_zone to cover the 513 * beginning of the volume as well. This is in order to protect the 514 * area reserved for the mft bitmap as well within the mft_zone itself. 515 * On non-standard volumes we don't protect it as the overhead would be 516 * higher than the speed increase we would get by doing it. 517 */ 518 mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size; 519 if (mft_lcn * vol->cluster_size < 16 * 1024) 520 mft_lcn = (16 * 1024 + vol->cluster_size - 1) / 521 vol->cluster_size; 522 if (vol->mft_zone_start <= mft_lcn) 523 vol->mft_zone_start = 0; 524 ntfs_log_debug("mft_zone_start = 0x%llx\n", (long long)vol->mft_zone_start); 525 526 /* 527 * Need to cap the mft zone on non-standard volumes so that it does 528 * not point outside the boundaries of the volume. We do this by 529 * halving the zone size until we are inside the volume. 530 */ 531 vol->mft_zone_end = vol->mft_lcn + mft_zone_size; 532 while (vol->mft_zone_end >= vol->nr_clusters) { 533 mft_zone_size >>= 1; 534 vol->mft_zone_end = vol->mft_lcn + mft_zone_size; 535 } 536 ntfs_log_debug("mft_zone_end = 0x%llx\n", (long long)vol->mft_zone_end); 537 538 /* 539 * Set the current position within each data zone to the start of the 540 * respective zone. 541 */ 542 vol->data1_zone_pos = vol->mft_zone_end; 543 ntfs_log_debug("data1_zone_pos = 0x%llx\n", vol->data1_zone_pos); 544 vol->data2_zone_pos = 0; 545 ntfs_log_debug("data2_zone_pos = 0x%llx\n", vol->data2_zone_pos); 546 547 /* Set the mft data allocation position to mft record 24. */ 548 vol->mft_data_pos = 24; 549 550 /* 551 * The cluster allocator is now fully operational. 552 */ 553 554 /* Need to setup $MFT so we can use the library read functions. */ 555 ntfs_log_debug("Loading $MFT... "); 556 if (ntfs_mft_load(vol) < 0) { 557 ntfs_log_debug(FAILED); 558 ntfs_log_perror("Failed to load $MFT"); 559 goto error_exit; 560 } 561 ntfs_log_debug(OK); 562 563 /* Need to setup $MFTMirr so we can use the write functions, too. */ 564 ntfs_log_debug("Loading $MFTMirr... "); 565 if (ntfs_mftmirr_load(vol) < 0) { 566 ntfs_log_debug(FAILED); 567 ntfs_log_perror("Failed to load $MFTMirr"); 568 goto error_exit; 569 } 570 ntfs_log_debug(OK); 571 return vol; 572 error_exit: 573 eo = errno; 574 free(bs); 575 if (vol) 576 __ntfs_volume_release(vol); 577 errno = eo; 578 return NULL; 579 } 580 581 /** 582 * ntfs_volume_check_logfile - check logfile on target volume 583 * @vol: volume on which to check logfile 584 * 585 * Return 0 on success and -1 on error with errno set error code. 586 */ 587 static int ntfs_volume_check_logfile(ntfs_volume *vol) 588 { 589 ntfs_inode *ni; 590 ntfs_attr *na = NULL; 591 RESTART_PAGE_HEADER *rp = NULL; 592 int err = 0; 593 594 ni = ntfs_inode_open(vol, FILE_LogFile); 595 if (!ni) { 596 ntfs_log_perror("Failed to open inode FILE_LogFile"); 597 errno = EIO; 598 return -1; 599 } 600 601 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 602 if (!na) { 603 ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); 604 err = EIO; 605 goto out; 606 } 607 608 if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) 609 err = EOPNOTSUPP; 610 free(rp); 611 ntfs_attr_close(na); 612 out: 613 if (ntfs_inode_close(ni)) 614 ntfs_error_set(&err); 615 if (err) { 616 errno = err; 617 return -1; 618 } 619 return 0; 620 } 621 622 /** 623 * ntfs_hiberfile_open - Find and open '/hiberfil.sys' 624 * @vol: An ntfs volume obtained from ntfs_mount 625 * 626 * Return: inode Success, hiberfil.sys is valid 627 * NULL hiberfil.sys doesn't exist or some other error occurred 628 */ 629 static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol) 630 { 631 u64 inode; 632 ntfs_inode *ni_root; 633 ntfs_inode *ni_hibr = NULL; 634 ntfschar *unicode = NULL; 635 int unicode_len; 636 const char *hiberfile = "hiberfil.sys"; 637 638 if (!vol) { 639 errno = EINVAL; 640 return NULL; 641 } 642 643 ni_root = ntfs_inode_open(vol, FILE_root); 644 if (!ni_root) { 645 ntfs_log_debug("Couldn't open the root directory.\n"); 646 return NULL; 647 } 648 649 unicode_len = ntfs_mbstoucs(hiberfile, &unicode, 0); 650 if (unicode_len < 0) { 651 ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode"); 652 goto out; 653 } 654 655 inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len); 656 if (inode == (u64)-1) { 657 ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile); 658 goto out; 659 } 660 661 inode = MREF(inode); 662 ni_hibr = ntfs_inode_open(vol, inode); 663 if (!ni_hibr) { 664 ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode); 665 goto out; 666 } 667 out: 668 if (ntfs_inode_close(ni_root)) { 669 ntfs_inode_close(ni_hibr); 670 ni_hibr = NULL; 671 } 672 free(unicode); 673 return ni_hibr; 674 } 675 676 677 #define NTFS_HIBERFILE_HEADER_SIZE 4096 678 679 /** 680 * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is 681 * hibernated on the target volume 682 * @vol: volume on which to check hiberfil.sys 683 * 684 * Return: 0 if Windows isn't hibernated for sure 685 * -1 otherwise and errno is set to the appropriate value 686 */ 687 static int ntfs_volume_check_hiberfile(ntfs_volume *vol) 688 { 689 ntfs_inode *ni; 690 ntfs_attr *na = NULL; 691 int i, bytes_read, err; 692 char *buf = NULL; 693 694 ni = ntfs_hiberfile_open(vol); 695 if (!ni) { 696 if (errno == ENOENT) 697 return 0; 698 return -1; 699 } 700 701 buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE); 702 if (!buf) 703 goto out; 704 705 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 706 if (!na) { 707 ntfs_log_perror("Failed to open hiberfil.sys data attribute"); 708 goto out; 709 } 710 711 bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf); 712 if (bytes_read == -1) { 713 ntfs_log_perror("Failed to read hiberfil.sys"); 714 goto out; 715 } 716 if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) { 717 ntfs_log_error("Hibernated non-system partition, refused to " 718 "mount.\n"); 719 errno = EPERM; 720 goto out; 721 } 722 if (memcmp(buf, "hibr", 4) == 0) { 723 ntfs_log_error("Windows is hibernated, refused to mount.\n"); 724 errno = EPERM; 725 goto out; 726 } 727 for (i = 0; i < NTFS_HIBERFILE_HEADER_SIZE; i++) { 728 if (buf[i]) { 729 ntfs_log_error("Windows is hibernated, won't mount.\n"); 730 errno = EPERM; 731 goto out; 732 } 733 } 734 /* All right, all header bytes are zero */ 735 errno = 0; 736 out: 737 if (na) 738 ntfs_attr_close(na); 739 free(buf); 740 err = errno; 741 if (ntfs_inode_close(ni)) 742 ntfs_error_set(&err); 743 errno = err; 744 return errno ? -1 : 0; 745 } 746 747 /** 748 * ntfs_device_mount - open ntfs volume 749 * @dev: device to open 750 * @flags: optional mount flags 751 * 752 * This function mounts an ntfs volume. @dev should describe the device which 753 * to mount as the ntfs volume. 754 * 755 * @flags is an optional second parameter. The same flags are used as for 756 * the mount system call (man 2 mount). Currently only the following flags 757 * are implemented: 758 * MS_RDONLY - mount volume read-only 759 * MS_NOATIME - do not update access time 760 * 761 * The function opens the device @dev and verifies that it contains a valid 762 * bootsector. Then, it allocates an ntfs_volume structure and initializes 763 * some of the values inside the structure from the information stored in the 764 * bootsector. It proceeds to load the necessary system files and completes 765 * setting up the structure. 766 * 767 * Return the allocated volume structure on success and NULL on error with 768 * errno set to the error code. 769 */ 770 ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags) 771 { 772 s64 l; 773 #ifdef DEBUG 774 const char *OK = "OK\n"; 775 const char *FAILED = "FAILED\n"; 776 #endif 777 ntfs_volume *vol; 778 u8 *m = NULL, *m2 = NULL; 779 ntfs_attr_search_ctx *ctx = NULL; 780 ntfs_inode *ni; 781 ntfs_attr *na; 782 ATTR_RECORD *a; 783 VOLUME_INFORMATION *vinf; 784 ntfschar *vname; 785 int i, j, eo; 786 u32 u; 787 788 vol = ntfs_volume_startup(dev, flags); 789 if (!vol) { 790 ntfs_log_perror("Failed to startup volume"); 791 return NULL; 792 } 793 794 /* Load data from $MFT and $MFTMirr and compare the contents. */ 795 m = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits); 796 m2 = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits); 797 if (!m || !m2) 798 goto error_exit; 799 800 l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size, 801 vol->mft_record_size, m); 802 if (l != vol->mftmirr_size) { 803 if (l == -1) 804 ntfs_log_perror("Failed to read $MFT"); 805 else { 806 ntfs_log_error("Failed to read $MFT, unexpected length " 807 "(%lld != %d).\n", (long long)l, 808 vol->mftmirr_size); 809 errno = EIO; 810 } 811 goto error_exit; 812 } 813 l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size, 814 vol->mft_record_size, m2); 815 if (l != vol->mftmirr_size) { 816 if (l == -1) { 817 ntfs_log_perror("Failed to read $MFTMirr"); 818 goto error_exit; 819 } 820 vol->mftmirr_size = l; 821 } 822 ntfs_log_debug("Comparing $MFTMirr to $MFT... "); 823 for (i = 0; i < vol->mftmirr_size; ++i) { 824 MFT_RECORD *mrec, *mrec2; 825 const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", 826 "$Volume", "$AttrDef", "root directory", "$Bitmap", 827 "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" }; 828 const char *s; 829 830 if (i < 12) 831 s = ESTR[i]; 832 else if (i < 16) 833 s = "system file"; 834 else 835 s = "mft record"; 836 837 mrec = (MFT_RECORD*)(m + i * vol->mft_record_size); 838 if (mrec->flags & MFT_RECORD_IN_USE) { 839 if (ntfs_is_baad_recordp(mrec)) { 840 ntfs_log_debug("FAILED\n"); 841 ntfs_log_error("$MFT error: Incomplete multi " 842 "sector transfer detected in " 843 "'%s'.\n", s); 844 goto io_error_exit; 845 } 846 if (!ntfs_is_mft_recordp(mrec)) { 847 ntfs_log_debug("FAILED\n"); 848 ntfs_log_error("$MFT error: Invalid mft " 849 "record for '%s'.\n", s); 850 goto io_error_exit; 851 } 852 } 853 mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size); 854 if (mrec2->flags & MFT_RECORD_IN_USE) { 855 if (ntfs_is_baad_recordp(mrec2)) { 856 ntfs_log_debug("FAILED\n"); 857 ntfs_log_error("$MFTMirr error: Incomplete " 858 "multi sector transfer " 859 "detected in '%s'.\n", s); 860 goto io_error_exit; 861 } 862 if (!ntfs_is_mft_recordp(mrec2)) { 863 ntfs_log_debug("FAILED\n"); 864 ntfs_log_error("$MFTMirr error: Invalid mft " 865 "record for '%s'.\n", s); 866 goto io_error_exit; 867 } 868 } 869 if (memcmp(mrec, mrec2, ntfs_mft_record_get_data_size(mrec))) { 870 ntfs_log_debug(FAILED); 871 ntfs_log_error("$MFTMirr does not match $MFT (record " 872 "%d).\n", i); 873 goto io_error_exit; 874 } 875 } 876 ntfs_log_debug(OK); 877 878 free(m2); 879 free(m); 880 m = m2 = NULL; 881 882 /* Now load the bitmap from $Bitmap. */ 883 ntfs_log_debug("Loading $Bitmap... "); 884 vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap); 885 if (!vol->lcnbmp_ni) { 886 ntfs_log_debug(FAILED); 887 ntfs_log_perror("Failed to open inode"); 888 goto error_exit; 889 } 890 /* Get an ntfs attribute for $Bitmap/$DATA. */ 891 vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); 892 if (!vol->lcnbmp_na) { 893 ntfs_log_debug(FAILED); 894 ntfs_log_perror("Failed to open ntfs attribute"); 895 goto error_exit; 896 } 897 /* Done with the $Bitmap mft record. */ 898 ntfs_log_debug(OK); 899 900 /* Now load the upcase table from $UpCase. */ 901 ntfs_log_debug("Loading $UpCase... "); 902 ni = ntfs_inode_open(vol, FILE_UpCase); 903 if (!ni) { 904 ntfs_log_debug(FAILED); 905 ntfs_log_perror("Failed to open inode"); 906 goto error_exit; 907 } 908 /* Get an ntfs attribute for $UpCase/$DATA. */ 909 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 910 if (!na) { 911 ntfs_log_debug(FAILED); 912 ntfs_log_perror("Failed to open ntfs attribute"); 913 goto error_exit; 914 } 915 /* 916 * Note: Normally, the upcase table has a length equal to 65536 917 * 2-byte Unicode characters but allow for different cases, so no 918 * checks done. Just check we don't overflow 32-bits worth of Unicode 919 * characters. 920 */ 921 if (na->data_size & ~0x1ffffffffULL) { 922 ntfs_log_debug(FAILED); 923 ntfs_log_error("Error: Upcase table is too big (max 32-bit " 924 "allowed).\n"); 925 errno = EINVAL; 926 goto error_exit; 927 } 928 if (vol->upcase_len != na->data_size >> 1) { 929 vol->upcase_len = na->data_size >> 1; 930 /* Throw away default table. */ 931 free(vol->upcase); 932 vol->upcase = ntfs_malloc(na->data_size); 933 if (!vol->upcase) { 934 ntfs_log_debug(FAILED); 935 goto error_exit; 936 } 937 } 938 /* Read in the $DATA attribute value into the buffer. */ 939 l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase); 940 if (l != na->data_size) { 941 ntfs_log_debug(FAILED); 942 ntfs_log_error("Failed to read $UpCase, unexpected length " 943 "(%lld != %lld).\n", (long long)l, 944 (long long)na->data_size); 945 errno = EIO; 946 goto error_exit; 947 } 948 /* Done with the $UpCase mft record. */ 949 ntfs_log_debug(OK); 950 ntfs_attr_close(na); 951 if (ntfs_inode_close(ni)) { 952 ntfs_log_perror("Failed to close $UpCase"); 953 goto error_exit; 954 } 955 956 /* 957 * Now load $Volume and set the version information and flags in the 958 * vol structure accordingly. 959 */ 960 ntfs_log_debug("Loading $Volume... "); 961 vol->vol_ni = ntfs_inode_open(vol, FILE_Volume); 962 if (!vol->vol_ni) { 963 ntfs_log_debug(FAILED); 964 ntfs_log_perror("Failed to open inode"); 965 goto error_exit; 966 } 967 /* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */ 968 ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); 969 if (!ctx) { 970 ntfs_log_debug(FAILED); 971 ntfs_log_perror("Failed to allocate attribute search context"); 972 goto error_exit; 973 } 974 /* Find the $VOLUME_INFORMATION attribute. */ 975 if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, 976 0, ctx)) { 977 ntfs_log_debug(FAILED); 978 ntfs_log_perror("$VOLUME_INFORMATION attribute not found in " 979 "$Volume"); 980 goto error_exit; 981 } 982 a = ctx->attr; 983 /* Has to be resident. */ 984 if (a->non_resident) { 985 ntfs_log_debug(FAILED); 986 ntfs_log_error("Attribute $VOLUME_INFORMATION must be " 987 "resident but it isn't.\n"); 988 errno = EIO; 989 goto error_exit; 990 } 991 /* Get a pointer to the value of the attribute. */ 992 vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a); 993 /* Sanity checks. */ 994 if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec + 995 le32_to_cpu(ctx->mrec->bytes_in_use) || 996 le16_to_cpu(a->value_offset) + le32_to_cpu( 997 a->value_length) > le32_to_cpu(a->length)) { 998 ntfs_log_debug(FAILED); 999 ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n"); 1000 errno = EIO; 1001 goto error_exit; 1002 } 1003 /* Setup vol from the volume information attribute value. */ 1004 vol->major_ver = vinf->major_ver; 1005 vol->minor_ver = vinf->minor_ver; 1006 /* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are 1007 defined using cpu_to_le16() macro and hence are consistent. */ 1008 vol->flags = vinf->flags; 1009 /* 1010 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup. 1011 */ 1012 ntfs_attr_reinit_search_ctx(ctx); 1013 if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, 1014 ctx)) { 1015 if (errno != ENOENT) { 1016 ntfs_log_debug(FAILED); 1017 ntfs_log_perror("Failed to lookup of $VOLUME_NAME in " 1018 "$Volume failed"); 1019 goto error_exit; 1020 } 1021 /* 1022 * Attribute not present. This has been seen in the field. 1023 * Treat this the same way as if the attribute was present but 1024 * had zero length. 1025 */ 1026 vol->vol_name = ntfs_malloc(1); 1027 if (!vol->vol_name) { 1028 ntfs_log_debug(FAILED); 1029 goto error_exit; 1030 } 1031 vol->vol_name[0] = '\0'; 1032 } else { 1033 a = ctx->attr; 1034 /* Has to be resident. */ 1035 if (a->non_resident) { 1036 ntfs_log_debug(FAILED); 1037 ntfs_log_error("$VOLUME_NAME must be resident.\n"); 1038 errno = EIO; 1039 goto error_exit; 1040 } 1041 /* Get a pointer to the value of the attribute. */ 1042 vname = (ntfschar*)(le16_to_cpu(a->value_offset) + (char*)a); 1043 u = le32_to_cpu(a->value_length) / 2; 1044 /* 1045 * Convert Unicode volume name to current locale multibyte 1046 * format. 1047 */ 1048 vol->vol_name = NULL; 1049 if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) { 1050 ntfs_log_perror("Volume name could not be converted " 1051 "to current locale"); 1052 ntfs_log_debug("Forcing name into ASCII by replacing " 1053 "non-ASCII characters with underscores.\n"); 1054 vol->vol_name = ntfs_malloc(u + 1); 1055 if (!vol->vol_name) { 1056 ntfs_log_debug(FAILED); 1057 goto error_exit; 1058 } 1059 for (j = 0; j < (s32)u; j++) { 1060 ntfschar uc = le16_to_cpu(vname[j]); 1061 if (uc > 0xff) 1062 uc = (ntfschar)'_'; 1063 vol->vol_name[j] = (char)uc; 1064 } 1065 vol->vol_name[u] = '\0'; 1066 } 1067 } 1068 ntfs_log_debug(OK); 1069 ntfs_attr_put_search_ctx(ctx); 1070 ctx = NULL; 1071 /* Now load the attribute definitions from $AttrDef. */ 1072 ntfs_log_debug("Loading $AttrDef... "); 1073 ni = ntfs_inode_open(vol, FILE_AttrDef); 1074 if (!ni) { 1075 ntfs_log_debug(FAILED); 1076 ntfs_log_perror("Failed to open $AttrDef"); 1077 goto error_exit; 1078 } 1079 /* Get an ntfs attribute for $AttrDef/$DATA. */ 1080 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 1081 if (!na) { 1082 ntfs_log_debug(FAILED); 1083 ntfs_log_perror("Failed to open ntfs attribute"); 1084 goto error_exit; 1085 } 1086 /* Check we don't overflow 32-bits. */ 1087 if (na->data_size > 0xffffffffLL) { 1088 ntfs_log_debug(FAILED); 1089 ntfs_log_error("Attribute definition table is too big (max " 1090 "32-bit allowed).\n"); 1091 errno = EINVAL; 1092 goto error_exit; 1093 } 1094 vol->attrdef_len = na->data_size; 1095 vol->attrdef = ntfs_malloc(na->data_size); 1096 if (!vol->attrdef) { 1097 ntfs_log_debug(FAILED); 1098 goto error_exit; 1099 } 1100 /* Read in the $DATA attribute value into the buffer. */ 1101 l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef); 1102 if (l != na->data_size) { 1103 ntfs_log_debug(FAILED); 1104 ntfs_log_error("Failed to read $AttrDef, unexpected length " 1105 "(%lld != %lld).\n", (long long)l, 1106 (long long)na->data_size); 1107 errno = EIO; 1108 goto error_exit; 1109 } 1110 /* Done with the $AttrDef mft record. */ 1111 ntfs_log_debug(OK); 1112 ntfs_attr_close(na); 1113 if (ntfs_inode_close(ni)) { 1114 ntfs_log_perror("Failed to close $AttrDef"); 1115 goto error_exit; 1116 } 1117 /* 1118 * Check for dirty logfile and hibernated Windows. 1119 * We care only about read-write mounts. 1120 */ 1121 if (!(flags & MS_RDONLY)) { 1122 if (ntfs_volume_check_hiberfile(vol) < 0) 1123 goto error_exit; 1124 if (ntfs_volume_check_logfile(vol) < 0) { 1125 if (!(flags & MS_FORCE)) 1126 goto error_exit; 1127 ntfs_log_info("WARNING: Forced mount, reset $LogFile.\n"); 1128 if (ntfs_logfile_reset(vol)) 1129 goto error_exit; 1130 } 1131 } 1132 1133 return vol; 1134 io_error_exit: 1135 errno = EIO; 1136 error_exit: 1137 eo = errno; 1138 if (ctx) 1139 ntfs_attr_put_search_ctx(ctx); 1140 free(m); 1141 free(m2); 1142 __ntfs_volume_release(vol); 1143 errno = eo; 1144 return NULL; 1145 } 1146 1147 /** 1148 * ntfs_mount - open ntfs volume 1149 * @name: name of device/file to open 1150 * @flags: optional mount flags 1151 * 1152 * This function mounts an ntfs volume. @name should contain the name of the 1153 * device/file to mount as the ntfs volume. 1154 * 1155 * @flags is an optional second parameter. The same flags are used as for 1156 * the mount system call (man 2 mount). Currently only the following flags 1157 * are implemented: 1158 * MS_RDONLY - mount volume read-only 1159 * MS_NOATIME - do not update access time 1160 * 1161 * The function opens the device or file @name and verifies that it contains a 1162 * valid bootsector. Then, it allocates an ntfs_volume structure and initializes 1163 * some of the values inside the structure from the information stored in the 1164 * bootsector. It proceeds to load the necessary system files and completes 1165 * setting up the structure. 1166 * 1167 * Return the allocated volume structure on success and NULL on error with 1168 * errno set to the error code. 1169 * 1170 * Note, that a copy is made of @name, and hence it can be discarded as 1171 * soon as the function returns. 1172 */ 1173 ntfs_volume *ntfs_mount(const char *name __attribute__((unused)), 1174 unsigned long flags __attribute__((unused))) 1175 { 1176 #ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS 1177 struct ntfs_device *dev; 1178 ntfs_volume *vol; 1179 1180 /* Allocate an ntfs_device structure. */ 1181 dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL); 1182 if (!dev) 1183 return NULL; 1184 /* Call ntfs_device_mount() to do the actual mount. */ 1185 vol = ntfs_device_mount(dev, flags); 1186 if (!vol) { 1187 int eo = errno; 1188 ntfs_device_free(dev); 1189 errno = eo; 1190 } 1191 return vol; 1192 #else 1193 /* 1194 * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is 1195 * defined as there are no device operations available in libntfs in 1196 * this case. 1197 */ 1198 errno = EOPNOTSUPP; 1199 return NULL; 1200 #endif 1201 } 1202 1203 /** 1204 * ntfs_umount - close ntfs volume 1205 * @vol: address of ntfs_volume structure of volume to close 1206 * @force: if true force close the volume even if it is busy 1207 * 1208 * Deallocate all structures (including @vol itself) associated with the ntfs 1209 * volume @vol. 1210 * 1211 * Return 0 on success. On error return -1 with errno set appropriately 1212 * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that 1213 * an operation is in progress and if you try the close later the operation 1214 * might be completed and the close succeed. 1215 * 1216 * If @force is true (i.e. not zero) this function will close the volume even 1217 * if this means that data might be lost. 1218 * 1219 * @vol must have previously been returned by a call to ntfs_mount(). 1220 * 1221 * @vol itself is deallocated and should no longer be dereferenced after this 1222 * function returns success. If it returns an error then nothing has been done 1223 * so it is safe to continue using @vol. 1224 */ 1225 int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused))) 1226 { 1227 struct ntfs_device *dev; 1228 int ret; 1229 1230 if (!vol) { 1231 errno = EINVAL; 1232 return -1; 1233 } 1234 dev = vol->dev; 1235 ret = __ntfs_volume_release(vol); 1236 ntfs_device_free(dev); 1237 return ret; 1238 } 1239 1240 #ifdef HAVE_MNTENT_H 1241 1242 #ifndef HAVE_REALPATH 1243 /** 1244 * realpath - If there is no realpath on the system 1245 */ 1246 static char *realpath(const char *path, char *resolved_path) 1247 { 1248 strncpy(resolved_path, path, PATH_MAX); 1249 resolved_path[PATH_MAX] = '\0'; 1250 return resolved_path; 1251 } 1252 #endif 1253 1254 /** 1255 * ntfs_mntent_check - desc 1256 * 1257 * If you are wanting to use this, you actually wanted to use 1258 * ntfs_check_if_mounted(), you just didn't realize. (-: 1259 * 1260 * See description of ntfs_check_if_mounted(), below. 1261 */ 1262 static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags) 1263 { 1264 struct mntent *mnt; 1265 char *real_file = NULL, *real_fsname = NULL; 1266 FILE *f; 1267 int err = 0; 1268 1269 real_file = ntfs_malloc(PATH_MAX + 1); 1270 if (!real_file) 1271 return -1; 1272 real_fsname = ntfs_malloc(PATH_MAX + 1); 1273 if (!real_fsname) { 1274 err = errno; 1275 goto exit; 1276 } 1277 if (!realpath(file, real_file)) { 1278 err = errno; 1279 goto exit; 1280 } 1281 if (!(f = setmntent(MOUNTED, "r"))) { 1282 err = errno; 1283 goto exit; 1284 } 1285 while ((mnt = getmntent(f))) { 1286 if (!realpath(mnt->mnt_fsname, real_fsname)) 1287 continue; 1288 if (!strcmp(real_file, real_fsname)) 1289 break; 1290 } 1291 endmntent(f); 1292 if (!mnt) 1293 goto exit; 1294 *mnt_flags = NTFS_MF_MOUNTED; 1295 if (!strcmp(mnt->mnt_dir, "/")) 1296 *mnt_flags |= NTFS_MF_ISROOT; 1297 #ifdef HAVE_HASMNTOPT 1298 if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw")) 1299 *mnt_flags |= NTFS_MF_READONLY; 1300 #endif 1301 exit: 1302 free(real_file); 1303 free(real_fsname); 1304 if (err) { 1305 errno = err; 1306 return -1; 1307 } 1308 return 0; 1309 } 1310 #endif /* HAVE_MNTENT_H */ 1311 1312 /** 1313 * ntfs_check_if_mounted - check if an ntfs volume is currently mounted 1314 * @file: device file to check 1315 * @mnt_flags: pointer into which to return the ntfs mount flags (see volume.h) 1316 * 1317 * If the running system does not support the {set,get,end}mntent() calls, 1318 * just return 0 and set *@mnt_flags to zero. 1319 * 1320 * When the system does support the calls, ntfs_check_if_mounted() first tries 1321 * to find the device @file in /etc/mtab (or wherever this is kept on the 1322 * running system). If it is not found, assume the device is not mounted and 1323 * return 0 and set *@mnt_flags to zero. 1324 * 1325 * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags. 1326 * 1327 * Further if @file is mounted as the file system root ("/"), set the flag 1328 * NTFS_MF_ISROOT in *@mnt_flags. 1329 * 1330 * Finally, check if the file system is mounted read-only, and if so set the 1331 * NTFS_MF_READONLY flag in *@mnt_flags. 1332 * 1333 * On success return 0 with *@mnt_flags set to the ntfs mount flags. 1334 * 1335 * On error return -1 with errno set to the error code. 1336 */ 1337 int ntfs_check_if_mounted(const char *file __attribute__((unused)), 1338 unsigned long *mnt_flags) 1339 { 1340 *mnt_flags = 0; 1341 #ifdef HAVE_MNTENT_H 1342 return ntfs_mntent_check(file, mnt_flags); 1343 #else 1344 return 0; 1345 #endif 1346 } 1347 1348 /** 1349 * ntfs_version_is_supported - check if NTFS version is supported. 1350 * @vol: ntfs volume whose version we're interested in. 1351 * 1352 * The function checks if the NTFS volume version is known or not. 1353 * Version 1.1 and 1.2 are used by Windows NT3.x and NT4. 1354 * Version 2.x is used by Windows 2000 Betas. 1355 * Version 3.0 is used by Windows 2000. 1356 * Version 3.1 is used by Windows XP, Windows Server 2003 and Longhorn. 1357 * 1358 * Return 0 if NTFS version is supported otherwise -1 with errno set. 1359 * 1360 * The following error codes are defined: 1361 * EOPNOTSUPP - Unknown NTFS version 1362 * EINVAL - Invalid argument 1363 */ 1364 int ntfs_version_is_supported(ntfs_volume *vol) 1365 { 1366 u8 major, minor; 1367 1368 if (!vol) { 1369 errno = EINVAL; 1370 return -1; 1371 } 1372 1373 major = vol->major_ver; 1374 minor = vol->minor_ver; 1375 1376 if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor)) 1377 return 0; 1378 1379 if (NTFS_V2_X(major, minor)) 1380 return 0; 1381 1382 if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor)) 1383 return 0; 1384 1385 errno = EOPNOTSUPP; 1386 return -1; 1387 } 1388 1389 /** 1390 * ntfs_logfile_reset - "empty" $LogFile data attribute value 1391 * @vol: ntfs volume whose $LogFile we intend to reset. 1392 * 1393 * Fill the value of the $LogFile data attribute, i.e. the contents of 1394 * the file, with 0xff's, thus marking the journal as empty. 1395 * 1396 * FIXME(?): We might need to zero the LSN field of every single mft 1397 * record as well. (But, first try without doing that and see what 1398 * happens, since chkdsk might pickup the pieces and do it for us...) 1399 * 1400 * On success return 0. 1401 * 1402 * On error return -1 with errno set to the error code. 1403 */ 1404 int ntfs_logfile_reset(ntfs_volume *vol) 1405 { 1406 ntfs_inode *ni; 1407 ntfs_attr *na; 1408 int eo; 1409 1410 if (!vol) { 1411 errno = EINVAL; 1412 return -1; 1413 } 1414 1415 ni = ntfs_inode_open(vol, FILE_LogFile); 1416 if (!ni) { 1417 ntfs_log_perror("Failed to open inode FILE_LogFile"); 1418 return -1; 1419 } 1420 1421 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); 1422 if (!na) { 1423 eo = errno; 1424 ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); 1425 goto error_exit; 1426 } 1427 1428 if (ntfs_empty_logfile(na)) { 1429 eo = errno; 1430 ntfs_attr_close(na); 1431 goto error_exit; 1432 } 1433 1434 ntfs_attr_close(na); 1435 return ntfs_inode_close(ni); 1436 1437 error_exit: 1438 ntfs_inode_close(ni); 1439 errno = eo; 1440 return -1; 1441 } 1442 1443 /** 1444 * ntfs_volume_write_flags - set the flags of an ntfs volume 1445 * @vol: ntfs volume where we set the volume flags 1446 * @flags: new flags 1447 * 1448 * Set the on-disk volume flags in the mft record of $Volume and 1449 * on volume @vol to @flags. 1450 * 1451 * Return 0 if successful and -1 if not with errno set to the error code. 1452 */ 1453 int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags) 1454 { 1455 ATTR_RECORD *a; 1456 VOLUME_INFORMATION *c; 1457 ntfs_attr_search_ctx *ctx; 1458 int ret = -1; /* failure */ 1459 1460 if (!vol || !vol->vol_ni) { 1461 errno = EINVAL; 1462 return -1; 1463 } 1464 /* Get a pointer to the volume information attribute. */ 1465 ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL); 1466 if (!ctx) { 1467 ntfs_log_perror("Failed to allocate attribute search context"); 1468 return -1; 1469 } 1470 if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, 1471 0, ctx)) { 1472 ntfs_log_error("Attribute $VOLUME_INFORMATION was not found " 1473 "in $Volume!\n"); 1474 goto err_out; 1475 } 1476 a = ctx->attr; 1477 /* Sanity check. */ 1478 if (a->non_resident) { 1479 ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident " 1480 "but it isn't.\n"); 1481 errno = EIO; 1482 goto err_out; 1483 } 1484 /* Get a pointer to the value of the attribute. */ 1485 c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a); 1486 /* Sanity checks. */ 1487 if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec + 1488 le32_to_cpu(ctx->mrec->bytes_in_use) || 1489 le16_to_cpu(a->value_offset) + 1490 le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) { 1491 ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is " 1492 "corrupt!\n"); 1493 errno = EIO; 1494 goto err_out; 1495 } 1496 /* Set the volume flags. */ 1497 vol->flags = c->flags = flags & VOLUME_FLAGS_MASK; 1498 /* Write them to disk. */ 1499 ntfs_inode_mark_dirty(vol->vol_ni); 1500 if (ntfs_inode_sync(vol->vol_ni)) { 1501 ntfs_log_perror("Error writing $Volume"); 1502 goto err_out; 1503 } 1504 ret = 0; /* success */ 1505 err_out: 1506 ntfs_attr_put_search_ctx(ctx); 1507 return ret; 1508 } 1509 1510