]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.sbin/pkg_install/lib/url.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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 const char *
36 fileGetURL(const char *base, const char *spec, int keep_package)
37 {
38     const char *rp;
39     char *cp, *tmp;
40     char fname[FILENAME_MAX];
41     char pen[FILENAME_MAX];
42     char pkg[FILENAME_MAX];
43     char buf[8192];
44     FILE *ftp;
45     pid_t tpid;
46     int pfd[2], pstat, r, w = 0;
47     char *hint;
48     int fd, pkgfd = 0;
49
50     rp = NULL;
51     /* Special tip that sysinstall left for us */
52     hint = getenv("PKG_ADD_BASE");
53     if (!isURL(spec)) {
54         if (!base && !hint)
55             return NULL;
56         /*
57          * We've been given an existing URL (that's known-good) and now we need
58          * to construct a composite one out of that and the basename we were
59          * handed as a dependency.
60          */
61         if (base) {
62             strcpy(fname, base);
63             /*
64              * Advance back two slashes to get to the root of the package
65              * hierarchy
66              */
67             cp = strrchr(fname, '/');
68             if (cp) {
69                 *cp = '\0';     /* chop name */
70                 cp = strrchr(fname, '/');
71             }
72             if (cp) {
73                 *(cp + 1) = '\0';
74                 strcat(cp, "All/");
75                 strcat(cp, spec);
76                 strcat(cp, ".tbz");
77             }
78             else
79                 return NULL;
80         }
81         else {
82             /*
83              * Otherwise, we've been given an environment variable hinting
84              * at the right location from sysinstall
85              */
86             strcpy(fname, hint);
87             strcat(fname, spec);
88             strcat(fname, ".tbz");
89         }
90     }
91     else
92         strcpy(fname, spec);
93
94     if (keep_package) {
95         tmp = getenv("PKGDIR");
96         strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
97         tmp = basename(fname);
98         strlcat(pkg, "/", sizeof(pkg));
99         strlcat(pkg, tmp, sizeof(pkg));
100         if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
101             printf("Error: Unable to open %s\n", pkg);
102             perror("open");
103             return NULL;
104         }
105     }
106
107     fetchDebug = (Verbose > 0);
108     if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
109         printf("Error: Unable to get %s: %s\n",
110                fname, fetchLastErrString);
111         return NULL;
112     }
113
114     if (isatty(0) || Verbose)
115         printf("Fetching %s...", fname), fflush(stdout);
116     pen[0] = '\0';
117     if ((rp = make_playpen(pen, 0)) == NULL) {
118         printf("Error: Unable to construct a new playpen for FTP!\n");
119         fclose(ftp);
120         return NULL;
121     }
122     if (pipe(pfd) == -1) {
123         warn("pipe()");
124         cleanup(0);
125         exit(2);
126     }
127     if ((tpid = fork()) == -1) {
128         warn("pipe()");
129         cleanup(0);
130         exit(2);
131     }
132     if (!tpid) {
133         dup2(pfd[0], 0);
134         for (fd = getdtablesize() - 1; fd >= 3; --fd)
135             close(fd);
136         execl("/usr/bin/tar", "tar",
137             Verbose ? "-xpjvf" : "-xpjf",
138             "-", (char *)0);
139         _exit(2);
140     }
141     close(pfd[0]);
142     for (;;) {
143         if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
144             break;
145         if ((w = write(pfd[1], buf, r)) != r)
146             break;
147         if (keep_package) {
148             if ((w = write(pkgfd, buf, r)) != r)
149                 break;
150         }    
151     }
152     if (ferror(ftp))
153         warn("warning: error reading from server");
154     fclose(ftp);
155     if (keep_package) {
156         close(pkgfd);
157     } 
158     close(pfd[1]);
159     if (w == -1)
160         warn("warning: error writing to tar");
161     tpid = waitpid(tpid, &pstat, 0);
162     if (Verbose)
163         printf("tar command returns %d status\n", WEXITSTATUS(pstat));
164     if (rp && (isatty(0) || Verbose))
165         printf(" Done.\n");
166     return rp;
167 }