diff options
Diffstat (limited to 'lib/libpkg/url.c')
-rw-r--r-- | lib/libpkg/url.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/lib/libpkg/url.c b/lib/libpkg/url.c new file mode 100644 index 0000000..4c10849 --- /dev/null +++ b/lib/libpkg/url.c @@ -0,0 +1,171 @@ +/* + * FreeBSD install - a package for the installation and maintainance + * of non-core utilities. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Jordan K. Hubbard + * 18 July 1993 + * + * URL file access utilities. + * + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "pkg.h" +#include <err.h> +#include <fetch.h> +#include <libgen.h> +#include <sys/wait.h> +#include <stdio.h> + +/* + * Try and fetch a file by URL, returning the directory name for where + * it's unpacked, if successful. + */ +const char * +fileGetURL(const char *base, const char *spec, int keep_package) +{ + const char *rp; + char *cp, *tmp; + char fname[FILENAME_MAX]; + char pen[FILENAME_MAX]; + char pkg[FILENAME_MAX]; + char buf[8192]; + FILE *ftp; + pid_t tpid; + int pfd[2], pstat, r, w = 0; + char *hint; + int fd, pkgfd = 0; + + rp = NULL; + /* Special tip that sysinstall left for us */ + hint = getenv("PKG_ADD_BASE"); + if (!isURL(spec)) { + if (!base && !hint) + return NULL; + /* + * We've been given an existing URL (that's known-good) and now we need + * to construct a composite one out of that and the basename we were + * handed as a dependency. + */ + if (base) { + strcpy(fname, base); + /* + * Advance back two slashes to get to the root of the package + * hierarchy + */ + cp = strrchr(fname, '/'); + if (cp) { + *cp = '\0'; /* chop name */ + cp = strrchr(fname, '/'); + } + if (cp) { + *(cp + 1) = '\0'; + strcat(cp, "All/"); + strcat(cp, spec); + strcat(cp, ".tbz"); + } + else + return NULL; + } + else { + /* + * Otherwise, we've been given an environment variable hinting + * at the right location from sysinstall + */ + strcpy(fname, hint); + strcat(fname, spec); + strcat(fname, ".tbz"); + } + } + else + strcpy(fname, spec); + + if (keep_package) { + tmp = getenv("PKGDIR"); + strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg)); + tmp = basename(fname); + strlcat(pkg, "/", sizeof(pkg)); + strlcat(pkg, tmp, sizeof(pkg)); + if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { + printf("Error: Unable to open %s\n", pkg); + perror("open"); + return NULL; + } + } + + fetchDebug = (Verbose > 0); + if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) { + printf("Error: Unable to get %s: %s\n", + fname, fetchLastErrString); + /* If the fetch fails, yank the package. */ + if (keep_package && unlink(pkg) < 0) { + warnx("failed to remove partially fetched package: %s", pkg); + } + return NULL; + } + + if (isatty(0) || Verbose) + printf("Fetching %s...", fname), fflush(stdout); + pen[0] = '\0'; + if ((rp = make_playpen(pen, 0)) == NULL) { + printf("Error: Unable to construct a new playpen for FTP!\n"); + fclose(ftp); + return NULL; + } + if (pipe(pfd) == -1) { + warn("pipe()"); + cleanup(0); + exit(2); + } + if ((tpid = fork()) == -1) { + warn("pipe()"); + cleanup(0); + exit(2); + } + if (!tpid) { + dup2(pfd[0], 0); + for (fd = getdtablesize() - 1; fd >= 3; --fd) + close(fd); + execl("/usr/bin/tar", "tar", + Verbose ? "-xpjvf" : "-xpjf", + "-", (char *)0); + _exit(2); + } + close(pfd[0]); + for (;;) { + if ((r = fread(buf, 1, sizeof buf, ftp)) < 1) + break; + if ((w = write(pfd[1], buf, r)) != r) + break; + if (keep_package) { + if ((w = write(pkgfd, buf, r)) != r) + break; + } + } + if (ferror(ftp)) + warn("warning: error reading from server"); + fclose(ftp); + if (keep_package) { + close(pkgfd); + } + close(pfd[1]); + if (w == -1) + warn("warning: error writing to tar"); + tpid = waitpid(tpid, &pstat, 0); + if (Verbose) + printf("tar command returns %d status\n", WEXITSTATUS(pstat)); + if (rp && (isatty(0) || Verbose)) + printf(" Done.\n"); + return rp; +} |