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