5 * Copyright © 2010 Joel Lopes Da Silva. All rights reserved.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 //---------------------------------------------------------
23 //---------------------------------------------------------
26 #include "FileMD5Hash.h"
33 #include <CoreFoundation/CoreFoundation.h>
36 #include <CommonCrypto/CommonDigest.h>
39 //---------------------------------------------------------
40 // Function definition
41 //---------------------------------------------------------
43 CFStringRef FileMD5HashCreateWithPath(CFStringRef filePath,
44 size_t chunkSizeForReadingData) {
46 // Declare needed variables
47 CFStringRef result = NULL;
48 CFReadStreamRef readStream = NULL;
52 CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
53 (CFStringRef)filePath,
56 if (!fileURL) goto done;
58 // Create and open the read stream
59 readStream = CFReadStreamCreateWithFile(kCFAllocatorDefault,
61 if (!readStream) goto done;
62 bool didSucceed = (bool)CFReadStreamOpen(readStream);
63 if (!didSucceed) goto done;
65 // Initialize the hash object
66 CC_MD5_CTX hashObject;
67 CC_MD5_Init(&hashObject);
69 // Make sure chunkSizeForReadingData is valid
70 if (!chunkSizeForReadingData) {
71 chunkSizeForReadingData = FileHashDefaultChunkSizeForReadingData;
74 // Feed the data to the hash object
75 bool hasMoreData = true;
77 uint8_t buffer[chunkSizeForReadingData];
78 CFIndex readBytesCount = CFReadStreamRead(readStream,
80 (CFIndex)sizeof(buffer));
81 if (readBytesCount == -1) break;
82 if (readBytesCount == 0) {
86 CC_MD5_Update(&hashObject,
88 (CC_LONG)readBytesCount);
91 // Check if the read operation succeeded
92 didSucceed = !hasMoreData;
94 // Compute the hash digest
95 unsigned char digest[CC_MD5_DIGEST_LENGTH];
96 CC_MD5_Final(digest, &hashObject);
98 // Abort if the read operation failed
99 if (!didSucceed) goto done;
101 // Compute the string result
102 char hash[2 * sizeof(digest) + 1];
103 for (size_t i = 0; i < sizeof(digest); ++i) {
104 snprintf(hash + (2 * i), 3, "%02x", (int)(digest[i]));
106 result = CFStringCreateWithCString(kCFAllocatorDefault,
108 kCFStringEncodingUTF8);
113 CFReadStreamClose(readStream);
114 CFRelease(readStream);