aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2020-04-18 15:28:54 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2020-04-19 00:32:26 -0400
commit8cdddbb0f1a8c6eb023cbe732e5701240a54ff3c (patch)
tree12cc1ea0186b242a82d87bc2f62142e5decefedb
parentf70b803e39484a2eba362414545ba8afd027c9da (diff)
downloadspmc-8cdddbb0f1a8c6eb023cbe732e5701240a54ff3c.tar.gz
Implement error handling
* Die on bad root directory
-rw-r--r--include/conf.h1
-rw-r--r--include/install.h2
-rw-r--r--lib/CMakeLists.txt1
-rw-r--r--lib/config_global.c6
-rw-r--r--lib/fs.c2
-rw-r--r--lib/install.c54
-rw-r--r--lib/purge.c6
-rw-r--r--src/spm.c12
8 files changed, 67 insertions, 17 deletions
diff --git a/include/conf.h b/include/conf.h
index a5a4d36..7952eed 100644
--- a/include/conf.h
+++ b/include/conf.h
@@ -16,6 +16,7 @@ typedef struct {
} ConfigItem;
typedef struct {
+ char *rootrec;
char *rootdir;
char *bindir;
char *includedir;
diff --git a/include/install.h b/include/install.h
index fb08661..bc1fe19 100644
--- a/include/install.h
+++ b/include/install.h
@@ -4,6 +4,8 @@
#ifndef SPM_INSTALL_H
#define SPM_INSTALL_H
+int spm_hierarchy_is_root(SPM_Hierarchy *fs);
+int spm_hierarchy_make_root(SPM_Hierarchy *fs);
void spm_install_show_package(ManifestPackage *package);
int spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package);
int spm_install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name);
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index fd5c905..2185ef4 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -30,6 +30,7 @@ set(libspm_src
user_input.c
metadata.c
purge.c
+ error_handler.c
)
add_library(libspm_obj OBJECT ${libspm_src})
diff --git a/lib/config_global.c b/lib/config_global.c
index f63566b..e97cddb 100644
--- a/lib/config_global.c
+++ b/lib/config_global.c
@@ -153,7 +153,7 @@ void check_runtime_environment(void) {
}
/**
- *
+ * Define the structure of a SPM root hierarchy
* @param basepath
* @return
*/
@@ -170,12 +170,13 @@ SPM_Hierarchy *spm_hierarchy_init(char *basepath) {
fs->tmpdir = join((char *[]) {fs->rootdir, "tmp", NULL}, DIRSEPS);
fs->dbdir = join((char *[]) {fs->localstatedir, "db", NULL}, DIRSEPS);
fs->dbrecdir = join((char *[]) {fs->dbdir, "records", NULL}, DIRSEPS);
+ fs->rootrec = join((char *[]) {".spm_root", NULL}, DIRSEPS);
return fs;
}
/**
- *
+ * Free SPM_Hierarchy structure
* @param fs
*/
void spm_hierarchy_free(SPM_Hierarchy *fs) {
@@ -190,6 +191,7 @@ void spm_hierarchy_free(SPM_Hierarchy *fs) {
free(fs->tmpdir);
free(fs->dbdir);
free(fs->dbrecdir);
+ free(fs->rootrec);
free(fs);
}
diff --git a/lib/fs.c b/lib/fs.c
index 3ba01e7..20a5999 100644
--- a/lib/fs.c
+++ b/lib/fs.c
@@ -624,7 +624,6 @@ char *spm_mkdtemp(const char *base, const char *name, const char *extended_path)
path_stat = stat(path, &st);
if (path_stat < 0) {
if ((fp = fopen(path, "w+")) == NULL) {
- perror(path);
return -1;
}
fclose(fp);
@@ -632,7 +631,6 @@ char *spm_mkdtemp(const char *base, const char *name, const char *extended_path)
if ((S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) > 0) {
if (utime(path, NULL) < 0) {
// failed to set file time
- perror(path);
return -1;
}
// updated file time
diff --git a/lib/install.c b/lib/install.c
index c6e12ca..c5c2c4c 100644
--- a/lib/install.c
+++ b/lib/install.c
@@ -4,6 +4,37 @@
#include <url.h>
#include "spm.h"
+/**
+ * Check for the existence of `$ROOT/var/.spm_root`
+ * @param path
+ * @return yes=1, no=0
+ */
+int spm_hierarchy_is_root(SPM_Hierarchy *fs) {
+ if (exists(fs->rootrec) != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+/**
+ * Initialize (not populate) a spm root directory.
+ * A "root record" is dropped into $ROOT/var
+ * @param fs `SPM_Hierarchy` structure
+ * @return success=0, error=-1
+ */
+int spm_hierarchy_make_root(SPM_Hierarchy *fs) {
+ // Create the root directory if it does not exist
+ if (mkdirs(fs->rootdir, 0755) != 0) {
+ return -1;
+ }
+
+ if (touch(fs->rootrec) < 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
void spm_install_show_package(ManifestPackage *package) {
if (package == NULL) {
fprintf(stderr, "ERROR: package was NULL\n");
@@ -27,17 +58,6 @@ int spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) {
return -1;
}
- if (exists(fs->rootdir) != 0) {
- if (SPM_GLOBAL.verbose) {
- printf("Creating destination root: %s\n", fs->rootdir);
- }
- if (mkdirs(fs->rootdir, 0755) != 0) {
- fprintf(SYSERROR);
- free(package);
- return -2;
- }
- }
-
if (SPM_GLOBAL.verbose) {
printf("Extracting archive: %s\n", package);
}
@@ -192,6 +212,11 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
printf("Installation root: %s\n", fs->rootdir);
}
+ if (spm_hierarchy_make_root(fs) < 0) {
+ spmerrno = SPM_ERR_ROOT_NO_RECORD;
+ 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);
@@ -272,6 +297,12 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
manifest_free(tmp_manifest);
}
+ if (spm_hierarchy_is_root(fs) == 0) {
+ if (SPM_GLOBAL.verbose) {
+ printf("Creating destination root: %s\n", fs->rootdir);
+ }
+ }
+
printf("Installing package(s):\n");
size_t num_installed = 0;
for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) {
@@ -288,7 +319,6 @@ int spm_do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) {
// Relocate installation root
relocate_root(fs->rootdir, tmpdir);
-
spm_install_package_record(fs, tmpdir, requirements[i]->name);
num_installed++;
free(package_path);
diff --git a/lib/purge.c b/lib/purge.c
index 997df51..da3e5e6 100644
--- a/lib/purge.c
+++ b/lib/purge.c
@@ -14,6 +14,7 @@ int spm_purge(SPM_Hierarchy *fs, const char *_package_name) {
char *package_topdir = join((char *[]) {fs->dbrecdir, package_name, NULL}, DIRSEPS);
char *descriptor = join((char *[]) {package_topdir, SPM_META_DESCRIPTOR, NULL}, DIRSEPS);
char *filelist = join((char *[]) {package_topdir, SPM_META_FILELIST, NULL}, DIRSEPS);
+ char *rootrec = join((char *[]){path, "var", ".spm_root"}, DIRSEPS);
if (spm_check_installed(fs, package_name) == 0) {
// package is not installed in this root
@@ -67,6 +68,11 @@ int spm_purge(SPM_Hierarchy *fs, const char *_package_name) {
int spm_do_purge(SPM_Hierarchy *fs, StrList *packages) {
int status_remove = 0;
+ if (spm_hierarchy_is_root(fs) < 0) {
+ spmerrno = SPM_ERR_ROOT_NO_RECORD;
+ return -1;
+ }
+
printf("Removing package(s):\n");
for (size_t i = 0; i < strlist_count(packages); i++) {
char *package = strlist_item(packages, i);
diff --git a/src/spm.c b/src/spm.c
index e2e7a8f..bb58401 100644
--- a/src/spm.c
+++ b/src/spm.c
@@ -128,6 +128,13 @@ int main(int argc, char *argv[], char *arge[]) {
usage(program_name);
exit(1);
}
+
+ // Installing into the system's root is forbidden for obvious reasons
+ if (strcmp(arg_next, DIRSEPS) == 0) {
+ fprintf(stderr, "FATAL: refusing to operate on the system root directory\n");
+ exit(1);
+ }
+
strcpy(rootdir, arg_next);
i++;
}
@@ -236,7 +243,10 @@ int main(int argc, char *argv[], char *arge[]) {
if (RUNTIME_INSTALL) {
int status_install = 0;
if ((status_install = spm_do_install(rootfs, mf, packages)) == -1) {
- // failed to create temporary destination root
+ // general failure
+ if (spmerrno) {
+ spm_perror("Failed with reason");
+ }
exit(1);
} else if (status_install == -2) {
// user said no when asked to proceed