ZPKGBIN=zpm-addfile zpm-extract zpm-init zpm-vercmp zpm-stat zpm-hash \
zpm-findpkg zpm-shell zpm-soneed zpm-foreach-path zpm-parse \
- zpm-runscript zpm-soname zpm-syncfs zpm-packagehash zpm-verify \
+ zpm-script zpm-soname zpm-syncfs zpm-packagehash zpm-verify \
zpm-elftype zpm-quote zpm-note
SCRIPTS=zpm zpm-install zpm-merge zpm-list zpm-preserve zpm-test zpm-log \
zpm-contents zpm-uninstall zpm-pathmod zpm-rmpackage zpm-newpackage \
- zpm-pkg zpm-add zpm-setscript zpm-pkgfile zpm-gc
+ zpm-pkg zpm-add zpm-pkgfile zpm-gc
COMPILED=$(ZPKGBIN)
PROGRAMS=$(SCRIPTS) $(COMPILED)
zpm-extract: zpm-extract.o libzpm.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lzpm -lelf
-zpm-runscript: zpm-runscript.o libzpm.a
+zpm-script: zpm-script.o libzpm.a
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lzpm -lelf
zpm-packagehash: zpm-packagehash.o libzpm.a
#include "sqlite3.h"
#include "zpm.h"
+int zpm_script_set(struct zpm *zpm, char *pkgstr, char *phase, char *hash) {
+ char package[64];
+ char version[32];
+ int release;
+ char *insert = "insert into scripts (package,version,release,stage,hash) values (%Q,%Q,%d,%Q,%Q) on conflict (package,version,release,stage) do update set hash = excluded.hash ";
+ char *delete = "delete from scripts where package = ? and version = ? and release = ? and stage = ?";
+
+ if (!zpm || !zpm->db || !phase) {
+ return 0;
+ }
+
+ if (zpm_parse_package(pkgstr, package, version, &release)) {
+ if (hash) {
+ zpm_db_run(zpm, insert, package, version, release, phase, hash);
+ } else {
+ zpm_db_run(zpm, delete, package, version, release, phase);
+
+ }
+ }
+
+ return !zpm->error;
+}
+
int zpm_script_hash(struct zpm *zpm, char *pkgstr, char *phase, char *hash) {
char *pkgid = 0;
char *template = "select hash from scripts_pkgid where pkgid = %Q and stage = %Q";
. tap.sh
-plan 16
+plan 13
PF=test.db
pkgid=scriptrunner-1.0-1
require zpm init $PF
require zpm newpackage -f $PF $pkgid
-tryrun zpm setscript -f $PF scriptrunner-1.0-1 configure /bin/true
-tryrun zpm runscript -f $PF -p configure scriptrunner-1.0-1
-tryrun zpm setscript -f $PF scriptrunner-1.0-1 configure /bin/false
-zpm runscript -f $PF -p configure scriptrunner-1.0-1 2>/dev/null
+tryrun -v zpm script -f $PF -s -p configure scriptrunner-1.0-1 /bin/false
+zpm script -f $PF -p configure -r scriptrunner-1.0-1 2>/dev/null
failsok failure script fails
-zpm runscript -f $PF -p nosuchphase -R scriptrunner-1.0-1 2>/dev/null
+zpm script -f $PF -p nosuchphase -r -F scriptrunner-1.0-1 2>/dev/null
failsok required non-existing script fails
-tryrun zpm runscript -f $PF -p nosuchphase scriptrunner-1.0-1 2>/dev/null
cat >script <<-'EOC'
#!/bin/sh
echo $1
EOC
-tryrun zpm setscript -f $PF scriptrunner-1.0-1 configure script
-first=$(zpm runscript -f $PF -p configure -o - scriptrunner-1.0-1)
+
+tryrun zpm script -f $PF -s -p configure scriptrunner-1.0-1 script
+
+first=$(zpm script -f $PF -p configure -r -o - scriptrunner-1.0-1)
okexit first arg script
okstreq "$first" "scriptrunner-1.0-1" "first arg value"
#!/bin/sh
echo $2
EOC
-tryrun zpm setscript -f $PF scriptrunner-1.0-1 configure script
-second=$(zpm runscript -f $PF -p configure -o - scriptrunner-1.0-1 secondarg)
+
+tryrun zpm script -s -f $PF scriptrunner-1.0-1 script
+second=$(zpm script -f $PF -p configure -o - scriptrunner-1.0-1 secondarg)
okexit second arg script
okstreq "$second" "secondarg" "second arg value"
cd ..
rm -rf tmp
-
-finish
-
-rm -f $PF
if [ $runscripts -gt 0 ]; then
# TODO run pre-upgrade script if needed
# zpm runscript -p pre-upgrade $current $pkgid
- zpm runscript -f $pkgfile -p pre-install $pkgid $current
+ zpm script -f $pkgfile -p pre-install $pkgid $current
if [ $? -ne 0 ]; then
die "pre-install script for $pkgid failed"
fi
fi
if [ $runscripts -gt 0 ]; then
- zpm runscript -f $pkgfile -p post-install $pkgid $current
+ zpm script -f $pkgfile -p post-install $pkgid $current
fi
if [ -n "$current" ]; then
# TODO skip configure if not on a terminal, regardless of settings
# TODO will need force option
if [ $runconfigure -gt 0 ]; then
- zpm runscript -f $pkgfile -p configure $pkgid $current
+ zpm script -f $pkgfile -p configure $pkgid $current
+ else
+ true
fi
done
+++ /dev/null
-#define _POSIX_C_SOURCE 200809L
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <sys/mman.h>
-
-#include "zpm.h"
-
-/*
- * -f package file, otherwise localdb
- * -p phase, defaults to 'configure'
- * -s script name, defaults to /var/tmp/zpm-script
- * -r chroot to directory
- * -o script output, /var/tmp/zpm-script.out, '-' for stdout
- *
- * arg is package id
- */
-
-void usage(void) {
- fprintf(stderr, "usage: db hash file\n");
-}
-
-int run(char *program, char **args, char *output, int *status) {
- /* if stdout is a terminal, leave stdout where it goes,
- * if it's not a terminal, redirect stdout to output.
- * in either case, send stderr to output, unless null
- * if output is null or "-", just run the program
- */
- int interactive = 0;
- pid_t pid;
- int rv;
-
- errno = 0;
-
- interactive = isatty(1);
-
- pid = fork();
-
- if (pid == -1) {
- *status = 1;
- return -1;
- }
-
- if (pid == 0) {
- /* child */
- if (output && strcmp(output, "-") != 0) {
- close(2);
- rv = open(output, O_NOFOLLOW|O_TRUNC|O_CREAT|O_WRONLY,
- 0600);
- if (rv == -1) {
- perror("cannot open output file");
- }
- if (!interactive) {
- rv = dup2(2,1);
- if (rv == -1) {
- perror("unable to redirect stdout");
- exit(EXIT_FAILURE);
- }
- }
- }
-
- rv = execvp(program, args);
- if (rv == -1) {
- perror("cannot exec");
- exit(EXIT_FAILURE);
- }
- }
-
- pid = wait(status);
- if (pid == -1) {
- perror("error waiting for child");
- return -2;
- }
-
- if (WIFEXITED(*status)) {
- return WEXITSTATUS(*status);
- }
-
- return -3;
-}
-
-int main(int ac, char **av){
- struct zpm zpm;
- int rv;
- int status;
- int failures = 0;
- char *pkgstr;
- int opt;
- int required = 0;
-
- char hash[ZPM_HASH_STRLEN+1];
- char *args[4];
- char *pkgid;
-
- char *rootdir = 0;
- char *db = "/var/lib/zpm/zpm.db";
- char *script = "/var/tmp/zpm-script";
- char *output = "/var/tmp/zpm-script.out";
- char *phase = "configure";
-
- if (getenv("ZPMDB")) {
- db = getenv("ZPMDB");
- }
- /* ZPM_PACKAGE_FILE ? */
-
- rootdir = getenv("ZPM_ROOT_DIR");
-
- while ((opt = getopt(ac, av, "f:p:o:s:r:R")) != -1) {
- switch (opt) {
- case 'f': db = optarg; break;
- case 'p': phase = optarg; break;
- case 's': script = optarg; break;
- case 'o': output = optarg; break;
- case 'r': rootdir = optarg; break;
- case 'R': required = 1; break;
- default:
- usage();
- exit(EXIT_FAILURE);
- break;
- }
- }
- int argn = optind;
-
- if (argn >= ac) {
- usage();
- exit(EXIT_FAILURE);
- }
-
- pkgstr = av[argn];
-
- if (!zpm_open(&zpm, db)) {
- fprintf(stderr, "unable to open zpm database: %s\n", db);
- if (zpm.errmsg) {
- fprintf(stderr, "error detail: %s\n", zpm.errmsg);
- }
- exit(EXIT_FAILURE);
- }
-
- pkgid = zpm_findpkg(&zpm, pkgstr);
- if (pkgid) {
- if (zpm_script_hash(&zpm, pkgid, phase, hash)) {
- /* since the script file name doesn't really
- * mean anything, pass in the phase as arg 0
- */
-
- /* TODO sanitize environment ? */
- args[0] = phase;
- args[1] = pkgid;
- args[2] = 0;
- args[3] = 0;
- if (argn + 1 <= ac) {
- args[2] = av[argn+1];
- }
-
- if (rootdir) {
- if (chdir(rootdir) == -1) {
- perror("can not chdir to rootdir");
- exit(EXIT_FAILURE);
- }
- if (geteuid() == 0) {
- /* chroot is deprecated, and not in
- * posix. need to use OS/kernel
- * specific code.
- */
- fprintf(stderr, "support for chroot equivalent not supported on this OS\n");
- } else {
- fprintf(stderr, "unable to chroot as non root user\n");
- }
- } else {
- if (chdir("/") == -1) {
- perror("can not chdir to /");
- exit(EXIT_FAILURE);
- }
- }
-
- if (!zpm_extract(&zpm, hash, script, 0700)) {
- fprintf(stderr, "unable to extract script");
- exit(EXIT_FAILURE);
- }
-
- rv = run(script, args, output, &status);
- if (rv) {
- // cat(output);
- fprintf(stderr, "package %s script failed with code %d\n",
- pkgid, rv);
- }
- /* TODO log output */
- if (script) {
- unlink(script);
- }
- if (output) {
- unlink(output);
- }
- if (rv) {
- failures++;
- }
- } else {
- if (required) {
- fprintf(stderr, "no script for %s %s\n", phase, pkgid);
- failures++;
- }
- }
- free(pkgid);
- } else {
- fprintf(stderr, "unable to find package for %s in %s\n",
- pkgstr, db);
- failures++;
- }
-
- zpm_close(&zpm);
-
- return failures ? EXIT_FAILURE : EXIT_SUCCESS;
-}
--- /dev/null
+#define _POSIX_C_SOURCE 200809L
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "zpm.h"
+
+/*
+ * -f package file, otherwise localdb
+ * -p phase, defaults to 'configure'
+ * -s script name, defaults to /var/tmp/zpm-script
+ * -r chroot to directory
+ * -o script output, /var/tmp/zpm-script.out, '-' for stdout
+ *
+ * arg is package id
+ */
+
+void usage(void) {
+ fprintf(stderr, "usage: db hash file\n");
+}
+
+int setdir(char *rootdir) {
+ if (rootdir && strcmp(rootdir, "/")) {
+ if (chdir(rootdir) == -1) {
+ perror("can not chdir to rootdir");
+ return 0;
+ }
+ if (geteuid() == 0) {
+ /* chroot is deprecated, and not in posix. need to use
+ * OS/kernel specific code.
+ */
+ fprintf(stderr, "support for chroot equivalent not supported on this OS\n");
+ } else {
+ fprintf(stderr, "unable to chroot as non root user\n");
+ }
+ } else {
+ if (chdir("/") == -1) {
+ perror("can not chdir to /");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+int run(char *program, char **args, char *output, int *status) {
+ /* if stdout is a terminal, leave stdout where it goes,
+ * if it's not a terminal, redirect stdout to output.
+ * in either case, send stderr to output, unless null
+ * if output is null or "-", just run the program
+ */
+ int interactive = 0;
+ pid_t pid;
+ int rv;
+
+ errno = 0;
+
+ interactive = isatty(1);
+
+ pid = fork();
+
+ if (pid == -1) {
+ *status = 1;
+ return -1;
+ }
+
+ if (pid == 0) {
+ /* child */
+ if (output && strcmp(output, "-") != 0) {
+ close(2);
+ rv = open(output, O_NOFOLLOW|O_TRUNC|O_CREAT|O_WRONLY,
+ 0600);
+ if (rv == -1) {
+ perror("cannot open output file");
+ }
+ if (!interactive) {
+ rv = dup2(2,1);
+ if (rv == -1) {
+ perror("unable to redirect stdout");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ rv = execvp(program, args);
+ if (rv == -1) {
+ perror("cannot exec");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ pid = wait(status);
+ if (pid == -1) {
+ perror("error waiting for child");
+ return -2;
+ }
+
+ if (WIFEXITED(*status)) {
+ return WEXITSTATUS(*status);
+ }
+
+ return -3;
+}
+
+#define RUN 1
+#define SET 2
+#define LIST 3
+
+#define SOFT 1
+#define HARD 2
+
+int main(int ac, char **av){
+ struct zpm zpm;
+ int rv;
+ int status;
+ int required = 0;
+ int fail = 0;
+ char *pkgstr;
+ int opt;
+
+ char hash[ZPM_HASH_STRLEN+1];
+ char *args[4];
+ char *pkgid;
+
+ char *rootdir = 0;
+ char *db = "/var/lib/zpm/zpm.db";
+ char *script = "/var/tmp/zpm-script";
+ char *output = "/var/tmp/zpm-script.out";
+ char *phase = 0;
+ int quiet = 0;
+ int scriptishash = 0;
+ int mode = RUN;
+ int all = 0;
+
+ if (getenv("ZPMDB")) {
+ db = getenv("ZPMDB");
+ }
+ /* ZPM_PACKAGE_FILE ? */
+
+ rootdir = getenv("ZPM_ROOT_DIR");
+
+ /* run, set, show, hash */
+ /* set -S, if -H set the hash, output hash, unless quiet
+ * show: -o, or stdout,
+ * All modes: [-f pkgfile] default to zpmdb
+ * All modes: [-p phase], default to configure
+ * All modes: [-R rootdir], chdir, attempt to chroot
+ * All modes: [-N], required, error if no such script
+ *
+ * run: zpm-script -r -p foo <pkgid args...>
+ * set: zpm-script -s <pkgid [script]>
+ * set: zpm-script -s -h <pkgid [hash]>
+ * show: zpm-script -l [-a] [-o outfile] <pkgid>
+ * show hash: zpm-script -lh <pkgid>
+ */
+ while ((opt = getopt(ac, av, "f:p:rslRFho:S:q")) != -1) {
+ switch (opt) {
+ case 'f': db = optarg; break;
+ case 'p': phase = optarg; break;
+ case 'r': mode = RUN; break;
+ case 's': mode = SET; break;
+ case 'l': mode = LIST; break;
+ case 'R': rootdir = optarg; break;
+ case 'F': required = 1; break;
+ case 'a': all = 1; break;
+
+ case 'h': scriptishash = 1; break;
+ case 'o': output = optarg; break;
+ case 'S': script = optarg; break;
+ case 'q': quiet = 1;
+
+ default:
+ usage();
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+ int argn = optind;
+
+ if (argn >= ac) {
+ usage();
+ exit(EXIT_FAILURE);
+ }
+
+ if (!zpm_open(&zpm, db)) {
+ fprintf(stderr, "unable to open zpm database: %s\n", db);
+ if (zpm.errmsg) {
+ fprintf(stderr, "error detail: %s\n", zpm.errmsg);
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ /* first non option arg is always a package id */
+ pkgstr = av[argn];
+ pkgid = zpm_findpkg(&zpm, pkgstr);
+
+ if (!pkgid) {
+ fprintf(stderr, "no package for %s\n", pkgstr);
+ zpm_close(&zpm);
+ exit(EXIT_FAILURE);
+ }
+
+ argn++;
+
+ if (mode == SET) {
+ char *sethash = 0;
+ char *setscript = 0;
+ int rv = 0;
+
+ if (!phase) {
+ phase = "configure";
+ }
+
+ if (argn < ac) {
+ if (scriptishash) {
+ sethash = av[argn];
+ } else {
+ setscript = av[argn];
+ }
+ }
+
+ if (setscript) {
+ rv = zpm_import(&zpm,setscript,0,hash);
+ if (!rv) {
+ fprintf(stderr, "unable to import %s\n",
+ setscript);
+ fail = HARD;
+ } else {
+ sethash = hash;
+ }
+ }
+
+ if (!fail && !zpm_script_set(&zpm,pkgid,phase,sethash)) {
+ fprintf(stderr, "unable to set %s script hash %s\n",
+ pkgid,
+ sethash ? sethash : "null");
+ fprintf(stderr, "zpm error: %s\n", zpm.errmsg);
+ fail = HARD;
+ }
+ } else if (mode == LIST) {
+ if (!zpm_script_hash(&zpm, pkgid, phase, hash)) {
+ fail = SOFT;
+ } else if (scriptishash) {
+ printf("%s\n", hash);
+ } else {
+ if (!output) {
+ output = "-";
+ }
+ if (!zpm_extract(&zpm, hash, output, 0700)) {
+ fail = HARD;
+ }
+ }
+ } else {
+ /* run a script */
+ if (!phase) {
+ phase = "configure";
+ }
+
+ if (!output) {
+ output = "/var/tmp/zpm-script.out";
+ }
+
+ if (!script) {
+ script = "/var/tmp/zpm-script";
+ }
+
+ /* since the script file name doesn't really
+ * mean anything, pass in the phase as arg 0
+ */
+ /* TODO sanitize environment ? */
+ args[0] = phase;
+ args[1] = pkgid;
+ args[2] = 0;
+ args[3] = 0;
+
+ if (argn <= ac) {
+ args[2] = av[argn];
+ }
+
+ if (!zpm_script_hash(&zpm, pkgid, phase, hash)) {
+ fail = SOFT;
+ goto cleanup;
+ }
+
+ if (!setdir(rootdir)) {
+ fail = HARD;
+ goto cleanup;
+ }
+
+ if (!zpm_extract(&zpm, hash, script, 0700)) {
+ fprintf(stderr, "unable to extract script");
+ fail = HARD;
+ goto cleanup;
+ }
+
+ rv = run(script, args, output, &status);
+ if (rv) {
+ fprintf(stderr, "package %s script failed with code %d\n",
+ pkgid, rv);
+ fail = HARD;
+ }
+
+ /* TODO log output */
+ if (script) {
+ unlink(script);
+ }
+ if (output) {
+ unlink(output);
+ }
+ }
+
+cleanup:
+ free(pkgid);
+ zpm_close(&zpm);
+
+ return (fail == HARD || (required && fail)) ? EXIT_FAILURE : 0;
+
+}
+++ /dev/null
-#!/bin/sh
-
-# zpm add -f pkgfile pkgid [ files ]
-
-# no package file? take from ZPM_PACKAGE_FILE
-# no pkgid ? take from ZPM_PACKAGE_ID
-# no id impossible
-
-die() {
- echo $* 1>&2
- exit 1
-}
-
-while getopts :f: opt; do
- case $opt in
- f) pkgfile="$OPTARG" ;;
- *) echo 'zpm-setscript unknown option' $opt; exit 1 ;;
- esac
-done
-shift $((OPTIND - 1))
-
-pkgid=$1
-shift
-
-if [ -z "$pkgid" ]; then
- die "must specify pkgid"
-fi
-
-eval "$(zpm parse -E $pkgid)"
-
-if [ -z "$pkgfile" ]; then
- pkgfile=$ZPM_PACKAGE_FILE
-fi
-
-# cases R = full package id, F = specified package file
-
-# immediate error
-# --- 000 error, must specify something
-if [ -z "$release" ] && [ -z "$pkgfile" ]; then
- die must specify package file or complete package id
-fi
-
-# try to get from package file
-if [ -z "$release" ]; then
- pkgid=$(zpm findpkg -f $pkgfile $pkgid)
- if [ -z "$pkgid" ]; then
- die cannot find package id
- fi
- eval "$(zpm parse -E $pkgid)"
-fi
-
-# --F 001 error, wouldn't know which pkgid to create, could derive from file?
-if [ -z "$release" ]; then
- die must specify complete package id
-fi
-
-#echo "have '$pkgid' '$pkgfile'"
-
-# set file from pkgid
-# -R- 010 set file from pkgid, create in file, error if no file
-if [ -z "$pkgfile" ]; then
- pkgfile="$pkgid.zpm"
-fi
-
-# will now be one of these
-# -RF 011 create package in file, error if file doesn't exist
-if [ ! -f "$pkgfile" ]; then
- die $pkgfile does not exist
-fi
-
-set -e
-
-if [ "$idempotent" = 1 ]; then
- idempotent='or ignore'
-fi
-
-package=$(zpm quote "$name")
-pkgver=$(zpm quote "$version")
-pkgrel=$(zpm quote "$release")
-
-# args are stage and script
-
-addscript() (
- stage=$1
- path=$2
-
- #echo adding $path
- if [ ! -f "$script" ]; then
- die "$script is not a regular file"
- fi
- hash=$(zpm addfile $pkgfile "$path")
- if [ $? -ne 0 ]; then
- die "zpm addfile failed ($?): $pkgfile $path"
- fi
- #echo adding script $hash $path
- hash=$(zpm quote "$hash")
-
- stage=$(zpm quote "$stage")
-
- #cat <<EOS
- zpm shell $pkgfile <<EOS
-PRAGMA foreign_keys = ON;
-begin;
-insert or replace into scripts (package,version,release,stage,hash)
-values ('$package', '$pkgver', $pkgrel, '$stage', '$hash');
-commit;
-EOS
-
-#printf "%s %s%s\n" $path $rpath ${target:+" -> $target"}
-#printf "%s\n" $path
-)
-
-removescript() (
- stage=$1
- stage=$(zpm quote "$stage")
-
- #cat <<EOS
- zpm shell $pkgfile <<EOS
-PRAGMA foreign_keys = ON;
-begin;
-delete from scripts
-where package = '$package' and version = '$pkgver' and release = $pkgrel
-and stage = '$stage'
-;
-commit;
-EOS
-
-#printf "%s %s%s\n" $path $rpath ${target:+" -> $target"}
-#printf "%s\n" $path
-)
-
-showscript() (
- stage=$1
- stage=$(zpm quote "$stage")
- hash=$(zpm shell $pkgfile "select hash from scripts_pkgid
- where pkgid = '$pkgid' and stage = '$stage'")
- if [ -z "$hash" ]; then
- die "no script for $stage $pkgid"
- fi
- zpm extract $pkgfile "$hash" -
-)
-
-# TODO better syntax for showing the script
-# TODO a way to set the script hash directly
-while [ $# -gt 1 ]; do
- stage=$1
- script=$2
- shift 2
-
- if [ "$script" = '--' ]; then
- removescript "$stage"
- elif [ "$script" = '-' ]; then
- showscript "$stage"
- else
- addscript "$stage" "$script"
- fi
-
-done
int (*callback)(void *f, int ncols, char **vals, char **cols),
void *data, char **errmsg);
-
int zpm_script_hash(struct zpm *zpm, char *pkgstr, char *phase, char *hash);
+int zpm_script_set(struct zpm *zpm, char *pkgstr, char *phase, char *hash);
+
int zpm_package_hash(struct zpm *zpm, char *pkgid, char *hash);
int zpm_package_sethash(struct zpm *zpm, char *pkgid, char *hash);