1 /*
2 ** blkcalc
3 ** The Sleuth Kit
4 **
5 ** Calculates the corresponding block number between 'blkls' and 'dd' images
6 ** when given an 'blkls' block number, it determines the block number it
7 ** had in a 'dd' image.  When given a 'dd' image, it determines the
8 ** value it would have in a 'blkls' image (if the block is unallocated)
9 **
10 ** Brian Carrier [carrier <at> sleuthkit [dot] org]
11 ** Copyright (c) 2006-2011 Brian Carrier, Basis Technology.  All Rights reserved
12 ** Copyright (c) 2003-2005 Brian Carrier. All Rights reserved
13 **
14 ** TASK
15 ** Copyright (c) 2002 Brian Carrier, @stake Inc. All Rights reserved
16 **
17 ** TCTUTILs
18 ** Copyright (c) 2001 Brian Carrier.  All rights reserved
19 **
20 **
21 ** This software is distributed under the Common Public License 1.0
22 **
23 */
24 #include "tsk/tsk_tools_i.h"
25 #include <locale.h>
26 
27 static TSK_TCHAR *progname;
28 
29 static void
usage()30 usage()
31 {
32     TFPRINTF(stderr,
33         _TSK_T
34         ("usage: %s [-dsu unit_addr] [-vV] [-f fstype] [-i imgtype] [-b dev_sector_size] [-o imgoffset] image [images]\n"),
35         progname);
36     tsk_fprintf(stderr, "Slowly calculates the opposite block number\n");
37     tsk_fprintf(stderr, "\tOne of the following must be given:\n");
38     tsk_fprintf(stderr,
39         "\t  -d: The given address is from a 'dd' image \n");
40     tsk_fprintf(stderr,
41         "\t  -s: The given address is from a 'blkls -s' (slack) image\n");
42     tsk_fprintf(stderr,
43         "\t  -u: The given address is from a 'blkls' (unallocated) image\n");
44     tsk_fprintf(stderr,
45         "\t-f fstype: The file system type (use '-f list' for supported types)\n");
46     tsk_fprintf(stderr,
47         "\t-i imgtype: The format of the image file (use '-i list' for supported types)\n");
48     tsk_fprintf(stderr,
49         "\t-b dev_sector_size: The size (in bytes) of the device sectors\n");
50     tsk_fprintf(stderr,
51         "\t-o imgoffset: The offset of the file system in the image (in sectors)\n");
52     tsk_fprintf(stderr, "\t-v: verbose output to stderr\n");
53     tsk_fprintf(stderr, "\t-V: Print version\n");
54 
55     exit(1);
56 }
57 
58 
59 
60 int
main(int argc,char ** argv1)61 main(int argc, char **argv1)
62 {
63     TSK_IMG_TYPE_ENUM imgtype = TSK_IMG_TYPE_DETECT;
64     TSK_IMG_INFO *img;
65 
66     TSK_OFF_T imgaddr = 0;
67     TSK_FS_TYPE_ENUM fstype = TSK_FS_TYPE_DETECT;
68     TSK_FS_INFO *fs;
69 
70     int ch;
71     TSK_TCHAR *cp;
72     uint8_t type = 0;
73     int set = 0;
74 
75     TSK_DADDR_T count = 0;
76     TSK_TCHAR **argv;
77     unsigned int ssize = 0;
78 
79 #ifdef TSK_WIN32
80     // On Windows, get the wide arguments (mingw doesn't support wmain)
81     argv = CommandLineToArgvW(GetCommandLineW(), &argc);
82     if (argv == NULL) {
83         fprintf(stderr, "Error getting wide arguments\n");
84         exit(1);
85     }
86 #else
87     argv = (TSK_TCHAR **) argv1;
88 #endif
89 
90 
91     progname = argv[0];
92     setlocale(LC_ALL, "");
93 
94     while ((ch = GETOPT(argc, argv, _TSK_T("b:d:f:i:o:s:u:vV"))) > 0) {
95         switch (ch) {
96         case _TSK_T('?'):
97         default:
98             TFPRINTF(stderr, _TSK_T("Invalid argument: %s\n"),
99                 argv[OPTIND]);
100             usage();
101 
102         case _TSK_T('b'):
103             ssize = (unsigned int) TSTRTOUL(OPTARG, &cp, 0);
104             if (*cp || *cp == *OPTARG || ssize < 1) {
105                 TFPRINTF(stderr,
106                     _TSK_T
107                     ("invalid argument: sector size must be positive: %s\n"),
108                     OPTARG);
109                 usage();
110             }
111             break;
112 
113         case _TSK_T('d'):
114             type |= TSK_FS_BLKCALC_DD;
115             count = TSTRTOULL(OPTARG, &cp, 0);
116             if (*cp || *cp == *OPTARG) {
117                 TFPRINTF(stderr, _TSK_T("Invalid address: %s\n"), OPTARG);
118                 usage();
119             }
120             set = 1;
121             break;
122 
123         case _TSK_T('f'):
124             if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) {
125                 tsk_fs_type_print(stderr);
126                 exit(1);
127             }
128             fstype = tsk_fs_type_toid(OPTARG);
129             if (fstype == TSK_FS_TYPE_UNSUPP) {
130                 TFPRINTF(stderr,
131                     _TSK_T("Unsupported file system type: %s\n"), OPTARG);
132                 usage();
133             }
134             break;
135 
136         case _TSK_T('i'):
137             if (TSTRCMP(OPTARG, _TSK_T("list")) == 0) {
138                 tsk_img_type_print(stderr);
139                 exit(1);
140             }
141             imgtype = tsk_img_type_toid(OPTARG);
142             if (imgtype == TSK_IMG_TYPE_UNSUPP) {
143                 TFPRINTF(stderr, _TSK_T("Unsupported image type: %s\n"),
144                     OPTARG);
145                 usage();
146             }
147             break;
148 
149         case _TSK_T('o'):
150             if ((imgaddr = tsk_parse_offset(OPTARG)) == -1) {
151                 tsk_error_print(stderr);
152                 exit(1);
153             }
154             break;
155 
156         case _TSK_T('s'):
157             type |= TSK_FS_BLKCALC_SLACK;
158             count = TSTRTOULL(OPTARG, &cp, 0);
159             if (*cp || *cp == *OPTARG) {
160                 TFPRINTF(stderr, _TSK_T("Invalid address: %s\n"), OPTARG);
161                 usage();
162             }
163             set = 1;
164             break;
165 
166         case _TSK_T('u'):
167             type |= TSK_FS_BLKCALC_BLKLS;
168             count = TSTRTOULL(OPTARG, &cp, 0);
169             if (*cp || *cp == *OPTARG) {
170                 TFPRINTF(stderr, _TSK_T("Invalid address: %s\n"), OPTARG);
171                 usage();
172             }
173             set = 1;
174             break;
175 
176         case _TSK_T('v'):
177             tsk_verbose++;
178             break;
179 
180         case _TSK_T('V'):
181             tsk_version_print(stdout);
182             exit(0);
183         }
184     }
185 
186     /* We need at least one more argument */
187     if (OPTIND == argc) {
188         tsk_fprintf(stderr, "Missing image name\n");
189         usage();
190     }
191 
192     if ((!type) || (set == 0)) {
193         tsk_fprintf(stderr, "Calculation type not given (-u, -d, -s)\n");
194         usage();
195     }
196 
197     if ((type & TSK_FS_BLKCALC_DD) && (type & TSK_FS_BLKCALC_BLKLS)
198         && (type & TSK_FS_BLKCALC_SLACK)) {
199         tsk_fprintf(stderr, "Only one block type can be given\n");
200         usage();
201     }
202 
203 
204     if ((img =
205             tsk_img_open(argc - OPTIND, &argv[OPTIND], imgtype,
206                 ssize)) == NULL) {
207         tsk_error_print(stderr);
208         exit(1);
209     }
210     if ((imgaddr * img->sector_size) >= img->size) {
211         tsk_fprintf(stderr,
212             "Sector offset supplied is larger than disk image (maximum: %"
213             PRIu64 ")\n", img->size / img->sector_size);
214         exit(1);
215     }
216 
217     if ((fs = tsk_fs_open_img(img, imgaddr * img->sector_size, fstype)) == NULL) {
218         tsk_error_print(stderr);
219         if (tsk_error_get_errno() == TSK_ERR_FS_UNSUPTYPE)
220             tsk_fs_type_print(stderr);
221         img->close(img);
222         exit(1);
223     }
224 
225     if (-1 == tsk_fs_blkcalc(fs, (TSK_FS_BLKCALC_FLAG_ENUM) type, count)) {
226         tsk_error_print(stderr);
227         fs->close(fs);
228         img->close(img);
229         exit(1);
230     }
231 
232     fs->close(fs);
233     img->close(img);
234 
235     exit(0);
236 }
237