18 char *path; /* path to package file */
22 time_t installed; /* install time, 0 for not installed */
32 char *hash; /* could be fixed length */
34 struct zpm_file *next; /* so you can make a linked list */
38 /* associate with a package ? if only one? first? */
39 int zpm_open(struct zpm *pkg, char *path);
40 int zpm_pkgname(char *base, char *version, int release); /* construct a package file name */
42 /* flags for preserving mode, owner, etc */
43 /* puts hash of import in hash */
44 /* path can be a hash, with an "INTERNAL" flag, i.e. internally import */
48 #define ZPM_INTERNAL 0x8
49 #define ZPM_NOBLOB 0x10
50 /* don't run scripts on install */
51 #define ZPM_NOSCRIPTS 0x10
52 /* don't associate the file with a package, just do a raw insert */
53 /* otherwise, associate it with the current package */
54 #define ZPM_NOPACKAGE 0x20
56 int zpm_import(struct zpm *zp, char *path, uint32_t flags, uint8_t *hash);
58 /* link and unlink hashes to packages */
59 int zpm_link(struct zpm *pkg, char *path, char *hash, struct zpm_file *fileinfo);
60 int zpm_unlink(struct zpm *pkg, char *path);
62 /* tag a file. relative to "current package" */
63 int zpm_tag(struct zpm *zp, char *path, char *tags);
64 /* should this be broken up into separage functions ? */
65 int zpm_md(struct zpm *zp, char *path, int mode, char *owner, char *group, time_t mtime);
67 /* export hash to dest */
68 int zpm_extract(struct zpm *pkg, char *hash, char *path, int mode);
70 /* export path to dest */
71 int zpm_export(struct zpm *zp, char *path, uint32_t flags, char *dest);
73 int zpm_close(struct zpm *zp);
75 /* attach a signature to a package */
76 int zpm_sign(struct zpm *z, size_t s, void *signature);
78 /* set the package info to the nth package, -1 to return count? */
79 /* further import/exports and such will be relative to this package */
80 int zpm_package(struct zpm *zp, int n);
82 /* get file information */
83 int zpm_stat(struct zpm *z, struct zpm_file *f, int n);
85 /* will also set the package context to the new package */
86 int zpm_newpkg(struct zpm *z, char *base, char *version, int release);
89 int zpm_begin(struct zpm *z);
90 int zpm_commit(struct zpm *z);
91 int zpm_rollback(struct zpm *z);
93 /* higher level operations */
95 /* install or uninstall the package */
96 /* flag for keeping the blobs in local */
97 /* what about tag filtering */
98 int zpm_install(struct zpm *z, struct zpm *local, uint32_t flags);
99 int zpm_uninstall(struct zpm *local);
101 /* slurp up the actual blobs */
102 /* what about versioning them if they change */
103 int zpm_preserve(struct zpm *local);
105 /* check file integrity */
106 int zpm_checkinstall(struct zpm *local);
108 int zpm_merge(struct zpm *z, struct zpm *src, uint32_t flags);
110 void uncompresslzma(void *buf, size_t bufsize, FILE *out);
111 #define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x))
114 static char *dupstr(char *s) {
127 int zpm_newpkg(struct zpm *z, char *base, char *version, int release) {
128 char *sql = "insert or ignore into packages (package,version,release) values (?,?,?)";
132 rc = sqlite3_prepare(db, sql, -1, &ifile,0);
133 if (rc != SQLITE_OK) {
134 SQLERROR(sqlite3_errmsg(db));
137 rc = sqlite3_bind_text(ifile, 1, base, strlen(base), SQLITE_STATIC);
138 if (rc != SQLITE_OK) {
139 SQLERROR(sqlite3_errmsg(db));
140 fprintf(stderr, "cant bind package name\n");
144 sqlite3_bind_text(ifile, 2, version, strlen(version), SQLITE_STATIC);
145 sqlite3_bind_int(ifile, 3, release)
147 rc = sqlite3_step(ifile);
149 if (rc != SQLITE_DONE) {
150 SQLERROR(sqlite3_errmsg(db));
151 sqlite3_finalize(ifile);
154 sqlite3_finalize(ifile);
155 z->pkg = dupstr(base);
156 z->version = dupstr(version);
157 z->release = release;
161 int zpm_begin(struct zpm *z) {
163 sqlite3_exec(z->db, "begin;", NULL, NULL, &errstr);
165 fprintf(stderr, "sqlite begin error: %s\n", errstr);
166 sqlite3_free(errstr);
172 int zpm_commit(struct zpm *z) {
174 sqlite3_exec(z->db, "commit;", NULL, NULL, &errstr);
176 fprintf(stderr, "sqlite commit error: %s\n", errstr);
177 sqlite3_free(errstr);
183 int zpm_rollback(struct zpm *z) {
185 sqlite3_exec(z->db, "rollback;", NULL, NULL, &errstr);
187 fprintf(stderr, "sqlite rollback error: %s\n", errstr);
188 sqlite3_free(errstr);
194 int zpm_db_set_pragma(struct zpm *db, int pragma, int value) {
200 case 1: sql = "pragma application_id = ?;"; break;
201 case 2: sql = "pragma user_version = ?;"; break;
202 default: return -1; break;
205 rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0);
207 if (rc != SQLITE_OK) {
208 SQLERROR(sqlite3_errmsg(db->db));
212 sqlite3_bind_int(s, 1, value);
213 if (rc != SQLITE_OK) {
214 SQLERROR(sqlite3_errmsg(db->db));
215 fprintf(stderr, "cant bind pragma value\n");
219 rc = sqlite3_step(s);
220 if (rc != SQLITE_DONE) {
221 SQLERROR(sqlite3_errmsg(db->db));
222 fprintf(stderr, "cant set pragma\n");
231 int zpm_db_pragma(struct zpm *db, int pragma) {
238 case 1: sql = "pragma application_id;"; break;
239 case 2: sql = "pragma user_version;"; break;
240 default: return -1; break;
243 rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0);
245 if (rc != SQLITE_OK) {
246 SQLERROR(sqlite3_errmsg(db->db));
247 fprintf(stderr, "%s, errnum = %d\n", sqlite3_errmsg(db->db), rc);
248 /* TODO just abort? */
252 rc = sqlite3_step(s);
253 if (rc == SQLITE_ROW) {
254 value = sqlite3_column_int(s, 0);
264 int zpm_db_initialize(struct zpm *pkg) {
265 //fprintf(stderr, "initializing zpm database\n");
266 switch (sqlite3_exec(pkg->db, createdb, (int (*)(void *,int,char **,char **))0, NULL, NULL)) {
267 case SQLITE_OK: break;
269 SQLERROR(sqlite3_errmsg(pkg->db));
277 int zpm_open(struct zpm *pkg, char *path) {
290 rc = sqlite3_open(path, &db);
292 SQLERROR(sqlite3_errmsg(db));
297 pkg->path = dupstr(path);
299 appid = zpm_db_pragma(pkg, 1);
300 dbver = zpm_db_pragma(pkg, 2);
302 //fprintf(stderr, "db appid = %x, dbver = %d\n", appid, dbver);
304 case 0: if (!zpm_db_initialize(pkg)) {
309 case 0x5a504442: break;
311 fprintf(stderr, "unknown database type\n");
317 fprintf(stderr, "version %d zpm db detected, this program only works with version 1 databases\n", dbver);
322 sqlite3_exec(pkg->db, "pragma foreign_keys = ON;", NULL, NULL, &errstr);
324 fprintf(stderr, "sqlite foreign key error: %s\n", errstr);
325 sqlite3_free(errstr);
331 /* TODO if this is a new database, create structures */
333 /* get a package. what if more than one? what if none? */
337 int zpm_close(struct zpm *pkg) {
339 sqlite3_close(pkg->db);
342 /* TODO free any malloced names and such */
346 /* set package struct variables, database, environment, then command line */
347 int zpm_readopts(struct zpm *pkg, int ac, char **av) {
354 ev = getenv("ZPMPACKAGE");
356 pkg->pkgname = dupstr(ev);
358 ev = getenv("ZPMPKGREL");
360 pkg->release = strtol(ev, 0, 0);
362 ev = getenv("ZPMPKGVER");
364 pkg->version = dupstr(ev);
367 /* now, parse the options, return optind so the caller can adjust if needed */
372 int zpm_extract(struct zpm *pkg, char *hash, char *path, int mode) {
382 /* TODO check null */
383 sqlite3 *db = pkg->db;
385 rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0);
386 if (rc != SQLITE_OK) {
387 SQLERROR(sqlite3_errmsg(db));
393 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
395 rc = sqlite3_step(ifile);
397 if (rc == SQLITE_DONE) {
398 /* didn't find a row */
399 sqlite3_finalize(ifile);
401 fprintf(stderr, "no such hash\n");
404 /* either way we're done with this now */
406 if (rc != SQLITE_ROW) {
407 SQLERROR(sqlite3_errmsg(db));
408 sqlite3_finalize(ifile);
413 type = sqlite3_column_type(ifile, 0);
414 if (type == SQLITE_NULL) {
415 fprintf(stderr, "no file size\n");
416 sqlite3_finalize(ifile);
420 type = sqlite3_column_type(ifile, 1);
421 if (type == SQLITE_NULL) {
422 fprintf(stderr, "no file data\n");
423 sqlite3_finalize(ifile);
427 //size = sqlite3_column_int64(ifile, 0);
428 xzdata = (void *)sqlite3_column_blob(ifile, 1);
429 blobsize = sqlite3_column_bytes(ifile, 1);
431 out = fopen(path, "w");
433 fprintf(stderr, "can't open output file %s\n", path);
434 sqlite3_finalize(ifile);
438 //fwrite(xzdata, blobsize, 1, stdout);
440 //fprintf(stderr, "uncompressing %d bytes at %p, expect %lld\n", blobsize, xzdata, (long long int)size);
441 uncompresslzma(xzdata, blobsize, out);
444 sqlite3_finalize(ifile);
450 /* flags 0, close mmap, flags 1, return mmap fd */
451 int zpm_hash(char *path, char *hash, uint32_t flags) {
457 unsigned char tmp[32];
460 fd = open(path, O_RDONLY);
462 fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno));
465 if (fstat(fd, &sbuf) == -1) {
466 fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno));
469 /* not a regular file? */
470 if (!S_ISREG(sbuf.st_mode)) {
471 /* TODO this is ok, just stored differently */
472 fprintf(stderr, "%s non-regular files unsupported %s\n", __FUNCTION__, path);
476 content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
479 fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno));
485 sha256_process(&md, content, sbuf.st_size);
486 sha256_done(&md, tmp);
488 sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
491 munmap(content, sbuf.st_size);
496 int zpm_import(struct zpm *pkg, char *path, uint32_t flags, char *hash) {
500 unsigned char tmp[32];
503 int haverow = 0,havedata = 0;
511 if (!pkg || !pkg->db || !path) {
515 /* use local if caller didn't pass in room */
521 fd = open(path, O_RDONLY);
523 fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno));
526 if (fstat(fd, &sbuf) == -1) {
527 fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno));
530 /* not a regular file? */
531 if (!S_ISREG(sbuf.st_mode)) {
532 /* TODO this is ok, just stored differently */
533 fprintf(stderr, "%s non-regular files unsupported %s\n", __FUNCTION__, path);
537 content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0);
539 fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno));
545 sha256_process(&md, content, sbuf.st_size);
546 sha256_done(&md, tmp);
548 sprintf(hash+j*2, "%02x", (unsigned)tmp[j]);
551 //fprintf(stderr, "file %s: %s\n", path, hash);
553 /* prepare and bind */
554 /* TODO check null */
555 sqlite3 *db = pkg->db;
557 rc = sqlite3_prepare_v2(db, "select size, content is not null from files where hash = ?", -1, &ifile,0);
558 if (rc != SQLITE_OK) {
559 SQLERROR(sqlite3_errmsg(db));
565 sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC);
567 rc = sqlite3_step(ifile);
569 if (rc != SQLITE_DONE) {
570 if (rc != SQLITE_ROW) {
571 /* didn't find a row */
572 SQLERROR(sqlite3_errmsg(db));
577 // fprintf(stderr, "have row for hash\n");
578 type = sqlite3_column_type(ifile, 0);
579 if (type == SQLITE_NULL) {
580 /* TODO assert, this shouldn't be possible? */
581 fprintf(stderr, "no file size\n");
582 sqlite3_finalize(ifile);
585 type = sqlite3_column_type(ifile, 1);
586 if (type == SQLITE_NULL) {
587 /* TODO assert, this shouldn't be possible? */
588 fprintf(stderr, "no file data\n");
589 sqlite3_finalize(ifile);
591 /* which is fine, just need to update the row then */
593 havedata = sqlite3_column_int(ifile, 1);
596 sqlite3_finalize(ifile);
600 outbuf = compresslzma(content, sbuf.st_size, &outlen);
602 fprintf(stderr, "compresslzma failed\n");
605 //fprintf(stderr, "compressed to %zu\n", outlen);
606 /* don't need the original file now */
607 munmap(content, sbuf.st_size);
610 /* start a transaction */
611 // do that outside of here
616 //fprintf(stderr, "adding file data\n");
617 rc = sqlite3_prepare(db, "update files set size = ?, content = ? where hash = ?", -1, &ifile,0);
619 //fprintf(stderr, "creating new data row\n");
620 rc = sqlite3_prepare(db, "insert into files (size, content, hash) values (?,?,?)", -1, &ifile,0);
622 if (rc != SQLITE_OK) {
623 SQLERROR(sqlite3_errmsg(db));
624 fprintf(stderr, "cant prepare data\n");
629 sqlite3_bind_int64(ifile, 1, (sqlite3_int64)sbuf.st_size);
630 if (rc != SQLITE_OK) {
631 SQLERROR(sqlite3_errmsg(db));
632 fprintf(stderr, "cant bind size\n");
636 sqlite3_bind_blob64(ifile, 2, outbuf, (sqlite3_int64)outlen, SQLITE_STATIC);
637 if (rc != SQLITE_OK) {
638 SQLERROR(sqlite3_errmsg(db));
639 fprintf(stderr, "cant bind content\n");
643 sqlite3_bind_text(ifile, 3, hash, 64, SQLITE_STATIC);
644 if (rc != SQLITE_OK) {
645 SQLERROR(sqlite3_errmsg(db));
646 fprintf(stderr, "cant bind hash\n");
650 rc = sqlite3_step(ifile);
651 if (rc != SQLITE_DONE) {
652 SQLERROR(sqlite3_errmsg(db));
653 sqlite3_finalize(ifile);
657 sqlite3_finalize(ifile);
663 /* don't need the original file now */
664 munmap(content, sbuf.st_size);
669 /* if package and not nopackage flag, add to package */
670 if (pkg->pkgname && (!ZPM_NOPACKAGE)) {
680 int main(int ac, char **av){
695 fprintf(stderr, "usage: db hash file\n");
699 rc = sqlite3_open(av[1], &db);
701 SQLERROR(sqlite3_errmsg(db));
710 Packages are sqlite databases
712 get application id and userver
714 Primitive operations:
717 associate path with package
718 associate blob with path?
720 * extract blob to a path
721 compare blob to filesystem path
722 create package with info
726 record elf information about blob
729 sign a package? What are we verifying?