2 * ntfsundelete - Part of the Linux-NTFS project.
4 * Copyright (c) 2002-2003 Richard Russon
6 * This utility will recover deleted files from an NTFS volume.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program (in the main directory of the Linux-NTFS
20 * distribution in the file COPYING); if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <sys/types.h>
43 #include "ntfsundelete.h"
53 static const char *EXEC_NAME = "ntfsundelete";
54 static const char *MFTFILE = "mft";
55 static const char *UNNAMED = "<unnamed>";
56 static char *NONE = "<none>";
57 static char *UNKNOWN = "unknown";
58 static struct options opts;
60 GEN_PRINTF (Eprintf, stderr, NULL, FALSE)
61 GEN_PRINTF (Vprintf, stdout, &opts.verbose, TRUE)
62 GEN_PRINTF (Qprintf, stdout, &opts.quiet, FALSE)
64 #define _(S) gettext(S)
67 * version - Print version information about the program
69 * Print a copyright statement and a brief description of the program.
75 printf ("\n%s v%s - Recover deleted files from an NTFS Volume.\n\n",
77 printf ("Copyright (c)\n");
78 printf (" 2002-2003 Richard Russon\n");
79 printf ("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
83 * usage - Print a list of the parameters to the program
85 * Print a list of the parameters and options for the program.
91 printf ("\nUsage: %s [options] device\n"
92 " -s --scan Scan for files (default)\n"
93 " -p num --percentage num Minimum percentage recoverable\n"
94 " -m pattern --match pattern Only work on files with matching names\n"
95 " -C --case Case sensitive matching\n"
96 " -S range --size range Match files of this size\n"
97 " -t since --time since Last referenced since this time\n"
99 " -u num --undelete num Undelete inode\n"
100 " -o file --output file Save with this filename\n"
101 " -d dir --destination dir Destination directory\n"
102 " -b num --byte num Fill missing parts with this byte\n"
104 " -c range --copy range Write a range of MFT records to a file\n"
106 " -f --force Use less caution\n"
107 " -q --quiet Less output\n"
108 " -v --verbose More output\n"
109 " -V --version Display version information\n"
110 " -h --help Display this help\n\n",
112 printf ("%s%s\n", ntfs_bugs, ntfs_home);
116 * transform - Convert a shell style pattern to a regex
117 * @pattern: String to be converted
118 * @regex: Resulting regular expression is put here
120 * This will transform patterns, such as "*.doc" to true regular expressions.
121 * The function will also place '^' and '$' around the expression to make it
122 * behave as the user would expect
130 * The returned string must be freed by the caller.
131 * If transform fails, @regex will not be changed.
133 * Return: 1, Success, the string was transformed
134 * 0, An error occurred
136 int transform (const char *pattern, char **regex)
141 if (!pattern || !regex)
144 length = strlen (pattern);
146 Eprintf ("Pattern to transform is empty\n");
150 for (i = 0; pattern[i]; i++) {
151 if ((pattern[i] == '*') || (pattern[i] == '.'))
155 result = malloc (length + 3);
157 Eprintf ("Couldn't allocate memory in transform()\n");
163 for (i = 0, j = 1; pattern[i]; i++, j++) {
164 if (pattern[i] == '*') {
168 } else if (pattern[i] == '.') {
172 } else if (pattern[i] == '?') {
175 result[j] = pattern[i];
181 Dprintf ("Pattern '%s' replaced with regex '%s'\n", pattern, result);
188 * parse_time - Convert a time abbreviation to seconds
189 * @string: The string to be converted
190 * @since: The absolute time referred to
192 * Strings representing times will be converted into a time_t. The numbers will
193 * be regarded as seconds unless suffixed.
202 * Therefore, passing "1W" will return the time_t representing 1 week ago.
205 * Only the first character of the suffix is read.
206 * If parse_time fails, @since will not be changed
209 * 0 Error, the string was malformed
211 int parse_time (const char *value, time_t *since)
216 if (!value || !since)
219 Dprintf ("parsing time '%s' ago\n", value);
221 result = strtoll (value, &suffix, 10);
222 if (result < 0 || errno == ERANGE) {
223 Eprintf ("Invalid time '%s'.\n", value);
228 Eprintf ("Internal error, strtoll didn't return a suffix.\n");
232 if (strlen (suffix) > 1) {
233 Eprintf ("Invalid time suffix '%s'. Use Y, M, W, D or H.\n", suffix);
238 case 'y': case 'Y': result *= 12;
239 case 'm': case 'M': result *= 4;
240 case 'w': case 'W': result *= 7;
241 case 'd': case 'D': result *= 24;
242 case 'h': case 'H': result *= 3600;
247 Eprintf ("Invalid time suffix '%s'. Use Y, M, W, D or H.\n", suffix);
253 Dprintf ("Time now = %lld, Time then = %lld.\n", (long long) now, (long long) result);
254 *since = now - result;
259 * parse_options - Read and validate the programs command line
261 * Read the command line, verify the syntax and parse the options.
262 * This function is very long, but quite simple.
265 * 0 Error, one or more problems
267 int parse_options (int argc, char *argv[])
269 static const char *sopt = "-b:Cc:d:fh?m:o:p:sS:t:u:qvV";
270 static const struct option lopt[] = {
271 { "byte", required_argument, NULL, 'b' },
272 { "case", no_argument, NULL, 'C' },
273 { "copy", required_argument, NULL, 'c' },
274 { "destination", required_argument, NULL, 'd' },
275 { "force", no_argument, NULL, 'f' },
276 { "help", no_argument, NULL, 'h' },
277 { "match", required_argument, NULL, 'm' },
278 { "output", required_argument, NULL, 'o' },
279 { "percentage", required_argument, NULL, 'p' },
280 { "scan", no_argument, NULL, 's' },
281 { "size", required_argument, NULL, 'S' },
282 { "time", required_argument, NULL, 't' },
283 { "undelete", required_argument, NULL, 'u' },
284 { "quiet", no_argument, NULL, 'q' },
285 { "verbose", no_argument, NULL, 'v' },
286 { "version", no_argument, NULL, 'V' },
296 opterr = 0; /* We'll handle the errors, thank you. */
298 opts.mode = MODE_NONE;
303 while ((c = getopt_long (argc, argv, sopt, lopt, NULL)) != -1) {
305 case 1: /* A non-option argument */
307 opts.device = argv[optind-1];
314 if (opts.fillbyte == -1) {
316 opts.fillbyte = strtol (optarg, &end, 0);
327 if (opts.mode == MODE_NONE) {
328 if (!utils_parse_range (argv[optind-1],
329 &opts.mft_begin, &opts.mft_end, TRUE))
331 opts.mode = MODE_COPY;
333 opts.mode = MODE_ERROR;
338 opts.dest = argv[optind-1];
351 if (!transform (argv[optind-1], &opts.match))
359 opts.output = argv[optind-1];
365 if (opts.percent == -1) {
367 opts.percent = strtol (optarg, &end, 0);
368 if (end && ((*end != '%') && (*end != 0)))
378 if (opts.mode == MODE_NONE)
379 opts.mode = MODE_SCAN;
381 opts.mode = MODE_ERROR;
384 if ((opts.size_begin > 0) || (opts.size_end > 0) ||
385 !utils_parse_range (argv[optind-1], &opts.size_begin,
386 &opts.size_end, TRUE)) {
391 if (opts.since == 0) {
392 if (!parse_time (argv[optind-1], &opts.since))
399 if (opts.mode == MODE_NONE) {
401 opts.mode = MODE_UNDELETE;
402 opts.uinode = strtol (optarg, &end, 0);
406 opts.mode = MODE_ERROR;
416 if (((optopt == 'b') || (optopt == 'c') ||
417 (optopt == 'd') || (optopt == 'm') ||
418 (optopt == 'o') || (optopt == 'p') ||
419 (optopt == 'S') || (optopt == 't') ||
420 (optopt == 'u')) && (!optarg)) {
421 Eprintf ("Option '%s' requires an argument.\n", argv[optind-1]);
423 Eprintf ("Unknown option '%s'.\n", argv[optind-1]);
433 if (opts.device == NULL) {
435 Eprintf ("You must specify exactly one device.\n");
439 if (opts.mode == MODE_NONE) {
440 opts.mode = MODE_SCAN;
445 if (opts.output || opts.dest || (opts.fillbyte != -1)) {
446 Eprintf ("Scan can only be used with --percent, "
447 "--match, --ignore-case, --size and --time.\n");
450 if (opts.match_case && !opts.match) {
451 Eprintf ("The --case option doesn't make sense without the --match option\n");
456 if ((opts.percent != -1) || opts.match || opts.match_case ||
457 (opts.size_begin > 0) || (opts.size_end > 0)) {
458 Eprintf ("Undelete can only be used with "
459 "--output, --destination and --byte.\n");
464 if ((opts.fillbyte != -1) || (opts.percent != -1) ||
465 opts.match || opts.match_case ||
466 (opts.size_begin > 0) || (opts.size_end > 0)) {
467 Eprintf ("Copy can only be used with --output and --destination.\n");
472 Eprintf ("You can only select one of Scan, Undelete or Copy.\n");
476 if ((opts.percent < -1) || (opts.percent > 100)) {
477 Eprintf ("Percentage value must be in the range 0 - 100.\n");
483 Eprintf ("You may not use --quiet and --verbose at the same time.\n");
485 } else if (opts.mode == MODE_SCAN) {
486 Eprintf ("You may not use --quiet when scanning a volume.\n");
497 return (!err && !help && !ver);
502 * free_file - Release the resources used by a file object
503 * @file: The unwanted file object
505 * This will free up the memory used by a file object and iterate through the
506 * object's children, freeing their resources too.
510 void free_file (struct ufile *file)
512 struct list_head *item, *tmp;
517 list_for_each_safe (item, tmp, &file->name) { /* List of filenames */
518 struct filename *f = list_entry (item, struct filename, list);
519 Dprintf ("freeing filename '%s'\n", f->name ? f->name : NONE);
525 list_for_each_safe (item, tmp, &file->data) { /* List of data streams */
526 struct data *d = list_entry (item, struct data, list);
527 Dprintf ("freeing data stream '%s'\n", d->name ? d->name : UNNAMED);
540 * get_filenames - Read an MFT Record's $FILENAME attributes
541 * @file: The file object to work with
543 * A single file may have more than one filename. This is quite common.
544 * Windows creates a short DOS name for each long name, e.g. LONGFI~1.XYZ,
547 * The filenames that are found are put in filename objects and added to a
548 * linked list of filenames in the file object. For convenience, the unicode
549 * filename is converted into the current locale and stored in the filename
552 * One of the filenames is picked (the one with the lowest numbered namespace)
553 * and its locale friendly name is put in pref_name.
555 * Return: n The number of $FILENAME attributes found
558 int get_filenames (struct ufile *file)
561 FILE_NAME_ATTR *attr;
562 ntfs_attr_search_ctx *ctx;
563 struct filename *name;
570 ctx = ntfs_attr_get_search_ctx (NULL, file->mft);
574 while ((rec = find_attribute (AT_FILE_NAME, ctx))) {
575 /* We know this will always be resident. */
576 attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu (rec->value_offset));
578 name = calloc (1, sizeof (*name));
580 Eprintf ("Couldn't allocate memory in get_filenames().\n");
585 name->uname = attr->file_name;
586 name->uname_len = attr->file_name_length;
587 name->name_space = attr->file_name_type;
588 name->size_alloc = sle64_to_cpu (attr->allocated_size);
589 name->size_data = sle64_to_cpu (attr->data_size);
590 name->flags = attr->file_attributes;
592 name->date_c = ntfs2utc (sle64_to_cpu (attr->creation_time));
593 name->date_a = ntfs2utc (sle64_to_cpu (attr->last_data_change_time));
594 name->date_m = ntfs2utc (sle64_to_cpu (attr->last_mft_change_time));
595 name->date_r = ntfs2utc (sle64_to_cpu (attr->last_access_time));
597 if (ntfs_ucstombs (name->uname, name->uname_len, &name->name,
598 name->uname_len) < 0) {
599 Dprintf ("Couldn't translate filename to current locale.\n");
602 if (name->name_space < space) {
603 file->pref_name = name->name;
604 space = name->name_space;
607 file->max_size = max (file->max_size, name->size_alloc);
608 file->max_size = max (file->max_size, name->size_data);
610 list_add_tail (&name->list, &file->name);
614 ntfs_attr_put_search_ctx(ctx);
615 Dprintf ("File has %d names.\n", count);
620 * get_data - Read an MFT Record's $DATA attributes
621 * @file: The file object to work with
622 * @vol: An ntfs volume obtained from ntfs_mount
624 * A file may have more than one data stream. All files will have an unnamed
625 * data stream which contains the file's data. Some Windows applications store
626 * extra information in a separate stream.
628 * The streams that are found are put in data objects and added to a linked
629 * list of data streams in the file object.
631 * Return: n The number of $FILENAME attributes found
634 int get_data (struct ufile *file, ntfs_volume *vol)
637 ntfs_attr_search_ctx *ctx;
644 ctx = ntfs_attr_get_search_ctx (NULL, file->mft);
648 while ((rec = find_attribute (AT_DATA, ctx))) {
649 data = calloc (1, sizeof (*data));
651 Eprintf ("Couldn't allocate memory in get_data().\n");
656 data->resident = !rec->non_resident;
657 data->compressed = rec->flags & ATTR_IS_COMPRESSED;
658 data->encrypted = rec->flags & ATTR_IS_ENCRYPTED;
660 if (rec->name_length) {
661 data->uname = (uchar_t *) ((char *) rec + le16_to_cpu (rec->name_offset));
662 data->uname_len = rec->name_length;
664 if (ntfs_ucstombs (data->uname, data->uname_len, &data->name,
665 data->uname_len) < 0) {
666 Eprintf ("Cannot translate name into current locale.\n");
670 if (data->resident) {
671 data->size_data = le32_to_cpu (rec->value_length);
672 data->data = ((char*) (rec)) + le16_to_cpu (rec->value_offset);
674 data->size_alloc = sle64_to_cpu (rec->allocated_size);
675 data->size_data = sle64_to_cpu (rec->data_size);
676 data->size_init = sle64_to_cpu (rec->initialized_size);
677 data->size_vcn = sle64_to_cpu (rec->highest_vcn) + 1;
680 data->runlist = ntfs_mapping_pairs_decompress(vol, rec, NULL);
681 if (!data->runlist) {
682 Dprintf ("Couldn't decompress the data runs\n");
685 file->max_size = max (file->max_size, data->size_data);
686 file->max_size = max (file->max_size, data->size_init);
688 list_add_tail (&data->list, &file->data);
692 ntfs_attr_put_search_ctx(ctx);
693 Dprintf ("File has %d data streams.\n", count);
698 * read_record - Read an MFT record into memory
699 * @vol: An ntfs volume obtained from ntfs_mount
700 * @record: The record number to read
702 * Read the specified MFT record and gather as much information about it as
705 * Return: Pointer A ufile object containing the results
708 struct ufile * read_record (ntfs_volume *vol, long long record)
710 ATTR_RECORD *attr10, *attr20, *attr90;
717 file = calloc (1, sizeof (*file));
719 Eprintf ("Couldn't allocate memory in read_record()\n");
723 INIT_LIST_HEAD (&file->name);
724 INIT_LIST_HEAD (&file->data);
725 file->inode = record;
727 file->mft = malloc (vol->mft_record_size);
729 Eprintf ("Couldn't allocate memory in read_record()\n");
734 mft = ntfs_attr_open (vol->mft_ni, AT_DATA, NULL, 0);
736 Eprintf ("Couldn't open $MFT/$DATA: %s\n", strerror (errno));
741 if (ntfs_attr_mst_pread (mft, vol->mft_record_size * record, 1, vol->mft_record_size, file->mft) < 1) {
742 Eprintf ("Couldn't read MFT Record %lld.\n", record);
743 ntfs_attr_close (mft);
748 ntfs_attr_close (mft);
751 attr10 = find_first_attribute (AT_STANDARD_INFORMATION, file->mft);
752 attr20 = find_first_attribute (AT_ATTRIBUTE_LIST, file->mft);
753 attr90 = find_first_attribute (AT_INDEX_ROOT, file->mft);
755 Dprintf ("Attributes present: %s %s %s\n", attr10?"0x10":"", attr20?"0x20":"", attr90?"0x90":"");
759 STANDARD_INFORMATION *si;
760 si = (STANDARD_INFORMATION *) ((char *) attr10 + le16_to_cpu (attr10->value_offset));
761 file->date = ntfs2utc (sle64_to_cpu (si->last_data_change_time));
764 if (attr20 || !attr10)
769 if (get_filenames (file) < 0) {
770 Eprintf ("Couldn't get filenames.\n");
772 if (get_data (file, vol) < 0) {
773 Eprintf ("Couldn't get data streams.\n");
781 * calc_percentage - Calculate how much of the file is recoverable
782 * @file: The file object to work with
783 * @vol: An ntfs volume obtained from ntfs_mount
785 * Read through all the $DATA streams and determine if each cluster in each
786 * stream is still free disk space. This is just measuring the potential for
787 * recovery. The data may have still been overwritten by a another file which
790 * Files with a resident $DATA stream will have a 100% potential.
792 * N.B. If $DATA attribute spans more than one MFT record (i.e. badly
793 * fragmented) then only the data in this segment will be used for the
796 * N.B. Currently, compressed and encrypted files cannot be recovered, so they
799 * Return: n The percentage of the file that _could_ be recovered
802 int calc_percentage (struct ufile *file, ntfs_volume *vol)
804 runlist_element *rl = NULL;
805 struct list_head *pos;
808 long long start, end;
815 if (file->directory) {
816 Dprintf ("Found a directory: not recoverable.\n");
820 if (list_empty (&file->data)) {
821 Vprintf ("File has no data streams.\n");
825 list_for_each (pos, &file->data) {
826 data = list_entry (pos, struct data, list);
830 if (data->encrypted) {
831 Vprintf ("File is encrypted, recovery is impossible.\n");
835 if (data->compressed) {
836 Vprintf ("File is compressed, recovery not yet implemented.\n");
840 if (data->resident) {
841 Vprintf ("File is resident, therefore recoverable.\n");
849 Vprintf ("File has no runlist, hence no data.\n");
853 if (rl[0].length <= 0) {
854 Vprintf ("File has an empty runlist, hence no data.\n");
858 if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */
859 Vprintf ("Missing segment at beginning, %lld clusters\n", rl[0].length);
860 inuse += rl[0].length;
864 for (i = 0; rl[i].length > 0; i++) {
865 if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
866 Vprintf ("Missing segment at end, %lld clusters\n", rl[i].length);
867 inuse += rl[i].length;
871 if (rl[i].lcn == LCN_HOLE) {
872 free += rl[i].length;
877 end = rl[i].lcn + rl[i].length;
879 for (j = start; j < end; j++) {
880 if (utils_cluster_in_use (vol, j))
887 if ((inuse + free) == 0) {
888 Eprintf ("Unexpected error whilst calculating percentage for inode %lld\n", file->inode);
892 data->percent = (free * 100) / (inuse + free);
894 percent = max (percent, data->percent);
897 Vprintf ("File is %d%% recoverable\n", percent);
902 * dump_record - Print everything we know about an MFT record
903 * @file: The file to work with
905 * Output the contents of the file object. This will print everything that has
906 * been read from the MFT record, or implied by various means.
908 * Because of the redundant nature of NTFS, there will be some duplication of
909 * information, though it will have been read from different sources.
911 * N.B. If the filename is missing, or couldn't be converted to the current
912 * locale, "<none>" will be displayed.
916 void dump_record (struct ufile *file)
920 struct list_head *item;
926 Qprintf ("MFT Record %lld\n", file->inode);
927 Qprintf ("Type: %s\n", (file->directory) ? "Directory" : "File");
928 strftime (buffer, sizeof (buffer), "%F %R", localtime (&file->date));
929 Qprintf ("Date: %s\n", buffer);
932 Qprintf ("Metadata may span more than one MFT record\n");
934 list_for_each (item, &file->name) {
935 struct filename *f = list_entry (item, struct filename, list);
942 Qprintf ("Filename: (%d) %s\n", f->name_space, f->name);
943 Qprintf ("File Flags: ");
944 if (f->flags & FILE_ATTR_SYSTEM) Qprintf ("System ");
945 if (f->flags & FILE_ATTR_DIRECTORY) Qprintf ("Directory ");
946 if (f->flags & FILE_ATTR_SPARSE_FILE) Qprintf ("Sparse ");
947 if (f->flags & FILE_ATTR_REPARSE_POINT) Qprintf ("Reparse ");
948 if (f->flags & FILE_ATTR_COMPRESSED) Qprintf ("Compressed ");
949 if (f->flags & FILE_ATTR_ENCRYPTED) Qprintf ("Encrypted ");
950 if (!(f->flags & (FILE_ATTR_SYSTEM || FILE_ATTR_DIRECTORY ||
951 FILE_ATTR_SPARSE_FILE || FILE_ATTR_REPARSE_POINT ||
952 FILE_ATTR_COMPRESSED || FILE_ATTR_ENCRYPTED))) {
956 Qprintf ("Size alloc: %lld\n", f->size_alloc);
957 Qprintf ("Size data: %lld\n", f->size_data);
959 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_c));
960 Qprintf ("Date C: %s\n", buffer);
961 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_a));
962 Qprintf ("Date A: %s\n", buffer);
963 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_m));
964 Qprintf ("Date M: %s\n", buffer);
965 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_r));
966 Qprintf ("Date R: %s\n", buffer);
969 Qprintf ("Data Streams:\n");
970 list_for_each (item, &file->data) {
971 struct data *d = list_entry (item, struct data, list);
972 Qprintf ("Name: %s\n", (d->name) ? d->name : "<unnamed>");
974 if (d->resident) Qprintf ("Resident\n");
975 if (d->compressed) Qprintf ("Compressed\n");
976 if (d->encrypted) Qprintf ("Encrypted\n");
977 if (!d->resident && !d->compressed && !d->encrypted)
982 Qprintf ("Size alloc: %lld\n", d->size_alloc);
983 Qprintf ("Size data: %lld\n", d->size_data);
984 Qprintf ("Size init: %lld\n", d->size_init);
985 Qprintf ("Size vcn: %lld\n", d->size_vcn);
987 Qprintf ("Data runs:\n");
988 if ((!d->runlist) || (d->runlist[0].length <= 0)) {
991 for (i = 0; d->runlist[i].length > 0; i++) {
992 Qprintf (" %lld @ %lld\n", d->runlist[i].length, d->runlist[i].lcn);
996 Qprintf ("Amount potentially recoverable %d%%\n", d->percent);
999 Qprintf ("________________________________________\n\n");
1003 * list_record - Print a one line summary of the file
1004 * @file: The file to work with
1006 * Print a one line description of a file.
1008 * Inode Flags %age Date Size Filename
1010 * The output will contain the file's inode number (MFT Record), some flags,
1011 * the percentage of the file that is recoverable, the last modification date,
1012 * the size and the filename.
1014 * The flags are F/D = File/Directory, N/R = Data is (Non-)Resident,
1015 * C = Compressed, E = Encrypted, ! = Metadata may span multiple records.
1017 * N.B. The file size is stored in many forms in several attributes. This
1018 * display the largest it finds.
1020 * N.B. If the filename is missing, or couldn't be converted to the current
1021 * locale, "<none>" will be displayed.
1025 void list_record (struct ufile *file)
1028 struct list_head *item;
1033 char flagd = '.', flagr = '.', flagc = '.', flagx = '.';
1035 strftime (buffer, sizeof (buffer), "%F", localtime (&file->date));
1037 if (file->attr_list)
1040 if (file->directory)
1045 list_for_each (item, &file->data) {
1046 struct data *d = list_entry (item, struct data, list);
1049 if (d->resident) flagr = 'R';
1051 if (d->compressed) flagc = 'C'; /* These two are mutually exclusive */
1052 if (d->encrypted) flagc = 'E';
1054 percent = max (percent, d->percent);
1057 size = max (size, d->size_data);
1058 size = max (size, d->size_init);
1061 if (file->pref_name)
1062 name = file->pref_name;
1066 Qprintf ("%-8lld %c%c%c%c %3d%% %s %9lld %s\n",
1067 file->inode, flagd, flagr, flagc, flagx,
1068 percent, buffer, size, name);
1072 * name_match - Does a file have a name matching a regex
1073 * @re: The regular expression object
1074 * @file: The file to be tested
1076 * Iterate through the file's $FILENAME attributes and compare them against the
1077 * regular expression, created with regcomp.
1079 * Return: 1 There is a matching filename.
1080 * 0 There is no match.
1082 int name_match (regex_t *re, struct ufile *file)
1084 struct list_head *item;
1090 list_for_each (item, &file->name) {
1091 struct filename *f = list_entry (item, struct filename, list);
1095 result = regexec (re, f->name, 0, NULL, 0);
1097 Eprintf ("Couldn't compare filename with regex: %s\n", strerror (errno));
1099 } else if (result == REG_NOERROR) {
1100 Dprintf ("Found a matching filename.\n");
1105 Dprintf ("Filename '%s' doesn't match regex.\n", file->pref_name);
1110 * write_data - Write out a block of data
1111 * @fd: File descriptor to write to
1112 * @buffer: Data to write
1113 * @bufsize: Amount of data to write
1115 * Write a block of data to a file descriptor.
1117 * Return: -1 Error, something went wrong
1118 * 0 Success, all the data was written
1120 unsigned int write_data (int fd, const char *buffer, unsigned int bufsize)
1122 ssize_t result1, result2;
1129 result1 = write (fd, buffer, bufsize);
1130 if ((result1 == (ssize_t) bufsize) || (result1 < 0))
1133 /* Try again with the rest of the buffer */
1137 result2 = write (fd, buffer, bufsize);
1141 return result1 + result2;
1145 * create_pathname - Create a path/file from some components
1146 * @dir: Directory in which to create the file (optional)
1147 * @name: Filename to give the file (optional)
1148 * @stream: Name of the stream (optional)
1149 * @buffer: Store the result here
1150 * @bufsize: Size of buffer
1152 * Create a filename from various pieces. The output will be of the form:
1158 * All the components are optional. If the name is missing, "unknown" will be
1159 * used. If the directory is missing the file will be created in the current
1160 * directory. If the stream name is present it will be appended to the
1161 * filename, delimited by a colon.
1163 * N.B. If the buffer isn't large enough the name will be truncated.
1165 * Return: n Length of the allocated name
1167 int create_pathname (const char *dir, const char *name, const char *stream,
1168 char *buffer, int bufsize)
1175 snprintf (buffer, bufsize, "%s/%s:%s", dir, name, stream);
1177 snprintf (buffer, bufsize, "%s/%s", dir, name);
1180 snprintf (buffer, bufsize, "%s:%s", name, stream);
1182 snprintf (buffer, bufsize, "%s", name);
1184 return strlen (buffer);
1188 * open_file - Open a file to write to
1189 * @pathname: Path, name and stream of the file to open
1191 * Create a file and return the file descriptor.
1193 * N.B. If option force is given and existing file will be overwritten.
1195 * Return: -1 Error, failed to create the file
1196 * n Success, this is the file descriptor
1198 int open_file (const char *pathname)
1202 Vprintf ("Creating file: %s\n", pathname);
1205 flags = O_RDWR | O_CREAT | O_TRUNC;
1207 flags = O_RDWR | O_CREAT | O_EXCL;
1209 return open (pathname, flags, S_IRUSR | S_IWUSR);
1213 * set_date - Set the file's date and time
1214 * @pathname: Path and name of the file to alter
1215 * @date: Date and time to set
1217 * Give a file a particular date and time.
1219 * Return: 1 Success, set the file's date and time
1220 * 0 Error, failed to change the file's date and time
1222 int set_date (const char *pathname, time_t date)
1231 if (utime (pathname, &ut)) {
1232 Eprintf ("Couldn't set the file's date and time\n");
1239 * scan_disk - Search an NTFS volume for files that could be undeleted
1240 * @vol: An ntfs volume obtained from ntfs_mount
1242 * Read through all the MFT entries looking for deleted files. For each one
1243 * determine how much of the data lies in unused disk space.
1245 * The list can be filtered by name, size and date, using command line options.
1247 * Return: -1 Error, something went wrong
1248 * n Success, the number of recoverable files
1250 int scan_disk (ntfs_volume *vol)
1252 const int BUFSIZE = 8192;
1253 char *buffer = NULL;
1267 attr = ntfs_attr_open (vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
1269 Eprintf ("Couldn't open $MFT/$BITMAP: %s\n", strerror (errno));
1272 bmpsize = attr->initialized_size;
1274 buffer = malloc (BUFSIZE);
1276 Eprintf ("Couldn't allocate memory in scan_disk()\n");
1282 int flags = REG_NOSUB;
1284 if (!opts.match_case)
1286 if (regcomp (&re, opts.match, flags)) {
1287 Eprintf ("Couldn't create a regex.\n");
1292 Qprintf ("Inode Flags %%age Date Size Filename\n");
1293 Qprintf ("---------------------------------------------------------------\n");
1294 for (i = 0; i < bmpsize; i += BUFSIZE) {
1295 read = min ((bmpsize - i), BUFSIZE);
1296 size = ntfs_attr_pread (attr, i, read, buffer);
1300 for (j = 0; j < size; j++) {
1302 for (k = 0; k < 8; k++, b>>=1) {
1303 if (((i+j)*8+k) >= vol->nr_mft_records)
1307 file = read_record (vol, (i+j)*8+k);
1309 Eprintf ("Couldn't read MFT Record %d.\n", (i+j)*8+k);
1313 if ((opts.since > 0) && (file->date <= opts.since))
1315 if (opts.match && !name_match (&re, file))
1317 if (opts.size_begin && (opts.size_begin > file->max_size))
1319 if (opts.size_end && (opts.size_end < file->max_size))
1322 percent = calc_percentage (file, vol);
1324 if ((opts.percent == -1) || (percent >= opts.percent)) {
1331 if (((opts.percent == -1) && (percent > 0)) ||
1332 ((opts.percent > 0) && (percent >= opts.percent))) {
1341 Qprintf ("\nFiles with potentially recoverable content: %d\n", results);
1347 ntfs_attr_close (attr);
1352 * undelete_file - Recover a deleted file from an NTFS volume
1353 * @vol: An ntfs volume obtained from ntfs_mount
1354 * @inode: MFT Record number to be recovered
1356 * Read an MFT Record and try an recover any data associated with it. Some of
1357 * the clusters may be in use; these will be filled with zeros or the fill byte
1358 * supplied in the options.
1360 * Each data stream will be recovered and saved to a file. The file's name will
1361 * be the original filename and it will be written to the current directory.
1362 * Any named data stream will be saved as filename:streamname.
1364 * The output file's name and location can be altered by using the command line
1367 * N.B. We cannot tell if someone has overwritten some of the data since the
1370 * Return: 0 Error, something went wrong
1371 * 1 Success, the data was recovered
1373 int undelete_file (ntfs_volume *vol, long long inode)
1376 char *buffer = NULL;
1377 unsigned int bufsize;
1380 long long start, end;
1381 runlist_element *rl;
1382 struct list_head *item;
1390 file = read_record (vol, inode);
1391 if (!file || !file->mft) {
1392 Eprintf ("Can't read info from mft record %lld.\n", inode);
1396 bufsize = vol->cluster_size;
1397 buffer = malloc (bufsize);
1404 Qprintf ("Inode Flags %%age Date Size Filename\n");
1405 Qprintf ("---------------------------------------------------------------\n");
1410 if (file->mft->flags & MFT_RECORD_IN_USE) {
1411 Eprintf ("Record is in use by the mft\n");
1416 Vprintf ("Forced to continue.\n");
1419 if (calc_percentage (file, vol) == 0) {
1420 Qprintf ("File has no recoverable data.\n");
1424 if (list_empty (&file->data)) {
1425 Qprintf ("File has no data. There is nothing to recover.\n");
1429 list_for_each (item, &file->data) {
1430 struct data *d = list_entry (item, struct data, list);
1432 create_pathname (opts.dest, file->pref_name, d->name, pathname, sizeof (pathname));
1434 fd = open_file (pathname);
1436 Eprintf ("Couldn't create file: %s\n", strerror (errno));
1440 Vprintf ("File has resident data.\n");
1441 if (write_data (fd, d->data, d->size_data) < d->size_data) {
1442 Eprintf ("Write failed: %s\n", strerror (errno));
1447 if (close (fd) < 0) {
1448 Eprintf ("Close failed: %s\n", strerror (errno));
1454 Vprintf ("File has no runlist, hence no data.\n");
1458 if (rl[0].length <= 0) {
1459 Vprintf ("File has an empty runlist, hence no data.\n");
1463 fd = open_file (pathname);
1465 Eprintf ("Couldn't create output file: %s\n", strerror (errno));
1469 if (rl[0].lcn == LCN_RL_NOT_MAPPED) { /* extended mft record */
1470 Vprintf ("Missing segment at beginning, %lld clusters.\n", rl[0].length);
1471 memset (buffer, opts.fillbyte, bufsize);
1472 for (k = 0; k < rl[0].length * vol->cluster_size; k += bufsize) {
1473 if (write_data (fd, buffer, bufsize) < bufsize) {
1474 Eprintf ("Write failed: %s\n", strerror (errno));
1481 for (i = 0; rl[i].length > 0; i++) {
1483 if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
1484 Vprintf ("Missing segment at end, %lld clusters.\n", rl[i].length);
1485 memset (buffer, opts.fillbyte, bufsize);
1486 for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) {
1487 if (write_data (fd, buffer, bufsize) < bufsize) {
1488 Eprintf ("Write failed: %s\n", strerror (errno));
1496 if (rl[i].lcn == LCN_HOLE) {
1497 Vprintf ("File has a sparse section.\n");
1498 memset (buffer, 0, bufsize);
1499 for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) {
1500 if (write_data (fd, buffer, bufsize) < bufsize) {
1501 Eprintf ("Write failed: %s\n", strerror (errno));
1510 end = rl[i].lcn + rl[i].length;
1512 for (j = start; j < end; j++) {
1513 if (utils_cluster_in_use (vol, j)) {
1514 memset (buffer, opts.fillbyte, bufsize);
1515 if (write_data (fd, buffer, bufsize) < bufsize) {
1516 Eprintf ("Write failed: %s\n", strerror (errno));
1521 if (ntfs_cluster_read(vol, j, 1, buffer) < 1) {
1522 Eprintf ("Read failed: %s\n", strerror (errno));
1526 if (write_data (fd, buffer, bufsize) < bufsize) {
1527 Eprintf ("Write failed: %s\n", strerror (errno));
1535 if (close (fd) < 0) {
1536 Eprintf ("Close failed: %s\n", strerror (errno));
1541 set_date (pathname, file->date);
1543 Qprintf ("Undeleted '%s:%s' successfully.\n", file->pref_name, d->name);
1545 Qprintf ("Undeleted '%s' successfully.\n", file->pref_name);
1556 * copy_mft - Write a range of MFT Records to a file
1557 * @vol: An ntfs volume obtained from ntfs_mount
1558 * @mft_begin: First MFT Record to save
1559 * @mft_end: Last MFT Record to save
1561 * Read a number of MFT Records and write them to a file.
1563 * Return: 0 Success, all the records were written
1564 * 1 Error, something went wrong
1566 int copy_mft (ntfs_volume *vol, long long mft_begin, long long mft_end)
1579 if (mft_end < mft_begin) {
1580 Eprintf ("Range to copy is backwards.\n");
1584 buffer = malloc (vol->mft_record_size);
1586 Eprintf ("Couldn't allocate memory in copy_mft()\n");
1590 mft = ntfs_attr_open (vol->mft_ni, AT_DATA, NULL, 0);
1592 Eprintf ("Couldn't open $MFT/$DATA: %s\n", strerror (errno));
1599 Dprintf ("No output filename, defaulting to '%s'.\n", name);
1602 create_pathname (opts.dest, name, NULL, pathname, sizeof (pathname));
1603 fd = open_file (pathname);
1605 Eprintf ("Couldn't open output file '%s': %s\n", name, strerror (errno));
1609 mft_end = min (mft_end, vol->nr_mft_records - 1);
1611 Dprintf ("MFT records\n");
1612 Dprintf (" Total: %8lld\n", vol->nr_mft_records);
1613 Dprintf (" Begin: %8lld\n", mft_begin);
1614 Dprintf (" End: %8lld\n", mft_end);
1616 for (i = mft_begin; i <= mft_end; i++) {
1617 if (ntfs_attr_pread (mft, vol->mft_record_size * i, vol->mft_record_size, buffer) < vol->mft_record_size) {
1618 Eprintf ("Couldn't read MFT Record %lld: %s.\n", i, strerror (errno));
1622 if (write_data (fd, buffer, vol->mft_record_size) < vol->mft_record_size) {
1623 Eprintf ("Write failed: %s\n", strerror (errno));
1628 Vprintf ("Read %lld MFT Records\n", mft_end - mft_begin + 1);
1633 ntfs_attr_close (mft);
1644 * Return: 0 Success, the program worked
1645 * 1 Error, something went wrong
1647 int main (int argc, char *argv[])
1652 if (!parse_options (argc, argv))
1657 vol = utils_mount_volume (opts.device, MS_RDONLY, opts.force);
1661 switch (opts.mode) {
1663 result = !scan_disk (vol);
1665 Vprintf ("Failed to scan device '%s'.\n", opts.device);
1668 result = !undelete_file (vol, opts.uinode);
1670 Vprintf ("Failed to undelete inode %d.\n", opts.uinode);
1673 result = !copy_mft (vol, opts.mft_begin, opts.mft_end);
1675 Vprintf ("Failed to read MFT blocks %lld-%lld.\n",
1676 opts.mft_begin, min (vol->nr_mft_records, opts.mft_end));
1679 ; /* Cannot happen */
1682 ntfs_umount (vol, FALSE);