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