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
~ChecksumAccessor()31 ChecksumAccessor::~ChecksumAccessor()
32 {
33 }
34
35
36 // #pragma mark - ChecksumFileChecksumAccessor
37
38
ChecksumFileChecksumAccessor(const BEntry & checksumFileEntry)39 ChecksumFileChecksumAccessor::ChecksumFileChecksumAccessor(
40 const BEntry& checksumFileEntry)
41 :
42 fChecksumFileEntry(checksumFileEntry)
43 {
44 }
45
46
47 status_t
GetChecksum(BString & checksum) const48 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
GeneralFileChecksumAccessor(const BEntry & fileEntry,bool skipMissingFile)75 GeneralFileChecksumAccessor::GeneralFileChecksumAccessor(
76 const BEntry& fileEntry, bool skipMissingFile)
77 :
78 fFileEntry(fileEntry),
79 fSkipMissingFile(skipMissingFile)
80 {
81 }
82
83
84 status_t
GetChecksum(BString & checksum) const85 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
StringChecksumAccessor(const BString & checksum)143 StringChecksumAccessor::StringChecksumAccessor(const BString& checksum)
144 :
145 fChecksum(checksum)
146 {
147 }
148
149
150 status_t
GetChecksum(BString & _checksum) const151 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