[checksum] add an individual checksum function call

* Part of #758
* Also define checksum types and fix a missing change in smart.c
This commit is contained in:
Pete Batard 2016-05-24 13:21:23 +01:00
parent a41bca3183
commit 04d6ac0cdd
5 changed files with 80 additions and 21 deletions

View File

@ -63,9 +63,9 @@
#define WAIT_TIME 5000 #define WAIT_TIME 5000
/* Globals */ /* Globals */
char sum_str[NUM_CHECKSUMS][65]; char sum_str[CHECKSUM_MAX][65];
uint32_t bufnum, sum_count[NUM_CHECKSUMS] = { 16, 20, 32 }; uint32_t bufnum, sum_count[CHECKSUM_MAX] = { 16, 20, 32 };
HANDLE data_ready[NUM_CHECKSUMS], thread_ready[NUM_CHECKSUMS]; HANDLE data_ready[CHECKSUM_MAX], thread_ready[CHECKSUM_MAX];
DWORD read_size[2]; DWORD read_size[2];
char ALIGNED(64) buffer[2][BUFFER_SIZE]; char ALIGNED(64) buffer[2][BUFFER_SIZE];
@ -709,9 +709,52 @@ static void null_final(SUM_CONTEXT *ctx) { }
typedef void sum_init_t(SUM_CONTEXT *ctx); typedef void sum_init_t(SUM_CONTEXT *ctx);
typedef void sum_write_t(SUM_CONTEXT *ctx, const unsigned char *buf, size_t len); typedef void sum_write_t(SUM_CONTEXT *ctx, const unsigned char *buf, size_t len);
typedef void sum_final_t(SUM_CONTEXT *ctx); typedef void sum_final_t(SUM_CONTEXT *ctx);
sum_init_t *sum_init[NUM_CHECKSUMS] = { md5_init, sha1_init , sha256_init }; sum_init_t *sum_init[CHECKSUM_MAX] = { md5_init, sha1_init , sha256_init };
sum_write_t *sum_write[NUM_CHECKSUMS] = { md5_write, sha1_write , sha256_write }; sum_write_t *sum_write[CHECKSUM_MAX] = { md5_write, sha1_write , sha256_write };
sum_final_t *sum_final[NUM_CHECKSUMS] = { md5_final, sha1_final , sha256_final }; sum_final_t *sum_final[CHECKSUM_MAX] = { md5_final, sha1_final , sha256_final };
// Compute an individual checksum without threading or buffering, for a single file
BOOL Checksum(const unsigned type, const char* path, uint8_t* sum)
{
BOOL r = FALSE;
SUM_CONTEXT sum_ctx = { 0 };
HANDLE h = INVALID_HANDLE_VALUE;
DWORD read_size = 0;
uint64_t rb;
char buffer[4096];
if ((type >= CHECKSUM_MAX) || (path == NULL) || (sum == NULL))
goto out;
uprintf("\r\nComputing checksum for '%s'...", path);
h = CreateFileU(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (h == INVALID_HANDLE_VALUE) {
uprintf("Could not open file: %s", WindowsErrorString());
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED;
goto out;
}
sum_init[type](&sum_ctx);
for (rb = 0; ; rb += read_size) {
CHECK_FOR_USER_CANCEL;
if (!ReadFile(h, buffer, sizeof(buffer), &read_size, NULL)) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_READ_FAULT;
uprintf(" Read error: %s", WindowsErrorString());
goto out;
}
if (read_size == 0)
break;
sum_write[type](&sum_ctx, buffer, (size_t)read_size);
}
sum_final[type](&sum_ctx);
memcpy(sum, sum_ctx.buf, sum_count[type]);
r = TRUE;
out:
safe_closehandle(h);
return r;
}
/* /*
* Checksum dialog callback * Checksum dialog callback
@ -817,7 +860,7 @@ error:
DWORD WINAPI SumThread(void* param) DWORD WINAPI SumThread(void* param)
{ {
DWORD_PTR* thread_affinity = (DWORD_PTR*)param; DWORD_PTR* thread_affinity = (DWORD_PTR*)param;
HANDLE sum_thread[NUM_CHECKSUMS] = { NULL, NULL, NULL }; HANDLE sum_thread[CHECKSUM_MAX] = { NULL, NULL, NULL };
HANDLE h = INVALID_HANDLE_VALUE; HANDLE h = INVALID_HANDLE_VALUE;
uint64_t rb, LastRefresh = 0; uint64_t rb, LastRefresh = 0;
int i, _bufnum, r = -1; int i, _bufnum, r = -1;
@ -835,7 +878,7 @@ DWORD WINAPI SumThread(void* param)
// is usually in this first mask, for other tasks. // is usually in this first mask, for other tasks.
SetThreadAffinityMask(GetCurrentThread(), thread_affinity[0]); SetThreadAffinityMask(GetCurrentThread(), thread_affinity[0]);
for (i = 0; i < NUM_CHECKSUMS; i++) { for (i = 0; i < CHECKSUM_MAX; i++) {
// NB: Can't use a single manual-reset event for data_ready as we // NB: Can't use a single manual-reset event for data_ready as we
// wouldn't be able to ensure the event is reset before the thread // wouldn't be able to ensure the event is reset before the thread
// gets into its next wait loop // gets into its next wait loop
@ -882,7 +925,7 @@ DWORD WINAPI SumThread(void* param)
// Toggle the read buffer // Toggle the read buffer
_bufnum = (bufnum + 1) % 2; _bufnum = (bufnum + 1) % 2;
// Signal the waiting threads // Signal the waiting threads
for (i = 0; i < NUM_CHECKSUMS; i++) { for (i = 0; i < CHECKSUM_MAX; i++) {
if (!SetEvent(data_ready[i])) { if (!SetEvent(data_ready[i])) {
uprintf("Could not signal checksum thread %d: %s", i, WindowsErrorString()); uprintf("Could not signal checksum thread %d: %s", i, WindowsErrorString());
goto out; goto out;
@ -902,14 +945,14 @@ DWORD WINAPI SumThread(void* param)
} }
// Wait for the thread to signal they are ready to process data // Wait for the thread to signal they are ready to process data
if (WaitForMultipleObjects(NUM_CHECKSUMS, thread_ready, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { if (WaitForMultipleObjects(CHECKSUM_MAX, thread_ready, TRUE, WAIT_TIME) != WAIT_OBJECT_0) {
uprintf("Checksum threads failed to signal: %s", WindowsErrorString()); uprintf("Checksum threads failed to signal: %s", WindowsErrorString());
goto out; goto out;
} }
} }
// Our last event with read_size=0 signaled the threads to exit - wait for that to happen // Our last event with read_size=0 signaled the threads to exit - wait for that to happen
if (WaitForMultipleObjects(NUM_CHECKSUMS, sum_thread, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { if (WaitForMultipleObjects(CHECKSUM_MAX, sum_thread, TRUE, WAIT_TIME) != WAIT_OBJECT_0) {
uprintf("Checksum threads did not finalize: %s", WindowsErrorString()); uprintf("Checksum threads did not finalize: %s", WindowsErrorString());
goto out; goto out;
} }
@ -920,7 +963,7 @@ DWORD WINAPI SumThread(void* param)
r = 0; r = 0;
out: out:
for (i = 0; i < NUM_CHECKSUMS; i++) { for (i = 0; i < CHECKSUM_MAX; i++) {
if (sum_thread[i] != NULL) if (sum_thread[i] != NULL)
TerminateThread(sum_thread[i], 1); TerminateThread(sum_thread[i], 1);
CloseHandle(data_ready[i]); CloseHandle(data_ready[i]);

View File

@ -2270,7 +2270,16 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
break; break;
#ifdef RUFUS_TEST #ifdef RUFUS_TEST
case IDC_TEST: case IDC_TEST:
{
int j;
char str[65];
uint8_t sum[32];
Checksum(CHECKSUM_SHA256, "C:\\rufus\\src\\.msvc\\rufus_files\\syslinux-6.03\\ldlinux.sys", sum);
for (j = 0; j < sizeof(sum); j++)
safe_sprintf(&str[2 * j], ARRAYSIZE(str) - 2 * j, "%02x", sum[j]);
uprintf(" Checksum: %s", str);
break; break;
}
#endif #endif
case IDC_ADVANCED: case IDC_ADVANCED:
advanced_mode = !advanced_mode; advanced_mode = !advanced_mode;
@ -2540,7 +2549,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA
// Disable all controls except cancel // Disable all controls except cancel
EnableControls(FALSE); EnableControls(FALSE);
InitProgress(FALSE); InitProgress(FALSE);
SetThreadAffinity(thread_affinity, NUM_CHECKSUMS + 1); SetThreadAffinity(thread_affinity, CHECKSUM_MAX + 1);
format_thid = CreateThread(NULL, 0, SumThread, (LPVOID)thread_affinity, 0, NULL); format_thid = CreateThread(NULL, 0, SumThread, (LPVOID)thread_affinity, 0, NULL);
if (format_thid != NULL) { if (format_thid != NULL) {
PrintInfo(0, -1); PrintInfo(0, -1);

View File

@ -42,7 +42,7 @@
#define APPLICATION_NAME "Rufus" #define APPLICATION_NAME "Rufus"
#define COMPANY_NAME "Akeo Consulting" #define COMPANY_NAME "Akeo Consulting"
#define STR_NO_LABEL "NO_LABEL" #define STR_NO_LABEL "NO_LABEL"
// Yes, there is a character between these seemingly empty quotes! // Yes, there exist characters between these seemingly empty quotes!
#define LEFT_TO_RIGHT_MARK "" #define LEFT_TO_RIGHT_MARK ""
#define RIGHT_TO_LEFT_MARK "" #define RIGHT_TO_LEFT_MARK ""
#define LEFT_TO_RIGHT_EMBEDDING "" #define LEFT_TO_RIGHT_EMBEDDING ""
@ -68,7 +68,6 @@
#define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword #define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword
#define STATUS_MSG_TIMEOUT 3500 // How long should cheat mode messages appear for on the status bar #define STATUS_MSG_TIMEOUT 3500 // How long should cheat mode messages appear for on the status bar
#define WRITE_RETRIES 3 #define WRITE_RETRIES 3
#define NUM_CHECKSUMS 3 // Number of checksum algorithms we support (MD5, SHA1, SHA256)
#define FS_DEFAULT FS_FAT32 #define FS_DEFAULT FS_FAT32
#define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100 #define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100
#define BADBLOCK_PATTERNS {0xaa, 0x55, 0xff, 0x00} #define BADBLOCK_PATTERNS {0xaa, 0x55, 0xff, 0x00}
@ -232,6 +231,13 @@ enum target_type {
#define GETTARGETTYPE(x) (((x)>0)?(((x) >> 16) & 0xFFFF):0) #define GETTARGETTYPE(x) (((x)>0)?(((x) >> 16) & 0xFFFF):0)
#define GETPARTTYPE(x) (((x)>0)?((x) & 0xFFFF):0); #define GETPARTTYPE(x) (((x)>0)?((x) & 0xFFFF):0);
enum checksum_type {
CHECKSUM_MD5 = 0,
CHECKSUM_SHA1,
CHECKSUM_SHA256,
CHECKSUM_MAX
};
/* Special handling for old .c32 files we need to replace */ /* Special handling for old .c32 files we need to replace */
#define NB_OLD_C32 2 #define NB_OLD_C32 2
#define OLD_C32_NAMES { "menu.c32", "vesamenu.c32" } #define OLD_C32_NAMES { "menu.c32", "vesamenu.c32" }
@ -450,6 +456,7 @@ extern BOOL IsFontAvailable(const char* font_name);
extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries); LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries);
extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads); extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads);
extern BOOL Checksum(const unsigned type, const char* path, uint8_t* sum);
#define printbits(x) _printbits(sizeof(x), &x, 0) #define printbits(x) _printbits(sizeof(x), &x, 0)
#define printbitslz(x) _printbits(sizeof(x), &x, 1) #define printbitslz(x) _printbits(sizeof(x), &x, 1)
extern char* _printbits(size_t const size, void const * const ptr, int leading_zeroes); extern char* _printbits(size_t const size, void const * const ptr, int leading_zeroes);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 242, 376 IDD_DIALOG DIALOGEX 12, 12, 242, 376
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 2.10.938" CAPTION "Rufus 2.10.939"
FONT 8, "Segoe UI Symbol", 400, 0, 0x0 FONT 8, "Segoe UI Symbol", 400, 0, 0x0
BEGIN BEGIN
LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8
@ -320,8 +320,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,10,938,0 FILEVERSION 2,10,939,0
PRODUCTVERSION 2,10,938,0 PRODUCTVERSION 2,10,939,0
FILEFLAGSMASK 0x3fL FILEFLAGSMASK 0x3fL
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -338,13 +338,13 @@ BEGIN
BEGIN BEGIN
VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)"
VALUE "FileDescription", "Rufus" VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "2.10.938" VALUE "FileVersion", "2.10.939"
VALUE "InternalName", "Rufus" VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)" VALUE "LegalCopyright", "© 2011-2016 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus.exe" VALUE "OriginalFilename", "rufus.exe"
VALUE "ProductName", "Rufus" VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "2.10.938" VALUE "ProductVersion", "2.10.939"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View File

@ -181,7 +181,7 @@ static int SatAtaPassthrough(HANDLE hPhysical, ATA_PASSTHROUGH_CMD* Command, voi
int t_length = 0; /* 0 -> no data transferred */ int t_length = 0; /* 0 -> no data transferred */
uint8_t Direction; uint8_t Direction;
if (BufLen % SelectedDrive.Geometry.BytesPerSector != 0) { if (BufLen % SelectedDrive.SectorSize != 0) {
uprintf("SatAtaPassthrough: BufLen must be a multiple of <block size>\n"); uprintf("SatAtaPassthrough: BufLen must be a multiple of <block size>\n");
return SPT_ERROR_BUFFER; return SPT_ERROR_BUFFER;
} }