From beaa824076f37412b3606e241d00932b4fc1befb Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Wed, 9 Sep 2015 19:26:50 +0200 Subject: [PATCH] Store tixinfo and manifest on tix install. --- build-aux/build-ports.sh | 4 +-- tix/tix-collection.cpp | 17 ++++++++++ tix/tix-install.cpp | 50 +++++++++++++++++++++++++++- tix/util.h | 72 ++++++++++++++++++++++++++++++++++++---- 4 files changed, 133 insertions(+), 10 deletions(-) diff --git a/build-aux/build-ports.sh b/build-aux/build-ports.sh index 37799ce5..7b918528 100755 --- a/build-aux/build-ports.sh +++ b/build-aux/build-ports.sh @@ -135,7 +135,7 @@ mkdir -p "$SORTIX_REPOSITORY_DIR" # Initialize Tix package management in the system root if absent. [ -e "$SYSROOT/tix/collection.conf" ] || -tix-collection "$SYSROOT" create --platform=$HOST --prefix= --disable-multiarch --generation=1 +tix-collection "$SYSROOT" create --platform=$HOST --prefix= --disable-multiarch --generation=2 # Build all the packages (if needed) and otherwise install them. for PACKAGE in $PACKAGES; do @@ -149,7 +149,7 @@ for PACKAGE in $PACKAGES; do --prefix= \ --exec-prefix= \ --destination="$SORTIX_REPOSITORY_DIR" \ - --generation=1 \ + --generation=2 \ "$SORTIX_PORTS_DIR/$PACKAGE" tix-install \ --collection="$SYSROOT" \ diff --git a/tix/tix-collection.cpp b/tix/tix-collection.cpp index aceb2e6c..5df00d69 100644 --- a/tix/tix-collection.cpp +++ b/tix/tix-collection.cpp @@ -161,6 +161,20 @@ int main(int argc, char* argv[]) tixdb_path = strdup(tix_path); } + // TODO: After releasing Sortix 1.0, do this unconditionally. + if ( 2 <= generation ) + { + char* tixinfo_path = join_paths(tixdb_path, "tixinfo"); + if ( mkdir_p(tixinfo_path, 0755) != 0 ) + error(1, errno, "mkdir: `%s'", tixinfo_path); + free(tixinfo_path); + + char* manifest_path = join_paths(tixdb_path, "manifest"); + if ( mkdir_p(manifest_path, 0755) != 0 ) + error(1, errno, "mkdir: `%s'", manifest_path); + free(manifest_path); + } + char* collection_conf_path = join_paths(tixdb_path, "collection.conf"); FILE* conf_fp = fopen(collection_conf_path, "wx"); if ( !conf_fp && errno == EEXIST ) @@ -169,6 +183,9 @@ int main(int argc, char* argv[]) collection); fprintf(conf_fp, "tix.version=1\n"); fprintf(conf_fp, "tix.class=collection\n"); + // TODO: After releasing Sortix 1.0, do this unconditionally. + if ( 2 <= generation ) + fprintf(conf_fp, "collection.generation=%i\n", generation); fprintf(conf_fp, "collection.prefix=%s\n", !strcmp(prefix, "/") ? "" : prefix); fprintf(conf_fp, "collection.platform=%s\n", platform); diff --git a/tix/tix-install.cpp b/tix/tix-install.cpp index 08744bc7..59fe175a 100644 --- a/tix/tix-install.cpp +++ b/tix/tix-install.cpp @@ -234,6 +234,13 @@ int main(int argc, char* argv[]) return 0; } +static int strcmp_indirect(const void* a_ptr, const void* b_ptr) +{ + const char* a = *(const char* const*) a_ptr; + const char* b = *(const char* const*) b_ptr; + return strcmp(a, b); +} + void InstallPackage(const char* tix_path) { if ( !IsFile(tix_path) ) @@ -281,7 +288,8 @@ void InstallPackage(const char* tix_path) if ( !coll_generation ) coll_generation = "1"; assert(coll_generation); - (void) coll_generation; + int generation = atoi(coll_generation); + (void) generation; const char* coll_prefix = dictionary_get(&coll_conf, "collection.prefix"); assert(coll_prefix); const char* coll_platform = dictionary_get(&coll_conf, "collection.platform"); @@ -314,6 +322,46 @@ void InstallPackage(const char* tix_path) char* data_and_prefix = package_prefix && package_prefix[0] ? print_string("data%s", package_prefix) : strdup("data"); + + // TODO: After releasing Sortix 1.0, do this unconditionally. + if ( 2 <= generation ) + { + char* tixinfo_path = print_string("%s/tixinfo/%s", tixdb_path, package_name); + int tixinfo_fd = open(tixinfo_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if ( tixinfo_fd < 0 ) + error(1, errno, "%s", tixinfo_path); + TarExtractFileToFD(tix_path, "tix/tixinfo", tixinfo_fd); + close(tixinfo_fd); + + FILE* index_fp = TarOpenIndex(tix_path); + string_array_t files = string_array_make(); + string_array_append_file(&files, index_fp); + qsort(files.strings, files.length, sizeof(char*), strcmp_indirect); + char* manifest_path = print_string("%s/manifest/%s", tixdb_path, package_name); + FILE* manifest_fp = fopen(manifest_path, "w"); + if ( !manifest_fp ) + error(1, errno, "%s", manifest_path); + for ( size_t i = 0; i < files.length; i++ ) + { + char* str = files.strings[i]; + if ( strncmp(str, "data", strlen("data")) != 0 ) + continue; + str += strlen("data"); + if ( str[0] && str[0] != '/' ) + continue; + size_t len = strlen(str); + while ( 2 <= len && str[len-1] == '/' ) + str[--len] = '\0'; + if ( fprintf(manifest_fp, "%s\n", str) < 0 ) + error(1, errno, "%s", manifest_path); + } + if ( ferror(manifest_fp) || fflush(manifest_fp) == EOF ) + error(1, errno, "%s", manifest_path); + fclose(manifest_fp); + string_array_reset(&files); + fclose(index_fp); + } + if ( fork_and_wait_or_death() ) { size_t num_strips = count_tar_components(data_and_prefix); diff --git a/tix/util.h b/tix/util.h index 6248ef46..5da5a488 100644 --- a/tix/util.h +++ b/tix/util.h @@ -25,7 +25,13 @@ #ifndef UTIL_H #define UTIL_H +// TODO: After releasing Sortix 1.0, remove this ifdef and default it to the +// latest generation. +#if defined(__sortix__) +#define DEFAULT_GENERATION "2" +#else #define DEFAULT_GENERATION "1" +#endif bool does_path_contain_dotdot(const char* path) { @@ -573,16 +579,17 @@ bool TarContainsFile(const char* archive, const char* file) return ret; } -FILE* TarOpenFile(const char* archive, const char* file) +void TarExtractFileToFD(const char* archive, const char* file, int fd) { - FILE* fp = tmpfile(); - if ( !fp ) - error(1, errno, "tmpfile"); pid_t tar_pid = fork_or_death(); if ( !tar_pid ) { - dup2(fileno(fp), 1); - fclose(fp); + if ( dup2(fd, 1) < 0 ) + { + error(0, errno, "dup2"); + _exit(127); + } + close(fd); const char* cmd_argv[] = { "tar", @@ -593,7 +600,8 @@ FILE* TarOpenFile(const char* archive, const char* file) NULL }; execvp(cmd_argv[0], (char* const*) cmd_argv); - error(127, errno, "%s", cmd_argv[0]); + error(0, errno, "%s", cmd_argv[0]); + _exit(127); } int tar_exit_status; waitpid(tar_pid, &tar_exit_status, 0); @@ -602,6 +610,56 @@ FILE* TarOpenFile(const char* archive, const char* file) error(1, 0, "Unable to extract `%s/%s'", archive, file); exit(WEXITSTATUS(tar_exit_status)); } +} + +FILE* TarOpenFile(const char* archive, const char* file) +{ + FILE* fp = tmpfile(); + if ( !fp ) + error(1, errno, "tmpfile"); + TarExtractFileToFD(archive, file, fileno(fp)); + if ( fseeko(fp, 0, SEEK_SET) < 0 ) + error(1, errno, "fseeko(tmpfile(), 0, SEEK_SET)"); + return fp; +} + +void TarIndexToFD(const char* archive, int fd) +{ + pid_t tar_pid = fork_or_death(); + if ( !tar_pid ) + { + if ( dup2(fd, 1) < 0 ) + { + error(0, errno, "dup2"); + _exit(127); + } + close(fd); + const char* cmd_argv[] = + { + "tar", + "--list", + "--file", archive, + NULL + }; + execvp(cmd_argv[0], (char* const*) cmd_argv); + error(0, errno, "%s", cmd_argv[0]); + _exit(127); + } + int tar_exit_status; + waitpid(tar_pid, &tar_exit_status, 0); + if ( !WIFEXITED(tar_exit_status) || WEXITSTATUS(tar_exit_status) != 0 ) + { + error(1, 0, "Unable to list contents of `%s'", archive); + exit(WEXITSTATUS(tar_exit_status)); + } +} + +FILE* TarOpenIndex(const char* archive) +{ + FILE* fp = tmpfile(); + if ( !fp ) + error(1, errno, "tmpfile"); + TarIndexToFD(archive, fileno(fp)); if ( fseeko(fp, 0, SEEK_SET) < 0 ) error(1, errno, "fseeko(tmpfile(), 0, SEEK_SET)"); return fp;