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