ntfsclone.c revision 9663:ace9a2ac3683
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
91static const char *EXEC_NAME = "ntfsclone";
92
93static 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
101static 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
105static 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
127struct bitmap {
128	s64 size;
129	u8 *bm;
130};
131
132struct progress_bar {
133	u64 start;
134	u64 stop;
135	int resolution;
136	float unit;
137};
138
139typedef 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
145typedef int (ntfs_walk_op)(ntfs_inode *ni, void *data);
146
147struct ntfs_walk_cluster {
148	ntfs_walk_op *inode_op;		/* not implemented yet */
149	ntfs_walk_clusters_ctx *image;
150};
151
152
153static ntfs_volume *vol = NULL;
154static struct bitmap lcn_bitmap;
155
156static int fd_in;
157static int fd_out;
158static FILE *msg_out = NULL;
159
160static int wipe = 0;
161static unsigned int nr_used_mft_records   = 0;
162static unsigned int wiped_unused_mft_data = 0;
163static unsigned int wiped_unused_mft      = 0;
164static unsigned int wiped_resident_data   = 0;
165static unsigned int wiped_timestamp_data  = 0;
166
167static 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
193static 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)))
232static 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)))
243static 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)))
257static 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)))
270static 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)))
284static 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))
300static 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
326static 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
469static 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
478static 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
491static 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
525static 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
549static 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
571static 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
620static 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
636static 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
655static 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
672static 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
718static 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
733static 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
775static 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
793static 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);
876out_indexa:
877	free(indexa);
878out_na:
879	ntfs_attr_close(na);
880out_bitmap:
881	free(bitmap);
882out_indexr:
883	free(indexr);
884}
885
886static 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)			\
932do {								\
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
945static 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
960static 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
986static 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
1007static 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
1067static 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
1087static 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	}
1139done:
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
1154static 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
1168static 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
1182static 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
1195static 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
1204static 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
1219static 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);
1287out:
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 */
1305static 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 */
1317static 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
1330static s64 volume_size(ntfs_volume *volume, s64 nr_clusters)
1331{
1332	return nr_clusters * volume->cluster_size;
1333}
1334
1335
1336static 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
1343static 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
1358static 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
1377static 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 */
1401static 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
1437static struct ntfs_walk_cluster backup_clusters = { NULL, NULL };
1438
1439static 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
1448static 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
1502static void fsync_clone(int fd)
1503{
1504	Printf("Syncing ...\n");
1505	if (fsync(fd) && errno != EINVAL)
1506		perr_exit("fsync");
1507}
1508
1509static 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
1584static 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
1654static 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
1674static 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
1687static 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
1700static 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 */
1715static 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;
1735error_out:
1736	ntfs_attr_put_search_ctx(ctx);
1737	return NULL;
1738}
1739
1740static 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
1777static 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
1813int 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 = &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 = &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