• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Copyright (c) 2010      Jean-Pierre Andre
8  *
9  * This program/include file is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program/include file is distributed in the hope that it will be
15  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
16  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program (in the main directory of the NTFS-3G
21  * distribution in the file COPYING); if not, write to the Free Software
22  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24 
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28 
29 #ifdef HAVE_STDLIB_H
30 #include <stdlib.h>
31 #endif
32 #ifdef HAVE_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
56 
57 #if defined(__sun) && defined (__SVR4)
58 #include <sys/mnttab.h>
59 #endif
60 
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"
78 
79 const char *ntfs_home =
80 "News, support and information:  https://github.com/tuxera/ntfs-3g/\n";
81 
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";
86 
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";
95 
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";
100 
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";
105 
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";
109 
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";
114 
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";
120 
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 "https://github.com/tuxera/ntfs-3g/wiki/NTFS-3G-FAQ\n";
125 
126 /**
127  * ntfs_volume_alloc - Create an NTFS volume object and initialise it
128  *
129  * Description...
130  *
131  * Returns:
132  */
ntfs_volume_alloc(void)133 ntfs_volume *ntfs_volume_alloc(void)
134 {
135 	return ntfs_calloc(sizeof(ntfs_volume));
136 }
137 
ntfs_attr_free(ntfs_attr ** na)138 static void ntfs_attr_free(ntfs_attr **na)
139 {
140 	if (na && *na) {
141 		ntfs_attr_close(*na);
142 		*na = NULL;
143 	}
144 }
145 
ntfs_inode_free(ntfs_inode ** ni)146 static int ntfs_inode_free(ntfs_inode **ni)
147 {
148 	int ret = -1;
149 
150 	if (ni && *ni) {
151 		ret = ntfs_inode_close(*ni);
152 		*ni = NULL;
153 	}
154 
155 	return ret;
156 }
157 
ntfs_error_set(int * err)158 static void ntfs_error_set(int *err)
159 {
160 	if (!*err)
161 		*err = errno;
162 }
163 
164 /**
165  * __ntfs_volume_release - Destroy an NTFS volume object
166  * @v:
167  *
168  * Description...
169  *
170  * Returns:
171  */
__ntfs_volume_release(ntfs_volume * v)172 static int __ntfs_volume_release(ntfs_volume *v)
173 {
174 	int err = 0;
175 
176 	if (ntfs_close_secure(v))
177 		ntfs_error_set(&err);
178 
179 	if (ntfs_inode_free(&v->vol_ni))
180 		ntfs_error_set(&err);
181 	/*
182 	 * FIXME: Inodes must be synced before closing
183 	 * attributes, otherwise unmount could fail.
184 	 */
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);
190 
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);
197 
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);
203 
204 	if (v->dev) {
205 		struct ntfs_device *dev = v->dev;
206 
207 		if (dev->d_ops->sync(dev))
208 			ntfs_error_set(&err);
209 		if (dev->d_ops->close(dev))
210 			ntfs_error_set(&err);
211 	}
212 
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);
219 
220 	errno = err;
221 	return errno ? -1 : 0;
222 }
223 
ntfs_attr_setup_flag(ntfs_inode * ni)224 static int ntfs_attr_setup_flag(ntfs_inode *ni)
225 {
226 	STANDARD_INFORMATION *si;
227 	s64 lth;
228 	int r;
229 
230 	si = (STANDARD_INFORMATION*)ntfs_attr_readall(ni,
231 			AT_STANDARD_INFORMATION, AT_UNNAMED, 0, &lth);
232 	if (si) {
233 		if ((u64)lth >= offsetof(STANDARD_INFORMATION, owner_id))
234 			ni->flags = si->file_attributes;
235 		free(si);
236 		r = 0;
237 	} else {
238 		ntfs_log_error("Failed to get standard information of $MFT\n");
239 		r = -1;
240 	}
241 	return (r);
242 }
243 
244 /**
245  * ntfs_mft_load - load the $MFT and setup the ntfs volume with it
246  * @vol:	ntfs volume whose $MFT to load
247  *
248  * Load $MFT from @vol and setup @vol with it. After calling this function the
249  * volume @vol is ready for use by all read access functions provided by the
250  * ntfs library.
251  *
252  * Return 0 on success and -1 on error with errno set to the error code.
253  */
ntfs_mft_load(ntfs_volume * vol)254 static int ntfs_mft_load(ntfs_volume *vol)
255 {
256 	VCN next_vcn, last_vcn, highest_vcn;
257 	s64 l;
258 	MFT_RECORD *mb = NULL;
259 	ntfs_attr_search_ctx *ctx = NULL;
260 	ATTR_RECORD *a;
261 	int eo;
262 
263 	/* Manually setup an ntfs_inode. */
264 	vol->mft_ni = ntfs_inode_allocate(vol);
265 	mb = ntfs_malloc(vol->mft_record_size);
266 	if (!vol->mft_ni || !mb) {
267 		ntfs_log_perror("Error allocating memory for $MFT");
268 		goto error_exit;
269 	}
270 	vol->mft_ni->mft_no = 0;
271 	vol->mft_ni->mrec = mb;
272 	/* Can't use any of the higher level functions yet! */
273 	l = ntfs_mst_pread(vol->dev, vol->mft_lcn << vol->cluster_size_bits, 1,
274 			vol->mft_record_size, mb);
275 	if (l != 1) {
276 		if (l != -1)
277 			errno = EIO;
278 		ntfs_log_perror("Error reading $MFT");
279 		goto error_exit;
280 	}
281 
282 	if (ntfs_mft_record_check(vol, 0, mb))
283 		goto error_exit;
284 
285 	ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
286 	if (!ctx)
287 		goto error_exit;
288 
289 	/* Find the $ATTRIBUTE_LIST attribute in $MFT if present. */
290 	if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
291 			ctx)) {
292 		if (errno != ENOENT) {
293 			ntfs_log_error("$MFT has corrupt attribute list.\n");
294 			goto io_error_exit;
295 		}
296 		goto mft_has_no_attr_list;
297 	}
298 	NInoSetAttrList(vol->mft_ni);
299 	l = ntfs_get_attribute_value_length(ctx->attr);
300 	if (l <= 0 || l > 0x40000) {
301 		ntfs_log_error("$MFT/$ATTR_LIST invalid length (%lld).\n",
302 			       (long long)l);
303 		goto io_error_exit;
304 	}
305 	vol->mft_ni->attr_list_size = l;
306 	vol->mft_ni->attr_list = ntfs_malloc(l);
307 	if (!vol->mft_ni->attr_list)
308 		goto error_exit;
309 
310 	l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
311 	if (!l) {
312 		ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
313 		goto io_error_exit;
314 	}
315 	if ((l != vol->mft_ni->attr_list_size)
316 	    || (l < (s64)offsetof(ATTR_LIST_ENTRY, name))) {
317 		ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
318 				"%u or < %d).\n", (long long)l,
319 				vol->mft_ni->attr_list_size,
320 				(int)offsetof(ATTR_LIST_ENTRY, name));
321 		goto io_error_exit;
322 	}
323 
324 mft_has_no_attr_list:
325 
326 	if (ntfs_attr_setup_flag(vol->mft_ni))
327 		goto error_exit;
328 
329 	/* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
330 
331 	/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
332 	vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
333 	if (!vol->mft_na) {
334 		ntfs_log_perror("Failed to open ntfs attribute");
335 		goto error_exit;
336 	}
337 	/* Read all extents from the $DATA attribute in $MFT. */
338 	ntfs_attr_reinit_search_ctx(ctx);
339 	last_vcn = vol->mft_na->allocated_size >> vol->cluster_size_bits;
340 	highest_vcn = next_vcn = 0;
341 	a = NULL;
342 	while (!ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, next_vcn, NULL, 0,
343 			ctx)) {
344 		runlist_element *nrl;
345 
346 		a = ctx->attr;
347 		/* $MFT must be non-resident. */
348 		if (!a->non_resident) {
349 			ntfs_log_error("$MFT must be non-resident.\n");
350 			goto io_error_exit;
351 		}
352 		/* $MFT must be uncompressed and unencrypted. */
353 		if (a->flags & ATTR_COMPRESSION_MASK ||
354 				a->flags & ATTR_IS_ENCRYPTED) {
355 			ntfs_log_error("$MFT must be uncompressed and "
356 				       "unencrypted.\n");
357 			goto io_error_exit;
358 		}
359 		/*
360 		 * Decompress the mapping pairs array of this extent and merge
361 		 * the result into the existing runlist. No need for locking
362 		 * as we have exclusive access to the inode at this time and we
363 		 * are a mount in progress task, too.
364 		 */
365 		nrl = ntfs_mapping_pairs_decompress(vol, a, vol->mft_na->rl);
366 		if (!nrl) {
367 			ntfs_log_perror("ntfs_mapping_pairs_decompress() failed");
368 			goto error_exit;
369 		}
370 		/* Make sure $DATA is the MFT itself */
371 		if (nrl->lcn != vol->mft_lcn) {
372 			ntfs_log_perror("The MFT is not self-contained");
373 			goto error_exit;
374 		}
375 		vol->mft_na->rl = nrl;
376 
377 		/* Get the lowest vcn for the next extent. */
378 		highest_vcn = sle64_to_cpu(a->highest_vcn);
379 		next_vcn = highest_vcn + 1;
380 
381 		/* Only one extent or error, which we catch below. */
382 		if (next_vcn <= 0)
383 			break;
384 
385 		/* Avoid endless loops due to corruption. */
386 		if (next_vcn < sle64_to_cpu(a->lowest_vcn)) {
387 			ntfs_log_error("$MFT has corrupt attribute list.\n");
388 			goto io_error_exit;
389 		}
390 	}
391 	if (!a) {
392 		ntfs_log_error("$MFT/$DATA attribute not found.\n");
393 		goto io_error_exit;
394 	}
395 	if (highest_vcn && highest_vcn != last_vcn - 1) {
396 		ntfs_log_error("Failed to load runlist for $MFT/$DATA.\n");
397 		ntfs_log_error("highest_vcn = 0x%llx, last_vcn - 1 = 0x%llx\n",
398 			       (long long)highest_vcn, (long long)last_vcn - 1);
399 		goto io_error_exit;
400 	}
401 	/* Done with the $Mft mft record. */
402 	ntfs_attr_put_search_ctx(ctx);
403 	ctx = NULL;
404 
405 	/* Update the size fields in the inode. */
406 	vol->mft_ni->data_size = vol->mft_na->data_size;
407 	vol->mft_ni->allocated_size = vol->mft_na->allocated_size;
408 	set_nino_flag(vol->mft_ni, KnownSize);
409 
410 	/*
411 	 * The volume is now setup so we can use all read access functions.
412 	 */
413 	vol->mftbmp_na = ntfs_attr_open(vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
414 	if (!vol->mftbmp_na) {
415 		ntfs_log_perror("Failed to open $MFT/$BITMAP");
416 		goto error_exit;
417 	}
418 	return 0;
419 io_error_exit:
420 	errno = EIO;
421 error_exit:
422 	eo = errno;
423 	if (ctx)
424 		ntfs_attr_put_search_ctx(ctx);
425 	if (vol->mft_na) {
426 		ntfs_attr_close(vol->mft_na);
427 		vol->mft_na = NULL;
428 	}
429 	if (vol->mft_ni) {
430 		ntfs_inode_close(vol->mft_ni);
431 		vol->mft_ni = NULL;
432 	}
433 	errno = eo;
434 	return -1;
435 }
436 
437 /**
438  * ntfs_mftmirr_load - load the $MFTMirr and setup the ntfs volume with it
439  * @vol:	ntfs volume whose $MFTMirr to load
440  *
441  * Load $MFTMirr from @vol and setup @vol with it. After calling this function
442  * the volume @vol is ready for use by all write access functions provided by
443  * the ntfs library (assuming ntfs_mft_load() has been called successfully
444  * beforehand).
445  *
446  * Return 0 on success and -1 on error with errno set to the error code.
447  */
ntfs_mftmirr_load(ntfs_volume * vol)448 static int ntfs_mftmirr_load(ntfs_volume *vol)
449 {
450 	int err;
451 
452 	vol->mftmirr_ni = ntfs_inode_open(vol, FILE_MFTMirr);
453 	if (!vol->mftmirr_ni) {
454 		ntfs_log_perror("Failed to open inode $MFTMirr");
455 		return -1;
456 	}
457 
458 	vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
459 	if (!vol->mftmirr_na) {
460 		ntfs_log_perror("Failed to open $MFTMirr/$DATA");
461 		goto error_exit;
462 	}
463 
464 	if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
465 		ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
466 		goto error_exit;
467 	}
468 	if (vol->mftmirr_na->rl->lcn != vol->mftmirr_lcn) {
469 		ntfs_log_error("Bad $MFTMirr lcn 0x%llx, want 0x%llx\n",
470 				(long long)vol->mftmirr_na->rl->lcn,
471 				(long long)vol->mftmirr_lcn);
472 		goto error_exit;
473 	}
474 
475 	return 0;
476 
477 error_exit:
478 	err = errno;
479 	if (vol->mftmirr_na) {
480 		ntfs_attr_close(vol->mftmirr_na);
481 		vol->mftmirr_na = NULL;
482 	}
483 	ntfs_inode_close(vol->mftmirr_ni);
484 	vol->mftmirr_ni = NULL;
485 	errno = err;
486 	return -1;
487 }
488 
489 /**
490  * ntfs_volume_startup - allocate and setup an ntfs volume
491  * @dev:	device to open
492  * @flags:	optional mount flags
493  *
494  * Load, verify, and parse bootsector; load and setup $MFT and $MFTMirr. After
495  * calling this function, the volume is setup sufficiently to call all read
496  * and write access functions provided by the library.
497  *
498  * Return the allocated volume structure on success and NULL on error with
499  * errno set to the error code.
500  */
ntfs_volume_startup(struct ntfs_device * dev,ntfs_mount_flags flags)501 ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
502 		ntfs_mount_flags flags)
503 {
504 	LCN mft_zone_size, mft_lcn;
505 	s64 br;
506 	ntfs_volume *vol;
507 	NTFS_BOOT_SECTOR *bs;
508 	int eo;
509 
510 	if (!dev || !dev->d_ops || !dev->d_name) {
511 		errno = EINVAL;
512 		ntfs_log_perror("%s: dev = %p", __FUNCTION__, dev);
513 		return NULL;
514 	}
515 
516 	bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
517 	if (!bs)
518 		return NULL;
519 
520 	/* Allocate the volume structure. */
521 	vol = ntfs_volume_alloc();
522 	if (!vol)
523 		goto error_exit;
524 
525 	/* Create the default upcase table. */
526 	vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
527 	if (!vol->upcase_len || !vol->upcase)
528 		goto error_exit;
529 
530 	/* Default with no locase table and case sensitive file names */
531 	vol->locase = (ntfschar*)NULL;
532 	NVolSetCaseSensitive(vol);
533 
534 		/* by default, all files are shown and not marked hidden */
535 	NVolSetShowSysFiles(vol);
536 	NVolSetShowHidFiles(vol);
537 	NVolClearHideDotFiles(vol);
538 		/* set default compression */
539 #if DEFAULT_COMPRESSION
540 	NVolSetCompression(vol);
541 #else
542 	NVolClearCompression(vol);
543 #endif
544 	if (flags & NTFS_MNT_RDONLY)
545 		NVolSetReadOnly(vol);
546 
547 	/* ...->open needs bracketing to compile with glibc 2.7 */
548 	if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
549 		if (!NVolReadOnly(vol) && (errno == EROFS)) {
550 			if ((dev->d_ops->open)(dev, O_RDONLY)) {
551 				ntfs_log_perror("Error opening read-only '%s'",
552 						dev->d_name);
553 				goto error_exit;
554 			} else {
555 				ntfs_log_info("Error opening '%s' read-write\n",
556 						dev->d_name);
557 				NVolSetReadOnly(vol);
558 			}
559 		} else {
560 			ntfs_log_perror("Error opening '%s'", dev->d_name);
561 			goto error_exit;
562 		}
563 	}
564 	/* Attach the device to the volume. */
565 	vol->dev = dev;
566 
567 	/* Now read the bootsector. */
568 	br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
569 	if (br != sizeof(NTFS_BOOT_SECTOR)) {
570 		if (br != -1)
571 			errno = EINVAL;
572 		if (!br)
573 			ntfs_log_error("Failed to read bootsector (size=0)\n");
574 		else
575 			ntfs_log_perror("Error reading bootsector");
576 		goto error_exit;
577 	}
578 	if (!ntfs_boot_sector_is_ntfs(bs)) {
579 		errno = EINVAL;
580 		goto error_exit;
581 	}
582 	if (ntfs_boot_sector_parse(vol, bs) < 0)
583 		goto error_exit;
584 
585 	free(bs);
586 	bs = NULL;
587 	/* Now set the device block size to the sector size. */
588 	if (ntfs_device_block_size_set(vol->dev, vol->sector_size))
589 		ntfs_log_debug("Failed to set the device block size to the "
590 				"sector size.  This may affect performance "
591 				"but should be harmless otherwise.  Error: "
592 				"%s\n", strerror(errno));
593 
594 	/* We now initialize the cluster allocator. */
595 	vol->full_zones = 0;
596 	mft_zone_size = vol->nr_clusters >> 3;      /* 12.5% */
597 
598 	/* Setup the mft zone. */
599 	vol->mft_zone_start = vol->mft_zone_pos = vol->mft_lcn;
600 	ntfs_log_debug("mft_zone_pos = 0x%llx\n", (long long)vol->mft_zone_pos);
601 
602 	/*
603 	 * Calculate the mft_lcn for an unmodified NTFS volume (see mkntfs
604 	 * source) and if the actual mft_lcn is in the expected place or even
605 	 * further to the front of the volume, extend the mft_zone to cover the
606 	 * beginning of the volume as well. This is in order to protect the
607 	 * area reserved for the mft bitmap as well within the mft_zone itself.
608 	 * On non-standard volumes we don't protect it as the overhead would be
609 	 * higher than the speed increase we would get by doing it.
610 	 */
611 	mft_lcn = (8192 + 2 * vol->cluster_size - 1) / vol->cluster_size;
612 	if (mft_lcn * vol->cluster_size < 16 * 1024)
613 		mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
614 				vol->cluster_size;
615 	if (vol->mft_zone_start <= mft_lcn)
616 		vol->mft_zone_start = 0;
617 	ntfs_log_debug("mft_zone_start = 0x%llx\n", (long long)vol->mft_zone_start);
618 
619 	/*
620 	 * Need to cap the mft zone on non-standard volumes so that it does
621 	 * not point outside the boundaries of the volume. We do this by
622 	 * halving the zone size until we are inside the volume.
623 	 */
624 	vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
625 	while (vol->mft_zone_end >= vol->nr_clusters) {
626 		mft_zone_size >>= 1;
627 		if (!mft_zone_size) {
628 			errno = EINVAL;
629 			goto error_exit;
630 		}
631 		vol->mft_zone_end = vol->mft_lcn + mft_zone_size;
632 	}
633 	ntfs_log_debug("mft_zone_end = 0x%llx\n", (long long)vol->mft_zone_end);
634 
635 	/*
636 	 * Set the current position within each data zone to the start of the
637 	 * respective zone.
638 	 */
639 	vol->data1_zone_pos = vol->mft_zone_end;
640 	ntfs_log_debug("data1_zone_pos = %lld\n", (long long)vol->data1_zone_pos);
641 	vol->data2_zone_pos = 0;
642 	ntfs_log_debug("data2_zone_pos = %lld\n", (long long)vol->data2_zone_pos);
643 
644 	/* Set the mft data allocation position to mft record 24. */
645 	vol->mft_data_pos = 24;
646 
647 	/*
648 	 * The cluster allocator is now fully operational.
649 	 */
650 
651 	/* Need to setup $MFT so we can use the library read functions. */
652 	if (ntfs_mft_load(vol) < 0) {
653 		ntfs_log_perror("Failed to load $MFT");
654 		goto error_exit;
655 	}
656 
657 	/* Need to setup $MFTMirr so we can use the write functions, too. */
658 	if (ntfs_mftmirr_load(vol) < 0) {
659 		ntfs_log_perror("Failed to load $MFTMirr");
660 		goto error_exit;
661 	}
662 	return vol;
663 error_exit:
664 	eo = errno;
665 	free(bs);
666 	if (vol)
667 		__ntfs_volume_release(vol);
668 	errno = eo;
669 	return NULL;
670 }
671 
672 /**
673  * ntfs_volume_check_logfile - check logfile on target volume
674  * @vol:	volume on which to check logfile
675  *
676  * Return 0 on success and -1 on error with errno set error code.
677  */
ntfs_volume_check_logfile(ntfs_volume * vol)678 static int ntfs_volume_check_logfile(ntfs_volume *vol)
679 {
680 	ntfs_inode *ni;
681 	ntfs_attr *na = NULL;
682 	RESTART_PAGE_HEADER *rp = NULL;
683 	int err = 0;
684 
685 	ni = ntfs_inode_open(vol, FILE_LogFile);
686 	if (!ni) {
687 		ntfs_log_perror("Failed to open inode FILE_LogFile");
688 		errno = EIO;
689 		return -1;
690 	}
691 
692 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
693 	if (!na) {
694 		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
695 		err = EIO;
696 		goto out;
697 	}
698 
699 	if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
700 		err = EOPNOTSUPP;
701 		/*
702 		 * If the latest restart page was identified as version
703 		 * 2.0, then Windows may have kept a cached copy of
704 		 * metadata for fast restarting, and we should not mount.
705 		 * Hibernation will be seen the same way on a non
706 		 * Windows-system partition, so we have to use the same
707 		 * error code (EPERM).
708 		 * The restart page may also be identified as version 2.0
709 		 * when access to the file system is terminated abruptly
710 		 * by unplugging or power cut, so mounting is also rejected
711 		 * after such an event.
712 		 */
713 	if (rp
714 	    && (rp->major_ver == const_cpu_to_le16(2))
715 	    && (rp->minor_ver == const_cpu_to_le16(0))) {
716 		ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n");
717 		err = EPERM;
718 	}
719 	free(rp);
720 	ntfs_attr_close(na);
721 out:
722 	if (ntfs_inode_close(ni))
723 		ntfs_error_set(&err);
724 	if (err) {
725 		errno = err;
726 		return -1;
727 	}
728 	return 0;
729 }
730 
731 /**
732  * ntfs_hiberfile_open - Find and open '/hiberfil.sys'
733  * @vol:    An ntfs volume obtained from ntfs_mount
734  *
735  * Return:  inode  Success, hiberfil.sys is valid
736  *	    NULL   hiberfil.sys doesn't exist or some other error occurred
737  */
ntfs_hiberfile_open(ntfs_volume * vol)738 static ntfs_inode *ntfs_hiberfile_open(ntfs_volume *vol)
739 {
740 	u64 inode;
741 	ntfs_inode *ni_root;
742 	ntfs_inode *ni_hibr = NULL;
743 	ntfschar   *unicode = NULL;
744 	int unicode_len;
745 	const char *hiberfile = "hiberfil.sys";
746 
747 	if (!vol) {
748 		errno = EINVAL;
749 		return NULL;
750 	}
751 
752 	ni_root = ntfs_inode_open(vol, FILE_root);
753 	if (!ni_root) {
754 		ntfs_log_debug("Couldn't open the root directory.\n");
755 		return NULL;
756 	}
757 
758 	unicode_len = ntfs_mbstoucs(hiberfile, &unicode);
759 	if (unicode_len < 0) {
760 		ntfs_log_perror("Couldn't convert 'hiberfil.sys' to Unicode");
761 		goto out;
762 	}
763 
764 	inode = ntfs_inode_lookup_by_name(ni_root, unicode, unicode_len);
765 	if (inode == (u64)-1) {
766 		ntfs_log_debug("Couldn't find file '%s'.\n", hiberfile);
767 		goto out;
768 	}
769 
770 	inode = MREF(inode);
771 	ni_hibr = ntfs_inode_open(vol, inode);
772 	if (!ni_hibr) {
773 		ntfs_log_debug("Couldn't open inode %lld.\n", (long long)inode);
774 		goto out;
775 	}
776 out:
777 	if (ntfs_inode_close(ni_root)) {
778 		ntfs_inode_close(ni_hibr);
779 		ni_hibr = NULL;
780 	}
781 	free(unicode);
782 	return ni_hibr;
783 }
784 
785 
786 #define NTFS_HIBERFILE_HEADER_SIZE	4096
787 
788 /**
789  * ntfs_volume_check_hiberfile - check hiberfil.sys whether Windows is
790  *                               hibernated on the target volume
791  * @vol:    volume on which to check hiberfil.sys
792  *
793  * Return:  0 if Windows isn't hibernated for sure
794  *         -1 otherwise and errno is set to the appropriate value
795  */
ntfs_volume_check_hiberfile(ntfs_volume * vol,int verbose)796 int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose)
797 {
798 	ntfs_inode *ni;
799 	ntfs_attr *na = NULL;
800 	int bytes_read, err;
801 	char *buf = NULL;
802 
803 	ni = ntfs_hiberfile_open(vol);
804 	if (!ni) {
805 		if (errno == ENOENT)
806 			return 0;
807 		return -1;
808 	}
809 
810 	buf = ntfs_malloc(NTFS_HIBERFILE_HEADER_SIZE);
811 	if (!buf)
812 		goto out;
813 
814 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
815 	if (!na) {
816 		ntfs_log_perror("Failed to open hiberfil.sys data attribute");
817 		goto out;
818 	}
819 
820 	bytes_read = ntfs_attr_pread(na, 0, NTFS_HIBERFILE_HEADER_SIZE, buf);
821 	if (bytes_read == -1) {
822 		ntfs_log_perror("Failed to read hiberfil.sys");
823 		goto out;
824 	}
825 	if (bytes_read < NTFS_HIBERFILE_HEADER_SIZE) {
826 		if (verbose)
827 			ntfs_log_error("Hibernated non-system partition, "
828 				       "refused to mount.\n");
829 		errno = EPERM;
830 		goto out;
831 	}
832 	if ((memcmp(buf, "hibr", 4) == 0)
833 	   ||  (memcmp(buf, "HIBR", 4) == 0)) {
834 		if (verbose)
835 			ntfs_log_error("Windows is hibernated, refused to mount.\n");
836 		errno = EPERM;
837 		goto out;
838 	}
839         /* All right, all header bytes are zero */
840 	errno = 0;
841 out:
842 	if (na)
843 		ntfs_attr_close(na);
844 	free(buf);
845 	err = errno;
846 	if (ntfs_inode_close(ni))
847 		ntfs_error_set(&err);
848 	errno = err;
849 	return errno ? -1 : 0;
850 }
851 
852 /*
853  *		Make sure a LOGGED_UTILITY_STREAM attribute named "$TXF_DATA"
854  *	on the root directory is resident.
855  *	When it is non-resident, the partition cannot be mounted on Vista
856  *	(see http://support.microsoft.com/kb/974729)
857  *
858  *	We take care to avoid this situation, however this can be a
859  *	consequence of having used an older version (including older
860  *	Windows version), so we had better fix it.
861  *
862  *	Returns 0 if unneeded or successful
863  *		-1 if there was an error, explained by errno
864  */
865 
fix_txf_data(ntfs_volume * vol)866 static int fix_txf_data(ntfs_volume *vol)
867 {
868 	void *txf_data;
869 	s64 txf_data_size;
870 	ntfs_inode *ni;
871 	ntfs_attr *na;
872 	int res;
873 
874 	res = 0;
875 	ntfs_log_debug("Loading root directory\n");
876 	ni = ntfs_inode_open(vol, FILE_root);
877 	if (!ni) {
878 		ntfs_log_perror("Failed to open root directory");
879 		res = -1;
880 	} else {
881 		/* Get the $TXF_DATA attribute */
882 		na = ntfs_attr_open(ni, AT_LOGGED_UTILITY_STREAM, TXF_DATA, 9);
883 		if (na) {
884 			if (NAttrNonResident(na)) {
885 				/*
886 				 * Fix the attribute by truncating, then
887 				 * rewriting it.
888 				 */
889 				ntfs_log_debug("Making $TXF_DATA resident\n");
890 				txf_data = ntfs_attr_readall(ni,
891 						AT_LOGGED_UTILITY_STREAM,
892 						TXF_DATA, 9, &txf_data_size);
893 				if (txf_data) {
894 					if (ntfs_attr_truncate(na, 0)
895 					    || (ntfs_attr_pwrite(na, 0,
896 						 txf_data_size, txf_data)
897 							!= txf_data_size))
898 						res = -1;
899 					free(txf_data);
900 				}
901 			if (res)
902 				ntfs_log_error("Failed to make $TXF_DATA resident\n");
903 			else
904 				ntfs_log_error("$TXF_DATA made resident\n");
905 			}
906 			ntfs_attr_close(na);
907 		}
908 		if (ntfs_inode_close(ni)) {
909 			ntfs_log_perror("Failed to close root");
910 			res = -1;
911 		}
912 	}
913 	return (res);
914 }
915 
916 /**
917  * ntfs_device_mount - open ntfs volume
918  * @dev:	device to open
919  * @flags:	optional mount flags
920  *
921  * This function mounts an ntfs volume. @dev should describe the device which
922  * to mount as the ntfs volume.
923  *
924  * @flags is an optional second parameter. The same flags are used as for
925  * the mount system call (man 2 mount). Currently only the following flag
926  * is implemented:
927  *	NTFS_MNT_RDONLY	- mount volume read-only
928  *
929  * The function opens the device @dev and verifies that it contains a valid
930  * bootsector. Then, it allocates an ntfs_volume structure and initializes
931  * some of the values inside the structure from the information stored in the
932  * bootsector. It proceeds to load the necessary system files and completes
933  * setting up the structure.
934  *
935  * Return the allocated volume structure on success and NULL on error with
936  * errno set to the error code.
937  */
ntfs_device_mount(struct ntfs_device * dev,ntfs_mount_flags flags)938 ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
939 {
940 	s64 l;
941 	ntfs_volume *vol;
942 	u8 *m = NULL, *m2 = NULL;
943 	ntfs_attr_search_ctx *ctx = NULL;
944 	ntfs_inode *ni;
945 	ntfs_attr *na;
946 	ATTR_RECORD *a;
947 	VOLUME_INFORMATION *vinf;
948 	ntfschar *vname;
949 	u32 record_size;
950 	int i, j, eo;
951 	unsigned int k;
952 	u32 u;
953 	BOOL need_fallback_ro;
954 
955 	need_fallback_ro = FALSE;
956 	vol = ntfs_volume_startup(dev, flags);
957 	if (!vol)
958 		return NULL;
959 
960 	/* Load data from $MFT and $MFTMirr and compare the contents. */
961 	m  = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
962 	m2 = ntfs_malloc(vol->mftmirr_size << vol->mft_record_size_bits);
963 	if (!m || !m2)
964 		goto error_exit;
965 
966 	l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size,
967 			vol->mft_record_size, m);
968 	if (l != vol->mftmirr_size) {
969 		if (l == -1)
970 			ntfs_log_perror("Failed to read $MFT");
971 		else {
972 			ntfs_log_error("Failed to read $MFT, unexpected length "
973 				       "(%lld != %d).\n", (long long)l,
974 				       vol->mftmirr_size);
975 			errno = EIO;
976 		}
977 		goto error_exit;
978 	}
979 	for (i = 0; (i < l) && (i < FILE_first_user); ++i)
980 		if (ntfs_mft_record_check(vol, FILE_MFT + i,
981 				(MFT_RECORD*)(m + i*vol->mft_record_size)))
982 			goto error_exit;
983 	l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size,
984 			vol->mft_record_size, m2);
985 	if (l != vol->mftmirr_size) {
986 		if (l == -1) {
987 			ntfs_log_perror("Failed to read $MFTMirr");
988 			goto error_exit;
989 		}
990 		vol->mftmirr_size = l;
991 	}
992 	for (i = 0; (i < l) && (i < FILE_first_user); ++i)
993 		if (ntfs_mft_record_check(vol, FILE_MFT + i,
994 				(MFT_RECORD*)(m2 + i*vol->mft_record_size)))
995 			goto error_exit;
996 	ntfs_log_debug("Comparing $MFTMirr to $MFT...\n");
997 		/* Windows 10 does not update the full $MFTMirr any more */
998 	for (i = 0; (i < vol->mftmirr_size) && (i < FILE_first_user); ++i) {
999 		MFT_RECORD *mrec, *mrec2;
1000 		const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile",
1001 			"$Volume", "$AttrDef", "root directory", "$Bitmap",
1002 			"$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" };
1003 		const char *s;
1004 
1005 		if (i < 12)
1006 			s = ESTR[i];
1007 		else if (i < 16)
1008 			s = "system file";
1009 		else
1010 			s = "mft record";
1011 
1012 		mrec = (MFT_RECORD*)(m + i * vol->mft_record_size);
1013 		if (mrec->flags & MFT_RECORD_IN_USE) {
1014 			if (ntfs_is_baad_record(mrec->magic)) {
1015 				ntfs_log_error("$MFT error: Incomplete multi "
1016 					       "sector transfer detected in "
1017 					       "'%s'.\n", s);
1018 				goto io_error_exit;
1019 			}
1020 			if (!ntfs_is_mft_record(mrec->magic)) {
1021 				ntfs_log_error("$MFT error: Invalid mft "
1022 						"record for '%s'.\n", s);
1023 				goto io_error_exit;
1024 			}
1025 		}
1026 		mrec2 = (MFT_RECORD*)(m2 + i * vol->mft_record_size);
1027 		if (mrec2->flags & MFT_RECORD_IN_USE) {
1028 			if (ntfs_is_baad_record(mrec2->magic)) {
1029 				ntfs_log_error("$MFTMirr error: Incomplete "
1030 						"multi sector transfer "
1031 						"detected in '%s'.\n", s);
1032 				goto io_error_exit;
1033 			}
1034 			if (!ntfs_is_mft_record(mrec2->magic)) {
1035 				ntfs_log_error("$MFTMirr error: Invalid mft "
1036 						"record for '%s'.\n", s);
1037 				goto io_error_exit;
1038 			}
1039 		}
1040 		record_size = ntfs_mft_record_get_data_size(mrec);
1041 		if ((record_size <= sizeof(MFT_RECORD))
1042 		    || (record_size > vol->mft_record_size)
1043 		    || memcmp(mrec, mrec2, record_size)) {
1044 			ntfs_log_error("$MFTMirr does not match $MFT (record "
1045 				       "%d).\n", i);
1046 			goto io_error_exit;
1047 		}
1048 	}
1049 
1050 	free(m2);
1051 	free(m);
1052 	m = m2 = NULL;
1053 
1054 	/* Now load the bitmap from $Bitmap. */
1055 	ntfs_log_debug("Loading $Bitmap...\n");
1056 	vol->lcnbmp_ni = ntfs_inode_open(vol, FILE_Bitmap);
1057 	if (!vol->lcnbmp_ni) {
1058 		ntfs_log_perror("Failed to open inode FILE_Bitmap");
1059 		goto error_exit;
1060 	}
1061 
1062 	vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
1063 	if (!vol->lcnbmp_na) {
1064 		ntfs_log_perror("Failed to open ntfs attribute");
1065 		goto error_exit;
1066 	}
1067 
1068 	if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
1069 		ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
1070 				(long long)vol->lcnbmp_na->data_size,
1071 				(long long)vol->lcnbmp_na->allocated_size);
1072 		goto io_error_exit;
1073 	}
1074 
1075 	/* Now load the upcase table from $UpCase. */
1076 	ntfs_log_debug("Loading $UpCase...\n");
1077 	ni = ntfs_inode_open(vol, FILE_UpCase);
1078 	if (!ni) {
1079 		ntfs_log_perror("Failed to open inode FILE_UpCase");
1080 		goto error_exit;
1081 	}
1082 	/* Get an ntfs attribute for $UpCase/$DATA. */
1083 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1084 	if (!na) {
1085 		ntfs_log_perror("Failed to open ntfs attribute");
1086 		ntfs_inode_close(ni);
1087 		goto error_exit;
1088 	}
1089 	/*
1090 	 * Note: Normally, the upcase table has a length equal to 65536
1091 	 * 2-byte Unicode characters. Anyway we currently can only process
1092 	 * such characters.
1093 	 */
1094 	if ((na->data_size - 2) & ~0x1fffeULL) {
1095 		ntfs_log_error("Error: Upcase table is invalid (want size even "
1096 				"<= 131072).\n");
1097 		errno = EINVAL;
1098 		goto bad_upcase;
1099 	}
1100 	if (vol->upcase_len != na->data_size >> 1) {
1101 		vol->upcase_len = na->data_size >> 1;
1102 		/* Throw away default table. */
1103 		free(vol->upcase);
1104 		vol->upcase = ntfs_malloc(na->data_size);
1105 		if (!vol->upcase)
1106 			goto bad_upcase;
1107 	}
1108 	/* Read in the $DATA attribute value into the buffer. */
1109 	l = ntfs_attr_pread(na, 0, na->data_size, vol->upcase);
1110 	if (l != na->data_size) {
1111 		ntfs_log_error("Failed to read $UpCase, unexpected length "
1112 			       "(%lld != %lld).\n", (long long)l,
1113 			       (long long)na->data_size);
1114 		errno = EIO;
1115 		goto bad_upcase;
1116 	}
1117 	/* Done with the $UpCase mft record. */
1118 	ntfs_attr_close(na);
1119 	if (ntfs_inode_close(ni)) {
1120 		ntfs_log_perror("Failed to close $UpCase");
1121 		goto error_exit;
1122 	}
1123 	/* Consistency check of $UpCase, restricted to plain ASCII chars */
1124 	k = 0x20;
1125 	while ((k < vol->upcase_len)
1126 	    && (k < 0x7f)
1127 	    && (le16_to_cpu(vol->upcase[k])
1128 			== ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
1129 		k++;
1130 	if (k < 0x7f) {
1131 		ntfs_log_error("Corrupted file $UpCase\n");
1132 		goto io_error_exit;
1133 	}
1134 
1135 	/*
1136 	 * Now load $Volume and set the version information and flags in the
1137 	 * vol structure accordingly.
1138 	 */
1139 	ntfs_log_debug("Loading $Volume...\n");
1140 	vol->vol_ni = ntfs_inode_open(vol, FILE_Volume);
1141 	if (!vol->vol_ni) {
1142 		ntfs_log_perror("Failed to open inode FILE_Volume");
1143 		goto error_exit;
1144 	}
1145 	/* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */
1146 	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
1147 	if (!ctx)
1148 		goto error_exit;
1149 
1150 	/* Find the $VOLUME_INFORMATION attribute. */
1151 	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
1152 			0, ctx)) {
1153 		ntfs_log_perror("$VOLUME_INFORMATION attribute not found in "
1154 				"$Volume");
1155 		goto error_exit;
1156 	}
1157 	a = ctx->attr;
1158 	/* Has to be resident. */
1159 	if (a->non_resident) {
1160 		ntfs_log_error("Attribute $VOLUME_INFORMATION must be "
1161 			       "resident but it isn't.\n");
1162 		errno = EIO;
1163 		goto error_exit;
1164 	}
1165 	/* Get a pointer to the value of the attribute. */
1166 	vinf = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
1167 	/* Sanity checks. */
1168 	if ((char*)vinf + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
1169 			le32_to_cpu(ctx->mrec->bytes_in_use) ||
1170 			le16_to_cpu(a->value_offset) + le32_to_cpu(
1171 			a->value_length) > le32_to_cpu(a->length)) {
1172 		ntfs_log_error("$VOLUME_INFORMATION in $Volume is corrupt.\n");
1173 		errno = EIO;
1174 		goto error_exit;
1175 	}
1176 	/* Setup vol from the volume information attribute value. */
1177 	vol->major_ver = vinf->major_ver;
1178 	vol->minor_ver = vinf->minor_ver;
1179 	/* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are
1180 	   defined using cpu_to_le16() macro and hence are consistent. */
1181 	vol->flags = vinf->flags;
1182 	/*
1183 	 * Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.
1184 	 */
1185 	ntfs_attr_reinit_search_ctx(ctx);
1186 	if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
1187 			ctx)) {
1188 		if (errno != ENOENT) {
1189 			ntfs_log_perror("Failed to lookup of $VOLUME_NAME in "
1190 					"$Volume failed");
1191 			goto error_exit;
1192 		}
1193 		/*
1194 		 * Attribute not present.  This has been seen in the field.
1195 		 * Treat this the same way as if the attribute was present but
1196 		 * had zero length.
1197 		 */
1198 		vol->vol_name = ntfs_malloc(1);
1199 		if (!vol->vol_name)
1200 			goto error_exit;
1201 		vol->vol_name[0] = '\0';
1202 	} else {
1203 		a = ctx->attr;
1204 		/* Has to be resident. */
1205 		if (a->non_resident) {
1206 			ntfs_log_error("$VOLUME_NAME must be resident.\n");
1207 			errno = EIO;
1208 			goto error_exit;
1209 		}
1210 		/* Get a pointer to the value of the attribute. */
1211 		vname = (ntfschar*)(le16_to_cpu(a->value_offset) + (char*)a);
1212 		u = le32_to_cpu(a->value_length) / 2;
1213 		/*
1214 		 * Convert Unicode volume name to current locale multibyte
1215 		 * format.
1216 		 */
1217 		vol->vol_name = NULL;
1218 		if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
1219 			ntfs_log_perror("Volume name could not be converted "
1220 					"to current locale");
1221 			ntfs_log_debug("Forcing name into ASCII by replacing "
1222 				"non-ASCII characters with underscores.\n");
1223 			vol->vol_name = ntfs_malloc(u + 1);
1224 			if (!vol->vol_name)
1225 				goto error_exit;
1226 
1227 			for (j = 0; j < (s32)u; j++) {
1228 				u16 uc = le16_to_cpu(vname[j]);
1229 				if (uc > 0xff)
1230 					uc = (u16)'_';
1231 				vol->vol_name[j] = (char)uc;
1232 			}
1233 			vol->vol_name[u] = '\0';
1234 		}
1235 	}
1236 	ntfs_attr_put_search_ctx(ctx);
1237 	ctx = NULL;
1238 	/* Now load the attribute definitions from $AttrDef. */
1239 	ntfs_log_debug("Loading $AttrDef...\n");
1240 	ni = ntfs_inode_open(vol, FILE_AttrDef);
1241 	if (!ni) {
1242 		ntfs_log_perror("Failed to open $AttrDef");
1243 		goto error_exit;
1244 	}
1245 	/* Get an ntfs attribute for $AttrDef/$DATA. */
1246 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1247 	if (!na) {
1248 		ntfs_log_perror("Failed to open ntfs attribute");
1249 		goto error_exit;
1250 	}
1251 	/* Check we don't overflow 24-bits. */
1252 	if ((u64)na->data_size > 0xffffffLL) {
1253 		ntfs_log_error("Attribute definition table is too big (max "
1254 			       "24-bit allowed).\n");
1255 		errno = EINVAL;
1256 		goto error_exit;
1257 	}
1258 	vol->attrdef_len = na->data_size;
1259 	vol->attrdef = ntfs_malloc(na->data_size);
1260 	if (!vol->attrdef)
1261 		goto error_exit;
1262 	/* Read in the $DATA attribute value into the buffer. */
1263 	l = ntfs_attr_pread(na, 0, na->data_size, vol->attrdef);
1264 	if (l != na->data_size) {
1265 		ntfs_log_error("Failed to read $AttrDef, unexpected length "
1266 			       "(%lld != %lld).\n", (long long)l,
1267 			       (long long)na->data_size);
1268 		errno = EIO;
1269 		goto error_exit;
1270 	}
1271 	/* Done with the $AttrDef mft record. */
1272 	ntfs_attr_close(na);
1273 	if (ntfs_inode_close(ni)) {
1274 		ntfs_log_perror("Failed to close $AttrDef");
1275 		goto error_exit;
1276 	}
1277 
1278 	/* Open $Secure. */
1279 	if (ntfs_open_secure(vol))
1280 		goto error_exit;
1281 
1282 	/*
1283 	 * Check for dirty logfile and hibernated Windows.
1284 	 * We care only about read-write mounts.
1285 	 */
1286 	if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) {
1287 		if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) &&
1288 		    ntfs_volume_check_hiberfile(vol, 1) < 0) {
1289 			if (flags & NTFS_MNT_MAY_RDONLY)
1290 				need_fallback_ro = TRUE;
1291 			else
1292 				goto error_exit;
1293 			}
1294 		if (ntfs_volume_check_logfile(vol) < 0) {
1295 			/* Always reject cached metadata for now */
1296 			if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM)) {
1297 				if (flags & NTFS_MNT_MAY_RDONLY)
1298 					need_fallback_ro = TRUE;
1299 				else
1300 					goto error_exit;
1301 			} else {
1302 				ntfs_log_info("The file system wasn't safely "
1303 					      "closed on Windows. Fixing.\n");
1304 				if (ntfs_logfile_reset(vol))
1305 					goto error_exit;
1306 			}
1307 		}
1308 		/* make $TXF_DATA resident if present on the root directory */
1309 		if (!(flags & NTFS_MNT_RDONLY) && !need_fallback_ro) {
1310 			if (fix_txf_data(vol))
1311 				goto error_exit;
1312 		}
1313 	}
1314 	if (need_fallback_ro) {
1315 		NVolSetReadOnly(vol);
1316 		ntfs_log_error("%s", fallback_readonly_msg);
1317 	}
1318 
1319 	return vol;
1320 bad_upcase :
1321 	ntfs_attr_close(na);
1322 	ntfs_inode_close(ni);
1323 	goto error_exit;
1324 io_error_exit:
1325 	errno = EIO;
1326 error_exit:
1327 	eo = errno;
1328 	if (ctx)
1329 		ntfs_attr_put_search_ctx(ctx);
1330 	free(m);
1331 	free(m2);
1332 	__ntfs_volume_release(vol);
1333 	errno = eo;
1334 	return NULL;
1335 }
1336 
1337 /*
1338  *		Set appropriate flags for showing NTFS metafiles
1339  *	or files marked as hidden.
1340  *	Not set in ntfs_mount() to avoid breaking existing tools.
1341  */
1342 
ntfs_set_shown_files(ntfs_volume * vol,BOOL show_sys_files,BOOL show_hid_files,BOOL hide_dot_files)1343 int ntfs_set_shown_files(ntfs_volume *vol,
1344 			BOOL show_sys_files, BOOL show_hid_files,
1345 			BOOL hide_dot_files)
1346 {
1347 	int res;
1348 
1349 	res = -1;
1350 	if (vol) {
1351 		NVolClearShowSysFiles(vol);
1352 		NVolClearShowHidFiles(vol);
1353 		NVolClearHideDotFiles(vol);
1354 		if (show_sys_files)
1355 			NVolSetShowSysFiles(vol);
1356 		if (show_hid_files)
1357 			NVolSetShowHidFiles(vol);
1358 		if (hide_dot_files)
1359 			NVolSetHideDotFiles(vol);
1360 		res = 0;
1361 	}
1362 	if (res)
1363 		ntfs_log_error("Failed to set file visibility\n");
1364 	return (res);
1365 }
1366 
1367 /*
1368  *		Set ignore case mode
1369  */
1370 
ntfs_set_ignore_case(ntfs_volume * vol)1371 int ntfs_set_ignore_case(ntfs_volume *vol)
1372 {
1373 	int res;
1374 
1375 	res = -1;
1376 	if (vol && vol->upcase) {
1377 		vol->locase = ntfs_locase_table_build(vol->upcase,
1378 					vol->upcase_len);
1379 		if (vol->locase) {
1380 			NVolClearCaseSensitive(vol);
1381 			res = 0;
1382 		}
1383 	}
1384 	if (res)
1385 		ntfs_log_error("Failed to set ignore_case mode\n");
1386 	return (res);
1387 }
1388 
1389 /**
1390  * ntfs_mount - open ntfs volume
1391  * @name:	name of device/file to open
1392  * @flags:	optional mount flags
1393  *
1394  * This function mounts an ntfs volume. @name should contain the name of the
1395  * device/file to mount as the ntfs volume.
1396  *
1397  * @flags is an optional second parameter. The same flags are used as for
1398  * the mount system call (man 2 mount). Currently only the following flags
1399  * is implemented:
1400  *	NTFS_MNT_RDONLY	- mount volume read-only
1401  *
1402  * The function opens the device or file @name and verifies that it contains a
1403  * valid bootsector. Then, it allocates an ntfs_volume structure and initializes
1404  * some of the values inside the structure from the information stored in the
1405  * bootsector. It proceeds to load the necessary system files and completes
1406  * setting up the structure.
1407  *
1408  * Return the allocated volume structure on success and NULL on error with
1409  * errno set to the error code.
1410  *
1411  * Note, that a copy is made of @name, and hence it can be discarded as
1412  * soon as the function returns.
1413  */
ntfs_mount(const char * name,ntfs_mount_flags flags)1414 ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),
1415 		ntfs_mount_flags flags __attribute__((unused)))
1416 {
1417 #ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
1418 	struct ntfs_device *dev;
1419 	ntfs_volume *vol;
1420 
1421 	/* Allocate an ntfs_device structure. */
1422 	dev = ntfs_device_alloc(name, 0, &ntfs_device_default_io_ops, NULL);
1423 	if (!dev)
1424 		return NULL;
1425 	/* Call ntfs_device_mount() to do the actual mount. */
1426 	vol = ntfs_device_mount(dev, flags);
1427 	if (!vol) {
1428 		int eo = errno;
1429 		ntfs_device_free(dev);
1430 		errno = eo;
1431 	} else
1432 		ntfs_create_lru_caches(vol);
1433 	return vol;
1434 #else
1435 	/*
1436 	 * ntfs_mount() makes no sense if NO_NTFS_DEVICE_DEFAULT_IO_OPS is
1437 	 * defined as there are no device operations available in libntfs in
1438 	 * this case.
1439 	 */
1440 	errno = EOPNOTSUPP;
1441 	return NULL;
1442 #endif
1443 }
1444 
1445 /**
1446  * ntfs_umount - close ntfs volume
1447  * @vol: address of ntfs_volume structure of volume to close
1448  * @force: if true force close the volume even if it is busy
1449  *
1450  * Deallocate all structures (including @vol itself) associated with the ntfs
1451  * volume @vol.
1452  *
1453  * Return 0 on success. On error return -1 with errno set appropriately
1454  * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that
1455  * an operation is in progress and if you try the close later the operation
1456  * might be completed and the close succeed.
1457  *
1458  * If @force is true (i.e. not zero) this function will close the volume even
1459  * if this means that data might be lost.
1460  *
1461  * @vol must have previously been returned by a call to ntfs_mount().
1462  *
1463  * @vol itself is deallocated and should no longer be dereferenced after this
1464  * function returns success. If it returns an error then nothing has been done
1465  * so it is safe to continue using @vol.
1466  */
ntfs_umount(ntfs_volume * vol,const BOOL force)1467 int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused)))
1468 {
1469 	struct ntfs_device *dev;
1470 	int ret;
1471 
1472 	if (!vol) {
1473 		errno = EINVAL;
1474 		return -1;
1475 	}
1476 	dev = vol->dev;
1477 	ret = __ntfs_volume_release(vol);
1478 	ntfs_device_free(dev);
1479 	return ret;
1480 }
1481 
1482 #ifdef HAVE_MNTENT_H
1483 
1484 /**
1485  * ntfs_mntent_check - desc
1486  *
1487  * If you are wanting to use this, you actually wanted to use
1488  * ntfs_check_if_mounted(), you just didn't realize. (-:
1489  *
1490  * See description of ntfs_check_if_mounted(), below.
1491  */
ntfs_mntent_check(const char * file,unsigned long * mnt_flags)1492 static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
1493 {
1494 	struct mntent *mnt;
1495 	char *real_file = NULL, *real_fsname = NULL;
1496 	FILE *f;
1497 	int err = 0;
1498 
1499 	real_file = ntfs_malloc(PATH_MAX + 1);
1500 	if (!real_file)
1501 		return -1;
1502 	real_fsname = ntfs_malloc(PATH_MAX + 1);
1503 	if (!real_fsname) {
1504 		err = errno;
1505 		goto exit;
1506 	}
1507 	if (!ntfs_realpath_canonicalize(file, real_file)) {
1508 		err = errno;
1509 		goto exit;
1510 	}
1511 	f = setmntent("/proc/mounts", "r");
1512 	if (!f && !(f = setmntent(MOUNTED, "r"))) {
1513 		err = errno;
1514 		goto exit;
1515 	}
1516 	while ((mnt = getmntent(f))) {
1517 		if (!ntfs_realpath_canonicalize(mnt->mnt_fsname, real_fsname))
1518 			continue;
1519 		if (!strcmp(real_file, real_fsname))
1520 			break;
1521 	}
1522 	endmntent(f);
1523 	if (!mnt)
1524 		goto exit;
1525 	*mnt_flags = NTFS_MF_MOUNTED;
1526 	if (!strcmp(mnt->mnt_dir, "/"))
1527 		*mnt_flags |= NTFS_MF_ISROOT;
1528 #ifdef HAVE_HASMNTOPT
1529 	if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
1530 		*mnt_flags |= NTFS_MF_READONLY;
1531 #endif
1532 exit:
1533 	free(real_file);
1534 	free(real_fsname);
1535 	if (err) {
1536 		errno = err;
1537 		return -1;
1538 	}
1539 	return 0;
1540 }
1541 
1542 #else /* HAVE_MNTENT_H */
1543 
1544 #if defined(__sun) && defined (__SVR4)
1545 
ntfs_mntent_check(const char * file,unsigned long * mnt_flags)1546 static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
1547 {
1548 	struct mnttab *mnt = NULL;
1549 	char *real_file = NULL, *real_fsname = NULL;
1550 	FILE *f;
1551 	int err = 0;
1552 
1553 	real_file = (char*)ntfs_malloc(PATH_MAX + 1);
1554 	if (!real_file)
1555 		return -1;
1556 	real_fsname = (char*)ntfs_malloc(PATH_MAX + 1);
1557 	mnt = (struct mnttab*)ntfs_malloc(MNT_LINE_MAX + 1);
1558 	if (!real_fsname || !mnt) {
1559 		err = errno;
1560 		goto exit;
1561 	}
1562 	if (!ntfs_realpath_canonicalize(file, real_file)) {
1563 		err = errno;
1564 		goto exit;
1565 	}
1566 	if (!(f = fopen(MNTTAB, "r"))) {
1567 		err = errno;
1568 		goto exit;
1569 	}
1570 	while (!getmntent(f, mnt)) {
1571 		if (!ntfs_realpath_canonicalize(mnt->mnt_special, real_fsname))
1572 			continue;
1573 		if (!strcmp(real_file, real_fsname)) {
1574 			*mnt_flags = NTFS_MF_MOUNTED;
1575 			if (!strcmp(mnt->mnt_mountp, "/"))
1576 				*mnt_flags |= NTFS_MF_ISROOT;
1577 			if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
1578 				*mnt_flags |= NTFS_MF_READONLY;
1579 			break;
1580 		}
1581 	}
1582 	fclose(f);
1583 exit:
1584 	free(mnt);
1585 	free(real_file);
1586 	free(real_fsname);
1587 	if (err) {
1588 		errno = err;
1589 		return -1;
1590 	}
1591 	return 0;
1592 }
1593 
1594 #endif /* defined(__sun) && defined (__SVR4) */
1595 #endif /* HAVE_MNTENT_H */
1596 
1597 /**
1598  * ntfs_check_if_mounted - check if an ntfs volume is currently mounted
1599  * @file:	device file to check
1600  * @mnt_flags:	pointer into which to return the ntfs mount flags (see volume.h)
1601  *
1602  * If the running system does not support the {set,get,end}mntent() calls,
1603  * just return 0 and set *@mnt_flags to zero.
1604  *
1605  * When the system does support the calls, ntfs_check_if_mounted() first tries
1606  * to find the device @file in /etc/mtab (or wherever this is kept on the
1607  * running system). If it is not found, assume the device is not mounted and
1608  * return 0 and set *@mnt_flags to zero.
1609  *
1610  * If the device @file is found, set the NTFS_MF_MOUNTED flags in *@mnt_flags.
1611  *
1612  * Further if @file is mounted as the file system root ("/"), set the flag
1613  * NTFS_MF_ISROOT in *@mnt_flags.
1614  *
1615  * Finally, check if the file system is mounted read-only, and if so set the
1616  * NTFS_MF_READONLY flag in *@mnt_flags.
1617  *
1618  * On success return 0 with *@mnt_flags set to the ntfs mount flags.
1619  *
1620  * On error return -1 with errno set to the error code.
1621  */
ntfs_check_if_mounted(const char * file,unsigned long * mnt_flags)1622 int ntfs_check_if_mounted(const char *file __attribute__((unused)),
1623 		unsigned long *mnt_flags)
1624 {
1625 	*mnt_flags = 0;
1626 #if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4))
1627 	return ntfs_mntent_check(file, mnt_flags);
1628 #else
1629 	return 0;
1630 #endif
1631 }
1632 
1633 /**
1634  * ntfs_version_is_supported - check if NTFS version is supported.
1635  * @vol:	ntfs volume whose version we're interested in.
1636  *
1637  * The function checks if the NTFS volume version is known or not.
1638  * Version 1.1 and 1.2 are used by Windows NT3.x and NT4.
1639  * Version 2.x is used by Windows 2000 Betas.
1640  * Version 3.0 is used by Windows 2000.
1641  * Version 3.1 is used by Windows XP, Windows Server 2003 and Longhorn.
1642  *
1643  * Return 0 if NTFS version is supported otherwise -1 with errno set.
1644  *
1645  * The following error codes are defined:
1646  *	EOPNOTSUPP - Unknown NTFS version
1647  *	EINVAL	   - Invalid argument
1648  */
ntfs_version_is_supported(ntfs_volume * vol)1649 int ntfs_version_is_supported(ntfs_volume *vol)
1650 {
1651 	u8 major, minor;
1652 
1653 	if (!vol) {
1654 		errno = EINVAL;
1655 		return -1;
1656 	}
1657 
1658 	major = vol->major_ver;
1659 	minor = vol->minor_ver;
1660 
1661 	if (NTFS_V1_1(major, minor) || NTFS_V1_2(major, minor))
1662 		return 0;
1663 
1664 	if (NTFS_V2_X(major, minor))
1665 		return 0;
1666 
1667 	if (NTFS_V3_0(major, minor) || NTFS_V3_1(major, minor))
1668 		return 0;
1669 
1670 	errno = EOPNOTSUPP;
1671 	return -1;
1672 }
1673 
1674 /**
1675  * ntfs_logfile_reset - "empty" $LogFile data attribute value
1676  * @vol:	ntfs volume whose $LogFile we intend to reset.
1677  *
1678  * Fill the value of the $LogFile data attribute, i.e. the contents of
1679  * the file, with 0xff's, thus marking the journal as empty.
1680  *
1681  * FIXME(?): We might need to zero the LSN field of every single mft
1682  * record as well. (But, first try without doing that and see what
1683  * happens, since chkdsk might pickup the pieces and do it for us...)
1684  *
1685  * On success return 0.
1686  *
1687  * On error return -1 with errno set to the error code.
1688  */
ntfs_logfile_reset(ntfs_volume * vol)1689 int ntfs_logfile_reset(ntfs_volume *vol)
1690 {
1691 	ntfs_inode *ni;
1692 	ntfs_attr *na;
1693 	int eo;
1694 
1695 	if (!vol) {
1696 		errno = EINVAL;
1697 		return -1;
1698 	}
1699 
1700 	ni = ntfs_inode_open(vol, FILE_LogFile);
1701 	if (!ni) {
1702 		ntfs_log_perror("Failed to open inode FILE_LogFile");
1703 		return -1;
1704 	}
1705 
1706 	na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
1707 	if (!na) {
1708 		eo = errno;
1709 		ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
1710 		goto error_exit;
1711 	}
1712 
1713 	if (ntfs_empty_logfile(na)) {
1714 		eo = errno;
1715 		ntfs_attr_close(na);
1716 		goto error_exit;
1717 	}
1718 
1719 	ntfs_attr_close(na);
1720 	return ntfs_inode_close(ni);
1721 
1722 error_exit:
1723 	ntfs_inode_close(ni);
1724 	errno = eo;
1725 	return -1;
1726 }
1727 
1728 /**
1729  * ntfs_volume_write_flags - set the flags of an ntfs volume
1730  * @vol:	ntfs volume where we set the volume flags
1731  * @flags:	new flags
1732  *
1733  * Set the on-disk volume flags in the mft record of $Volume and
1734  * on volume @vol to @flags.
1735  *
1736  * Return 0 if successful and -1 if not with errno set to the error code.
1737  */
ntfs_volume_write_flags(ntfs_volume * vol,const le16 flags)1738 int ntfs_volume_write_flags(ntfs_volume *vol, const le16 flags)
1739 {
1740 	ATTR_RECORD *a;
1741 	VOLUME_INFORMATION *c;
1742 	ntfs_attr_search_ctx *ctx;
1743 	int ret = -1;	/* failure */
1744 
1745 	if (!vol || !vol->vol_ni) {
1746 		errno = EINVAL;
1747 		return -1;
1748 	}
1749 	/* Get a pointer to the volume information attribute. */
1750 	ctx = ntfs_attr_get_search_ctx(vol->vol_ni, NULL);
1751 	if (!ctx)
1752 		return -1;
1753 
1754 	if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL,
1755 			0, ctx)) {
1756 		ntfs_log_error("Attribute $VOLUME_INFORMATION was not found "
1757 			       "in $Volume!\n");
1758 		goto err_out;
1759 	}
1760 	a = ctx->attr;
1761 	/* Sanity check. */
1762 	if (a->non_resident) {
1763 		ntfs_log_error("Attribute $VOLUME_INFORMATION must be resident "
1764 			       "but it isn't.\n");
1765 		errno = EIO;
1766 		goto err_out;
1767 	}
1768 	/* Get a pointer to the value of the attribute. */
1769 	c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a);
1770 	/* Sanity checks. */
1771 	if ((char*)c + le32_to_cpu(a->value_length) > (char*)ctx->mrec +
1772 			le32_to_cpu(ctx->mrec->bytes_in_use) ||
1773 			le16_to_cpu(a->value_offset) +
1774 			le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
1775 		ntfs_log_error("Attribute $VOLUME_INFORMATION in $Volume is "
1776 			       "corrupt!\n");
1777 		errno = EIO;
1778 		goto err_out;
1779 	}
1780 	/* Set the volume flags. */
1781 	vol->flags = c->flags = flags & VOLUME_FLAGS_MASK;
1782 	/* Write them to disk. */
1783 	ntfs_inode_mark_dirty(vol->vol_ni);
1784 	if (ntfs_inode_sync(vol->vol_ni))
1785 		goto err_out;
1786 
1787 	ret = 0; /* success */
1788 err_out:
1789 	ntfs_attr_put_search_ctx(ctx);
1790 	return ret;
1791 }
1792 
ntfs_volume_error(int err)1793 int ntfs_volume_error(int err)
1794 {
1795 	int ret;
1796 
1797 	switch (err) {
1798 		case 0:
1799 			ret = NTFS_VOLUME_OK;
1800 			break;
1801 		case EINVAL:
1802 			ret = NTFS_VOLUME_NOT_NTFS;
1803 			break;
1804 		case EIO:
1805 			ret = NTFS_VOLUME_CORRUPT;
1806 			break;
1807 		case EPERM:
1808 			/*
1809 			 * Hibernation and fast restarting are seen the
1810 			 * same way on a non Windows-system partition.
1811 			 */
1812 			ret = NTFS_VOLUME_HIBERNATED;
1813 			break;
1814 		case EOPNOTSUPP:
1815 			ret = NTFS_VOLUME_UNCLEAN_UNMOUNT;
1816 			break;
1817 		case EBUSY:
1818 			ret = NTFS_VOLUME_LOCKED;
1819 			break;
1820 		case ENXIO:
1821 			ret = NTFS_VOLUME_RAID;
1822 			break;
1823 		case EACCES:
1824 			ret = NTFS_VOLUME_NO_PRIVILEGE;
1825 			break;
1826 		default:
1827 			ret = NTFS_VOLUME_UNKNOWN_REASON;
1828 			break;
1829 	}
1830 	return ret;
1831 }
1832 
1833 
ntfs_mount_error(const char * volume,const char * mntpoint,int err)1834 void ntfs_mount_error(const char *volume, const char *mntpoint, int err)
1835 {
1836 	switch (err) {
1837 		case NTFS_VOLUME_NOT_NTFS:
1838 			ntfs_log_error(invalid_ntfs_msg, volume);
1839 			break;
1840 		case NTFS_VOLUME_CORRUPT:
1841 			ntfs_log_error("%s", corrupt_volume_msg);
1842 			break;
1843 		case NTFS_VOLUME_HIBERNATED:
1844 			ntfs_log_error(hibernated_volume_msg, volume, mntpoint);
1845 			break;
1846 		case NTFS_VOLUME_UNCLEAN_UNMOUNT:
1847 			ntfs_log_error("%s", unclean_journal_msg);
1848 			break;
1849 		case NTFS_VOLUME_LOCKED:
1850 			ntfs_log_error("%s", opened_volume_msg);
1851 			break;
1852 		case NTFS_VOLUME_RAID:
1853 			ntfs_log_error("%s", fakeraid_msg);
1854 			break;
1855 		case NTFS_VOLUME_NO_PRIVILEGE:
1856 			ntfs_log_error(access_denied_msg, volume);
1857 			break;
1858 	}
1859 }
1860 
ntfs_set_locale(void)1861 int ntfs_set_locale(void)
1862 {
1863 	const char *locale;
1864 
1865 	locale = setlocale(LC_ALL, "");
1866 	if (!locale) {
1867 		locale = setlocale(LC_ALL, NULL);
1868 		ntfs_log_error("Couldn't set local environment, using default "
1869 			       "'%s'.\n", locale);
1870 		return 1;
1871 	}
1872 	return 0;
1873 }
1874 
1875 /*
1876  *		Feed the counts of free clusters and free mft records
1877  */
1878 
ntfs_volume_get_free_space(ntfs_volume * vol)1879 int ntfs_volume_get_free_space(ntfs_volume *vol)
1880 {
1881 	ntfs_attr *na;
1882 	int ret;
1883 
1884 	ret = -1; /* default return */
1885 	vol->free_clusters = ntfs_attr_get_free_bits(vol->lcnbmp_na);
1886 	if (vol->free_clusters < 0) {
1887 		ntfs_log_perror("Failed to read NTFS $Bitmap");
1888 	} else {
1889 		na = vol->mftbmp_na;
1890 		vol->free_mft_records = ntfs_attr_get_free_bits(na);
1891 
1892 		if (vol->free_mft_records >= 0)
1893 			vol->free_mft_records += (na->allocated_size - na->data_size) << 3;
1894 
1895 		if (vol->free_mft_records < 0)
1896 			ntfs_log_perror("Failed to calculate free MFT records");
1897 		else {
1898 			NVolSetFreeSpaceKnown(vol);
1899 			ret = 0;
1900 		}
1901 	}
1902 	return (ret);
1903 }
1904 
1905 /**
1906  * ntfs_volume_rename - change the current label on a volume
1907  * @vol:	volume to change the label on
1908  * @label:	the new label
1909  * @label_len:	the length of @label in ntfschars including the terminating NULL
1910  *		character, which is mandatory (the value can not exceed 128)
1911  *
1912  * Change the label on the volume @vol to @label.
1913  */
ntfs_volume_rename(ntfs_volume * vol,const ntfschar * label,int label_len)1914 int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, int label_len)
1915 {
1916 	ntfs_attr *na;
1917 	char *old_vol_name;
1918 	char *new_vol_name = NULL;
1919 	int new_vol_name_len;
1920 	int err;
1921 
1922 	if (NVolReadOnly(vol)) {
1923 		ntfs_log_error("Refusing to change label on read-only mounted "
1924 			"volume.\n");
1925 		errno = EROFS;
1926 		return -1;
1927 	}
1928 
1929 	label_len *= sizeof(ntfschar);
1930 	if (label_len > 0x100) {
1931 		ntfs_log_error("New label is too long. Maximum %u characters "
1932 				"allowed.\n",
1933 				(unsigned)(0x100 / sizeof(ntfschar)));
1934 		errno = ERANGE;
1935 		return -1;
1936 	}
1937 
1938 	na = ntfs_attr_open(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0);
1939 	if (!na) {
1940 		if (errno != ENOENT) {
1941 			err = errno;
1942 			ntfs_log_perror("Lookup of $VOLUME_NAME attribute "
1943 				"failed");
1944 			goto err_out;
1945 		}
1946 
1947 		/* The volume name attribute does not exist.  Need to add it. */
1948 		if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
1949 			(const u8*) label, label_len))
1950 		{
1951 			err = errno;
1952 			ntfs_log_perror("Encountered error while adding "
1953 				"$VOLUME_NAME attribute");
1954 			goto err_out;
1955 		}
1956 	}
1957 	else {
1958 		s64 written;
1959 
1960 		if (NAttrNonResident(na)) {
1961 			err = errno;
1962 			ntfs_log_error("Error: Attribute $VOLUME_NAME must be "
1963 					"resident.\n");
1964 			goto err_out;
1965 		}
1966 
1967 		if (na->data_size != label_len) {
1968 			if (ntfs_attr_truncate(na, label_len)) {
1969 				err = errno;
1970 				ntfs_log_perror("Error resizing resident "
1971 					"attribute");
1972 				goto err_out;
1973 			}
1974 		}
1975 
1976 		if (label_len) {
1977 			written = ntfs_attr_pwrite(na, 0, label_len, label);
1978 			if (written == -1) {
1979 				err = errno;
1980 				ntfs_log_perror("Error when writing "
1981 					"$VOLUME_NAME data");
1982 				goto err_out;
1983 			}
1984 			else if (written != label_len) {
1985 				err = EIO;
1986 				ntfs_log_error("Partial write when writing "
1987 					"$VOLUME_NAME data.");
1988 				goto err_out;
1989 
1990 			}
1991 		}
1992 	}
1993 
1994 	new_vol_name_len =
1995 		ntfs_ucstombs(label, label_len, &new_vol_name, 0);
1996 	if (new_vol_name_len == -1) {
1997 		err = errno;
1998 		ntfs_log_perror("Error while decoding new volume name");
1999 		goto err_out;
2000 	}
2001 
2002 	old_vol_name = vol->vol_name;
2003 	vol->vol_name = new_vol_name;
2004 	free(old_vol_name);
2005 
2006 	err = 0;
2007 err_out:
2008 	if (na)
2009 		ntfs_attr_close(na);
2010 	if (err)
2011 		errno = err;
2012 	return err ? -1 : 0;
2013 }
2014