]> git.saurik.com Git - apple/file_cmds.git/blame - mtree/commoncrypto.c
file_cmds-251.tar.gz
[apple/file_cmds.git] / mtree / commoncrypto.c
CommitLineData
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. */
9char *
10Digest_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}