url.c revision 167972
1/* 2 * FreeBSD install - a package for the installation and maintainance 3 * of non-core utilities. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * Jordan K. Hubbard 15 * 18 July 1993 16 * 17 * URL file access utilities. 18 * 19 */ 20 21#include <sys/cdefs.h> 22__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/lib/url.c 167972 2007-03-28 05:33:52Z njl $"); 23 24#include "lib.h" 25#include <err.h> 26#include <fetch.h> 27#include <libgen.h> 28#include <sys/wait.h> 29#include <stdio.h> 30 31/* 32 * Try and fetch a file by URL, returning the directory name for where 33 * it's unpacked, if successful. 34 */ 35char * 36fileGetURL(const char *base, const char *spec, int keep_package) 37{ 38 char *cp, *rp, *tmp; 39 char fname[FILENAME_MAX]; 40 char pen[FILENAME_MAX]; 41 char pkg[FILENAME_MAX]; 42 char buf[8192]; 43 FILE *ftp; 44 pid_t tpid; 45 int pfd[2], pstat, r, w = 0; 46 char *hint; 47 int fd, pkgfd = 0; 48 49 rp = NULL; 50 /* Special tip that sysinstall left for us */ 51 hint = getenv("PKG_ADD_BASE"); 52 if (!isURL(spec)) { 53 if (!base && !hint) 54 return NULL; 55 /* 56 * We've been given an existing URL (that's known-good) and now we need 57 * to construct a composite one out of that and the basename we were 58 * handed as a dependency. 59 */ 60 if (base) { 61 strcpy(fname, base); 62 /* 63 * Advance back two slashes to get to the root of the package 64 * hierarchy 65 */ 66 cp = strrchr(fname, '/'); 67 if (cp) { 68 *cp = '\0'; /* chop name */ 69 cp = strrchr(fname, '/'); 70 } 71 if (cp) { 72 *(cp + 1) = '\0'; 73 strcat(cp, "All/"); 74 strcat(cp, spec); 75#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 76 strcat(cp, ".tbz"); 77#else 78 strcat(cp, ".tgz"); 79#endif 80 } 81 else 82 return NULL; 83 } 84 else { 85 /* 86 * Otherwise, we've been given an environment variable hinting 87 * at the right location from sysinstall 88 */ 89 strcpy(fname, hint); 90 strcat(fname, spec); 91#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 92 strcat(fname, ".tbz"); 93#else 94 strcat(fname, ".tgz"); 95#endif 96 } 97 } 98 else 99 strcpy(fname, spec); 100 101 if (keep_package) { 102 tmp = getenv("PKGDIR"); 103 strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg)); 104 tmp = basename(fname); 105 strlcat(pkg, "/", sizeof(pkg)); 106 strlcat(pkg, tmp, sizeof(pkg)); 107 if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { 108 printf("Error: Unable to open %s\n", pkg); 109 perror("open"); 110 return NULL; 111 } 112 } 113 114 fetchDebug = (Verbose > 0); 115 if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) { 116 printf("Error: FTP Unable to get %s: %s\n", 117 fname, fetchLastErrString); 118 return NULL; 119 } 120 121 if (isatty(0) || Verbose) 122 printf("Fetching %s...", fname), fflush(stdout); 123 pen[0] = '\0'; 124 if ((rp = make_playpen(pen, 0)) == NULL) { 125 printf("Error: Unable to construct a new playpen for FTP!\n"); 126 fclose(ftp); 127 return NULL; 128 } 129 if (pipe(pfd) == -1) { 130 warn("pipe()"); 131 cleanup(0); 132 exit(2); 133 } 134 if ((tpid = fork()) == -1) { 135 warn("pipe()"); 136 cleanup(0); 137 exit(2); 138 } 139 if (!tpid) { 140 dup2(pfd[0], 0); 141 for (fd = getdtablesize() - 1; fd >= 3; --fd) 142 close(fd); 143 execl("/usr/bin/tar", "tar", 144#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 145 Verbose ? "-xpjvf" : "-xpjf", 146#else 147 Verbose ? "-xpzvf" : "-xpzf", 148#endif 149 "-", (char *)0); 150 _exit(2); 151 } 152 close(pfd[0]); 153 for (;;) { 154 if ((r = fread(buf, 1, sizeof buf, ftp)) < 1) 155 break; 156 if ((w = write(pfd[1], buf, r)) != r) 157 break; 158 if (keep_package) { 159 if ((w = write(pkgfd, buf, r)) != r) 160 break; 161 } 162 } 163 if (ferror(ftp)) 164 warn("warning: error reading from server"); 165 fclose(ftp); 166 if (keep_package) { 167 close(pkgfd); 168 } 169 close(pfd[1]); 170 if (w == -1) 171 warn("warning: error writing to tar"); 172 tpid = waitpid(tpid, &pstat, 0); 173 if (Verbose) 174 printf("tar command returns %d status\n", WEXITSTATUS(pstat)); 175 if (rp && (isatty(0) || Verbose)) 176 printf(" Done.\n"); 177 return rp; 178} 179