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