]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - usr.sbin/pkg_install/lib/url.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / usr.sbin / pkg_install / lib / url.c
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$");
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  */
35 char *
36 fileGetURL(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                 strcat(cp, ".tbz");
76             }
77             else
78                 return NULL;
79         }
80         else {
81             /*
82              * Otherwise, we've been given an environment variable hinting
83              * at the right location from sysinstall
84              */
85             strcpy(fname, hint);
86             strcat(fname, spec);
87             strcat(fname, ".tbz");
88         }
89     }
90     else
91         strcpy(fname, spec);
92
93     if (keep_package) {
94         tmp = getenv("PKGDIR");
95         strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
96         tmp = basename(fname);
97         strlcat(pkg, "/", sizeof(pkg));
98         strlcat(pkg, tmp, sizeof(pkg));
99         if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
100             printf("Error: Unable to open %s\n", pkg);
101             perror("open");
102             return NULL;
103         }
104     }
105
106     fetchDebug = (Verbose > 0);
107     if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
108         printf("Error: FTP Unable to get %s: %s\n",
109                fname, fetchLastErrString);
110         return NULL;
111     }
112
113     if (isatty(0) || Verbose)
114         printf("Fetching %s...", fname), fflush(stdout);
115     pen[0] = '\0';
116     if ((rp = make_playpen(pen, 0)) == NULL) {
117         printf("Error: Unable to construct a new playpen for FTP!\n");
118         fclose(ftp);
119         return NULL;
120     }
121     if (pipe(pfd) == -1) {
122         warn("pipe()");
123         cleanup(0);
124         exit(2);
125     }
126     if ((tpid = fork()) == -1) {
127         warn("pipe()");
128         cleanup(0);
129         exit(2);
130     }
131     if (!tpid) {
132         dup2(pfd[0], 0);
133         for (fd = getdtablesize() - 1; fd >= 3; --fd)
134             close(fd);
135         execl("/usr/bin/tar", "tar",
136             Verbose ? "-xpjvf" : "-xpjf",
137             "-", (char *)0);
138         _exit(2);
139     }
140     close(pfd[0]);
141     for (;;) {
142         if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
143             break;
144         if ((w = write(pfd[1], buf, r)) != r)
145             break;
146         if (keep_package) {
147             if ((w = write(pkgfd, buf, r)) != r)
148                 break;
149         }    
150     }
151     if (ferror(ftp))
152         warn("warning: error reading from server");
153     fclose(ftp);
154     if (keep_package) {
155         close(pkgfd);
156     } 
157     close(pfd[1]);
158     if (w == -1)
159         warn("warning: error writing to tar");
160     tpid = waitpid(tpid, &pstat, 0);
161     if (Verbose)
162         printf("tar command returns %d status\n", WEXITSTATUS(pstat));
163     if (rp && (isatty(0) || Verbose))
164         printf(" Done.\n");
165     return rp;
166 }