+++ /dev/null
-#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;
- int striparg;
- 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);
- if (!new) {
- return NULL;
- }
- memset(new, 0, len);
-
- t = new;
-
- if (*s == 0) {
- /* path is only stripped */
- return 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;
- }
- linkval[n] = 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 & 07777;
- } else {
- file->mode = st.st_mode & 07777;
- }
-
- 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);
-
-char *pathcat(char *dir, char *path) {
- size_t dirlen = 0, pathlen = 0;
- char *cat;
-
- /* chop off trailing / on dir */
- if (dir) {
- dirlen = strlen(dir);
- while (dirlen && dir[dirlen-1] == '/') {
- dirlen--;
- }
- }
-
- if (path) {
- pathlen = strlen(path);
- while (*path && *path == '/') {
- path++;
- pathlen--;
- }
- }
-
- cat = malloc(dirlen + pathlen + 2);
- if (cat) {
- strncpy(cat, dir, dirlen);
- cat[dirlen] = '/';
- strcpy(cat+dirlen+1, path);
- }
- return cat;
-}
-
-int add_dir(struct zpm *zpm, char *path, struct opts *opt) {
- DIR *dir;
- struct dirent *de;
- struct zpm_file file = { 0 };
- int fail = 0;
-
- char *dpath = 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;
- }
-
- dpath = pathcat(path, de->d_name);
- if (!dpath) {
- zpm_seterror(zpm, "pathcat failed");
- fail = 1;
- break;
- }
-
- if (!stat_file(&file, dpath, opt)) {
- zpm_seterror(zpm, "stat %s failed: %s",
- dpath, strerror(errno));
- fail = 1;
- break;
- }
-
- if (!add_file(zpm, &file, opt)) {
- free_file(&file);
- fail = 1;
- break;
- }
- free_file(&file);
- free(dpath);
- }
- closedir(dir);
- return fail ? 0 : 1;
-}
-
-int add_file(struct zpm *zpm, struct zpm_file *file, struct opts *opt) {
- char hash[ZPM_HASH_STRLEN+1];
-
- if (file->path[0] != 0) {
- 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->type == 'r' ? file->hash : NULL,
- file->configuration,
- file->type == 'l' ? file->target : NULL
- );
-
- 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);
- fflush(stdout);
- }
- }
-
- 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, "CF:H:M:NP:S:T:cf:g:hlm:ru:vxz")) != -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 's': opt.striparg = 1; 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);
- 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 (opt.striparg) {
- opt.strip = 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;
-}