From 5fd83771641d15c418f747bd343ba6738d3875f7 Mon Sep 17 00:00:00 2001 From: Cameron Katri Date: Sun, 9 May 2021 14:20:58 -0400 Subject: Import macOS userland adv_cmds-176 basic_cmds-55 bootstrap_cmds-116.100.1 developer_cmds-66 diskdev_cmds-667.40.1 doc_cmds-53.60.1 file_cmds-321.40.3 mail_cmds-35 misc_cmds-34 network_cmds-606.40.1 patch_cmds-17 remote_cmds-63 shell_cmds-216.60.1 system_cmds-880.60.2 text_cmds-106 --- text_cmds/md5/commoncrypto.c | 108 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 text_cmds/md5/commoncrypto.c (limited to 'text_cmds/md5/commoncrypto.c') diff --git a/text_cmds/md5/commoncrypto.c b/text_cmds/md5/commoncrypto.c new file mode 100644 index 0000000..3551afe --- /dev/null +++ b/text_cmds/md5/commoncrypto.c @@ -0,0 +1,108 @@ +/* Generic CommonDigest wrappers to match the semantics of libmd. */ + +#include +#include +#include +#include + +#include "commoncrypto.h" + +#define CHUNK_SIZE (10 * 1024 * 1024) + +char * +Digest_End(CCDigestRef ctx, char *buf) +{ + static const char hex[] = "0123456789abcdef"; + uint8_t digest[32]; // SHA256 is the biggest + size_t i, length; + + (void)os_assumes_zero(CCDigestFinal(ctx, digest)); + length = CCDigestOutputSize(ctx); + os_assert(length <= sizeof(digest)); + for (i = 0; i < length; i++) { + buf[i+i] = hex[digest[i] >> 4]; + buf[i+i+1] = hex[digest[i] & 0x0f]; + } + buf[i+i] = '\0'; + return buf; +} + +char * +Digest_Data(CCDigestAlg algorithm, const void *data, size_t len, char *buf) +{ + CCDigestCtx ctx; + + (void)os_assumes_zero(CCDigestInit(algorithm, &ctx)); + (void)os_assumes_zero(CCDigestUpdate(&ctx, data, len)); + return Digest_End(&ctx, buf); +} + +char * +Digest_File(CCDigestAlg algorithm, const char *filename, char *buf) +{ + int fd; + __block CCDigestCtx ctx; + dispatch_queue_t queue; + dispatch_semaphore_t sema; + dispatch_io_t io; + __block int s_error = 0; + __block bool eof = false; + off_t chunk_offset; + + /* dispatch_io_create_with_path requires an absolute path */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + return NULL; + } + + (void)fcntl(fd, F_NOCACHE, 1); + + (void)os_assumes_zero(CCDigestInit(algorithm, &ctx)); + + queue = dispatch_queue_create("com.apple.mtree.io", NULL); + os_assert(queue); + sema = dispatch_semaphore_create(0); + os_assert(sema); + + io = dispatch_io_create(DISPATCH_IO_STREAM, fd, queue, ^(int error) { + if (error != 0) { + s_error = error; + } + (void)close(fd); + (void)dispatch_semaphore_signal(sema); + }); + os_assert(io); + for (chunk_offset = 0; eof == false && s_error == 0; chunk_offset += CHUNK_SIZE) { + dispatch_io_read(io, chunk_offset, CHUNK_SIZE, queue, ^(bool done, dispatch_data_t data, int error) { + if (data != NULL) { + (void)dispatch_data_apply(data, ^(__unused dispatch_data_t region, __unused size_t offset, const void *buffer, size_t size) { + (void)os_assumes_zero(CCDigestUpdate(&ctx, buffer, size)); + return (bool)true; + }); + } + + if (error != 0) { + s_error = error; + } + + if (done) { + eof = (data == dispatch_data_empty); + dispatch_semaphore_signal(sema); + } + }); + dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + } + dispatch_release(io); // it will close on its own + + (void)dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); + + dispatch_release(queue); + dispatch_release(sema); + + if (s_error != 0) { + errno = s_error; + return NULL; + } + + return Digest_End(&ctx, buf); +} -- cgit v1.2.3-56-ge451