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