]> pd.if.org Git - zpackage/blob - lib/integ.c
switch to blake2
[zpackage] / lib / integ.c
1 #define _POSIX_C_SOURCE 200809L
2 #include <string.h>
3
4 #include "zpm.h"
5 #include "sqlite3.h"
6 #include "lib/blake2/ref/blake2.h"
7
8 static void hash_byte(struct blake2b_state__ *h, int ch) {
9         unsigned char buf[1];
10
11         buf[0] = ch & 0xff;
12         blake2b_update(h, buf, 1);
13 }
14
15 /* i will be positive, we are hashing column sizes */
16 static void hash_int(struct blake2b_state__ *h, int i) {
17         int n;
18         uint64_t z;
19
20         z = i;
21
22         n = sizeof i;
23         while (n--) {
24                 hash_byte(h, (int)(z & 0xff));
25                 z = z>>8;
26         }
27 }
28
29 /*
30  * Implementation of the sha3_query(SQL,SIZE) function.
31  *
32  * This function compiles and runs the SQL statement(s) given in the argument.
33  * The results are hashed using a SIZE-bit SHA3.  The default size is 256.
34  *
35  * The format of the byte stream that is hashed is summarized as follows:
36  *
37  *       R
38  *       N
39  *       I<int>
40  *       F<ieee-float>
41  *       B<size>:<bytes>
42  *       T<size>:<text>
43  *
44  * <sql> is the original SQL text for each statement run and <n> is the size of
45  * that text.  The SQL text is UTF-8.  A single R character occurs before the
46  * start of each row.  N means a NULL value.  I mean an 8-byte little-endian
47  * integer <int>.  F is a floating point number with an 8-byte little-endian
48  * IEEE floating point value <ieee-float>.  B means blobs of <size> bytes.  T
49  * means text rendered as <size> bytes of UTF-8.  The <size> values are
50  * expressed as little endian 8 byte integers.
51  *
52  * 
53  * There are zero or more R segments, one for each row in the
54  * result set.  After each R, there are one or more N, I, F, B, or T segments,
55  * one for each column in the result set.  Segments are concatentated directly
56  * with no delimiters of any kind.
57  */
58
59 static void hash_query(struct zpm *zpm, const char *zSql, struct blake2b_state__ *h) {
60         sqlite3 *db;
61         sqlite3_stmt *pStmt = 0;
62         int nCol; /* Number of columns in the result set */
63         int i, rc;
64
65         const unsigned char *data;
66         int bytes;
67
68         double r;
69         sqlite3_uint64 u;
70         sqlite3_int64 v;
71         int j;
72         unsigned char x[9];
73
74         if (!zSql) return;
75         if (!zpm) return;
76
77         db = zpm->db;
78
79         rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql);
80         if (rc) {
81                 zpm->dberrmsg = strdup(sqlite3_errmsg(db));
82                 sqlite3_finalize(pStmt);
83                 return;
84         }
85
86         nCol = sqlite3_column_count(pStmt);
87
88         while (sqlite3_step(pStmt) == SQLITE_ROW) {
89                 blake2b_update(h, "R", 1);
90                 for (i = 0; i < nCol; i++) {
91                         switch (sqlite3_column_type(pStmt, i)) {
92                                 case SQLITE_NULL:
93                                         hash_byte(h, 'N');
94                                         continue;
95                                         break;
96                                 case SQLITE_INTEGER:
97                                         v = sqlite3_column_int64(pStmt, i);
98                                         memcpy(&u, &v, 8);
99                                         for (j = 8; j >= 1; j--) {
100                                                 x[j] = u & 0xff;
101                                                 u >>= 8;
102                                         }
103                                         x[0] = 'I';
104                                         data = x;
105                                         bytes = 9;
106                                         break;
107                                 case SQLITE_FLOAT:
108                                         r = sqlite3_column_double(pStmt, i);
109                                         memcpy(&u, &r, 8);
110                                         for (j = 8; j >= 1; j--) {
111                                                 x[j] = u & 0xff;
112                                                 u >>= 8;
113                                         }
114                                         x[0] = 'F';
115                                         data = x;
116                                         bytes = 9;
117                                         break;
118                                 case SQLITE_TEXT:
119                                         bytes = sqlite3_column_bytes(pStmt, i);
120                                         data = sqlite3_column_text(pStmt, i);
121                                         hash_byte(h, 'T');
122                                         hash_int(h, bytes);
123                                         break;
124                                 case SQLITE_BLOB:
125                                         bytes = sqlite3_column_bytes(pStmt, i);
126                                         data = sqlite3_column_blob(pStmt, i);
127                                         hash_byte(h, 'B');
128                                         hash_int(h, bytes);
129                                         break;
130                                 default:
131                                         hash_byte(h, 'U');
132                                         continue;
133                                         break;
134                         }
135                         blake2b_update(h, data, bytes);
136                 }
137         }
138         sqlite3_finalize(pStmt);
139 }
140
141 int zpm_package_hash(struct zpm *zpm, char *pkgid, char *hash) {
142         struct blake2b_state__ d;
143         char *sql;
144         int i;
145         unsigned char tmp[32];
146
147         if (!hash) {
148                 return 0;
149         }
150
151         /* find package */
152
153         blake2b_init(&d, 32);
154
155         sql = sqlite3_mprintf("select package,version,release,description,architecture,url,licenses,packager,build_time from packages_pkgid where pkgid = %Q", pkgid);
156
157         hash_query(zpm, sql, &d);
158         sqlite3_free(sql);
159
160         /* hash package files */
161
162         sql = sqlite3_mprintf("select path, mode, username, groupname, configuration, "
163                 "filetype, target, device, mtime, hash "
164                 "from packagefiles_pkgid where pkgid = %Q order by path",
165                 pkgid);
166         hash_query(zpm, sql, &d);
167         sqlite3_free(sql);
168
169         /* package dependencies */
170         sql = sqlite3_mprintf("dselect requires from packagedeps"
171                 " where printf('%%q-%%q-%%d',package,version,release) = %Q"
172                "order by requires",
173                 pkgid);
174         hash_query(zpm, sql, &d);
175         sqlite3_free(sql);
176
177         blake2b_final(&d, tmp, sizeof tmp);
178         for (i=0; i<32; i++) {
179                 sprintf(hash+i*2, "%02x", (unsigned)tmp[i]);
180         }
181         hash[64] = 0;
182
183         return 1;
184 }
185
186 int zpm_package_sethash(struct zpm *zpm, char *pkgid, char *hash) {
187         char buf[ZPM_HASH_STRLEN + 1];
188         char *sql;
189
190         if (!hash) {
191                 hash = buf;
192         }
193
194         zpm_package_hash(zpm, pkgid, hash);
195
196         sql = sqlite3_mprintf("update packages_pkgid set hash = %Q where pkgid = %Q", hash, pkgid);
197
198         zpm_exec(zpm, sql, NULL, NULL, NULL);
199         sqlite3_free(sql);
200
201         return 1;
202 }