]> pd.if.org Git - zpackage/commitdiff
add files for zpm-add rewrite
authorNathan Wagner <nw@hydaspes.if.org>
Wed, 12 Dec 2018 22:02:27 +0000 (22:02 +0000)
committerNathan Wagner <nw@hydaspes.if.org>
Wed, 12 Dec 2018 22:02:27 +0000 (22:02 +0000)
zpm-add [deleted file]
zpm-add.c [new file with mode: 0644]

diff --git a/zpm-add b/zpm-add
deleted file mode 100755 (executable)
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 (file)
index 0000000..82a92fa
--- /dev/null
+++ b/zpm-add.c
@@ -0,0 +1,434 @@
+#define _POSIX_C_SOURCE 200809L
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#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;
+}