diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-02-26 16:09:32 -0500 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2020-02-26 16:09:32 -0500 |
commit | d3580f8c0b5c17150382c4b4456e0b1bfa81a50f (patch) | |
tree | 5d0fa6911974b2a0541738a7cffc408b09918b8b | |
parent | 639aa9dbf60050bf1bbaeea67df13729239c3a31 (diff) | |
download | spmc-d3580f8c0b5c17150382c4b4456e0b1bfa81a50f.tar.gz |
Multiple things:
* Add strdup_array()
* Begin consolidating spm root information into SPM_Hierarchy
* Begin consolidating metadata
* Begin trimming repeated code (mostly file reading)
* Store information about installed packages under [root]/var/db/records
-rw-r--r-- | include/conf.h | 16 | ||||
-rw-r--r-- | include/install.h | 9 | ||||
-rw-r--r-- | include/metadata.h | 12 | ||||
-rw-r--r-- | include/mirrors.h | 2 | ||||
-rw-r--r-- | include/spm.h | 1 | ||||
-rw-r--r-- | include/str.h | 1 | ||||
-rw-r--r-- | src/CMakeLists.txt | 29 | ||||
-rw-r--r-- | src/config_global.c | 67 | ||||
-rw-r--r-- | src/fs.c | 4 | ||||
-rw-r--r-- | src/install.c | 68 | ||||
-rw-r--r-- | src/manifest.c | 2 | ||||
-rw-r--r-- | src/metadata.c | 128 | ||||
-rw-r--r-- | src/mirrors.c | 41 | ||||
-rw-r--r-- | src/spm.c | 31 | ||||
-rw-r--r-- | src/str.c | 24 |
15 files changed, 356 insertions, 79 deletions
diff --git a/include/conf.h b/include/conf.h index 80ba457..99d550d 100644 --- a/include/conf.h +++ b/include/conf.h @@ -13,11 +13,14 @@ typedef struct { } ConfigItem; typedef struct { - char *binpath; - char *includepath; - char *libpath; - char *datapath; - char *manpath; + char *rootdir; + char *bindir; + char *includedir; + char *libdir; + char *datadir; + char *mandir; + char *sysconfdir; + char *localstatedir; } SPM_Hierarchy; typedef struct { @@ -52,4 +55,7 @@ void free_global_config(void); void show_global_config(void); void check_runtime_environment(void); +SPM_Hierarchy *spm_hierarchy_init(char *basepath); +void spm_hierarchy_free(SPM_Hierarchy *fs); + #endif //SPM_CONF_H diff --git a/include/install.h b/include/install.h index a3118c7..94a49df 100644 --- a/include/install.h +++ b/include/install.h @@ -3,9 +3,10 @@ int metadata_remove(const char *_path); void install_show_package(ManifestPackage *package); -int install(const char *destroot, const char *tmpdir, const char *_package); -int install_package_record(char *from_root, char *package_name); -int is_installed(const char *rootdir, char *package_name); -int do_install(ManifestList *mf, const char *rootdir, StrList *packages); +int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package); +int install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name); +int is_installed(SPM_Hierarchy *fs, char *package_name); +int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages); + #endif //SPM_INSTALL_H diff --git a/include/metadata.h b/include/metadata.h new file mode 100644 index 0000000..bb864f6 --- /dev/null +++ b/include/metadata.h @@ -0,0 +1,12 @@ +#ifndef SPM_METADATA_H +#define SPM_METADATA_H + +#define SPM_METADATA_VERIFY 0 << 1 +#define SPM_METADATA_NO_VERIFY 1 << 1 + +typedef int (ReaderFn)(size_t line, char **); + +char **metadata_filelist_read(const char *filename); +char **metadata_read(const char *filename, int no_verify); + +#endif //SPM_METADATA_H diff --git a/include/mirrors.h b/include/mirrors.h index 1be39f6..7cf4236 100644 --- a/include/mirrors.h +++ b/include/mirrors.h @@ -4,7 +4,7 @@ #define SPM_MIRROR_MAX 0xff #define SPM_MIRROR_FILENAME "mirrorlist" -char **file_readlines(const char *filename); +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn); char **mirror_list(const char *filename); void mirror_list_free(char **m); void mirror_clone(Manifest *info, char *dest); diff --git a/include/spm.h b/include/spm.h index 97d005a..690d1f9 100644 --- a/include/spm.h +++ b/include/spm.h @@ -34,6 +34,7 @@ #include "config.h" #include "internal_cmd.h" #include "environment.h" +#include "metadata.h" #include "manifest.h" #include "fs.h" #include "version_spec.h" diff --git a/include/str.h b/include/str.h index 2674fb9..06e4a77 100644 --- a/include/str.h +++ b/include/str.h @@ -23,5 +23,6 @@ char *strip(char *sptr); int isempty(char *sptr); int isquoted(char *sptr); char *normalize_space(char *s); +char **strdup_array(char **array); #endif //SPM_STR_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b2a2c26..06065a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,34 @@ include_directories( ${CMAKE_BINARY_DIR}/include ) -add_executable(spm spm.c config.c compat.c resolve.c fs.c rpath.c find.c shell.c archive.c str.c relocation.c install.c config_global.c manifest.c checksum.c extern/url.c version_spec.c spm_build.c mime.c internal_cmd.c environment.c mirrors.c strlist.c shlib.c user_input.c) +add_executable(spm + spm.c + config.c + compat.c + resolve.c + fs.c + rpath.c + find.c + shell.c + archive.c + str.c + relocation.c + install.c + config_global.c + manifest.c + checksum.c + extern/url.c + version_spec.c + spm_build.c + mime.c + internal_cmd.c + environment.c + mirrors.c + strlist.c + shlib.c + user_input.c + metadata.c +) target_link_libraries(spm crypto ssl curl) if (LINUX) diff --git a/src/config_global.c b/src/config_global.c index a43ae5b..fb97a61 100644 --- a/src/config_global.c +++ b/src/config_global.c @@ -155,6 +155,41 @@ void check_runtime_environment(void) { } /** + * + * @param basepath + * @return + */ +SPM_Hierarchy *spm_hierarchy_init(char *basepath) { + SPM_Hierarchy *fs = calloc(1, sizeof(SPM_Hierarchy)); + fs->rootdir = strdup(basepath); + fs->bindir = join((char *[]) {fs->rootdir, "bin", NULL}, DIRSEPS); + fs->includedir = join((char *[]) {fs->rootdir, "include", NULL}, DIRSEPS); + fs->libdir = join((char *[]) {fs->rootdir, "lib", NULL}, DIRSEPS); + fs->datadir = join((char *[]) {fs->rootdir, "share", NULL}, DIRSEPS); + fs->localstatedir = join((char *[]) {fs->rootdir, "var", NULL}, DIRSEPS); + fs->sysconfdir = join((char *[]) {fs->rootdir, "etc", NULL}, DIRSEPS); + fs->mandir = join((char *[]) {fs->datadir, "man", NULL}, DIRSEPS); + + return fs; +} + +/** + * + * @param fs + */ +void spm_hierarchy_free(SPM_Hierarchy *fs) { + free(fs->rootdir); + free(fs->bindir); + free(fs->includedir); + free(fs->libdir); + free(fs->datadir); + free(fs->localstatedir); + free(fs->sysconfdir); + free(fs->mandir); + free(fs); +} + +/** * Populate global configuration structure */ void init_config_global(void) { @@ -175,23 +210,23 @@ void init_config_global(void) { } // Initialize filesystem paths structure - SPM_GLOBAL.fs.binpath = calloc(strlen(SPM_PROGRAM_BIN) + 1, sizeof(char)); - SPM_GLOBAL.fs.includepath = calloc(strlen(SPM_PROGRAM_INCLUDE) + 1, sizeof(char)); - SPM_GLOBAL.fs.libpath = calloc(strlen(SPM_PROGRAM_LIB) + 1, sizeof(char)); - SPM_GLOBAL.fs.datapath = calloc(strlen(SPM_PROGRAM_DATA) + 1, sizeof(char)); + SPM_GLOBAL.fs.bindir = calloc(strlen(SPM_PROGRAM_BIN) + 1, sizeof(char)); + SPM_GLOBAL.fs.includedir = calloc(strlen(SPM_PROGRAM_INCLUDE) + 1, sizeof(char)); + SPM_GLOBAL.fs.libdir = calloc(strlen(SPM_PROGRAM_LIB) + 1, sizeof(char)); + SPM_GLOBAL.fs.datadir = calloc(strlen(SPM_PROGRAM_DATA) + 1, sizeof(char)); - if (!SPM_GLOBAL.fs.binpath || !SPM_GLOBAL.fs.includepath - || !SPM_GLOBAL.fs.libpath) { + if (!SPM_GLOBAL.fs.bindir || !SPM_GLOBAL.fs.includedir + || !SPM_GLOBAL.fs.libdir) { perror("Unable to allocate memory for global filesystem paths"); fprintf(SYSERROR); exit(errno); } - strcpy(SPM_GLOBAL.fs.binpath, SPM_PROGRAM_BIN); - strcpy(SPM_GLOBAL.fs.includepath, SPM_PROGRAM_INCLUDE); - strcpy(SPM_GLOBAL.fs.libpath, SPM_PROGRAM_LIB); - strcpy(SPM_GLOBAL.fs.datapath, SPM_PROGRAM_DATA); - SPM_GLOBAL.fs.manpath = join((char *[]) {SPM_PROGRAM_DATA, "man", NULL}, DIRSEPS); + strcpy(SPM_GLOBAL.fs.bindir, SPM_PROGRAM_BIN); + strcpy(SPM_GLOBAL.fs.includedir, SPM_PROGRAM_INCLUDE); + strcpy(SPM_GLOBAL.fs.libdir, SPM_PROGRAM_LIB); + strcpy(SPM_GLOBAL.fs.datadir, SPM_PROGRAM_DATA); + SPM_GLOBAL.fs.mandir = join((char *[]) {SPM_PROGRAM_DATA, "man", NULL}, DIRSEPS); SPM_GLOBAL.user_config_basedir = get_user_conf_dir(); SPM_GLOBAL.user_config_file = get_user_config_file(); @@ -300,11 +335,11 @@ void free_global_config(void) { mirror_list_free(SPM_GLOBAL.mirror_list); } - free(SPM_GLOBAL.fs.binpath); - free(SPM_GLOBAL.fs.includepath); - free(SPM_GLOBAL.fs.libpath); - free(SPM_GLOBAL.fs.datapath); - free(SPM_GLOBAL.fs.manpath); + free(SPM_GLOBAL.fs.bindir); + free(SPM_GLOBAL.fs.includedir); + free(SPM_GLOBAL.fs.libdir); + free(SPM_GLOBAL.fs.datadir); + free(SPM_GLOBAL.fs.mandir); if (SPM_GLOBAL.config) { config_free(SPM_GLOBAL.config); } @@ -244,10 +244,10 @@ char *expandpath(const char *_path) { * - On UNIX, Win32 paths will be converted UNIX * - On Win32, UNIX paths will be converted to Win32 * - * This function is platform dependent. + * This function is platform dependent. The string is modified in-place. * * @param path a system path - * @return string (caller is responsible for `free`ing memory) + * @return string */ char *normpath(const char *path) { char *result = strdup(path); diff --git a/src/install.c b/src/install.c index 3603af5..2655626 100644 --- a/src/install.c +++ b/src/install.c @@ -48,7 +48,7 @@ void install_show_package(ManifestPackage *package) { * @param _package name of archive to install (not a path) * @return success=0, exists=1, error=-1 (general), -2 (unable to create `destroot`) */ -int install(const char *destroot, const char *tmpdir, const char *_package) { +int install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { char *package = strdup(_package); if (!package) { @@ -56,11 +56,11 @@ int install(const char *destroot, const char *tmpdir, const char *_package) { return -1; } - if (exists(destroot) != 0) { + if (exists(fs->rootdir) != 0) { if (SPM_GLOBAL.verbose) { - printf("Creating destination root: %s\n", destroot); + printf("Creating destination root: %s\n", fs->rootdir); } - if (mkdirs(destroot, 0755) != 0) { + if (mkdirs(fs->rootdir, 0755) != 0) { fprintf(SYSERROR); free(package); return -2; @@ -81,12 +81,12 @@ int install(const char *destroot, const char *tmpdir, const char *_package) { return 0; } -int install_package_record(char *from_root, char *package_name) { +int install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name) { RuntimeEnv *rt = runtime_copy(__environ); - char *records_topdir = normpath(runtime_expand_var(rt, "$SPM_LOCALSTATE/db/records")); + char *records_topdir = join((char *[]) {fs->localstatedir, "db", "records", NULL}, DIRSEPS); char *records_pkgdir = join((char *[]) {records_topdir, package_name, NULL}, DIRSEPS); - char *descriptor = join((char *[]) {from_root, SPM_META_DESCRIPTOR, NULL}, DIRSEPS); - char *filelist = join((char *[]) {from_root, SPM_META_FILELIST, NULL}, DIRSEPS); + char *descriptor = join((char *[]) {tmpdir, SPM_META_DESCRIPTOR, NULL}, DIRSEPS); + char *filelist = join((char *[]) {tmpdir, SPM_META_FILELIST, NULL}, DIRSEPS); if (exists(records_pkgdir) != 0) { if (mkdirs(records_pkgdir, 0755) != 0) { @@ -122,21 +122,41 @@ int install_package_record(char *from_root, char *package_name) { return 0; } -int is_installed(const char *rootdir, char *package_name) { - RuntimeEnv *rt = runtime_copy(__environ); - char *records_topdir = normpath(runtime_expand_var(rt, "$SPM_LOCALSTATE/db/records")); +int is_installed(SPM_Hierarchy *fs, char *package_name) { + char *records_topdir = join((char *[]) {fs->localstatedir, "db", "records", NULL}, DIRSEPS); char *records_pkgdir = join((char *[]) {records_topdir, package_name, NULL}, DIRSEPS); - int result = 1; // 1 == exists + char *descriptor = join((char *[]) {records_pkgdir, SPM_META_DESCRIPTOR, NULL}, DIRSEPS); + char *filelist = join((char *[]) {records_pkgdir, SPM_META_FILELIST, NULL}, DIRSEPS); + char **data = NULL; if (exists(records_pkgdir) != 0) { - // does not exist - result = 0; + free(records_topdir); + free(records_pkgdir); + free(descriptor); + free(filelist); + return 0; // does not exist + } + + data = metadata_read(filelist, SPM_METADATA_VERIFY); + if (data == NULL) { + free(records_topdir); + free(records_pkgdir); + free(descriptor); + free(filelist); + return -1; } + for (size_t i = 0; data[i] != NULL; i++) { + printf("%zu: %s\n", i, data[i]); + free(data[i]); + } + free(data); + free(records_topdir); free(records_pkgdir); - // exists - return result; + free(descriptor); + free(filelist); + return 1; // exists } /** @@ -146,7 +166,7 @@ int is_installed(const char *rootdir, char *package_name) { * @param packages * @return 0=success, -1=failed to create storage, -2=denied by user */ -int do_install(ManifestList *mf, const char *rootdir, StrList *packages) { +int do_install(SPM_Hierarchy *fs, ManifestList *mf, StrList *packages) { size_t num_requirements = 0; ManifestPackage **requirements = NULL; char source[PATH_MAX]; @@ -159,7 +179,7 @@ int do_install(ManifestList *mf, const char *rootdir, StrList *packages) { } if (SPM_GLOBAL.verbose) { - printf("Installation root: %s\n", rootdir); + printf("Installation root: %s\n", fs->rootdir); } // Produce a dependency tree from requested package(s) @@ -207,15 +227,15 @@ int do_install(ManifestList *mf, const char *rootdir, StrList *packages) { for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) { char *package_path = join((char *[]) {requirements[i]->origin, SPM_GLOBAL.repo_target, requirements[i]->archive, NULL}, DIRSEPS); - if (is_installed(rootdir, requirements[i]->name)) { + if (is_installed(fs, requirements[i]->name)) { printf(" -> %s is already installed\n", requirements[i]->name); free(package_path); continue; } install_show_package(requirements[i]); - install(rootdir, tmpdir, package_path); - install_package_record(tmpdir, requirements[i]->name); + install(fs, tmpdir, package_path); + install_package_record(fs, tmpdir, requirements[i]->name); num_installed++; free(package_path); } @@ -227,7 +247,7 @@ int do_install(ManifestList *mf, const char *rootdir, StrList *packages) { if (num_installed != 0) { // Relocate installation root - relocate_root(rootdir, tmpdir); + relocate_root(fs->rootdir, tmpdir); // Append a trailing slash to tmpdir to direct rsync to copy files, not the directory, into destroot sprintf(source, "%s%c", tmpdir, DIRSEP); @@ -240,10 +260,10 @@ int do_install(ManifestList *mf, const char *rootdir, StrList *packages) { // Copy temporary directory to destination if (SPM_GLOBAL.verbose) { - printf("Installing tree: '%s' => '%s'\n", source, rootdir); + printf("Installing tree: '%s' => '%s'\n", source, fs->rootdir); } - if (rsync(NULL, source, rootdir) != 0) { + if (rsync(NULL, source, fs->rootdir) != 0) { exit(1); } } diff --git a/src/manifest.c b/src/manifest.c index ba0fe6d..e971bb7 100644 --- a/src/manifest.c +++ b/src/manifest.c @@ -133,7 +133,7 @@ Manifest *manifest_from(const char *package_dir) { exit(1); } char *depfile = join((char *[]) {tmpdir, SPM_META_DEPENDS, NULL}, DIRSEPS); - info->packages[i]->requirements = file_readlines(depfile); + info->packages[i]->requirements = file_readlines(depfile, 0, 0, NULL); // Record count of requirement specs if (info->packages[i]->requirements != NULL) { diff --git a/src/metadata.c b/src/metadata.c new file mode 100644 index 0000000..d2bb078 --- /dev/null +++ b/src/metadata.c @@ -0,0 +1,128 @@ +#include "spm.h" + +static int verify_filelist(size_t lineno, char **a) { + if (lineno == 0) { + if (strncmp((*a), SPM_PACKAGE_HEADER_FILELIST, strlen(SPM_PACKAGE_HEADER_FILELIST)) != 0) { + fprintf(stderr, "invalid or missing header: line %zu: %s (expected: '%s')\n", + lineno, (*a), SPM_PACKAGE_HEADER_FILELIST); + return 1; + } + } + return -1; +} + +#pragma GCC diagnostic ignored "-Wunused-parameter" +static int verify_depends(size_t lineno, char **a) { + return -1; +} + +static int verify_descriptor(size_t lineno, char **a) { + if (lineno == 0) { + if (strncmp((*a), SPM_PACKAGE_HEADER_DESCRIPTOR, strlen(SPM_PACKAGE_HEADER_DESCRIPTOR)) != 0) { + fprintf(stderr, "invalid or missing header: line %zu: %s (expected: '%s')\n", + lineno, (*a), SPM_PACKAGE_HEADER_DESCRIPTOR); + return 1; + } + } + return -1; +} + +static int verify_prefix(size_t lineno, char **a) { + size_t parity = lineno % 2; + if (parity == 0 && *(*a) == '#') { + return 0; + } + else { + return 1; + } +} + +#pragma GCC diagnostic ignored "-Wunused-parameter" +static int verify_no_op(size_t lineno, char **a) { + return -1; +} + +#pragma GCC diagnostic ignored "-Wunused-parameter" +static int reader_metadata(size_t lineno, char **line) { + (*line) = strip((*line)); + if (isempty((*line))) { + return 1; // indicate "continue" + } + return 0; // indicate "ok" +} + +/** + * Detect the type of metadata based on file name and execute the appropriate function against each line + * in the file. Verification can be disabled by passing a non-zero value as the second argument. + * @param _filename + * @param no_verify SPM_METADATA_VERIFY or SPM_METADATA_NO_VERIFY + * @return array of strings (line endings removed) + */ +char **metadata_read(const char *_filename, int no_verify) { + char *filename = strdup(_filename); + char **data = NULL; + char **result = NULL; + size_t start = 0; + ReaderFn *func_verify; + + // Guard + if (file_is_metadata(filename) == 0) { + free(filename); + return NULL; + } + + // Setup function pointer and data starting offsets (if any) + if (strcmp(basename(filename), SPM_META_FILELIST) == 0) { + func_verify = verify_filelist; + start = 1; + } else if (strcmp(basename(filename), SPM_META_DESCRIPTOR) == 0) { + func_verify = verify_descriptor; + start = 1; + } else if (strcmp(basename(filename), SPM_META_DEPENDS) == 0) { + func_verify = verify_depends; + } else if (strcmp(basename(filename), SPM_META_PREFIX_BIN) == 0) { + func_verify = verify_prefix; + } else if (strcmp(basename(filename), SPM_META_PREFIX_TEXT) == 0) { + func_verify = verify_prefix; + } else { + func_verify = verify_no_op; + } + + // Get file contents + data = file_readlines(filename, 0, 0, reader_metadata); + + // Strip newlines and whitespace + for (size_t i = 0; data[i] != NULL; i++) { + data[i] = strip(data[i]); + } + + // Perform verification + if (no_verify == 0) { + for (size_t i = 0; data[i] != NULL; i++) { + int status = func_verify(i, &data[i]); + if (status > 0) { + fprintf(stderr, "%s: file verification failed\n", filename); + return NULL; + } else if (status < 0) { + // NOT AN ERROR + // a negative value indicates the verification function has processed enough information + // so we can gracefully + break; + } + } + } + + // If there was a header, duplicate the array from the start of the data + // Otherwise return the array + if (start > 0) { + result = strdup_array(&data[start]); + for (size_t i = 0; data[i] != NULL; i++) { + free(data[i]); + } + free(data); + } else { + result = data; + } + + return result; +} diff --git a/src/mirrors.c b/src/mirrors.c index 2275be4..6a67623 100644 --- a/src/mirrors.c +++ b/src/mirrors.c @@ -1,7 +1,7 @@ #include "spm.h" #include "url.h" -char **file_readlines(const char *filename) { +char **file_readlines(const char *filename, size_t start, size_t limit, ReaderFn *readerFn) { FILE *fp = NULL; char **result = NULL; char *buffer = NULL; @@ -34,13 +34,46 @@ char **file_readlines(const char *filename) { rewind(fp); + // Handle invalid start offset + if (start > lines) { + start = 0; + } + + // Adjust line count when start offset is non-zero + if (start != 0 && start < lines) { + lines -= start; + } + + + // Handle minimum and maximum limits + if (limit == 0 || limit > lines) { + limit = lines; + } + // Populate results array result = calloc(lines + 1, sizeof(char *)); - for (size_t i = 0; i < lines; i++) { + for (size_t i = start; i < limit; i++) { + if (i < start) { + continue; + } + if (fgets(buffer, BUFSIZ, fp) == NULL) { break; } - result[i] = strdup(buffer); + + if (readerFn != NULL) { + int status = readerFn(i - start, &buffer); + // A status greater than zero indicates we should ignore this line entirely and "continue" + // A status less than zero indicates we should "break" + // A zero status proceeds normally + if (status > 0) { + i--; + continue; + } else if (status < 0) { + break; + } + } + result[i - start] = strdup(buffer); } free(buffer); @@ -49,7 +82,7 @@ char **file_readlines(const char *filename) { } char **mirror_list(const char *filename) { - char **mirrors = file_readlines(filename); + char **mirrors = file_readlines(filename, 0, 0, NULL); char **result = NULL; size_t count; for (count = 0; mirrors[count] != NULL; count++); @@ -175,36 +175,24 @@ int main(int argc, char *argv[], char *arge[]) { sprintf(rootdir, "%s%c%s", getenv("HOME"), DIRSEP, "spm_root"); } + SPM_Hierarchy *rootfs = spm_hierarchy_init(rootdir); + // Construct installation runtime environment RuntimeEnv *rt = runtime_copy(arge); // TODO: Move environment allocation out of (above) this loop if possible // TODO: replace variables below with SPM_Hierarchy, and write some control functions - char *spm_bindir = join((char *[]) {rootdir, "bin", NULL}, DIRSEPS); - char *spm_includedir = join((char *[]) {rootdir, "include", NULL}, DIRSEPS); - char *spm_libdir = join((char *[]) {rootdir, "lib", NULL}, DIRSEPS); - char *spm_datadir = join((char *[]) {rootdir, "share", NULL}, DIRSEPS); - char *spm_mandir = join((char *[]) {spm_datadir, "man", NULL}, DIRSEPS); - char *spm_localstatedir = join((char *[]) {rootdir, "var", NULL}, DIRSEPS); - - runtime_set(rt, "SPM_BIN", spm_bindir); - runtime_set(rt, "SPM_INCLUDE", spm_includedir); - runtime_set(rt, "SPM_LIB", spm_libdir); - runtime_set(rt, "SPM_DATA", spm_datadir); - runtime_set(rt, "SPM_MAN", spm_mandir); - runtime_set(rt, "SPM_LOCALSTATE", spm_localstatedir); + runtime_set(rt, "SPM_BIN", rootfs->bindir); + runtime_set(rt, "SPM_INCLUDE", rootfs->includedir); + runtime_set(rt, "SPM_LIB", rootfs->libdir); + runtime_set(rt, "SPM_DATA", rootfs->datadir); + runtime_set(rt, "SPM_MAN", rootfs->mandir); + runtime_set(rt, "SPM_LOCALSTATE", rootfs->localstatedir); runtime_apply(rt); - free(spm_bindir); - free(spm_includedir); - free(spm_libdir); - free(spm_datadir); - free(spm_mandir); - free(spm_localstatedir); - if (RUNTIME_INSTALL) { int status_install = 0; - if ((status_install = do_install(mf, rootdir, packages)) == -1) { + if ((status_install = do_install(rootfs, mf, packages)) == -1) { // failed to create temporary destination root exit(1); } @@ -287,5 +275,6 @@ int main(int argc, char *argv[], char *arge[]) { free_global_config(); strlist_free(packages); manifestlist_free(mf); + spm_hierarchy_free(rootfs); return 0; } @@ -597,4 +597,28 @@ char *normalize_space(char *s) { return result; } +/** + * Duplicate an array of strings + * @param array + * @return + */ +char **strdup_array(char **array) { + char **result = NULL; + size_t elems = 0; + + // Guard + if (array == NULL) { + return NULL; + } + // Count elements in `array` + for (elems = 0; array[elems] != NULL; elems++); + + // Create new array + result = calloc(elems + 1, sizeof(char *)); + for (size_t i = 0; i < elems; i++) { + result[i] = strdup(array[i]); + } + + return result; +} |