]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/pkg_install/lib/url.c
This commit was generated by cvs2svn to compensate for changes in r175256,
[FreeBSD/FreeBSD.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 #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 }