branch update for ntfsprogs_200309071734
[ntfsprogs.git] / ntfsprogs / ntfsundelete.c
1 /**
2  * ntfsundelete - Part of the Linux-NTFS project.
3  *
4  * Copyright (c) 2002-2003 Richard Russon
5  *
6  * This utility will recover deleted files from an NTFS volume.
7  *
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.
12  *
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.
17  *
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
22  */
23
24 #include "config.h"
25
26 #include <features.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <unistd.h>
34 #include <fcntl.h>
35 #include <getopt.h>
36 #include <time.h>
37 #include <limits.h>
38 #include <regex.h>
39 #include <time.h>
40 #include <stdarg.h>
41 #include <utime.h>
42
43 #include "ntfsundelete.h"
44 #include "bootsect.h"
45 #include "mft.h"
46 #include "attrib.h"
47 #include "layout.h"
48 #include "inode.h"
49 #include "disk_io.h"
50 #include "utils.h"
51 #include "debug.h"
52
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;
59
60 GEN_PRINTF (Eprintf, stderr, NULL,          FALSE)
61 GEN_PRINTF (Vprintf, stdout, &opts.verbose, TRUE)
62 GEN_PRINTF (Qprintf, stdout, &opts.quiet,   FALSE)
63
64 #define _(S)    gettext(S)
65
66 /**
67  * version - Print version information about the program
68  *
69  * Print a copyright statement and a brief description of the program.
70  *
71  * Return:  none
72  */
73 void version (void)
74 {
75         printf ("\n%s v%s - Recover deleted files from an NTFS Volume.\n\n",
76                 EXEC_NAME, VERSION);
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);
80 }
81
82 /**
83  * usage - Print a list of the parameters to the program
84  *
85  * Print a list of the parameters and options for the program.
86  *
87  * Return:  none
88  */
89 void usage (void)
90 {
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"
98                 "\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"
103                 "\n"
104                 "    -c range    --copy range       Write a range of MFT records to a file\n"
105                 "\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",
111                 EXEC_NAME);
112         printf ("%s%s\n", ntfs_bugs, ntfs_home);
113 }
114
115 /**
116  * transform - Convert a shell style pattern to a regex
117  * @pattern:  String to be converted
118  * @regex:    Resulting regular expression is put here
119  *
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
123  *
124  * Before  After
125  *   .       \.
126  *   *       .*
127  *   ?       .
128  *
129  * Notes:
130  *     The returned string must be freed by the caller.
131  *     If transform fails, @regex will not be changed.
132  *
133  * Return:  1, Success, the string was transformed
134  *          0, An error occurred
135  */
136 int transform (const char *pattern, char **regex)
137 {
138         char *result;
139         int length, i, j;
140
141         if (!pattern || !regex)
142                 return 0;
143
144         length = strlen (pattern);
145         if (length < 1) {
146                 Eprintf ("Pattern to transform is empty\n");
147                 return 0;
148         }
149
150         for (i = 0; pattern[i]; i++) {
151                 if ((pattern[i] == '*') || (pattern[i] == '.'))
152                         length++;
153         }
154
155         result = malloc (length + 3);
156         if (!result) {
157                 Eprintf ("Couldn't allocate memory in transform()\n");
158                 return 0;
159         }
160
161         result[0] = '^';
162
163         for (i = 0, j = 1; pattern[i]; i++, j++) {
164                 if (pattern[i] == '*') {
165                         result[j] = '.';
166                         j++;
167                         result[j] = '*';
168                 } else if (pattern[i] == '.') {
169                         result[j] = '\\';
170                         j++;
171                         result[j] = '.';
172                 } else if (pattern[i] == '?') {
173                         result[j] = '.';
174                 } else {
175                         result[j] = pattern[i];
176                 }
177         }
178
179         result[j]   = '$';
180         result[j+1] = 0;
181         Dprintf ("Pattern '%s' replaced with regex '%s'\n", pattern, result);
182
183         *regex = result;
184         return 1;
185 }
186
187 /**
188  * parse_time - Convert a time abbreviation to seconds
189  * @string:  The string to be converted
190  * @since:   The absolute time referred to
191  *
192  * Strings representing times will be converted into a time_t.  The numbers will
193  * be regarded as seconds unless suffixed.
194  *
195  * Suffix  Description
196  *  [yY]      Year
197  *  [mM]      Month
198  *  [wW]      Week
199  *  [dD]      Day
200  *  [sS]      Second
201  *
202  * Therefore, passing "1W" will return the time_t representing 1 week ago.
203  *
204  * Notes:
205  *     Only the first character of the suffix is read.
206  *     If parse_time fails, @since will not be changed
207  *
208  * Return:  1  Success
209  *          0  Error, the string was malformed
210  */
211 int parse_time (const char *value, time_t *since)
212 {
213         time_t result, now;
214         char *suffix = NULL;
215
216         if (!value || !since)
217                 return -1;
218
219         Dprintf ("parsing time '%s' ago\n", value);
220
221         result = strtoll (value, &suffix, 10);
222         if (result < 0 || errno == ERANGE) {
223                 Eprintf ("Invalid time '%s'.\n", value);
224                 return 0;
225         }
226
227         if (!suffix) {
228                 Eprintf ("Internal error, strtoll didn't return a suffix.\n");
229                 return 0;
230         }
231
232         if (strlen (suffix) > 1) {
233                 Eprintf ("Invalid time suffix '%s'.  Use Y, M, W, D or H.\n", suffix);
234                 return 0;
235         }
236
237         switch (suffix[0]) {
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;
243                 case 0:
244                     break;
245
246                 default:
247                         Eprintf ("Invalid time suffix '%s'.  Use Y, M, W, D or H.\n", suffix);
248                         return 0;
249         }
250
251         now = time (NULL);
252
253         Dprintf ("Time now = %lld, Time then = %lld.\n", (long long) now, (long long) result);
254         *since = now - result;
255         return 1;
256 }
257
258 /**
259  * parse_options - Read and validate the programs command line
260  *
261  * Read the command line, verify the syntax and parse the options.
262  * This function is very long, but quite simple.
263  *
264  * Return:  1 Success
265  *          0 Error, one or more problems
266  */
267 int parse_options (int argc, char *argv[])
268 {
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' },
287                 { NULL, 0, NULL, 0 }
288         };
289
290         char c = -1;
291         char *end = NULL;
292         int err  = 0;
293         int ver  = 0;
294         int help = 0;
295
296         opterr = 0; /* We'll handle the errors, thank you. */
297
298         opts.mode     = MODE_NONE;
299         opts.uinode   = -1;
300         opts.percent  = -1;
301         opts.fillbyte = -1;
302
303         while ((c = getopt_long (argc, argv, sopt, lopt, NULL)) != -1) {
304                 switch (c) {
305                 case 1: /* A non-option argument */
306                         if (!opts.device) {
307                                 opts.device = argv[optind-1];
308                         } else {
309                                 opts.device = NULL;
310                                 err++;
311                         }
312                         break;
313                 case 'b':
314                         if (opts.fillbyte == -1) {
315                                 end = NULL;
316                                 opts.fillbyte = strtol (optarg, &end, 0);
317                                 if (end && *end)
318                                         err++;
319                         } else {
320                                 err++;
321                         }
322                         break;
323                 case 'C':
324                         opts.match_case++;
325                         break;
326                 case 'c':
327                         if (opts.mode == MODE_NONE) {
328                                 if (!utils_parse_range (argv[optind-1],
329                                     &opts.mft_begin, &opts.mft_end, TRUE))
330                                         err++;
331                                 opts.mode = MODE_COPY;
332                         } else {
333                                 opts.mode = MODE_ERROR;
334                         }
335                         break;
336                 case 'd':
337                         if (!opts.dest)
338                                 opts.dest = argv[optind-1];
339                         else
340                                 err++;
341                         break;
342                 case 'f':
343                         opts.force++;
344                         break;
345                 case 'h':
346                 case '?':
347                         help++;
348                         break;
349                 case 'm':
350                         if (!opts.match) {
351                                 if (!transform (argv[optind-1], &opts.match))
352                                         err++;
353                         } else {
354                                 err++;
355                         }
356                         break;
357                 case 'o':
358                         if (!opts.output) {
359                                 opts.output = argv[optind-1];
360                         } else {
361                                 err++;
362                         }
363                         break;
364                 case 'p':
365                         if (opts.percent == -1) {
366                                 end = NULL;
367                                 opts.percent = strtol (optarg, &end, 0);
368                                 if (end && ((*end != '%') && (*end != 0)))
369                                         err++;
370                         } else {
371                                 err++;
372                         }
373                         break;
374                 case 'q':
375                         opts.quiet++;
376                         break;
377                 case 's':
378                         if (opts.mode == MODE_NONE)
379                                 opts.mode = MODE_SCAN;
380                         else
381                                 opts.mode = MODE_ERROR;
382                         break;
383                 case 'S':
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)) {
387                             err++;
388                         }
389                         break;
390                 case 't':
391                         if (opts.since == 0) {
392                                 if (!parse_time (argv[optind-1], &opts.since))
393                                         err++;
394                         } else {
395                             err++;
396                         }
397                         break;
398                 case 'u':
399                         if (opts.mode == MODE_NONE) {
400                                 end = NULL;
401                                 opts.mode = MODE_UNDELETE;
402                                 opts.uinode = strtol (optarg, &end, 0);
403                                 if (end && *end)
404                                         err++;
405                         } else {
406                                 opts.mode = MODE_ERROR;
407                         }
408                         break;
409                 case 'v':
410                         opts.verbose++;
411                         break;
412                 case 'V':
413                         ver++;
414                         break;
415                 default:
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]);
422                         } else {
423                                 Eprintf ("Unknown option '%s'.\n", argv[optind-1]);
424                         }
425                         err++;
426                         break;
427                 }
428         }
429
430         if (help || ver) {
431                 opts.quiet = 0;
432         } else {
433                 if (opts.device == NULL) {
434                         if (argc > 1)
435                                 Eprintf ("You must specify exactly one device.\n");
436                         err++;
437                 }
438
439                 if (opts.mode == MODE_NONE) {
440                         opts.mode = MODE_SCAN;
441                 }
442
443                 switch (opts.mode) {
444                 case 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");
448                                 err++;
449                         }
450                         if (opts.match_case && !opts.match) {
451                                 Eprintf ("The --case option doesn't make sense without the --match option\n");
452                                 err++;
453                         }
454                         break;
455                 case MODE_UNDELETE:
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");
460                                 err++;
461                         }
462                         break;
463                 case MODE_COPY:
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");
468                                 err++;
469                         }
470                         break;
471                 default:
472                         Eprintf ("You can only select one of Scan, Undelete or Copy.\n");
473                         err++;
474                 }
475
476                 if ((opts.percent < -1) || (opts.percent > 100)) {
477                         Eprintf ("Percentage value must be in the range 0 - 100.\n");
478                         err++;
479                 }
480
481                 if (opts.quiet) {
482                         if (opts.verbose) {
483                                 Eprintf ("You may not use --quiet and --verbose at the same time.\n");
484                                 err++;
485                         } else if (opts.mode == MODE_SCAN) {
486                                 Eprintf ("You may not use --quiet when scanning a volume.\n");
487                                 err++;
488                         }
489                 }
490         }
491
492         if (opts.fillbyte == -1)
493                 opts.fillbyte = 0;
494
495         if (ver)
496                 version();
497         if (help || err)
498                 usage();
499
500         return (!err && !help && !ver);
501 }
502
503
504 /**
505  * free_file - Release the resources used by a file object
506  * @file:  The unwanted file object
507  *
508  * This will free up the memory used by a file object and iterate through the
509  * object's children, freeing their resources too.
510  *
511  * Return:  none
512  */
513 void free_file (struct ufile *file)
514 {
515         struct list_head *item, *tmp;
516
517         if (!file)
518                 return;
519
520         list_for_each_safe (item, tmp, &file->name) { /* List of filenames */
521                 struct filename *f = list_entry (item, struct filename, list);
522                 Dprintf ("freeing filename '%s'\n", f->name ? f->name : NONE);
523                 if (f->name)
524                         free (f->name);
525                 free (f);
526         }
527
528         list_for_each_safe (item, tmp, &file->data) { /* List of data streams */
529                 struct data *d = list_entry (item, struct data, list);
530                 Dprintf ("freeing data stream '%s'\n", d->name ? d->name : UNNAMED);
531                 if (d->name)
532                         free (d->name);
533                 if (d->runlist)
534                         free (d->runlist);
535                 free (d);
536         }
537
538         free (file->mft);
539         free (file);
540 }
541
542 /**
543  * get_filenames - Read an MFT Record's $FILENAME attributes
544  * @file:  The file object to work with
545  *
546  * A single file may have more than one filename.  This is quite common.
547  * Windows creates a short DOS name for each long name, e.g. LONGFI~1.XYZ,
548  * LongFiLeName.xyZ.
549  *
550  * The filenames that are found are put in filename objects and added to a
551  * linked list of filenames in the file object.  For convenience, the unicode
552  * filename is converted into the current locale and stored in the filename
553  * object.
554  *
555  * One of the filenames is picked (the one with the lowest numbered namespace)
556  * and its locale friendly name is put in pref_name.
557  *
558  * Return:  n  The number of $FILENAME attributes found
559  *         -1  Error
560  */
561 int get_filenames (struct ufile *file)
562 {
563         ATTR_RECORD *rec;
564         FILE_NAME_ATTR *attr;
565         ntfs_attr_search_ctx *ctx;
566         struct filename *name;
567         int count = 0;
568         int space = 4;
569
570         if (!file)
571                 return -1;
572
573         ctx = ntfs_attr_get_search_ctx (NULL, file->mft);
574         if (!ctx)
575                 return -1;
576
577         while ((rec = find_attribute (AT_FILE_NAME, ctx))) {
578                 /* We know this will always be resident. */
579                 attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu (rec->value_offset));
580
581                 name = calloc (1, sizeof (*name));
582                 if (!name) {
583                         Eprintf ("Couldn't allocate memory in get_filenames().\n");
584                         count = -1;
585                         break;
586                 }
587
588                 name->uname      = attr->file_name;
589                 name->uname_len  = attr->file_name_length;
590                 name->name_space = attr->file_name_type;
591                 name->size_alloc = sle64_to_cpu (attr->allocated_size);
592                 name->size_data  = sle64_to_cpu (attr->data_size);
593                 name->flags      = attr->file_attributes;
594
595                 name->date_c     = ntfs2utc (sle64_to_cpu (attr->creation_time));
596                 name->date_a     = ntfs2utc (sle64_to_cpu (attr->last_data_change_time));
597                 name->date_m     = ntfs2utc (sle64_to_cpu (attr->last_mft_change_time));
598                 name->date_r     = ntfs2utc (sle64_to_cpu (attr->last_access_time));
599
600                 if (ntfs_ucstombs (name->uname, name->uname_len, &name->name,
601                     name->uname_len) < 0) {
602                         Dprintf ("Couldn't translate filename to current locale.\n");
603                 }
604
605                 if (name->name_space < space) {
606                         file->pref_name = name->name;
607                         space = name->name_space;
608                 }
609
610                 file->max_size = max (file->max_size, name->size_alloc);
611                 file->max_size = max (file->max_size, name->size_data);
612
613                 list_add_tail (&name->list, &file->name);
614                 count++;
615         }
616
617         ntfs_attr_put_search_ctx(ctx);
618         Dprintf ("File has %d names.\n", count);
619         return count;
620 }
621
622 /**
623  * get_data - Read an MFT Record's $DATA attributes
624  * @file:  The file object to work with
625  * @vol:  An ntfs volume obtained from ntfs_mount
626  *
627  * A file may have more than one data stream.  All files will have an unnamed
628  * data stream which contains the file's data.  Some Windows applications store
629  * extra information in a separate stream.
630  *
631  * The streams that are found are put in data objects and added to a linked
632  * list of data streams in the file object.
633  *
634  * Return:  n  The number of $FILENAME attributes found
635  *         -1  Error
636  */
637 int get_data (struct ufile *file, ntfs_volume *vol)
638 {
639         ATTR_RECORD *rec;
640         ntfs_attr_search_ctx *ctx;
641         int count = 0;
642         struct data *data;
643
644         if (!file)
645                 return -1;
646
647         ctx = ntfs_attr_get_search_ctx (NULL, file->mft);
648         if (!ctx)
649                 return -1;
650
651         while ((rec = find_attribute (AT_DATA, ctx))) {
652                 data = calloc (1, sizeof (*data));
653                 if (!data) {
654                         Eprintf ("Couldn't allocate memory in get_data().\n");
655                         count = -1;
656                         break;
657                 }
658
659                 data->resident   = !rec->non_resident;
660                 data->compressed = rec->flags & ATTR_IS_COMPRESSED;
661                 data->encrypted  = rec->flags & ATTR_IS_ENCRYPTED;
662
663                 if (rec->name_length) {
664                         data->uname     = (uchar_t *) ((char *) rec + le16_to_cpu (rec->name_offset));
665                         data->uname_len = rec->name_length;
666
667                         if (ntfs_ucstombs (data->uname, data->uname_len, &data->name,
668                             data->uname_len) < 0) {
669                                 Eprintf ("Cannot translate name into current locale.\n");
670                         }
671                 }
672
673                 if (data->resident) {
674                         data->size_data  = le32_to_cpu (rec->value_length);
675                         data->data       = ((char*) (rec)) + le16_to_cpu (rec->value_offset);
676                 } else {
677                         data->size_alloc = sle64_to_cpu (rec->allocated_size);
678                         data->size_data  = sle64_to_cpu (rec->data_size);
679                         data->size_init  = sle64_to_cpu (rec->initialized_size);
680                         data->size_vcn   = sle64_to_cpu (rec->highest_vcn) + 1;
681                 }
682
683                 data->runlist = ntfs_mapping_pairs_decompress(vol, rec, NULL);
684                 if (!data->runlist) {
685                         Dprintf ("Couldn't decompress the data runs\n");
686                 }
687
688                 file->max_size = max (file->max_size, data->size_data);
689                 file->max_size = max (file->max_size, data->size_init);
690
691                 list_add_tail (&data->list, &file->data);
692                 count++;
693         }
694
695         ntfs_attr_put_search_ctx(ctx);
696         Dprintf ("File has %d data streams.\n", count);
697         return count;
698 }
699
700 /**
701  * read_record - Read an MFT record into memory
702  * @vol:     An ntfs volume obtained from ntfs_mount
703  * @record:  The record number to read
704  *
705  * Read the specified MFT record and gather as much information about it as
706  * possible.
707  *
708  * Return:  Pointer  A ufile object containing the results
709  *          NULL     Error
710  */
711 struct ufile * read_record (ntfs_volume *vol, long long record)
712 {
713         ATTR_RECORD *attr10, *attr20, *attr90;
714         struct ufile *file;
715         ntfs_attr *mft;
716
717         if (!vol)
718                 return NULL;
719
720         file = calloc (1, sizeof (*file));
721         if (!file) {
722                 Eprintf ("Couldn't allocate memory in read_record()\n");
723                 return NULL;
724         }
725
726         INIT_LIST_HEAD (&file->name);
727         INIT_LIST_HEAD (&file->data);
728         file->inode = record;
729
730         file->mft = malloc (vol->mft_record_size);
731         if (!file->mft) {
732                 Eprintf ("Couldn't allocate memory in read_record()\n");
733                 free_file (file);
734                 return NULL;
735         }
736
737         mft = ntfs_attr_open (vol->mft_ni, AT_DATA, NULL, 0);
738         if (!mft) {
739                 Eprintf ("Couldn't open $MFT/$DATA: %s\n", strerror (errno));
740                 free_file (file);
741                 return NULL;
742         }
743
744         if (ntfs_attr_mst_pread (mft, vol->mft_record_size * record, 1, vol->mft_record_size, file->mft) < 1) {
745                 Eprintf ("Couldn't read MFT Record %lld.\n", record);
746                 ntfs_attr_close (mft);
747                 free_file (file);
748                 return NULL;
749         }
750
751         ntfs_attr_close (mft);
752         mft = NULL;
753
754         attr10 = find_first_attribute (AT_STANDARD_INFORMATION, file->mft);
755         attr20 = find_first_attribute (AT_ATTRIBUTE_LIST,       file->mft);
756         attr90 = find_first_attribute (AT_INDEX_ROOT,           file->mft);
757
758         Dprintf ("Attributes present: %s %s %s\n", attr10?"0x10":"", attr20?"0x20":"", attr90?"0x90":"");
759
760         if (attr10)
761         {
762                 STANDARD_INFORMATION *si;
763                 si = (STANDARD_INFORMATION *) ((char *) attr10 + le16_to_cpu (attr10->value_offset));
764                 file->date = ntfs2utc (sle64_to_cpu (si->last_data_change_time));
765         }
766
767         if (attr20 || !attr10)
768                 file->attr_list = 1;
769         if (attr90)
770                 file->directory = 1;
771
772         if (get_filenames (file) < 0) {
773                 Eprintf ("Couldn't get filenames.\n");
774         }
775         if (get_data (file, vol) < 0) {
776                 Eprintf ("Couldn't get data streams.\n");
777         }
778
779         return file;
780 }
781
782
783 /**
784  * calc_percentage - Calculate how much of the file is recoverable
785  * @file:  The file object to work with
786  * @vol:   An ntfs volume obtained from ntfs_mount
787  *
788  * Read through all the $DATA streams and determine if each cluster in each
789  * stream is still free disk space.  This is just measuring the potential for
790  * recovery.  The data may have still been overwritten by a another file which
791  * was then deleted.
792  *
793  * Files with a resident $DATA stream will have a 100% potential.
794  *
795  * N.B.  If $DATA attribute spans more than one MFT record (i.e. badly
796  *       fragmented) then only the data in this segment will be used for the
797  *       calculation.
798  *
799  * N.B.  Currently, compressed and encrypted files cannot be recovered, so they
800  *       will return 0%.
801  *
802  * Return:  n  The percentage of the file that _could_ be recovered
803  *         -1  Error
804  */
805 int calc_percentage (struct ufile *file, ntfs_volume *vol)
806 {
807         runlist_element *rl = NULL;
808         struct list_head *pos;
809         struct data *data;
810         long long i, j;
811         long long start, end;
812         int inuse, free;
813         int percent = 0;
814
815         if (!file || !vol)
816                 return -1;
817
818         if (file->directory) {
819                 Dprintf ("Found a directory: not recoverable.\n");
820                 return 0;
821         }
822
823         if (list_empty (&file->data)) {
824                 Vprintf ("File has no data streams.\n");
825                 return 0;
826         }
827
828         list_for_each (pos, &file->data) {
829                 data  = list_entry (pos, struct data, list);
830                 inuse = 0;
831                 free  = 0;
832
833                 if (data->encrypted) {
834                         Vprintf ("File is encrypted, recovery is impossible.\n");
835                         continue;
836                 }
837
838                 if (data->compressed) {
839                         Vprintf ("File is compressed, recovery not yet implemented.\n");
840                         continue;
841                 }
842
843                 if (data->resident) {
844                         Vprintf ("File is resident, therefore recoverable.\n");
845                         percent = 100;
846                         data->percent = 100;
847                         continue;
848                 }
849
850                 rl = data->runlist;
851                 if (!rl) {
852                         Vprintf ("File has no runlist, hence no data.\n");
853                         continue;
854                 }
855
856                 if (rl[0].length <= 0) {
857                         Vprintf ("File has an empty runlist, hence no data.\n");
858                         continue;
859                 }
860
861                 if (rl[0].lcn == LCN_RL_NOT_MAPPED) {   /* extended mft record */
862                         Vprintf ("Missing segment at beginning, %lld clusters\n", rl[0].length);
863                         inuse += rl[0].length;
864                         rl++;
865                 }
866
867                 for (i = 0; rl[i].length > 0; i++) {
868                         if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
869                                 Vprintf ("Missing segment at end, %lld clusters\n", rl[i].length);
870                                 inuse += rl[i].length;
871                                 continue;
872                         }
873
874                         if (rl[i].lcn == LCN_HOLE) {
875                                 free += rl[i].length;
876                                 continue;
877                         }
878
879                         start = rl[i].lcn;
880                         end   = rl[i].lcn + rl[i].length;
881
882                         for (j = start; j < end; j++) {
883                                 if (utils_cluster_in_use (vol, j))
884                                         inuse++;
885                                 else
886                                         free++;
887                         }
888                 }
889
890                 if ((inuse + free) == 0) {
891                         Eprintf ("Unexpected error whilst calculating percentage for inode %lld\n", file->inode);
892                         continue;
893                 }
894
895                 data->percent = (free * 100) / (inuse + free);
896
897                 percent = max (percent, data->percent);
898         }
899
900         Vprintf ("File is %d%% recoverable\n", percent);
901         return percent;
902 }
903
904 /**
905  * dump_record - Print everything we know about an MFT record
906  * @file:  The file to work with
907  *
908  * Output the contents of the file object.  This will print everything that has
909  * been read from the MFT record, or implied by various means.
910  *
911  * Because of the redundant nature of NTFS, there will be some duplication of
912  * information, though it will have been read from different sources.
913  *
914  * N.B.  If the filename is missing, or couldn't be converted to the current
915  *       locale, "<none>" will be displayed.
916  *
917  * Return:  none
918  */
919 void dump_record (struct ufile *file)
920 {
921         char buffer[20];
922         char *name;
923         struct list_head *item;
924         int i;
925
926         if (!file)
927                 return;
928
929         Qprintf ("MFT Record %lld\n", file->inode);
930         Qprintf ("Type: %s\n", (file->directory) ? "Directory" : "File");
931         strftime (buffer, sizeof (buffer), "%F %R", localtime (&file->date));
932         Qprintf ("Date: %s\n", buffer);
933
934         if (file->attr_list)
935                 Qprintf ("Metadata may span more than one MFT record\n");
936
937         list_for_each (item, &file->name) {
938                 struct filename *f = list_entry (item, struct filename, list);
939
940                 if (f->name)
941                         name = f->name;
942                 else
943                         name = NONE;
944
945                 Qprintf ("Filename: (%d) %s\n", f->name_space, f->name);
946                 Qprintf ("File Flags: ");
947                 if (f->flags & FILE_ATTR_SYSTEM)        Qprintf ("System ");
948                 if (f->flags & FILE_ATTR_DIRECTORY)     Qprintf ("Directory ");
949                 if (f->flags & FILE_ATTR_SPARSE_FILE)   Qprintf ("Sparse ");
950                 if (f->flags & FILE_ATTR_REPARSE_POINT) Qprintf ("Reparse ");
951                 if (f->flags & FILE_ATTR_COMPRESSED)    Qprintf ("Compressed ");
952                 if (f->flags & FILE_ATTR_ENCRYPTED)     Qprintf ("Encrypted ");
953                 if (!(f->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_DIRECTORY |
954                     FILE_ATTR_SPARSE_FILE | FILE_ATTR_REPARSE_POINT |
955                     FILE_ATTR_COMPRESSED | FILE_ATTR_ENCRYPTED))) {
956                         Qprintf (NONE);
957                 }
958                 Qprintf ("\n");
959                 Qprintf ("Size alloc: %lld\n", f->size_alloc);
960                 Qprintf ("Size data: %lld\n", f->size_data);
961
962                 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_c));
963                 Qprintf ("Date C: %s\n", buffer);
964                 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_a));
965                 Qprintf ("Date A: %s\n", buffer);
966                 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_m));
967                 Qprintf ("Date M: %s\n", buffer);
968                 strftime (buffer, sizeof (buffer), "%F %R", localtime (&f->date_r));
969                 Qprintf ("Date R: %s\n", buffer);
970         }
971
972         Qprintf ("Data Streams:\n");
973         list_for_each (item, &file->data) {
974                 struct data *d = list_entry (item, struct data, list);
975                 Qprintf ("Name: %s\n", (d->name) ? d->name : "<unnamed>");
976                 Qprintf ("Flags: ");
977                 if (d->resident)   Qprintf ("Resident\n");
978                 if (d->compressed) Qprintf ("Compressed\n");
979                 if (d->encrypted)  Qprintf ("Encrypted\n");
980                 if (!d->resident && !d->compressed && !d->encrypted)
981                         Qprintf ("None\n");
982                 else
983                         Qprintf ("\n");
984
985                 Qprintf ("Size alloc: %lld\n", d->size_alloc);
986                 Qprintf ("Size data: %lld\n", d->size_data);
987                 Qprintf ("Size init: %lld\n", d->size_init);
988                 Qprintf ("Size vcn: %lld\n", d->size_vcn);
989
990                 Qprintf ("Data runs:\n");
991                 if ((!d->runlist) || (d->runlist[0].length <= 0)) {
992                         Qprintf ("    None\n");
993                 } else {
994                         for (i = 0; d->runlist[i].length > 0; i++) {
995                                 Qprintf ("    %lld @ %lld\n", d->runlist[i].length, d->runlist[i].lcn);
996                         }
997                 }
998
999                 Qprintf ("Amount potentially recoverable %d%%\n", d->percent);
1000         }
1001
1002         Qprintf ("________________________________________\n\n");
1003 }
1004
1005 /**
1006  * list_record - Print a one line summary of the file
1007  * @file:  The file to work with
1008  *
1009  * Print a one line description of a file.
1010  *
1011  *   Inode    Flags  %age  Date            Size  Filename
1012  *
1013  * The output will contain the file's inode number (MFT Record), some flags,
1014  * the percentage of the file that is recoverable, the last modification date,
1015  * the size and the filename.
1016  *
1017  * The flags are F/D = File/Directory, N/R = Data is (Non-)Resident,
1018  * C = Compressed, E = Encrypted, ! = Metadata may span multiple records.
1019  *
1020  * N.B.  The file size is stored in many forms in several attributes.   This
1021  *       display the largest it finds.
1022  *
1023  * N.B.  If the filename is missing, or couldn't be converted to the current
1024  *       locale, "<none>" will be displayed.
1025  *
1026  * Return:  none
1027  */
1028 void list_record (struct ufile *file)
1029 {
1030         char buffer[20];
1031         struct list_head *item;
1032         char *name = NULL;
1033         long long size = 0;
1034         int percent = 0;
1035
1036         char flagd = '.', flagr = '.', flagc = '.', flagx = '.';
1037
1038         strftime (buffer, sizeof (buffer), "%F", localtime (&file->date));
1039
1040         if (file->attr_list)
1041                 flagx = '!';
1042
1043         if (file->directory)
1044                 flagd = 'D';
1045         else
1046                 flagd = 'F';
1047
1048         list_for_each (item, &file->data) {
1049                 struct data *d = list_entry (item, struct data, list);
1050
1051                 if (!d->name) {
1052                         if (d->resident)   flagr = 'R';
1053                         else               flagr = 'N';
1054                         if (d->compressed) flagc = 'C'; /* These two are mutually exclusive */
1055                         if (d->encrypted)  flagc = 'E';
1056
1057                         percent = max (percent, d->percent);
1058                 }
1059
1060                 size = max (size, d->size_data);
1061                 size = max (size, d->size_init);
1062         }
1063
1064         if (file->pref_name)
1065                 name = file->pref_name;
1066         else
1067                 name = NONE;
1068
1069         Qprintf ("%-8lld %c%c%c%c   %3d%%  %s %9lld  %s\n",
1070                 file->inode, flagd, flagr, flagc, flagx,
1071                 percent, buffer, size, name);
1072 }
1073
1074 /**
1075  * name_match - Does a file have a name matching a regex
1076  * @re:    The regular expression object
1077  * @file:  The file to be tested
1078  *
1079  * Iterate through the file's $FILENAME attributes and compare them against the
1080  * regular expression, created with regcomp.
1081  *
1082  * Return:  1  There is a matching filename.
1083  *          0  There is no match.
1084  */
1085 int name_match (regex_t *re, struct ufile *file)
1086 {
1087         struct list_head *item;
1088         int result;
1089
1090         if (!re || !file)
1091                 return 0;
1092
1093         list_for_each (item, &file->name) {
1094                 struct filename *f = list_entry (item, struct filename, list);
1095
1096                 if (!f->name)
1097                         continue;
1098                 result = regexec (re, f->name, 0, NULL, 0);
1099                 if (result < 0) {
1100                         Eprintf ("Couldn't compare filename with regex: %s\n", strerror (errno));
1101                         return 0;
1102                 } else if (result == REG_NOERROR) {
1103                         Dprintf ("Found a matching filename.\n");
1104                         return 1;
1105                 }
1106         }
1107
1108         Dprintf ("Filename '%s' doesn't match regex.\n", file->pref_name);
1109         return 0;
1110 }
1111
1112 /**
1113  * write_data - Write out a block of data
1114  * @fd:       File descriptor to write to
1115  * @buffer:   Data to write
1116  * @bufsize:  Amount of data to write
1117  *
1118  * Write a block of data to a file descriptor.
1119  *
1120  * Return:  -1  Error, something went wrong
1121  *           0  Success, all the data was written
1122  */
1123 unsigned int write_data (int fd, const char *buffer, unsigned int bufsize)
1124 {
1125         ssize_t result1, result2;
1126
1127         if (!buffer) {
1128                 errno = EINVAL;
1129                 return -1;
1130         }
1131
1132         result1 = write (fd, buffer, bufsize);
1133         if ((result1 == (ssize_t) bufsize) || (result1 < 0))
1134                 return result1;
1135
1136         /* Try again with the rest of the buffer */
1137         buffer  += result1;
1138         bufsize -= result1;
1139
1140         result2 = write (fd, buffer, bufsize);
1141         if (result2 < 0)
1142                 return result1;
1143
1144         return result1 + result2;
1145 }
1146
1147 /**
1148  * create_pathname - Create a path/file from some components
1149  * @dir:      Directory in which to create the file (optional)
1150  * @name:     Filename to give the file (optional)
1151  * @stream:   Name of the stream (optional)
1152  * @buffer:   Store the result here
1153  * @bufsize:  Size of buffer
1154  *
1155  * Create a filename from various pieces.  The output will be of the form:
1156  *      dir/file
1157  *      dir/file:stream
1158  *      file
1159  *      file:stream
1160  *
1161  * All the components are optional.  If the name is missing, "unknown" will be
1162  * used.  If the directory is missing the file will be created in the current
1163  * directory.  If the stream name is present it will be appended to the
1164  * filename, delimited by a colon.
1165  *
1166  * N.B. If the buffer isn't large enough the name will be truncated.
1167  *
1168  * Return:  n  Length of the allocated name
1169  */
1170 int create_pathname (const char *dir, const char *name, const char *stream,
1171                      char *buffer, int bufsize)
1172 {
1173         if (!name)
1174                 name = UNKNOWN;
1175
1176         if (dir)
1177                 if (stream)
1178                         snprintf (buffer, bufsize, "%s/%s:%s", dir, name, stream);
1179                 else
1180                         snprintf (buffer, bufsize, "%s/%s", dir, name);
1181         else
1182                 if (stream)
1183                         snprintf (buffer, bufsize, "%s:%s", name, stream);
1184                 else
1185                         snprintf (buffer, bufsize, "%s", name);
1186
1187         return strlen (buffer);
1188 }
1189
1190 /**
1191  * open_file - Open a file to write to
1192  * @pathname:  Path, name and stream of the file to open
1193  *
1194  * Create a file and return the file descriptor.
1195  *
1196  * N.B.  If option force is given and existing file will be overwritten.
1197  *
1198  * Return:  -1  Error, failed to create the file
1199  *           n  Success, this is the file descriptor
1200  */
1201 int open_file (const char *pathname)
1202 {
1203         int flags;
1204
1205         Vprintf ("Creating file: %s\n", pathname);
1206
1207         if (opts.force)
1208                 flags = O_RDWR | O_CREAT | O_TRUNC;
1209         else
1210                 flags = O_RDWR | O_CREAT | O_EXCL;
1211
1212         return open (pathname, flags, S_IRUSR | S_IWUSR);
1213 }
1214
1215 /**
1216  * set_date - Set the file's date and time
1217  * @pathname:  Path and name of the file to alter
1218  * @date:      Date and time to set
1219  *
1220  * Give a file a particular date and time.
1221  *
1222  * Return:  1  Success, set the file's date and time
1223  *          0  Error, failed to change the file's date and time
1224  */
1225 int set_date (const char *pathname, time_t date)
1226 {
1227         struct utimbuf ut;
1228
1229         if (!pathname)
1230                 return 0;
1231
1232         ut.actime  = date;
1233         ut.modtime = date;
1234         if (utime (pathname, &ut)) {
1235                 Eprintf ("Couldn't set the file's date and time\n");
1236                 return 0;
1237         }
1238         return 1;
1239 }
1240
1241 /**
1242  * scan_disk - Search an NTFS volume for files that could be undeleted
1243  * @vol:  An ntfs volume obtained from ntfs_mount
1244  *
1245  * Read through all the MFT entries looking for deleted files.  For each one
1246  * determine how much of the data lies in unused disk space.
1247  *
1248  * The list can be filtered by name, size and date, using command line options.
1249  *
1250  * Return:  -1  Error, something went wrong
1251  *           n  Success, the number of recoverable files
1252  */
1253 int scan_disk (ntfs_volume *vol)
1254 {
1255         const int BUFSIZE = 8192;
1256         char *buffer = NULL;
1257         int results = 0;
1258         ntfs_attr *attr;
1259         long long size;
1260         long long read;
1261         long long bmpsize;
1262         int i, j, k, b;
1263         int percent;
1264         struct ufile *file;
1265         regex_t re;
1266
1267         if (!vol)
1268                 return -1;
1269
1270         attr = ntfs_attr_open (vol->mft_ni, AT_BITMAP, AT_UNNAMED, 0);
1271         if (!attr) {
1272                 Eprintf ("Couldn't open $MFT/$BITMAP: %s\n", strerror (errno));
1273                 return -1;
1274         }
1275         bmpsize = attr->initialized_size;
1276
1277         buffer = malloc (BUFSIZE);
1278         if (!buffer) {
1279                 Eprintf ("Couldn't allocate memory in scan_disk()\n");
1280                 results = -1;
1281                 goto out;
1282         }
1283
1284         if (opts.match) {
1285                 int flags = REG_NOSUB;
1286
1287                 if (!opts.match_case)
1288                         flags |= REG_ICASE;
1289                 if (regcomp (&re, opts.match, flags)) {
1290                         Eprintf ("Couldn't create a regex.\n");
1291                         goto out;
1292                 }
1293         }
1294
1295         Qprintf ("Inode    Flags  %%age  Date            Size  Filename\n");
1296         Qprintf ("---------------------------------------------------------------\n");
1297         for (i = 0; i < bmpsize; i += BUFSIZE) {
1298                 read = min ((bmpsize - i), BUFSIZE);
1299                 size = ntfs_attr_pread (attr, i, read, buffer);
1300                 if (size < 0)
1301                         break;
1302
1303                 for (j = 0; j < size; j++) {
1304                         b = buffer[j];
1305                         for (k = 0; k < 8; k++, b>>=1) {
1306                                 if (((i+j)*8+k) >= vol->nr_mft_records)
1307                                         goto done;
1308                                 if (b & 1)
1309                                         continue;
1310                                 file = read_record (vol, (i+j)*8+k);
1311                                 if (!file) {
1312                                         Eprintf ("Couldn't read MFT Record %d.\n", (i+j)*8+k);
1313                                         continue;
1314                                 }
1315
1316                                 if ((opts.since > 0) && (file->date <= opts.since))
1317                                         goto skip;
1318                                 if (opts.match && !name_match (&re, file))
1319                                         goto skip;
1320                                 if (opts.size_begin && (opts.size_begin > file->max_size))
1321                                         goto skip;
1322                                 if (opts.size_end && (opts.size_end < file->max_size))
1323                                         goto skip;
1324
1325                                 percent = calc_percentage (file, vol);
1326
1327                                 if ((opts.percent == -1) || (percent >= opts.percent)) {
1328                                         if (opts.verbose)
1329                                                 dump_record (file);
1330                                         else
1331                                                 list_record (file);
1332                                 }
1333
1334                                 if (((opts.percent == -1) && (percent > 0)) ||
1335                                     ((opts.percent > 0)  && (percent >= opts.percent))) {
1336                                         results++;
1337                                 }
1338 skip:
1339                                 free_file (file);
1340                         }
1341                 }
1342         }
1343 done:
1344         Qprintf ("\nFiles with potentially recoverable content: %d\n", results);
1345 out:
1346         if (opts.match)
1347                 regfree (&re);
1348         free (buffer);
1349         if (attr)
1350                 ntfs_attr_close (attr);
1351         return results;
1352 }
1353
1354 /**
1355  * undelete_file - Recover a deleted file from an NTFS volume
1356  * @vol:    An ntfs volume obtained from ntfs_mount
1357  * @inode:  MFT Record number to be recovered
1358  *
1359  * Read an MFT Record and try an recover any data associated with it.  Some of
1360  * the clusters may be in use; these will be filled with zeros or the fill byte
1361  * supplied in the options.
1362  *
1363  * Each data stream will be recovered and saved to a file.  The file's name will
1364  * be the original filename and it will be written to the current directory.
1365  * Any named data stream will be saved as filename:streamname.
1366  *
1367  * The output file's name and location can be altered by using the command line
1368  * options.
1369  *
1370  * N.B.  We cannot tell if someone has overwritten some of the data since the
1371  *       file was deleted.
1372  *
1373  * Return:  0  Error, something went wrong
1374  *          1  Success, the data was recovered
1375  */
1376 int undelete_file (ntfs_volume *vol, long long inode)
1377 {
1378         char pathname[256];
1379         char *buffer = NULL;
1380         unsigned int bufsize;
1381         struct ufile *file;
1382         int i, j;
1383         long long start, end;
1384         runlist_element *rl;
1385         struct list_head *item;
1386         int fd = -1;
1387         long long k;
1388         int result = 0;
1389
1390         if (!vol)
1391                 return 0;
1392
1393         file = read_record (vol, inode);
1394         if (!file || !file->mft) {
1395                 Eprintf ("Can't read info from mft record %lld.\n", inode);
1396                 return 0;
1397         }
1398
1399         bufsize = vol->cluster_size;
1400         buffer = malloc (bufsize);
1401         if (!buffer)
1402                 goto free;
1403
1404         if (opts.verbose) {
1405                 dump_record (file);
1406         } else {
1407                 Qprintf ("Inode    Flags  %%age  Date            Size  Filename\n");
1408                 Qprintf ("---------------------------------------------------------------\n");
1409                 list_record (file);
1410                 Qprintf ("\n");
1411         }
1412
1413         if (file->mft->flags & MFT_RECORD_IN_USE) {
1414                 Eprintf ("Record is in use by the mft\n");
1415                 if (!opts.force) {
1416                         free_file (file);
1417                         return 0;
1418                 }
1419                 Vprintf ("Forced to continue.\n");
1420         }
1421
1422         if (calc_percentage (file, vol) == 0) {
1423                 Qprintf ("File has no recoverable data.\n");
1424                 goto free;
1425         }
1426
1427         if (list_empty (&file->data)) {
1428                 Qprintf ("File has no data.  There is nothing to recover.\n");
1429                 goto free;
1430         }
1431
1432         list_for_each (item, &file->data) {
1433                 struct data *d = list_entry (item, struct data, list);
1434
1435                 create_pathname (opts.dest, file->pref_name, d->name, pathname, sizeof (pathname));
1436                 if (d->resident) {
1437                         fd = open_file (pathname);
1438                         if (fd < 0) {
1439                                 Eprintf ("Couldn't create file: %s\n", strerror (errno));
1440                                 goto free;
1441                         }
1442
1443                         Vprintf ("File has resident data.\n");
1444                         if (write_data (fd, d->data, d->size_data) < d->size_data) {
1445                                 Eprintf ("Write failed: %s\n", strerror (errno));
1446                                 close (fd);
1447                                 goto free;
1448                         }
1449
1450                         if (close (fd) < 0) {
1451                                 Eprintf ("Close failed: %s\n", strerror (errno));
1452                         }
1453                         fd = -1;
1454                 } else {
1455                         rl = d->runlist;
1456                         if (!rl) {
1457                                 Vprintf ("File has no runlist, hence no data.\n");
1458                                 continue;
1459                         }
1460
1461                         if (rl[0].length <= 0) {
1462                                 Vprintf ("File has an empty runlist, hence no data.\n");
1463                                 continue;
1464                         }
1465
1466                         fd = open_file (pathname);
1467                         if (fd < 0) {
1468                                 Eprintf ("Couldn't create output file: %s\n", strerror (errno));
1469                                 goto free;
1470                         }
1471
1472                         if (rl[0].lcn == LCN_RL_NOT_MAPPED) {   /* extended mft record */
1473                                 Vprintf ("Missing segment at beginning, %lld clusters.\n", rl[0].length);
1474                                 memset (buffer, opts.fillbyte, bufsize);
1475                                 for (k = 0; k < rl[0].length * vol->cluster_size; k += bufsize) {
1476                                         if (write_data (fd, buffer, bufsize) < bufsize) {
1477                                                 Eprintf ("Write failed: %s\n", strerror (errno));
1478                                                 close (fd);
1479                                                 goto free;
1480                                         }
1481                                 }
1482                         }
1483
1484                         for (i = 0; rl[i].length > 0; i++) {
1485
1486                                 if (rl[i].lcn == LCN_RL_NOT_MAPPED) {
1487                                         Vprintf ("Missing segment at end, %lld clusters.\n", rl[i].length);
1488                                         memset (buffer, opts.fillbyte, bufsize);
1489                                         for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) {
1490                                                 if (write_data (fd, buffer, bufsize) < bufsize) {
1491                                                         Eprintf ("Write failed: %s\n", strerror (errno));
1492                                                         close (fd);
1493                                                         goto free;
1494                                                 }
1495                                         }
1496                                         continue;
1497                                 }
1498
1499                                 if (rl[i].lcn == LCN_HOLE) {
1500                                         Vprintf ("File has a sparse section.\n");
1501                                         memset (buffer, 0, bufsize);
1502                                         for (k = 0; k < rl[k].length * vol->cluster_size; k += bufsize) {
1503                                                 if (write_data (fd, buffer, bufsize) < bufsize) {
1504                                                         Eprintf ("Write failed: %s\n", strerror (errno));
1505                                                         close (fd);
1506                                                         goto free;
1507                                                 }
1508                                         }
1509                                         continue;
1510                                 }
1511
1512                                 start = rl[i].lcn;
1513                                 end   = rl[i].lcn + rl[i].length;
1514
1515                                 for (j = start; j < end; j++) {
1516                                         if (utils_cluster_in_use (vol, j)) {
1517                                                 memset (buffer, opts.fillbyte, bufsize);
1518                                                 if (write_data (fd, buffer, bufsize) < bufsize) {
1519                                                         Eprintf ("Write failed: %s\n", strerror (errno));
1520                                                         close (fd);
1521                                                         goto free;
1522                                                 }
1523                                         } else {
1524                                                 if (ntfs_cluster_read(vol, j, 1, buffer) < 1) {
1525                                                         Eprintf ("Read failed: %s\n", strerror (errno));
1526                                                         close (fd);
1527                                                         goto free;
1528                                                 }
1529                                                 if (write_data (fd, buffer, bufsize) < bufsize) {
1530                                                         Eprintf ("Write failed: %s\n", strerror (errno));
1531                                                         close (fd);
1532                                                         goto free;
1533                                                 }
1534                                         }
1535                                 }
1536                         }
1537                         Qprintf ("\n");
1538                         if (close (fd) < 0) {
1539                                 Eprintf ("Close failed: %s\n", strerror (errno));
1540                         }
1541                         fd = -1;
1542
1543                 }
1544                 set_date (pathname, file->date);
1545                 if (d->name)
1546                         Qprintf ("Undeleted '%s:%s' successfully.\n", file->pref_name, d->name);
1547                 else
1548                         Qprintf ("Undeleted '%s' successfully.\n", file->pref_name);
1549         }
1550         result = 1;
1551 free:
1552         if (buffer)
1553                 free (buffer);
1554         free_file (file);
1555         return result;
1556 }
1557
1558 /**
1559  * copy_mft - Write a range of MFT Records to a file
1560  * @vol:        An ntfs volume obtained from ntfs_mount
1561  * @mft_begin:  First MFT Record to save
1562  * @mft_end:    Last MFT Record to save
1563  *
1564  * Read a number of MFT Records and write them to a file.
1565  *
1566  * Return:  0  Success, all the records were written
1567  *          1  Error, something went wrong
1568  */
1569 int copy_mft (ntfs_volume *vol, long long mft_begin, long long mft_end)
1570 {
1571         char pathname[256];
1572         ntfs_attr *mft;
1573         char *buffer;
1574         const char *name;
1575         long long i;
1576         int result = 1;
1577         int fd;
1578
1579         if (!vol)
1580                 return 1;
1581
1582         if (mft_end < mft_begin) {
1583                 Eprintf ("Range to copy is backwards.\n");
1584                 return 1;
1585         }
1586
1587         buffer = malloc (vol->mft_record_size);
1588         if (!buffer) {
1589                 Eprintf ("Couldn't allocate memory in copy_mft()\n");
1590                 return 1;
1591         }
1592
1593         mft = ntfs_attr_open (vol->mft_ni, AT_DATA, NULL, 0);
1594         if (!mft) {
1595                 Eprintf ("Couldn't open $MFT/$DATA: %s\n", strerror (errno));
1596                 goto free;
1597         }
1598
1599         name = opts.output;
1600         if (!name) {
1601                 name = MFTFILE;
1602                 Dprintf ("No output filename, defaulting to '%s'.\n", name);
1603         }
1604
1605         create_pathname (opts.dest, name, NULL, pathname, sizeof (pathname));
1606         fd = open_file (pathname);
1607         if (fd < 0) {
1608                 Eprintf ("Couldn't open output file '%s': %s\n", name, strerror (errno));
1609                 goto attr;
1610         }
1611
1612         mft_end = min (mft_end, vol->nr_mft_records - 1);
1613
1614         Dprintf ("MFT records\n");
1615         Dprintf ("    Total: %8lld\n", vol->nr_mft_records);
1616         Dprintf ("    Begin: %8lld\n", mft_begin);
1617         Dprintf ("    End:   %8lld\n", mft_end);
1618
1619         for (i = mft_begin; i <= mft_end; i++) {
1620                 if (ntfs_attr_pread (mft, vol->mft_record_size * i, vol->mft_record_size, buffer) < vol->mft_record_size) {
1621                         Eprintf ("Couldn't read MFT Record %lld: %s.\n", i, strerror (errno));
1622                         goto close;
1623                 }
1624
1625                 if (write_data (fd, buffer, vol->mft_record_size) < vol->mft_record_size) {
1626                         Eprintf ("Write failed: %s\n", strerror (errno));
1627                         goto close;
1628                 }
1629         }
1630
1631         Vprintf ("Read %lld MFT Records\n", mft_end - mft_begin + 1);
1632         result = 0;
1633 close:
1634         close (fd);
1635 attr:
1636         ntfs_attr_close (mft);
1637 free:
1638         free (buffer);
1639         return result;
1640 }
1641
1642 /**
1643  * main - Begin here
1644  *
1645  * Start from here.
1646  *
1647  * Return:  0  Success, the program worked
1648  *          1  Error, something went wrong
1649  */
1650 int main (int argc, char *argv[])
1651 {
1652         ntfs_volume *vol;
1653         int result = 1;
1654
1655         if (!parse_options (argc, argv))
1656                 goto free;
1657
1658         utils_set_locale();
1659
1660         vol = utils_mount_volume (opts.device, MS_RDONLY, opts.force);
1661         if (!vol)
1662                 return 1;
1663
1664         switch (opts.mode) {
1665         case MODE_SCAN:
1666                 result = !scan_disk (vol);
1667                 if (result)
1668                         Vprintf ("Failed to scan device '%s'.\n", opts.device);
1669                 break;
1670         case MODE_UNDELETE:
1671                 result = !undelete_file (vol, opts.uinode);
1672                 if (result)
1673                         Vprintf ("Failed to undelete inode %d.\n", opts.uinode);
1674                 break;
1675         case MODE_COPY:
1676                 result = !copy_mft (vol, opts.mft_begin, opts.mft_end);
1677                 if (result)
1678                         Vprintf ("Failed to read MFT blocks %lld-%lld.\n",
1679                                 opts.mft_begin, min (vol->nr_mft_records, opts.mft_end));
1680                 break;
1681         default:
1682                 ; /* Cannot happen */
1683         }
1684
1685         ntfs_umount (vol, FALSE);
1686 free:
1687         if (opts.match)
1688                 free (opts.match);
1689
1690         return result;
1691 }
1692