1 /*
2 * Brian Carrier [carrier <at> sleuthkit [dot] org]
3 * Copyright (c) 2006-2016 Brian Carrier, Basis Technology. All rights reserved
4 * Copyright (c) 2005 Brian Carrier. All rights reserved
5 *
6 * This software is distributed under the Common Public License 1.0
7 *
8 */
9
10
11 /** \file vhd.c
12 * Internal code for TSK to interface with libvhdi.
13 */
14
15 #include "tsk_img_i.h"
16
17 #if HAVE_LIBVHDI
18 #include "vhd.h"
19
20 #define TSK_VHDI_ERROR_STRING_SIZE 512
21
22 /**
23 * Get error string from libvhdi and make buffer empty if that didn't work.
24 * @returns 1 if error message was not set
25 */
26 static uint8_t
getError(libvhdi_error_t * vhdi_error,char error_string[TSK_VHDI_ERROR_STRING_SIZE])27 getError(libvhdi_error_t * vhdi_error,
28 char error_string[TSK_VHDI_ERROR_STRING_SIZE])
29 {
30 int retval;
31 error_string[0] = '\0';
32 retval = libvhdi_error_backtrace_sprint(vhdi_error,
33 error_string, TSK_VHDI_ERROR_STRING_SIZE);
34 if (retval)
35 return 1;
36 return 0;
37 }
38
39
40 static ssize_t
vhdi_image_read(TSK_IMG_INFO * img_info,TSK_OFF_T offset,char * buf,size_t len)41 vhdi_image_read(TSK_IMG_INFO * img_info, TSK_OFF_T offset, char *buf,
42 size_t len)
43 {
44 char error_string[TSK_VHDI_ERROR_STRING_SIZE];
45 libvhdi_error_t *vhdi_error = NULL;
46
47 ssize_t cnt;
48 IMG_VHDI_INFO *vhdi_info = (IMG_VHDI_INFO *) img_info;
49
50 if (tsk_verbose)
51 tsk_fprintf(stderr,
52 "vhdi_image_read: byte offset: %" PRIdOFF " len: %" PRIuSIZE
53 "\n", offset, len);
54
55 if (offset > img_info->size) {
56 tsk_error_reset();
57 tsk_error_set_errno(TSK_ERR_IMG_READ_OFF);
58 tsk_error_set_errstr("vhdi_image_read - %" PRIdOFF, offset);
59 return -1;
60 }
61
62 tsk_take_lock(&(vhdi_info->read_lock));
63
64 cnt = libvhdi_file_read_buffer_at_offset(vhdi_info->handle,
65 buf, len, offset, &vhdi_error);
66 if (cnt < 0) {
67 char *errmsg = NULL;
68 tsk_error_reset();
69 tsk_error_set_errno(TSK_ERR_IMG_READ);
70 if (getError(vhdi_error, error_string))
71 errmsg = strerror(errno);
72 else
73 errmsg = error_string;
74
75 tsk_error_set_errstr("vhdi_image_read - offset: %" PRIdOFF
76 " - len: %" PRIuSIZE " - %s", offset, len, errmsg);
77 tsk_release_lock(&(vhdi_info->read_lock));
78 return -1;
79 }
80
81 tsk_release_lock(&(vhdi_info->read_lock));
82
83 return cnt;
84 }
85
86 static void
vhdi_image_imgstat(TSK_IMG_INFO * img_info,FILE * hFile)87 vhdi_image_imgstat(TSK_IMG_INFO * img_info, FILE * hFile)
88 {
89 tsk_fprintf(hFile, "IMAGE FILE INFORMATION\n");
90 tsk_fprintf(hFile, "--------------------------------------------\n");
91 tsk_fprintf(hFile, "Image Type:\t\tvhdi\n");
92 tsk_fprintf(hFile, "\nSize of data in bytes:\t%" PRIdOFF "\n",
93 img_info->size);
94 tsk_fprintf(hFile, "Sector size:\t%d\n", img_info->sector_size);
95
96 return;
97 }
98
99
100 static void
vhdi_image_close(TSK_IMG_INFO * img_info)101 vhdi_image_close(TSK_IMG_INFO * img_info)
102 {
103 int i;
104 char error_string[TSK_VHDI_ERROR_STRING_SIZE];
105 libvhdi_error_t *vhdi_error = NULL;
106 char *errmsg = NULL;
107 IMG_VHDI_INFO *vhdi_info = (IMG_VHDI_INFO *) img_info;
108
109 if( libvhdi_file_close(vhdi_info->handle, &vhdi_error ) != 0 )
110 {
111 tsk_error_reset();
112 tsk_error_set_errno(TSK_ERR_AUX_GENERIC);
113 if (getError(vhdi_error, error_string))
114 errmsg = strerror(errno);
115 else
116 errmsg = error_string;
117
118 tsk_error_set_errstr("vhdi_image_close: unable to close handle - %s", errmsg);
119 }
120
121 libvhdi_file_free(&(vhdi_info->handle), NULL);
122 if( libvhdi_file_free(&(vhdi_info->handle), &vhdi_error ) != 1 )
123 {
124 tsk_error_reset();
125 tsk_error_set_errno(TSK_ERR_AUX_GENERIC);
126 if (getError(vhdi_error, error_string))
127 errmsg = strerror(errno);
128 else
129 errmsg = error_string;
130
131 tsk_error_set_errstr("vhdi_image_close: unable to free handle - %s", errmsg);
132 }
133
134 for (i = 0; i < vhdi_info->img_info.num_img; i++) {
135 free(vhdi_info->img_info.images[i]);
136 }
137 free(vhdi_info->img_info.images);
138
139 tsk_deinit_lock(&(vhdi_info->read_lock));
140 tsk_img_free(img_info);
141 }
142
143 TSK_IMG_INFO *
vhdi_open(int a_num_img,const TSK_TCHAR * const a_images[],unsigned int a_ssize)144 vhdi_open(int a_num_img,
145 const TSK_TCHAR * const a_images[], unsigned int a_ssize)
146 {
147 char error_string[TSK_VHDI_ERROR_STRING_SIZE];
148 libvhdi_error_t *vhdi_error = NULL;
149 int i;
150
151 IMG_VHDI_INFO *vhdi_info = NULL;
152 TSK_IMG_INFO *img_info = NULL;
153
154 if (tsk_verbose) {
155 libvhdi_notify_set_verbose(1);
156 libvhdi_notify_set_stream(stderr, NULL);
157 }
158
159 if ((vhdi_info =
160 (IMG_VHDI_INFO *) tsk_img_malloc(sizeof(IMG_VHDI_INFO))) ==
161 NULL) {
162 return NULL;
163 }
164 vhdi_info->handle = NULL;
165 img_info = (TSK_IMG_INFO *) vhdi_info;
166
167 vhdi_info->img_info.num_img = a_num_img;
168 if ((vhdi_info->img_info.images =
169 (TSK_TCHAR **) tsk_malloc(a_num_img *
170 sizeof(TSK_TCHAR *))) == NULL) {
171 tsk_img_free(vhdi_info);
172 return NULL;
173 }
174 for (i = 0; i < a_num_img; i++) {
175 if ((vhdi_info->img_info.images[i] =
176 (TSK_TCHAR *) tsk_malloc((TSTRLEN(a_images[i]) +
177 1) * sizeof(TSK_TCHAR))) == NULL) {
178 tsk_img_free(vhdi_info);
179 return NULL;
180 }
181 TSTRNCPY(vhdi_info->img_info.images[i], a_images[i],
182 TSTRLEN(a_images[i]) + 1);
183 }
184
185 if (libvhdi_file_initialize(&(vhdi_info->handle), &vhdi_error) != 1) {
186 tsk_error_reset();
187 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
188
189 getError(vhdi_error, error_string);
190 tsk_error_set_errstr("vhdi_open file: %" PRIttocTSK
191 ": Error initializing handle (%s)", a_images[0], error_string);
192 libvhdi_error_free(&vhdi_error);
193
194 tsk_img_free(vhdi_info);
195
196 if (tsk_verbose != 0) {
197 tsk_fprintf(stderr, "Unable to create vhdi handle\n");
198 }
199 return (NULL);
200 }
201 // Check the file signature before we call the library open
202 #if defined( TSK_WIN32 )
203 if( libvhdi_check_file_signature_wide((const wchar_t *) vhdi_info->img_info.images[0], &vhdi_error ) != 1 )
204 #else
205 if( libvhdi_check_file_signature((const char *) vhdi_info->img_info.images[0], &vhdi_error) != 1)
206 #endif
207 {
208 tsk_error_reset();
209 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
210
211 getError(vhdi_error, error_string);
212 tsk_error_set_errstr("vhdi_open file: %" PRIttocTSK
213 ": Error checking file signature for image (%s)", a_images[0],
214 error_string);
215 libvhdi_error_free(&vhdi_error);
216
217 tsk_img_free(vhdi_info);
218
219 if (tsk_verbose != 0) {
220 tsk_fprintf(stderr, "Error checking file signature for vhd file\n");
221 }
222 return (NULL);
223 }
224 #if defined( TSK_WIN32 )
225 if (libvhdi_file_open_wide(vhdi_info->handle,
226 (const wchar_t *) vhdi_info->img_info.images[0],
227 LIBVHDI_OPEN_READ, &vhdi_error) != 1)
228 #else
229 if (libvhdi_file_open(vhdi_info->handle,
230 (const char *) vhdi_info->img_info.images[0],
231 LIBVHDI_OPEN_READ, &vhdi_error) != 1)
232 #endif
233 {
234 tsk_error_reset();
235 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
236
237 getError(vhdi_error, error_string);
238 tsk_error_set_errstr("vhdi_open file: %" PRIttocTSK
239 ": Error opening (%s)", a_images[0], error_string);
240 libvhdi_error_free(&vhdi_error);
241
242 tsk_img_free(vhdi_info);
243
244 if (tsk_verbose != 0) {
245 tsk_fprintf(stderr, "Error opening vhdi file\n");
246 }
247 return (NULL);
248 }
249 if (libvhdi_file_get_media_size(vhdi_info->handle,
250 (size64_t *) & (img_info->size), &vhdi_error) != 1) {
251 tsk_error_reset();
252 tsk_error_set_errno(TSK_ERR_IMG_OPEN);
253
254 getError(vhdi_error, error_string);
255 tsk_error_set_errstr("vhdi_open file: %" PRIttocTSK
256 ": Error getting size of image (%s)", a_images[0],
257 error_string);
258 libvhdi_error_free(&vhdi_error);
259
260 tsk_img_free(vhdi_info);
261
262 if (tsk_verbose != 0) {
263 tsk_fprintf(stderr, "Error getting size of vhdi file\n");
264 }
265 return (NULL);
266 }
267
268 if (a_ssize != 0) {
269 img_info->sector_size = a_ssize;
270 }
271 else {
272 img_info->sector_size = 512;
273 }
274 img_info->itype = TSK_IMG_TYPE_VHD_VHD;
275 img_info->read = &vhdi_image_read;
276 img_info->close = &vhdi_image_close;
277 img_info->imgstat = &vhdi_image_imgstat;
278
279 // initialize the read lock
280 tsk_init_lock(&(vhdi_info->read_lock));
281
282 return (img_info);
283 }
284
285 #endif /* HAVE_LIBVHDI */
286