]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/pkg_install/lib/url.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.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 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                 if (getenv("PACKAGESUFFIX"))
77                    strcat(cp, getenv("PACKAGESUFFIX"));
78                 else
79                    strcat(cp, ".tbz");
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 (getenv("PACKAGESUFFIX"))
92                strcat(fname, getenv("PACKAGESUFFIX"));
93             else
94                strcat(fname, ".tbz");
95         }
96     }
97     else
98         strcpy(fname, spec);
99
100     if (keep_package) {
101         tmp = getenv("PKGDIR");
102         strlcpy(pkg, tmp ? tmp : ".", sizeof(pkg));
103         tmp = basename(fname);
104         strlcat(pkg, "/", sizeof(pkg));
105         strlcat(pkg, tmp, sizeof(pkg));
106         if ((pkgfd = open(pkg, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
107             printf("Error: Unable to open %s\n", pkg);
108             perror("open");
109             return NULL;
110         }
111     }
112
113     fetchDebug = (Verbose > 0);
114     if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
115         printf("Error: Unable to get %s: %s\n",
116                fname, fetchLastErrString);
117         /* If the fetch fails, yank the package. */
118         if (keep_package && unlink(pkg) < 0 && Verbose) {
119             warnx("failed to remove partially fetched package: %s", pkg);
120         }
121         return NULL;
122     }
123
124     if (isatty(0) || Verbose)
125         printf("Fetching %s...", fname), fflush(stdout);
126     pen[0] = '\0';
127     if ((rp = make_playpen(pen, 0)) == NULL) {
128         printf("Error: Unable to construct a new playpen for FTP!\n");
129         fclose(ftp);
130         return NULL;
131     }
132     if (pipe(pfd) == -1) {
133         warn("pipe()");
134         cleanup(0);
135         exit(2);
136     }
137     if ((tpid = fork()) == -1) {
138         warn("pipe()");
139         cleanup(0);
140         exit(2);
141     }
142     if (!tpid) {
143         dup2(pfd[0], 0);
144         for (fd = getdtablesize() - 1; fd >= 3; --fd)
145             close(fd);
146         execl("/usr/bin/tar", "tar",
147             Verbose ? "-xpjvf" : "-xpjf",
148             "-", (char *)0);
149         _exit(2);
150     }
151     close(pfd[0]);
152     for (;;) {
153         if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
154             break;
155         if ((w = write(pfd[1], buf, r)) != r)
156             break;
157         if (keep_package) {
158             if ((w = write(pkgfd, buf, r)) != r)
159                 break;
160         }    
161     }
162     if (ferror(ftp))
163         warn("warning: error reading from server");
164     fclose(ftp);
165     if (keep_package) {
166         close(pkgfd);
167     } 
168     close(pfd[1]);
169     if (w == -1)
170         warn("warning: error writing to tar");
171     tpid = waitpid(tpid, &pstat, 0);
172     if (Verbose)
173         printf("tar command returns %d status\n", WEXITSTATUS(pstat));
174     if (rp && (isatty(0) || Verbose))
175         printf(" Done.\n");
176     return rp;
177 }