LTP GCOV extension - code coverage report
Current view: directory - src/libutil - hash.cc
Test: app.info
Date: 2006-10-11 Instrumented lines: 161
Code covered: 87.6 % Executed lines: 141

       1                 : #include "config.h"
       2                 : 
       3                 : #include <iostream>
       4                 : 
       5                 : #ifdef HAVE_OPENSSL
       6                 : #include <openssl/md5.h>
       7                 : #include <openssl/sha.h>
       8                 : #else
       9                 : extern "C" {
      10                 : #include "md5.h"
      11                 : #include "sha1.h"
      12                 : #include "sha256.h"
      13                 : }
      14                 : #endif
      15                 : 
      16                 : #include "hash.hh"
      17                 : #include "archive.hh"
      18                 : #include "util.hh"
      19                 : 
      20                 : #include <sys/types.h>
      21                 : #include <sys/stat.h>
      22                 : #include <fcntl.h>
      23                 : 
      24                 : 
      25                 : namespace nix {
      26                 : 
      27                 : 
      28                 : Hash::Hash()
      29            3136 : {
      30            3136 :     type = htUnknown;
      31            3136 :     hashSize = 0;
      32            3136 :     memset(hash, 0, maxHashSize);
      33                 : }
      34                 : 
      35                 : 
      36                 : Hash::Hash(HashType type)
      37            3584 : {
      38            3584 :     this->type = type;
      39            3584 :     if (type == htMD5) hashSize = md5HashSize;
      40            3554 :     else if (type == htSHA1) hashSize = sha1HashSize;
      41            3538 :     else if (type == htSHA256) hashSize = sha256HashSize;
      42               0 :     else throw Error("unknown hash type");
      43            3584 :     assert(hashSize <= maxHashSize);
      44            3584 :     memset(hash, 0, maxHashSize);
      45                 : }
      46                 : 
      47                 : 
      48                 : bool Hash::operator == (const Hash & h2) const
      49              50 : {
      50              50 :     if (hashSize != h2.hashSize) return false;
      51            1562 :     for (unsigned int i = 0; i < hashSize; i++)
      52            1513 :         if (hash[i] != h2.hash[i]) return false;
      53              49 :     return true;
      54                 : }
      55                 : 
      56                 : 
      57                 : bool Hash::operator != (const Hash & h2) const
      58              50 : {
      59              50 :     return !(*this == h2);
      60                 : }
      61                 : 
      62                 : 
      63                 : bool Hash::operator < (const Hash & h) const
      64               0 : {
      65               0 :     for (unsigned int i = 0; i < hashSize; i++) {
      66               0 :         if (hash[i] < h.hash[i]) return true;
      67               0 :         if (hash[i] > h.hash[i]) return false;
      68                 :     }
      69               0 :     return false;
      70                 : }
      71                 : 
      72                 : 
      73             690 : const string base16Chars = "0123456789abcdef";
      74                 : 
      75                 : 
      76                 : string printHash(const Hash & hash)
      77            3106 : {
      78            3106 :     char buf[hash.hashSize * 2];
      79          102090 :     for (unsigned int i = 0; i < hash.hashSize; i++) {
      80           98984 :         buf[i * 2] = base16Chars[hash.hash[i] >> 4];
      81           98984 :         buf[i * 2 + 1] = base16Chars[hash.hash[i] & 0x0f];
      82                 :     }
      83            3106 :     return string(buf, hash.hashSize * 2);
      84                 : }
      85                 : 
      86                 :     
      87                 : Hash parseHash(HashType ht, const string & s)
      88              15 : {
      89              15 :     Hash hash(ht);
      90              15 :     if (s.length() != hash.hashSize * 2)
      91               0 :         throw Error(format("invalid hash `%1%'") % s);
      92             323 :     for (unsigned int i = 0; i < hash.hashSize; i++) {
      93             308 :         string s2(s, i * 2, 2);
      94             308 :         if (!isxdigit(s2[0]) || !isxdigit(s2[1])) 
      95               0 :             throw Error(format("invalid hash `%1%'") % s);
      96             308 :         std::istringstream str(s2);
      97             308 :         int n;
      98             308 :         str >> std::hex >> n;
      99             308 :         hash.hash[i] = n;
     100                 :     }
     101              15 :     return hash;
     102                 : }
     103                 : 
     104                 : 
     105                 : static unsigned char divMod(unsigned char * bytes, unsigned char y)
     106           10888 : {
     107           10888 :     unsigned int borrow = 0;
     108                 : 
     109           10888 :     int pos = Hash::maxHashSize - 1;
     110          233478 :     while (pos >= 0 && !bytes[pos]) --pos;
     111                 : 
     112          262540 :     for ( ; pos >= 0; --pos) {
     113          125826 :         unsigned int s = bytes[pos] + (borrow << 8);
     114          125826 :         unsigned int d = s / y;
     115          125826 :         borrow = s % y;
     116          125826 :         bytes[pos] = d;
     117                 :     }
     118                 : 
     119           10888 :     return borrow;
     120                 : }
     121                 : 
     122                 : 
     123                 : unsigned int hashLength32(const Hash & hash)
     124             322 : {
     125             322 :     return (hash.hashSize * 8 - 1) / 5 + 1;
     126                 : }
     127                 : 
     128                 : 
     129                 : // omitted: E O U T
     130             345 : const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
     131                 : 
     132                 : 
     133                 : string printHash32(const Hash & hash)
     134             319 : {
     135             319 :     Hash hash2(hash);
     136             319 :     unsigned int len = hashLength32(hash);
     137                 : 
     138             319 :     const char * chars = base32Chars.c_str();
     139                 :     
     140             319 :     string s(len, '0');
     141                 : 
     142             319 :     int pos = len - 1;
     143           11207 :     while (pos >= 0) {
     144           10888 :         unsigned char digit = divMod(hash2.hash, 32);
     145           10888 :         s[pos--] = chars[digit];
     146                 :     }
     147                 : 
     148           10527 :     for (unsigned int i = 0; i < hash2.maxHashSize; ++i)
     149           10208 :         assert(hash2.hash[i] == 0);
     150                 : 
     151               0 :     return s;
     152                 : }
     153                 : 
     154                 : 
     155                 : static bool mul(unsigned char * bytes, unsigned char y, int maxSize)
     156             792 : {
     157             792 :     unsigned char carry = 0;
     158                 : 
     159           25368 :     for (int pos = 0; pos < maxSize; ++pos) {
     160           24576 :         unsigned int m = bytes[pos] * y + carry;
     161           24576 :         bytes[pos] = m & 0xff;
     162           24576 :         carry = m >> 8;
     163                 :     }
     164                 : 
     165             792 :     return carry;
     166                 : }
     167                 : 
     168                 : 
     169                 : static bool add(unsigned char * bytes, unsigned char y, int maxSize)
     170             792 : {
     171             792 :     unsigned char carry = y;
     172                 : 
     173             792 :     for (int pos = 0; pos < maxSize; ++pos) {
     174             792 :         unsigned int m = bytes[pos] + carry;
     175             792 :         bytes[pos] = m & 0xff;
     176             792 :         carry = m >> 8;
     177             792 :         if (carry == 0) break;
     178                 :     }
     179                 : 
     180             792 :     return carry;
     181                 : }
     182                 : 
     183                 : 
     184                 : Hash parseHash32(HashType ht, const string & s)
     185              16 : {
     186              16 :     Hash hash(ht);
     187                 : 
     188              16 :     const char * chars = base32Chars.c_str();
     189                 : 
     190             808 :     for (unsigned int i = 0; i < s.length(); ++i) {
     191             792 :         char c = s[i];
     192             792 :         unsigned char digit;
     193           12787 :         for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
     194           12787 :             if (chars[digit] == c) break;
     195             792 :         if (digit >= 32)
     196               0 :             throw Error(format("invalid base-32 hash `%1%'") % s);
     197             792 :         if (mul(hash.hash, 32, hash.hashSize) ||
     198                 :             add(hash.hash, digit, hash.hashSize))
     199               0 :             throw Error(format("base-32 hash `%1%' is too large") % s);
     200                 :     }
     201                 : 
     202              16 :     return hash;
     203                 : }
     204                 : 
     205                 : 
     206                 : bool isHash(const string & s)
     207               0 : {
     208               0 :     if (s.length() != 32) return false;
     209               0 :     for (int i = 0; i < 32; i++) {
     210               0 :         char c = s[i];
     211               0 :         if (!((c >= '0' && c <= '9') ||
     212                 :               (c >= 'a' && c <= 'f')))
     213               0 :             return false;
     214                 :     }
     215               0 :     return true;
     216                 : }
     217                 : 
     218                 : 
     219                 : union Ctx
     220                 : {
     221                 :     MD5_CTX md5;
     222                 :     SHA_CTX sha1;
     223                 :     SHA256_CTX sha256;
     224                 : };
     225                 : 
     226                 : 
     227                 : static void start(HashType ht, Ctx & ctx)
     228            3440 : {
     229            3440 :     if (ht == htMD5) MD5_Init(&ctx.md5);
     230            3422 :     else if (ht == htSHA1) SHA1_Init(&ctx.sha1);
     231            3416 :     else if (ht == htSHA256) SHA256_Init(&ctx.sha256);
     232                 : }
     233                 : 
     234                 : 
     235                 : static void update(HashType ht, Ctx & ctx,
     236                 :     const unsigned char * bytes, unsigned int len)
     237           55796 : {
     238           55796 :     if (ht == htMD5) MD5_Update(&ctx.md5, bytes, len);
     239           55457 :     else if (ht == htSHA1) SHA1_Update(&ctx.sha1, bytes, len);
     240           55336 :     else if (ht == htSHA256) SHA256_Update(&ctx.sha256, bytes, len);
     241                 : }
     242                 : 
     243                 : 
     244                 : static void finish(HashType ht, Ctx & ctx, unsigned char * hash)
     245            3439 : {
     246            3439 :     if (ht == htMD5) MD5_Final(hash, &ctx.md5);
     247            3421 :     else if (ht == htSHA1) SHA1_Final(hash, &ctx.sha1);
     248            3415 :     else if (ht == htSHA256) SHA256_Final(hash, &ctx.sha256);
     249                 : }
     250                 : 
     251                 : 
     252                 : Hash hashString(HashType ht, const string & s)
     253             586 : {
     254             586 :     Ctx ctx;
     255             586 :     Hash hash(ht);
     256             586 :     start(ht, ctx);
     257             586 :     update(ht, ctx, (const unsigned char *) s.c_str(), s.length());
     258             586 :     finish(ht, ctx, hash.hash);
     259             586 :     return hash;
     260                 : }
     261                 : 
     262                 : 
     263                 : Hash hashFile(HashType ht, const Path & path)
     264              61 : {
     265              61 :     Ctx ctx;
     266              61 :     Hash hash(ht);
     267              61 :     start(ht, ctx);
     268                 : 
     269              61 :     AutoCloseFD fd = open(path.c_str(), O_RDONLY);
     270              61 :     if (fd == -1) throw SysError(format("opening file `%1%'") % path);
     271                 : 
     272             121 :     unsigned char buf[8192];
     273             121 :     ssize_t n;
     274             121 :     while ((n = read(fd, buf, sizeof(buf)))) {
     275              60 :         checkInterrupt();
     276              60 :         if (n == -1) throw SysError(format("reading file `%1%'") % path);
     277              60 :         update(ht, ctx, buf, n);
     278                 :     }
     279                 :     
     280              61 :     finish(ht, ctx, hash.hash);
     281              61 :     return hash;
     282                 : }
     283                 : 
     284                 : 
     285                 : struct HashSink : DumpSink
     286                 : {
     287                 :     HashType ht;
     288                 :     Ctx ctx;
     289                 :     virtual void operator ()
     290                 :         (const unsigned char * data, unsigned int len)
     291           55150 :     {
     292           55150 :         update(ht, ctx, data, len);
     293                 :     }
     294                 : };
     295                 : 
     296                 : 
     297                 : Hash hashPath(HashType ht, const Path & path)
     298            2793 : {
     299           13965 :     HashSink sink;
     300            2793 :     sink.ht = ht;
     301            2793 :     Hash hash(ht);
     302            2793 :     start(ht, sink.ctx);
     303            2793 :     dumpPath(path, sink);
     304            2792 :     finish(ht, sink.ctx, hash.hash);
     305            2792 :     return hash;
     306                 : }
     307                 : 
     308                 : 
     309                 : Hash compressHash(const Hash & hash, unsigned int newSize)
     310             282 : {
     311             282 :     Hash h;
     312             282 :     h.hashSize = newSize;
     313            9306 :     for (unsigned int i = 0; i < hash.hashSize; ++i)
     314            9024 :         h.hash[i % newSize] ^= hash.hash[i];
     315             282 :     return h;
     316                 : }
     317                 : 
     318                 : 
     319                 : HashType parseHashType(const string & s)
     320              91 : {
     321              91 :     if (s == "md5") return htMD5;
     322              72 :     else if (s == "sha1") return htSHA1;
     323              63 :     else if (s == "sha256") return htSHA256;
     324               0 :     else return htUnknown;
     325                 : }
     326                 : 
     327                 :  
     328             345 : }

Generated by: LTP GCOV extension version 1.1