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 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 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 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 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 * 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