xref: /haiku/src/kits/package/ChecksumAccessors.cpp (revision 25a7b01d15612846f332751841da3579db313082)
1 /*
2  * Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Oliver Tappe <zooey@hirschkaefer.de>
7  *		Ingo Weinhold <ingo_weinhold@gmx.de>
8  */
9 
10 
11 #include <File.h>
12 
13 #include <AutoDeleter.h>
14 #include <SHA256.h>
15 
16 #include <package/ChecksumAccessors.h>
17 
18 
19 namespace BPackageKit {
20 
21 namespace BPrivate {
22 
23 
24 #define NIBBLE_AS_HEX(nibble) \
25 	(nibble >= 10 ? 'a' + nibble - 10 : '0' + nibble)
26 
27 
28 // #pragma mark - ChecksumAccessor
29 
30 
31 ChecksumAccessor::~ChecksumAccessor()
32 {
33 }
34 
35 
36 // #pragma mark - ChecksumFileChecksumAccessor
37 
38 
39 ChecksumFileChecksumAccessor::ChecksumFileChecksumAccessor(
40 	const BEntry& checksumFileEntry)
41 	:
42 	fChecksumFileEntry(checksumFileEntry)
43 {
44 }
45 
46 
47 status_t
48 ChecksumFileChecksumAccessor::GetChecksum(BString& checksum) const
49 {
50 	BFile checksumFile(&fChecksumFileEntry, B_READ_ONLY);
51 	status_t result = checksumFile.InitCheck();
52 	if (result != B_OK)
53 		return result;
54 
55 	const int kSHA256ChecksumHexDumpSize = 64;
56 	char* buffer = checksum.LockBuffer(kSHA256ChecksumHexDumpSize);
57 	if (buffer == NULL)
58 		return B_NO_MEMORY;
59 
60 	ssize_t bytesRead = checksumFile.Read(buffer, kSHA256ChecksumHexDumpSize);
61 	buffer[kSHA256ChecksumHexDumpSize] = '\0';
62 	checksum.UnlockBuffer(kSHA256ChecksumHexDumpSize);
63 	if (bytesRead < 0)
64 		return bytesRead;
65 	if (bytesRead != kSHA256ChecksumHexDumpSize)
66 		return B_IO_ERROR;
67 
68 	return B_OK;
69 }
70 
71 
72 // #pragma mark - GeneralFileChecksumAccessor
73 
74 
75 GeneralFileChecksumAccessor::GeneralFileChecksumAccessor(
76 	const BEntry& fileEntry, bool skipMissingFile)
77 	:
78 	fFileEntry(fileEntry),
79 	fSkipMissingFile(skipMissingFile)
80 {
81 }
82 
83 
84 status_t
85 GeneralFileChecksumAccessor::GetChecksum(BString& checksum) const
86 {
87 	SHA256 sha;
88 
89 	checksum.Truncate(0);
90 
91 	{
92 		BFile file(&fFileEntry, B_READ_ONLY);
93 		status_t result = file.InitCheck();
94 		if (result != B_OK) {
95 			if (result == B_ENTRY_NOT_FOUND && fSkipMissingFile)
96 				return B_OK;
97 			return result;
98 		}
99 
100 		off_t fileSize;
101 		if ((result = file.GetSize(&fileSize)) != B_OK)
102 			return result;
103 
104 		const int kBlockSize = 64 * 1024;
105 		void* buffer = malloc(kBlockSize);
106 		if (buffer == NULL)
107 			return B_NO_MEMORY;
108 		MemoryDeleter memoryDeleter(buffer);
109 
110 		off_t handledSize = 0;
111 		while (handledSize < fileSize) {
112 			ssize_t bytesRead = file.Read(buffer, kBlockSize);
113 			if (bytesRead < 0)
114 				return bytesRead;
115 
116 			sha.Update(buffer, bytesRead);
117 
118 			handledSize += bytesRead;
119 		}
120 	}
121 
122 	const int kSHA256ChecksumSize = sha.DigestLength();
123 	char* buffer = checksum.LockBuffer(2 * kSHA256ChecksumSize);
124 	if (buffer == NULL)
125 		return B_NO_MEMORY;
126 	const uint8* digest = sha.Digest();
127 	for (int i = 0; i < kSHA256ChecksumSize; ++i) {
128 		uint8 highNibble = (digest[i] & 0xF0) >> 4;
129 		buffer[i * 2] = NIBBLE_AS_HEX(highNibble);
130 		uint8 lowNibble = digest[i] & 0x0F;
131 		buffer[1 + i * 2] = NIBBLE_AS_HEX(lowNibble);
132 	}
133 	buffer[2 * kSHA256ChecksumSize] = '\0';
134 	checksum.UnlockBuffer(2 * kSHA256ChecksumSize);
135 
136 	return B_OK;
137 }
138 
139 
140 // #pragma mark - StringChecksumAccessor
141 
142 
143 StringChecksumAccessor::StringChecksumAccessor(const BString& checksum)
144 	:
145 	fChecksum(checksum)
146 {
147 }
148 
149 
150 status_t
151 StringChecksumAccessor::GetChecksum(BString& _checksum) const
152 {
153 	_checksum = fChecksum;
154 	return B_OK;
155 }
156 
157 
158 
159 }	// namespace BPrivate
160 
161 }	// namespace BPackageKit
162