#define _POSIX_C_SOURCE 200809L #include #include #include #include #include #include #include #include #include #include "zpm.h" #include "elf.h" #include "sha256.h" #if 0 struct zpm { sqlite3 *db; char *path; /* path to package file */ char *version; int release; char *pkgname; time_t installed; /* install time, 0 for not installed */ }; struct zpm_file { char *path; int mode; uint32_t filetype; char *tags; char *owner; char *group; char *hash; /* could be fixed length */ time_t mtime; struct zpm_file *next; /* so you can make a linked list */ }; /* NULL? Create? */ /* associate with a package ? if only one? first? */ int zpm_open(struct zpm *pkg, char *path); int zpm_pkgname(char *base, char *version, int release); /* construct a package file name */ /* flags for preserving mode, owner, etc */ /* puts hash of import in hash */ /* path can be a hash, with an "INTERNAL" flag, i.e. internally import */ #define ZPM_MODE 0x1 #define ZPM_OWNER 0x2 #define ZPM_MTIME 0x4 #define ZPM_INTERNAL 0x8 #define ZPM_NOBLOB 0x10 /* don't run scripts on install */ #define ZPM_NOSCRIPTS 0x10 /* don't associate the file with a package, just do a raw insert */ /* otherwise, associate it with the current package */ #define ZPM_NOPACKAGE 0x20 int zpm_import(struct zpm *zp, char *path, uint32_t flags, uint8_t *hash); /* link and unlink hashes to packages */ int zpm_link(struct zpm *pkg, char *path, char *hash, struct zpm_file *fileinfo); int zpm_unlink(struct zpm *pkg, char *path); /* tag a file. relative to "current package" */ int zpm_tag(struct zpm *zp, char *path, char *tags); /* should this be broken up into separage functions ? */ int zpm_md(struct zpm *zp, char *path, int mode, char *owner, char *group, time_t mtime); /* export hash to dest */ int zpm_extract(struct zpm *pkg, char *hash, char *path, int mode); /* export path to dest */ int zpm_export(struct zpm *zp, char *path, uint32_t flags, char *dest); int zpm_close(struct zpm *zp); /* attach a signature to a package */ int zpm_sign(struct zpm *z, size_t s, void *signature); /* set the package info to the nth package, -1 to return count? */ /* further import/exports and such will be relative to this package */ int zpm_package(struct zpm *zp, int n); /* get file information */ int zpm_stat(struct zpm *z, struct zpm_file *f, int n); /* will also set the package context to the new package */ int zpm_newpkg(struct zpm *z, char *base, char *version, int release); /* transactions */ int zpm_begin(struct zpm *z); int zpm_commit(struct zpm *z); int zpm_rollback(struct zpm *z); /* higher level operations */ /* install or uninstall the package */ /* flag for keeping the blobs in local */ /* what about tag filtering */ int zpm_install(struct zpm *z, struct zpm *local, uint32_t flags); int zpm_uninstall(struct zpm *local); /* slurp up the actual blobs */ /* what about versioning them if they change */ int zpm_preserve(struct zpm *local); /* check file integrity */ int zpm_checkinstall(struct zpm *local); int zpm_merge(struct zpm *z, struct zpm *src, uint32_t flags); void uncompresslzma(void *buf, size_t bufsize, FILE *out); #define SQLERROR(x) fprintf(stderr, "%s %d: %s\n", __func__, __LINE__, (x)) #endif static char *dupstr(char *s) { size_t n; char *d; n = strlen(s); d = malloc(n+1); if (d) { d = strcpy(d, s); } return d; } #if 0 int zpm_newpkg(struct zpm *z, char *base, char *version, int release) { char *sql = "insert or ignore into packages (package,version,release) values (?,?,?)"; int rc; sqlite3_stmt *ifile; rc = sqlite3_prepare(db, sql, -1, &ifile,0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); return 0; } rc = sqlite3_bind_text(ifile, 1, base, strlen(base), SQLITE_STATIC); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); fprintf(stderr, "cant bind package name\n"); zpm_rollback(pkg); return 0; } sqlite3_bind_text(ifile, 2, version, strlen(version), SQLITE_STATIC); sqlite3_bind_int(ifile, 3, release) rc = sqlite3_step(ifile); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); return 0; } sqlite3_finalize(ifile); z->pkg = dupstr(base); z->version = dupstr(version); z->release = release; } #endif int zpm_begin(struct zpm *z) { char *errstr = 0; sqlite3_exec(z->db, "begin;", NULL, NULL, &errstr); if (errstr) { fprintf(stderr, "sqlite begin error: %s\n", errstr); sqlite3_free(errstr); return 0; } return 1; } int zpm_commit(struct zpm *z) { char *errstr = 0; sqlite3_exec(z->db, "commit;", NULL, NULL, &errstr); if (errstr) { fprintf(stderr, "sqlite commit error: %s\n", errstr); sqlite3_free(errstr); return 0; } return 1; } int zpm_rollback(struct zpm *z) { char *errstr = 0; sqlite3_exec(z->db, "rollback;", NULL, NULL, &errstr); if (errstr) { fprintf(stderr, "sqlite rollback error: %s\n", errstr); sqlite3_free(errstr); return 0; } return 1; } int zpm_db_set_pragma(struct zpm *db, int pragma, int value) { int rc; char *sql; sqlite3_stmt *s; switch (pragma) { case 1: sql = "pragma application_id = ?;"; break; case 2: sql = "pragma user_version = ?;"; break; default: return -1; break; } rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db->db)); return -1; } sqlite3_bind_int(s, 1, value); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db->db)); fprintf(stderr, "cant bind pragma value\n"); sqlite3_finalize(s); return -1; } rc = sqlite3_step(s); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db->db)); fprintf(stderr, "cant set pragma\n"); sqlite3_finalize(s); return -1; } sqlite3_finalize(s); return value; } int zpm_db_pragma(struct zpm *db, int pragma) { int rc; int value = -1; char *sql = 0; sqlite3_stmt *s; switch (pragma) { case 1: sql = "pragma application_id;"; break; case 2: sql = "pragma user_version;"; break; default: return -1; break; } rc = sqlite3_prepare_v2(db->db, sql, -1, &s, 0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db->db)); fprintf(stderr, "%s, errnum = %d\n", sqlite3_errmsg(db->db), rc); /* TODO just abort? */ return -1; } rc = sqlite3_step(s); if (rc == SQLITE_ROW) { value = sqlite3_column_int(s, 0); } sqlite3_finalize(s); return value; } static #include "newdb.c" int zpm_db_initialize(struct zpm *pkg) { //fprintf(stderr, "initializing zpm database\n"); char *error; switch (sqlite3_exec(pkg->db, createdb, (int (*)(void *,int,char **,char **))0, NULL, &error)) { case SQLITE_OK: break; default: SQLERROR(sqlite3_errmsg(pkg->db)); fprintf(stderr, "error: %s\n", error); sqlite3_free(error); return 0; break; } return 1; } /* NULL? Create? */ int zpm_open(struct zpm *pkg, char *path) { int rc; char *errstr = 0; sqlite3 *db = 0; int appid, dbver; pkg->db = 0; pkg->path = 0; pkg->version = 0; pkg->release = 0; pkg->pkgname = 0; pkg->installed = 0; rc = sqlite3_open(path, &db); if (rc) { SQLERROR(sqlite3_errmsg(db)); sqlite3_close(db); return 0; } pkg->db = db; pkg->path = dupstr(path); appid = zpm_db_pragma(pkg, 1); dbver = zpm_db_pragma(pkg, 2); //fprintf(stderr, "db appid = %x, dbver = %d\n", appid, dbver); switch (appid) { case 0: if (!zpm_db_initialize(pkg)) { sqlite3_close(db); return 1; }; break; case 0x5a504442: break; default: fprintf(stderr, "unknown database type\n"); sqlite3_close(db); return 0; break; } if (dbver > 1) { fprintf(stderr, "version %d zpm db detected, this program only works with version 1 databases\n", dbver); sqlite3_close(db); return 0; } sqlite3_exec(pkg->db, "pragma foreign_keys = ON;", NULL, NULL, &errstr); if (errstr) { fprintf(stderr, "sqlite foreign key error: %s\n", errstr); sqlite3_free(errstr); sqlite3_close(db); return 0; } /* TODO if this is a new database, create structures */ /* get a package. what if more than one? what if none? */ return 1; } int zpm_close(struct zpm *pkg) { if (pkg) { sqlite3_close(pkg->db); free(pkg->path); } /* TODO free any malloced names and such */ return 1; } /* set package struct variables, database, environment, then command line */ int zpm_readopts(struct zpm *pkg, int ac, char **av) { char *ev; if (!pkg) { return -1; } ev = getenv("ZPMPACKAGE"); if (ev) { pkg->pkgname = dupstr(ev); } ev = getenv("ZPMPKGREL"); if (ev) { pkg->release = strtol(ev, 0, 0); } ev = getenv("ZPMPKGVER"); if (ev) { pkg->version = dupstr(ev); } /* now, parse the options, return optind so the caller can adjust if needed */ return 1; } int zpm_extract(struct zpm *pkg, char *hash, char *path, int mode) { int rc; int blobsize; //int64_t size; void *xzdata; int type; FILE *out; sqlite3_stmt *ifile; /* TODO check null */ sqlite3 *db = pkg->db; rc = sqlite3_prepare(db, "select size, content from files where hash = ?", -1, &ifile,0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); return 0; } /* hash, filename */ 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 0; } /* either way we're done with this now */ if (rc != SQLITE_ROW) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); sqlite3_close(db); return 0; } type = sqlite3_column_type(ifile, 0); if (type == SQLITE_NULL) { fprintf(stderr, "no file size\n"); sqlite3_finalize(ifile); sqlite3_close(db); return 0; } type = sqlite3_column_type(ifile, 1); if (type == SQLITE_NULL) { fprintf(stderr, "no file data\n"); sqlite3_finalize(ifile); sqlite3_close(db); return 0; } //size = sqlite3_column_int64(ifile, 0); xzdata = (void *)sqlite3_column_blob(ifile, 1); blobsize = sqlite3_column_bytes(ifile, 1); if (strcmp(path, "-")) { out = fopen(path, "w"); } else { out = stdout; } if (!out) { fprintf(stderr, "can't open output file %s\n", path); sqlite3_finalize(ifile); sqlite3_close(db); return 0; } //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); return 1; } /* flags 0, close mmap, flags 1, return mmap fd */ int zpm_hash(char *path, char *hash, uint32_t flags) { int fd; void *content; struct stat sbuf; hash_state md; int j; unsigned char tmp[32]; /* mmap the file */ fd = open(path, O_RDONLY); if (fd == -1) { fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } if (fstat(fd, &sbuf) == -1) { fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } /* not a regular file? */ if (!S_ISREG(sbuf.st_mode)) { /* TODO this is ok, just stored differently */ fprintf(stderr, "%s non-regular files unsupported %s\n", __FUNCTION__, path); return 0; } content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0); close(fd); if (!content) { fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } /* get hash */ 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; munmap(content, sbuf.st_size); return 1; } static sqlite3_stmt *run_for_hash(sqlite3 *db, char *sql, char *hash) { int rc; sqlite3_stmt *ifile; rc = sqlite3_prepare_v2(db, sql, -1, &ifile, 0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); return 0; } /* hash, filename */ sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC); return ifile; } static int set_elf_info(sqlite3 *db, char *hash, char *content, size_t length) { if (length >= sizeof (Elf64_Ehdr) && libelf_iself(content)) { char *strtab; Elf64_Dyn *dyn; int i; Elf64_Phdr *phdr; Elf64_Ehdr *hdr; sqlite3_stmt *ifile; int rc; /* go ahead and set up elf information now */ /* clear existing for this hash */ ifile = run_for_hash(db, "delete from elfinfo where file = ?", hash); do { rc = sqlite3_step(ifile); #if 0 if (rc == SQLITE_ROW) { int nc; fprintf(stderr, "delete row has %d columns: ", sqlite3_column_count(ifile)); nc = sqlite3_column_count(ifile); for (i = 0; i < nc; i++) { char *r; r = sqlite3_column_text(ifile, i); fprintf(stderr, ", %s", r); } fprintf(stderr, "\n"); } #endif } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); fprintf(stderr, "error clearing elf info: %d\n", rc); return 0; } sqlite3_finalize(ifile); ifile = run_for_hash(db, "delete from elflibraries where file = ?", hash); do { rc = sqlite3_step(ifile); } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); fprintf(stderr, "error clearing elf library: %d\n", rc); return 0; } sqlite3_finalize(ifile); ifile = run_for_hash(db, "delete from elfneeded where file = ?", hash); do { rc = sqlite3_step(ifile); } while (rc == SQLITE_ROW); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); fprintf(stderr, "error clearing elf needed\n"); return 0; } sqlite3_finalize(ifile); hdr = libelf_header(content); /* if lib, set soname */ if (libelf_type(content) == ET_DYN) { char *elf; Elf64_Shdr *shdr, *dynsect, *dynstrtab = 0; elf = (char *)content; for (i = 0; i < hdr->e_shnum; i++) { shdr = (Elf64_Shdr *)(elf + hdr->e_shoff + i * hdr->e_shentsize); if (shdr->sh_type == SHT_DYNAMIC) { dynsect = shdr; } else if (shdr->sh_type == SHT_STRTAB && i == hdr->e_shstrndx) { dynstrtab = shdr; } } if (!dynstrtab) { exit(8); } if (!dynsect) { exit(9); } char *name; Elf64_Shdr *dyntab; name = elf + dynstrtab->sh_offset; for (i = 0; i < hdr->e_shnum; i++) { shdr = (Elf64_Shdr *)(elf + hdr->e_shoff + i * hdr->e_shentsize); if (shdr->sh_type == SHT_STRTAB && !strcmp(".dynstr", name+shdr->sh_name)) { dyntab = shdr; } } if (!dyntab) { exit(10); } char *dynname; Elf64_Dyn *dent; dynname = elf + dyntab->sh_offset; for (dent = (Elf64_Dyn *)(elf + dynsect->sh_offset); dent->d_tag != DT_NULL; dent++) { if (dent->d_tag == DT_SONAME) { char *soname = dynname + dent->d_un.d_val; sqlite3_prepare_v2(db, "insert into elflibraries (file,soname) values (?,?)",-1, &ifile, 0); sqlite3_bind_text(ifile,1,hash,64,SQLITE_STATIC); sqlite3_bind_text(ifile,2,soname,-1,SQLITE_STATIC); rc = sqlite3_step(ifile); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); fprintf(stderr, "error setting library soname\n"); return 0; } sqlite3_finalize(ifile); } } } /* if exe, set neededs */ if (libelf_type(content) == ET_EXEC) { Elf64_Shdr *dsect; char *elf; elf = (char *)content; /* find program header table */ for (i = 0; i < hdr->e_phnum; i++) { phdr = (Elf64_Phdr *)(elf + hdr->e_phoff + i * hdr->e_phentsize); if (phdr->p_type == PT_DYNAMIC) { dsect = (Elf64_Shdr *)(elf + phdr->p_offset); } } dyn = (Elf64_Dyn *)(elf + dsect->sh_offset); if (!dyn) { exit(9); } dyn = (Elf64_Dyn *)dsect; dsect = libelf_section(elf, SHT_DYNAMIC); Elf64_Shdr *strsect; strsect = libelf_section_n(elf, dsect->sh_link); strtab = elf + strsect->sh_offset; sqlite3_prepare_v2(db, "insert into elfneeded (file,needed) values (?,?)",-1, &ifile, 0); sqlite3_bind_text(ifile,1,hash,64,SQLITE_STATIC); while (dyn->d_tag != DT_NULL) { if (dyn->d_tag == DT_NEEDED) { char *need; int rc; need = strtab + dyn->d_un.d_val; if (strlen(need) == 0) continue; sqlite3_bind_text(ifile,2,need,strlen(need),SQLITE_STATIC); fprintf(stderr, "%s needs %s\n", hash, need); rc = sqlite3_step(ifile); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); fprintf(stderr, "error setting needed library\n"); return 0; } sqlite3_reset(ifile); } dyn++; } sqlite3_finalize(ifile); } } return 1; } #if 1 int zpm_import(struct zpm *pkg, char *path, uint32_t flags, char *hash) { int fd; void *content; struct stat sbuf; unsigned char tmp[32]; hash_state md; sqlite3_stmt *ifile; int haverow = 0,havedata = 0; int j,rc,type; char hashbuf[65]; /* xz compress it */ size_t outlen = 0; void *outbuf; if (!pkg || !pkg->db || !path) { return 0; } /* use local if caller didn't pass in room */ if (!hash) { hash = hashbuf; } /* mmap the file */ fd = open(path, O_RDONLY); if (fd == -1) { pkg->error = errno; fprintf(stderr, "%s can't open %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } if (fstat(fd, &sbuf) == -1) { pkg->error = errno; fprintf(stderr, "%s can't fstat %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } /* not a regular file? */ if (!S_ISREG(sbuf.st_mode)) { char *ftype; switch (sbuf.st_mode & S_IFMT) { case S_IFSOCK: ftype = "socket"; break; case S_IFLNK : ftype = "symlink"; break; case S_IFBLK : ftype = "block device"; break; case S_IFDIR : ftype = "directory"; break; case S_IFCHR : ftype = "character device"; break; case S_IFIFO : ftype = "fifo"; break; default: ftype = "unknown file type"; break; } /* TODO this is ok, just stored differently */ fprintf(stderr, "%s can't import %s file: %s\n", __FUNCTION__, ftype, path); pkg->error = EINVAL; return 0; } content = mmap(0, sbuf.st_size, PROT_READ,MAP_PRIVATE, fd, 0); close(fd); if (!content) { pkg->error = errno; fprintf(stderr, "%s can't mmap %s: %s\n", __FUNCTION__, path,strerror(errno)); return 0; } /* get hash */ 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", path, hash); /* TODO check null */ sqlite3 *db = pkg->db; /* prepare and bind */ rc = sqlite3_prepare_v2(db, "select size, content is not null from files where hash = ?", -1, &ifile,0); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); munmap(content, sbuf.st_size); return 0; } /* hash, filename */ sqlite3_bind_text(ifile, 1, hash, 64, SQLITE_STATIC); rc = sqlite3_step(ifile); if (rc != SQLITE_DONE) { if (rc != SQLITE_ROW) { /* didn't find a row */ SQLERROR(sqlite3_errmsg(db)); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } haverow = 1; // fprintf(stderr, "have row for hash\n"); type = sqlite3_column_type(ifile, 0); if (type == SQLITE_NULL) { /* TODO assert, this shouldn't be possible? */ fprintf(stderr, "no file size\n"); sqlite3_finalize(ifile); munmap(content, sbuf.st_size); return 0; } type = sqlite3_column_type(ifile, 1); if (type == SQLITE_NULL) { /* TODO assert, this shouldn't be possible? */ fprintf(stderr, "no file data\n"); sqlite3_finalize(ifile); munmap(content, sbuf.st_size); return 0; /* which is fine, just need to update the row then */ } havedata = sqlite3_column_int(ifile, 1); } sqlite3_finalize(ifile); if (!havedata) { /* compress */ outbuf = compresslzma(content, sbuf.st_size, &outlen); if (!outbuf) { fprintf(stderr, "compresslzma failed\n"); munmap(content, sbuf.st_size); return 0; } //fprintf(stderr, "compressed to %zu\n", outlen); /* start a transaction */ // do that outside of here //zpm_begin(pkg); /* insert */ if (haverow) { //fprintf(stderr, "adding file data\n"); rc = sqlite3_prepare(db, "update files set size = ?, content = ? where hash = ?", -1, &ifile,0); } else { //fprintf(stderr, "creating new data row\n"); rc = sqlite3_prepare(db, "insert into files (size, content, hash) values (?,?,?)", -1, &ifile,0); } if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); fprintf(stderr, "cant prepare data\n"); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } sqlite3_bind_int64(ifile, 1, (sqlite3_int64)sbuf.st_size); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); fprintf(stderr, "cant bind size\n"); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } sqlite3_bind_blob64(ifile, 2, outbuf, (sqlite3_int64)outlen, SQLITE_STATIC); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); fprintf(stderr, "cant bind content\n"); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } sqlite3_bind_text(ifile, 3, hash, 64, SQLITE_STATIC); if (rc != SQLITE_OK) { SQLERROR(sqlite3_errmsg(db)); fprintf(stderr, "cant bind hash\n"); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } rc = sqlite3_step(ifile); if (rc != SQLITE_DONE) { SQLERROR(sqlite3_errmsg(db)); sqlite3_finalize(ifile); zpm_rollback(pkg); munmap(content, sbuf.st_size); return 0; } sqlite3_finalize(ifile); /* commit */ //zpm_commit(pkg); /* don't need the original file now */ } if (!set_elf_info(pkg->db, hash, content, sbuf.st_size)) { fprintf(stderr, "setting elf info failed\n"); munmap(content, sbuf.st_size); return 0; } munmap(content, sbuf.st_size); /* if package and not nopackage flag, add to package */ if (pkg->pkgname && (!ZPM_NOPACKAGE)) { /* TODO */ } /* return */ return 1; } #endif #if 0 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; } } #endif #if 0 Packages are sqlite databases get application id and userver Primitive operations: add path to repo associate path with package associate blob with path? add blob to repo * extract blob to a path compare blob to filesystem path create package with info Extra primitives: record elf information about blob compress blob uncompress blob sign a package? What are we verifying? #endif