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