package

simple and robust package manager
Log | Files | Refs | README

commit 26543ba1ff5e186039c41f086aa4649d972eee22
parent 89c7613377fe8285d0369c4ceaeb15e150d839a5
Author: Josuah Demangeon <mail@josuah.net>
Date:   Wed, 16 Jan 2019 23:30:51 +0100

Fix pack-build and pack-get, rename all pack* in package*

Diffstat:
MMakefile | 37+++++++++++++++++++------------------
Dbin/pack-ftp | 10----------
Dbin/pack-http | 11-----------
Rbin/pack-cvs -> bin/package-cvs | 0
Abin/package-ftp | 2++
Rbin/pack-git -> bin/package-git | 0
Abin/package-http | 21+++++++++++++++++++++
Mfmt.c | 25+++++++++++++++++--------
Mfmt.h | 1+
Dpack-add.c | 103-------------------------------------------------------------------------------
Dpack-build.c | 322-------------------------------------------------------------------------------
Dpack-dep.c | 56--------------------------------------------------------
Dpack-get.c | 143-------------------------------------------------------------------------------
Dpack-tree.c | 94-------------------------------------------------------------------------------
Dpack.c | 211-------------------------------------------------------------------------------
Dpack.h | 28----------------------------
Apackage-add.c | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage-build | 0
Apackage-build.c | 321+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage-dep | 0
Apackage-dep.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage-get | 0
Apackage-get.c | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage-install.c | 36++++++++++++++++++++++++++++++++++++
Apackage-tree | 0
Apackage-tree.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.c | 211+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.h | 22++++++++++++++++++++++
Mtai.c | 4++--
Mtai.h | 16+++++++---------
Atain.c | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atain.h | 29+++++++++++++++++++++++++++++
32 files changed, 1201 insertions(+), 1015 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,5 +1,5 @@ -bin = pack-build pack-dep pack-get pack-tree # pack-add -obj = pack.o buffer.o fmt.o stat.o hier.o log.o mem.o str.o stralloc.o forkexec.o tai.o +bin = package-build package-dep package-get package-tree # package-add +obj = package.o buffer.o fmt.o stat.o hier.o log.o mem.o str.o stralloc.o forkexec.o tai.o tain.o .PHONY: all all: ${bin} @@ -14,20 +14,20 @@ install: all cp -r bin ${PREFIX} cp ${bin} ${PREFIX}/bin -pack-build: pack-build.o ${obj} - ./make-bin $@ pack-build.o ${obj} +package-build: package-build.o ${obj} + ./make-bin $@ package-build.o ${obj} -pack-dep: pack-dep.o ${obj} - ./make-bin $@ pack-dep.o ${obj} +package-dep: package-dep.o ${obj} + ./make-bin $@ package-dep.o ${obj} -pack-add: pack-add.o ${obj} - ./make-bin $@ pack-add.o ${obj} +package-add: package-add.o ${obj} + ./make-bin $@ package-add.o ${obj} -pack-get: pack-get.o ${obj} - ./make-bin $@ pack-get.o ${obj} +package-get: package-get.o ${obj} + ./make-bin $@ package-get.o ${obj} -pack-tree: pack-tree.o ${obj} - ./make-bin $@ pack-tree.o ${obj} +package-tree: package-tree.o ${obj} + ./make-bin $@ package-tree.o ${obj} .c.o: ./make-o $< @@ -38,14 +38,15 @@ forkexec.o: forkexec.c open.h forkexec.h hier.o: hier.c hier.h open.h str.h stralloc.h log.o: log.c buffer.h log.h mem.o: mem.c mem.h -pack-add.o: pack-add.c buffer.h env.h fmt.h genalloc.h log.h open.h pack.h stat.h str.h -pack-build.o: pack-build.c buffer.h env.h fmt.h forkexec.h hier.h hier.h log.h open.h pack.h stat.h str.h stralloc.h tai.h -pack-dep.o: pack-dep.c buffer.h env.h stat.h genalloc.h log.h pack.h str.h -pack-get.o: pack-get.c buffer.h env.h forkexec.h hier.h lock.h log.h open.h pack.h stat.h stralloc.h -pack-tree.o: pack-tree.c buffer.h env.h log.h open.h pack.h stat.h stralloc.h -pack.o: pack.c buffer.h env.h fmt.h forkexec.h genalloc.h mem.h open.h pack.h stralloc.h lock.h tai.h +package-add.o: package-add.c buffer.h env.h fmt.h genalloc.h log.h open.h package.h stat.h str.h +package-build.o: package-build.c buffer.h env.h fmt.h forkexec.h hier.h hier.h log.h open.h package.h stat.h str.h stralloc.h tain.h +package-dep.o: package-dep.c buffer.h env.h stat.h genalloc.h log.h package.h str.h +package-get.o: package-get.c buffer.h env.h forkexec.h hier.h lock.h log.h open.h package.h stat.h stralloc.h +package-tree.o: package-tree.c buffer.h env.h log.h open.h package.h stat.h stralloc.h +package.o: package.c buffer.h env.h fmt.h forkexec.h genalloc.h mem.h open.h package.h stralloc.h lock.h tai.h stat.o: stat.c stat.h str.o: str.c str.h stralloc.o: stralloc.c mem.h fmt.h str.h stralloc.h tai.o: tai.c tai.h +tain.o: tain.c tain.h uint64.h fmt.h uint64.o: uint64.c uint64.h diff --git a/bin/pack-ftp b/bin/pack-ftp @@ -1,10 +0,0 @@ -#!/bin/sh -e - -wget --no-check-certificate -O- "$2" | pack-extract "$2" | -case $1 in -(*.tgz|*.tar.gz) gzip -d - ;; -(*.tbz|*.tar.bz2) bzip2 -d - ;; -(*.txz|*.tar.xz) xz -d - ;; -(*.tlz|*.tar.lz) lzip -d - ;; -(*) exit 1 ;; -esac diff --git a/bin/pack-http b/bin/pack-http @@ -1,11 +0,0 @@ -#!/bin/sh -e - -wget --no-check-certificate -O- "$1" | pack-extract "$1" | -case $1 in -(*.tgz|*.tar.gz) gzip -d - ;; -(*.tbz|*.tar.bz2) bzip2 -d - ;; -(*.txz|*.tar.xz) xz -d - ;; -(*.tlz|*.tar.lz) lzip -d - ;; -(*) exit 1 ;; -esac - diff --git a/bin/pack-cvs b/bin/package-cvs diff --git a/bin/package-ftp b/bin/package-ftp @@ -0,0 +1 @@ +package-http+ \ No newline at end of file diff --git a/bin/pack-git b/bin/package-git diff --git a/bin/package-http b/bin/package-http @@ -0,0 +1,21 @@ +#!/bin/sh -ex + +cd "$(mktemp -d)" +trap "rm -rf '$PWD'" EXIT INT TERM + +wget --no-check-certificate -O compressed "$2" + +case $2 in +(*.tgz|*.tar.gz) gzip -cd - >tar <compressed ;; +(*.tbz|*.tar.bz2) bzip2 -cd - >tar <compressed ;; +(*.txz|*.tar.xz) xz -cd - >tar <compressed ;; +(*.tlz|*.tar.lz) lzip -cd - >tar <compressed ;; +(*) exit 1 ;; +esac +rm compressed + +tar -x -f tar +rm tar + +! cd * +tar -c . diff --git a/fmt.c b/fmt.c @@ -135,24 +135,18 @@ fmt_utf8(char *dest, uint32_t u) return 1 + n; } -static inline char -hex(char c) -{ - if (c >= 10) return 'a' + c - 10; - return '0' + c; -} - size_t fmt_xlong(char *buf, unsigned long u) { size_t n = 0; unsigned long x; + char *ascii = "0123456789abcdef"; x = u; do { x >>= 4; ++n; } while (x); if (!buf) return n; buf += n; - x = u; do { *--buf = hex(x & 15); x >>= 4; } while (x); + x = u; do { *--buf = ascii[x & 15]; x >>= 4; } while (x); return n; } @@ -169,3 +163,18 @@ fmt_xlong0(char *buf, unsigned long i, size_t pad) if (buf) fmt_xlong(buf, i); return n; } + +size_t +fmt_xbuf(char const *pack, size_t n, char *s) +{ + char *ascii = "0123456789abcdefghijklmnopqrstuvwxyz"; + + if (!s) return n * 2; + + for (size_t i = 0; i < n; ++i) { + s[i * 2] = ascii[pack[i] >> 4]; + s[i * 2 + 1] = ascii[pack[i] & 0x0f]; + } + + return n * 2; +} diff --git a/fmt.h b/fmt.h @@ -14,6 +14,7 @@ size_t fmt_strn(char *, size_t, char const *); size_t fmt_ulong(char *, unsigned long); size_t fmt_ulong0(char *, unsigned long, size_t); size_t fmt_utf8(char *, uint32_t); +size_t fmt_xbuf(char const *, size_t, char *); size_t fmt_xlong(char *, unsigned long); size_t fmt_xlong0(char *, unsigned long, size_t); diff --git a/pack-add.c b/pack-add.c @@ -1,103 +0,0 @@ -#include <sys/stat.h> -#include <errno.h> -#include <unistd.h> - -#include "buffer.h" -#include "env.h" -#include "fmt.h" -#include "genalloc.h" -#include "log.h" -#include "open.h" -#include "pack.h" -#include "stat.h" -#include "str.h" - -void -die_nomem(void) -{ - log_diesys1(100, "malloc"); -} - -void -step(pack const *p, char const *cmd char const *dir, char const *sub) -{ - int x; - char fmt[4]; - - buffer_puts(buffer_2, " "); - buffer_puts(buffer_2, sub); - buffer_puts(buffer_2, " "); - buffer_flush(buffer_2); - - if ((x = pack_step(p, cmd, log, dir, sub)) == 0) return; - - fmt_long(fmt, x); - buffer_puts(buffer_2, "< exit "); - buffer_puts(buffer_2, fmt); - buffer_puts(buffer_2, "\n"); - buffer_flush(buffer_2); - - if (dir && !pack_remove(p, dir, char const *sub)) - log_errsys6("deleting .../", sub, "/", p->name, "/", p->ver); - exit(100); -} - -int -main(int argc, char **argv) -{ - genalloc ga; - size_t i; - pack p; - char *dir; - char *def; - - if (argc != 2) log_usage(*argv, "package[/version]"); - ++argv; - - dir = env_get("PACK_DIR"); if (!dir) dir = PACK_DIR; - def = env_get("PACK_DEF"); if (!def) def = PACK_DEF; - - if (!stat_isdir(def)) log_diesys1(101, def); - - i = pack_scan(&p, *argv); - if (i == 0 || (*argv)[i] != '\0') - log_die2(1, "invalid package name: ", *argv); - - if (!pack_version(&p, def)) - log_diesys3(101, "could not get ", *argv," version"); - - genalloc_init(&ga); - if (!pack_dep(&p, &ga, def)) - log_diesys1(103, "could not resolve package dependencies"); - if (!genalloc_append(&ga, p)) die_nomem(); - - for (i = 0; i < genalloc_len(&ga, pack); ++i) - { - pack *p = genalloc_get(&ga, pack, i); - char fmt[PACK_FMT + 80]; - - buffer_puts(buffer_2, " "); - fmt_fill(fmt, sizeof fmt, p->name, 25); - buffer_puts(buffer_2, fmt); - buffer_puts(buffer_2, " "); - fmt_fill(fmt, sizeof fmt, p->ver, 10); - buffer_puts(buffer_2, fmt); - buffer_puts(buffer_2, " "); - buffer_flush(buffer_2); - - if (pack_isdone(p, dir, "run")) goto step_install; - if (pack_isdone(p, dir, "src")) goto step_build; - if (pack_isdone(p, dir, "tar")) goto step_tar; - - step(p, "pack-get", log, tar); -step_build: - step(p, "pack-build", log, out); -step_install: - step(p, "pack-install", log, NULL); - buffer_puts(buffer_2, "\n"); - buffer_flush(buffer_2); - } - genalloc_free(&ga); - - return 0; -} diff --git a/pack-build.c b/pack-build.c @@ -1,322 +0,0 @@ -#include <sys/types.h> -#include <sys/dirent.h> -#include <sys/stat.h> -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <stdio.h> - -#include "buffer.h" -#include "env.h" -#include "fmt.h" -#include "forkexec.h" -#include "hier.h" -#include "hier.h" -#include "log.h" -#include "open.h" -#include "pack.h" -#include "stat.h" -#include "str.h" -#include "stralloc.h" -#include "tai.h" - -static int -untar(void) -{ - char const *argv[] = { "tar", "-x", "-f", "../../source.tar", NULL }; - int fd; - int x; - - if ((fd = open_trunc("../log/1-untar")) == -1) return 0; - x = forkexec_wait_redir(argv, fd); - close(fd); - return x; -} - -static int -patch(pack const *p, char *def) -{ - char const *argv[] = { "patch", "-N", NULL }; - char const *d[2]; - stralloc sa; - size_t n; - size_t m; - DIR *dp = NULL; - struct dirent *de; - int i; - int fd = -1; - int ret = 0; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - n = sa.n; - - if ((fd = open_trunc("../log/2-patch")) == -1) goto err; - d[0] = "default"; - d[1] = p->ver; - for (i = 0; i < 2; ++i) { - sa.n = n; - if (!stralloc_cats(&sa, d[i])) goto err; - if (!stralloc_cats(&sa, "/patch/")) goto err; - m = sa.n; - if (!stralloc_cat0(&sa)) goto err; - dp = opendir(sa.x); - if (dp == NULL) { - if (errno == ENOTDIR || errno == ENOENT) continue; - goto err; - } - while ((de = readdir(dp)) != NULL) { - if (str_equal(de->d_name, ".")) continue; - if (str_equal(de->d_name, "..")) continue; - - sa.n = m; - if (!stralloc_cats(&sa, de->d_name)) goto err; - if (!stralloc_cat0(&sa)) goto err; - close(0); - if (open_read(sa.x) == -1) goto err; - if (write(fd, "=== patch ===\n", 23) == -1) goto err; - if (forkexec_wait_redir(argv, fd) != 0) goto err; - if (write(fd, "\n", 1) == -1) goto err; - } - closedir(dp); - } - - ret = 1; -err: - close(0); - stralloc_free(&sa); - if (fd >= 0) { write(fd, "=== end ===\n", 12); close(fd); } - if (ret == 0) closedir(dp); - return ret; -} - -static int -data(pack const *p, char const *def) -{ - stralloc sa = STRALLOC_ZERO; - size_t n; - int ret = 0; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - - if (close(open_trunc("../log/3-data")) == -1) goto err; - - n = sa.n; - if (!stralloc_cats(&sa, "default/data")) goto err; - if (!stralloc_cat0(&sa)) goto err; - if (stat_isdir(sa.x)) if (!hier_copy(sa.x, ".")) goto err; - - sa.n = n; - if (!stralloc_cats(&sa, p->ver)) goto err; - if (!stralloc_cats(&sa, "/data")) goto err; - if (!stralloc_cat0(&sa)) goto err; - if (stat_isdir(sa.x)) if (!hier_copy(sa.x, ".")) goto err; - - ret = 1; -err: - stralloc_free(&sa); - return ret; -} - -static int -build(pack const *p, char const *def) -{ - stralloc sa; - char const *argv[] = { NULL, NULL }; - size_t n; - int fd = - 1; - int ret = -1; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - - if ((fd = open_trunc("../log/4-build")) == -1) goto err; - - n = sa.n; - if (!stralloc_cats(&sa, p->ver)) goto err; - if (!stralloc_cats(&sa, "/build")) goto err; - if (!stralloc_cat0(&sa)) goto err; - argv[0] = sa.x; - if (stat_isfile(sa.x)) { ret = forkexec_wait_redir(argv, fd); goto err; } - - sa.n = n; - if (!stralloc_cats(&sa, "default/build")) goto err; - if (!stralloc_cat0(&sa)) goto err; - argv[0] = sa.x; - if (stat_isfile(sa.x)) { ret = forkexec_wait_redir(argv, fd); goto err; } - -err: - stralloc_free(&sa); - if (fd >= 0) close(fd); - return ret; -} - -static int -pack_env_set(char const *name, char const *path) -{ - char buf[NAME_MAX]; - int len; - - for (len = 0; name[len] != '\0'; ++len) - buf[len] = isalnum(name[len]) ? name[len] : '_'; - buf[len] = '\0'; - return env_set(buf, path); -} - -static int -env(pack *p, char const *def, char const *pkg, char const *id) -{ - stralloc sa = STRALLOC_ZERO; - stralloc line = STRALLOC_ZERO; - buffer b; - char buf[1024]; - size_t r; - size_t n; - int fd = -1; - int ret = 0; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, pkg)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->ver)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, id)) goto err; - if (!stralloc_cats(&sa, "/build")) goto err; - if (!stralloc_cat0(&sa)) goto err; - if (!pack_env_set("PREFIX", sa.x)) goto err; - - errno = 0; - fd = pack_opendepfile(p, def); - if (fd == -1) { ret = (errno == ENOTDIR || errno == ENOENT); goto err; } - - stralloc_init(&line); - buffer_init(&b, &read, fd, buf, sizeof buf); - while (stralloc_zero(&line), (r = buffer_getline(&b, &line)) > 0) - { - pack new; - - line.n -= (line.x[line.n - 1] == '\n'); - if (!stralloc_cat0(&line)) goto err; - n = pack_scan(&new, line.x); if (n == 0 || line.x[n] != '\0') goto err; - if (!pack_version(&new, def)) goto err; - - stralloc_zero(&sa); - if (!stralloc_cats(&sa, pkg)) - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, new.name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, new.ver)) goto err; - if (!stralloc_cats(&sa, "/current/build")) goto err; - if (!stralloc_cat0(&sa)) goto err; - if (!pack_env_set(new.name, sa.x)) goto err; - } - ret = (r == 0); -err: - stralloc_free(&sa); - stralloc_free(&line); - if (fd >= 0) close(fd); - return ret; -} - -void -usage(char const *argv0, char const *param) -{ - log_err2("missing parameter: ", param); - log_usage(argv0, "-p pkgdir -d defdir package[/version]"); -} - -int -main(int argc, char **argv) -{ - pack p; - tai t; - char *def; - char *pkg; - char **av = argv; - char id[50 + PACK_FMT]; - int x; - - (void)argc; - - while (*++av) { - if (str_equal(*av, "-d")) { if (!(def = *++av)) break; continue; } - if (str_equal(*av, "-p")) { if (!(pkg = *++av)) break; continue; } - break; - } - - if (!def) usage(*argv, "-d"); - if (!pkg) usage(*argv, "-p"); - if (!*av) usage(*argv, "package[/version]"); - - if (!stat_isdir(def)) log_diesys1(101, def); - if (!stat_isdir(pkg)) log_diesys1(101, pkg); - - tai_now(&t); - id[0] = '@'; - id[fmt_xlong(id + 1, tai_approx(&t)) + 1] = '\0'; - - if (chdir(pkg) == -1) - log_diesys2(101, "chdir ", pkg); - if ((*av)[pack_scan(&p, *av)] != '\0') - log_diesys2(1, "invalid package format: ", *av); - if (mkdir(p.name, 075) == -1 && errno != EEXIST) - log_diesys4(101, "mkdir ", pkg, "/", p.name); - if (chdir(p.name) == -1) - log_diesys4(101, "chdir ", pkg, "/", p.name); - if (!pack_version(&p, def)) - log_diesys4(101, "version ", def, "/", p.name); - if (mkdir(p.ver, 075) == -1 && errno != EEXIST) - log_diesys6(101, "mkdir ", pkg, "/", p.name, "/", p.ver); - if (chdir(p.ver) == -1) - log_diesys6(101, "chdir ", pkg, "/", p.name, "/", p.ver); - if (mkdir(id, 075) == -1 && errno != EEXIST) - log_diesys8(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id); - if (chdir(id) == -1) - log_diesys8(101, "chdir ", pkg, "/", p.name, "/", p.ver, "/", id); - if (mkdir("build", 075) == -1 && errno != EEXIST) - log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/build"); - if (mkdir("log", 075) == -1 && errno != EEXIST) - log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/log"); - if (mkdir("source", 075) == -1 && errno != EEXIST) - log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/source"); - if (symlink(id, "latest") == -1 && errno != EEXIST) - log_diesys9(101, "symlink ", pkg, "/", p.name, "/", p.ver, "/", id, "/latest"); - if (rename("latest", "../latest") == -1 && errno != EEXIST) - log_diesys7(101, "rename ", pkg, "/", p.name, "/", p.ver, "/latest"); - if (chdir("source") == -1) - log_diesys4(101, "could not change directory to ", pkg, "/", p.name); - if ((x = untar()) != 0) { - char fmt[50]; - fmt_long(fmt, x); - log_die4(100, "tar of ", p.name, " exited ", fmt); - } - if (!patch(&p, def)) - log_diesys3(100, "patching ", p.name, "'s source"); - if (!data(&p, def)) - log_diesys6(100, "copying ", p.name, "'s data from ", def, " to ", pkg); - if (!env(&p, def, pkg, id)) - log_diesys2(100, "could not set environment variables for ", *argv); - if ((x = build(&p, def)) != 0) { - char fmt[50]; - fmt_long(fmt, x); - log_die4(100, "build script of ", p.name, " exited ", fmt); - } - if (symlink(id, "../current") == -1 && errno != EEXIST) - log_diesys9(101, "symlink ", pkg, "/", p.name, "/", p.ver, "/", id, "/current"); - if (rename("../current", "../../current") == -1 && errno != EEXIST) - log_diesys7(101, "rename ", pkg, "/", p.name, "/", p.ver, "/current"); - - return 0; -} diff --git a/pack-dep.c b/pack-dep.c @@ -1,56 +0,0 @@ -#include <sys/stat.h> -#include <errno.h> -#include <unistd.h> - -#include "buffer.h" -#include "env.h" -#include "stat.h" -#include "genalloc.h" -#include "log.h" -#include "pack.h" -#include "str.h" - -int -main(int argc, char **argv) -{ - (void)argc; - (void)argv; - char *def; - genalloc ga; - size_t i; - size_t n; - pack p; - - if (argc != 2) log_usage(*argv, "package[/version]"); - ++argv; - - def = env_get("PACK_DEF"); if (!def) def = PACK_DEF; - - if (!stat_isdir(def)) log_diesys1(101, def); - - n = pack_scan(&p, *argv); - if (n == 0 || (*argv)[n] != '\0') - log_die2(1, "invalid package name: ", *argv); - - if (!pack_version(&p, def)) - log_diesys3(103, "could not get ", *argv," version"); - - genalloc_init(&ga); - if (!pack_dep(&p, &ga, def)) - log_diesys1(103, "could not resolve package dependencies"); - if (!genalloc_append(&ga, p)) log_diesys1(103, "malloc"); - - for (i = 0; i < genalloc_len(&ga, pack); ++i) { - char fmt[PACK_FMT]; - pack *p = genalloc_get(&ga, pack, i); - - pack_fmt(p, fmt); - buffer_puts(buffer_1, fmt); - buffer_putc(buffer_1, '\n'); - } - buffer_flush(buffer_1); - - genalloc_free(&ga); - - return 0; -} diff --git a/pack-get.c b/pack-get.c @@ -1,143 +0,0 @@ -#include <unistd.h> -#include <stdio.h> - -#include "buffer.h" -#include "env.h" -#include "forkexec.h" -#include "hier.h" -#include "lock.h" -#include "log.h" -#include "open.h" -#include "pack.h" -#include "stat.h" -#include "stralloc.h" - -int -get(pack const *p, char const *cmd, char const *url) -{ - char const *argv[] = { NULL, NULL, NULL, NULL }; - char fmt[PACK_FMT]; - stralloc sa; - - stralloc_init(&sa); - - log_info2("trying mirror ", url); - - pack_fmt(p, fmt); - argv[0] = cmd; - argv[1] = fmt; - argv[2] = url; - argv[3] = NULL; - if ((forkexec_wait(argv)) != 0) - { - log_err4("downloading package ", p->name, "/", p->ver); - return 0; - } - - return 1; -} - -void -die_nomem() -{ - log_diesys1(100, "malloc"); -} - -void -usage(char const *argv0, char const *param) -{ - log_err2("missing parameter: ", param); - log_usage(argv0, "-p pkgdir -d defdir package[/version]"); -} - -int -main(int argc, char **argv) -{ - stralloc sa; - pack p; - buffer b; - char buf[1024]; - char *def = NULL; - char *pkg = NULL; - char *cmd = NULL; - char **av = argv; - int fd = -1; - size_t n; - size_t r; - - (void)argc; - - while (*++av) { - if (str_equal(*av, "-p")) { if (!(pkg = *++av)) break; continue; } - if (str_equal(*av, "-d")) { if (!(def = *++av)) break; continue; } - break; - } - - if (!def) usage(*argv, "-d"); - if (!pkg) usage(*argv, "-p"); - if (!*av) usage(*argv, "package[/version]"); - - if (!stat_isdir(def)) log_diesys1(101, def); - - n = pack_scan(&p, *av); - if ((*av)[n] != '\0') - log_die2(1, "invalid package format: ", *argv); - if (!pack_version(&p, def)) - log_diesys2(101, "pack_version ", p.name); - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) die_nomem(); - if (!stralloc_cats(&sa, "/")) die_nomem(); - if (!stralloc_cats(&sa, p.name)) die_nomem(); - if (!stralloc_cats(&sa, "/")) die_nomem(); - if (!stralloc_cats(&sa, p.ver)) die_nomem(); - if (!stralloc_cats(&sa, "/uri")) die_nomem(); - if (!stralloc_cat0(&sa)) die_nomem(); - fd = open_read(sa.x); if (fd == -1) die_nomem(); - - stralloc_zero(&sa); - if (!stralloc_cats(&sa, pkg)) die_nomem(); - if (!stralloc_cats(&sa, "/")) die_nomem(); - if (!stralloc_cats(&sa, p.name)) die_nomem(); - if (!stralloc_cats(&sa, "/")) die_nomem(); - if (!stralloc_cats(&sa, p.ver)) die_nomem(); - if (!stralloc_cat0(&sa)) die_nomem(); - if (!hier_mkdir(sa.x, 0750)) - log_diesys2(101, "mkdir ", sa.x); - if (chdir(sa.x) == -1) - log_diesys2(101, "chdir ", sa.x); - - sa.n--; - if (close(1) == -1 || dup(open_trunc("source.tmp")) == -1) - log_diesys3(100, "redirect tar output to ", sa.x, "/source.tmp"); - if (!lock_exclusive(1)) - log_diesys3(100, "flock ", sa.x, "/source.tmp"); - if (close(2) == -1 || dup(open_trunc("source.log")) == -1) - log_diesys3(100, "redirect err output to ", sa.x, "/source.log"); - - buffer_init(&b, &read, fd, buf, sizeof buf); - while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa)) > 0) - { - cmd = NULL; - - if (sa.x[sa.n - 1] == '\n') --sa.n; - if (!stralloc_cat0(&sa)) die_nomem(); - if (str_start(sa.x, "http://")) cmd = "pack-http"; - if (str_start(sa.x, "https://")) cmd = "pack-http"; - if (str_start(sa.x, "ftp://")) cmd = "pack-ftp"; - if (str_start(sa.x, "ftps://")) cmd = "pack-ftps"; - if (str_start(sa.x, "git://")) cmd = "pack-git"; - if (str_start(sa.x, "cvs://")) cmd = "pack-cvs"; - if (!cmd) log_warn2("no handler found for downloading ", sa.x); - else if (get(&p, cmd, sa.x)) break; - } - if (r < 0) log_errsys1("buffering"); - if (!cmd) log_errsys4("no mirror found for ", p.name, "/", p.ver); - - if (rename("source.tmp", "source.tar") == -1) - log_diesys1(100, "rename source.tmp source.tar"); - - stralloc_free(&sa); - close(fd); - return 0; -} diff --git a/pack-tree.c b/pack-tree.c @@ -1,94 +0,0 @@ -#include <unistd.h> -#include <errno.h> - -#include "buffer.h" -#include "env.h" -#include "log.h" -#include "open.h" -#include "pack.h" -#include "stat.h" -#include "stralloc.h" - -int -tree(pack *p, stralloc *prefix, char const *def) -{ - stralloc sa = STRALLOC_ZERO; - buffer b; - char buf[1024]; - ssize_t r; - int fd = -1; - char *ver[2]; - size_t n; - int ret = 0; - - if (!pack_version(p, def)) goto err; - if (!stralloc_cats(prefix, p->name)) goto err; - if (!stralloc_cats(prefix, " - ")) goto err; - if (!stralloc_cats(prefix, p->ver)) goto err; - if (!stralloc_cats(prefix, "/")) goto err; - buffer_puts(buffer_1, "\t"); - buffer_put(buffer_1, prefix->x, prefix->n - 1); - buffer_puts(buffer_1, "\n"); - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - n = sa.n; - ver[0] = p->ver; ver[1] = "default"; - errno = 0; - for (size_t i = 0; i < 2 && fd == -1; ++i) - { - sa.n = n; - if (!stralloc_cats(&sa, ver[i])) goto err; - if (!stralloc_cats(&sa, "/dependencies")) goto err; - if (!stralloc_cat0(&sa)) goto err; - fd = open_read(sa.x); - } - if (fd == -1) { ret = (errno == ENOENT); goto err; } - - buffer_init(&b, &read, fd, buf, sizeof buf); - while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa))) - { - if (sa.x[sa.n - 1] == '\n') --sa.n; - if (!stralloc_cat0(&sa)) goto err; - if (sa.x[pack_scan(p, sa.x)] != '\0') goto err; - n = prefix->n; - - if (!tree(p, prefix, def)) goto err; - prefix->n = n; - } - if (r != 0) goto err; - - ret = 1; -err: - stralloc_free(&sa); - if (fd >= 0) close (fd); - return ret; -} - -int -main(int argc, char **argv) -{ - char *def; - stralloc sa; - pack p; - - def = env_get("PACK_DEF"); if (!def) def = PACK_DEF; - if (!stat_isdir(def)) log_diesys1(101, def); - - if (argc != 2) log_usage(*argv, "package[/version]"); - ++argv; - - if (!pack_scan(&p, *argv)) - log_die2(1, "invalid package format: ", *argv); - - stralloc_init(&sa); - if (!tree(&p, &sa, def)) - log_diesys4(100, "generating tree for ", p.name, "/", p.ver); - stralloc_free(&sa); - - buffer_flush(buffer_1); - return 0; -} diff --git a/pack.c b/pack.c @@ -1,211 +0,0 @@ -#include <ctype.h> -#include <errno.h> -#include <unistd.h> -#include <dirent.h> - -#include "buffer.h" -#include "env.h" -#include "fmt.h" -#include "forkexec.h" -#include "genalloc.h" -#include "mem.h" -#include "open.h" -#include "pack.h" -#include "stralloc.h" -#include "lock.h" -#include "tai.h" - -size_t -pack_fmt(pack const *p, char *buf) -{ - size_t i = 0; - - i += str_copy(buf + i, p->name, PACK_FMT - i); - if (p->ver[0] == '\0') return i; - buf[i++] = '/'; - i += str_copy(buf + i, p->ver, PACK_FMT - i); - buf[i++] = '\0'; - - return i; -} - -size_t -pack_scan(pack *p, char const *s) -{ - size_t i; - size_t n = 0; - size_t v = 0; - - if (s[0] == '/') return 0; - - for (n = 0, i = 0 ;; ++n, ++i) - { - if (!isprint(s[i]) || s[i] == ' ') goto end; - if (s[i] == '/') break; - if (i >= sizeof p->name) return 0; - p->name[n] = s[i]; - } - - for (v = 0, ++i ;; ++i, ++v) - { - if (!isprint(s[i]) || s[i] == ' ') goto end; - if (s[i] == '/') break; - if (i > sizeof p->ver) return 0; - p->ver[v] = s[i]; - } - -end: - p->name[n] = '\0'; - p->ver[v] = '\0'; - return i; -} - -int -pack_version(pack *p, char const *def) -{ - stralloc sa; - buffer b; - char buf[1024]; - int fd = -1; - int ret = 0; - - if (*p->ver) return 1; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, def)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/default/version")) goto err; - if (!stralloc_cat0(&sa)) goto err; - - fd = open_read(sa.x); if (fd == -1) goto err; - - stralloc_zero(&sa); - buffer_init(&b, &read, fd, buf, sizeof buf); - if (buffer_getline(&b, &sa) <= 0) goto err; - if (sa.x[sa.n - 1] == '\n') --sa.n; - - if (sa.n >= sizeof p->ver) goto err; - - mem_copy(p->ver, sa.x, sa.n); - p->ver[sa.n] = '\0'; - - ret = 1; -err: - stralloc_free(&sa); - if (fd >= 0) close(fd); - return ret; -} - -int -pack_opendepfile(pack const *p, char const *def) -{ - stralloc sa; - size_t n; - int fd = -1; - - stralloc_init(&sa); - if (!stralloc_copys(&sa, def)) goto err; - if (!stralloc_append(&sa, '/')) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_append(&sa, '/')) goto err; - n = sa.n; - if (!stralloc_cats(&sa, p->ver)) goto err; - if (!stralloc_cats(&sa, "/dependencies")) goto err; - if (!stralloc_append(&sa, '\0')) goto err; - - errno = 0; - fd = open_read(sa.x); - if (errno == ENOTDIR || errno == ENOENT) - { - sa.n = n; - if (!stralloc_cats(&sa, "default/dependencies")) goto err; - if (!stralloc_append(&sa, '\0')) goto err; - errno = 0; - fd = open_read(sa.x); - } - -err: - stralloc_free(&sa); - return fd; -} - -int -pack_hasdep(pack const *p, genalloc *packs) -{ - size_t i; - - for (i = 0; i < genalloc_len(packs, pack); ++i) - { - pack *x = genalloc_get(packs, pack, i); - if (str_equal(x->name, p->name)) - if (str_equal(x->ver, p->ver)) - return 1; - } - - return 0; -} - -int -pack_lock(pack *p, char const *pkg) -{ - stralloc sa; - int fd = -1; - int ret = 0; - - stralloc_init(&sa); - if (!stralloc_cats(&sa, pkg)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->name)) goto err; - if (!stralloc_cats(&sa, "/")) goto err; - if (!stralloc_cats(&sa, p->ver)) goto err; - if (!stralloc_cats(&sa, "/source.tar")) goto err; - if (!stralloc_cat0(&sa)) goto err; - - if ((fd = open_trunc(sa.x)) == -1) goto err; - if (!lock_exclusive(fd)) { ret = -1; goto err; } - - ret = fd; -err: - stralloc_free(&sa); - return ret; -} - -int -pack_dep(pack const *p, genalloc *packs, char const *def) -{ - stralloc sa = STRALLOC_ZERO; - buffer b; - char buf[1024]; - size_t r; - int fd = -1; - int ret = 0; - - errno = 0; - fd = pack_opendepfile(p, def); - if (fd == -1) return (errno == ENOTDIR || errno == ENOENT); - - buffer_init(&b, &read, fd, buf, sizeof buf); - stralloc_init(&sa); - while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa)) > 0) - { - pack new; - size_t n; - - stralloc_cat0(&sa); - n = pack_scan(&new, sa.x); if (n == 0) goto err; - if (sa.x[n] != '\n' && sa.x[n] != '\0') goto err; - if (!pack_version(&new, def)) goto err; - - if (pack_hasdep(&new, packs)) continue; - if (!pack_dep(&new, packs, def)) goto err; - if (!genalloc_append(packs, new)) goto err; - } - - ret = (r == 0); - -err: - stralloc_free(&sa); - close(fd); - return ret; -} diff --git a/pack.h b/pack.h @@ -1,28 +0,0 @@ -#ifndef PACK_H -#define PACK_H - -#include <limits.h> -#include "genalloc.h" - -#define PACK_DEF "/etc/pack" -#define PACK_SRC "/var/pack/src" -#define PACK_LOG "/var/log/pack" -#define PACK_OUT "/var/pack/pkg" -#define PACK_TAR "/var/pack/tar" - -#define PACK_FMT (NAME_MAX * 2 + 1) - -typedef struct { - char name[NAME_MAX]; - char ver[NAME_MAX]; -} pack; - -int pack_dep(pack const *, genalloc *, char const *); -int pack_hasdep(pack const *, genalloc *); -int pack_lock(pack *, char const *); -int pack_opendepfile(pack const *, char const *); -int pack_version(pack *, char const *); -size_t pack_fmt(pack const *, char *); -size_t pack_scan(pack *, char const *); - -#endif diff --git a/package-add.c b/package-add.c @@ -0,0 +1,103 @@ +#include <sys/stat.h> +#include <errno.h> +#include <unistd.h> + +#include "buffer.h" +#include "env.h" +#include "fmt.h" +#include "genalloc.h" +#include "log.h" +#include "open.h" +#include "package.h" +#include "stat.h" +#include "str.h" + +void +die_nomem(void) +{ + log_diesys1(100, "malloc"); +} + +void +step(package const *p, char const *cmd char const *dir, char const *sub) +{ + int x; + char fmt[4]; + + buffer_puts(buffer_2, " "); + buffer_puts(buffer_2, sub); + buffer_puts(buffer_2, " "); + buffer_flush(buffer_2); + + if ((x = package_step(p, cmd, log, dir, sub)) == 0) return; + + fmt_long(fmt, x); + buffer_puts(buffer_2, "< exit "); + buffer_puts(buffer_2, fmt); + buffer_puts(buffer_2, "\n"); + buffer_flush(buffer_2); + + if (dir && !package_remove(p, dir, char const *sub)) + log_errsys6("deleting .../", sub, "/", p->name, "/", p->ver); + exit(100); +} + +int +main(int argc, char **argv) +{ + genalloc ga; + size_t i; + package p; + char *dir; + char *def; + + if (argc != 2) log_usage(*argv, "packageage[/version]"); + ++argv; + + dir = env_get("PACKAGE_DIR"); if (!dir) dir = PACKAGE_DIR; + def = env_get("PACKAGE_DEF"); if (!def) def = PACKAGE_DEF; + + if (!stat_isdir(def)) log_diesys1(101, def); + + i = package_scan(&p, *argv); + if (i == 0 || (*argv)[i] != '\0') + log_die2(1, "invalid packageage name: ", *argv); + + if (!package_version(&p, def)) + log_diesys3(101, "could not get ", *argv," version"); + + genalloc_init(&ga); + if (!package_dep(&p, &ga, def)) + log_diesys1(103, "could not resolve packageage dependencies"); + if (!genalloc_append(&ga, p)) die_nomem(); + + for (i = 0; i < genalloc_len(&ga, package); ++i) + { + package *p = genalloc_get(&ga, package, i); + char fmt[PACKAGE_FMT + 80]; + + buffer_puts(buffer_2, " "); + fmt_fill(fmt, sizeof fmt, p->name, 25); + buffer_puts(buffer_2, fmt); + buffer_puts(buffer_2, " "); + fmt_fill(fmt, sizeof fmt, p->ver, 10); + buffer_puts(buffer_2, fmt); + buffer_puts(buffer_2, " "); + buffer_flush(buffer_2); + + if (package_isdone(p, dir, "run")) goto step_install; + if (package_isdone(p, dir, "src")) goto step_build; + if (package_isdone(p, dir, "tar")) goto step_tar; + + step(p, "package-get", log, tar); +step_build: + step(p, "package-build", log, out); +step_install: + step(p, "package-install", log, NULL); + buffer_puts(buffer_2, "\n"); + buffer_flush(buffer_2); + } + genalloc_free(&ga); + + return 0; +} diff --git a/package-build b/package-build Binary files differ. diff --git a/package-build.c b/package-build.c @@ -0,0 +1,321 @@ +#include <sys/types.h> +#include <sys/dirent.h> +#include <sys/stat.h> +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <stdio.h> + +#include "buffer.h" +#include "env.h" +#include "fmt.h" +#include "forkexec.h" +#include "hier.h" +#include "hier.h" +#include "log.h" +#include "open.h" +#include "package.h" +#include "stat.h" +#include "str.h" +#include "stralloc.h" +#include "tain.h" + +static int +untar(void) +{ + char const *argv[] = { "tar", "-x", "-f", "../../source.tar", NULL }; + int fd; + int x; + + if ((fd = open_trunc("../log/1-untar")) == -1) return 0; + x = forkexec_wait_redir(argv, fd); + close(fd); + return x; +} + +static int +patch(package const *p, char *def) +{ + char const *argv[] = { "patch", "-N", NULL }; + char const *d[2]; + stralloc sa; + size_t n; + size_t m; + DIR *dp = NULL; + struct dirent *de; + int i; + int fd = -1; + int ret = 0; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + n = sa.n; + + if ((fd = open_trunc("../log/2-patch")) == -1) goto err; + d[0] = "default"; + d[1] = p->ver; + for (i = 0; i < 2; ++i) { + sa.n = n; + if (!stralloc_cats(&sa, d[i])) goto err; + if (!stralloc_cats(&sa, "/patch/")) goto err; + m = sa.n; + if (!stralloc_cat0(&sa)) goto err; + dp = opendir(sa.x); + if (dp == NULL) { + if (errno == ENOTDIR || errno == ENOENT) continue; + goto err; + } + while ((de = readdir(dp)) != NULL) { + if (str_equal(de->d_name, ".")) continue; + if (str_equal(de->d_name, "..")) continue; + + sa.n = m; + if (!stralloc_cats(&sa, de->d_name)) goto err; + if (!stralloc_cat0(&sa)) goto err; + close(0); + if (open_read(sa.x) == -1) goto err; + if (write(fd, "=== patch ===\n", 23) == -1) goto err; + if (forkexec_wait_redir(argv, fd) != 0) goto err; + if (write(fd, "\n", 1) == -1) goto err; + } + closedir(dp); + } + + ret = 1; +err: + close(0); + stralloc_free(&sa); + if (fd >= 0) { write(fd, "=== end ===\n", 12); close(fd); } + if (ret == 0) closedir(dp); + return ret; +} + +static int +data(package const *p, char const *def) +{ + stralloc sa = STRALLOC_ZERO; + size_t n; + int ret = 0; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + + if (close(open_trunc("../log/3-data")) == -1) goto err; + + n = sa.n; + if (!stralloc_cats(&sa, "default/data")) goto err; + if (!stralloc_cat0(&sa)) goto err; + if (stat_isdir(sa.x)) if (!hier_copy(sa.x, ".")) goto err; + + sa.n = n; + if (!stralloc_cats(&sa, p->ver)) goto err; + if (!stralloc_cats(&sa, "/data")) goto err; + if (!stralloc_cat0(&sa)) goto err; + if (stat_isdir(sa.x)) if (!hier_copy(sa.x, ".")) goto err; + + ret = 1; +err: + stralloc_free(&sa); + return ret; +} + +static int +build(package const *p, char const *def) +{ + stralloc sa; + char const *argv[] = { NULL, NULL }; + size_t n; + int fd = - 1; + int ret = -1; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + + if ((fd = open_trunc("../log/4-build")) == -1) goto err; + + n = sa.n; + if (!stralloc_cats(&sa, p->ver)) goto err; + if (!stralloc_cats(&sa, "/build")) goto err; + if (!stralloc_cat0(&sa)) goto err; + argv[0] = sa.x; + if (stat_isfile(sa.x)) { ret = forkexec_wait_redir(argv, fd); goto err; } + + sa.n = n; + if (!stralloc_cats(&sa, "default/build")) goto err; + if (!stralloc_cat0(&sa)) goto err; + argv[0] = sa.x; + if (stat_isfile(sa.x)) { ret = forkexec_wait_redir(argv, fd); goto err; } + +err: + stralloc_free(&sa); + if (fd >= 0) close(fd); + return ret; +} + +static int +package_env_set(char const *name, char const *path) +{ + char buf[NAME_MAX]; + int len; + + for (len = 0; name[len] != '\0'; ++len) + buf[len] = isalnum(name[len]) ? name[len] : '_'; + buf[len] = '\0'; + return env_set(buf, path); +} + +static int +env(package *p, char const *def, char const *pkg, char const *id) +{ + stralloc sa = STRALLOC_ZERO; + stralloc line = STRALLOC_ZERO; + buffer b; + char buf[1024]; + size_t r; + size_t n; + int fd = -1; + int ret = 0; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, pkg)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->ver)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, id)) goto err; + if (!stralloc_cats(&sa, "/build")) goto err; + if (!stralloc_cat0(&sa)) goto err; + if (!package_env_set("PREFIX", sa.x)) goto err; + + errno = 0; + fd = package_opendepfile(p, def); + if (fd == -1) { ret = (errno == ENOTDIR || errno == ENOENT); goto err; } + + stralloc_init(&line); + buffer_init(&b, &read, fd, buf, sizeof buf); + while (stralloc_zero(&line), (r = buffer_getline(&b, &line)) > 0) + { + package new; + + line.n -= (line.x[line.n - 1] == '\n'); + if (!stralloc_cat0(&line)) goto err; + n = package_scan(&new, line.x); if (n == 0 || line.x[n] != '\0') goto err; + if (!package_version(&new, def)) goto err; + + stralloc_zero(&sa); + if (!stralloc_cats(&sa, pkg)) + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, new.name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, new.ver)) goto err; + if (!stralloc_cats(&sa, "/current/build")) goto err; + if (!stralloc_cat0(&sa)) goto err; + if (!package_env_set(new.name, sa.x)) goto err; + } + ret = (r == 0); +err: + stralloc_free(&sa); + stralloc_free(&line); + if (fd >= 0) close(fd); + return ret; +} + +void +usage(char const *argv0, char const *param) +{ + log_err2("missing parameter: ", param); + log_usage(argv0, "-p pkgdir -d defdir packageage[/version]"); +} + +int +main(int argc, char **argv) +{ + package p; + tain tn; + char *def; + char *pkg; + char **av = argv; + char id[TAIN_FMT + 1]; + int x; + + (void)argc; + + while (*++av) { + if (str_equal(*av, "-d")) { if (!(def = *++av)) break; continue; } + if (str_equal(*av, "-p")) { if (!(pkg = *++av)) break; continue; } + break; + } + + if (!def) usage(*argv, "-d"); + if (!pkg) usage(*argv, "-p"); + if (!*av) usage(*argv, "packageage[/version]"); + + if (!stat_isdir(def)) log_diesys1(101, def); + if (!stat_isdir(pkg)) log_diesys1(101, pkg); + + tain_now(&tn); + id[tain_fmt(&tn, id)] = '\0'; + + if (chdir(pkg) == -1) + log_diesys2(101, "chdir ", pkg); + if ((*av)[package_scan(&p, *av)] != '\0') + log_diesys2(1, "invalid packageage format: ", *av); + if (mkdir(p.name, 075) == -1 && errno != EEXIST) + log_diesys4(101, "mkdir ", pkg, "/", p.name); + if (chdir(p.name) == -1) + log_diesys4(101, "chdir ", pkg, "/", p.name); + if (!package_version(&p, def)) + log_diesys4(101, "version ", def, "/", p.name); + if (mkdir(p.ver, 075) == -1 && errno != EEXIST) + log_diesys6(101, "mkdir ", pkg, "/", p.name, "/", p.ver); + if (chdir(p.ver) == -1) + log_diesys6(101, "chdir ", pkg, "/", p.name, "/", p.ver); + if (mkdir(id, 075) == -1 && errno != EEXIST) + log_diesys8(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id); + if (chdir(id) == -1) + log_diesys8(101, "chdir ", pkg, "/", p.name, "/", p.ver, "/", id); + if (mkdir("build", 075) == -1 && errno != EEXIST) + log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/build"); + if (mkdir("log", 075) == -1 && errno != EEXIST) + log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/log"); + if (mkdir("source", 075) == -1 && errno != EEXIST) + log_diesys9(101, "mkdir ", pkg, "/", p.name, "/", p.ver, "/", id, "/source"); + if (symlink(id, "latest") == -1 && errno != EEXIST) + log_diesys9(101, "symlink ", pkg, "/", p.name, "/", p.ver, "/", id, "/latest"); + if (rename("latest", "../latest") == -1 && errno != EEXIST) + log_diesys7(101, "rename ", pkg, "/", p.name, "/", p.ver, "/latest"); + if (chdir("source") == -1) + log_diesys4(101, "could not change directory to ", pkg, "/", p.name); + if ((x = untar()) != 0) { + char fmt[50]; + fmt_long(fmt, x); + log_die4(100, "tar of ", p.name, " exited ", fmt); + } + if (!patch(&p, def)) + log_diesys3(100, "patching ", p.name, "'s source"); + if (!data(&p, def)) + log_diesys6(100, "copying ", p.name, "'s data from ", def, " to ", pkg); + if (!env(&p, def, pkg, id)) + log_diesys2(100, "could not set environment variables for ", *argv); + if ((x = build(&p, def)) != 0) { + char fmt[50]; + fmt_long(fmt, x); + log_die4(100, "build script of ", p.name, " exited ", fmt); + } + if (symlink(id, "../current") == -1 && errno != EEXIST) + log_diesys9(101, "symlink ", pkg, "/", p.name, "/", p.ver, "/", id, "/current"); + if (rename("../current", "../../current") == -1 && errno != EEXIST) + log_diesys7(101, "rename ", pkg, "/", p.name, "/", p.ver, "/current"); + + return 0; +} diff --git a/package-dep b/package-dep Binary files differ. diff --git a/package-dep.c b/package-dep.c @@ -0,0 +1,56 @@ +#include <sys/stat.h> +#include <errno.h> +#include <unistd.h> + +#include "buffer.h" +#include "env.h" +#include "stat.h" +#include "genalloc.h" +#include "log.h" +#include "package.h" +#include "str.h" + +int +main(int argc, char **argv) +{ + (void)argc; + (void)argv; + char *def; + genalloc ga; + size_t i; + size_t n; + package p; + + if (argc != 2) log_usage(*argv, "packageage[/version]"); + ++argv; + + def = "/etc/pack"; + + if (!stat_isdir(def)) log_diesys1(101, def); + + n = package_scan(&p, *argv); + if (n == 0 || (*argv)[n] != '\0') + log_die2(1, "invalid packageage name: ", *argv); + + if (!package_version(&p, def)) + log_diesys3(103, "could not get ", *argv," version"); + + genalloc_init(&ga); + if (!package_dep(&p, &ga, def)) + log_diesys1(103, "could not resolve packageage dependencies"); + if (!genalloc_append(&ga, p)) log_diesys1(103, "malloc"); + + for (i = 0; i < genalloc_len(&ga, package); ++i) { + char fmt[PACKAGE_FMT]; + package *p = genalloc_get(&ga, package, i); + + package_fmt(p, fmt); + buffer_puts(buffer_1, fmt); + buffer_putc(buffer_1, '\n'); + } + buffer_flush(buffer_1); + + genalloc_free(&ga); + + return 0; +} diff --git a/package-get b/package-get Binary files differ. diff --git a/package-get.c b/package-get.c @@ -0,0 +1,143 @@ +#include <unistd.h> +#include <stdio.h> + +#include "buffer.h" +#include "env.h" +#include "forkexec.h" +#include "hier.h" +#include "lock.h" +#include "log.h" +#include "open.h" +#include "package.h" +#include "stat.h" +#include "stralloc.h" + +int +get(package const *p, char const *cmd, char const *url) +{ + char const *argv[] = { NULL, NULL, NULL, NULL }; + char fmt[PACKAGE_FMT]; + stralloc sa; + + stralloc_init(&sa); + + log_info2("trying mirror ", url); + + package_fmt(p, fmt); + argv[0] = cmd; + argv[1] = fmt; + argv[2] = url; + argv[3] = NULL; + if ((forkexec_wait(argv)) != 0) + { + log_err4("downloading packageage ", p->name, "/", p->ver); + return 0; + } + + return 1; +} + +void +die_nomem(void) +{ + log_diesys1(100, "malloc"); +} + +void +usage(char const *argv0, char const *param) +{ + log_err2("missing parameter: ", param); + log_usage(argv0, "-p pkgdir -d defdir packageage[/version]"); +} + +int +main(int argc, char **argv) +{ + stralloc sa; + package p; + buffer b; + char buf[1024]; + char *def = NULL; + char *pkg = NULL; + char *cmd = NULL; + char **av = argv; + int fd = -1; + size_t n; + size_t r; + + (void)argc; + + while (*++av) { + if (str_equal(*av, "-p")) { if (!(pkg = *++av)) break; continue; } + if (str_equal(*av, "-d")) { if (!(def = *++av)) break; continue; } + break; + } + + if (!def) usage(*argv, "-d"); + if (!pkg) usage(*argv, "-p"); + if (!*av) usage(*argv, "packageage[/version]"); + + if (!stat_isdir(def)) log_diesys1(101, def); + + n = package_scan(&p, *av); + if ((*av)[n] != '\0') + log_die2(1, "invalid packageage format: ", *argv); + if (!package_version(&p, def)) + log_diesys2(101, "package_version ", p.name); + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) die_nomem(); + if (!stralloc_cats(&sa, "/")) die_nomem(); + if (!stralloc_cats(&sa, p.name)) die_nomem(); + if (!stralloc_cats(&sa, "/")) die_nomem(); + if (!stralloc_cats(&sa, p.ver)) die_nomem(); + if (!stralloc_cats(&sa, "/uri")) die_nomem(); + if (!stralloc_cat0(&sa)) die_nomem(); + fd = open_read(sa.x); if (fd == -1) die_nomem(); + + stralloc_zero(&sa); + if (!stralloc_cats(&sa, pkg)) die_nomem(); + if (!stralloc_cats(&sa, "/")) die_nomem(); + if (!stralloc_cats(&sa, p.name)) die_nomem(); + if (!stralloc_cats(&sa, "/")) die_nomem(); + if (!stralloc_cats(&sa, p.ver)) die_nomem(); + if (!stralloc_cat0(&sa)) die_nomem(); + if (!hier_mkdir(sa.x, 0750)) + log_diesys2(101, "mkdir ", sa.x); + if (chdir(sa.x) == -1) + log_diesys2(101, "chdir ", sa.x); + + sa.n--; + if (close(1) == -1 || dup(open_trunc("source.tmp")) == -1) + log_diesys3(100, "redirect tar output to ", sa.x, "/source.tmp"); + if (!lock_exclusive(1)) + log_diesys3(100, "flock ", sa.x, "/source.tmp"); + if (close(2) == -1 || dup(open_trunc("source.log")) == -1) + log_diesys3(100, "redirect err output to ", sa.x, "/source.log"); + + buffer_init(&b, &read, fd, buf, sizeof buf); + while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa)) > 0) + { + cmd = NULL; + + if (sa.x[sa.n - 1] == '\n') --sa.n; + if (!stralloc_cat0(&sa)) die_nomem(); + if (str_start(sa.x, "http://")) cmd = "package-http"; + if (str_start(sa.x, "https://")) cmd = "package-http"; + if (str_start(sa.x, "ftp://")) cmd = "package-ftp"; + if (str_start(sa.x, "ftps://")) cmd = "package-ftps"; + if (str_start(sa.x, "git://")) cmd = "package-git"; + if (str_start(sa.x, "cvs://")) cmd = "package-cvs"; + if (!cmd) log_warn2("no handler found for downloading ", sa.x); + else if (get(&p, cmd, sa.x)) break; + } + if (r < 0) log_errsys1("buffering"); + if (!cmd) log_errsys4("no mirror found for ", p.name, "/", p.ver); + + if (rename("source.tmp", "source.tar") == -1) + log_diesys1(100, "rename source.tmp source.tar"); + + stralloc_free(&sa); + close(fd); + return 0; +} diff --git a/package-install.c b/package-install.c @@ -0,0 +1,36 @@ +#include "package.h" + +void +die_nomem(void) +{ + log_diesys1(100, "malloc"); +} + +int +main(int argc, char **argv) +{ + package p; + stralloc sa; + char *def = NULL; + char *pkg = NULL; + char *root = NULL; + + (void)argc; + + while (*++av) { + if (str_equal(*av, "-p")) { if (!(pkg = *++av)) break; continue; } + if (str_equal(*av, "-d")) { if (!(def = *++av)) break; continue; } + if (str_equal(*av, "-r")) { if (!(root = *++av)) break; continue; } + break; + } + + if (!def) usage(*argv, "-d"); + if (!pkg) usage(*argv, "-p"); + if (!*av) usage(*argv, "packageage[/version]"); + + if (!stat_isdir(def)) log_diesys1(101, def); + if (!stat_isdir(root)) log_diesys1(101, root); + + stralloc_init(&sa); + if (!stralloc_init(&sa)) die_nomem(); +} diff --git a/package-tree b/package-tree Binary files differ. diff --git a/package-tree.c b/package-tree.c @@ -0,0 +1,94 @@ +#include <unistd.h> +#include <errno.h> + +#include "buffer.h" +#include "env.h" +#include "log.h" +#include "open.h" +#include "package.h" +#include "stat.h" +#include "stralloc.h" + +int +tree(package *p, stralloc *prefix, char const *def) +{ + stralloc sa = STRALLOC_ZERO; + buffer b; + char buf[1024]; + ssize_t r; + int fd = -1; + char *ver[2]; + size_t n; + int ret = 0; + + if (!package_version(p, def)) goto err; + if (!stralloc_cats(prefix, p->name)) goto err; + if (!stralloc_cats(prefix, " - ")) goto err; + if (!stralloc_cats(prefix, p->ver)) goto err; + if (!stralloc_cats(prefix, "/")) goto err; + buffer_puts(buffer_1, "\t"); + buffer_put(buffer_1, prefix->x, prefix->n - 1); + buffer_puts(buffer_1, "\n"); + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + n = sa.n; + ver[0] = p->ver; ver[1] = "default"; + errno = 0; + for (size_t i = 0; i < 2 && fd == -1; ++i) + { + sa.n = n; + if (!stralloc_cats(&sa, ver[i])) goto err; + if (!stralloc_cats(&sa, "/dependencies")) goto err; + if (!stralloc_cat0(&sa)) goto err; + fd = open_read(sa.x); + } + if (fd == -1) { ret = (errno == ENOENT); goto err; } + + buffer_init(&b, &read, fd, buf, sizeof buf); + while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa))) + { + if (sa.x[sa.n - 1] == '\n') --sa.n; + if (!stralloc_cat0(&sa)) goto err; + if (sa.x[package_scan(p, sa.x)] != '\0') goto err; + n = prefix->n; + + if (!tree(p, prefix, def)) goto err; + prefix->n = n; + } + if (r != 0) goto err; + + ret = 1; +err: + stralloc_free(&sa); + if (fd >= 0) close (fd); + return ret; +} + +int +main(int argc, char **argv) +{ + char *def; + stralloc sa; + package p; + + def = "/etc/pack"; + if (!stat_isdir(def)) log_diesys1(101, def); + + if (argc != 2) log_usage(*argv, "packageage[/version]"); + ++argv; + + if (!package_scan(&p, *argv)) + log_die2(1, "invalid packageage format: ", *argv); + + stralloc_init(&sa); + if (!tree(&p, &sa, def)) + log_diesys4(100, "generating tree for ", p.name, "/", p.ver); + stralloc_free(&sa); + + buffer_flush(buffer_1); + return 0; +} diff --git a/package.c b/package.c @@ -0,0 +1,211 @@ +#include <ctype.h> +#include <errno.h> +#include <unistd.h> +#include <dirent.h> + +#include "buffer.h" +#include "env.h" +#include "fmt.h" +#include "forkexec.h" +#include "genalloc.h" +#include "mem.h" +#include "open.h" +#include "package.h" +#include "stralloc.h" +#include "lock.h" +#include "tai.h" + +size_t +package_fmt(package const *p, char *buf) +{ + size_t i = 0; + + i += str_copy(buf + i, p->name, PACKAGE_FMT - i); + if (p->ver[0] == '\0') return i; + buf[i++] = '/'; + i += str_copy(buf + i, p->ver, PACKAGE_FMT - i); + buf[i++] = '\0'; + + return i; +} + +size_t +package_scan(package *p, char const *s) +{ + size_t i; + size_t n = 0; + size_t v = 0; + + if (s[0] == '/') return 0; + + for (n = 0, i = 0 ;; ++n, ++i) + { + if (!isprint(s[i]) || s[i] == ' ') goto end; + if (s[i] == '/') break; + if (i >= sizeof p->name) return 0; + p->name[n] = s[i]; + } + + for (v = 0, ++i ;; ++i, ++v) + { + if (!isprint(s[i]) || s[i] == ' ') goto end; + if (s[i] == '/') break; + if (i > sizeof p->ver) return 0; + p->ver[v] = s[i]; + } + +end: + p->name[n] = '\0'; + p->ver[v] = '\0'; + return i; +} + +int +package_version(package *p, char const *def) +{ + stralloc sa; + buffer b; + char buf[1024]; + int fd = -1; + int ret = 0; + + if (*p->ver) return 1; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, def)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/default/version")) goto err; + if (!stralloc_cat0(&sa)) goto err; + + fd = open_read(sa.x); if (fd == -1) goto err; + + stralloc_zero(&sa); + buffer_init(&b, &read, fd, buf, sizeof buf); + if (buffer_getline(&b, &sa) <= 0) goto err; + if (sa.x[sa.n - 1] == '\n') --sa.n; + + if (sa.n >= sizeof p->ver) goto err; + + mem_copy(p->ver, sa.x, sa.n); + p->ver[sa.n] = '\0'; + + ret = 1; +err: + stralloc_free(&sa); + if (fd >= 0) close(fd); + return ret; +} + +int +package_opendepfile(package const *p, char const *def) +{ + stralloc sa; + size_t n; + int fd = -1; + + stralloc_init(&sa); + if (!stralloc_copys(&sa, def)) goto err; + if (!stralloc_append(&sa, '/')) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_append(&sa, '/')) goto err; + n = sa.n; + if (!stralloc_cats(&sa, p->ver)) goto err; + if (!stralloc_cats(&sa, "/dependencies")) goto err; + if (!stralloc_append(&sa, '\0')) goto err; + + errno = 0; + fd = open_read(sa.x); + if (errno == ENOTDIR || errno == ENOENT) + { + sa.n = n; + if (!stralloc_cats(&sa, "default/dependencies")) goto err; + if (!stralloc_append(&sa, '\0')) goto err; + errno = 0; + fd = open_read(sa.x); + } + +err: + stralloc_free(&sa); + return fd; +} + +int +package_hasdep(package const *p, genalloc *packages) +{ + size_t i; + + for (i = 0; i < genalloc_len(packages, package); ++i) + { + package *x = genalloc_get(packages, package, i); + if (str_equal(x->name, p->name)) + if (str_equal(x->ver, p->ver)) + return 1; + } + + return 0; +} + +int +package_lock(package *p, char const *pkg) +{ + stralloc sa; + int fd = -1; + int ret = 0; + + stralloc_init(&sa); + if (!stralloc_cats(&sa, pkg)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->name)) goto err; + if (!stralloc_cats(&sa, "/")) goto err; + if (!stralloc_cats(&sa, p->ver)) goto err; + if (!stralloc_cats(&sa, "/source.tar")) goto err; + if (!stralloc_cat0(&sa)) goto err; + + if ((fd = open_trunc(sa.x)) == -1) goto err; + if (!lock_exclusive(fd)) { ret = -1; goto err; } + + ret = fd; +err: + stralloc_free(&sa); + return ret; +} + +int +package_dep(package const *p, genalloc *packages, char const *def) +{ + stralloc sa = STRALLOC_ZERO; + buffer b; + char buf[1024]; + size_t r; + int fd = -1; + int ret = 0; + + errno = 0; + fd = package_opendepfile(p, def); + if (fd == -1) return (errno == ENOTDIR || errno == ENOENT); + + buffer_init(&b, &read, fd, buf, sizeof buf); + stralloc_init(&sa); + while (stralloc_zero(&sa), (r = buffer_getline(&b, &sa)) > 0) + { + package new; + size_t n; + + stralloc_cat0(&sa); + n = package_scan(&new, sa.x); if (n == 0) goto err; + if (sa.x[n] != '\n' && sa.x[n] != '\0') goto err; + if (!package_version(&new, def)) goto err; + + if (package_hasdep(&new, packages)) continue; + if (!package_dep(&new, packages, def)) goto err; + if (!genalloc_append(packages, new)) goto err; + } + + ret = (r == 0); + +err: + stralloc_free(&sa); + close(fd); + return ret; +} diff --git a/package.h b/package.h @@ -0,0 +1,22 @@ +#ifndef PACKAGE_H +#define PACKAGE_H + +#include <limits.h> +#include "genalloc.h" + +#define PACKAGE_FMT (NAME_MAX * 2 + 1) + +typedef struct { + char name[NAME_MAX]; + char ver[NAME_MAX]; +} package; + +int package_dep(package const *, genalloc *, char const *); +int package_hasdep(package const *, genalloc *); +int package_lock(package *, char const *); +int package_opendepfile(package const *, char const *); +int package_version(package *, char const *); +size_t package_fmt(package const *, char *); +size_t package_scan(package *, char const *); + +#endif diff --git a/tai.c b/tai.c @@ -5,7 +5,7 @@ tai_pack(char *s, tai *t) { uint64_t x; - x = t->x; + x = *t; s[7] = x & 255; x >>= 8; s[6] = x & 255; x >>= 8; s[5] = x & 255; x >>= 8; @@ -29,5 +29,5 @@ tai_unpack(char *s, tai *t) x <<= 8; x += (unsigned char) s[5]; x <<= 8; x += (unsigned char) s[6]; x <<= 8; x += (unsigned char) s[7]; - t->x = x; + *t = x; } diff --git a/tai.h b/tai.h @@ -4,18 +4,16 @@ #include <time.h> #include "uint64.h" -typedef struct { - uint64_t x; -} tai; +typedef uint64_t tai; #define TAI_PACK 8 -#define tai_approx(t) ((t)->x) -#define tai_add(t, t1, t2) ((t)->x = (t1)->x + (t2)->x) -#define tai_sub(t, t1, t2) ((t)->x = (t1)->x - (t2)->x) -#define tai_less(t1, t2) ((t1)->x < (t2)->x) -#define tai_more(t1, t2) ((t1)->x > (t2)->x) -#define tai_now(t) ((t)->x = 0x400000000000000aULL + (uint64_t)time((time_t *)0)) +#define tai_approx(t) (*(t)) +#define tai_add(t, t1, t2) (*(t) = *(t1) + *(t2)) +#define tai_sub(t, t1, t2) (*(t) = *(t1) - *(t2)) +#define tai_less(t1, t2) (*(t1) < *(t2)) +#define tai_more(t1, t2) (*(t1) > *(t2)) +#define tai_now(t) (*(t) = 0x400000000000000aULL + (uint64_t)time((time_t *)0)) void tai_pack(char *, tai *); void tai_unpack(char *, tai *); diff --git a/tain.c b/tain.c @@ -0,0 +1,117 @@ +#include <sys/types.h> +#include <sys/time.h> + +#include "tain.h" +#include "uint64.h" +#include "fmt.h" + +void +tain_add(tain *tn, tain *tn1, tain *tn2) +{ + tn->sec = tn1->sec + tn2->sec; + tn->nano = tn1->nano + tn2->nano; + if (tn->nano > 999999999UL) { + tn->nano -= 1000000000UL; + ++tn->sec; + } +} + +unsigned int +tain_fmtfrac(char *s, tain *tn) +{ + uint64_t x; + + x = tn->nano; + s[8] = '0' + (x % 10); x /= 10; + s[7] = '0' + (x % 10); x /= 10; + s[6] = '0' + (x % 10); x /= 10; + s[5] = '0' + (x % 10); x /= 10; + s[4] = '0' + (x % 10); x /= 10; + s[3] = '0' + (x % 10); x /= 10; + s[2] = '0' + (x % 10); x /= 10; + s[1] = '0' + (x % 10); x /= 10; + s[0] = '0' + (x % 10); + + return 18; +} + +void +tain_half(tain *tn1, tain *tn2) +{ + tn1->nano = tn2->nano >> 1; + if (tn2->sec & 1) tn1->nano += 500000000UL; + tn1->sec = tn2->sec >> 1; +} + +int +tain_less(tain *tn1, tain *tn2) +{ + if (tn1->sec < tn2->sec) return 1; + if (tn1->sec > tn2->sec) return 0; + return tn1->nano < tn2->nano; +} + +void +tain_now(tain *tn) +{ + struct timeval now; + + gettimeofday(&now, (struct timezone *) 0); + tn->sec = 4611686018427387914ULL + (uint64_t) now.tv_sec; + tn->nano = 1000 * now.tv_usec + 500; +} + +void +tain_pack(char *s, tain *tn) +{ + uint64_t x; + + tai_pack(s, &tn->sec); + s += 8; + + x = tn->nano; + s[3] = x & 0xff; x >>= 8; + s[2] = x & 0xff; x >>= 8; + s[1] = x & 0xff; x >>= 8; + s[0] = x; +} + +void +tain_sub(tain *tn, tain *tn1, tain *tn2) +{ + uint64_t unano = tn1->nano; + + tn->sec = tn1->sec - tn2->sec; + tn->nano = unano - tn2->nano; + if (tn->nano > unano) { + tn->nano += 1000000000UL; + --tn->sec; + } +} + +void +tain_unpack(char *s, tain *tn) +{ + uint64_t x; + + tai_unpack(s, &tn->sec); + s += 8; + + x = (unsigned char) s[0]; + x <<= 8; x += (unsigned char) s[1]; + x <<= 8; x += (unsigned char) s[2]; + x <<= 8; x += (unsigned char) s[3]; + tn->nano = x; +} + +size_t +tain_fmt(tain *tn, char *s) +{ + char pack[TAIN_PACK]; + + if (!s) return TAIN_FMT; + + tain_pack(pack, tn); + *s = '@'; + return fmt_xbuf(pack, sizeof pack, s + 1) + 1; +} diff --git a/tain.h b/tain.h @@ -0,0 +1,29 @@ +#ifndef TAIN_H +#define TAIN_H + +#include "tai.h" + +typedef struct { + tai sec; + unsigned long nano; /* 0...999999999 */ +} tain; + +#define TAIN_PACK 12 +#define TAIN_FMT 25 + +#define tain_frac(tn) (((tn)->nano) * 0.000000001) +#define tain_more(ta1, ta2) (!tain_less((t1), (t2))) +#define tain_tai(ta, t) (*(t) = (tn)->sec) +#define tain_approx(tn) (tai_approx(&(tn)->sec) + tain_frac(tn)) + +int tain_less(tain *, tain *); +size_t tain_fmt(tain *, char *); +unsigned int tain_fmtfrac(char *, tain *); +void tain_add(tain *, tain *, tain *); +void tain_half(tain *, tain *); +void tain_now(tain *); +void tain_pack(char *, tain *); +void tain_sub(tain *, tain *, tain *); +void tain_unpack(char *, tain *); + +#endif