1 /**
2 * ntfsclone - Part of the Linux-NTFS project.
3 *
4 * Copyright (c) 2003-2006 Szabolcs Szakacsits
5 * Copyright (c) 2004-2006 Anton Altaparmakov
6 * Special image format support copyright (c) 2004 Per Olofsson
7 *
8 * Clone NTFS data and/or metadata to a sparse file, image, device or stdout.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 */
15
16 #include "config.h"
17
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #ifdef HAVE_STDLIB_H
22 #include <stdlib.h>
23 #endif
24 #ifdef HAVE_STDIO_H
25 #include <stdio.h>
26 #endif
27 #ifdef HAVE_SYS_TYPES_H
28 #include <sys/types.h>
29 #endif
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #ifdef HAVE_SYS_IOCTL_H
34 #include <sys/ioctl.h>
35 #endif
36 #ifdef HAVE_SYS_VFS_H
37 #include <sys/vfs.h>
38 #endif
39 #ifdef HAVE_SYS_STATVFS_H
40 #include <sys/statvfs.h>
41 #endif
42 #ifdef HAVE_FCNTL_H
43 #include <fcntl.h>
44 #endif
45 #ifdef HAVE_STDARG_H
46 #include <stdarg.h>
47 #endif
48 #ifdef HAVE_STRING_H
49 #include <string.h>
50 #endif
51 #ifdef HAVE_ERRNO_H
52 #include <errno.h>
53 #endif
54 #ifdef HAVE_GETOPT_H
55 #include <getopt.h>
56 #endif
57
58 /*
59 * FIXME: ntfsclone do bad things about endians handling. Fix it and remove
60 * this note and define.
61 */
62 #define NTFS_DO_NOT_CHECK_ENDIANS
63
64 #include "compat.h"
65 #include "debug.h"
66 #include "types.h"
67 #include "support.h"
68 #include "endians.h"
69 #include "bootsect.h"
70 #include "device.h"
71 #include "attrib.h"
72 #include "mst.h"
73 #include "volume.h"
74 #include "mft.h"
75 #include "bitmap.h"
76 #include "inode.h"
77 #include "index.h"
78 #include "dir.h"
79 #include "runlist.h"
80 #include "ntfstime.h"
81 #include "utils.h"
82 #include "version.h"
83
84 #if defined(linux) && defined(_IO) && !defined(BLKGETSIZE)
85 #define BLKGETSIZE _IO(0x12,96) /* Get device size in 512-byte blocks. */
86 #endif
87 #if defined(linux) && defined(_IOR) && !defined(BLKGETSIZE64)
88 #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* Get device size in bytes. */
89 #endif
90
91 static const char *EXEC_NAME = "ntfsclone";
92
93 static const char *bad_sectors_warning_msg =
94 "*************************************************************************\n"
95 "* WARNING: The disk has bad sector. This means physical damage on the *\n"
96 "* disk surface caused by deterioration, manufacturing faults or other *\n"
97 "* reason. The reliability of the disk may stay stable or degrade fast. *\n"
98 "* Use the --rescue option to efficiently save as much data as possible! *\n"
99 "*************************************************************************\n";
100
101 static const char *dirty_volume_msg =
102 "Volume '%s' is scheduled for a check or it was shutdown \n"
103 "uncleanly. Please boot Windows or use the --force option to progress.\n";
104
105 static struct {
106 int verbose;
107 int quiet;
108 int debug;
109 int force;
110 int overwrite;
111 int std_out;
112 int blkdev_out; /* output file is block device */
113 int metadata; /* metadata only cloning */
114 int ignore_fs_check;
115 int rescue;
116 int save_image;
117 int restore_image;
118 char *output;
119 char *volume;
120 #ifdef __sun
121 struct statvfs stfs;
122 #else
123 struct statfs stfs;
124 #endif
125 } opt;
126
127 struct bitmap {
128 s64 size;
129 u8 *bm;
130 };
131
132 struct progress_bar {
133 u64 start;
134 u64 stop;
135 int resolution;
136 float unit;
137 };
138
139 typedef struct {
140 ntfs_inode *ni; /* inode being processed */
141 ntfs_attr_search_ctx *ctx; /* inode attribute being processed */
142 s64 inuse; /* number of clusters in use */
143 } ntfs_walk_clusters_ctx;
144
145 typedef int (ntfs_walk_op)(ntfs_inode *ni, void *data);
146
147 struct ntfs_walk_cluster {
148 ntfs_walk_op *inode_op; /* not implemented yet */
149 ntfs_walk_clusters_ctx *image;
150 };
151
152
153 static ntfs_volume *vol = NULL;
154 static struct bitmap lcn_bitmap;
155
156 static int fd_in;
157 static int fd_out;
158 static FILE *msg_out = NULL;
159
160 static int wipe = 0;
161 static unsigned int nr_used_mft_records = 0;
162 static unsigned int wiped_unused_mft_data = 0;
163 static unsigned int wiped_unused_mft = 0;
164 static unsigned int wiped_resident_data = 0;
165 static unsigned int wiped_timestamp_data = 0;
166
167 static BOOL image_is_host_endian = FALSE;
168
169 #define IMAGE_MAGIC "\0ntfsclone-image"
170 #define IMAGE_MAGIC_SIZE 16
171
172 /* This is the first endianness safe format version. */
173 #define NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE 10
174 #define NTFSCLONE_IMG_VER_MINOR_ENDIANNESS_SAFE 0
175
176 /*
177 * Set the version to 10.0 to avoid colisions with old ntfsclone which
178 * stupidly used the volume version as the image version... )-: I hope NTFS
179 * never reaches version 10.0 and if it does one day I hope no-one is using
180 * such an old ntfsclone by then...
181 *
182 * NOTE: Only bump the minor version if the image format and header are still
183 * backwards compatible. Otherwise always bump the major version. If in
184 * doubt, bump the major version.
185 */
186 #define NTFSCLONE_IMG_VER_MAJOR 10
187 #define NTFSCLONE_IMG_VER_MINOR 0
188
189 /* All values are in little endian. */
190 #ifdef __sun
191 #pragma pack(1)
192 #endif
193 static struct image_hdr {
194 char magic[IMAGE_MAGIC_SIZE];
195 u8 major_ver;
196 u8 minor_ver;
197 u32 cluster_size;
198 s64 device_size;
199 s64 nr_clusters;
200 s64 inuse;
201 u32 offset_to_image_data; /* From start of image_hdr. */
202 } __attribute__((__packed__)) image_hdr;
203 #ifdef __sun
204 #pragma pack()
205 #endif
206
207 #ifdef __sun
208 #define NTFSCLONE_IMG_HEADER_SIZE_OLD \
209 (offsetof(struct image_hdr, offset_to_image_data))
210 #else
211 #define NTFSCLONE_IMG_HEADER_SIZE_OLD \
212 (offsetof(typeof(image_hdr), offset_to_image_data))
213 #endif
214
215 #define NTFS_MBYTE (1000 * 1000)
216
217 #define ERR_PREFIX "ERROR"
218 #define PERR_PREFIX ERR_PREFIX "(%d): "
219 #define NERR_PREFIX ERR_PREFIX ": "
220
221 #define LAST_METADATA_INODE 11
222
223 #define NTFS_MAX_CLUSTER_SIZE 65536
224 #define NTFS_SECTOR_SIZE 512
225
226 #define rounded_up_division(a, b) (((a) + (b - 1)) / (b))
227
228 #define read_all(f, p, n) io_all((f), (p), (n), 0)
229 #define write_all(f, p, n) io_all((f), (p), (n), 1)
230
231 __attribute__((format(printf, 1, 2)))
Printf(const char * fmt,...)232 static void Printf(const char *fmt, ...)
233 {
234 va_list ap;
235
236 va_start(ap, fmt);
237 vfprintf(msg_out, fmt, ap);
238 va_end(ap);
239 fflush(msg_out);
240 }
241
242 __attribute__((format(printf, 1, 2)))
perr_printf(const char * fmt,...)243 static void perr_printf(const char *fmt, ...)
244 {
245 va_list ap;
246 int eo = errno;
247
248 Printf(PERR_PREFIX, eo);
249 va_start(ap, fmt);
250 vfprintf(msg_out, fmt, ap);
251 va_end(ap);
252 Printf(": %s\n", strerror(eo));
253 fflush(msg_out);
254 }
255
256 __attribute__((format(printf, 1, 2)))
err_printf(const char * fmt,...)257 static void err_printf(const char *fmt, ...)
258 {
259 va_list ap;
260
261 Printf(NERR_PREFIX);
262 va_start(ap, fmt);
263 vfprintf(msg_out, fmt, ap);
264 va_end(ap);
265 fflush(msg_out);
266 }
267
268 __attribute__((noreturn))
269 __attribute__((format(printf, 1, 2)))
err_exit(const char * fmt,...)270 static int err_exit(const char *fmt, ...)
271 {
272 va_list ap;
273
274 Printf(NERR_PREFIX);
275 va_start(ap, fmt);
276 vfprintf(msg_out, fmt, ap);
277 va_end(ap);
278 fflush(msg_out);
279 exit(1);
280 }
281
282 __attribute__((noreturn))
283 __attribute__((format(printf, 1, 2)))
perr_exit(const char * fmt,...)284 static int perr_exit(const char *fmt, ...)
285 {
286 va_list ap;
287 int eo = errno;
288
289 Printf(PERR_PREFIX, eo);
290 va_start(ap, fmt);
291 vfprintf(msg_out, fmt, ap);
292 va_end(ap);
293 Printf(": %s\n", strerror(eo));
294 fflush(msg_out);
295 exit(1);
296 }
297
298
299 __attribute__((noreturn))
usage(void)300 static void usage(void)
301 {
302 fprintf(stderr, "\nUsage: %s [OPTIONS] SOURCE\n"
303 " Efficiently clone NTFS to a sparse file, image, device or standard output.\n"
304 "\n"
305 " -o, --output FILE Clone NTFS to the non-existent FILE\n"
306 " -O, --overwrite FILE Clone NTFS to FILE, overwriting if exists\n"
307 " -s, --save-image Save to the special image format\n"
308 " -r, --restore-image Restore from the special image format\n"
309 " --rescue Continue after disk read errors\n"
310 " -m, --metadata Clone *only* metadata (for NTFS experts)\n"
311 " --ignore-fs-check Ignore the filesystem check result\n"
312 " -f, --force Force to progress (DANGEROUS)\n"
313 " -h, --help Display this help\n"
314 #ifdef DEBUG
315 " -d, --debug Show debug information\n"
316 #endif
317 "\n"
318 " If FILE is '-' then send the image to the standard output. If SOURCE is '-'\n"
319 " and --restore-image is used then read the image from the standard input.\n"
320 "\n", EXEC_NAME);
321 fprintf(stderr, "%s%s", ntfs_bugs, ntfs_home);
322 exit(1);
323 }
324
325
parse_options(int argc,char ** argv)326 static void parse_options(int argc, char **argv)
327 {
328 static const char *sopt = "-dfhmo:O:rs";
329 static const struct option lopt[] = {
330 #ifdef DEBUG
331 { "debug", no_argument, NULL, 'd' },
332 #endif
333 { "force", no_argument, NULL, 'f' },
334 { "help", no_argument, NULL, 'h' },
335 { "metadata", no_argument, NULL, 'm' },
336 { "output", required_argument, NULL, 'o' },
337 { "overwrite", required_argument, NULL, 'O' },
338 { "restore-image", no_argument, NULL, 'r' },
339 { "ignore-fs-check", no_argument, NULL, 'C' },
340 { "rescue", no_argument, NULL, 'R' },
341 { "save-image", no_argument, NULL, 's' },
342 { NULL, 0, NULL, 0 }
343 };
344
345 int c;
346
347 memset(&opt, 0, sizeof(opt));
348
349 while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
350 switch (c) {
351 case 1: /* A non-option argument */
352 if (opt.volume)
353 usage();
354 opt.volume = argv[optind-1];
355 break;
356 case 'd':
357 opt.debug++;
358 break;
359 case 'f':
360 opt.force++;
361 break;
362 case 'h':
363 case '?':
364 usage();
365 case 'm':
366 opt.metadata++;
367 break;
368 case 'O':
369 opt.overwrite++;
370 case 'o':
371 if (opt.output)
372 usage();
373 opt.output = optarg;
374 break;
375 case 'r':
376 opt.restore_image++;
377 break;
378 case 'C':
379 opt.ignore_fs_check++;
380 break;
381 case 'R':
382 opt.rescue++;
383 break;
384 case 's':
385 opt.save_image++;
386 break;
387 default:
388 err_printf("Unknown option '%s'.\n", argv[optind-1]);
389 usage();
390 }
391 }
392
393 if (opt.output == NULL) {
394 err_printf("You must specify an output file.\n");
395 usage();
396 }
397
398 if (strcmp(opt.output, "-") == 0)
399 opt.std_out++;
400
401 if (opt.volume == NULL) {
402 err_printf("You must specify a device file.\n");
403 usage();
404 }
405
406 if (opt.metadata && opt.save_image)
407 err_exit("Saving only metadata to an image is not "
408 "supported!\n");
409
410 if (opt.metadata && opt.restore_image)
411 err_exit("Restoring only metadata from an image is not "
412 "supported!\n");
413
414 if (opt.metadata && opt.std_out)
415 err_exit("Cloning only metadata to stdout isn't supported!\n");
416
417 if (opt.ignore_fs_check && !opt.metadata)
418 err_exit("Filesystem check can be ignored only for metadata "
419 "cloning!\n");
420
421 if (opt.save_image && opt.restore_image)
422 err_exit("Saving and restoring an image at the same time "
423 "is not supported!\n");
424
425 if (!opt.std_out) {
426 struct stat st;
427
428 if (stat(opt.output, &st) == -1) {
429 if (errno != ENOENT)
430 perr_exit("Couldn't access '%s'", opt.output);
431 } else {
432 if (!opt.overwrite)
433 err_exit("Output file '%s' already exists.\n"
434 "Use option --overwrite if you want to"
435 " replace its content.\n", opt.output);
436
437 if (S_ISBLK(st.st_mode)) {
438 opt.blkdev_out = 1;
439 if (opt.metadata)
440 err_exit("Cloning only metadata to a "
441 "block device isn't supported!\n");
442 }
443 }
444 }
445
446 msg_out = stdout;
447
448 /* FIXME: this is a workaround for losing debug info if stdout != stderr
449 and for the uncontrollable verbose messages in libntfs. Ughhh. */
450 if (opt.std_out)
451 msg_out = stderr;
452 else if (opt.debug) {
453 /* Redirect stderr to stdout, note fflush()es are essential! */
454 fflush(stdout);
455 fflush(stderr);
456 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) {
457 perror("Failed to redirect stderr to stdout");
458 exit(1);
459 }
460 fflush(stdout);
461 fflush(stderr);
462 } else {
463 fflush(stderr);
464 if (!freopen("/dev/null", "w", stderr))
465 perr_exit("Failed to redirect stderr to /dev/null");
466 }
467 }
468
progress_init(struct progress_bar * p,u64 start,u64 stop,int res)469 static void progress_init(struct progress_bar *p, u64 start, u64 stop, int res)
470 {
471 p->start = start;
472 p->stop = stop;
473 p->unit = 100.0 / (stop - start);
474 p->resolution = res;
475 }
476
477
progress_update(struct progress_bar * p,u64 current)478 static void progress_update(struct progress_bar *p, u64 current)
479 {
480 float percent = p->unit * current;
481
482 if (current != p->stop) {
483 if ((current - p->start) % p->resolution)
484 return;
485 Printf("%6.2f percent completed\r", percent);
486 } else
487 Printf("100.00 percent completed\n");
488 fflush(msg_out);
489 }
490
is_critical_metadata(ntfs_walk_clusters_ctx * image,runlist * rl)491 static s64 is_critical_metadata(ntfs_walk_clusters_ctx *image, runlist *rl)
492 {
493 s64 inode = image->ni->mft_no;
494
495 if (inode <= LAST_METADATA_INODE) {
496
497 /* Don't save bad sectors (both $Bad and unnamed are ignored */
498 if (inode == FILE_BadClus && image->ctx->attr->type == AT_DATA)
499 return 0;
500
501 if (inode != FILE_LogFile)
502 return rl->length;
503
504 if (image->ctx->attr->type == AT_DATA) {
505
506 /* Save at least the first 16 KiB of FILE_LogFile */
507 s64 s = (s64)16384 - rl->vcn * vol->cluster_size;
508 if (s > 0) {
509 s = rounded_up_division(s, vol->cluster_size);
510 if (rl->length < s)
511 s = rl->length;
512 return s;
513 }
514 return 0;
515 }
516 }
517
518 if (image->ctx->attr->type != AT_DATA)
519 return rl->length;
520
521 return 0;
522 }
523
524
io_all(void * fd,void * buf,int count,int do_write)525 static int io_all(void *fd, void *buf, int count, int do_write)
526 {
527 int i;
528 struct ntfs_device *dev = fd;
529
530 while (count > 0) {
531 if (do_write)
532 i = write(*(int *)fd, buf, count);
533 else if (opt.restore_image)
534 i = read(*(int *)fd, buf, count);
535 else
536 i = dev->d_ops->read(dev, buf, count);
537 if (i < 0) {
538 if (errno != EAGAIN && errno != EINTR)
539 return -1;
540 } else {
541 count -= i;
542 buf = i + (char *) buf;
543 }
544 }
545 return 0;
546 }
547
548
rescue_sector(void * fd,off_t pos,void * buff)549 static void rescue_sector(void *fd, off_t pos, void *buff)
550 {
551 const char *badsector_magic = "BadSectoR\0";
552 struct ntfs_device *dev = fd;
553
554 if (opt.restore_image) {
555 if (lseek(*(int *)fd, pos, SEEK_SET) == (off_t)-1)
556 perr_exit("lseek");
557 } else {
558 if (vol->u.dev->d_ops->seek(dev, pos, SEEK_SET) == (off_t)-1)
559 perr_exit("seek input");
560 }
561
562 if (read_all(fd, buff, NTFS_SECTOR_SIZE) == -1) {
563 Printf("WARNING: Can't read sector at %llu, lost data.\n",
564 (unsigned long long)pos);
565 memset(buff, '?', NTFS_SECTOR_SIZE);
566 memmove(buff, badsector_magic, sizeof(badsector_magic));
567 }
568 }
569
570
copy_cluster(int rescue,u64 rescue_lcn)571 static void copy_cluster(int rescue, u64 rescue_lcn)
572 {
573 char buff[NTFS_MAX_CLUSTER_SIZE]; /* overflow checked at mount time */
574 /* vol is NULL if opt.restore_image is set */
575 u32 csize = le32_to_cpu(image_hdr.cluster_size);
576 void *fd = (void *)&fd_in;
577 off_t rescue_pos;
578
579 if (!opt.restore_image) {
580 csize = vol->cluster_size;
581 fd = vol->u.dev;
582 }
583
584 rescue_pos = (off_t)(rescue_lcn * csize);
585
586 if (read_all(fd, buff, csize) == -1) {
587
588 if (errno != EIO)
589 perr_exit("read_all");
590 else if (rescue){
591 u32 i;
592 for (i = 0; i < csize; i += NTFS_SECTOR_SIZE)
593 rescue_sector(fd, rescue_pos + i, buff + i);
594 } else {
595 Printf("%s", bad_sectors_warning_msg);
596 err_exit("Disk is faulty, can't make full backup!");
597 }
598 }
599
600 if (opt.save_image) {
601 char cmd = 1;
602 if (write_all(&fd_out, &cmd, sizeof(cmd)) == -1)
603 perr_exit("write_all");
604 }
605
606 if (write_all(&fd_out, buff, csize) == -1) {
607 perr_printf("Write failed");
608 #ifndef __sun
609 int err = errno;
610 if (errno == EIO && opt.stfs.f_type == 0x517b)
611 Printf("Apparently you tried to clone to a remote "
612 "Windows computer but they don't\nhave "
613 "efficient sparse file handling by default. "
614 "Please try a different method.\n");
615 #endif /* !defined(__sun) */
616 exit(1);
617 }
618 }
619
lseek_to_cluster(s64 lcn)620 static void lseek_to_cluster(s64 lcn)
621 {
622 off_t pos;
623
624 pos = (off_t)(lcn * vol->cluster_size);
625
626 if (vol->u.dev->d_ops->seek(vol->u.dev, pos, SEEK_SET) == (off_t)-1)
627 perr_exit("lseek input");
628
629 if (opt.std_out || opt.save_image)
630 return;
631
632 if (lseek(fd_out, pos, SEEK_SET) == (off_t)-1)
633 perr_exit("lseek output");
634 }
635
image_skip_clusters(s64 count)636 static void image_skip_clusters(s64 count)
637 {
638 if (opt.save_image && count > 0) {
639 #ifdef __sun
640 s64 count_buf;
641 #else
642 typeof(count) count_buf;
643 #endif
644 char buff[1 + sizeof(count)];
645
646 buff[0] = 0;
647 count_buf = cpu_to_sle64(count);
648 memcpy(buff + 1, &count_buf, sizeof(count_buf));
649
650 if (write_all(&fd_out, buff, sizeof(buff)) == -1)
651 perr_exit("write_all");
652 }
653 }
654
dump_clusters(ntfs_walk_clusters_ctx * image,runlist * rl)655 static void dump_clusters(ntfs_walk_clusters_ctx *image, runlist *rl)
656 {
657 s64 i, len; /* number of clusters to copy */
658
659 if (opt.std_out || !opt.metadata)
660 return;
661
662 if (!(len = is_critical_metadata(image, rl)))
663 return;
664
665 lseek_to_cluster(rl->lcn);
666
667 /* FIXME: this could give pretty suboptimal performance */
668 for (i = 0; i < len; i++)
669 copy_cluster(opt.rescue, rl->lcn + i);
670 }
671
clone_ntfs(u64 nr_clusters)672 static void clone_ntfs(u64 nr_clusters)
673 {
674 u64 cl, last_cl; /* current and last used cluster */
675 void *buf;
676 u32 csize = vol->cluster_size;
677 u64 p_counter = 0;
678 struct progress_bar progress;
679
680 if (opt.save_image)
681 Printf("Saving NTFS to image ...\n");
682 else
683 Printf("Cloning NTFS ...\n");
684
685 buf = ntfs_calloc(csize);
686 if (!buf)
687 perr_exit("clone_ntfs");
688
689 progress_init(&progress, p_counter, nr_clusters, 100);
690
691 if (opt.save_image) {
692 if (write_all(&fd_out, &image_hdr,
693 image_hdr.offset_to_image_data) == -1)
694 perr_exit("write_all");
695 }
696
697 for (last_cl = cl = 0; cl < (u64)vol->nr_clusters; cl++) {
698
699 if (ntfs_bit_get(lcn_bitmap.bm, cl)) {
700 progress_update(&progress, ++p_counter);
701 lseek_to_cluster(cl);
702 image_skip_clusters(cl - last_cl - 1);
703
704 copy_cluster(opt.rescue, cl);
705 last_cl = cl;
706 continue;
707 }
708
709 if (opt.std_out && !opt.save_image) {
710 progress_update(&progress, ++p_counter);
711 if (write_all(&fd_out, buf, csize) == -1)
712 perr_exit("write_all");
713 }
714 }
715 image_skip_clusters(cl - last_cl - 1);
716 }
717
write_empty_clusters(s32 csize,s64 count,struct progress_bar * progress,u64 * p_counter)718 static void write_empty_clusters(s32 csize, s64 count,
719 struct progress_bar *progress, u64 *p_counter)
720 {
721 s64 i;
722 char buff[NTFS_MAX_CLUSTER_SIZE];
723
724 memset(buff, 0, csize);
725
726 for (i = 0; i < count; i++) {
727 if (write_all(&fd_out, buff, csize) == -1)
728 perr_exit("write_all");
729 progress_update(progress, ++(*p_counter));
730 }
731 }
732
restore_image(void)733 static void restore_image(void)
734 {
735 s64 pos = 0, count;
736 s32 csize = le32_to_cpu(image_hdr.cluster_size);
737 char cmd;
738 u64 p_counter = 0;
739 struct progress_bar progress;
740
741 Printf("Restoring NTFS from image ...\n");
742
743 progress_init(&progress, p_counter, opt.std_out ?
744 sle64_to_cpu(image_hdr.nr_clusters) :
745 sle64_to_cpu(image_hdr.inuse),
746 100);
747
748 while (pos < sle64_to_cpu(image_hdr.nr_clusters)) {
749 if (read_all(&fd_in, &cmd, sizeof(cmd)) == -1)
750 perr_exit("read_all");
751
752 if (cmd == 0) {
753 if (read_all(&fd_in, &count, sizeof(count)) == -1)
754 perr_exit("read_all");
755 if (!image_is_host_endian)
756 count = sle64_to_cpu(count);
757 if (opt.std_out)
758 write_empty_clusters(csize, count,
759 &progress, &p_counter);
760 else {
761 if (lseek(fd_out, count * csize, SEEK_CUR) ==
762 (off_t)-1)
763 perr_exit("restore_image: lseek");
764 }
765 pos += count;
766 } else if (cmd == 1) {
767 copy_cluster(0, 0);
768 pos++;
769 progress_update(&progress, ++p_counter);
770 } else
771 err_exit("Invalid command code in image\n");
772 }
773 }
774
wipe_index_entry_timestams(INDEX_ENTRY * e)775 static void wipe_index_entry_timestams(INDEX_ENTRY *e)
776 {
777 s64 timestamp = utc2ntfs(0);
778
779 /* FIXME: can fall into infinite loop if corrupted */
780 while (!(e->flags & INDEX_ENTRY_END)) {
781
782 e->key.file_name.creation_time = timestamp;
783 e->key.file_name.last_data_change_time = timestamp;
784 e->key.file_name.last_mft_change_time = timestamp;
785 e->key.file_name.last_access_time = timestamp;
786
787 wiped_timestamp_data += 32;
788
789 e = (INDEX_ENTRY *)((u8 *)e + le16_to_cpu(e->length));
790 }
791 }
792
wipe_index_allocation_timestamps(ntfs_inode * ni,ATTR_RECORD * attr)793 static void wipe_index_allocation_timestamps(ntfs_inode *ni, ATTR_RECORD *attr)
794 {
795 INDEX_ALLOCATION *indexa, *tmp_indexa;
796 INDEX_ENTRY *entry;
797 INDEX_ROOT *indexr;
798 u8 *bitmap, *byte;
799 int bit;
800 ntfs_attr *na;
801 ntfschar *name;
802 u32 name_len;
803
804 indexr = ntfs_index_root_get(ni, attr);
805 if (!indexr) {
806 perr_printf("Failed to read $INDEX_ROOT attribute of inode "
807 "%lld", ni->mft_no);
808 return;
809 }
810
811 if (indexr->type != AT_FILE_NAME)
812 goto out_indexr;
813
814 name = (ntfschar *)((u8 *)attr + le16_to_cpu(attr->name_offset));
815 name_len = attr->name_length;
816
817 byte = bitmap = ntfs_attr_readall(ni, AT_BITMAP, name, name_len, NULL);
818 if (!byte) {
819 perr_printf("Failed to read $BITMAP attribute");
820 goto out_indexr;
821 }
822
823 na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, name, name_len);
824 if (!na) {
825 perr_printf("Failed to open $INDEX_ALLOCATION attribute");
826 goto out_bitmap;
827 }
828
829 if (!na->data_size)
830 goto out_na;
831
832 tmp_indexa = indexa = ntfs_malloc(na->data_size);
833 if (!tmp_indexa)
834 goto out_na;
835
836 if (ntfs_attr_pread(na, 0, na->data_size, indexa) != na->data_size) {
837 perr_printf("Failed to read $INDEX_ALLOCATION attribute");
838 goto out_indexa;
839 }
840
841 bit = 0;
842 while ((u8 *)tmp_indexa < (u8 *)indexa + na->data_size) {
843 if (*byte & (1 << bit)) {
844 if (ntfs_mst_post_read_fixup((NTFS_RECORD *)tmp_indexa,
845 le32_to_cpu(
846 indexr->index_block_size))) {
847 perr_printf("Damaged INDX record");
848 goto out_indexa;
849 }
850 entry = (INDEX_ENTRY *)((u8 *)tmp_indexa + le32_to_cpu(
851 tmp_indexa->index.entries_offset) + 0x18);
852
853 wipe_index_entry_timestams(entry);
854
855 if (ntfs_mft_usn_dec((MFT_RECORD *)tmp_indexa))
856 perr_exit("ntfs_mft_usn_dec");
857
858 if (ntfs_mst_pre_write_fixup((NTFS_RECORD *)tmp_indexa,
859 le32_to_cpu(
860 indexr->index_block_size))) {
861 perr_printf("INDX write fixup failed");
862 goto out_indexa;
863 }
864 }
865 tmp_indexa = (INDEX_ALLOCATION *)((u8 *)tmp_indexa +
866 le32_to_cpu(indexr->index_block_size));
867 bit++;
868 if (bit > 7) {
869 bit = 0;
870 byte++;
871 }
872 }
873
874 if (ntfs_rl_pwrite(vol, na->rl, 0, na->data_size, indexa) != na->data_size)
875 perr_printf("ntfs_rl_pwrite failed for inode %lld", ni->mft_no);
876 out_indexa:
877 free(indexa);
878 out_na:
879 ntfs_attr_close(na);
880 out_bitmap:
881 free(bitmap);
882 out_indexr:
883 free(indexr);
884 }
885
wipe_index_root_timestamps(ATTR_RECORD * attr,s64 timestamp)886 static void wipe_index_root_timestamps(ATTR_RECORD *attr, s64 timestamp)
887 {
888 INDEX_ENTRY *entry;
889 INDEX_ROOT *iroot;
890
891 iroot = (INDEX_ROOT *)((u8 *)attr + le16_to_cpu(attr->u.res.value_offset));
892 entry = (INDEX_ENTRY *)((u8 *)iroot +
893 le32_to_cpu(iroot->index.entries_offset) + 0x10);
894
895 while (!(entry->flags & INDEX_ENTRY_END)) {
896
897 if (iroot->type == AT_FILE_NAME) {
898
899 entry->key.file_name.creation_time = timestamp;
900 entry->key.file_name.last_access_time = timestamp;
901 entry->key.file_name.last_data_change_time = timestamp;
902 entry->key.file_name.last_mft_change_time = timestamp;
903
904 wiped_timestamp_data += 32;
905
906 } else if (ntfs_names_are_equal(NTFS_INDEX_Q,
907 sizeof(NTFS_INDEX_Q) / 2 - 1,
908 (ntfschar *)((char *)attr +
909 le16_to_cpu(attr->name_offset)),
910 attr->name_length, 0, NULL, 0)) {
911
912 QUOTA_CONTROL_ENTRY *quota_q;
913
914 quota_q = (QUOTA_CONTROL_ENTRY *)((u8 *)entry +
915 le16_to_cpu(entry->u.s.data_offset));
916 /*
917 * FIXME: no guarantee it's indeed /$Extend/$Quota:$Q.
918 * For now, as a minimal safeguard, we check only for
919 * quota version 2 ...
920 */
921 if (le32_to_cpu(quota_q->version) == 2) {
922 quota_q->change_time = timestamp;
923 wiped_timestamp_data += 4;
924 }
925 }
926
927 entry = (INDEX_ENTRY*)((u8*)entry + le16_to_cpu(entry->length));
928 }
929 }
930
931 #define WIPE_TIMESTAMPS(atype, attr, timestamp) \
932 do { \
933 atype *ats; \
934 ats = (atype *)((char *)(attr) + le16_to_cpu((attr)->u.res.value_offset)); \
935 \
936 ats->creation_time = (timestamp); \
937 ats->last_data_change_time = (timestamp); \
938 ats->last_mft_change_time= (timestamp); \
939 ats->last_access_time = (timestamp); \
940 \
941 wiped_timestamp_data += 32; \
942 \
943 } while (0)
944
wipe_timestamps(ntfs_walk_clusters_ctx * image)945 static void wipe_timestamps(ntfs_walk_clusters_ctx *image)
946 {
947 ATTR_RECORD *a = image->ctx->attr;
948 s64 timestamp = utc2ntfs(0);
949
950 if (a->type == AT_FILE_NAME)
951 WIPE_TIMESTAMPS(FILE_NAME_ATTR, a, timestamp);
952
953 else if (a->type == AT_STANDARD_INFORMATION)
954 WIPE_TIMESTAMPS(STANDARD_INFORMATION, a, timestamp);
955
956 else if (a->type == AT_INDEX_ROOT)
957 wipe_index_root_timestamps(a, timestamp);
958 }
959
wipe_resident_data(ntfs_walk_clusters_ctx * image)960 static void wipe_resident_data(ntfs_walk_clusters_ctx *image)
961 {
962 ATTR_RECORD *a;
963 u32 i;
964 int n = 0;
965 u8 *p;
966
967 a = image->ctx->attr;
968 p = (u8*)a + le16_to_cpu(a->u.res.value_offset);
969
970 if (image->ni->mft_no <= LAST_METADATA_INODE)
971 return;
972
973 if (a->type != AT_DATA)
974 return;
975
976 for (i = 0; i < le32_to_cpu(a->u.res.value_length); i++) {
977 if (p[i]) {
978 p[i] = 0;
979 n++;
980 }
981 }
982
983 wiped_resident_data += n;
984 }
985
clone_logfile_parts(ntfs_walk_clusters_ctx * image,runlist * rl)986 static void clone_logfile_parts(ntfs_walk_clusters_ctx *image, runlist *rl)
987 {
988 s64 offset = 0, lcn, vcn;
989
990 while (1) {
991
992 vcn = offset / image->ni->vol->cluster_size;
993 lcn = ntfs_rl_vcn_to_lcn(rl, vcn);
994 if (lcn < 0)
995 break;
996
997 lseek_to_cluster(lcn);
998 copy_cluster(opt.rescue, lcn);
999
1000 if (offset == 0)
1001 offset = NTFS_BLOCK_SIZE >> 1;
1002 else
1003 offset <<= 1;
1004 }
1005 }
1006
walk_runs(struct ntfs_walk_cluster * walk)1007 static void walk_runs(struct ntfs_walk_cluster *walk)
1008 {
1009 int i, j;
1010 runlist *rl;
1011 ATTR_RECORD *a;
1012 ntfs_attr_search_ctx *ctx;
1013
1014 ctx = walk->image->ctx;
1015 a = ctx->attr;
1016
1017 if (!a->non_resident) {
1018 if (wipe) {
1019 wipe_resident_data(walk->image);
1020 wipe_timestamps(walk->image);
1021 }
1022 return;
1023 }
1024
1025 if (wipe && walk->image->ctx->attr->type == AT_INDEX_ALLOCATION)
1026 wipe_index_allocation_timestamps(walk->image->ni, a);
1027
1028 if (!(rl = ntfs_mapping_pairs_decompress(vol, a, NULL)))
1029 perr_exit("ntfs_decompress_mapping_pairs");
1030
1031 for (i = 0; rl[i].length; i++) {
1032 s64 lcn = rl[i].lcn;
1033 s64 lcn_length = rl[i].length;
1034
1035 if (lcn == LCN_HOLE || lcn == LCN_RL_NOT_MAPPED)
1036 continue;
1037
1038 /* FIXME: ntfs_mapping_pairs_decompress should return error */
1039 if (lcn < 0 || lcn_length < 0)
1040 err_exit("Corrupt runlist in inode %lld attr %x LCN "
1041 "%llx length %llx\n", ctx->ntfs_ino->mft_no,
1042 (unsigned int)le32_to_cpu(a->type), lcn,
1043 lcn_length);
1044
1045 if (!wipe)
1046 dump_clusters(walk->image, rl + i);
1047
1048 for (j = 0; j < lcn_length; j++) {
1049 u64 k = (u64)lcn + j;
1050 if (ntfs_bit_get_and_set(lcn_bitmap.bm, k, 1))
1051 err_exit("Cluster %llu referenced twice!\n"
1052 "You didn't shutdown your Windows"
1053 "properly?\n", (unsigned long long)k);
1054 }
1055
1056 walk->image->inuse += lcn_length;
1057 }
1058 if (!wipe && !opt.std_out && opt.metadata &&
1059 walk->image->ni->mft_no == FILE_LogFile &&
1060 walk->image->ctx->attr->type == AT_DATA)
1061 clone_logfile_parts(walk->image, rl);
1062
1063 free(rl);
1064 }
1065
1066
walk_attributes(struct ntfs_walk_cluster * walk)1067 static void walk_attributes(struct ntfs_walk_cluster *walk)
1068 {
1069 ntfs_attr_search_ctx *ctx;
1070
1071 if (!(ctx = ntfs_attr_get_search_ctx(walk->image->ni, NULL)))
1072 perr_exit("ntfs_get_attr_search_ctx");
1073
1074 while (!ntfs_attrs_walk(ctx)) {
1075 if (ctx->attr->type == AT_END)
1076 break;
1077
1078 walk->image->ctx = ctx;
1079 walk_runs(walk);
1080 }
1081
1082 ntfs_attr_put_search_ctx(ctx);
1083 }
1084
1085
1086
compare_bitmaps(struct bitmap * a)1087 static void compare_bitmaps(struct bitmap *a)
1088 {
1089 s64 i, pos, count;
1090 int mismatch = 0;
1091 u8 bm[NTFS_BUF_SIZE];
1092
1093 Printf("Accounting clusters ...\n");
1094
1095 pos = 0;
1096 while (1) {
1097 count = ntfs_attr_pread(vol->lcnbmp_na, pos, NTFS_BUF_SIZE, bm);
1098 if (count == -1)
1099 perr_exit("Couldn't get $Bitmap $DATA");
1100
1101 if (count == 0) {
1102 if (a->size > pos)
1103 err_exit("$Bitmap size is smaller than expected"
1104 " (%lld != %lld)\n", a->size, pos);
1105 break;
1106 }
1107
1108 for (i = 0; i < count; i++, pos++) {
1109 s64 cl; /* current cluster */
1110
1111 if (a->size <= pos)
1112 goto done;
1113
1114 if (a->bm[pos] == bm[i])
1115 continue;
1116
1117 for (cl = pos * 8; cl < (pos + 1) * 8; cl++) {
1118 char bit;
1119
1120 bit = ntfs_bit_get(a->bm, cl);
1121 if (bit == ntfs_bit_get(bm, i * 8 + cl % 8))
1122 continue;
1123
1124 if (opt.ignore_fs_check) {
1125 lseek_to_cluster(cl);
1126 copy_cluster(opt.rescue, cl);
1127 }
1128
1129 if (++mismatch > 10)
1130 continue;
1131
1132 Printf("Cluster accounting failed at %lld "
1133 "(0x%llx): %s cluster in $Bitmap\n",
1134 (long long)cl, (unsigned long long)cl,
1135 bit ? "missing" : "extra");
1136 }
1137 }
1138 }
1139 done:
1140 if (mismatch) {
1141 Printf("Totally %d cluster accounting mismatches.\n", mismatch);
1142 if (opt.ignore_fs_check) {
1143 Printf("WARNING: The NTFS inconsistency was overruled "
1144 "by the --ignore-fs-check option.\n");
1145 return;
1146 }
1147 err_exit("Filesystem check failed! Windows wasn't shutdown "
1148 "properly or inconsistent\nfilesystem. Please run "
1149 "chkdsk /f on Windows then reboot it TWICE.\n");
1150 }
1151 }
1152
1153
wipe_data(char * p,int pos,int len)1154 static int wipe_data(char *p, int pos, int len)
1155 {
1156 int wiped = 0;
1157
1158 for (p += pos; --len >= 0;) {
1159 if (p[len]) {
1160 p[len] = 0;
1161 wiped++;
1162 }
1163 }
1164
1165 return wiped;
1166 }
1167
wipe_unused_mft_data(ntfs_inode * ni)1168 static void wipe_unused_mft_data(ntfs_inode *ni)
1169 {
1170 int unused;
1171 MFT_RECORD *m = ni->mrec;
1172
1173 /* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */
1174 if (ni->mft_no <= LAST_METADATA_INODE)
1175 return;
1176
1177 unused = le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use);
1178 wiped_unused_mft_data += wipe_data((char *)m,
1179 le32_to_cpu(m->bytes_in_use), unused);
1180 }
1181
wipe_unused_mft(ntfs_inode * ni)1182 static void wipe_unused_mft(ntfs_inode *ni)
1183 {
1184 int unused;
1185 MFT_RECORD *m = ni->mrec;
1186
1187 /* FIXME: broken MFTMirr update was fixed in libntfs, check if OK now */
1188 if (ni->mft_no <= LAST_METADATA_INODE)
1189 return;
1190
1191 unused = le32_to_cpu(m->bytes_in_use) - sizeof(MFT_RECORD);
1192 wiped_unused_mft += wipe_data((char *)m, sizeof(MFT_RECORD), unused);
1193 }
1194
mft_record_write_with_same_usn(ntfs_volume * volume,ntfs_inode * ni)1195 static void mft_record_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
1196 {
1197 if (ntfs_mft_usn_dec(ni->mrec))
1198 perr_exit("ntfs_mft_usn_dec");
1199
1200 if (ntfs_mft_record_write(volume, ni->mft_no, ni->mrec))
1201 perr_exit("ntfs_mft_record_write");
1202 }
1203
mft_inode_write_with_same_usn(ntfs_volume * volume,ntfs_inode * ni)1204 static void mft_inode_write_with_same_usn(ntfs_volume *volume, ntfs_inode *ni)
1205 {
1206 s32 i;
1207
1208 mft_record_write_with_same_usn(volume, ni);
1209
1210 if (ni->nr_extents <= 0)
1211 return;
1212
1213 for (i = 0; i < ni->nr_extents; ++i) {
1214 ntfs_inode *eni = ni->u.extent_nis[i];
1215 mft_record_write_with_same_usn(volume, eni);
1216 }
1217 }
1218
walk_clusters(ntfs_volume * volume,struct ntfs_walk_cluster * walk)1219 static int walk_clusters(ntfs_volume *volume, struct ntfs_walk_cluster *walk)
1220 {
1221 s64 inode = 0;
1222 s64 last_mft_rec;
1223 ntfs_inode *ni;
1224 struct progress_bar progress;
1225
1226 Printf("Scanning volume ...\n");
1227
1228 last_mft_rec = (volume->mft_na->initialized_size >>
1229 volume->mft_record_size_bits) - 1;
1230 progress_init(&progress, inode, last_mft_rec, 100);
1231
1232 for (; inode <= last_mft_rec; inode++) {
1233
1234 int err, deleted_inode;
1235 MFT_REF mref = (MFT_REF)inode;
1236
1237 progress_update(&progress, inode);
1238
1239 /* FIXME: Terrible kludge for libntfs not being able to return
1240 a deleted MFT record as inode */
1241 ni = ntfs_calloc(sizeof(ntfs_inode));
1242 if (!ni)
1243 perr_exit("walk_clusters");
1244
1245 ni->vol = volume;
1246
1247 err = ntfs_file_record_read(volume, mref, &ni->mrec, NULL);
1248 if (err == -1) {
1249 free(ni);
1250 continue;
1251 }
1252
1253 deleted_inode = !(ni->mrec->flags & MFT_RECORD_IN_USE);
1254
1255 if (deleted_inode) {
1256
1257 ni->mft_no = MREF(mref);
1258 if (wipe) {
1259 wipe_unused_mft(ni);
1260 wipe_unused_mft_data(ni);
1261 mft_record_write_with_same_usn(volume, ni);
1262 }
1263 }
1264
1265 free(ni->mrec);
1266 free(ni);
1267
1268 if (deleted_inode)
1269 continue;
1270
1271 if ((ni = ntfs_inode_open(volume, mref)) == NULL) {
1272 /* FIXME: continue only if it make sense, e.g.
1273 MFT record not in use based on $MFT bitmap */
1274 if (errno == EIO || errno == ENOENT)
1275 continue;
1276 perr_exit("Reading inode %lld failed", inode);
1277 }
1278
1279 if (wipe)
1280 nr_used_mft_records++;
1281
1282 if (ni->mrec->base_mft_record)
1283 goto out;
1284
1285 walk->image->ni = ni;
1286 walk_attributes(walk);
1287 out:
1288 if (wipe) {
1289 wipe_unused_mft_data(ni);
1290 mft_inode_write_with_same_usn(volume, ni);
1291 }
1292
1293 if (ntfs_inode_close(ni))
1294 perr_exit("ntfs_inode_close for inode %lld", inode);
1295 }
1296
1297 return 0;
1298 }
1299
1300
1301 /*
1302 * $Bitmap can overlap the end of the volume. Any bits in this region
1303 * must be set. This region also encompasses the backup boot sector.
1304 */
bitmap_file_data_fixup(s64 cluster,struct bitmap * bm)1305 static void bitmap_file_data_fixup(s64 cluster, struct bitmap *bm)
1306 {
1307 for (; cluster < bm->size << 3; cluster++)
1308 ntfs_bit_set(bm->bm, (u64)cluster, 1);
1309 }
1310
1311
1312 /*
1313 * Allocate a block of memory with one bit for each cluster of the disk.
1314 * All the bits are set to 0, except those representing the region beyond the
1315 * end of the disk.
1316 */
setup_lcn_bitmap(void)1317 static void setup_lcn_bitmap(void)
1318 {
1319 /* Determine lcn bitmap byte size and allocate it. */
1320 lcn_bitmap.size = rounded_up_division(vol->nr_clusters, 8);
1321
1322 lcn_bitmap.bm = ntfs_calloc(lcn_bitmap.size);
1323 if (!lcn_bitmap.bm)
1324 perr_exit("Failed to allocate internal buffer");
1325
1326 bitmap_file_data_fixup(vol->nr_clusters, &lcn_bitmap);
1327 }
1328
1329
volume_size(ntfs_volume * volume,s64 nr_clusters)1330 static s64 volume_size(ntfs_volume *volume, s64 nr_clusters)
1331 {
1332 return nr_clusters * volume->cluster_size;
1333 }
1334
1335
print_volume_size(const char * str,s64 bytes)1336 static void print_volume_size(const char *str, s64 bytes)
1337 {
1338 Printf("%s: %lld bytes (%lld MB)\n", str, (long long)bytes,
1339 (long long)rounded_up_division(bytes, NTFS_MBYTE));
1340 }
1341
1342
print_disk_usage(const char * spacer,u32 cluster_size,s64 nr_clusters,s64 inuse)1343 static void print_disk_usage(const char *spacer, u32 cluster_size,
1344 s64 nr_clusters, s64 inuse)
1345 {
1346 s64 total, used;
1347
1348 total = nr_clusters * cluster_size;
1349 used = inuse * cluster_size;
1350
1351 Printf("Space in use %s: %lld MB (%.1f%%) ", spacer,
1352 (long long)rounded_up_division(used, NTFS_MBYTE),
1353 100.0 * ((float)used / total));
1354
1355 Printf("\n");
1356 }
1357
print_image_info(void)1358 static void print_image_info(void)
1359 {
1360 Printf("Ntfsclone image version: %d.%d\n",
1361 image_hdr.major_ver, image_hdr.minor_ver);
1362 Printf("Cluster size : %u bytes\n",
1363 (unsigned)le32_to_cpu(image_hdr.cluster_size));
1364 print_volume_size("Image volume size ",
1365 sle64_to_cpu(image_hdr.nr_clusters) *
1366 le32_to_cpu(image_hdr.cluster_size));
1367 Printf("Image device size : %lld bytes\n",
1368 sle64_to_cpu(image_hdr.device_size));
1369 print_disk_usage(" ", le32_to_cpu(image_hdr.cluster_size),
1370 sle64_to_cpu(image_hdr.nr_clusters),
1371 sle64_to_cpu(image_hdr.inuse));
1372 Printf("Offset to image data : %u (0x%x) bytes\n",
1373 (unsigned)le32_to_cpu(image_hdr.offset_to_image_data),
1374 (unsigned)le32_to_cpu(image_hdr.offset_to_image_data));
1375 }
1376
check_if_mounted(const char * device,unsigned long new_mntflag)1377 static void check_if_mounted(const char *device, unsigned long new_mntflag)
1378 {
1379 unsigned long mntflag;
1380
1381 if (ntfs_check_if_mounted(device, &mntflag))
1382 perr_exit("Failed to check '%s' mount state", device);
1383
1384 if (mntflag & NTFS_MF_MOUNTED) {
1385 if (!(mntflag & NTFS_MF_READONLY))
1386 err_exit("Device '%s' is mounted read-write. "
1387 "You must 'umount' it first.\n", device);
1388 if (!new_mntflag)
1389 err_exit("Device '%s' is mounted. "
1390 "You must 'umount' it first.\n", device);
1391 }
1392 }
1393
1394 /**
1395 * mount_volume -
1396 *
1397 * First perform some checks to determine if the volume is already mounted, or
1398 * is dirty (Windows wasn't shutdown properly). If everything is OK, then mount
1399 * the volume (load the metadata into memory).
1400 */
mount_volume(unsigned long new_mntflag)1401 static void mount_volume(unsigned long new_mntflag)
1402 {
1403 check_if_mounted(opt.volume, new_mntflag);
1404
1405 if (!(vol = ntfs_mount(opt.volume, new_mntflag))) {
1406
1407 int err = errno;
1408
1409 perr_printf("Opening '%s' as NTFS failed", opt.volume);
1410 if (err == EINVAL) {
1411 Printf("Apparently device '%s' doesn't have a "
1412 "valid NTFS. Maybe you selected\nthe whole "
1413 "disk instead of a partition (e.g. /dev/hda, "
1414 "not /dev/hda1)?\n", opt.volume);
1415 }
1416 exit(1);
1417 }
1418
1419 if (NVolWasDirty(vol))
1420 if (opt.force-- <= 0)
1421 err_exit(dirty_volume_msg, opt.volume);
1422
1423 if (NTFS_MAX_CLUSTER_SIZE < vol->cluster_size)
1424 err_exit("Cluster size %u is too large!\n",
1425 (unsigned int)vol->cluster_size);
1426
1427 Printf("NTFS volume version: %d.%d\n", vol->major_ver, vol->minor_ver);
1428 if (ntfs_version_is_supported(vol))
1429 perr_exit("Unknown NTFS version");
1430
1431 Printf("Cluster size : %u bytes\n",
1432 (unsigned int)vol->cluster_size);
1433 print_volume_size("Current volume size",
1434 volume_size(vol, vol->nr_clusters));
1435 }
1436
1437 static struct ntfs_walk_cluster backup_clusters = { NULL, NULL };
1438
device_offset_valid(int fd,s64 ofs)1439 static int device_offset_valid(int fd, s64 ofs)
1440 {
1441 char ch;
1442
1443 if (lseek(fd, ofs, SEEK_SET) >= 0 && read(fd, &ch, 1) == 1)
1444 return 0;
1445 return -1;
1446 }
1447
device_size_get(int fd)1448 static s64 device_size_get(int fd)
1449 {
1450 s64 high, low;
1451 #ifdef BLKGETSIZE64
1452 { u64 size;
1453
1454 if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
1455 ntfs_log_debug("BLKGETSIZE64 nr bytes = %llu "
1456 "(0x%llx).\n", (unsigned long long)size,
1457 (unsigned long long)size);
1458 return (s64)size;
1459 }
1460 }
1461 #endif
1462 #ifdef BLKGETSIZE
1463 { unsigned long size;
1464
1465 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
1466 ntfs_log_debug("BLKGETSIZE nr 512 byte blocks = %lu "
1467 "(0x%lx).\n", size, size);
1468 return (s64)size * 512;
1469 }
1470 }
1471 #endif
1472 #ifdef FDGETPRM
1473 { struct floppy_struct this_floppy;
1474
1475 if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) {
1476 ntfs_log_debug("FDGETPRM nr 512 byte blocks = %lu "
1477 "(0x%lx).\n", this_floppy.size,
1478 this_floppy.size);
1479 return (s64)this_floppy.size * 512;
1480 }
1481 }
1482 #endif
1483 /*
1484 * We couldn't figure it out by using a specialized ioctl,
1485 * so do binary search to find the size of the device.
1486 */
1487 low = 0LL;
1488 for (high = 1024LL; !device_offset_valid(fd, high); high <<= 1)
1489 low = high;
1490 while (low < high - 1LL) {
1491 const s64 mid = (low + high) / 2;
1492
1493 if (!device_offset_valid(fd, mid))
1494 low = mid;
1495 else
1496 high = mid;
1497 }
1498 lseek(fd, 0LL, SEEK_SET);
1499 return (low + 1LL);
1500 }
1501
fsync_clone(int fd)1502 static void fsync_clone(int fd)
1503 {
1504 Printf("Syncing ...\n");
1505 if (fsync(fd) && errno != EINVAL)
1506 perr_exit("fsync");
1507 }
1508
set_filesize(s64 filesize)1509 static void set_filesize(s64 filesize)
1510 {
1511
1512 #ifdef __sun
1513
1514 if (fstatvfs(fd_out, &opt.stfs) == -1)
1515 Printf("WARNING: Couldn't get filesystem type: "
1516 "%s\n", strerror(errno));
1517
1518 if (strcmp(opt.stfs.f_basetype, "pcfs") == 0)
1519 Printf("WARNING: You're using PCFS, it does not support "
1520 "sparse files so the next operation might take "
1521 "a while. You should consider using the more "
1522 "efficient --save-image option of ntfsclone. Use "
1523 "the --restore-image option to restore the image.\n");
1524
1525 if (ftruncate(fd_out, filesize) == -1) {
1526 int err = errno;
1527 perr_printf("ftruncate failed for file '%s'", opt.output);
1528 Printf("Destination filesystem type is %s\n",
1529 opt.stfs.f_basetype);
1530 if (err == EFBIG || (err == EINVAL && filesize > 0))
1531 Printf("Your system or the destination filesystem "
1532 "doesn't support large files.\n");
1533 exit(1);
1534 }
1535
1536 #else /* !defined(__sun) */
1537
1538 long fs_type = 0; /* Unknown filesystem type */
1539
1540 if (fstatfs(fd_out, &opt.stfs) == -1)
1541 Printf("WARNING: Couldn't get filesystem type: "
1542 "%s\n", strerror(errno));
1543 else
1544 fs_type = opt.stfs.f_type;
1545
1546 if (fs_type == 0x52654973)
1547 Printf("WARNING: You're using ReiserFS, it has very poor "
1548 "performance creating\nlarge sparse files. The next "
1549 "operation might take a very long time!\n"
1550 "Creating sparse output file ...\n");
1551 else if (fs_type == 0x517b)
1552 Printf("WARNING: You're using SMBFS and if the remote share "
1553 "isn't Samba but a Windows\ncomputer then the clone "
1554 "operation will be very inefficient and may fail!\n");
1555
1556 if (ftruncate(fd_out, filesize) == -1) {
1557 int err = errno;
1558 perr_printf("ftruncate failed for file '%s'", opt.output);
1559 if (fs_type)
1560 Printf("Destination filesystem type is 0x%lx.\n",
1561 (unsigned long)fs_type);
1562 if (err == E2BIG) {
1563 Printf("Your system or the destination filesystem "
1564 "doesn't support large files.\n");
1565 if (fs_type == 0x517b) {
1566 Printf("SMBFS needs minimum Linux kernel "
1567 "version 2.4.25 and\n the 'lfs' option"
1568 "\nfor smbmount to have large "
1569 "file support.\n");
1570 }
1571 } else if (err == EPERM) {
1572 Printf("Apparently the destination filesystem doesn't "
1573 "support sparse files.\nYou can overcome this "
1574 "by using the more efficient --save-image "
1575 "option\nof ntfsclone. Use the --restore-image "
1576 "option to restore the image.\n");
1577 }
1578 exit(1);
1579 }
1580
1581 #endif /* defined(__sun) */
1582 }
1583
open_image(void)1584 static s64 open_image(void)
1585 {
1586 if (strcmp(opt.volume, "-") == 0) {
1587 if ((fd_in = fileno(stdin)) == -1)
1588 perr_exit("fileno for stdout failed");
1589 } else {
1590 if ((fd_in = open(opt.volume, O_RDONLY)) == -1)
1591 perr_exit("failed to open image");
1592 }
1593 if (read_all(&fd_in, &image_hdr, NTFSCLONE_IMG_HEADER_SIZE_OLD) == -1)
1594 perr_exit("read_all");
1595 if (memcmp(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE) != 0)
1596 err_exit("Input file is not an image! (invalid magic)\n");
1597 if (image_hdr.major_ver < NTFSCLONE_IMG_VER_MAJOR_ENDIANNESS_SAFE) {
1598 image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
1599 image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
1600 #if (__BYTE_ORDER == __BIG_ENDIAN)
1601 Printf("Old image format detected. If the image was created "
1602 "on a little endian architecture it will not "
1603 "work. Use a more recent version of "
1604 "ntfsclone to recreate the image.\n");
1605 image_hdr.cluster_size = cpu_to_le32(image_hdr.cluster_size);
1606 image_hdr.device_size = cpu_to_sle64(image_hdr.device_size);
1607 image_hdr.nr_clusters = cpu_to_sle64(image_hdr.nr_clusters);
1608 image_hdr.inuse = cpu_to_sle64(image_hdr.inuse);
1609 #endif
1610 image_hdr.offset_to_image_data =
1611 const_cpu_to_le32((sizeof(image_hdr) + 7) & ~7);
1612 image_is_host_endian = TRUE;
1613 } else {
1614 #ifdef __sun
1615 u32 offset_to_image_data;
1616 #else
1617 typeof(image_hdr.offset_to_image_data) offset_to_image_data;
1618 #endif
1619 int delta;
1620
1621 if (image_hdr.major_ver > NTFSCLONE_IMG_VER_MAJOR)
1622 err_exit("Do not know how to handle image format "
1623 "version %d.%d. Please obtain a "
1624 "newer version of ntfsclone.\n",
1625 image_hdr.major_ver,
1626 image_hdr.minor_ver);
1627 /* Read the image header data offset. */
1628 if (read_all(&fd_in, &offset_to_image_data,
1629 sizeof(offset_to_image_data)) == -1)
1630 perr_exit("read_all");
1631 image_hdr.offset_to_image_data =
1632 le32_to_cpu(offset_to_image_data);
1633 /*
1634 * Read any fields from the header that we have not read yet so
1635 * that the input stream is positioned correctly. This means
1636 * we can support future minor versions that just extend the
1637 * header in a backwards compatible way.
1638 */
1639 delta = offset_to_image_data - (NTFSCLONE_IMG_HEADER_SIZE_OLD +
1640 sizeof(image_hdr.offset_to_image_data));
1641 if (delta > 0) {
1642 char *dummy_buf;
1643
1644 dummy_buf = malloc(delta);
1645 if (!dummy_buf)
1646 perr_exit("malloc dummy_buffer");
1647 if (read_all(&fd_in, dummy_buf, delta) == -1)
1648 perr_exit("read_all");
1649 }
1650 }
1651 return sle64_to_cpu(image_hdr.device_size);
1652 }
1653
open_volume(void)1654 static s64 open_volume(void)
1655 {
1656 s64 device_size;
1657
1658 mount_volume(NTFS_MNT_RDONLY);
1659
1660 device_size = ntfs_device_size_get(vol->u.dev, 1);
1661 if (device_size <= 0)
1662 err_exit("Couldn't get device size (%lld)!\n", device_size);
1663
1664 print_volume_size("Current device size", device_size);
1665
1666 if (device_size < vol->nr_clusters * vol->cluster_size)
1667 err_exit("Current NTFS volume size is bigger than the device "
1668 "size (%lld)!\nCorrupt partition table or incorrect "
1669 "device partitioning?\n", device_size);
1670
1671 return device_size;
1672 }
1673
initialise_image_hdr(s64 device_size,s64 inuse)1674 static void initialise_image_hdr(s64 device_size, s64 inuse)
1675 {
1676 memcpy(image_hdr.magic, IMAGE_MAGIC, IMAGE_MAGIC_SIZE);
1677 image_hdr.major_ver = NTFSCLONE_IMG_VER_MAJOR;
1678 image_hdr.minor_ver = NTFSCLONE_IMG_VER_MINOR;
1679 image_hdr.cluster_size = cpu_to_le32(vol->cluster_size);
1680 image_hdr.device_size = cpu_to_sle64(device_size);
1681 image_hdr.nr_clusters = cpu_to_sle64(vol->nr_clusters);
1682 image_hdr.inuse = cpu_to_sle64(inuse);
1683 image_hdr.offset_to_image_data = cpu_to_le32((sizeof(image_hdr) + 7) &
1684 ~7);
1685 }
1686
check_output_device(s64 input_size)1687 static void check_output_device(s64 input_size)
1688 {
1689 if (opt.blkdev_out) {
1690 s64 dest_size = device_size_get(fd_out);
1691 if (dest_size < input_size)
1692 err_exit("Output device is too small (%lld) to fit the "
1693 "NTFS image (%lld).\n", dest_size, input_size);
1694
1695 check_if_mounted(opt.output, 0);
1696 } else
1697 set_filesize(input_size);
1698 }
1699
attr_get_search_ctx(ntfs_inode * ni)1700 static ntfs_attr_search_ctx *attr_get_search_ctx(ntfs_inode *ni)
1701 {
1702 ntfs_attr_search_ctx *ret;
1703
1704 if ((ret = ntfs_attr_get_search_ctx(ni, NULL)) == NULL)
1705 perr_printf("ntfs_attr_get_search_ctx");
1706
1707 return ret;
1708 }
1709
1710 /**
1711 * lookup_data_attr
1712 *
1713 * Find the $DATA attribute (with or without a name) for the given ntfs inode.
1714 */
lookup_data_attr(ntfs_inode * ni,const char * aname)1715 static ntfs_attr_search_ctx *lookup_data_attr(ntfs_inode *ni, const char *aname)
1716 {
1717 ntfs_attr_search_ctx *ctx;
1718 ntfschar *ustr;
1719 int len = 0;
1720
1721 if ((ctx = attr_get_search_ctx(ni)) == NULL)
1722 return NULL;
1723
1724 if ((ustr = ntfs_str2ucs(aname, &len)) == NULL) {
1725 perr_printf("Couldn't convert '%s' to Unicode", aname);
1726 goto error_out;
1727 }
1728
1729 if (ntfs_attr_lookup(AT_DATA, ustr, len, 0, 0, NULL, 0, ctx)) {
1730 perr_printf("ntfs_attr_lookup");
1731 goto error_out;
1732 }
1733 ntfs_ucsfree(ustr);
1734 return ctx;
1735 error_out:
1736 ntfs_attr_put_search_ctx(ctx);
1737 return NULL;
1738 }
1739
ignore_bad_clusters(ntfs_walk_clusters_ctx * image)1740 static void ignore_bad_clusters(ntfs_walk_clusters_ctx *image)
1741 {
1742 ntfs_inode *ni;
1743 ntfs_attr_search_ctx *ctx = NULL;
1744 runlist *rl, *rl_bad;
1745 s64 nr_bad_clusters = 0;
1746
1747 if (!(ni = ntfs_inode_open(vol, FILE_BadClus)))
1748 perr_exit("ntfs_open_inode");
1749
1750 if ((ctx = lookup_data_attr(ni, "$Bad")) == NULL)
1751 exit(1);
1752
1753 if (!(rl_bad = ntfs_mapping_pairs_decompress(vol, ctx->attr, NULL)))
1754 perr_exit("ntfs_mapping_pairs_decompress");
1755
1756 for (rl = rl_bad; rl->length; rl++) {
1757 s64 lcn = rl->lcn;
1758
1759 if (lcn == LCN_HOLE || lcn < 0)
1760 continue;
1761
1762 for (; lcn < rl->lcn + rl->length; lcn++, nr_bad_clusters++) {
1763 if (ntfs_bit_get_and_set(lcn_bitmap.bm, lcn, 0))
1764 image->inuse--;
1765 }
1766 }
1767 if (nr_bad_clusters)
1768 Printf("WARNING: The disk has %lld or more bad sectors"
1769 " (hardware faults).\n", nr_bad_clusters);
1770 free(rl_bad);
1771
1772 ntfs_attr_put_search_ctx(ctx);
1773 if (ntfs_inode_close(ni))
1774 perr_exit("ntfs_inode_close failed for $BadClus");
1775 }
1776
check_dest_free_space(u64 src_bytes)1777 static void check_dest_free_space(u64 src_bytes)
1778 {
1779 u64 dest_bytes;
1780 struct statvfs stvfs;
1781 struct stat st;
1782
1783 if (opt.metadata || opt.blkdev_out || opt.std_out)
1784 return;
1785 /*
1786 * TODO: save_image needs a bit more space than src_bytes
1787 * due to the free space encoding overhead.
1788 */
1789 if (fstatvfs(fd_out, &stvfs) == -1) {
1790 Printf("WARNING: Unknown free space on the destination: %s\n",
1791 strerror(errno));
1792 return;
1793 }
1794
1795 /* If file is a FIFO then there is no point in checking the size. */
1796 if (!fstat(fd_out, &st)) {
1797 if (S_ISFIFO(st.st_mode))
1798 return;
1799 } else
1800 Printf("WARNING: fstat failed: %s\n", strerror(errno));
1801
1802 dest_bytes = (u64)stvfs.f_frsize * stvfs.f_bfree;
1803 if (!dest_bytes)
1804 dest_bytes = (u64)stvfs.f_bsize * stvfs.f_bfree;
1805
1806 if (dest_bytes < src_bytes)
1807 err_exit("Destination doesn't have enough free space: "
1808 "%llu MB < %llu MB\n",
1809 rounded_up_division(dest_bytes, NTFS_MBYTE),
1810 rounded_up_division(src_bytes, NTFS_MBYTE));
1811 }
1812
main(int argc,char ** argv)1813 int main(int argc, char **argv)
1814 {
1815 ntfs_walk_clusters_ctx image;
1816 s64 device_size; /* input device size in bytes */
1817 s64 ntfs_size;
1818 unsigned int wiped_total = 0;
1819
1820 /* print to stderr, stdout can be an NTFS image ... */
1821 fprintf(stderr, "%s v%s (libntfs %s)\n", EXEC_NAME, VERSION,
1822 ntfs_libntfs_version());
1823 msg_out = stderr;
1824
1825 parse_options(argc, argv);
1826
1827 utils_set_locale();
1828
1829 if (opt.restore_image) {
1830 device_size = open_image();
1831 ntfs_size = sle64_to_cpu(image_hdr.nr_clusters) *
1832 le32_to_cpu(image_hdr.cluster_size);
1833 } else {
1834 device_size = open_volume();
1835 ntfs_size = vol->nr_clusters * vol->cluster_size;
1836 }
1837 // FIXME: This needs to be the cluster size...
1838 ntfs_size += 512; /* add backup boot sector */
1839
1840 if (opt.std_out) {
1841 if ((fd_out = fileno(stdout)) == -1)
1842 perr_exit("fileno for stdout failed");
1843 } else {
1844 /* device_size_get() might need to read() */
1845 int flags = O_RDWR;
1846
1847 if (!opt.blkdev_out) {
1848 flags |= O_CREAT | O_TRUNC;
1849 if (!opt.overwrite)
1850 flags |= O_EXCL;
1851 }
1852
1853 if ((fd_out = open(opt.output, flags, S_IRUSR | S_IWUSR)) == -1)
1854 perr_exit("Opening file '%s' failed", opt.output);
1855
1856 if (!opt.save_image)
1857 check_output_device(ntfs_size);
1858 }
1859
1860 if (opt.restore_image) {
1861 print_image_info();
1862 restore_image();
1863 fsync_clone(fd_out);
1864 exit(0);
1865 }
1866
1867 setup_lcn_bitmap();
1868 memset(&image, 0, sizeof(image));
1869 backup_clusters.image = ℑ
1870
1871 walk_clusters(vol, &backup_clusters);
1872 compare_bitmaps(&lcn_bitmap);
1873 print_disk_usage("", vol->cluster_size, vol->nr_clusters, image.inuse);
1874
1875 check_dest_free_space(vol->cluster_size * image.inuse);
1876
1877 ignore_bad_clusters(&image);
1878
1879 if (opt.save_image)
1880 initialise_image_hdr(device_size, image.inuse);
1881
1882 /* FIXME: save backup boot sector */
1883
1884 if (opt.std_out || !opt.metadata) {
1885 s64 nr_clusters_to_save = image.inuse;
1886 if (opt.std_out && !opt.save_image)
1887 nr_clusters_to_save = vol->nr_clusters;
1888
1889 clone_ntfs(nr_clusters_to_save);
1890 fsync_clone(fd_out);
1891 exit(0);
1892 }
1893
1894 wipe = 1;
1895 opt.volume = opt.output;
1896 /* 'force' again mount for dirty volumes (e.g. after resize).
1897 FIXME: use mount flags to avoid potential side-effects in future */
1898 opt.force++;
1899 mount_volume(0);
1900
1901 free(lcn_bitmap.bm);
1902 setup_lcn_bitmap();
1903 memset(&image, 0, sizeof(image));
1904 backup_clusters.image = ℑ
1905
1906 walk_clusters(vol, &backup_clusters);
1907
1908 Printf("Num of MFT records = %10lld\n",
1909 (long long)vol->mft_na->initialized_size >>
1910 vol->mft_record_size_bits);
1911 Printf("Num of used MFT records = %10u\n", nr_used_mft_records);
1912
1913 Printf("Wiped unused MFT data = %10u\n", wiped_unused_mft_data);
1914 Printf("Wiped deleted MFT data = %10u\n", wiped_unused_mft);
1915 Printf("Wiped resident user data = %10u\n", wiped_resident_data);
1916 Printf("Wiped timestamp data = %10u\n", wiped_timestamp_data);
1917
1918 wiped_total += wiped_unused_mft_data;
1919 wiped_total += wiped_unused_mft;
1920 wiped_total += wiped_resident_data;
1921 wiped_total += wiped_timestamp_data;
1922 Printf("Wiped totally = %10u\n", wiped_total);
1923
1924 fsync_clone(fd_out);
1925 exit(0);
1926 }
1927