1 #define _POSIX_C_SOURCE 200809L
18 int zpm_begin(struct zpm *z) {
20 sqlite3_exec(z->db, "begin;", NULL, NULL, &errstr);
22 fprintf(stderr, "sqlite begin error: %s\n", errstr);
29 int zpm_commit(struct zpm *z) {
31 sqlite3_exec(z->db, "commit;", NULL, NULL, &errstr);
33 fprintf(stderr, "sqlite commit error: %s\n", errstr);
40 /* wrapper for sqlite3_exec */
41 int zpm_exec(struct zpm *z, const char *sql, int(*callback)(void *, int, char **, char**), void *arg, char **errmsg) {
42 return sqlite3_exec(z->db, sql, callback, arg, errmsg);
45 int zpm_rollback(struct zpm *z) {
47 sqlite3_exec(z->db, "rollback;", NULL, NULL, &errstr);
49 fprintf(stderr, "sqlite rollback error: %s\n", errstr);
56 int zpm_db_set_pragma(struct zpm *db, int pragma, int value) {
62 case 1: sql = "pragma application_id = ?;"; break;
63 case 2: sql = "pragma user_version = ?;"; break;
64 default: return -1; break;
67 rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0);
69 if (rc != SQLITE_OK) {
70 SQLERROR(sqlite3_errmsg(db->db));
74 sqlite3_bind_int(s, 1, value);
75 if (rc != SQLITE_OK) {
76 SQLERROR(sqlite3_errmsg(db->db));
77 fprintf(stderr, "cant bind pragma value\n");
82 if (rc != SQLITE_DONE) {
83 SQLERROR(sqlite3_errmsg(db->db));
84 fprintf(stderr, "cant set pragma\n");
93 int zpm_db_pragma(struct zpm *db, int pragma) {
100 case 1: sql = "pragma application_id;"; break;
101 case 2: sql = "pragma user_version;"; break;
102 default: return -1; break;
105 rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0);
107 if (rc != SQLITE_OK) {
108 SQLERROR(sqlite3_errmsg(db->db));
109 fprintf(stderr, "%s, errnum = %d\n", sqlite3_errmsg(db->db), rc);
110 /* TODO just abort? */
114 rc = sqlite3_step(s);
115 if (rc == SQLITE_ROW) {
116 value = sqlite3_column_int(s, 0);
126 int zpm_db_initialize(struct zpm *pkg) {
128 switch (sqlite3_exec(pkg->db, createdb, (int (*)(void *,int,char **,char **))0, NULL, &error)) {
129 case SQLITE_OK: break;
131 SQLERROR(sqlite3_errmsg(pkg->db));
132 fprintf(stderr, "error: %s\n", error);
142 /* assumes pkg->db is set */
143 static int setupdb(struct zpm *zpm) {
149 appid = zpm_db_pragma(zpm, 1);
150 dbver = zpm_db_pragma(zpm, 2);
152 if (appid != 0x5a504442) {
153 fprintf(stderr, "unknown database type\n");
159 fprintf(stderr, "version %d zpm db detected, this program only works with version 1 databases\n", dbver);
164 sqlite3_exec(zpm->db, "pragma foreign_keys = ON;", NULL, NULL, &errstr);
168 zpm->errmsg = strdup(errstr);
169 fprintf(stderr, "sqlite foreign key error: %s\n", errstr);
170 sqlite3_free(errstr);
175 /* TODO add vercmp */
180 struct zpm *zpm_clearmem(struct zpm *zpm) {
182 zpm = malloc(sizeof *zpm);
186 *zpm = (struct zpm){0};
192 static void zpm_set_db_errmsg(struct zpm *zpm, const char *msg) {
198 zpm->dberrmsg = strdup(msg);
199 if (!zpm->dberrmsg) {
208 int zpm_init(struct zpm *pkg, char *path) {
219 rc = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
223 zpm_set_db_errmsg(pkg, sqlite3_errstr(rc));
227 fprintf(stderr, "error (%d): %s: %s\n", rc,
228 pkg->dberrmsg ? pkg->dberrmsg : "null", path);
233 pkg->path = strdup(path);
235 appid = zpm_db_pragma(pkg, 1);
238 case 0: if (!zpm_db_initialize(pkg)) {
244 /* already initialized */
247 fprintf(stderr, "unknown database type\n");
263 int zpm_open(struct zpm *zpm, char *path) {
270 path = getenv("ZPMDB");
274 path = "/var/lib/zpm/local.db";
277 rc = sqlite3_open_v2(path, &db, SQLITE_OPEN_READWRITE, NULL);
279 SQLERROR(sqlite3_errmsg(db));
282 fprintf(stderr, "path = %s\n", path);
286 zpm->path = strdup(path);
299 int zpm_close(struct zpm *pkg) {
301 sqlite3_close(pkg->db);
304 /* TODO free any malloced names and such */
308 static int zpm_sqlite_vercmp(void *not_used, int lena, const void *a,
309 int lenb, const void *b) {
310 /* not sure what the ints are, possibly string lengths */
311 if (not_used != 0) fprintf(stderr, "sqlite vercmp not_used = %p\n",
313 if (lena == 0 && lenb > 0) return 1;
314 return zpm_vercmp(a, b);
317 int zpm_addvercmp(struct zpm *pkg) {
318 return sqlite3_create_collation(
319 pkg->db, "vercmp", SQLITE_UTF8, NULL,
324 int zpm_extract(struct zpm *pkg, char *hash, char *path, mode_t mode) {
335 if (!pkg || !pkg->db) {
344 rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0);
345 if (rc != SQLITE_OK) {
346 SQLERROR(sqlite3_errmsg(db));
352 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
354 rc = sqlite3_step(ifile);
356 if (rc == SQLITE_DONE) {
357 /* didn't find a row */
358 sqlite3_finalize(ifile);
360 fprintf(stderr, "no such hash: %s\n", hash);
363 /* either way we're done with this now */
365 if (rc != SQLITE_ROW) {
366 SQLERROR(sqlite3_errmsg(db));
367 sqlite3_finalize(ifile);
372 type = sqlite3_column_type(ifile, 0);
373 if (type == SQLITE_NULL) {
374 fprintf(stderr, "no file size\n");
375 sqlite3_finalize(ifile);
379 type = sqlite3_column_type(ifile, 1);
380 if (type == SQLITE_NULL) {
381 fprintf(stderr, "no file data\n");
382 sqlite3_finalize(ifile);
386 //size = sqlite3_column_int64(ifile, 0);
387 xzdata = (void *)sqlite3_column_blob(ifile, 1);
388 blobsize = sqlite3_column_bytes(ifile, 1);
390 if (strcmp(path, "-")) {
392 tmpfile = malloc(len+8+1);
394 fprintf(stderr, "malloc error\n");
397 sprintf(tmpfile, "%sXXXXXX", path);
399 out = open(tmpfile, O_CREAT|O_WRONLY|O_TRUNC, 0600);
401 fprintf(stderr, "can't open output file %s: %s\n",
402 tmpfile, strerror(errno));
403 sqlite3_finalize(ifile);
413 fprintf(stderr, "uncompressing %d bytes at %p, expect %lld\n", blobsize, xzdata, (long long int)size);
415 uncompresslzma(xzdata, blobsize, out);
417 sqlite3_finalize(ifile);
421 if (chmod(tmpfile, mode) == -1) {
422 fprintf(stderr, "can't chmod %s: %s\n", tmpfile,
425 } else if (rename(tmpfile, path) == -1) {
426 fprintf(stderr, "extract rename failed: %s\n",
432 if (rc == 0 && tmpfile) {
433 if (unlink(tmpfile) == -1) {
434 fprintf(stderr, "unlink tmpfile %s fail: %s\n",
444 static int run_for_hash(sqlite3 *db, char *sql, char *hash) {
448 rc = sqlite3_prepare_v2(db, sql, -1, &ifile, 0);
449 if (rc != SQLITE_OK) {
450 SQLERROR(sqlite3_errmsg(db));
456 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
458 rc = sqlite3_step(ifile);
459 } while (rc == SQLITE_ROW);
461 sqlite3_finalize(ifile);
463 return rc == SQLITE_DONE;
466 #define SQLERP(db, msg) fprintf(stderr, "%s: %s\n", msg, sqlite3_errmsg(db))
468 static int set_elf_info(struct zpm *zpm, char *hash, char *content,
477 sqlite3 *db = zpm->db;
479 if (length < sizeof (Elf64_Ehdr) || !libelf_iself(content)) {
480 /* not an elf file */
484 /* clear existing for this hash */
486 if (!run_for_hash(db, "delete from elflibraries where file = ?", hash)) {
487 SQLERP(db, "error clearing elf library");
491 if (!run_for_hash(db, "delete from elfneeded where file = ?", hash)) {
492 SQLERP(db, "error clearing elf needed");
496 hdr = libelf_header(content);
497 /* if lib, set soname */
498 if (libelf_type(content) == ET_DYN) {
499 char *soname = libelf_soname(content);
501 zpm_db_run(zpm, "insert into elflibraries (file,soname) values (%Q,%Q);", hash, soname);
506 fprintf(stderr, "can't find soname\n");
510 /* if exe, set neededs */
511 /* libraries can have neededs too */
512 if (libelf_type(content) == ET_EXEC || libelf_type(content) == ET_DYN) {
513 Elf64_Shdr *dsect = 0;
516 elf = (char *)content;
517 /* find program header table */
518 for (i = 0; i < hdr->e_phnum; i++) {
519 phdr = (Elf64_Phdr *)(elf + hdr->e_phoff + i * hdr->e_phentsize);
520 if (phdr->p_type == PT_DYNAMIC) {
521 dsect = (Elf64_Shdr *)(elf + phdr->p_offset);
525 /* no dynamic section found */
529 dyn = (Elf64_Dyn *)dsect;
531 dsect = libelf_section(elf, SHT_DYNAMIC);
534 strsect = libelf_section_n(elf, dsect->sh_link);
535 strtab = elf + strsect->sh_offset;
537 sqlite3_prepare_v2(db, "insert into elfneeded (file,needed) values (?,?)",-1, &ifile, 0);
538 sqlite3_bind_text(ifile,1,hash,64,SQLITE_STATIC);
539 while (dyn->d_tag != DT_NULL) {
540 if (dyn->d_tag == DT_NEEDED) {
544 need = strtab + dyn->d_un.d_val;
545 if (strlen(need) == 0) continue;
546 sqlite3_bind_text(ifile,2,need,strlen(need),SQLITE_STATIC);
548 fprintf(stderr, "%s needs %s\n", hash, need);
550 rc = sqlite3_step(ifile);
551 if (rc != SQLITE_DONE) {
552 SQLERP(db, "error setting needed library");
553 sqlite3_finalize(ifile);
556 sqlite3_reset(ifile);
560 sqlite3_finalize(ifile);
565 int zpm_import(struct zpm *zpm, char *path, uint32_t flags, char *hash) {
569 unsigned char tmp[32];
570 struct sha256_state md;
571 sqlite3_stmt *ifile = 0;
572 int haverow = 0,havedata = 0;
580 if (!zpm || !zpm->db || !path) {
584 /* use local if caller didn't pass in room */
590 fprintf(stderr, "zpm_import unused flags = %d\n", flags);
593 fd = open(path, O_RDONLY);
596 fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno));
599 if (fstat(fd, &sbuf) == -1) {
601 fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno));
604 /* not a regular file? */
605 if (!S_ISREG(sbuf.st_mode)) {
607 switch (sbuf.st_mode & S_IFMT) {
608 case S_IFSOCK: ftype = "socket"; break;
609 case S_IFLNK : ftype = "symlink"; break;
610 case S_IFBLK : ftype = "block device"; break;
611 case S_IFDIR : ftype = "directory"; break;
612 case S_IFCHR : ftype = "character device"; break;
613 case S_IFIFO : ftype = "fifo"; break;
614 default: ftype = "unknown file type"; break;
616 /* TODO this is ok, just stored differently */
617 fprintf(stderr, "%s can't import %s file: %s\n", __FUNCTION__, ftype, path);
622 content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
626 fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno));
632 sha256_process(&md, content, sbuf.st_size);
633 sha256_done(&md, tmp);
635 sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
639 /* TODO check null */
640 sqlite3 *db = zpm->db;
642 /* prepare and bind */
644 rc = sqlite3_prepare_v2(db, "select size, content is not null from files where hash = ?", -1, &ifile,0);
645 if (rc != SQLITE_OK) {
646 SQLERROR(sqlite3_errmsg(db));
647 munmap(content, sbuf.st_size);
653 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
655 rc = sqlite3_step(ifile);
657 if (rc != SQLITE_DONE) {
658 if (rc != SQLITE_ROW) {
659 /* didn't find a row */
660 SQLERROR(sqlite3_errmsg(db));
661 munmap(content, sbuf.st_size);
665 type = sqlite3_column_type(ifile, 0);
666 if (type == SQLITE_NULL) {
667 /* TODO assert, this shouldn't be possible? */
668 fprintf(stderr, "no file size\n");
669 sqlite3_finalize(ifile);
670 munmap(content, sbuf.st_size);
673 type = sqlite3_column_type(ifile, 1);
674 if (type == SQLITE_NULL) {
675 /* TODO assert, this shouldn't be possible? */
676 fprintf(stderr, "no file data\n");
677 sqlite3_finalize(ifile);
678 munmap(content, sbuf.st_size);
680 /* which is fine, just need to update the row then */
682 havedata = sqlite3_column_int(ifile, 1);
685 sqlite3_finalize(ifile);
689 // fprintf(stderr, "compressing\n");
690 outbuf = compresslzma(content, sbuf.st_size, &outlen);
692 fprintf(stderr, "compresslzma failed\n");
693 munmap(content, sbuf.st_size);
696 //// fprintf(stderr, "compress finished\n");
700 rc = sqlite3_prepare_v2(db, "update files set size = ?, content = ? where hash = ?", -1, &ifile,0);
702 rc = sqlite3_prepare_v2(db, "insert into files (size, content, hash) values (?,?,?)", -1, &ifile,0);
705 if (rc != SQLITE_OK) {
706 SQLERROR(sqlite3_errmsg(db));
707 fprintf(stderr, "cant prepare data\n");
708 munmap(content, sbuf.st_size);
712 rc = sqlite3_bind_int64(ifile, 1, (sqlite3_int64)sbuf.st_size);
713 if (rc != SQLITE_OK) {
714 SQLERROR(sqlite3_errmsg(db));
715 sqlite3_finalize(ifile);
716 fprintf(stderr, "cant bind size\n");
717 munmap(content, sbuf.st_size);
721 rc = sqlite3_bind_blob64(ifile, 2, outbuf,
722 (sqlite3_int64)outlen, SQLITE_STATIC);
723 if (rc != SQLITE_OK) {
724 SQLERROR(sqlite3_errmsg(db));
725 sqlite3_finalize(ifile);
726 fprintf(stderr, "cant bind content\n");
727 munmap(content, sbuf.st_size);
731 rc = sqlite3_bind_text(ifile, 3, hash, 64, SQLITE_STATIC);
732 if (rc != SQLITE_OK) {
733 SQLERROR(sqlite3_errmsg(db));
734 fprintf(stderr, "cant bind hash\n");
735 sqlite3_finalize(ifile);
736 munmap(content, sbuf.st_size);
740 rc = sqlite3_step(ifile);
741 if (rc != SQLITE_DONE) {
742 SQLERROR(sqlite3_errmsg(db));
743 sqlite3_finalize(ifile);
744 munmap(content, sbuf.st_size);
747 sqlite3_finalize(ifile);
749 /* don't need the original file now */
752 if (!set_elf_info(zpm, hash, content, sbuf.st_size)) {
753 fprintf(stderr, "setting elf info failed\n");
754 munmap(content, sbuf.st_size);
758 munmap(content, sbuf.st_size);