X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=lib%2Finteg.c;fp=lib%2Finteg.c;h=016302e43f82dd0725192ea5b807d0d209fc42a7;hb=5774fe14b7203c06873e29d13c9520c9a32321cb;hp=0000000000000000000000000000000000000000;hpb=cb9584394f5d9becfbfc140a79bf83836325add2;p=zpackage diff --git a/lib/integ.c b/lib/integ.c new file mode 100644 index 0000000..016302e --- /dev/null +++ b/lib/integ.c @@ -0,0 +1,191 @@ +#define _POSIX_C_SOURCE 200809L +#include + +#include "zpm.h" +#include "sqlite3.h" +#include "sha256.h" + +static void hash_byte(struct sha256_state *h, int ch) { + unsigned char buf[1]; + + buf[0] = ch & 0xff; + sha256_process(h, buf, 1); +} + +/* i will be positive, we are hashing column sizes */ +static void hash_int(struct sha256_state *h, int i) { + int n; + uint64_t z; + + z = i; + + n = sizeof i; + while (n--) { + hash_byte(h, (int)(z & 0xff)); + z = z>>8; + } +} + +/* + * Implementation of the sha3_query(SQL,SIZE) function. + * + * This function compiles and runs the SQL statement(s) given in the argument. + * The results are hashed using a SIZE-bit SHA3. The default size is 256. + * + * The format of the byte stream that is hashed is summarized as follows: + * + * R + * N + * I + * F + * B: + * T: + * + * is the original SQL text for each statement run and is the size of + * that text. The SQL text is UTF-8. A single R character occurs before the + * start of each row. N means a NULL value. I mean an 8-byte little-endian + * integer . F is a floating point number with an 8-byte little-endian + * IEEE floating point value . B means blobs of bytes. T + * means text rendered as bytes of UTF-8. The values are + * expressed as little endian 8 byte integers. + * + * + * There are zero or more R segments, one for each row in the + * result set. After each R, there are one or more N, I, F, B, or T segments, + * one for each column in the result set. Segments are concatentated directly + * with no delimiters of any kind. + */ + +static void hash_query(struct zpm *zpm, const char *zSql, struct sha256_state *h) { + sqlite3 *db; + sqlite3_stmt *pStmt = 0; + int nCol; /* Number of columns in the result set */ + int i, rc; + + const unsigned char *data; + int bytes; + + double r; + sqlite3_uint64 u; + sqlite3_int64 v; + int j; + unsigned char x[9]; + + if (!zSql) return; + if (!zpm) return; + + db = zpm->db; + + rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zSql); + if (rc) { + zpm->dberrmsg = strdup(sqlite3_errmsg(db)); + sqlite3_finalize(pStmt); + return; + } + + nCol = sqlite3_column_count(pStmt); + + while (sqlite3_step(pStmt) == SQLITE_ROW) { + sha256_process(h, (const unsigned char *)"R", 1); + for (i = 0; i < nCol; i++) { + switch (sqlite3_column_type(pStmt, i)) { + case SQLITE_NULL: + hash_byte(h, 'N'); + continue; + break; + case SQLITE_INTEGER: + v = sqlite3_column_int64(pStmt, i); + memcpy(&u, &v, 8); + for (j = 8; j >= 1; j--) { + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'I'; + data = x; + bytes = 9; + break; + case SQLITE_FLOAT: + r = sqlite3_column_double(pStmt, i); + memcpy(&u, &r, 8); + for (j = 8; j >= 1; j--) { + x[j] = u & 0xff; + u >>= 8; + } + x[0] = 'F'; + data = x; + bytes = 9; + break; + case SQLITE_TEXT: + bytes = sqlite3_column_bytes(pStmt, i); + data = sqlite3_column_text(pStmt, i); + hash_byte(h, 'T'); + hash_int(h, bytes); + break; + case SQLITE_BLOB: + bytes = sqlite3_column_bytes(pStmt, i); + data = sqlite3_column_blob(pStmt, i); + hash_byte(h, 'B'); + hash_int(h, bytes); + break; + } + sha256_process(h, data, bytes); + } + } + sqlite3_finalize(pStmt); +} + +int zpm_package_hash(struct zpm *zpm, char *pkgid, char *hash) { + struct sha256_state d; + char *sql; + int i; + unsigned char tmp[32]; + + if (!hash) { + return 0; + } + + sha256_init(&d); + /* find package */ + + sql = sqlite3_mprintf("select package,version,release,description,architecture,url,licenses,packager,build_time from packages_pkgid where pkgid = %Q", pkgid); + + hash_query(zpm, sql, &d); + sqlite3_free(sql); + + /* hash package files */ + + sql = sqlite3_mprintf("select path, mode, username, groupname, configuration, " + "filetype, target, devmajor, devminor, mtime, hash " + "from packagefiles_pkgid where pkgid = %Q order by path", + pkgid); + hash_query(zpm, sql, &d); + sqlite3_free(sql); + + sha256_done(&d, tmp); + for (i=0; i<32; i++) { + sprintf(hash+i*2, "%02x", (unsigned)tmp[i]); + } + hash[64] = 0; + + return 1; + +} + +int zpm_package_sethash(struct zpm *zpm, char *pkgid, char *hash) { + char buf[ZPM_HASH_STRLEN + 1]; + char *sql; + + if (!hash) { + hash = buf; + } + + zpm_package_hash(zpm, pkgid, hash); + + sql = sqlite3_mprintf("update packages_pkgid set hash = %Q where pkgid = %Q", hash, pkgid); + + zpm_exec(zpm, sql, NULL, NULL, NULL); + sqlite3_free(sql); + + return 1; + +}