1 #include <dispatch/dispatch.h>
2 #include <os/assumes.h>
6 #include "commoncrypto.h"
8 /* Generic version of libmd's *_File() functions. */
10 Digest_File(CCDigestAlg algorithm
, const char *filename
, char *buf
)
12 static const char hex
[] = "0123456789abcdef";
14 __block CCDigestCtx ctx
;
15 dispatch_queue_t queue
;
16 dispatch_semaphore_t sema
;
18 __block
int s_error
= 0;
19 uint8_t digest
[32]; // SHA256 is the biggest
22 /* dispatch_io_create_with_path requires an absolute path */
23 fd
= open(filename
, O_RDONLY
);
28 (void)fcntl(fd
, F_NOCACHE
, 1);
30 (void)os_assumes_zero(CCDigestInit(algorithm
, &ctx
));
32 queue
= dispatch_queue_create("com.apple.mtree.io", NULL
);
34 sema
= dispatch_semaphore_create(0);
37 io
= dispatch_io_create(DISPATCH_IO_STREAM
, fd
, queue
, ^(int error
) {
42 (void)dispatch_semaphore_signal(sema
);
45 dispatch_io_read(io
, 0, SIZE_MAX
, queue
, ^(__unused
bool done
, dispatch_data_t data
, int error
) {
47 (void)dispatch_data_apply(data
, ^(__unused dispatch_data_t region
, __unused
size_t offset
, const void *buffer
, size_t size
) {
48 (void)os_assumes_zero(CCDigestUpdate(&ctx
, buffer
, size
));
57 dispatch_release(io
); // it will close on its own
59 (void)dispatch_semaphore_wait(sema
, DISPATCH_TIME_FOREVER
);
61 dispatch_release(queue
);
62 dispatch_release(sema
);
69 /* Finalize and convert to hex. */
70 (void)os_assumes_zero(CCDigestFinal(&ctx
, digest
));
71 length
= CCDigestOutputSize(&ctx
);
72 os_assert(length
<= sizeof(digest
));
73 for (i
= 0; i
< length
; i
++) {
74 buf
[i
+i
] = hex
[digest
[i
] >> 4];
75 buf
[i
+i
+1] = hex
[digest
[i
] & 0x0f];