X-Git-Url: https://pd.if.org/git/?a=blobdiff_plain;f=zpm-pkgfiles.c;fp=zpm-pkgfiles.c;h=0000000000000000000000000000000000000000;hb=6adc79aeafb90e90c9923b3eeedab662888927e9;hp=0a0f1d51d1343d6c636f5f8c8719bdcc61cde37a;hpb=5a5fb3563c6eaee14fb03fae46c1b5612a7c8d57;p=zpackage diff --git a/zpm-pkgfiles.c b/zpm-pkgfiles.c deleted file mode 100644 index 0a0f1d5..0000000 --- a/zpm-pkgfiles.c +++ /dev/null @@ -1,559 +0,0 @@ -#define _POSIX_C_SOURCE 200809L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* needed for S_IFMT and AT_FDCWD */ -#include - -#include - -#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; -}