diff options
Diffstat (limited to 'src/install.c')
-rw-r--r-- | src/install.c | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/src/install.c b/src/install.c deleted file mode 100644 index e0592db..0000000 --- a/src/install.c +++ /dev/null @@ -1,328 +0,0 @@ -/** - * @file install.c - */ -#include <url.h> -#include "spm.h" - -void spm_install_show_package(ManifestPackage *package) { - if (package == NULL) { - fprintf(stderr, "ERROR: package was NULL\n"); - return; - } - printf(" -> %-20s %-10s (origin: %s)\n", package->name, package->version, package->origin); -} - -/** - * Install a package and its dependencies into a destination root. - * The destination is created if it does not exist. - * @param _destroot directory to install 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 spm_install(SPM_Hierarchy *fs, const char *tmpdir, const char *_package) { - char *package = strdup(_package); - - if (!package) { - fprintf(SYSERROR); - 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); - } - - if (tar_extract_archive(package, tmpdir) != 0) { - fprintf(stderr, "%s: %s\n", package, strerror(errno)); - free(package); - return -1; - } - - free(package); - return 0; -} - -int spm_install_package_record(SPM_Hierarchy *fs, char *tmpdir, char *package_name) { - RuntimeEnv *rt = runtime_copy(__environ); - char *records_topdir = strdup(fs->dbrecdir); - char *records_pkgdir = join((char *[]) {records_topdir, package_name, 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) { - return -1; - } - } - - if (exists(descriptor) != 0) { - fprintf(stderr, "Missing: %s\n", descriptor); - return 1; - } - - if (exists(filelist) != 0) { - fprintf(stderr, "Missing: %s\n", filelist); - return 2; - } - - if (rsync(NULL, descriptor, records_pkgdir) != 0) { - fprintf(stderr, "Failed to copy '%s' to '%s'\n", descriptor, records_pkgdir); - return 3; - } - - if (rsync(NULL, filelist, records_pkgdir) != 0) { - fprintf(stderr, "Failed to copy '%s' to '%s'\n", filelist, records_pkgdir); - return 4; - } - - free(records_topdir); - free(records_pkgdir); - free(descriptor); - free(filelist); - runtime_free(rt); - return 0; -} - -int spm_check_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); - - 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) || exists(descriptor) || exists(descriptor)) != 0) { - free(records_topdir); - free(records_pkgdir); - free(descriptor); - free(filelist); - return 0; // does not exist - } - - data = spm_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++) { - free(data[i]); - } - free(data); - - free(records_topdir); - free(records_pkgdir); - free(descriptor); - free(filelist); - return 1; // exists -} - -/** - * - * @return - */ -char *spm_install_fetch(const char *pkgdir, const char *_package) { - char *package = strdup(_package); - if (package == NULL) { - perror("could not allocate memory for package name"); - fprintf(SYSERROR); - return NULL; - } - - long response = 0; - char *url = strdup(package); - char *payload = join_ex(DIRSEPS, pkgdir, basename(package), NULL); - size_t tmp_package_len = strlen(payload); - - if (tmp_package_len > strlen(package)) { - char *tmp = realloc(package, (tmp_package_len + 1) * sizeof(char)); - if (tmp == NULL) { - perror("cannot realloc package path"); - return NULL; - } - package = tmp; - } - strcpy(package, payload); - - if (exists(payload) != 0) { - if ((response = fetch(url, package)) >= 400) { - fprintf(stderr, "HTTP(%ld): %s\n", response, http_response_str(response)); - return NULL; - } - } - free(url); - free(payload); - - return package; -} - -/** - * Perform a full package installation - * @param mf - * @param rootdir - * @param packages - * @return 0=success, -1=failed to create storage, -2=denied by user - */ -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("spm_destroot", NULL); - - if (tmpdir == NULL) { - perror("Could not create temporary destination root"); - fprintf(SYSERROR); - return -1; - } - - if (SPM_GLOBAL.verbose) { - printf("Installation root: %s\n", fs->rootdir); - } - - // 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++) { - spm_install_show_package(requirements[i]); - } - - if (SPM_GLOBAL.prompt_user) { - if (spm_prompt_user("Proceed with installation?", 1) == 0) { - exit(-2); - } - } - - int fetched = 0; - 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); - - if (strstr(package_origin, SPM_GLOBAL.repo_target) == NULL) { - if (!endswith(package_origin, DIRSEPS)) { - strcat(package_origin, DIRSEPS); - } - strcat(package_origin, SPM_GLOBAL.repo_target); - } - - char *package_path = join((char *[]) {package_origin, requirements[i]->archive, NULL}, DIRSEPS); - char *package_localpath = join_ex(DIRSEPS, package_dir, requirements[i]->archive, NULL); - free(package_origin); - - // Download the archive if necessary - if (strstr(package_path, "://") != NULL && exists(package_localpath) != 0) { - printf("Fetching: %s\n", package_path); - package_path = spm_install_fetch(package_dir, package_path); - if (package_path == NULL) { - free(package_path); - free(package_localpath); - exit(1); - } - fetched = 1; - } - // Or copy the archive if necessary - else { - // TODO: Possibly an issue down the road, but not at the moment - // You have another local manifest in use. Copy any used packages from there into the local package directory. - if (exists(package_localpath) != 0 && strncmp(package_dir, package_path, strlen(package_dir)) != 0) { - printf("Copying: %s\n", package_path); - if (rsync(NULL, package_path, package_dir) != 0) { - fprintf(stderr, "Unable to copy: %s to %s\n", package_path, package_dir); - return -1; - } - fetched = 1; - } else if (exists(package_localpath) != 0) { - // All attempts to retrieve the requested package have failed. Die. - fprintf(stderr, "Package manifest in '%s' claims '%s' exists, however it does not.\n", requirements[i]->origin, package_path); - return -1; - } - } - free(package_path); - free(package_localpath); - } - - // Update the package manifest - if (fetched) { - printf("Updating package manifest...\n"); - Manifest *tmp_manifest = manifest_from(SPM_GLOBAL.package_dir); - manifest_write(tmp_manifest, package_dir); - manifest_free(tmp_manifest); - } - - printf("Installing package(s):\n"); - size_t num_installed = 0; - for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) { - char *package_path = join((char *[]) {package_dir, requirements[i]->archive, NULL}, DIRSEPS); - - if (spm_check_installed(fs, requirements[i]->name)) { - printf(" -> %s is already installed\n", requirements[i]->name); - free(package_path); - continue; - } - - spm_install_show_package(requirements[i]); - spm_install(fs, tmpdir, package_path); - - // Relocate installation root - relocate_root(fs->rootdir, tmpdir); - - spm_install_package_record(fs, tmpdir, requirements[i]->name); - num_installed++; - free(package_path); - } - - // free requirements array - for (size_t i = 0; requirements != NULL && requirements[i] != NULL; i++) { - manifest_package_free(requirements[i]); - } - free(package_dir); - - if (num_installed != 0) { - // Append a trailing slash to tmpdir to direct rsync to copy files, not the directory, into destroot - sprintf(source, "%s%c", tmpdir, DIRSEP); - - // Remove metadata files before copying - if (SPM_GLOBAL.verbose) { - printf("Removing metadata\n"); - } - spm_metadata_remove(source); - - // Copy temporary directory to destination - if (SPM_GLOBAL.verbose) { - printf("Installing tree: '%s' => '%s'\n", source, fs->rootdir); - } - - if (rsync(NULL, source, fs->rootdir) != 0) { - exit(1); - } - } - - if (SPM_GLOBAL.verbose) { - printf("Removing temporary storage: '%s'\n", tmpdir); - } - rmdirs(tmpdir); - return 0; -} |