+++ /dev/null
-/*
- * add a file/files to an sqlite db
- * in the 'files' table.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/mman.h>
-
-#include <sqlite3.h>
-#include "sha256.h"
-
-#include "lzma.h"
-
-
-void uncompresslzma(void *buf, size_t bufsize, FILE *out) {
- lzma_stream s = LZMA_STREAM_INIT;
- lzma_stream *strm;
-
- uint8_t outbuf[BUFSIZ];
-
- int ret;
-
- strm = &s;
-
- ret = lzma_stream_decoder(strm, UINT64_MAX, 0);
- /* The only reasonable error here is LZMA_MEM_ERROR. */
- if (ret != LZMA_OK) {
- fprintf(stderr, "%s", ret == LZMA_MEM_ERROR ? strerror(ENOMEM)
- : "Internal error (bug)");
- exit(EXIT_FAILURE);
- }
-
- strm->avail_in = bufsize;
- strm->next_in = buf;
- strm->avail_out = BUFSIZ;
- strm->next_out = outbuf;
-
- lzma_action action = LZMA_RUN;
-
- while (1) {
- ret = lzma_code(strm, action);
-
- // Write and check write error before checking decoder error.
- // This way as much data as possible gets written to output
- // even if decoder detected an error.
- if (strm->avail_out == 0 || ret != LZMA_OK) {
- const size_t write_size = BUFSIZ - strm->avail_out;
-
- if (fwrite(outbuf, 1, write_size, out) != write_size) {
- // Wouldn't be a surprise if writing to stderr
- // would fail too but at least try to show an
- // error message.
- fprintf(stderr, "Cannot write to output file stream: "
- "%s", strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- strm->next_out = outbuf;
- strm->avail_out = BUFSIZ;
- }
-
- if (ret != LZMA_OK) {
- if (ret == LZMA_STREAM_END) {
- // lzma_stream_decoder() already guarantees
- // that there's no trailing garbage.
- assert(strm->avail_in == 0);
- //assert(action == LZMA_FINISH);
- return;
- }
-
- const char *msg;
- switch (ret) {
- case LZMA_MEM_ERROR:
- msg = strerror(ENOMEM);
- break;
-
- case LZMA_FORMAT_ERROR:
- msg = "File format not recognized";
- break;
-
- case LZMA_OPTIONS_ERROR:
- // FIXME: Better message?
- msg = "Unsupported compression options";
- break;
-
- case LZMA_DATA_ERROR:
- msg = "File is corrupt";
- break;
-
- case LZMA_BUF_ERROR:
- msg = "Unexpected end of input";
- break;
-
- default:
- msg = "Internal error (bug)";
- break;
- }
-
- fprintf(stderr, "xz: %s\n", msg);
- exit(EXIT_FAILURE);
- }
- }
-}
-
-#define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x))
-
-int main(int ac, char **av){
- sqlite3 *db = 0;
- int rc;
-
- int blobsize;
- int64_t size;
- void *xzdata;
- int type;
- FILE *out;
- sqlite3_stmt *ifile;
-
- char *hash;
- char *filename;
-
- if (ac < 3) {
- fprintf(stderr, "usage: db hash file\n");
- return 1;
- }
-
- rc = sqlite3_open(av[1], &db);
- if (rc) {
- SQLERROR(sqlite3_errmsg(db));
- sqlite3_close(db);
- return 1;
- }
-
- rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0);
- if (rc != SQLITE_OK) {
- SQLERROR(sqlite3_errmsg(db));
- return 1;
- }
-
- /* hash, filename */
- hash = av[2];
- filename = av[3];
-
- sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
-
- rc = sqlite3_step(ifile);
-
- if (rc == SQLITE_DONE) {
- /* didn't find a row */
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- fprintf(stderr, "no such hash\n");
- return 1;
- }
- /* either way we're done with this now */
-
- if (rc != SQLITE_ROW) {
- SQLERROR(sqlite3_errmsg(db));
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- return 2;
- }
-
- type = sqlite3_column_type(ifile, 0);
- if (type == SQLITE_NULL) {
- fprintf(stderr, "no file size\n");
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- return 3;
- }
- type = sqlite3_column_type(ifile, 1);
- if (type == SQLITE_NULL) {
- fprintf(stderr, "no file data\n");
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- return 4;
- }
- size = sqlite3_column_int64(ifile, 0);
- xzdata = (void *)sqlite3_column_blob(ifile, 1);
- blobsize = sqlite3_column_bytes(ifile, 1);
-
- out = fopen(filename, "w");
- if (!out) {
- fprintf(stderr, "can't open output file %s\n", filename);
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- return 5;
- }
- //fwrite(xzdata, blobsize, 1, stdout);
-
- fprintf(stderr, "uncompressing %d bytes at %p, expect %lld\n", blobsize, xzdata, (long long int)size);
- uncompresslzma(xzdata, blobsize, out);
- fclose(out);
-
- sqlite3_finalize(ifile);
- sqlite3_close(db);
- return 0;
-}
-void *compresslzma(void *buf, size_t bufsize, size_t *len) {
- /* xz compress it */
- size_t outsize;
- void *outbuf;
- size_t outlen = 0;
-
- outsize = lzma_stream_buffer_bound(bufsize);
- outbuf = malloc(outsize);
- if (!outbuf) {
- *len = 0;
- return NULL;
- }
- /* TODO adjust encoding level for size */
- lzma_easy_buffer_encode(6, LZMA_CHECK_CRC64, NULL,
- buf, bufsize,
- outbuf, &outlen, outsize
- );
- *len = outlen;
- return outbuf;
-}
-
-static int callback(void *NotUsed, int argc, char **argv, char **azColName){
- int i;
- for(i=0; i<argc; i++){
- printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
- }
- printf("\n");
- return 0;
-}
-
-static char *create_table = "create table if not exists files (hash text primary key, size integer, compression text, content blob)";
-
-struct dbh {
- sqlite3 *db;
- char *errmsg;
- int rc;
-};
-
-#define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x))
-static int begin(sqlite3 *db) {
- int rc;
- char *err;
-
- rc = sqlite3_exec(db, "begin;", callback, 0, &err);
- if (rc != SQLITE_OK) {
- SQLERROR(err);
- sqlite3_free(err);
- }
- return rc;
-}
-
-static int commit(sqlite3 *db) {
- int rc;
- char *err;
-
- rc = sqlite3_exec(db, "commit;", callback, 0, &err);
- if (rc != SQLITE_OK) {
- SQLERROR(err);
- sqlite3_free(err);
- }
- return rc;
-}
-static int rollback(sqlite3 *db) {
- int rc;
- char *err;
-
- rc = sqlite3_exec(db, "rollback;", callback, 0, &err);
- if (rc != SQLITE_OK) {
- SQLERROR(err);
- sqlite3_free(err);
- }
- return rc;
-}
-
-int main(int ac, char **av){
- sqlite3 *db = 0;
- char *errmsg = 0;
- int rc, i, j;
-
- rc = sqlite3_open(av[1], &db);
- if (rc) {
- SQLERROR(sqlite3_errmsg(db));
- sqlite3_close(db);
- return 1;
- }
-
- rc = sqlite3_exec(db, create_table, callback, 0, &errmsg);
- if (rc != SQLITE_OK) {
- SQLERROR(errmsg);
- sqlite3_free(errmsg);
- sqlite3_close(db);
- return 1;
- }
-
- sqlite3_stmt *ifile;
-
- rc = sqlite3_prepare(db, "insert or ignore into files (hash,size,compression,content) values (?,?,?,?)", -1, &ifile,0);
- if (rc != SQLITE_OK) {
- SQLERROR(sqlite3_errmsg(db));
- return 1;
- }
-
- begin(db);
- /* insert each file */
- for (i = 2; i < ac; i++) {
- int fd;
- void *content;
- struct stat sbuf;
- unsigned char tmp[32];
- char hash[65];
- hash_state md;
-
- fd = open(av[i], O_RDONLY);
- if (fd == -1) {
- rollback(db);
- sqlite3_close(db);
- exit(1);
- }
- if (fstat(fd, &sbuf) == -1) {
- rollback(db);
- sqlite3_close(db);
- exit(1);
- }
- /* not a regular file? */
- if (!S_ISREG(sbuf.st_mode)) {
- rollback(db);
- sqlite3_close(db);
- exit(1);
- }
-
- content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
- if (!content) {
- rollback(db);
- sqlite3_close(db);
- exit(2);
- }
-
- sha256_init(&md);
- sha256_process(&md, content, sbuf.st_size);
- sha256_done(&md, tmp);
- for (j=0;j<32;j++) {
- sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
- }
- hash[64] = 0;
- //fprintf(stderr, "file %s: %s\n", av[i], hash);
-
- void *xzcompressed;
- size_t compresslen;
-
- xzcompressed = compresslzma(content, sbuf.st_size, &compresslen);
-
- sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
- sqlite3_bind_int64(ifile, 2, sbuf.st_size);
- sqlite3_bind_text(ifile, 3, "xz", 2, SQLITE_STATIC);
- sqlite3_bind_blob64(ifile, 4, xzcompressed, compresslen, SQLITE_STATIC);
-
- rc = sqlite3_step(ifile);
-
- /* either way we're done with this now */
- munmap(content, sbuf.st_size);
-
- if (rc != SQLITE_DONE) {
- SQLERROR(sqlite3_errmsg(db));
- sqlite3_finalize(ifile);
- rollback(db);
- sqlite3_close(db);
- return 1;
- }
- sqlite3_reset(ifile);
- free(xzcompressed);
- printf("%s\n", hash);
- }
- sqlite3_finalize(ifile);
- commit(db);
-
- sqlite3_close(db);
- return 0;
-}