]> pd.if.org Git - zpackage/blobdiff - zpm-pkgfiles.c
rename pkgfiles to syncfs
[zpackage] / zpm-pkgfiles.c
diff --git a/zpm-pkgfiles.c b/zpm-pkgfiles.c
deleted file mode 100644 (file)
index 0a0f1d5..0000000
+++ /dev/null
@@ -1,559 +0,0 @@
-#define _POSIX_C_SOURCE 200809L
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <limits.h>
-#include <errno.h>
-#include <ctype.h>
-#include <pwd.h>
-#include <grp.h>
-#include <math.h>
-
-/* needed for S_IFMT and AT_FDCWD */
-#include <fcntl.h>
-
-#include <string.h>
-
-#include "sqlite3.h"
-#include "zpm.h"
-
-struct config {
-       struct zpm *log; /* logging db will be attached as "log" */
-       struct zpm *src;
-       char *dbfile;
-       char *rootdir;
-       int errabort, errors, verbose, dryrun;
-       int setuser, setgroup;
-       int reverse, exitonerror;
-};
-
-static void usage() {
-       printf("usage: zpm $scriptname [-fncC] args ...\n");
-}
-
-static int exists(char *path, mode_t *mode) {
-       struct stat st;
-
-       if (lstat(path, &st) == -1) {
-               return 0;
-       }
-       if (mode) *mode = st.st_mode;
-       return 1;
-}
-
-/* TODO maintain a list of already created directories */
-static int create_leading_dirs(char *path) {
-       char *delim, *s;
-       int ch = 0;
-       char pcopy[ZPM_PATH_MAX];
-       struct stat st;
-       
-       strcpy(pcopy, path);
-
-       delim = strrchr(pcopy, '/');
-       if (!delim) return 1; /* not an error, but no leading dirs */
-
-       /* cut off last component */
-       *delim = 0;
-
-       s = pcopy;
-       do {
-               while (*s == '/') {
-                       s++;
-               }
-
-               delim = strchr(s, '/');
-               if (delim) {
-                       ch = *delim;
-                       *delim = 0;
-               }
-
-               /* try to create the directory, if it exists
-                * and is a directory or a symlink, that's ok
-                */
-               if (mkdir(pcopy, 0755) == -1) {
-                       switch (errno) {
-                               case EEXIST:
-                                       if (lstat(pcopy, &st) == -1) {
-                                               /* can't stat? */
-                                               return 0;
-                                       }
-                                       switch (st.st_mode & S_IFMT) {
-                                               case S_IFDIR:
-                                               case S_IFLNK:
-                                                       break;
-                                               default:
-                                                       return 0;
-                                       }
-                                       break;
-                               default:
-                                       return 0;
-                       }
-               }
-               if (delim) {
-                       *delim = ch;
-               }
-               s = delim;
-       } while (delim);
-       
-       return 1;
-}
-
-char *column(char *col, int ncols, char **vals, char **cols) {
-       int i = 0;
-       char *val = NULL;
-
-       for (i=0; i < ncols; i++) {
-//             fprintf(stderr, "checking '%s' = '%s'\n", cols[i], vals[i]);
-               
-               if (!strcmp(col, cols[i])) {
-                       val = vals[i];
-                       break;
-               }
-       }
-       return val;
-}
-
-#define IERR(x) do { conf->errors++; conf->log->errmsg = strdup(x); return conf->errabort; } while (0)
-#define COL(x) column(x, ncols, vals, cols)
-#define SYSERR(x) do { conf->log->error = 2; return conf->errabort; } while (0)
-
-static char *ops[] = { "new", "remove", "update", 0 };
-
-static int getop(char *opstr) {
-       int i;
-
-       if (!opstr) return 0;
-       for (i=0;ops[i];i++) {
-               if (!strcmp(opstr, ops[i])) {
-                       return i+1;
-               }
-       }
-       return 0;
-}
-
-static int report_conflicts(void *f, int ncols, char **vals, char **cols) {
-       struct config *conf = f;
-       char *path;
-       char *pkg;
-
-       pkg = COL("pkgid");
-       path = COL("path");
-
-       conf->errors++;
-       fprintf(stderr, "%s owned by %s\n", path, pkg);
-       return 0;
-}
-
-static int check_existing(void *f, int ncols, char **vals, char **cols) {
-       struct config *conf = f;
-       char *path;
-       struct stat st;
-
-       path = COL("dest");
-       if (!path) IERR("can't check for existing");
-
-       if (conf->dryrun) {
-               printf("checkfor %s\n", path);
-               return 0;
-       }
-
-       if (conf->verbose) {
-               fprintf(stderr, "check for existing %s\n", path);
-       }
-
-       if (lstat(path, &st) == 0) {
-               fprintf(stderr, "%s exists \n", path);
-               conf->errors++;
-       } else {
-               switch(errno) {
-                       /* not an error, file shouldn't exist*/
-                       case ENOENT: break;
-                       default:
-                               fprintf(stderr, "unable to check %s: %s\n",
-                                               path, strerror(errno));
-                               conf->errors++;
-                               break;
-               }
-       }
-       return 0;
-}
-
-static int update_files(void *f, int ncols, char **vals, char **cols) {
-       struct config *conf = f;
-       char *pkg;
-       char *path;
-       char *dest;
-
-       pkg = COL("pkgid");
-       if (!pkg) IERR("can't get pkgid");
-       path = COL("path");
-       if (!path) IERR("can't get path");
-       dest = COL("dest");
-       if (!dest) IERR("no file dest");
-
-       /* hash is different, so no different than install,
-        * but we don't need to create leading directories
-        */
-
-       if (conf->dryrun) {
-               fprintf(stderr, "update %s\n", dest);
-               return 0;
-       }
-
-       fprintf(stderr, "update not implemented: %s", dest);
-       conf->errors++;
-
-       return 0;
-}
-
-static int remove_files(void *f, int ncols, char **vals, char **cols) {
-       struct config *conf = f;
-       char *dest;
-       struct stat st;
-
-       dest = COL("dest");
-       if (!dest) IERR("no file dest");
-
-       if (conf->dryrun) {
-               char *ftype = COL("filetype");
-               int t = *ftype;
-
-               switch(t) {
-                       case 'd': printf("rmdir %s\n", dest); break;
-                       default: printf("unlink %s\n", dest); break;
-               }
-               return 0;
-       }
-
-       if (lstat(dest, &st) == -1) {
-               IERR("can't stat");
-       }
-
-       if (S_ISDIR(st.st_mode)) {
-               fprintf(stderr, "rmdir %s\n", dest);
-               rmdir(dest);
-       } else if (S_ISREG(st.st_mode)) {
-               /* TODO conf to import before removal */
-               if (conf->verbose) {
-                       fprintf(stderr, "unlink(%s)\n", dest);
-               }
-               unlink(dest);
-       } else {
-               unlink(dest);
-       }
-       
-       return 0;
-}
-
-static int install_files(void *f, int ncols, char **vals, char **cols) {
-       struct config *conf = f;
-       struct passwd *pw;
-       struct group *gr;
-
-       mode_t mode = 0;
-       char *path, *dest;
-       uid_t uid;
-       gid_t gid;
-       int ftype;
-       char *val;
-       char *hash = 0;
-       char *opstr;
-       int op = 0;
-
-       /* TODO put the result row in a hash table.  May not actually
-        * be faster
-        */
-       opstr = COL("op");
-       op = getop(opstr);
-       if (op == 0) IERR("invalid operation");
-
-       /* TODO config to dishonor setuid/setgid */
-       path = COL("path");
-       if (!path) IERR("no file path");
-       if (strlen(path) == 0) {
-               IERR("zero length path not allowed");
-       }
-       dest = COL("dest");
-       if (!dest) IERR("no file dest");
-       if (strlen(dest) == 0) {
-               IERR("zero length dest not allowed");
-       }
-
-       val = COL("mode");
-
-       if (!val) IERR("can't determine mode");
-       mode = strtoul(val, NULL, 8);
-
-       val = COL("filetype");
-       if (!val || strlen(val) == 0) {
-               IERR("can't determine file type");
-       }
-       ftype = *val;
-
-       if (ftype == 'r') {
-               hash = COL("hash");
-               if (!hash) IERR("can't get hash");
-       }
-
-       if (conf->verbose) {
-               fprintf(stderr, "installing '%c' %s\n", ftype, dest);
-       }
-
-       uid = getuid();
-       gid = getgid();
-
-       if (conf->setuser) {
-               val = COL("username");
-               if (!val) IERR("no username");
-               pw = getpwnam(val);
-               if (!pw) IERR("no passwd entry");
-               uid = pw->pw_uid;
-       }
-       if (conf->setgroup) {
-               val = COL("groupname");
-               if (!val) IERR("no groupname");
-               gr = getgrnam(val);
-               if (!gr) IERR("no group entry");
-               gid = gr->gr_gid;
-       }
-
-       if (conf->dryrun) {
-               //printf("cld %s\n", path);
-               printf("new %c%o %d:%d %s -> %s\n", ftype, mode, uid, gid, path, dest);
-               return 0;
-       }
-
-       /* TODO should these be owned by the path owner if they don't exist? */
-       /* probably, though they then belong to the package, sort of */
-       if (!create_leading_dirs(dest)) {
-               fprintf(stderr, "unable to create leading directories for %s\n",
-                               dest);
-               IERR("cld failure");
-       }
-
-       if (ftype == 'd') {
-               if (mkdir(dest, mode) == -1) {
-                       IERR("can't mkdir");
-               }
-       } else if (ftype == 'r') {
-               struct zpm *source;
-               source = conf->src ? conf->src : conf->log;
-               if (conf->verbose > 1) {
-                       fprintf(stderr, "extracting %8.8s to %s with mode %o\n",
-                                       hash, dest, mode);
-               }
-               if (!zpm_extract(source, hash, dest, mode)) {
-                       IERR("can't extract file");
-               }
-       } else if (ftype == 'l') {
-               char *target = COL("target");
-               if (!target) {
-                       fprintf(stderr, "no target for symlink %s\n", path);
-                       conf->errors++;
-                       return conf->errabort;
-               }
-
-               if (strlen(target) == 0) {
-                       IERR("zero length symlink not allowed");
-               }
-
-               if (conf->verbose > 1) {
-                       fprintf(stderr, "symlink %s -> %s\n", path, target);
-               }
-               if (symlink(target, path) == -1) {
-                       IERR("can't symlink");
-               }
-       } else {
-               fprintf(stderr, "unhandled filetype %c\n", ftype);
-       }
-
-       if (conf->setuser && conf->setgroup) {
-               if (chown(dest, uid, gid) == -1) {
-                       IERR("can't chown");
-               }
-       }
-
-       struct timespec times[2] = { 0 };
-       double mtime = strtod(COL("mtime"),NULL);
-
-       times[0].tv_nsec = UTIME_OMIT;
-       times[1].tv_sec = (time_t)llrint(floor(mtime));
-       times[1].tv_nsec = lrint(floor(fmod(mtime,1.0)*1000000000));
-
-       utimensat(AT_FDCWD, dest, times, AT_SYMLINK_NOFOLLOW);
-
-       if (conf->verbose) {
-               printf("%s\n", path);
-       }
-
-       return 0;
-}
-
-static void runstage(struct config *conf, char *stage,
-               int (callback)(void *, int, char **, char **)) {
-       int rv;
-       char *errmsg;
-       sqlite3_str *s;
-       char *sql;
-
-       s = sqlite3_str_new(conf->log->db);
-       sqlite3_str_appendall(s, "select *, ");
-       if (conf->rootdir) {
-               sqlite3_str_appendf(s, "printf('%%s/%%s',rtrim(%Q,'/'),ltrim(path,'/'))", conf->rootdir);
-       } else {
-               sqlite3_str_appendf(s, "printf('/%%s', trim(path, '/'))");
-       }
-       sqlite3_str_appendall(s, " as dest from install_status");
-
-       if (stage) {
-               sqlite3_str_appendf(s," where op = %Q", stage);
-       }
-       if (conf->reverse) {
-               sqlite3_str_appendall(s," order by length(path) desc, path desc");
-       }
-
-       sql = sqlite3_str_value(s);
-       if (conf->verbose > 2) {
-               fprintf(stderr, "stage query: %s\n", sql);
-       }
-
-       rv = zpm_exec(conf->log, sql, callback, conf, &errmsg);
-
-       sqlite3_str_finish(s);
-
-       if (rv) {
-               fprintf(stderr, "exec fail: %s\n", sqlite3_errstr(rv));
-               if (errmsg) {
-                       fprintf(stderr, "database error: %s\n", errmsg);
-                       conf->errors++;
-               }
-               if (conf->log->error == 1) {
-                       fprintf(stderr, "unable to allocate memory\n");
-               }
-               fprintf(stderr, "zpm_exec failure: %s\n",
-                               conf->log->errmsg ? conf->log->errmsg : "unknown");
-               conf->errors++;
-       }
-       if (conf->log->errmsg) {
-               fprintf(stderr, "error: %s\n", conf->log->errmsg);
-       }
-       if (conf->errors && conf->exitonerror) {
-               zpm_close(conf->log);
-               zpm_close(conf->src);
-               exit(EXIT_FAILURE);
-       }
-       /* TODO final report function in conf var */
-}
-
-int main(int ac, char **av){
-       struct zpm localdb;
-       struct zpm pkgdb;
-       int opt;
-       char *pkgdbfile = 0, *localdbfile = 0;
-       char *s;
-
-       struct config conf;
-
-       conf.errabort = 1;
-       conf.errors = 0;
-       conf.verbose = 0;
-       conf.dryrun = 0;
-       conf.setuser = 1;
-       conf.setgroup = 1;
-       conf.log = 0;
-       conf.src = 0;
-       conf.rootdir = 0;
-       conf.reverse = 0;
-
-       if (geteuid() != 0) {
-               conf.setuser = 0;
-               conf.setgroup = 0;
-       }
-
-       localdbfile = ZPM_LOCAL_DB;
-       if ((s = getenv("ZPMDB"))) {
-               /* TODO does this need to be copied ? */
-               localdbfile = s;
-       }
-
-       if ((s = getenv("ZPM_ROOT_DIR"))) {
-               /* TODO does this need to be copied ? */
-               conf.rootdir = s;
-       }
-
-       /*
-        * -d localdb or ZPMDB * or /var/lib/zpm/zpm.db, or die
-        * -f 'package database', otherwise regular default of env
-        *  ZPM_PACKAGE_FILE, or use pkgdb if otherwise not found
-        * -R root of pkg, will just chdir there
-        *
-        *  args are pkgid triple, but will do a pkg find on the pkgdb
-        */
-
-       while ((opt = getopt(ac, av, "f:d:c:nCR:v")) != -1) {
-               switch (opt) {
-                       case 'd': localdbfile = optarg; break;
-                       case 'f': pkgdbfile = optarg; break;
-                       case 'n': conf.dryrun = 1; break;
-                       case 'v': conf.verbose++; break;
-                       case 'C': conf.errabort = 0; break;
-                       case 'R': conf.rootdir = optarg; break;
-                       case 'N': conf.setuser = 0; conf.setgroup = 0; break;
-                       default:
-                                 usage();
-                                 exit(EXIT_FAILURE);
-                                 break;
-               }
-       }
-
-       /* verify root dir exists */
-       if (conf.rootdir && !exists(conf.rootdir, NULL)) {
-               fprintf(stderr, "rootdir %s does not exist\n", conf.rootdir);
-       }
-
-       if (!zpm_open(&localdb, localdbfile)) {
-               fprintf(stderr, "can't open zpm db %s\n", localdbfile);
-               exit(EXIT_FAILURE);
-       }
-       conf.log = &localdb;
-
-       if (pkgdbfile) {
-               if (!zpm_open(&pkgdb, pkgdbfile)) {
-                       fprintf(stderr, "can't open src db %s\n", localdbfile);
-                       exit(EXIT_FAILURE);
-               } else {
-                       conf.src = &pkgdb;
-               }
-       }
-
-       /* TODO find pkgid from arg */
-
-       /* TODO set conf var to finalize error reporting */
-       if (conf.verbose) {
-               fprintf(stderr, "syncing filesystem %s (ldb %s) from %s\n",
-                               conf.rootdir ? conf.rootdir : "/",
-                               localdbfile, pkgdbfile);
-       }
-
-       conf.errors = 0;
-       conf.exitonerror = 0;
-       runstage(&conf, "conflict", report_conflicts);
-       runstage(&conf, "new", check_existing);
-
-       if (!conf.errors) {
-               conf.exitonerror = 1;
-               runstage(&conf, "new", install_files);
-               runstage(&conf, "update", update_files);
-               conf.reverse = 1;
-               runstage(&conf, "remove", remove_files);
-               conf.reverse = 0;
-       }
-
-       zpm_close(&localdb);
-       zpm_close(conf.src);
-       return conf.errors ? 1 : 0;
-}