1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
/*
** The Sleuth Kit
**
** Copyright (c) 2022 Basis Technology Corp. All rights reserved
** Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
**
** This software is distributed under the Common Public License 1.0
**
*/
/*
* Common code used by the raw and logical images.
*/
#include "tsk/base/tsk_base_i.h"
#include "tsk/img/tsk_img_i.h"
#include "file_system_utils.h"
#ifdef __APPLE__
#include <sys/disk.h>
#endif
#ifdef TSK_WIN32
#include <winioctl.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#ifndef S_IFMT
#define S_IFMT __S_IFMT
#endif
#ifndef S_IFDIR
#define S_IFDIR __S_IFDIR
#endif
/**
* Test if the image is a Windows device
* @param The path to test
*
* Return 1 if the path represents a Windows device, 0 otherwise
*/
#ifdef TSK_WIN32
int is_windows_device_path(const TSK_TCHAR * image_name) {
return (TSTRNCMP(image_name, _TSK_T("\\\\.\\"), 4) == 0);
}
#endif
/**
* Get the size in bytes of the given file.
*
* @param a_file The file to test
* @param is_winobj 1 if the file is a windows object and not a real file
*
* @return the size in bytes, or -1 on error/unknown,
* -2 if unreadable, -3 if it's a directory.
*/
TSK_OFF_T
get_size_of_file_on_disk(const TSK_TCHAR * a_file, uint8_t a_is_winobj)
{
TSK_OFF_T size = -1;
struct STAT_STR sb;
if (TSTAT(a_file, &sb) < 0) {
if (a_is_winobj) {
/* stat can fail for Windows objects; ignore that */
if (tsk_verbose) {
tsk_fprintf(stderr,
"raw_open: ignoring stat result on Windows device %"
PRIttocTSK "\n", a_file);
}
}
else {
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_STAT);
tsk_error_set_errstr("raw_open: image \"%" PRIttocTSK
"\" - %s", a_file, strerror(errno));
return -2;
}
}
else if ((sb.st_mode & S_IFMT) == S_IFDIR) {
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_MAGIC);
tsk_error_set_errstr("raw_open: image \"%" PRIttocTSK
"\" - is a directory", a_file);
return -3;
}
#ifdef TSK_WIN32
{
HANDLE fd;
DWORD dwHi, dwLo;
if ((fd = CreateFile(a_file, FILE_READ_DATA,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL)) ==
INVALID_HANDLE_VALUE) {
int lastError = (int)GetLastError();
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_OPEN);
// print string of commonly found errors
if (lastError == ERROR_ACCESS_DENIED) {
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - access denied", a_file);
}
else if (lastError == ERROR_SHARING_VIOLATION) {
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - sharing violation", a_file);
}
else if (lastError == ERROR_FILE_NOT_FOUND) {
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - file not found", a_file);
}
else {
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - (error %d)", a_file, lastError);
}
return -2;
}
/* We need different techniques to determine the size of Windows physical
* devices versus normal files */
if (a_is_winobj == 0) {
dwLo = GetFileSize(fd, &dwHi);
if (dwLo == 0xffffffff) {
int lastError = (int)GetLastError();
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_OPEN);
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - GetFileSize: %d", a_file, lastError);
size = -1;
}
else {
size = dwLo | ((TSK_OFF_T)dwHi << 32);
}
}
else {
//use GET_PARTITION_INFO_EX prior to IOCTL_DISK_GET_DRIVE_GEOMETRY
// to determine the physical disk size because
//calculating it with the help of GET_DRIVE_GEOMETRY gives only
// approximate number
DWORD junk;
PARTITION_INFORMATION_EX partition;
if (FALSE == DeviceIoControl(fd,
IOCTL_DISK_GET_PARTITION_INFO_EX,
NULL, 0, &partition, sizeof(partition), &junk,
(LPOVERLAPPED)NULL)) {
DISK_GEOMETRY pdg;
if (FALSE == DeviceIoControl(fd, IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, 0, &pdg, sizeof(pdg), &junk, (LPOVERLAPPED)NULL)) {
int lastError = (int)GetLastError();
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_OPEN);
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK
"\" - DeviceIoControl: %d", a_file,
lastError);
size = -1;
}
else {
size = pdg.Cylinders.QuadPart *
(TSK_OFF_T)pdg.TracksPerCylinder *
(TSK_OFF_T)pdg.SectorsPerTrack *
(TSK_OFF_T)pdg.BytesPerSector;
}
}
else {
size = partition.PartitionLength.QuadPart;
}
}
CloseHandle(fd);
}
#else
int fd;
if ((fd = open(a_file, O_RDONLY | O_BINARY)) < 0) {
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_OPEN);
tsk_error_set_errstr("raw_open: file \"%" PRIttocTSK "\" - %s",
a_file, strerror(errno));
return -2;
}
#ifdef __APPLE__
/* OS X doesn't support SEEK_END on char devices */
if ((sb.st_mode & S_IFMT) != S_IFCHR) {
size = lseek(fd, 0, SEEK_END);
}
if (size <= 0) {
int blkSize;
long long blkCnt;
if (ioctl(fd, DKIOCGETBLOCKSIZE, &blkSize) >= 0) {
if (ioctl(fd, DKIOCGETBLOCKCOUNT, &blkCnt) >= 0) {
size = blkCnt * (long long)blkSize;
}
}
}
#else
/* We don't use the stat output because it doesn't work on raw
* devices and such */
size = lseek(fd, 0, SEEK_END);
#endif
close(fd);
#endif
return size;
}
|