Fixed a constant string concatenation
[ntfs-3g.git] / libntfs-3g / volume.c
blob7a1bcf2931ebfd83d871173a442731cd4ffd1304
1 /**
2 * volume.c - NTFS volume handling code. Originated from the Linux-NTFS project.
4 * Copyright (c) 2000-2006 Anton Altaparmakov
5 * Copyright (c) 2002-2009 Szabolcs Szakacsits
6 * Copyright (c) 2004-2005 Richard Russon
7 * Copyright (c) 2010 Jean-Pierre Andre
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.
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.
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
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_STDIO_H
33 #include <stdio.h>
34 #endif
35 #ifdef HAVE_STRING_H
36 #include <string.h>
37 #endif
38 #ifdef HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41 #ifdef HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 #ifdef HAVE_ERRNO_H
45 #include <errno.h>
46 #endif
47 #ifdef HAVE_SYS_STAT_H
48 #include <sys/stat.h>
49 #endif
50 #ifdef HAVE_LIMITS_H
51 #include <limits.h>
52 #endif
53 #ifdef HAVE_LOCALE_H
54 #include <locale.h>
55 #endif
57 #if defined(__sun) && defined (__SVR4)
58 #include <sys/mnttab.h>
59 #endif
61 #include "param.h"
62 #include "compat.h"
63 #include "volume.h"
64 #include "attrib.h"
65 #include "mft.h"
66 #include "bootsect.h"
67 #include "device.h"
68 #include "debug.h"
69 #include "inode.h"
70 #include "runlist.h"
71 #include "logfile.h"
72 #include "dir.h"
73 #include "logging.h"
74 #include "cache.h"
75 #include "realpath.h"
76 #include "misc.h"
77 #include "security.h"
79 const char *ntfs_home =
80 "News, support and information: http://tuxera.com\n";
82 static const char *invalid_ntfs_msg =
83 "The device '%s' doesn't seem to have a valid NTFS.\n"
84 "Maybe the wrong device is used? Or the whole disk instead of a\n"
85 "partition (e.g. /dev/sda, not /dev/sda1)? Or the other way around?\n";
87 static const char *corrupt_volume_msg =
88 "NTFS is either inconsistent, or there is a hardware fault, or it's a\n"
89 "SoftRAID/FakeRAID hardware. In the first case run chkdsk /f on Windows\n"
90 "then reboot into Windows twice. The usage of the /f parameter is very\n"
91 "important! If the device is a SoftRAID/FakeRAID then first activate\n"
92 "it and mount a different device under the /dev/mapper/ directory, (e.g.\n"
93 "/dev/mapper/nvidia_eahaabcc1). Please see the 'dmraid' documentation\n"
94 "for more details.\n";
96 static const char *hibernated_volume_msg =
97 "The NTFS partition is in an unsafe state. Please resume and shutdown\n"
98 "Windows fully (no hibernation or fast restarting), or mount the volume\n"
99 "read-only with the 'ro' mount option.\n";
101 static const char *fallback_readonly_msg =
102 "Falling back to read-only mount because the NTFS partition is in an\n"
103 "unsafe state. Please resume and shutdown Windows fully (no hibernation\n"
104 "or fast restarting.)\n";
106 static const char *unclean_journal_msg =
107 "Write access is denied because the disk wasn't safely powered\n"
108 "off and the 'norecover' mount option was specified.\n";
110 static const char *opened_volume_msg =
111 "Mount is denied because the NTFS volume is already exclusively opened.\n"
112 "The volume may be already mounted, or another software may use it which\n"
113 "could be identified for example by the help of the 'fuser' command.\n";
115 static const char *fakeraid_msg =
116 "Either the device is missing or it's powered down, or you have\n"
117 "SoftRAID hardware and must use an activated, different device under\n"
118 "/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
119 "Please see the 'dmraid' documentation for help.\n";
121 static const char *access_denied_msg =
122 "Please check '%s' and the ntfs-3g binary permissions,\n"
123 "and the mounting user ID. More explanation is provided at\n"
124 "http://tuxera.com/community/ntfs-3g-faq/#unprivileged\n";
127 * ntfs_volume_alloc - Create an NTFS volume object and initialise it
129 * Description...
131 * Returns:
133 ntfs_volume *ntfs_volume_alloc(void)
135 return ntfs_calloc(sizeof(ntfs_volume));
138 static void ntfs_attr_free(ntfs_attr **na)
140 if (na && *na) {
141 ntfs_attr_close(*na);
142 *na = NULL;
146 static int ntfs_inode_free(ntfs_inode **ni)
148 int ret = -1;
150 if (ni && *ni) {
151 ret = ntfs_inode_close(*ni);
152 *ni = NULL;
155 return ret;
158 static void ntfs_error_set(int *err)
160 if (!*err)
161 *err = errno;
165 * __ntfs_volume_release - Destroy an NTFS volume object
166 * @v:
168 * Description...
170 * Returns:
172 static int __ntfs_volume_release(ntfs_volume *v)
174 int err = 0;
176 if (ntfs_close_secure(v))
177 ntfs_error_set(&err);
179 if (ntfs_inode_free(&v->vol_ni))
180 ntfs_error_set(&err);
182 * FIXME: Inodes must be synced before closing
183 * attributes, otherwise unmount could fail.
185 if (v->lcnbmp_ni && NInoDirty(v->lcnbmp_ni))
186 ntfs_inode_sync(v->lcnbmp_ni);
187 ntfs_attr_free(&v->lcnbmp_na);
188 if (ntfs_inode_free(&v->lcnbmp_ni))
189 ntfs_error_set(&err);
191 if (v->mft_ni && NInoDirty(v->mft_ni))
192 ntfs_inode_sync(v->mft_ni);
193 ntfs_attr_free(&v->mftbmp_na);
194 ntfs_attr_free(&v->mft_na);
195 if (ntfs_inode_free(&v->mft_ni))
196 ntfs_error_set(&err);
198 if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni))
199 ntfs_inode_sync(v->mftmirr_ni);
200 ntfs_attr_free(&v->mftmirr_na);
201 if (ntfs_inode_free(&v->mftmirr_ni))
202 ntfs_error_set(&err);
204 if (v->dev) {
205 struct ntfs_device *dev = v->dev;
207 if (dev->d_ops->sync(dev))
208 ntfs_error_set(&err);
209 if (dev->d_ops->close(dev))
210 ntfs_error_set(&err);
213 ntfs_free_lru_caches(v);
214 free(v->vol_name);
215 free(v->upcase);
216 if (v->locase) free(v->locase);
217 free(v->attrdef);
218 free(v);
220 errno = err;
221 return errno ? -1 : 0;
224 static void ntfs_attr_setup_flag(ntfs_inode *ni)
226 STANDARD_INFORMATION *si;
228 si = ntfs_attr_readall(ni, AT_STANDARD_INFORMATION, AT_UNNAMED, 0, NULL);
229 if (si) {
230 ni->flags = si->file_attributes;
231 free(si);
236 * ntfs_mft_load - load the $MFT and setup the ntfs volume with it
237 * @vol: ntfs volume whose $MFT to load
239 * Load $MFT from @vol and setup @vol with it. After calling this function the
240 * volume @vol is ready for use by all read access functions provided by the
241 * ntfs library.
243 * Return 0 on success and -1 on error with errno set to the error code.
245 static int ntfs_mft_load(ntfs_volume *vol)
247 VCN next_vcn, last_vcn, highest_vcn;
248 s64 l;
249 MFT_RECORD *mb = NULL;
250 ntfs_attr_search_ctx *ctx = NULL;
251 ATTR_RECORD *a;
252 int eo;
254 /* Manually setup an ntfs_inode. */
255 vol->mft_ni = ntfs_inode_allocate(vol);
256 mb = ntfs_malloc(vol->mft_record_size);
257 if (!vol->mft_ni || !mb) {
258 ntfs_log_perror("Error allocating memory for $MFT");
259 goto error_exit;
261 vol->mft_ni->mft_no = 0;
262 vol->mft_ni->mrec = mb;
263 /* Can't use any of the higher level functions yet! */
264 l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1,
265 vol->mft_record_size, mb);
266 if (l != 1) {
267 if (l != -1)
268 errno = EIO;
269 ntfs_log_perror("Error reading $MFT");
270 goto error_exit;
273 if (ntfs_mft_record_check(vol, 0, mb))
274 goto error_exit;
276 ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
277 if (!ctx)
278 goto error_exit;
280 /* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */
281 if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
282 ctx)) {
283 if (errno != ENOENT) {
284 ntfs_log_error("$MFT has corrupt attribute list.\n");
285 goto io_error_exit;
287 goto mft_has_no_attr_list;
289 NInoSetAttrList(vol->mft_ni);
290 l = ntfs_get_attribute_value_length(ctx->attr);
291 if (l <= 0 || l > 0x40000) {
292 ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n",
293 (long long)l);
294 goto io_error_exit;
296 vol->mft_ni->attr_list_size = l;
297 vol->mft_ni->attr_list = ntfs_malloc(l);
298 if (!vol->mft_ni->attr_list)
299 goto error_exit;
301 l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
302 if (!l) {
303 ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
304 goto io_error_exit;
306 if (l != vol->mft_ni->attr_list_size) {
307 ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
308 "%u).\n", (long long)l,
309 vol->mft_ni->attr_list_size);
310 goto io_error_exit;
313 mft_has_no_attr_list:
315 ntfs_attr_setup_flag(vol->mft_ni);
317 /* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
319 /* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
320 vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
321 if (!vol->mft_na) {
322 ntfs_log_perror("Failed to open ntfs attribute");
323 goto error_exit;
325 /* Read all extents from the $DATA attribute in $MFT. */
326 ntfs_attr_reinit_search_ctx(ctx);
327 last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits;
328 highest_vcn = next_vcn = 0;
329 a = NULL;
330 while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0,
331 ctx)) {
332 runlist_element *nrl;
334 a = ctx->attr;
335 /* $MFT must be non-resident. */
336 if (!a->non_resident) {
337 ntfs_log_error("$MFT must be non-resident.\n");
338 goto io_error_exit;
340 /* $MFT must be uncompressed and unencrypted. */
341 if (a->flags & ATTR_COMPRESSION_MASK ||
342 a->flags & ATTR_IS_ENCRYPTED) {
343 ntfs_log_error("$MFT must be uncompressed and "
344 "unencrypted.\n");
345 goto io_error_exit;
348 * Decompress the mapping pairs array of this extent and merge
349 * the result into the existing runlist. No need for locking
350 * as we have exclusive access to the inode at this time and we
351 * are a mount in progress task, too.
353 nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl);
354 if (!nrl) {
355 ntfs_log_perror("ntfs_mapping_pairs_decompress() failed");
356 goto error_exit;
358 vol->mft_na->rl = nrl;
360 /* Get the lowest vcn for the next extent. */
361 highest_vcn = sle64_to_cpu(a->highest_vcn);
362 next_vcn = highest_vcn + 1;
364 /* Only one extent or error, which we catch below. */
365 if (next_vcn <= 0)
366 break;
368 /* Avoid endless loops due to corruption. */
369 if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
370 ntfs_log_error("$MFT has corrupt attribute list.\n");
371 goto io_error_exit;
374 if (!a) {
375 ntfs_log_error("$MFT/$DATA attribute not found.\n");
376 goto io_error_exit;
378 if (highest_vcn && highest_vcn != last_vcn - 1) {
379 ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n");
380 ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n",
381 (long long)highest_vcn, (long long)last_vcn - 1);
382 goto io_error_exit;
384 /* Done with the $Mft mft record. */
385 ntfs_attr_put_search_ctx(ctx);
386 ctx = NULL;
388 /* Update the size fields in the inode. */
389 vol->mft_ni->data_size = vol->mft_na->data_size;
390 vol->mft_ni->allocated_size = vol->mft_na->allocated_size;
391 set_nino_flag(vol->mft_ni, KnownSize);
394 * The volume is now setup so we can use all read access functions.
396 vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
397 if (!vol->mftbmp_na) {
398 ntfs_log_perror("Failed to open $MFT/$BITMAP");
399 goto error_exit;
401 return 0;
402 io_error_exit:
403 errno = EIO;
404 error_exit:
405 eo = errno;
406 if (ctx)
407 ntfs_attr_put_search_ctx(ctx);
408 if (vol->mft_na) {
409 ntfs_attr_close(vol->mft_na);
410 vol->mft_na = NULL;
412 if (vol->mft_ni) {
413 ntfs_inode_close(vol->mft_ni);
414 vol->mft_ni = NULL;
416 errno = eo;
417 return -1;
421 * ntfs_mftmirr_load - load the $MFTMirr and setup the ntfs volume with it
422 * @vol: ntfs volume whose $MFTMirr to load
424 * Load $MFTMirr from @vol and setup @vol with it. After calling this function
425 * the volume @vol is ready for use by all write access functions provided by
426 * the ntfs library (assuming ntfs_mft_load() has been called successfully
427 * beforehand).
429 * Return 0 on success and -1 on error with errno set to the error code.
431 static int ntfs_mftmirr_load(ntfs_volume *vol)
433 int err;
435 vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr);
436 if (!vol->mftmirr_ni) {
437 ntfs_log_perror("Failed to open inode $MFTMirr");
438 return -1;
441 vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
442 if (!vol->mftmirr_na) {
443 ntfs_log_perror("Failed to open $MFTMirr/$DATA");
444 goto error_exit;
447 if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
448 ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
449 goto error_exit;
452 return 0;
454 error_exit:
455 err = errno;
456 if (vol->mftmirr_na) {
457 ntfs_attr_close(vol->mftmirr_na);
458 vol->mftmirr_na = NULL;
460 ntfs_inode_close(vol->mftmirr_ni);
461 vol->mftmirr_ni = NULL;
462 errno = err;
463 return -1;
467 * ntfs_volume_startup - allocate and setup an ntfs volume
468 * @dev: device to open
469 * @flags: optional mount flags
471 * Load, verify, and parse bootsector; load and setup $MFT and $MFTMirr. After
472 * calling this function, the volume is setup sufficiently to call all read
473 * and write access functions provided by the library.
475 * Return the allocated volume structure on success and NULL on error with
476 * errno set to the error code.
478 ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
479 ntfs_mount_flags flags)
481 LCN mft_zone_size, mft_lcn;
482 s64 br;
483 ntfs_volume *vol;
484 NTFS_BOOT_SECTOR *bs;
485 int eo;
487 if (!dev || !dev->d_ops || !dev->d_name) {
488 errno = EINVAL;
489 ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
490 return NULL;
493 bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
494 if (!bs)
495 return NULL;
497 /* Allocate the volume structure. */
498 vol = ntfs_volume_alloc();
499 if (!vol)
500 goto error_exit;
502 /* Create the default upcase table. */
503 vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
504 if (!vol->upcase_len || !vol->upcase)
505 goto error_exit;
507 /* Default with no locase table and case sensitive file names */
508 vol->locase = (ntfschar*)NULL;
509 NVolSetCaseSensitive(vol);
511 /* by default, all files are shown and not marked hidden */
512 NVolSetShowSysFiles(vol);
513 NVolSetShowHidFiles(vol);
514 NVolClearHideDotFiles(vol);
515 /* set default compression */
516 #if DEFAULT_COMPRESSION
517 NVolSetCompression(vol);
518 #else
519 NVolClearCompression(vol);
520 #endif
521 if (flags & NTFS_MNT_RDONLY)
522 NVolSetReadOnly(vol);
524 /* ...->open needs bracketing to compile with glibc 2.7 */
525 if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
526 if (!NVolReadOnly(vol) && (errno == EROFS)) {
527 if ((dev->d_ops->open)(dev, O_RDONLY)) {
528 ntfs_log_perror("Error opening read-only '%s'",
529 dev->d_name);
530 goto error_exit;
531 } else {
532 ntfs_log_info("Error opening '%s' read-write\n",
533 dev->d_name);
534 NVolSetReadOnly(vol);
536 } else {
537 ntfs_log_perror("Error opening '%s'", dev->d_name);
538 goto error_exit;
541 /* Attach the device to the volume. */
542 vol->dev = dev;
544 /* Now read the bootsector. */
545 br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
546 if (br != sizeof(NTFS_BOOT_SECTOR)) {
547 if (br != -1)
548 errno = EINVAL;
549 if (!br)
550 ntfs_log_error("Failed to read bootsector (size=0)\n");
551 else
552 ntfs_log_perror("Error reading bootsector");
553 goto error_exit;
555 if (!ntfs_boot_sector_is_ntfs(bs)) {
556 errno = EINVAL;
557 goto error_exit;
559 if (ntfs_boot_sector_parse(vol, bs) < 0)
560 goto error_exit;
562 free(bs);
563 bs = NULL;
564 /* Now set the device block size to the sector size. */
565 if (ntfs_device_block_size_set(vol->dev, vol->sector_size))
566 ntfs_log_debug("Failed to set the device block size to the "
567 "sector size. This may affect performance "
568 "but should be harmless otherwise. Error: "
569 "%s\n", strerror(errno));
571 /* We now initialize the cluster allocator. */
572 vol->full_zones = 0;
573 mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */
575 /* Setup the mft zone. */
576 vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
577 ntfs_log_debug("mft_zone_pos = 0x%llx\n", (long long)vol->mft_zone_pos);
580 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
581 * source) and if the actual mft_lcn is in the expected place or even
582 * further to the front of the volume, extend the mft_zone to cover the
583 * beginning of the volume as well. This is in order to protect the
584 * area reserved for the mft bitmap as well within the mft_zone itself.
585 * On non-standard volumes we don't protect it as the overhead would be
586 * higher than the speed increase we would get by doing it.
588 mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
589 if (mft_lcn * vol->cluster_size < 16 * 1024)
590 mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
591 vol->cluster_size;
592 if (vol->mft_zone_start <= mft_lcn)
593 vol->mft_zone_start = 0;
594 ntfs_log_debug("mft_zone_start = 0x%llx\n", (long long)vol->mft_zone_start);
597 * Need to cap the mft zone on non-standard volumes so that it does
598 * not point outside the boundaries of the volume. We do this by
599 * halving the zone size until we are inside the volume.
601 vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
602 while (vol->mft_zone_end >= vol->nr_clusters) {
603 mft_zone_size >>= 1;
604 vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
606 ntfs_log_debug("mft_zone_end = 0x%llx\n", (long long)vol->mft_zone_end);
609 * Set the current position within each data zone to the start of the
610 * respective zone.
612 vol->data1_zone_pos = vol->mft_zone_end;
613 ntfs_log_debug("data1_zone_pos = %lld\n", (long long)vol->data1_zone_pos);
614 vol->data2_zone_pos = 0;
615 ntfs_log_debug("data2_zone_pos = %lld\n", (long long)vol->data2_zone_pos);
617 /* Set the mft data allocation position to mft record 24. */
618 vol->mft_data_pos = 24;
621 * The cluster allocator is now fully operational.
624 /* Need to setup $MFT so we can use the library read functions. */
625 if (ntfs_mft_load(vol) < 0) {
626 ntfs_log_perror("Failed to load $MFT");
627 goto error_exit;
630 /* Need to setup $MFTMirr so we can use the write functions, too. */
631 if (ntfs_mftmirr_load(vol) < 0) {
632 ntfs_log_perror("Failed to load $MFTMirr");
633 goto error_exit;
635 return vol;
636 error_exit:
637 eo = errno;
638 free(bs);
639 if (vol)
640 __ntfs_volume_release(vol);
641 errno = eo;
642 return NULL;
646 * ntfs_volume_check_logfile - check logfile on target volume
647 * @vol: volume on which to check logfile
649 * Return 0 on success and -1 on error with errno set error code.
651 static int ntfs_volume_check_logfile(ntfs_volume *vol)
653 ntfs_inode *ni;
654 ntfs_attr *na = NULL;
655 RESTART_PAGE_HEADER *rp = NULL;
656 int err = 0;
658 ni = ntfs_inode_open(vol, FILE_LogFile);
659 if (!ni) {
660 ntfs_log_perror("Failed to open inode FILE_LogFile");
661 errno = EIO;
662 return -1;
665 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
666 if (!na) {
667 ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
668 err = EIO;
669 goto out;
672 if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
673 err = EOPNOTSUPP;
675 * If the latest restart page was identified as version
676 * 2.0, then Windows may have kept a cached copy of
677 * metadata for fast restarting, and we should not mount.
678 * Hibernation will be seen the same way on a non
679 * Windows-system partition, so we have to use the same
680 * error code (EPERM).
681 * The restart page may also be identified as version 2.0
682 * when access to the file system is terminated abruptly
683 * by unplugging or power cut, so mounting is also rejected
684 * after such an event.
686 if (rp
687 && (rp->major_ver == const_cpu_to_le16(2))
688 && (rp->minor_ver == const_cpu_to_le16(0))) {
689 ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n");
690 err = EPERM;
692 free(rp);
693 ntfs_attr_close(na);
694 out:
695 if (ntfs_inode_close(ni))
696 ntfs_error_set(&err);
697 if (err) {
698 errno = err;
699 return -1;
701 return 0;
705 * ntfs_hiberfile_open - Find and open '/hiberfil.sys'
706 * @vol: An ntfs volume obtained from ntfs_mount
708 * Return: inode Success, hiberfil.sys is valid
709 * NULL hiberfil.sys doesn't exist or some other error occurred
711 static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol)
713 u64 inode;
714 ntfs_inode *ni_root;
715 ntfs_inode *ni_hibr = NULL;
716 ntfschar *unicode = NULL;
717 int unicode_len;
718 const char *hiberfile = "hiberfil.sys";
720 if (!vol) {
721 errno = EINVAL;
722 return NULL;
725 ni_root = ntfs_inode_open(vol, FILE_root);
726 if (!ni_root) {
727 ntfs_log_debug("Couldn't open the root directory.\n");
728 return NULL;
731 unicode_len = ntfs_mbstoucs(hiberfile, &unicode);
732 if (unicode_len < 0) {
733 ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode");
734 goto out;
737 inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len);
738 if (inode == (u64)-1) {
739 ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile);
740 goto out;
743 inode = MREF(inode);
744 ni_hibr = ntfs_inode_open(vol, inode);
745 if (!ni_hibr) {
746 ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode);
747 goto out;
749 out:
750 if (ntfs_inode_close(ni_root)) {
751 ntfs_inode_close(ni_hibr);
752 ni_hibr = NULL;
754 free(unicode);
755 return ni_hibr;
759 #define NTFS_HIBERFILE_HEADER_SIZE 4096
762 * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is
763 * hibernated on the target volume
764 * @vol: volume on which to check hiberfil.sys
766 * Return: 0 if Windows isn't hibernated for sure
767 * -1 otherwise and errno is set to the appropriate value
769 int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose)
771 ntfs_inode *ni;
772 ntfs_attr *na = NULL;
773 int bytes_read, err;
774 char *buf = NULL;
776 ni = ntfs_hiberfile_open(vol);
777 if (!ni) {
778 if (errno == ENOENT)
779 return 0;
780 return -1;
783 buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE);
784 if (!buf)
785 goto out;
787 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
788 if (!na) {
789 ntfs_log_perror("Failed to open hiberfil.sys data attribute");
790 goto out;
793 bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf);
794 if (bytes_read == -1) {
795 ntfs_log_perror("Failed to read hiberfil.sys");
796 goto out;
798 if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) {
799 if (verbose)
800 ntfs_log_error("Hibernated non-system partition, "
801 "refused to mount.\n");
802 errno = EPERM;
803 goto out;
805 if ((memcmp(buf, "hibr", 4) == 0)
806 || (memcmp(buf, "HIBR", 4) == 0)) {
807 if (verbose)
808 ntfs_log_error("Windows is hibernated, refused to mount.\n");
809 errno = EPERM;
810 goto out;
812 /* All right, all header bytes are zero */
813 errno = 0;
814 out:
815 if (na)
816 ntfs_attr_close(na);
817 free(buf);
818 err = errno;
819 if (ntfs_inode_close(ni))
820 ntfs_error_set(&err);
821 errno = err;
822 return errno ? -1 : 0;
826 * Make sure a LOGGED_UTILITY_STREAM attribute named "$TXF_DATA"
827 * on the root directory is resident.
828 * When it is non-resident, the partition cannot be mounted on Vista
829 * (see http://support.microsoft.com/kb/974729)
831 * We take care to avoid this situation, however this can be a
832 * consequence of having used an older version (including older
833 * Windows version), so we had better fix it.
835 * Returns 0 if unneeded or successful
836 * -1 if there was an error, explained by errno
839 static int fix_txf_data(ntfs_volume *vol)
841 void *txf_data;
842 s64 txf_data_size;
843 ntfs_inode *ni;
844 ntfs_attr *na;
845 int res;
847 res = 0;
848 ntfs_log_debug("Loading root directory\n");
849 ni = ntfs_inode_open(vol, FILE_root);
850 if (!ni) {
851 ntfs_log_perror("Failed to open root directory");
852 res = -1;
853 } else {
854 /* Get the $TXF_DATA attribute */
855 na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, TXF_DATA, 9);
856 if (na) {
857 if (NAttrNonResident(na)) {
859 * Fix the attribute by truncating, then
860 * rewriting it.
862 ntfs_log_debug("Making $TXF_DATA resident\n");
863 txf_data = ntfs_attr_readall(ni,
864 AT_LOGGED_UTILITY_STREAM,
865 TXF_DATA, 9, &txf_data_size);
866 if (txf_data) {
867 if (ntfs_attr_truncate(na, 0)
868 || (ntfs_attr_pwrite(na, 0,
869 txf_data_size, txf_data)
870 != txf_data_size))
871 res = -1;
872 free(txf_data);
874 if (res)
875 ntfs_log_error("Failed to make $TXF_DATA resident\n");
876 else
877 ntfs_log_error("$TXF_DATA made resident\n");
879 ntfs_attr_close(na);
881 if (ntfs_inode_close(ni)) {
882 ntfs_log_perror("Failed to close root");
883 res = -1;
886 return (res);
890 * ntfs_device_mount - open ntfs volume
891 * @dev: device to open
892 * @flags: optional mount flags
894 * This function mounts an ntfs volume. @dev should describe the device which
895 * to mount as the ntfs volume.
897 * @flags is an optional second parameter. The same flags are used as for
898 * the mount system call (man 2 mount). Currently only the following flag
899 * is implemented:
900 * NTFS_MNT_RDONLY - mount volume read-only
902 * The function opens the device @dev and verifies that it contains a valid
903 * bootsector. Then, it allocates an ntfs_volume structure and initializes
904 * some of the values inside the structure from the information stored in the
905 * bootsector. It proceeds to load the necessary system files and completes
906 * setting up the structure.
908 * Return the allocated volume structure on success and NULL on error with
909 * errno set to the error code.
911 ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
913 s64 l;
914 ntfs_volume *vol;
915 u8 *m = NULL, *m2 = NULL;
916 ntfs_attr_search_ctx *ctx = NULL;
917 ntfs_inode *ni;
918 ntfs_attr *na;
919 ATTR_RECORD *a;
920 VOLUME_INFORMATION *vinf;
921 ntfschar *vname;
922 u32 record_size;
923 int i, j, eo;
924 unsigned int k;
925 u32 u;
926 BOOL need_fallback_ro;
928 need_fallback_ro = FALSE;
929 vol = ntfs_volume_startup(dev, flags);
930 if (!vol)
931 return NULL;
933 /* Load data from $MFT and $MFTMirr and compare the contents. */
934 m = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
935 m2 = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
936 if (!m || !m2)
937 goto error_exit;
939 l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
940 vol->mft_record_size, m);
941 if (l != vol->mftmirr_size) {
942 if (l == -1)
943 ntfs_log_perror("Failed to read $MFT");
944 else {
945 ntfs_log_error("Failed to read $MFT, unexpected length "
946 "(%lld != %d).\n", (long long)l,
947 vol->mftmirr_size);
948 errno = EIO;
950 goto error_exit;
952 l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
953 vol->mft_record_size, m2);
954 if (l != vol->mftmirr_size) {
955 if (l == -1) {
956 ntfs_log_perror("Failed to read $MFTMirr");
957 goto error_exit;
959 vol->mftmirr_size = l;
961 ntfs_log_debug("Comparing $MFTMirr to $MFT...\n");
962 /* Windows 10 does not update the full $MFTMirr any more */
963 for (i = 0; (i < vol->mftmirr_size) && (i < FILE_first_user); ++i) {
964 MFT_RECORD *mrec, *mrec2;
965 const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
966 "$Volume", "$AttrDef", "root directory", "$Bitmap",
967 "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
968 const char *s;
970 if (i < 12)
971 s = ESTR[i];
972 else if (i < 16)
973 s = "system file";
974 else
975 s = "mft record";
977 mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
978 if (mrec->flags & MFT_RECORD_IN_USE) {
979 if (ntfs_is_baad_record(mrec->magic)) {
980 ntfs_log_error("$MFT error: Incomplete multi "
981 "sector transfer detected in "
982 "'%s'.\n", s);
983 goto io_error_exit;
985 if (!ntfs_is_mft_record(mrec->magic)) {
986 ntfs_log_error("$MFT error: Invalid mft "
987 "record for '%s'.\n", s);
988 goto io_error_exit;
991 mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
992 if (mrec2->flags & MFT_RECORD_IN_USE) {
993 if (ntfs_is_baad_record(mrec2->magic)) {
994 ntfs_log_error("$MFTMirr error: Incomplete "
995 "multi sector transfer "
996 "detected in '%s'.\n", s);
997 goto io_error_exit;
999 if (!ntfs_is_mft_record(mrec2->magic)) {
1000 ntfs_log_error("$MFTMirr error: Invalid mft "
1001 "record for '%s'.\n", s);
1002 goto io_error_exit;
1005 record_size = ntfs_mft_record_get_data_size(mrec);
1006 if ((record_size <= sizeof(MFT_RECORD))
1007 || (record_size > vol->mft_record_size)
1008 || memcmp(mrec, mrec2, record_size)) {
1009 ntfs_log_error("$MFTMirr does not match $MFT (record "
1010 "%d).\n", i);
1011 goto io_error_exit;
1015 free(m2);
1016 free(m);
1017 m = m2 = NULL;
1019 /* Now load the bitmap from $Bitmap. */
1020 ntfs_log_debug("Loading $Bitmap...\n");
1021 vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
1022 if (!vol->lcnbmp_ni) {
1023 ntfs_log_perror("Failed to open inode FILE_Bitmap");
1024 goto error_exit;
1027 vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
1028 if (!vol->lcnbmp_na) {
1029 ntfs_log_perror("Failed to open ntfs attribute");
1030 goto error_exit;
1033 if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
1034 ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
1035 (long long)vol->lcnbmp_na->data_size,
1036 (long long)vol->lcnbmp_na->allocated_size);
1037 goto io_error_exit;
1040 /* Now load the upcase table from $UpCase. */
1041 ntfs_log_debug("Loading $UpCase...\n");
1042 ni = ntfs_inode_open(vol, FILE_UpCase);
1043 if (!ni) {
1044 ntfs_log_perror("Failed to open inode FILE_UpCase");
1045 goto error_exit;
1047 /* Get an ntfs attribute for $UpCase/$DATA. */
1048 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1049 if (!na) {
1050 ntfs_log_perror("Failed to open ntfs attribute");
1051 goto error_exit;
1054 * Note: Normally, the upcase table has a length equal to 65536
1055 * 2-byte Unicode characters but allow for different cases, so no
1056 * checks done. Just check we don't overflow 32-bits worth of Unicode
1057 * characters.
1059 if (na->data_size & ~0x1ffffffffULL) {
1060 ntfs_log_error("Error: Upcase table is too big (max 32-bit "
1061 "allowed).\n");
1062 errno = EINVAL;
1063 goto error_exit;
1065 if (vol->upcase_len != na->data_size >> 1) {
1066 vol->upcase_len = na->data_size >> 1;
1067 /* Throw away default table. */
1068 free(vol->upcase);
1069 vol->upcase = ntfs_malloc(na->data_size);
1070 if (!vol->upcase)
1071 goto error_exit;
1073 /* Read in the $DATA attribute value into the buffer. */
1074 l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);
1075 if (l != na->data_size) {
1076 ntfs_log_error("Failed to read $UpCase, unexpected length "
1077 "(%lld != %lld).\n", (long long)l,
1078 (long long)na->data_size);
1079 errno = EIO;
1080 goto error_exit;
1082 /* Done with the $UpCase mft record. */
1083 ntfs_attr_close(na);
1084 if (ntfs_inode_close(ni)) {
1085 ntfs_log_perror("Failed to close $UpCase");
1086 goto error_exit;
1088 /* Consistency check of $UpCase, restricted to plain ASCII chars */
1089 k = 0x20;
1090 while ((k < vol->upcase_len)
1091 && (k < 0x7f)
1092 && (le16_to_cpu(vol->upcase[k])
1093 == ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
1094 k++;
1095 if (k < 0x7f) {
1096 ntfs_log_error("Corrupted file $UpCase\n");
1097 goto io_error_exit;
1101 * Now load $Volume and set the version information and flags in the
1102 * vol structure accordingly.
1104 ntfs_log_debug("Loading $Volume...\n");
1105 vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);
1106 if (!vol->vol_ni) {
1107 ntfs_log_perror("Failed to open inode FILE_Volume");
1108 goto error_exit;
1110 /* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */
1111 ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
1112 if (!ctx)
1113 goto error_exit;
1115 /* Find the $VOLUME_INFORMATION attribute. */
1116 if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
1117 0, ctx)) {
1118 ntfs_log_perror("$VOLUME_INFORMATION attribute not found in "
1119 "$Volume");
1120 goto error_exit;
1122 a = ctx->attr;
1123 /* Has to be resident. */
1124 if (a->non_resident) {
1125 ntfs_log_error("Attribute $VOLUME_INFORMATION must be "
1126 "resident but it isn't.\n");
1127 errno = EIO;
1128 goto error_exit;
1130 /* Get a pointer to the value of the attribute. */
1131 vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
1132 /* Sanity checks. */
1133 if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
1134 le32_to_cpu(ctx->mrec->bytes_in_use) ||
1135 le16_to_cpu(a->value_offset) + le32_to_cpu(
1136 a->value_length) > le32_to_cpu(a->length)) {
1137 ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n");
1138 errno = EIO;
1139 goto error_exit;
1141 /* Setup vol from the volume information attribute value. */
1142 vol->major_ver = vinf->major_ver;
1143 vol->minor_ver = vinf->minor_ver;
1144 /* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are
1145 defined using cpu_to_le16() macro and hence are consistent. */
1146 vol->flags = vinf->flags;
1148 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.
1150 ntfs_attr_reinit_search_ctx(ctx);
1151 if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
1152 ctx)) {
1153 if (errno != ENOENT) {
1154 ntfs_log_perror("Failed to lookup of $VOLUME_NAME in "
1155 "$Volume failed");
1156 goto error_exit;
1159 * Attribute not present. This has been seen in the field.
1160 * Treat this the same way as if the attribute was present but
1161 * had zero length.
1163 vol->vol_name = ntfs_malloc(1);
1164 if (!vol->vol_name)
1165 goto error_exit;
1166 vol->vol_name[0] = '\0';
1167 } else {
1168 a = ctx->attr;
1169 /* Has to be resident. */
1170 if (a->non_resident) {
1171 ntfs_log_error("$VOLUME_NAME must be resident.\n");
1172 errno = EIO;
1173 goto error_exit;
1175 /* Get a pointer to the value of the attribute. */
1176 vname = (ntfschar*)(le16_to_cpu(a->value_offset) + (char*)a);
1177 u = le32_to_cpu(a->value_length) / 2;
1179 * Convert Unicode volume name to current locale multibyte
1180 * format.
1182 vol->vol_name = NULL;
1183 if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
1184 ntfs_log_perror("Volume name could not be converted "
1185 "to current locale");
1186 ntfs_log_debug("Forcing name into ASCII by replacing "
1187 "non-ASCII characters with underscores.\n");
1188 vol->vol_name = ntfs_malloc(u + 1);
1189 if (!vol->vol_name)
1190 goto error_exit;
1192 for (j = 0; j < (s32)u; j++) {
1193 u16 uc = le16_to_cpu(vname[j]);
1194 if (uc > 0xff)
1195 uc = (u16)'_';
1196 vol->vol_name[j] = (char)uc;
1198 vol->vol_name[u] = '\0';
1201 ntfs_attr_put_search_ctx(ctx);
1202 ctx = NULL;
1203 /* Now load the attribute definitions from $AttrDef. */
1204 ntfs_log_debug("Loading $AttrDef...\n");
1205 ni = ntfs_inode_open(vol, FILE_AttrDef);
1206 if (!ni) {
1207 ntfs_log_perror("Failed to open $AttrDef");
1208 goto error_exit;
1210 /* Get an ntfs attribute for $AttrDef/$DATA. */
1211 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1212 if (!na) {
1213 ntfs_log_perror("Failed to open ntfs attribute");
1214 goto error_exit;
1216 /* Check we don't overflow 32-bits. */
1217 if (na->data_size > 0xffffffffLL) {
1218 ntfs_log_error("Attribute definition table is too big (max "
1219 "32-bit allowed).\n");
1220 errno = EINVAL;
1221 goto error_exit;
1223 vol->attrdef_len = na->data_size;
1224 vol->attrdef = ntfs_malloc(na->data_size);
1225 if (!vol->attrdef)
1226 goto error_exit;
1227 /* Read in the $DATA attribute value into the buffer. */
1228 l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef);
1229 if (l != na->data_size) {
1230 ntfs_log_error("Failed to read $AttrDef, unexpected length "
1231 "(%lld != %lld).\n", (long long)l,
1232 (long long)na->data_size);
1233 errno = EIO;
1234 goto error_exit;
1236 /* Done with the $AttrDef mft record. */
1237 ntfs_attr_close(na);
1238 if (ntfs_inode_close(ni)) {
1239 ntfs_log_perror("Failed to close $AttrDef");
1240 goto error_exit;
1243 /* Open $Secure. */
1244 if (ntfs_open_secure(vol))
1245 goto error_exit;
1248 * Check for dirty logfile and hibernated Windows.
1249 * We care only about read-write mounts.
1251 if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) {
1252 if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) &&
1253 ntfs_volume_check_hiberfile(vol, 1) < 0) {
1254 if (flags & NTFS_MNT_MAY_RDONLY)
1255 need_fallback_ro = TRUE;
1256 else
1257 goto error_exit;
1259 if (ntfs_volume_check_logfile(vol) < 0) {
1260 /* Always reject cached metadata for now */
1261 if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM)) {
1262 if (flags & NTFS_MNT_MAY_RDONLY)
1263 need_fallback_ro = TRUE;
1264 else
1265 goto error_exit;
1266 } else {
1267 ntfs_log_info("The file system wasn't safely "
1268 "closed on Windows. Fixing.\n");
1269 if (ntfs_logfile_reset(vol))
1270 goto error_exit;
1273 /* make $TXF_DATA resident if present on the root directory */
1274 if (!(flags & NTFS_MNT_RDONLY) && !need_fallback_ro) {
1275 if (fix_txf_data(vol))
1276 goto error_exit;
1279 if (need_fallback_ro) {
1280 NVolSetReadOnly(vol);
1281 ntfs_log_error("%s", fallback_readonly_msg);
1284 return vol;
1285 io_error_exit:
1286 errno = EIO;
1287 error_exit:
1288 eo = errno;
1289 if (ctx)
1290 ntfs_attr_put_search_ctx(ctx);
1291 free(m);
1292 free(m2);
1293 __ntfs_volume_release(vol);
1294 errno = eo;
1295 return NULL;
1299 * Set appropriate flags for showing NTFS metafiles
1300 * or files marked as hidden.
1301 * Not set in ntfs_mount() to avoid breaking existing tools.
1304 int ntfs_set_shown_files(ntfs_volume *vol,
1305 BOOL show_sys_files, BOOL show_hid_files,
1306 BOOL hide_dot_files)
1308 int res;
1310 res = -1;
1311 if (vol) {
1312 NVolClearShowSysFiles(vol);
1313 NVolClearShowHidFiles(vol);
1314 NVolClearHideDotFiles(vol);
1315 if (show_sys_files)
1316 NVolSetShowSysFiles(vol);
1317 if (show_hid_files)
1318 NVolSetShowHidFiles(vol);
1319 if (hide_dot_files)
1320 NVolSetHideDotFiles(vol);
1321 res = 0;
1323 if (res)
1324 ntfs_log_error("Failed to set file visibility\n");
1325 return (res);
1329 * Set ignore case mode
1332 int ntfs_set_ignore_case(ntfs_volume *vol)
1334 int res;
1336 res = -1;
1337 if (vol && vol->upcase) {
1338 vol->locase = ntfs_locase_table_build(vol->upcase,
1339 vol->upcase_len);
1340 if (vol->locase) {
1341 NVolClearCaseSensitive(vol);
1342 res = 0;
1345 if (res)
1346 ntfs_log_error("Failed to set ignore_case mode\n");
1347 return (res);
1351 * ntfs_mount - open ntfs volume
1352 * @name: name of device/file to open
1353 * @flags: optional mount flags
1355 * This function mounts an ntfs volume. @name should contain the name of the
1356 * device/file to mount as the ntfs volume.
1358 * @flags is an optional second parameter. The same flags are used as for
1359 * the mount system call (man 2 mount). Currently only the following flags
1360 * is implemented:
1361 * NTFS_MNT_RDONLY - mount volume read-only
1363 * The function opens the device or file @name and verifies that it contains a
1364 * valid bootsector. Then, it allocates an ntfs_volume structure and initializes
1365 * some of the values inside the structure from the information stored in the
1366 * bootsector. It proceeds to load the necessary system files and completes
1367 * setting up the structure.
1369 * Return the allocated volume structure on success and NULL on error with
1370 * errno set to the error code.
1372 * Note, that a copy is made of @name, and hence it can be discarded as
1373 * soon as the function returns.
1375 ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),
1376 ntfs_mount_flags flags __attribute__((unused)))
1378 #ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
1379 struct ntfs_device *dev;
1380 ntfs_volume *vol;
1382 /* Allocate an ntfs_device structure. */
1383 dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
1384 if (!dev)
1385 return NULL;
1386 /* Call ntfs_device_mount() to do the actual mount. */
1387 vol = ntfs_device_mount(dev, flags);
1388 if (!vol) {
1389 int eo = errno;
1390 ntfs_device_free(dev);
1391 errno = eo;
1392 } else
1393 ntfs_create_lru_caches(vol);
1394 return vol;
1395 #else
1397 * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is
1398 * defined as there are no device operations available in libntfs in
1399 * this case.
1401 errno = EOPNOTSUPP;
1402 return NULL;
1403 #endif
1407 * ntfs_umount - close ntfs volume
1408 * @vol: address of ntfs_volume structure of volume to close
1409 * @force: if true force close the volume even if it is busy
1411 * Deallocate all structures (including @vol itself) associated with the ntfs
1412 * volume @vol.
1414 * Return 0 on success. On error return -1 with errno set appropriately
1415 * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that
1416 * an operation is in progress and if you try the close later the operation
1417 * might be completed and the close succeed.
1419 * If @force is true (i.e. not zero) this function will close the volume even
1420 * if this means that data might be lost.
1422 * @vol must have previously been returned by a call to ntfs_mount().
1424 * @vol itself is deallocated and should no longer be dereferenced after this
1425 * function returns success. If it returns an error then nothing has been done
1426 * so it is safe to continue using @vol.
1428 int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused)))
1430 struct ntfs_device *dev;
1431 int ret;
1433 if (!vol) {
1434 errno = EINVAL;
1435 return -1;
1437 dev = vol->dev;
1438 ret = __ntfs_volume_release(vol);
1439 ntfs_device_free(dev);
1440 return ret;
1443 #ifdef HAVE_MNTENT_H
1446 * ntfs_mntent_check - desc
1448 * If you are wanting to use this, you actually wanted to use
1449 * ntfs_check_if_mounted(), you just didn't realize. (-:
1451 * See description of ntfs_check_if_mounted(), below.
1453 static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
1455 struct mntent *mnt;
1456 char *real_file = NULL, *real_fsname = NULL;
1457 FILE *f;
1458 int err = 0;
1460 real_file = ntfs_malloc(PATH_MAX + 1);
1461 if (!real_file)
1462 return -1;
1463 real_fsname = ntfs_malloc(PATH_MAX + 1);
1464 if (!real_fsname) {
1465 err = errno;
1466 goto exit;
1468 if (!ntfs_realpath_canonicalize(file, real_file)) {
1469 err = errno;
1470 goto exit;
1472 f = setmntent("/proc/mounts", "r");
1473 if (!f && !(f = setmntent(MOUNTED, "r"))) {
1474 err = errno;
1475 goto exit;
1477 while ((mnt = getmntent(f))) {
1478 if (!ntfs_realpath_canonicalize(mnt->mnt_fsname, real_fsname))
1479 continue;
1480 if (!strcmp(real_file, real_fsname))
1481 break;
1483 endmntent(f);
1484 if (!mnt)
1485 goto exit;
1486 *mnt_flags = NTFS_MF_MOUNTED;
1487 if (!strcmp(mnt->mnt_dir, "/"))
1488 *mnt_flags |= NTFS_MF_ISROOT;
1489 #ifdef HAVE_HASMNTOPT
1490 if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
1491 *mnt_flags |= NTFS_MF_READONLY;
1492 #endif
1493 exit:
1494 free(real_file);
1495 free(real_fsname);
1496 if (err) {
1497 errno = err;
1498 return -1;
1500 return 0;
1503 #else /* HAVE_MNTENT_H */
1505 #if defined(__sun) && defined (__SVR4)
1507 static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
1509 struct mnttab *mnt = NULL;
1510 char *real_file = NULL, *real_fsname = NULL;
1511 FILE *f;
1512 int err = 0;
1514 real_file = (char*)ntfs_malloc(PATH_MAX + 1);
1515 if (!real_file)
1516 return -1;
1517 real_fsname = (char*)ntfs_malloc(PATH_MAX + 1);
1518 mnt = (struct mnttab*)ntfs_malloc(MNT_LINE_MAX + 1);
1519 if (!real_fsname || !mnt) {
1520 err = errno;
1521 goto exit;
1523 if (!ntfs_realpath_canonicalize(file, real_file)) {
1524 err = errno;
1525 goto exit;
1527 if (!(f = fopen(MNTTAB, "r"))) {
1528 err = errno;
1529 goto exit;
1531 while (!getmntent(f, mnt)) {
1532 if (!ntfs_realpath_canonicalize(mnt->mnt_special, real_fsname))
1533 continue;
1534 if (!strcmp(real_file, real_fsname)) {
1535 *mnt_flags = NTFS_MF_MOUNTED;
1536 if (!strcmp(mnt->mnt_mountp, "/"))
1537 *mnt_flags |= NTFS_MF_ISROOT;
1538 if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
1539 *mnt_flags |= NTFS_MF_READONLY;
1540 break;
1543 fclose(f);
1544 exit:
1545 free(mnt);
1546 free(real_file);
1547 free(real_fsname);
1548 if (err) {
1549 errno = err;
1550 return -1;
1552 return 0;
1555 #endif /* defined(__sun) && defined (__SVR4) */
1556 #endif /* HAVE_MNTENT_H */
1559 * ntfs_check_if_mounted - check if an ntfs volume is currently mounted
1560 * @file: device file to check
1561 * @mnt_flags: pointer into which to return the ntfs mount flags (see volume.h)
1563 * If the running system does not support the {set,get,end}mntent() calls,
1564 * just return 0 and set *@mnt_flags to zero.
1566 * When the system does support the calls, ntfs_check_if_mounted() first tries
1567 * to find the device @file in /etc/mtab (or wherever this is kept on the
1568 * running system). If it is not found, assume the device is not mounted and
1569 * return 0 and set *@mnt_flags to zero.
1571 * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags.
1573 * Further if @file is mounted as the file system root ("/"), set the flag
1574 * NTFS_MF_ISROOT in *@mnt_flags.
1576 * Finally, check if the file system is mounted read-only, and if so set the
1577 * NTFS_MF_READONLY flag in *@mnt_flags.
1579 * On success return 0 with *@mnt_flags set to the ntfs mount flags.
1581 * On error return -1 with errno set to the error code.
1583 int ntfs_check_if_mounted(const char *file __attribute__((unused)),
1584 unsigned long *mnt_flags)
1586 *mnt_flags = 0;
1587 #if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4))
1588 return ntfs_mntent_check(file, mnt_flags);
1589 #else
1590 return 0;
1591 #endif
1595 * ntfs_version_is_supported - check if NTFS version is supported.
1596 * @vol: ntfs volume whose version we're interested in.
1598 * The function checks if the NTFS volume version is known or not.
1599 * Version 1.1 and 1.2 are used by Windows NT3.x and NT4.
1600 * Version 2.x is used by Windows 2000 Betas.
1601 * Version 3.0 is used by Windows 2000.
1602 * Version 3.1 is used by Windows XP, Windows Server 2003 and Longhorn.
1604 * Return 0 if NTFS version is supported otherwise -1 with errno set.
1606 * The following error codes are defined:
1607 * EOPNOTSUPP - Unknown NTFS version
1608 * EINVAL - Invalid argument
1610 int ntfs_version_is_supported(ntfs_volume *vol)
1612 u8 major, minor;
1614 if (!vol) {
1615 errno = EINVAL;
1616 return -1;
1619 major = vol->major_ver;
1620 minor = vol->minor_ver;
1622 if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor))
1623 return 0;
1625 if (NTFS_V2_X(major, minor))
1626 return 0;
1628 if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor))
1629 return 0;
1631 errno = EOPNOTSUPP;
1632 return -1;
1636 * ntfs_logfile_reset - "empty" $LogFile data attribute value
1637 * @vol: ntfs volume whose $LogFile we intend to reset.
1639 * Fill the value of the $LogFile data attribute, i.e. the contents of
1640 * the file, with 0xff's, thus marking the journal as empty.
1642 * FIXME(?): We might need to zero the LSN field of every single mft
1643 * record as well. (But, first try without doing that and see what
1644 * happens, since chkdsk might pickup the pieces and do it for us...)
1646 * On success return 0.
1648 * On error return -1 with errno set to the error code.
1650 int ntfs_logfile_reset(ntfs_volume *vol)
1652 ntfs_inode *ni;
1653 ntfs_attr *na;
1654 int eo;
1656 if (!vol) {
1657 errno = EINVAL;
1658 return -1;
1661 ni = ntfs_inode_open(vol, FILE_LogFile);
1662 if (!ni) {
1663 ntfs_log_perror("Failed to open inode FILE_LogFile");
1664 return -1;
1667 na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1668 if (!na) {
1669 eo = errno;
1670 ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
1671 goto error_exit;
1674 if (ntfs_empty_logfile(na)) {
1675 eo = errno;
1676 ntfs_attr_close(na);
1677 goto error_exit;
1680 ntfs_attr_close(na);
1681 return ntfs_inode_close(ni);
1683 error_exit:
1684 ntfs_inode_close(ni);
1685 errno = eo;
1686 return -1;
1690 * ntfs_volume_write_flags - set the flags of an ntfs volume
1691 * @vol: ntfs volume where we set the volume flags
1692 * @flags: new flags
1694 * Set the on-disk volume flags in the mft record of $Volume and
1695 * on volume @vol to @flags.
1697 * Return 0 if successful and -1 if not with errno set to the error code.
1699 int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags)
1701 ATTR_RECORD *a;
1702 VOLUME_INFORMATION *c;
1703 ntfs_attr_search_ctx *ctx;
1704 int ret = -1; /* failure */
1706 if (!vol || !vol->vol_ni) {
1707 errno = EINVAL;
1708 return -1;
1710 /* Get a pointer to the volume information attribute. */
1711 ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
1712 if (!ctx)
1713 return -1;
1715 if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
1716 0, ctx)) {
1717 ntfs_log_error("Attribute $VOLUME_INFORMATION was not found "
1718 "in $Volume!\n");
1719 goto err_out;
1721 a = ctx->attr;
1722 /* Sanity check. */
1723 if (a->non_resident) {
1724 ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
1725 "but it isn't.\n");
1726 errno = EIO;
1727 goto err_out;
1729 /* Get a pointer to the value of the attribute. */
1730 c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
1731 /* Sanity checks. */
1732 if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
1733 le32_to_cpu(ctx->mrec->bytes_in_use) ||
1734 le16_to_cpu(a->value_offset) +
1735 le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
1736 ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
1737 "corrupt!\n");
1738 errno = EIO;
1739 goto err_out;
1741 /* Set the volume flags. */
1742 vol->flags = c->flags = flags & VOLUME_FLAGS_MASK;
1743 /* Write them to disk. */
1744 ntfs_inode_mark_dirty(vol->vol_ni);
1745 if (ntfs_inode_sync(vol->vol_ni))
1746 goto err_out;
1748 ret = 0; /* success */
1749 err_out:
1750 ntfs_attr_put_search_ctx(ctx);
1751 return ret;
1754 int ntfs_volume_error(int err)
1756 int ret;
1758 switch (err) {
1759 case 0:
1760 ret = NTFS_VOLUME_OK;
1761 break;
1762 case EINVAL:
1763 ret = NTFS_VOLUME_NOT_NTFS;
1764 break;
1765 case EIO:
1766 ret = NTFS_VOLUME_CORRUPT;
1767 break;
1768 case EPERM:
1770 * Hibernation and fast restarting are seen the
1771 * same way on a non Windows-system partition.
1773 ret = NTFS_VOLUME_HIBERNATED;
1774 break;
1775 case EOPNOTSUPP:
1776 ret = NTFS_VOLUME_UNCLEAN_UNMOUNT;
1777 break;
1778 case EBUSY:
1779 ret = NTFS_VOLUME_LOCKED;
1780 break;
1781 case ENXIO:
1782 ret = NTFS_VOLUME_RAID;
1783 break;
1784 case EACCES:
1785 ret = NTFS_VOLUME_NO_PRIVILEGE;
1786 break;
1787 default:
1788 ret = NTFS_VOLUME_UNKNOWN_REASON;
1789 break;
1791 return ret;
1795 void ntfs_mount_error(const char *volume, const char *mntpoint, int err)
1797 switch (err) {
1798 case NTFS_VOLUME_NOT_NTFS:
1799 ntfs_log_error(invalid_ntfs_msg, volume);
1800 break;
1801 case NTFS_VOLUME_CORRUPT:
1802 ntfs_log_error("%s", corrupt_volume_msg);
1803 break;
1804 case NTFS_VOLUME_HIBERNATED:
1805 ntfs_log_error(hibernated_volume_msg, volume, mntpoint);
1806 break;
1807 case NTFS_VOLUME_UNCLEAN_UNMOUNT:
1808 ntfs_log_error("%s", unclean_journal_msg);
1809 break;
1810 case NTFS_VOLUME_LOCKED:
1811 ntfs_log_error("%s", opened_volume_msg);
1812 break;
1813 case NTFS_VOLUME_RAID:
1814 ntfs_log_error("%s", fakeraid_msg);
1815 break;
1816 case NTFS_VOLUME_NO_PRIVILEGE:
1817 ntfs_log_error(access_denied_msg, volume);
1818 break;
1822 int ntfs_set_locale(void)
1824 const char *locale;
1826 locale = setlocale(LC_ALL, "");
1827 if (!locale) {
1828 locale = setlocale(LC_ALL, NULL);
1829 ntfs_log_error("Couldn't set local environment, using default "
1830 "'%s'.\n", locale);
1831 return 1;
1833 return 0;
1837 * Feed the counts of free clusters and free mft records
1840 int ntfs_volume_get_free_space(ntfs_volume *vol)
1842 ntfs_attr *na;
1843 int ret;
1845 ret = -1; /* default return */
1846 vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
1847 if (vol->free_clusters < 0) {
1848 ntfs_log_perror("Failed to read NTFS $Bitmap");
1849 } else {
1850 na = vol->mftbmp_na;
1851 vol->free_mft_records = ntfs_attr_get_free_bits(na);
1853 if (vol->free_mft_records >= 0)
1854 vol->free_mft_records += (na->allocated_size - na->data_size) << 3;
1856 if (vol->free_mft_records < 0)
1857 ntfs_log_perror("Failed to calculate free MFT records");
1858 else
1859 ret = 0;
1861 return (ret);
1865 * ntfs_volume_rename - change the current label on a volume
1866 * @vol: volume to change the label on
1867 * @label: the new label
1868 * @label_len: the length of @label in ntfschars including the terminating NULL
1869 * character, which is mandatory (the value can not exceed 128)
1871 * Change the label on the volume @vol to @label.
1873 int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, int label_len)
1875 ntfs_attr *na;
1876 char *old_vol_name;
1877 char *new_vol_name = NULL;
1878 int new_vol_name_len;
1879 int err;
1881 if (NVolReadOnly(vol)) {
1882 ntfs_log_error("Refusing to change label on read-only mounted "
1883 "volume.\n");
1884 errno = EROFS;
1885 return -1;
1888 label_len *= sizeof(ntfschar);
1889 if (label_len > 0x100) {
1890 ntfs_log_error("New label is too long. Maximum %u characters "
1891 "allowed.\n",
1892 (unsigned)(0x100 / sizeof(ntfschar)));
1893 errno = ERANGE;
1894 return -1;
1897 na = ntfs_attr_open(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0);
1898 if (!na) {
1899 if (errno != ENOENT) {
1900 err = errno;
1901 ntfs_log_perror("Lookup of $VOLUME_NAME attribute "
1902 "failed");
1903 goto err_out;
1906 /* The volume name attribute does not exist. Need to add it. */
1907 if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
1908 (const u8*) label, label_len))
1910 err = errno;
1911 ntfs_log_perror("Encountered error while adding "
1912 "$VOLUME_NAME attribute");
1913 goto err_out;
1916 else {
1917 s64 written;
1919 if (NAttrNonResident(na)) {
1920 err = errno;
1921 ntfs_log_error("Error: Attribute $VOLUME_NAME must be "
1922 "resident.\n");
1923 goto err_out;
1926 if (na->data_size != label_len) {
1927 if (ntfs_attr_truncate(na, label_len)) {
1928 err = errno;
1929 ntfs_log_perror("Error resizing resident "
1930 "attribute");
1931 goto err_out;
1935 if (label_len) {
1936 written = ntfs_attr_pwrite(na, 0, label_len, label);
1937 if (written == -1) {
1938 err = errno;
1939 ntfs_log_perror("Error when writing "
1940 "$VOLUME_NAME data");
1941 goto err_out;
1943 else if (written != label_len) {
1944 err = EIO;
1945 ntfs_log_error("Partial write when writing "
1946 "$VOLUME_NAME data.");
1947 goto err_out;
1953 new_vol_name_len =
1954 ntfs_ucstombs(label, label_len, &new_vol_name, 0);
1955 if (new_vol_name_len == -1) {
1956 err = errno;
1957 ntfs_log_perror("Error while decoding new volume name");
1958 goto err_out;
1961 old_vol_name = vol->vol_name;
1962 vol->vol_name = new_vol_name;
1963 free(old_vol_name);
1965 err = 0;
1966 err_out:
1967 if (na)
1968 ntfs_attr_close(na);
1969 if (err)
1970 errno = err;
1971 return err ? -1 : 0;