aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2020-04-19 16:31:45 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2020-04-19 16:31:45 -0400
commit6d04ff98c4bfc21ad3fa779237a16ba760080fac (patch)
treee5cdaf218d7fc563899eb44292225fca7f051363
parent57c9489b28a481abc078ad3a2dd197079f9c414b (diff)
downloadspmc-6d04ff98c4bfc21ad3fa779237a16ba760080fac.tar.gz
Better reporting when a package does not exist
* Add additional errors * Fix user_input function missing an error return value * spmbuild sources a temporary file instead of output from a sub-shell * Fix indentation problem * A reason can be attached to spmerrno using spmerrno_cause()
-rw-r--r--include/error_handler.h5
-rw-r--r--include/spm.h4
-rw-r--r--lib/config_global.c10
-rw-r--r--lib/error_handler.c10
-rw-r--r--lib/install.c40
-rw-r--r--lib/internal_cmd.c6
-rw-r--r--lib/manifest.c21
-rw-r--r--lib/user_input.c1
-rwxr-xr-xscripts/spmbuild36
-rw-r--r--src/spm.c1
10 files changed, 113 insertions, 21 deletions
diff --git a/include/error_handler.h b/include/error_handler.h
index a731d28..9e7c1b8 100644
--- a/include/error_handler.h
+++ b/include/error_handler.h
@@ -14,6 +14,8 @@
#define SPM_ERR_PKG_INVALID _SPM_ERR(4) // invalid package (wrong structure, missing data, etc)
#define SPM_ERR_PKG_CHECKSUM _SPM_ERR(5) // bad checksum
#define SPM_ERR_PKG_FETCH _SPM_ERR(6) // failed to download package
+#define SPM_ERR_MANIFEST_INVALID _SPM_ERR(7) // manifest file is invalid (no header)
+#define SPM_ERR_MANIFEST_EMPTY _SPM_ERR(8) // manifest file has no data
extern int spmerrno;
@@ -25,9 +27,12 @@ static const char *SPM_ERR_STRING[] = {
"Invalid package",
"Bad package checksum",
"Failed to fetch package",
+ "Manifest has no header",
+ "Manifest has no data",
NULL,
};
+void spmerrno_cause(const char *reason);
char *spm_strerror(int code);
void spm_perror(const char *msg);
diff --git a/include/spm.h b/include/spm.h
index b96554a..f9b2201 100644
--- a/include/spm.h
+++ b/include/spm.h
@@ -27,6 +27,8 @@
#include <utime.h>
#endif
+#include "conf.h"
+extern spm_vars SPM_GLOBAL;
#include "compat.h"
#include "error_handler.h"
#include "package.h"
@@ -44,7 +46,6 @@
#include "resolve.h"
#include "shell.h"
#include "relocation.h"
-#include "conf.h"
#include "archive.h"
#include "find.h"
#include "rpath.h"
@@ -96,7 +97,6 @@
_1________________________________________________"
// GLOBALS
-spm_vars SPM_GLOBAL;
#ifdef __APPLE__
extern char **environ;
diff --git a/lib/config_global.c b/lib/config_global.c
index e97cddb..52589d4 100644
--- a/lib/config_global.c
+++ b/lib/config_global.c
@@ -3,6 +3,10 @@
*/
#include "spm.h"
+// GLOBAL
+spm_vars SPM_GLOBAL;
+
+
/**
* Get path to user's local configuration directory
* (The path will be created if it doesn't exist)
@@ -125,7 +129,13 @@ void check_runtime_environment(void) {
int bad_rt = 0;
char *required[] = {
"file",
+#if defined(__linux) || defined(__linux__)
"patchelf",
+#elif defined(__APPLE__) && defined(__MACH__)
+ "install_name_tool",
+#elif defined(__WIN32__)
+ // TODO: Does windows provide some kind of equivalent?
+#endif
"objdump",
"rsync",
"tar",
diff --git a/lib/error_handler.c b/lib/error_handler.c
index baf56b4..292fa6f 100644
--- a/lib/error_handler.c
+++ b/lib/error_handler.c
@@ -2,7 +2,13 @@
int spmerrno = 0;
static char spmerrbuf[255];
+static char spmerrbuf_reason[255];
+void spmerrno_cause(const char *reason) {
+ char *buf = spmerrbuf_reason;
+ sprintf(buf, " (%s)", reason);
+ return;
+}
/**
*
* @param code
@@ -18,6 +24,10 @@ char *spm_strerror(int code) {
} else {
strcpy(buf, SPM_ERR_STRING[SPM_ERR_INDEX(code)]);
}
+
+ if (strlen(spmerrbuf_reason)) {
+ strcat(buf, spmerrbuf_reason);
+ }
return buf;
}
diff --git a/lib/install.c b/lib/install.c
index c5c2c4c..32348e2 100644
--- a/lib/install.c
+++ b/lib/install.c
@@ -200,8 +200,32 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
size_t num_requirements = 0;
ManifestPackage **requirements = NULL;
char source[PATH_MAX];
- char *tmpdir = spm_mkdtemp(TMP_DIR, "spm_destroot", NULL);
+ char *tmpdir = NULL;
+ // Produce a dependency tree from requested package(s)
+ for (size_t i = 0; i < strlist_count(packages); i++) {
+ char *item = strlist_item(packages, i);
+
+ // Does the package exist in the manifest?
+ if (manifestlist_search(mf, item) == NULL) {
+ spmerrno = SPM_ERR_PKG_NOT_FOUND;
+ spmerrno_cause(item);
+ break;
+ }
+
+ requirements = resolve_dependencies(mf, item);
+ if (requirements != NULL) {
+ for (size_t c = num_requirements; requirements[c] != NULL; c++) {
+ num_requirements++;
+ }
+ }
+ }
+
+ if (spmerrno) {
+ return -1;
+ }
+
+ tmpdir = spm_mkdtemp(TMP_DIR, "spm_destroot", NULL);
if (tmpdir == NULL) {
perror("Could not create temporary destination root");
fprintf(SYSERROR);
@@ -214,20 +238,10 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
if (spm_hierarchy_make_root(fs) < 0) {
spmerrno = SPM_ERR_ROOT_NO_RECORD;
+ rmdirs(tmpdir);
return -1;
}
- // Produce a dependency tree from requested package(s)
- for (size_t i = 0; i < strlist_count(packages); i++) {
- char *item = strlist_item(packages, i);
- requirements = resolve_dependencies(mf, item);
- if (requirements != NULL) {
- for (size_t c = num_requirements; requirements[c] != NULL; c++) {
- num_requirements++;
- }
- }
- }
-
// Install packages
printf("Requested package(s):\n");
for (size_t i = 0; requirements !=NULL && requirements[i] != NULL; i++) {
@@ -244,7 +258,7 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
char *package_dir = strdup(SPM_GLOBAL.package_dir);
for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) {
char *package_origin = calloc(PATH_MAX, sizeof(char));
- strncpy(package_origin, requirements[i]->origin, PATH_MAX);
+ strncpy(package_origin, requirements[i]->origin, PATH_MAX);
if (strstr(package_origin, SPM_GLOBAL.repo_target) == NULL) {
if (!endswith(package_origin, DIRSEPS)) {
diff --git a/lib/internal_cmd.c b/lib/internal_cmd.c
index b1e8faa..e5f875f 100644
--- a/lib/internal_cmd.c
+++ b/lib/internal_cmd.c
@@ -237,7 +237,13 @@ int mkruntime_interface(int argc, char **argv) {
}
runtime_set(rt, "CFLAGS", "-I$SPM_INCLUDE $CFLAGS");
+#if defined(__APPLE__) && defined (__MACH__)
+ runtime_set(rt, "LDFLAGS", "-rpath $SPM_LIB:$SPM_LIB64 -L$SPM_LIB -L$SPM_LIB64 $LDFLAGS");
+#elif defined(__linux) || defined (__linux__)
runtime_set(rt, "LDFLAGS", "-Wl,-rpath=$SPM_LIB:$SPM_LIB64 -L$SPM_LIB -L$SPM_LIB64 $LDFLAGS");
+#else
+ // TODO: Windows?
+#endif
runtime_export(rt, NULL);
runtime_free(rt);
diff --git a/lib/manifest.c b/lib/manifest.c
index a95b566..1bd90b6 100644
--- a/lib/manifest.c
+++ b/lib/manifest.c
@@ -440,7 +440,21 @@ Manifest *manifest_read(char *file_or_url) {
while (fgets(dptr, BUFSIZ, fp) != NULL) {
total_records++;
}
- total_records--; // header does not count
+
+ if (total_records == 0) {
+ spmerrno = SPM_ERR_MANIFEST_INVALID;
+ } else if (total_records == 1) {
+ spmerrno = SPM_ERR_MANIFEST_EMPTY;
+ }
+
+ if (spmerrno) {
+ return NULL;
+ }
+
+ // There's a header, but don't count it in the total
+ total_records--;
+
+ // Going to reprocess the file again, so rewind
rewind(fp);
Manifest *info = (Manifest *)calloc(1, sizeof(Manifest));
@@ -582,10 +596,13 @@ void manifestlist_free(ManifestList *pManifestList) {
*/
void manifestlist_append(ManifestList *pManifestList, char *path) {
Manifest *manifest = manifest_read(path);
- if (manifest == NULL) {
+ if (manifest == NULL && spmerrno == 0) {
fprintf(stderr, "Failed to create manifest in memory\n");
fprintf(SYSERROR);
exit(1);
+ } else if (spmerrno == SPM_ERR_MANIFEST_EMPTY || spmerrno == SPM_ERR_MANIFEST_INVALID) {
+ manifest = calloc(1, sizeof(Manifest));
+ manifest->packages = calloc(1, sizeof(ManifestPackage *));
}
Manifest **tmp = realloc(pManifestList->data, (pManifestList->num_alloc + 1) * sizeof(Manifest *));
diff --git a/lib/user_input.c b/lib/user_input.c
index 416b59f..589a084 100644
--- a/lib/user_input.c
+++ b/lib/user_input.c
@@ -37,4 +37,5 @@ int spm_prompt_user(const char *msg, int empty_input_is_yes) {
}
input_count++;
}
+ return -1;
}
diff --git a/scripts/spmbuild b/scripts/spmbuild
index 1af9641..a5e6300 100755
--- a/scripts/spmbuild
+++ b/scripts/spmbuild
@@ -40,8 +40,16 @@ function msg_warn() {
_msg "WARNING:" "$@"
}
+function tar() {
+ local cmd=tar
+ if [[ $(uname -s) == Darwin ]]; then
+ cmd=gtar
+ fi
+ $cmd "$@"
+}
+
function spm_build_initialize_stage1() {
- export SPMDEV=$(readlink -f $(dirname ${BASH_SOURCE[0]})/../cmake-build-debug/src/spm)
+ export SPMDEV=$(python -c "import os; print(os.path.abspath('$(dirname ${BASH_SOURCE[0]})/../cmake-build-debug/src/spm'))")
export SPM=$(which spm 2>/dev/null || echo ${SPMDEV})
spm_build_check_rt_env
@@ -95,10 +103,24 @@ function spm_build_initialize_stage1() {
fi
}
+function spm_build_new_root() {
+ local path
+
+ path=$(mktemp)
+ if [[ ! -f "${path}" ]]; then
+ msg_error "spm_build_new_root: failed to create temporary file"
+ exit 1
+ fi
+ spm_build_mkruntime "$1" > "${path}"
+ source "${path}"
+ rm -f "${path}"
+}
+
function spm_build_initialize_stage2() {
# In order to get the SPM_* variables out spm, we need to give a path...
# this is ugly but safe-ish
- source <(spm_build_mkruntime "/usr")
+ spm_build_new_root "/usr"
+
unset CFLAGS
unset CPPFLAGS
unset LDFLAGS
@@ -152,9 +174,15 @@ function spm_build_initialize_stage2() {
_maxjobs=1
fi
- source <(spm_build_mkruntime "${SPM_BUILD_RUNTIME}")
+ spm_build_new_root "${SPM_BUILD_RUNTIME}"
export LD_LIBRARY_PATH="${SPM_BUILD_RUNTIME}/lib:${SPM_BUILD_RUNTIME}/lib64"
export LD_RUN_PATH="${LD_LIBRARY_PATH}"
+ if [[ $(uname -s) == Darwin ]]; then
+ DYLD_LIBRARY_PATH="${LD_LIBRARY_PATH}"
+ DYLD_RUN_PATH="${LD_RUN_PATH}"
+ unset LD_LIBRARY_PATH
+ unset LD_RUNPATH_PATH
+ fi
export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
}
@@ -214,7 +242,7 @@ function spm_build_fetch() {
local filename
local tmpdir
- if [[ $# < 2 ]]; then
+ if (( $# < 2 )); then
msg_error "spm_build_fetch: {url} {destination}"
spm_build_cleanup
exit 1
diff --git a/src/spm.c b/src/spm.c
index bb58401..971d506 100644
--- a/src/spm.c
+++ b/src/spm.c
@@ -29,6 +29,7 @@ void usage(const char *program_name) {
, program_name);
}
+extern spm_vars SPM_GLOBAL;
int main(int argc, char *argv[], char *arge[]) {
char *program_name = strdup(argv[0]);