2 * add a file/files to an sqlite db
3 * in the 'files' table.
21 void uncompresslzma(void *buf, size_t bufsize, FILE *out) {
22 lzma_stream s = LZMA_STREAM_INIT;
25 uint8_t outbuf[BUFSIZ];
31 ret = lzma_stream_decoder(strm, UINT64_MAX, 0);
32 /* The only reasonable error here is LZMA_MEM_ERROR. */
34 fprintf(stderr, "%s", ret == LZMA_MEM_ERROR ? strerror(ENOMEM)
35 : "Internal error (bug)");
39 strm->avail_in = bufsize;
41 strm->avail_out = BUFSIZ;
42 strm->next_out = outbuf;
44 lzma_action action = LZMA_RUN;
47 ret = lzma_code(strm, action);
49 // Write and check write error before checking decoder error.
50 // This way as much data as possible gets written to output
51 // even if decoder detected an error.
52 if (strm->avail_out == 0 || ret != LZMA_OK) {
53 const size_t write_size = BUFSIZ - strm->avail_out;
55 if (fwrite(outbuf, 1, write_size, out) != write_size) {
56 // Wouldn't be a surprise if writing to stderr
57 // would fail too but at least try to show an
59 fprintf(stderr, "Cannot write to output file stream: "
60 "%s", strerror(errno));
64 strm->next_out = outbuf;
65 strm->avail_out = BUFSIZ;
69 if (ret == LZMA_STREAM_END) {
70 // lzma_stream_decoder() already guarantees
71 // that there's no trailing garbage.
72 assert(strm->avail_in == 0);
73 //assert(action == LZMA_FINISH);
80 msg = strerror(ENOMEM);
83 case LZMA_FORMAT_ERROR:
84 msg = "File format not recognized";
87 case LZMA_OPTIONS_ERROR:
88 // FIXME: Better message?
89 msg = "Unsupported compression options";
93 msg = "File is corrupt";
97 msg = "Unexpected end of input";
101 msg = "Internal error (bug)";
105 fprintf(stderr, "xz: %s\n", msg);
111 #define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x))
113 int main(int ac, char **av){
128 fprintf(stderr, "usage: db hash file\n");
132 rc = sqlite3_open(av[1], &db);
134 SQLERROR(sqlite3_errmsg(db));
139 rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0);
140 if (rc != SQLITE_OK) {
141 SQLERROR(sqlite3_errmsg(db));
149 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
151 rc = sqlite3_step(ifile);
153 if (rc == SQLITE_DONE) {
154 /* didn't find a row */
155 sqlite3_finalize(ifile);
157 fprintf(stderr, "no such hash\n");
160 /* either way we're done with this now */
162 if (rc != SQLITE_ROW) {
163 SQLERROR(sqlite3_errmsg(db));
164 sqlite3_finalize(ifile);
169 type = sqlite3_column_type(ifile, 0);
170 if (type == SQLITE_NULL) {
171 fprintf(stderr, "no file size\n");
172 sqlite3_finalize(ifile);
176 type = sqlite3_column_type(ifile, 1);
177 if (type == SQLITE_NULL) {
178 fprintf(stderr, "no file data\n");
179 sqlite3_finalize(ifile);
183 size = sqlite3_column_int64(ifile, 0);
184 xzdata = (void *)sqlite3_column_blob(ifile, 1);
185 blobsize = sqlite3_column_bytes(ifile, 1);
187 out = fopen(filename, "w");
189 fprintf(stderr, "can't open output file %s\n", filename);
190 sqlite3_finalize(ifile);
194 //fwrite(xzdata, blobsize, 1, stdout);
196 fprintf(stderr, "uncompressing %d bytes at %p, expect %lld\n", blobsize, xzdata, (long long int)size);
197 uncompresslzma(xzdata, blobsize, out);
200 sqlite3_finalize(ifile);
204 void *compresslzma(void *buf, size_t bufsize, size_t *len) {
210 outsize = lzma_stream_buffer_bound(bufsize);
211 outbuf = malloc(outsize);
216 /* TODO adjust encoding level for size */
217 lzma_easy_buffer_encode(6, LZMA_CHECK_CRC64, NULL,
219 outbuf, &outlen, outsize
225 static int callback(void *NotUsed, int argc, char **argv, char **azColName){
227 for(i=0; i<argc; i++){
228 printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
234 static char *create_table = "create table if not exists files (hash text primary key, size integer, compression text, content blob)";
242 #define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x))
243 static int begin(sqlite3 *db) {
247 rc = sqlite3_exec(db, "begin;", callback, 0, &err);
248 if (rc != SQLITE_OK) {
255 static int commit(sqlite3 *db) {
259 rc = sqlite3_exec(db, "commit;", callback, 0, &err);
260 if (rc != SQLITE_OK) {
266 static int rollback(sqlite3 *db) {
270 rc = sqlite3_exec(db, "rollback;", callback, 0, &err);
271 if (rc != SQLITE_OK) {
278 int main(int ac, char **av){
283 rc = sqlite3_open(av[1], &db);
285 SQLERROR(sqlite3_errmsg(db));
290 rc = sqlite3_exec(db, create_table, callback, 0, &errmsg);
291 if (rc != SQLITE_OK) {
293 sqlite3_free(errmsg);
300 rc = sqlite3_prepare(db, "insert or ignore into files (hash,size,compression,content) values (?,?,?,?)", -1, &ifile,0);
301 if (rc != SQLITE_OK) {
302 SQLERROR(sqlite3_errmsg(db));
307 /* insert each file */
308 for (i = 2; i < ac; i++) {
312 unsigned char tmp[32];
316 fd = open(av[i], O_RDONLY);
322 if (fstat(fd, &sbuf) == -1) {
327 /* not a regular file? */
328 if (!S_ISREG(sbuf.st_mode)) {
334 content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
342 sha256_process(&md, content, sbuf.st_size);
343 sha256_done(&md, tmp);
345 sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
348 //fprintf(stderr, "file %s: %s\n", av[i], hash);
353 xzcompressed = compresslzma(content, sbuf.st_size, &compresslen);
355 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
356 sqlite3_bind_int64(ifile, 2, sbuf.st_size);
357 sqlite3_bind_text(ifile, 3, "xz", 2, SQLITE_STATIC);
358 sqlite3_bind_blob64(ifile, 4, xzcompressed, compresslen, SQLITE_STATIC);
360 rc = sqlite3_step(ifile);
362 /* either way we're done with this now */
363 munmap(content, sbuf.st_size);
365 if (rc != SQLITE_DONE) {
366 SQLERROR(sqlite3_errmsg(db));
367 sqlite3_finalize(ifile);
372 sqlite3_reset(ifile);
374 printf("%s\n", hash);
376 sqlite3_finalize(ifile);