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))) 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))) 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))) 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))) 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))) 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)) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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 */ 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 1330 static s64 volume_size(ntfs_volume *volume, s64 nr_clusters) 1331 { 1332 return nr_clusters * volume->cluster_size; 1333 } 1334 1335 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 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 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 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 */ 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 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 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 1502 static void fsync_clone(int fd) 1503 { 1504 Printf("Syncing ...\n"); 1505 if (fsync(fd) && errno != EINVAL) 1506 perr_exit("fsync"); 1507 } 1508 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 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 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 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 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 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 */ 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 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 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 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 }