diff options
-rw-r--r-- | include/conf.h | 1 | ||||
-rw-r--r-- | include/install.h | 2 | ||||
-rw-r--r-- | lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/config_global.c | 6 | ||||
-rw-r--r-- | lib/fs.c | 2 | ||||
-rw-r--r-- | lib/install.c | 54 | ||||
-rw-r--r-- | lib/purge.c | 6 | ||||
-rw-r--r-- | src/spm.c | 12 |
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); } @@ -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); @@ -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 |