1 : #include <iostream>
2 :
3 : extern "C" {
4 : #include "md5.h"
5 : }
6 :
7 : #include "hash.hh"
8 : #include "archive.hh"
9 :
10 :
11 : Hash::Hash()
12 303 : {
13 303 : memset(hash, 0, sizeof(hash));
14 : }
15 :
16 :
17 : bool Hash::operator == (const Hash & h2) const
18 0 : {
19 0 : for (unsigned int i = 0; i < hashSize; i++)
20 0 : if (hash[i] != h2.hash[i]) return false;
21 0 : return true;
22 : }
23 :
24 :
25 : bool Hash::operator != (const Hash & h2) const
26 0 : {
27 0 : return !(*this == h2);
28 : }
29 :
30 :
31 : bool Hash::operator < (const Hash & h) const
32 0 : {
33 0 : for (unsigned int i = 0; i < hashSize; i++) {
34 0 : if (hash[i] < h.hash[i]) return true;
35 0 : if (hash[i] > h.hash[i]) return false;
36 : }
37 0 : return false;
38 : }
39 :
40 :
41 : Hash::operator string() const
42 213 : {
43 213 : ostringstream str;
44 3621 : for (unsigned int i = 0; i < hashSize; i++) {
45 3408 : str.fill('0');
46 3408 : str.width(2);
47 3408 : str << hex << (int) hash[i];
48 : }
49 213 : return str.str();
50 : }
51 :
52 :
53 : Hash parseHash(const string & s)
54 72 : {
55 72 : Hash hash;
56 72 : if (s.length() != Hash::hashSize * 2)
57 0 : throw Error(format("invalid hash `%1%'") % s);
58 1224 : for (unsigned int i = 0; i < Hash::hashSize; i++) {
59 1152 : string s2(s, i * 2, 2);
60 1152 : if (!isxdigit(s2[0]) || !isxdigit(s2[1]))
61 0 : throw Error(format("invalid hash `%1%'") % s);
62 1152 : istringstream str(s2);
63 1152 : int n;
64 1152 : str >> hex >> n;
65 1152 : hash.hash[i] = n;
66 : }
67 72 : return hash;
68 : }
69 :
70 :
71 : bool isHash(const string & s)
72 0 : {
73 0 : if (s.length() != 32) return false;
74 0 : for (int i = 0; i < 32; i++) {
75 0 : char c = s[i];
76 0 : if (!((c >= '0' && c <= '9') ||
77 : (c >= 'a' && c <= 'f')))
78 0 : return false;
79 : }
80 0 : return true;
81 : }
82 :
83 :
84 : Hash hashString(const string & s)
85 135 : {
86 135 : Hash hash;
87 135 : md5_buffer(s.c_str(), s.length(), hash.hash);
88 135 : return hash;
89 : }
90 :
91 :
92 : Hash hashFile(const Path & path)
93 0 : {
94 0 : Hash hash;
95 0 : FILE * file = fopen(path.c_str(), "rb");
96 0 : if (!file)
97 0 : throw SysError(format("file `%1%' does not exist") % path);
98 0 : int err = md5_stream(file, hash.hash);
99 0 : fclose(file);
100 0 : if (err) throw SysError(format("cannot hash file `%1%'") % path);
101 0 : return hash;
102 : }
103 :
104 :
105 : struct HashSink : DumpSink
106 : {
107 : struct md5_ctx ctx;
108 : virtual void operator ()
109 : (const unsigned char * data, unsigned int len)
110 456 : {
111 456 : md5_process_bytes(data, len, &ctx);
112 : }
113 : };
114 :
115 :
116 : Hash hashPath(const Path & path)
117 23 : {
118 23 : Hash hash;
119 120 : HashSink sink;
120 125 : md5_init_ctx(&sink.ctx);
121 23 : dumpPath(path, sink);
122 23 : md5_finish_ctx(&sink.ctx, hash.hash);
123 23 : return hash;
124 : }
|