]>
Commit | Line | Data |
---|---|---|
4d0bb651 | 1 | #include <dispatch/dispatch.h> |
00337e45 | 2 | #include <os/assumes.h> |
4d0bb651 A |
3 | #include <errno.h> |
4 | #include <fcntl.h> | |
5 | ||
6 | #include "commoncrypto.h" | |
7 | ||
8 | /* Generic version of libmd's *_File() functions. */ | |
9 | char * | |
10 | Digest_File(CCDigestAlg algorithm, const char *filename, char *buf) | |
11 | { | |
12 | static const char hex[] = "0123456789abcdef"; | |
13 | int fd; | |
14 | __block CCDigestCtx ctx; | |
15 | dispatch_queue_t queue; | |
16 | dispatch_semaphore_t sema; | |
17 | dispatch_io_t io; | |
18 | __block int s_error = 0; | |
19 | uint8_t digest[32]; // SHA256 is the biggest | |
20 | size_t i, length; | |
21 | ||
22 | /* dispatch_io_create_with_path requires an absolute path */ | |
23 | fd = open(filename, O_RDONLY); | |
24 | if (fd < 0) { | |
25 | return NULL; | |
26 | } | |
27 | ||
28 | (void)fcntl(fd, F_NOCACHE, 1); | |
29 | ||
00337e45 | 30 | (void)os_assumes_zero(CCDigestInit(algorithm, &ctx)); |
4d0bb651 A |
31 | |
32 | queue = dispatch_queue_create("com.apple.mtree.io", NULL); | |
00337e45 | 33 | os_assert(queue); |
4d0bb651 | 34 | sema = dispatch_semaphore_create(0); |
00337e45 | 35 | os_assert(sema); |
4d0bb651 A |
36 | |
37 | io = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) { | |
38 | if (error != 0) { | |
39 | s_error = error; | |
40 | } | |
41 | (void)close(fd); | |
42 | (void)dispatch_semaphore_signal(sema); | |
43 | }); | |
00337e45 | 44 | os_assert(io); |
4d0bb651 A |
45 | dispatch_io_read(io, 0, SIZE_MAX, queue, ^(__unused bool done, dispatch_data_t data, int error) { |
46 | if (data != NULL) { | |
47 | (void)dispatch_data_apply(data, ^(__unused dispatch_data_t region, __unused size_t offset, const void *buffer, size_t size) { | |
00337e45 | 48 | (void)os_assumes_zero(CCDigestUpdate(&ctx, buffer, size)); |
4d0bb651 A |
49 | return (bool)true; |
50 | }); | |
51 | } | |
52 | ||
53 | if (error != 0) { | |
54 | s_error = error; | |
55 | } | |
56 | }); | |
57 | dispatch_release(io); // it will close on its own | |
58 | ||
59 | (void)dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); | |
60 | ||
61 | dispatch_release(queue); | |
62 | dispatch_release(sema); | |
63 | ||
64 | if (s_error != 0) { | |
65 | errno = s_error; | |
66 | return NULL; | |
67 | } | |
68 | ||
69 | /* Finalize and convert to hex. */ | |
00337e45 | 70 | (void)os_assumes_zero(CCDigestFinal(&ctx, digest)); |
4d0bb651 | 71 | length = CCDigestOutputSize(&ctx); |
00337e45 | 72 | os_assert(length <= sizeof(digest)); |
4d0bb651 A |
73 | for (i = 0; i < length; i++) { |
74 | buf[i+i] = hex[digest[i] >> 4]; | |
75 | buf[i+i+1] = hex[digest[i] & 0x0f]; | |
76 | } | |
77 | buf[i+i] = '\0'; | |
78 | ||
79 | return buf; | |
80 | } |