Merge from vendor branch BINUTILS:
[dragonfly.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  * $FreeBSD: src/usr.sbin/pkg_install/lib/url.c,v 1.4 2004/06/29 19:06:42 eik Exp $
20  * $DragonFly: src/usr.sbin/pkg_install/lib/Attic/url.c,v 1.1 2004/07/30 04:46:13 dillon Exp $
21  */
22
23 #include "lib.h"
24 #include <err.h>
25 #include <fetch.h>
26 #include <sys/wait.h>
27
28 /*
29  * Try and fetch a file by URL, returning the directory name for where
30  * it's unpacked, if successful.
31  */
32 char *
33 fileGetURL(const char *base, const char *spec)
34 {
35     char *cp, *rp;
36     char fname[FILENAME_MAX];
37     char pen[FILENAME_MAX];
38     char buf[8192];
39     FILE *ftp;
40     pid_t tpid;
41     int pfd[2], pstat, r, w = 0;
42     char *hint;
43     int fd;
44
45     rp = NULL;
46     /* Special tip that sysinstall left for us */
47     hint = getenv("PKG_ADD_BASE");
48     if (!isURL(spec)) {
49         if (!base && !hint)
50             return NULL;
51         /*
52          * We've been given an existing URL (that's known-good) and now we need
53          * to construct a composite one out of that and the basename we were
54          * handed as a dependency.
55          */
56         if (base) {
57             strcpy(fname, base);
58             /*
59              * Advance back two slashes to get to the root of the package
60              * hierarchy
61              */
62             cp = strrchr(fname, '/');
63             if (cp) {
64                 *cp = '\0';     /* chop name */
65                 cp = strrchr(fname, '/');
66             }
67             if (cp) {
68                 *(cp + 1) = '\0';
69                 strcat(cp, "All/");
70                 strcat(cp, spec);
71 #if defined(__FreeBSD_version) && __FreeBSD_version >= 500039
72                 strcat(cp, ".tbz");
73 #else
74                 strcat(cp, ".tgz");
75 #endif
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 #if defined(__FreeBSD_version) && __FreeBSD_version >= 500039
88             strcat(fname, ".tbz");
89 #else
90             strcat(fname, ".tgz");
91 #endif
92         }
93     }
94     else
95         strcpy(fname, spec);
96
97     if ((ftp = fetchGetURL(fname, Verbose ? "v" : NULL)) == NULL) {
98         printf("Error: FTP Unable to get %s: %s\n",
99                fname, fetchLastErrString);
100         return NULL;
101     }
102
103     if (isatty(0) || Verbose)
104         printf("Fetching %s...", fname), fflush(stdout);
105     pen[0] = '\0';
106     if ((rp = make_playpen(pen, 0)) == NULL) {
107         printf("Error: Unable to construct a new playpen for FTP!\n");
108         fclose(ftp);
109         return NULL;
110     }
111     if (pipe(pfd) == -1) {
112         warn("pipe()");
113         cleanup(0);
114         exit(2);
115     }
116     if ((tpid = fork()) == -1) {
117         warn("pipe()");
118         cleanup(0);
119         exit(2);
120     }
121     if (!tpid) {
122         dup2(pfd[0], 0);
123         for (fd = getdtablesize() - 1; fd >= 3; --fd)
124             close(fd);
125         execl("/usr/bin/tar", "tar",
126 #if defined(__FreeBSD_version) && __FreeBSD_version >= 500039
127             Verbose ? "-xjvf" : "-xjf",
128 #else
129             Verbose ? "-xzvf" : "-xzf",
130 #endif
131             "-", (char *)0);
132         _exit(2);
133     }
134     close(pfd[0]);
135     for (;;) {
136         if ((r = fread(buf, 1, sizeof buf, ftp)) < 1)
137             break;
138         if ((w = write(pfd[1], buf, r)) != r)
139             break;
140     }
141     if (ferror(ftp))
142         warn("warning: error reading from server");
143     fclose(ftp);
144     close(pfd[1]);
145     if (w == -1)
146         warn("warning: error writing to tar");
147     tpid = waitpid(tpid, &pstat, 0);
148     if (Verbose)
149         printf("tar command returns %d status\n", WEXITSTATUS(pstat));
150     if (rp && (isatty(0) || Verbose))
151         printf(" Done.\n");
152     return rp;
153 }