Created
August 15, 2013 06:26
-
-
Save leeprobert/6238704 to your computer and use it in GitHub Desktop.
A C file that creates an MD5 Hash efficiently. Credit to Joel : http://www.joel.lopes-da-silva.com/2010/09/07/compute-md5-or-sha-hash-of-large-file-efficiently-on-ios-and-mac-os-x/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Standard library | |
#include <stdint.h> | |
#include <stdio.h> | |
// Core Foundation | |
#include <CoreFoundation/CoreFoundation.h> | |
// Cryptography | |
#include <CommonCrypto/CommonDigest.h> | |
// In bytes | |
#define FileHashDefaultChunkSizeForReadingData 4096 | |
// Function | |
CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath, | |
size_t chunkSizeForReadingData) { | |
// Declare needed variables | |
CFStringRef result = NULL; | |
CFReadStreamRef readStream = NULL; | |
// Get the file URL | |
CFURLRef fileURL = | |
CFURLCreateWithFileSystemPath(kCFAllocatorDefault, | |
(CFStringRef)filePath, | |
kCFURLPOSIXPathStyle, | |
(Boolean)false); | |
if (!fileURL) goto done; | |
// Create and open the read stream | |
readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault, | |
(CFURLRef)fileURL); | |
if (!readStream) goto done; | |
bool didSucceed = (bool)CFReadStreamOpen(readStream); | |
if (!didSucceed) goto done; | |
// Initialize the hash object | |
CC_MD5_CTX hashObject; | |
CC_MD5_Init(&hashObject); | |
// Make sure chunkSizeForReadingData is valid | |
if (!chunkSizeForReadingData) { | |
chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData; | |
} | |
// Feed the data to the hash object | |
bool hasMoreData = true; | |
while (hasMoreData) { | |
uint8_t buffer[chunkSizeForReadingData]; | |
CFIndex readBytesCount = CFReadStreamRead(readStream, | |
(UInt8 *)buffer, | |
(CFIndex)sizeof(buffer)); | |
if (readBytesCount == -1) break; | |
if (readBytesCount == 0) { | |
hasMoreData = false; | |
continue; | |
} | |
CC_MD5_Update(&hashObject, | |
(const void *)buffer, | |
(CC_LONG)readBytesCount); | |
} | |
// Check if the read operation succeeded | |
didSucceed = !hasMoreData; | |
// Compute the hash digest | |
unsigned char digest[CC_MD5_DIGEST_LENGTH]; | |
CC_MD5_Final(digest, &hashObject); | |
// Abort if the read operation failed | |
if (!didSucceed) goto done; | |
// Compute the string result | |
char hash[2 * sizeof(digest) + 1]; | |
for (size_t i = 0; i < sizeof(digest); ++i) { | |
snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i])); | |
} | |
result = CFStringCreateWithCString(kCFAllocatorDefault, | |
(const char *)hash, | |
kCFStringEncodingUTF8); | |
done: | |
if (readStream) { | |
CFReadStreamClose(readStream); | |
CFRelease(readStream); | |
} | |
if (fileURL) { | |
CFRelease(fileURL); | |
} | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
NSString *filePath = ...; // Let's assume filePath is defined... | |
CFStringRef md5hash = | |
FileMD5HashCreateWithPath((CFStringRef)filePath, | |
FileHashDefaultChunkSizeForReadingData); | |
NSLog(@"MD5 hash of file at path \"%@\": %@", | |
filePath, (NSString *)md5hash); | |
CFRelease(md5hash); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment