diff options
author | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
---|---|---|
committer | Cameron Katri <me@cameronkatri.com> | 2021-05-09 14:20:58 -0400 |
commit | 5fd83771641d15c418f747bd343ba6738d3875f7 (patch) | |
tree | 5abf0f78f680d9837dbd93d4d4c3933bb7509599 /text_cmds/md5/commoncrypto.c | |
download | apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.gz apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.tar.zst apple_cmds-5fd83771641d15c418f747bd343ba6738d3875f7.zip |
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
Diffstat (limited to 'text_cmds/md5/commoncrypto.c')
-rw-r--r-- | text_cmds/md5/commoncrypto.c | 108 |
1 files changed, 108 insertions, 0 deletions
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 <dispatch/dispatch.h> +#include <os/assumes.h> +#include <errno.h> +#include <fcntl.h> + +#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); +} |