Skip to content
Snippets Groups Projects
Commit 7d201a38 authored by Ann Priestman's avatar Ann Priestman Committed by Richard Cordovano
Browse files

Force reads to be sector-aligned if reading from a local disk

parent 25405809
No related branches found
No related tags found
No related merge requests found
...@@ -124,41 +124,71 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, ...@@ -124,41 +124,71 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf,
#ifdef TSK_WIN32 #ifdef TSK_WIN32
{ {
// Default to the values that were passed in
TSK_OFF_T offset_to_read = rel_offset;
size_t len_to_read = len;
char ** buf_pointer = &buf;
char * sector_aligned_buf = NULL;
// If the offset to seek to isn't sector-aligned and this is a device, we need to start at the previous sector boundary and
// read some extra data.
if ((offset_to_read % raw_info->img_info.sector_size != 0)
&& (TSTRNCMP(raw_info->img_info.images[idx], _TSK_T("\\\\.\\"), 4) == 0)) {
offset_to_read = (offset_to_read / raw_info->img_info.sector_size) * raw_info->img_info.sector_size;
len_to_read += raw_info->img_info.sector_size; // this length will already be a multiple of sector size
sector_aligned_buf = (char *)tsk_malloc(len_to_read);
if (sector_aligned_buf == NULL) {
tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_READ);
tsk_error_set_errstr("raw_read: error allocating memory to read file \"%" PRIttocTSK
"\" offset: %" PRIdOFF " read len: %" PRIuSIZE,
raw_info->img_info.images[idx], offset_to_read, len_to_read);
return -1;
}
buf_pointer = &sector_aligned_buf;
}
DWORD nread; DWORD nread;
if (cimg->seek_pos != rel_offset) { if (cimg->seek_pos != offset_to_read) {
LARGE_INTEGER li; LARGE_INTEGER li;
li.QuadPart = rel_offset; li.QuadPart = offset_to_read;
li.LowPart = SetFilePointer(cimg->fd, li.LowPart, li.LowPart = SetFilePointer(cimg->fd, li.LowPart,
&li.HighPart, FILE_BEGIN); &li.HighPart, FILE_BEGIN);
if ((li.LowPart == INVALID_SET_FILE_POINTER) && if ((li.LowPart == INVALID_SET_FILE_POINTER) &&
(GetLastError() != NO_ERROR)) { (GetLastError() != NO_ERROR)) {
if (sector_aligned_buf != NULL) {
free(sector_aligned_buf);
}
int lastError = (int)GetLastError(); int lastError = (int)GetLastError();
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_SEEK); tsk_error_set_errno(TSK_ERR_IMG_SEEK);
tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK
"\" offset %" PRIdOFF " seek - %d", "\" offset %" PRIdOFF " seek - %d",
raw_info->img_info.images[idx], rel_offset, raw_info->img_info.images[idx], offset_to_read,
lastError); lastError);
return -1; return -1;
} }
cimg->seek_pos = rel_offset; cimg->seek_pos = offset_to_read;
} }
//For physical drive when the buffer is larger than remaining data, //For physical drive when the buffer is larger than remaining data,
// WinAPI ReadFile call returns -1 // WinAPI ReadFile call returns -1
//in this case buffer of exact length must be passed to ReadFile //in this case buffer of exact length must be passed to ReadFile
if ((raw_info->is_winobj) && (rel_offset + (TSK_OFF_T)len > raw_info->img_info.size )) if ((raw_info->is_winobj) && (offset_to_read + (TSK_OFF_T)len_to_read > raw_info->img_info.size ))
len = (size_t)(raw_info->img_info.size - rel_offset); len_to_read = (size_t)(raw_info->img_info.size - offset_to_read);
if (FALSE == ReadFile(cimg->fd, buf, (DWORD) len, &nread, NULL)) { if (FALSE == ReadFile(cimg->fd, *buf_pointer, (DWORD)len_to_read, &nread, NULL)) {
if (sector_aligned_buf != NULL) {
free(sector_aligned_buf);
}
int lastError = GetLastError(); int lastError = GetLastError();
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_READ); tsk_error_set_errno(TSK_ERR_IMG_READ);
tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK
"\" offset: %" PRIdOFF " read len: %" PRIuSIZE " - %d", "\" offset: %" PRIdOFF " read len: %" PRIuSIZE " - %d",
raw_info->img_info.images[idx], rel_offset, len, raw_info->img_info.images[idx], offset_to_read, len_to_read,
lastError); lastError);
return -1; return -1;
} }
...@@ -166,25 +196,42 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, ...@@ -166,25 +196,42 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf,
// ReadFile returns TRUE and sets nread to zero. // ReadFile returns TRUE and sets nread to zero.
// We need to check if we've reached the end of a file and set nread to // We need to check if we've reached the end of a file and set nread to
// the number of bytes read. // the number of bytes read.
if ((raw_info->is_winobj) && (nread == 0) && (rel_offset + len == raw_info->img_info.size)) { if ((raw_info->is_winobj) && (nread == 0) && (offset_to_read + len_to_read == raw_info->img_info.size)) {
nread = (DWORD)len; nread = (DWORD)len_to_read;
} }
cnt = (ssize_t) nread; cnt = (ssize_t) nread;
if (raw_info->img_writer != NULL) { if (raw_info->img_writer != NULL) {
/* img_writer is not used with split images, so rel_offset is just the normal offset*/ /* img_writer is not used with split images, so rel_offset is just the normal offset*/
TSK_RETVAL_ENUM result = raw_info->img_writer->add(raw_info->img_writer, rel_offset, buf, cnt); TSK_RETVAL_ENUM result = raw_info->img_writer->add(raw_info->img_writer, offset_to_read, *buf_pointer, cnt);
// If WriteFile returns error in the addNewBlock, hadErrorExtending is 1 // If WriteFile returns error in the addNewBlock, hadErrorExtending is 1
if (raw_info->img_writer->inFinalizeImageWriter && raw_info->img_writer->hadErrorExtending) { if (raw_info->img_writer->inFinalizeImageWriter && raw_info->img_writer->hadErrorExtending) {
if (sector_aligned_buf != NULL) {
free(sector_aligned_buf);
}
tsk_error_reset(); tsk_error_reset();
tsk_error_set_errno(TSK_ERR_IMG_WRITE); tsk_error_set_errno(TSK_ERR_IMG_WRITE);
tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK
"\" offset: %" PRIdOFF " tsk_img_writer_add cnt: %" PRIuSIZE " - %d", "\" offset: %" PRIdOFF " tsk_img_writer_add cnt: %" PRIuSIZE " - %d",
raw_info->img_info.images[idx], rel_offset, cnt raw_info->img_info.images[idx], offset_to_read, cnt
); );
return -1; return -1;
} }
} }
// Update this with the actual bytes read
cimg->seek_pos += cnt;
// If we had to do the sector alignment, copy the result into the original buffer and fix
// the number of bytes read
if (sector_aligned_buf != NULL) {
memcpy(buf, sector_aligned_buf + rel_offset % raw_info->img_info.sector_size, len);
cnt = cnt - offset_to_read % raw_info->img_info.sector_size;
if (cnt < 0) {
cnt = -1;
}
free(sector_aligned_buf);
}
} }
#else #else
if (cimg->seek_pos != rel_offset) { if (cimg->seek_pos != rel_offset) {
...@@ -208,8 +255,8 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, ...@@ -208,8 +255,8 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf,
rel_offset, len, strerror(errno)); rel_offset, len, strerror(errno));
return -1; return -1;
} }
#endif
cimg->seek_pos += cnt; cimg->seek_pos += cnt;
#endif
return cnt; return cnt;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment