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) {
340 rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0);
341 if (rc != SQLITE_OK) {
342 SQLERROR(sqlite3_errmsg(db));
348 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
350 rc = sqlite3_step(ifile);
352 if (rc == SQLITE_DONE) {
353 /* didn't find a row */
354 sqlite3_finalize(ifile);
356 fprintf(stderr, "no such hash: %s\n", hash);
359 /* either way we're done with this now */
361 if (rc != SQLITE_ROW) {
362 SQLERROR(sqlite3_errmsg(db));
363 sqlite3_finalize(ifile);
368 type = sqlite3_column_type(ifile, 0);
369 if (type == SQLITE_NULL) {
370 fprintf(stderr, "no file size\n");
371 sqlite3_finalize(ifile);
375 type = sqlite3_column_type(ifile, 1);
376 if (type == SQLITE_NULL) {
377 fprintf(stderr, "no file data\n");
378 sqlite3_finalize(ifile);
382 //size = sqlite3_column_int64(ifile, 0);
383 xzdata = (void *)sqlite3_column_blob(ifile, 1);
384 blobsize = sqlite3_column_bytes(ifile, 1);
386 if (strcmp(path, "-")) {
388 tmpfile = malloc(len+8+1);
390 fprintf(stderr, "malloc error\n");
393 sprintf(tmpfile, "%sXXXXXX", path);
395 out = open(tmpfile, O_CREAT|O_WRONLY|O_TRUNC, 0600);
397 fprintf(stderr, "can't open output file %s: %s\n",
398 tmpfile, strerror(errno));
399 sqlite3_finalize(ifile);
409 fprintf(stderr, "uncompressing %d bytes at %p, expect %lld\n", blobsize, xzdata, (long long int)size);
411 uncompresslzma(xzdata, blobsize, out);
413 sqlite3_finalize(ifile);
417 if (chmod(tmpfile, mode) == -1) {
418 fprintf(stderr, "can't chmod %s: %s\n", tmpfile,
421 } else if (rename(tmpfile, path) == -1) {
422 fprintf(stderr, "extract rename failed: %s\n",
428 if (rc == 0 && tmpfile) {
429 if (unlink(tmpfile) == -1) {
430 fprintf(stderr, "unlink tmpfile %s fail: %s\n",
440 static int run_for_hash(sqlite3 *db, char *sql, char *hash) {
444 rc = sqlite3_prepare_v2(db, sql, -1, &ifile, 0);
445 if (rc != SQLITE_OK) {
446 SQLERROR(sqlite3_errmsg(db));
452 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
454 rc = sqlite3_step(ifile);
455 } while (rc == SQLITE_ROW);
457 sqlite3_finalize(ifile);
459 return rc == SQLITE_DONE;
462 #define SQLERP(db, msg) fprintf(stderr, "%s: %s\n", msg, sqlite3_errmsg(db))
464 static int set_elf_info(struct zpm *zpm, char *hash, char *content,
473 sqlite3 *db = zpm->db;
475 if (length < sizeof (Elf64_Ehdr) || !libelf_iself(content)) {
476 /* not an elf file */
480 /* clear existing for this hash */
482 if (!run_for_hash(db, "delete from elflibraries where file = ?", hash)) {
483 SQLERP(db, "error clearing elf library");
487 if (!run_for_hash(db, "delete from elfneeded where file = ?", hash)) {
488 SQLERP(db, "error clearing elf needed");
492 hdr = libelf_header(content);
493 /* if lib, set soname */
494 if (libelf_type(content) == ET_DYN) {
495 char *soname = libelf_soname(content);
497 zpm_db_run(zpm, "insert into elflibraries (file,soname) values (%Q,%Q);", hash, soname);
502 fprintf(stderr, "can't find soname\n");
506 /* if exe, set neededs */
507 /* libraries can have neededs too */
508 if (libelf_type(content) == ET_EXEC || libelf_type(content) == ET_DYN) {
509 Elf64_Shdr *dsect = 0;
512 elf = (char *)content;
513 /* find program header table */
514 for (i = 0; i < hdr->e_phnum; i++) {
515 phdr = (Elf64_Phdr *)(elf + hdr->e_phoff + i * hdr->e_phentsize);
516 if (phdr->p_type == PT_DYNAMIC) {
517 dsect = (Elf64_Shdr *)(elf + phdr->p_offset);
521 /* no dynamic section found */
525 dyn = (Elf64_Dyn *)dsect;
527 dsect = libelf_section(elf, SHT_DYNAMIC);
530 strsect = libelf_section_n(elf, dsect->sh_link);
531 strtab = elf + strsect->sh_offset;
533 sqlite3_prepare_v2(db, "insert into elfneeded (file,needed) values (?,?)",-1, &ifile, 0);
534 sqlite3_bind_text(ifile,1,hash,64,SQLITE_STATIC);
535 while (dyn->d_tag != DT_NULL) {
536 if (dyn->d_tag == DT_NEEDED) {
540 need = strtab + dyn->d_un.d_val;
541 if (strlen(need) == 0) continue;
542 sqlite3_bind_text(ifile,2,need,strlen(need),SQLITE_STATIC);
544 fprintf(stderr, "%s needs %s\n", hash, need);
546 rc = sqlite3_step(ifile);
547 if (rc != SQLITE_DONE) {
548 SQLERP(db, "error setting needed library");
549 sqlite3_finalize(ifile);
552 sqlite3_reset(ifile);
556 sqlite3_finalize(ifile);
561 int zpm_import(struct zpm *zpm, char *path, uint32_t flags, char *hash) {
565 unsigned char tmp[32];
566 struct sha256_state md;
567 sqlite3_stmt *ifile = 0;
568 int haverow = 0,havedata = 0;
576 if (!zpm || !zpm->db || !path) {
580 /* use local if caller didn't pass in room */
586 fprintf(stderr, "zpm_import unused flags = %d\n", flags);
589 fd = open(path, O_RDONLY);
592 fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno));
595 if (fstat(fd, &sbuf) == -1) {
597 fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno));
600 /* not a regular file? */
601 if (!S_ISREG(sbuf.st_mode)) {
603 switch (sbuf.st_mode & S_IFMT) {
604 case S_IFSOCK: ftype = "socket"; break;
605 case S_IFLNK : ftype = "symlink"; break;
606 case S_IFBLK : ftype = "block device"; break;
607 case S_IFDIR : ftype = "directory"; break;
608 case S_IFCHR : ftype = "character device"; break;
609 case S_IFIFO : ftype = "fifo"; break;
610 default: ftype = "unknown file type"; break;
612 /* TODO this is ok, just stored differently */
613 fprintf(stderr, "%s can't import %s file: %s\n", __FUNCTION__, ftype, path);
618 content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
622 fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno));
628 sha256_process(&md, content, sbuf.st_size);
629 sha256_done(&md, tmp);
631 sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
635 /* TODO check null */
636 sqlite3 *db = zpm->db;
638 /* prepare and bind */
640 rc = sqlite3_prepare_v2(db, "select size, content is not null from files where hash = ?", -1, &ifile,0);
641 if (rc != SQLITE_OK) {
642 SQLERROR(sqlite3_errmsg(db));
643 munmap(content, sbuf.st_size);
649 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
651 rc = sqlite3_step(ifile);
653 if (rc != SQLITE_DONE) {
654 if (rc != SQLITE_ROW) {
655 /* didn't find a row */
656 SQLERROR(sqlite3_errmsg(db));
657 munmap(content, sbuf.st_size);
661 type = sqlite3_column_type(ifile, 0);
662 if (type == SQLITE_NULL) {
663 /* TODO assert, this shouldn't be possible? */
664 fprintf(stderr, "no file size\n");
665 sqlite3_finalize(ifile);
666 munmap(content, sbuf.st_size);
669 type = sqlite3_column_type(ifile, 1);
670 if (type == SQLITE_NULL) {
671 /* TODO assert, this shouldn't be possible? */
672 fprintf(stderr, "no file data\n");
673 sqlite3_finalize(ifile);
674 munmap(content, sbuf.st_size);
676 /* which is fine, just need to update the row then */
678 havedata = sqlite3_column_int(ifile, 1);
681 sqlite3_finalize(ifile);
685 // fprintf(stderr, "compressing\n");
686 outbuf = compresslzma(content, sbuf.st_size, &outlen);
688 fprintf(stderr, "compresslzma failed\n");
689 munmap(content, sbuf.st_size);
692 //// fprintf(stderr, "compress finished\n");
696 rc = sqlite3_prepare_v2(db, "update files set size = ?, content = ? where hash = ?", -1, &ifile,0);
698 rc = sqlite3_prepare_v2(db, "insert into files (size, content, hash) values (?,?,?)", -1, &ifile,0);
701 if (rc != SQLITE_OK) {
702 SQLERROR(sqlite3_errmsg(db));
703 fprintf(stderr, "cant prepare data\n");
704 munmap(content, sbuf.st_size);
708 rc = sqlite3_bind_int64(ifile, 1, (sqlite3_int64)sbuf.st_size);
709 if (rc != SQLITE_OK) {
710 SQLERROR(sqlite3_errmsg(db));
711 sqlite3_finalize(ifile);
712 fprintf(stderr, "cant bind size\n");
713 munmap(content, sbuf.st_size);
717 rc = sqlite3_bind_blob64(ifile, 2, outbuf,
718 (sqlite3_int64)outlen, SQLITE_STATIC);
719 if (rc != SQLITE_OK) {
720 SQLERROR(sqlite3_errmsg(db));
721 sqlite3_finalize(ifile);
722 fprintf(stderr, "cant bind content\n");
723 munmap(content, sbuf.st_size);
727 rc = sqlite3_bind_text(ifile, 3, hash, 64, SQLITE_STATIC);
728 if (rc != SQLITE_OK) {
729 SQLERROR(sqlite3_errmsg(db));
730 fprintf(stderr, "cant bind hash\n");
731 sqlite3_finalize(ifile);
732 munmap(content, sbuf.st_size);
736 rc = sqlite3_step(ifile);
737 if (rc != SQLITE_DONE) {
738 SQLERROR(sqlite3_errmsg(db));
739 sqlite3_finalize(ifile);
740 munmap(content, sbuf.st_size);
743 sqlite3_finalize(ifile);
745 /* don't need the original file now */
748 if (!set_elf_info(zpm, hash, content, sbuf.st_size)) {
749 fprintf(stderr, "setting elf info failed\n");
750 munmap(content, sbuf.st_size);
754 munmap(content, sbuf.st_size);