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