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