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 19namespace BPackageKit { 20 21namespace 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 31ChecksumAccessor::~ChecksumAccessor() 32{ 33} 34 35 36// #pragma mark - ChecksumFileChecksumAccessor 37 38 39ChecksumFileChecksumAccessor::ChecksumFileChecksumAccessor( 40 const BEntry& checksumFileEntry) 41 : 42 fChecksumFileEntry(checksumFileEntry) 43{ 44} 45 46 47status_t 48ChecksumFileChecksumAccessor::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 75GeneralFileChecksumAccessor::GeneralFileChecksumAccessor( 76 const BEntry& fileEntry, bool skipMissingFile) 77 : 78 fFileEntry(fileEntry), 79 fSkipMissingFile(skipMissingFile) 80{ 81} 82 83 84status_t 85GeneralFileChecksumAccessor::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 143StringChecksumAccessor::StringChecksumAccessor(const BString& checksum) 144 : 145 fChecksum(checksum) 146{ 147} 148 149 150status_t 151StringChecksumAccessor::GetChecksum(BString& _checksum) const 152{ 153 _checksum = fChecksum; 154 return B_OK; 155} 156 157 158 159} // namespace BPrivate 160 161} // namespace BPackageKit 162