From: Nathan Wagner Date: Wed, 12 Dec 2018 22:02:27 +0000 (+0000) Subject: add files for zpm-add rewrite X-Git-Tag: v0.5.0~48 X-Git-Url: https://pd.if.org/git/?p=zpackage;a=commitdiff_plain;h=bb3252b2e691c2517f1f06c39be77357703196f4 add files for zpm-add rewrite --- diff --git a/zpm-add b/zpm-add deleted file mode 100755 index 3131c72..0000000 Binary files a/zpm-add and /dev/null differ diff --git a/zpm-add.c b/zpm-add.c new file mode 100644 index 0000000..82a92fa --- /dev/null +++ b/zpm-add.c @@ -0,0 +1,434 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zpm.h" +#include "sqlite/sqlite3.h" + +struct opts { + char *package, *version; + int release; + int complete, addcontent, isconfig, opt_l, recursive, verbose; + int followsymlinks; + int xargs, noclear; + mode_t clmode; + + char *cltype, *clhash, *clmtime, *prefix, *strip, *cltarget; + char *clgroup, *cluser; +}; + +#if 0 +static void warn(char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); +} +#endif + +static int dieval = EXIT_FAILURE; + +static void die(char *fmt, ...) { + va_list args; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + exit(dieval); +} + +char *cleanpath(char *path, char *strip, char *prefix) { + char *s = path; + char *t = s; + size_t len = 0; + char *new; + + if (strip) { + len = strlen(strip); + if (strncmp(path, strip, len)) { + /* strip is not a prefix */ + return 0; + } + s += len; + } + + len += strlen(s)+1; + + new = malloc(len); + memset(new, 0, len); + + if (!new) { + return NULL; + } + t = new; + + if (prefix) { + strcpy(new, prefix); + t = new + strlen(prefix); + } + + /* skip leading curdir */ + if (*s && *s == '.' && s[1] && s[1] == '/') { + s += 2; + } + + /* skip leading slashes */ + while (*s == '/') { + s++; + } + + if (*t != '/') { + *t++ = '/'; + } + + for (; *s; s++) { + /* skip multiple slashes */ + if (*s == '/' && s[1] && s[1] == '/') { + continue; + } + /* skip trailing slash */ + if (*s == '/' && !s[1]) { + continue; + } + + /* skip curdirs */ + if (*s == '/' && s[1] && s[1] == '.' && s[2] && s[2] == '/') { + s += 1; + continue; + } + + if (*s == '/' && s[1] && s[1] == '.' && s[2] == 0) { + s += 1; + continue; + } + + *t++ = *s; + } + *t = 0; + + return new; +} + +char *getuser(uid_t uid) { + struct passwd *pw; + + pw = getpwuid(uid); + if (pw) { + return strdup(pw->pw_name); + } + return 0; +} + +char *getgroup(uid_t uid) { + struct passwd *pw; + + pw = getpwuid(uid); + if (pw) { + return strdup(pw->pw_name); + } + return 0; +} + +void free_file(struct zpm_file *file) { + free(file->path); + free(file->owner); + free(file->group); + free(file->target); + file->path = file->owner = file->group = file->target = 0; +} + +int stat_file(struct zpm_file *file, char *path, struct opts *opt) { + struct stat st; + int rv; + + file->data = path; + + errno = 0; + if (opt->followsymlinks) { + rv = stat(path, &st); + } else { + rv = lstat(path, &st); + } + + if (rv == -1) { + return 0; + } + + switch (st.st_mode & S_IFMT) { + case S_IFBLK: file->type = 'b'; break; + case S_IFCHR: file->type = 'c'; break; + case S_IFDIR: file->type = 'd'; break; + case S_IFIFO: file->type = 'p'; break; + case S_IFLNK: file->type = 'l'; break; + case S_IFREG: file->type = 'r'; break; + case S_IFSOCK: file->type = 's'; break; + default: file->type = 0; break; + } + + file->configuration = opt->isconfig; + + if (file->type == 0) { + return 0; + } + + if (file->type == 'l') { + if (opt->cltarget) { + file->target = strdup(opt->cltarget); + } else { + char linkval[4096]; + size_t n; + n = readlink(path, linkval, sizeof linkval); + if (n >= sizeof linkval) { + return 0; + } + file->target = strdup(linkval); + } + } + + /* strip and prefix */ + file->path = cleanpath(path, opt->strip, opt->prefix); + if (file->path == 0) { + free_file(file); + return 0; + } + + if (opt->clmode) { + file->mode = opt->clmode; + } else { + file->mode = st.st_mode; + } + + if (opt->cluser) { + file->owner = strdup(opt->cluser); + } else { + file->owner = getuser(st.st_uid); + } + + if (file->owner == 0) { + free_file(file); + return 0; + } + + if (opt->clgroup) { + file->group = strdup(opt->clgroup); + } else { + file->group = getgroup(st.st_gid); + } + if (file->group == 0) { + free_file(file); + return 0; + } + + file->mtime = st.st_mtime; + + return 1; +} + +int add_file(struct zpm *zpm, struct zpm_file *file, struct opts *opt); + +int add_dir(struct zpm *zpm, char *path, struct opts *opt) { + DIR *dir; + struct dirent *de; + struct zpm_file file = { 0 }; + + dir = opendir(path); + + if (!dir) { + zpm_seterror(zpm, "can't open dir %s: %s", path, strerror(errno)); + return 0; + } + + while ((de = readdir(dir))) { + if (!strcmp(de->d_name, ".")) { + continue; + } + if (!strcmp(de->d_name, "..")) { + continue; + } + + if (!stat_file(&file, de->d_name, opt)) { + zpm_seterror(zpm, "stat %s failed: %s", + de->d_name, strerror(errno)); + return 0; + } + + if (!add_file(zpm, &file, opt)) { + free_file(&file); + return 0; + } + free_file(&file); + } + return 1; +} + +int add_file(struct zpm *zpm, struct zpm_file *file, struct opts *opt) { + char hash[ZPM_HASH_STRLEN+1]; + + if (file->type == 'r') { + if (opt->addcontent) { + if (zpm_import(zpm, file->data, 0, hash)) { + strcpy(file->hash, hash); + } else { + return 0; + } + } else { + zpm_hash(file->data, hash, 0); + strcpy(file->hash, hash); + } + } + + zpm_db_run(zpm, "insert or replace into packagefiles " + "(package,version,release,path,mode,mtime,username," + "groupname,filetype,hash,configuration,target)" + " values " + "(%Q, %Q, %d, %Q, %o, %d, %Q, %Q, '%c', %Q, %d, %Q)", + opt->package, opt->version, opt->release, file->path, + file->mode, (int)file->mtime, file->owner, file->group, + file->type, + file->hash, file->configuration, file->target + ); + + if (zpm->error) { + return 0; + } + + if (opt->verbose > 1) { + printf("%c%o %s:%s %s\n", file->type, file->mode, file->owner, file->group, file->path); + } else if (opt->verbose > 0) { + + printf("%s\n", file->path); + + } + + if (opt->recursive && file->type == 'd') { + if (!add_dir(zpm, file->data, opt)) { + return 0; + } + } + + return 1; +} + +int main(int ac, char **av) { + struct zpm zpm; + struct opts opt = { 0 }; + int i; + int option; + + char hash[ZPM_HASH_STRLEN+1]; + + char *dbfile = getenv("ZPMDB"); + + if (!dbfile) { + dbfile = "/var/lib/zpm/local.db"; + } + + opt.addcontent = 1; + + while ((option = getopt(ac, av, ":f:vr:l:P:S:cu:g:NCm:M:T:H:F:zxh")) != -1) { + switch (option) { + case 'C': opt.complete = 1; break; + case 'F': opt.cltype = optarg; break; + case 'H': opt.clhash = optarg; break; + case 'M': opt.clmtime = optarg; break; + case 'N': opt.addcontent = 0; break; + case 'P': opt.prefix = optarg; break; + case 'S': opt.strip = optarg; break; + case 'T': opt.cltarget = optarg; break; + case 'c': opt.isconfig = 1; break; + case 'f': dbfile = optarg; break; + case 'g': opt.clgroup = optarg; break; + case 'h': opt.followsymlinks = 1; break; + case 'l': opt.opt_l = 1; break; + case 'm': opt.clmode = strtol(optarg, NULL, 8); break; + case 'r': opt.recursive = 1; break; + case 'u': opt.cluser = optarg; break; + case 'v': opt.verbose++; break; + case 'x': opt.xargs = 1; dieval = 255; break; + case 'z': opt.noclear = 1; break; + default: + exit(EXIT_FAILURE); + break; + } + } + + if (ac < optind) { + exit(EXIT_FAILURE); + } + + if (!zpm_open(&zpm, dbfile)) { + die("can't open zpm db %s", dbfile); + } + +#if 0 + i = sqlite3_config(SQLITE_CONFIG_MMAP_SIZE,98222080); + if (i != SQLITE_OK) { + exit(3); + } +#endif + + /* package is first arg */ + char *pkgstr; + char *pkgid; + pkgstr = av[optind++]; + pkgid = zpm_findpkg(&zpm, pkgstr, NULL); + /* TODO if not found, error */ + if (!pkgid) { + die("package %s not found\n", pkgstr); + } + + char package[128]; + char version[64]; + int release; + + zpm_parse_package(pkgid, package, version, &release); + opt.package = package; + opt.version = version; + opt.release = release; + + if (opt.verbose) { + printf("adding to %s %s\n", dbfile, pkgid); + } + fflush(stdout); + + //zpm_begin(&zpm); + + struct zpm_file file; + for (i=optind; av[i]; i++) { + if (!stat_file(&file, av[i], &opt)) { + die("can't stat %s: %s", av[i], strerror(errno)); + } + file.data = av[i]; + if (add_file(&zpm, &file, &opt)) { + free_file(&file); + } else { + die("error: %s", zpm.errmsg); + } + } + + if (opt.complete) { + zpm_db_run(&zpm, "update packages set build_time = %d where package = %Q and version = %Q and release = %d", time(NULL), package, version, release); + zpm_package_hash(&zpm, pkgid, hash); + zpm_package_sethash(&zpm, pkgid, hash); + } else if (!opt.noclear) { + zpm_db_run(&zpm, "update packages set build_time = null, hash = null where package = %Q and version = %Q and release = %d", package, version, release); + } + /* TODO error check */ + + //zpm_commit(&zpm); + zpm_close(&zpm); + return 0; +}