diff --git a/tsk/img/img_writer.cpp b/tsk/img/img_writer.cpp index 188f664414ec160fe7d4b4b8190287cf4775bdc8..54308e40d288bab95853534e9458330a729a5db7 100755 --- a/tsk/img/img_writer.cpp +++ b/tsk/img/img_writer.cpp @@ -190,11 +190,33 @@ static TSK_RETVAL_ENUM addToExistingBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr return TSK_OK; } +/* + * Write the footer at the position. + * Call this method when WriteFile failed and you want to output the footer at position for a valid VHD. + */ +static TSK_RETVAL_ENUM writeFooterAtPosition(TSK_IMG_WRITER* writer, TSK_OFF_T position) { + if (TSK_OK == seekToOffset(writer, position)) { + return writeFooter(writer); // write footer at lastPosition prior to WriteFile error + } + else { + int lastError = GetLastError(); + tsk_error_reset(); + tsk_error_set_errno(TSK_ERR_IMG_WRITE); + tsk_error_set_errstr("addNewBlock: error seekToOffset", + lastError); + return TSK_ERR; + } +} + /* * Add a new block to the VHD and copy in the buffer */ static TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len, TSK_OFF_T blockNum) { + if (writer->hadErrorExtending) { + return TSK_OK; // pretend we are OK, NOOP + } + if (tsk_verbose) { tsk_fprintf(stderr, "addNewBlock: Adding new block 0x%x\n", blockNum); fflush(stderr); @@ -270,6 +292,9 @@ static TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char free(sectorBitmap); return TSK_ERR; } + + TSK_OFF_T lastFooterPosition = writer->nextDataOffset; + if (FALSE == WriteFile(writer->outputFileHandle, sectorBitmap, writer->sectorBitmapLength, &bytesWritten, NULL)) { int lastError = GetLastError(); tsk_error_reset(); @@ -278,8 +303,12 @@ static TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char lastError); free(fullBuffer); free(sectorBitmap); + + writeFooterAtPosition(writer, lastFooterPosition); // so VHD is valid + writer->hadErrorExtending = 1; // WriteFile returns error, don't write anymore return TSK_ERR; } + if (FALSE == WriteFile(writer->outputFileHandle, fullBuffer, writer->blockSize, &bytesWritten, NULL)) { int lastError = GetLastError(); tsk_error_reset(); @@ -288,6 +317,9 @@ static TSK_RETVAL_ENUM addNewBlock(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char lastError); free(fullBuffer); free(sectorBitmap); + + writeFooterAtPosition(writer, lastFooterPosition); // so VHD is valid + writer->hadErrorExtending = 1; // WriteFile returns error, don't write anymore return TSK_ERR; } @@ -486,7 +518,7 @@ static TSK_RETVAL_ENUM writeDynamicDiskHeader(TSK_IMG_WRITER * writer) { */ static TSK_RETVAL_ENUM tsk_img_writer_add(TSK_IMG_WRITER* writer, TSK_OFF_T addr, char *buffer, size_t len) { - if (writer->is_finished) { + if (writer->is_finished || writer->hadErrorExtending) { return TSK_OK; } @@ -679,6 +711,7 @@ TSK_RETVAL_ENUM tsk_img_writer_create(TSK_IMG_INFO *img_info, const TSK_TCHAR *o writer->finishProgress = 0; writer->cancelFinish = 0; writer->inFinalizeImageWriter = 0; + writer->hadErrorExtending = 0; writer->footer = NULL; writer->img_info = img_info; writer->add = tsk_img_writer_add; diff --git a/tsk/img/img_writer.h b/tsk/img/img_writer.h index 23a04969809c685e650f7f3e2bbe720022f2500f..e53021cf5c26baac7564ac246f13380169e13c32 100644 --- a/tsk/img/img_writer.h +++ b/tsk/img/img_writer.h @@ -32,10 +32,11 @@ extern "C" { typedef struct TSK_IMG_WRITER TSK_IMG_WRITER; struct TSK_IMG_WRITER { TSK_IMG_INFO * img_info; - int is_finished; - int finishProgress; - int cancelFinish; - int inFinalizeImageWriter; + int is_finished; // set to 1 if finalize image is finished + int finishProgress; // finalize image progress indicator (0-100) + int cancelFinish; // set to 1 if finalize image is cancelled + int inFinalizeImageWriter; // set to 1 if we are in finalize image + int hadErrorExtending; // set to 1 if there is a WriteFile error in addNewBlock TSK_TCHAR* fileName; #ifdef TSK_WIN32 diff --git a/tsk/img/raw.c b/tsk/img/raw.c index 15ea8ff2e9b1dd44df7adb24abc70057a1f928f0..84cad54da14ce1e915892b962f55cf9c41cb2d6a 100644 --- a/tsk/img/raw.c +++ b/tsk/img/raw.c @@ -174,7 +174,8 @@ raw_read_segment(IMG_RAW_INFO * raw_info, int idx, char *buf, if (raw_info->img_writer != NULL) { /* 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); - if (raw_info->img_writer->inFinalizeImageWriter == 1 && result != TSK_OK) { + // If WriteFile returns error in the addNewBlock, hadErrorExtending is 1 + if (raw_info->img_writer->inFinalizeImageWriter && raw_info->img_writer->hadErrorExtending) { tsk_error_reset(); tsk_error_set_errno(TSK_ERR_IMG_WRITE); tsk_error_set_errstr("raw_read: file \"%" PRIttocTSK