2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
7 * $Id: dist.c,v 1.140 1999/05/14 07:15:03 jkh Exp $
10 * Jordan Hubbard. All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer,
17 * verbatim and that no modifications are made prior to this
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
23 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include "sysinstall.h"
43 unsigned int DESDists;
44 unsigned int SrcDists;
45 unsigned int XF86Dists;
46 unsigned int XF86ServerDists;
47 unsigned int XF86FontDists;
49 typedef struct _dist {
52 unsigned int *my_mask;
54 struct _dist *my_dist;
57 extern Distribution DistTable[];
58 extern Distribution DESDistTable[];
59 extern Distribution SrcDistTable[];
60 extern Distribution XF86DistTable[];
61 extern Distribution XF86FontDistTable[];
62 extern Distribution XF86ServerDistTable[];
64 /* The top-level distribution categories */
65 static Distribution DistTable[] = {
66 { "bin", "/", &Dists, DIST_BIN, NULL },
67 { "doc", "/", &Dists, DIST_DOC, NULL },
68 { "games", "/", &Dists, DIST_GAMES, NULL },
69 { "manpages", "/", &Dists, DIST_MANPAGES, NULL },
70 { "catpages", "/", &Dists, DIST_CATPAGES, NULL },
71 { "proflibs", "/", &Dists, DIST_PROFLIBS, NULL },
72 { "dict", "/", &Dists, DIST_DICT, NULL },
73 { "info", "/", &Dists, DIST_INFO, NULL },
74 { "src", "/", &Dists, DIST_SRC, SrcDistTable },
75 { "des", "/", &Dists, DIST_DES, DESDistTable },
76 { "compat1x", "/", &Dists, DIST_COMPAT1X, NULL },
77 { "compat20", "/", &Dists, DIST_COMPAT20, NULL },
78 { "compat21", "/", &Dists, DIST_COMPAT21, NULL },
79 { "compat22", "/", &Dists, DIST_COMPAT22, NULL },
81 { "compat3x", "/", &Dists, DIST_COMPAT3X, NULL },
83 { "ports", "/usr", &Dists, DIST_PORTS, NULL },
84 { "XF86333", "/usr", &Dists, DIST_XF86, XF86DistTable },
88 /* The DES distribution (not for export!) */
89 static Distribution DESDistTable[] = {
90 { "des", "/", &DESDists, DIST_DES_DES, NULL },
91 { "krb", "/", &DESDists, DIST_DES_KERBEROS, NULL },
92 { "ssecure", "/usr/src", &DESDists, DIST_DES_SSECURE, NULL },
93 { "scrypto", "/usr/src", &DESDists, DIST_DES_SCRYPTO, NULL },
94 { "skerbero", "/usr/src", &DESDists, DIST_DES_SKERBEROS, NULL },
98 /* The /usr/src distribution */
99 static Distribution SrcDistTable[] = {
100 { "sbase", "/usr/src", &SrcDists, DIST_SRC_BASE, NULL },
101 { "scontrib", "/usr/src", &SrcDists, DIST_SRC_CONTRIB, NULL },
102 { "sgnu", "/usr/src", &SrcDists, DIST_SRC_GNU, NULL },
103 { "setc", "/usr/src", &SrcDists, DIST_SRC_ETC, NULL },
104 { "sgames", "/usr/src", &SrcDists, DIST_SRC_GAMES, NULL },
105 { "sinclude", "/usr/src", &SrcDists, DIST_SRC_INCLUDE, NULL },
106 { "slib", "/usr/src", &SrcDists, DIST_SRC_LIB, NULL },
107 { "slibexec", "/usr/src", &SrcDists, DIST_SRC_LIBEXEC, NULL },
108 { "srelease", "/usr/src", &SrcDists, DIST_SRC_RELEASE, NULL },
109 { "sbin", "/usr/src", &SrcDists, DIST_SRC_BIN, NULL },
110 { "ssbin", "/usr/src", &SrcDists, DIST_SRC_SBIN, NULL },
111 { "sshare", "/usr/src", &SrcDists, DIST_SRC_SHARE, NULL },
112 { "ssys", "/usr/src", &SrcDists, DIST_SRC_SYS, NULL },
113 { "subin", "/usr/src", &SrcDists, DIST_SRC_UBIN, NULL },
114 { "susbin", "/usr/src", &SrcDists, DIST_SRC_USBIN, NULL },
118 /* The XFree86 distribution */
119 static Distribution XF86DistTable[] = {
120 { "XF86333", "/usr/X11R6", &XF86Dists, DIST_XF86_FONTS, XF86FontDistTable },
121 { "XF86333", "/usr/X11R6", &XF86Dists, DIST_XF86_SERVER, XF86ServerDistTable },
122 { "Xsrc1", "/usr/X11R6/src", &XF86Dists, DIST_XF86_SRC, NULL },
123 { "Xsrcctrb", "/usr/X11R6/src", &XF86Dists, DIST_XF86_CSRC, NULL },
124 { "Xbin", "/usr/X11R6", &XF86Dists, DIST_XF86_BIN, NULL },
125 { "Xcfg", "/usr/X11R6", &XF86Dists, DIST_XF86_CFG, NULL },
126 { "Xdoc", "/usr/X11R6", &XF86Dists, DIST_XF86_DOC, NULL },
127 { "Xhtml", "/usr/X11R6", &XF86Dists, DIST_XF86_HTML, NULL },
128 { "Xlib", "/usr/X11R6", &XF86Dists, DIST_XF86_LIB, NULL },
129 { "Xlk98", "/usr/X11R6", &XF86Dists, DIST_XF86_LKIT98, NULL },
130 { "Xlkit", "/usr/X11R6", &XF86Dists, DIST_XF86_LKIT, NULL },
131 { "Xman", "/usr/X11R6", &XF86Dists, DIST_XF86_MAN, NULL },
132 { "Xprog", "/usr/X11R6", &XF86Dists, DIST_XF86_PROG, NULL },
133 { "Xps", "/usr/X11R6", &XF86Dists, DIST_XF86_PS, NULL },
134 { "Xset", "/usr/X11R6", &XF86Dists, DIST_XF86_SET, NULL },
135 { "X9set", "/usr/X11R6", &XF86Dists, DIST_XF86_9SET, NULL },
139 /* The XFree86 server distribution */
140 static Distribution XF86ServerDistTable[] = {
141 { "PC98-Servers/X9480", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9480, NULL },
142 { "PC98-Servers/X9EGC", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9EGC, NULL },
143 { "PC98-Servers/X9GA9", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9GA9, NULL },
144 { "PC98-Servers/X9GAN", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9GAN, NULL },
145 { "PC98-Servers/X9LPW", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9LPW, NULL },
146 { "PC98-Servers/X9MGA", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9MGA, NULL },
147 { "PC98-Servers/X9NKV", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9NKV, NULL },
148 { "PC98-Servers/X9NS3", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9NS3, NULL },
149 { "PC98-Servers/X9SPW", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9SPW, NULL },
150 { "PC98-Servers/X9SVG", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9SVG, NULL },
151 { "PC98-Servers/X9TGU", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9TGU, NULL },
152 { "PC98-Servers/X9WEP", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WEP, NULL },
153 { "PC98-Servers/X9WS", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WS, NULL },
154 { "PC98-Servers/X9WSN", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WSN, NULL },
155 { "Servers/X3DL", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_3DL, NULL },
156 { "Servers/X8514", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_8514, NULL },
157 { "Servers/XAGX", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_AGX, NULL },
158 { "Servers/XI128", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_I128, NULL },
159 { "Servers/XMa8", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH8, NULL },
160 { "Servers/XMa32", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH32,NULL },
161 { "Servers/XMa64", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH64,NULL },
162 { "Servers/XMono", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MONO, NULL },
163 { "Servers/XP9K", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_P9000, NULL },
164 { "Servers/XS3", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_S3, NULL },
165 { "Servers/XS3V", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_S3V, NULL },
166 { "Servers/XSVGA", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_SVGA, NULL },
167 { "Servers/XVG16", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_VGA16, NULL },
168 { "Servers/XW32", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_W32, NULL },
172 /* The XFree86 font distribution */
173 static Distribution XF86FontDistTable[] = {
174 { "Xfnts", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_MISC, NULL },
175 { "Xf100", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_100, NULL },
176 { "Xfcyr", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_CYR, NULL },
177 { "Xfscl", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_SCALE, NULL },
178 { "Xfnon", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_NON, NULL },
179 { "Xfsrv", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_SERVER, NULL },
183 static int distMaybeSetDES(dialogMenuItem *self);
184 static int distMaybeSetPorts(dialogMenuItem *self);
188 distVerifyFlags(void)
193 if (DESDists & DIST_DES_KERBEROS)
194 DESDists |= DIST_DES_DES;
197 if (XF86Dists & DIST_XF86_SET)
198 XF86ServerDists |= DIST_XF86_SERVER_VGA16;
200 XF86Dists |= DIST_XF86_SERVER;
202 XF86Dists |= DIST_XF86_FONTS;
203 if (XF86Dists || XF86ServerDists || XF86FontDists)
206 msgDebug("Dist Masks: Dists: %0x, DES: %0x, Srcs: %0x\nXServer: %0x, XFonts: %0x, XDists: %0x\n",
207 Dists, DESDists, SrcDists, XF86ServerDists, XF86FontDists, XF86Dists);
211 distReset(dialogMenuItem *self)
219 return DITEM_SUCCESS | DITEM_REDRAW;
223 distConfig(dialogMenuItem *self)
229 if ((cp = variable_get(VAR_DIST_MAIN)) != NULL)
232 if ((cp = variable_get(VAR_DIST_DES)) != NULL)
235 if ((cp = variable_get(VAR_DIST_SRC)) != NULL)
238 if ((cp = variable_get(VAR_DIST_X11)) != NULL)
239 XF86Dists = atoi(cp);
241 if ((cp = variable_get(VAR_DIST_XSERVER)) != NULL)
242 XF86ServerDists = atoi(cp);
244 if ((cp = variable_get(VAR_DIST_XFONTS)) != NULL)
245 XF86FontDists = atoi(cp);
247 return DITEM_SUCCESS | DITEM_REDRAW;
254 XF86Dists = DIST_XF86_BIN | DIST_XF86_SET | DIST_XF86_CFG | DIST_XF86_LIB | DIST_XF86_PROG | DIST_XF86_MAN | DIST_XF86_SERVER | DIST_XF86_FONTS;
255 XF86ServerDists = DIST_XF86_SERVER_SVGA | DIST_XF86_SERVER_VGA16;
256 XF86FontDists = DIST_XF86_FONTS_MISC;
257 return distSetXF86(NULL);
261 distSetDeveloper(dialogMenuItem *self)
266 Dists = _DIST_DEVELOPER;
267 SrcDists = DIST_SRC_ALL;
268 i = distMaybeSetDES(self) | distMaybeSetPorts(self);
274 distSetXDeveloper(dialogMenuItem *self)
278 i = distSetDeveloper(self);
285 distSetKernDeveloper(dialogMenuItem *self)
290 Dists = _DIST_DEVELOPER;
291 SrcDists = DIST_SRC_SYS;
292 i = distMaybeSetDES(self) | distMaybeSetPorts(self);
298 distSetXKernDeveloper(dialogMenuItem *self)
302 i = distSetKernDeveloper(self);
309 distSetUser(dialogMenuItem *self)
315 i = distMaybeSetDES(self) | distMaybeSetPorts(self);
321 distSetXUser(dialogMenuItem *self)
325 i = distSetUser(self);
332 distSetMinimum(dialogMenuItem *self)
336 return DITEM_SUCCESS | DITEM_REDRAW;
340 distSetEverything(dialogMenuItem *self)
344 Dists = DIST_ALL | DIST_XF86;
345 SrcDists = DIST_SRC_ALL;
346 XF86Dists = DIST_XF86_ALL;
347 XF86ServerDists = DIST_XF86_SERVER_ALL;
348 XF86FontDists = DIST_XF86_FONTS_ALL;
349 i = distMaybeSetDES(self) | distMaybeSetPorts(self);
355 distSetDES(dialogMenuItem *self)
359 if (!dmenuOpenSimple(&MenuDESDistributions, FALSE))
364 return i | DITEM_RESTORE;
368 distMaybeSetDES(dialogMenuItem *self)
370 int i = DITEM_SUCCESS;
372 dialog_clear_norefresh();
373 if (!msgYesNo("Do wish to install DES cryptographic software?\n\n"
374 "If you choose No, FreeBSD will use an MD5 based password scheme which,\n"
375 "while perhaps more secure, is not interoperable with the traditional\n"
376 "UNIX DES passwords on other non-FreeBSD systems.\n\n"
377 "Please do NOT choose Yes at this point if you are outside the\n"
378 "United States and Canada yet are installing from a U.S. FTP server.\n"
379 "This will violate U.S. export restrictions and possibly get the\n"
380 "server site into trouble! In such cases, install everything but the\n"
381 "DES distribution from the U.S. server then switch your media type to\n"
382 "point to an international FTP server, using the Custom installation\n"
383 "option to select and extract the DES distribution in a second pass.")) {
384 if (!dmenuOpenSimple(&MenuDESDistributions, FALSE))
388 return i | DITEM_RESTORE;
392 distMaybeSetPorts(dialogMenuItem *self)
394 dialog_clear_norefresh();
395 if (!msgYesNo("Would you like to install the FreeBSD ports collection?\n\n"
396 "This will give you ready access to over 2000 ported software packages,\n"
397 "though at a cost of around 90MB of disk space when \"clean\" and possibly\n"
398 "much more than that if a lot of the distribution tarballs are loaded\n"
399 "(unless you have the extra CDs available from a FreeBSD CDROM distribution\n"
400 "and can mount them on /cdrom, in which case this is far less of a problem).\n\n"
401 "The ports collection is a very valuable resource and, if you have at least\n"
402 "100MB to spare in your /usr partition, well worth having around.\n\n"
403 "For more information on the ports collection & the latest ports, visit:\n"
404 " http://www.freebsd.org/ports\n"))
407 Dists &= ~DIST_PORTS;
408 return DITEM_SUCCESS | DITEM_RESTORE;
412 distSetByName(Distribution *dist, char *name)
414 int i, status = FALSE;
416 /* Loop through current set */
417 for (i = 0; dist[i].my_name; i++) {
418 /* This is shorthand for "dist currently disabled" */
421 if (!strcmp(dist[i].my_name, name)) {
422 *(dist[i].my_mask) |= dist[i].my_bit;
425 if (dist[i].my_dist) {
426 if (distSetByName(dist[i].my_dist, name)) {
435 /* Just for the dispatch stuff */
437 distSetCustom(dialogMenuItem *self)
439 char *cp, *cp2, *tmp;
441 if (!(tmp = variable_get(VAR_DISTS))) {
442 msgDebug("distSetCustom() called without %s variable set.\n", VAR_DISTS);
443 return DITEM_FAILURE;
446 cp = alloca(strlen(tmp) + 1);
448 msgFatal("Couldn't alloca() %d bytes!\n", strlen(tmp) + 1);
451 if ((cp2 = index(cp, ' ')) != NULL)
453 if (!distSetByName(DistTable, cp))
454 msgDebug("distSetCustom: Warning, no such release \"%s\"\n", cp);
458 return DITEM_SUCCESS;
462 distSetSrc(dialogMenuItem *self)
466 if (!dmenuOpenSimple(&MenuSrcDistributions, FALSE))
471 return i | DITEM_RESTORE;
475 distSetXF86(dialogMenuItem *self)
477 int i = DITEM_SUCCESS;
479 if (!dmenuOpenSimple(&MenuXF86Select, FALSE))
482 return i | DITEM_RESTORE;
485 static Boolean got_intr = FALSE;
487 /* timeout handler */
491 msgDebug("User generated interrupt.\n");
496 check_for_interrupt(void)
506 distExtract(char *parent, Distribution *me)
508 int i, status, total, intr;
509 int cpid, zpid, fd2, chunk, numchunks;
510 char *path, *dist, buf[BUFSIZ];
513 WINDOW *w = savescr();
514 struct timeval start, stop;
515 struct sigaction old, new;
518 dialog_clear_norefresh();
520 msgDebug("distExtract: parent: %s, me: %s\n", parent ? parent : "(none)", me->my_name);
522 /* Make ^C fake a sudden timeout */
523 new.sa_handler = handle_intr;
526 sigaction(SIGINT, &new, &old);
528 /* Loop through to see if we're in our parent's plans */
529 for (i = 0; me[i].my_name; i++) {
530 dist = me[i].my_name;
531 path = parent ? parent : dist;
533 /* If our bit isn't set, go to the next */
534 if (!(me[i].my_bit & *(me[i].my_mask)))
537 /* This is shorthand for "dist currently disabled" */
539 *(me[i].my_mask) &= ~(me[i].my_bit);
543 /* Recurse if we actually have a sub-distribution */
545 if ((status = distExtract(dist, me[i].my_dist)) == TRUE)
546 *(me[i].my_mask) &= ~(me[i].my_bit);
551 * Try to get distribution as multiple pieces, locating and parsing an
552 * info file which tells us how many we need for this distribution.
555 snprintf(buf, sizeof buf, "%s/%s.inf", path, dist);
558 fp = mediaDevice->get(mediaDevice, buf, TRUE);
559 intr = check_for_interrupt();
560 if (fp == (FILE *)IO_ERROR || intr) { /* Hard error, can't continue */
561 if (!msgYesNo("Unable to open %s: %s.\nReinitialize media?",
562 buf, !intr ? "I/O error." : "User interrupt.")) {
563 mediaDevice->shutdown(mediaDevice);
564 if (!mediaDevice->init(mediaDevice)) {
577 properties dist_attr;
580 msgDebug("Parsing attributes file for distribution %s\n", dist);
582 dist_attr = properties_read(fileno(fp));
583 intr = check_for_interrupt();
584 if (intr || !dist_attr) {
585 msgConfirm("Cannot parse information file for the %s distribution: %s\n"
586 "Please verify that your media is valid and try again.",
587 dist, !intr ? "I/O error" : "User interrupt");
590 tmp = property_find(dist_attr, "Pieces");
592 numchunks = strtol(tmp, 0, 0);
595 properties_free(dist_attr);
600 /* Try to get the distribution as a single file */
601 snprintf(buf, sizeof buf, "%s/%s.tgz", path, dist);
603 * Passing TRUE as 3rd parm to get routine makes this a "probing" get, for which errors
604 * are not considered too significant.
607 fp = mediaDevice->get(mediaDevice, buf, TRUE);
608 intr = check_for_interrupt();
609 if (fp == (FILE *)IO_ERROR || intr) { /* Hard error, can't continue */
610 if (intr) /* result of an interrupt */
611 msgConfirm("Unable to open %s: User interrupt", buf);
613 msgConfirm("Unable to open %s: I/O error", buf);
614 mediaDevice->shutdown(mediaDevice);
615 if (!mediaDevice->init(mediaDevice)) {
623 char *dir = root_bias(me[i].my_dir);
625 msgNotify("Extracting %s into %s directory...", dist, dir);
626 status = mediaExtractDist(dir, dist, fp);
634 /* Fall through from "we got the attribute file, now get the pieces" step */
639 msgDebug("Attempting to extract distribution from %u chunks.\n", numchunks);
642 (void)gettimeofday(&start, (struct timezone *)0);
644 /* We have one or more chunks, initialize unpackers... */
645 mediaExtractDistBegin(root_bias(me[i].my_dir), &fd2, &zpid, &cpid);
647 /* And go for all the chunks */
648 for (chunk = 0; chunk < numchunks; chunk++) {
649 int n, retval, last_msg;
655 snprintf(buf, sizeof buf, "%s/%s.%c%c", path, dist, (chunk / 26) + 'a', (chunk % 26) + 'a');
657 msgDebug("trying for piece %d of %d: %s\n", chunk + 1, numchunks, buf);
658 fp = mediaDevice->get(mediaDevice, buf, FALSE);
659 intr = check_for_interrupt();
660 if (fp <= (FILE *)0 || intr) {
662 msgConfirm("Failed to find %s on this media. Reinitializing media.", buf);
664 msgConfirm("failed to retreive piece file %s.\n"
665 "%s: Reinitializing media.", buf, !intr ? "I/O error" : "User interrupt");
666 mediaDevice->shutdown(mediaDevice);
667 if (!mediaDevice->init(mediaDevice))
673 snprintf(prompt, sizeof prompt, "Extracting %s into %s directory...", dist, root_bias(me[i].my_dir));
674 dialog_gauge("Progress", prompt, 8, 15, 6, 50, (int)((float)(chunk + 1) / numchunks * 100));
679 n = fread(buf, 1, BUFSIZ, fp);
680 if (check_for_interrupt()) {
681 msgConfirm("Media read error: User interrupt.");
689 /* Print statistics about how we're doing */
690 (void) gettimeofday(&stop, (struct timezone *)0);
691 stop.tv_sec = stop.tv_sec - start.tv_sec;
692 stop.tv_usec = stop.tv_usec - start.tv_usec;
693 if (stop.tv_usec < 0)
694 stop.tv_sec--, stop.tv_usec += 1000000;
695 seconds = stop.tv_sec + (stop.tv_usec / 1000000.0);
699 if (seconds != last_msg) {
701 msgInfo("%10d bytes read from %s dist, chunk %2d of %2d @ %.1f KB/sec.",
702 total, dist, chunk + 1, numchunks, (total / seconds) / 1024.0);
704 retval = write(fd2, buf, n);
707 dialog_clear_norefresh();
708 msgConfirm("Write failure on transfer! (wrote %d bytes of %d bytes)", retval, n);
715 status = mediaExtractDistEnd(zpid, cpid);
720 mediaExtractDistEnd(zpid, cpid);
726 msgConfirm("Unable to transfer all components of the %s distribution.\n"
727 "If this is a CDROM install, it may be because export restrictions prohibit\n"
728 "DES code from being shipped from the U.S. Try to get this code from a\n"
729 "local FTP site instead!", me[i].my_name);
732 status = msgYesNo("Unable to transfer the %s distribution from\n%s.\n\n"
733 "Do you want to try to retrieve it again?",
734 me[i].my_name, mediaDevice->name);
740 /* If extract was successful, remove ourselves from further consideration */
742 *(me[i].my_mask) &= ~(me[i].my_bit);
746 sigaction(SIGINT, &old, NULL); /* Restore signal handler */
752 printSelected(char *buf, int selected, Distribution *me, int *col)
756 /* Loop through to see if we're in our parent's plans */
757 for (i = 0; me[i].my_name; i++) {
759 /* If our bit isn't set, go to the next */
760 if (!(me[i].my_bit & selected))
763 /* This is shorthand for "dist currently disabled" */
767 *col += strlen(me[i].my_name);
772 sprintf(&buf[strlen(buf)], " %s", me[i].my_name);
773 /* Recurse if have a sub-distribution */
775 printSelected(buf, *(me[i].my_mask), me[i].my_dist, col);
780 distExtractAll(dialogMenuItem *self)
782 int old_dists, retries = 0, status = DITEM_SUCCESS;
787 if (!dmenuOpenSimple(&MenuSubDistributions, FALSE) || !Dists)
788 return DITEM_FAILURE | DITEM_RESTORE;
791 if (!mediaVerify() || !mediaDevice->init(mediaDevice))
792 return DITEM_FAILURE;
797 dialog_clear_norefresh();
798 msgNotify("Attempting to install all selected distributions..");
800 /* Try for 3 times around the loop, then give up. */
801 while (Dists && ++retries < 3)
802 distExtract(NULL, DistTable);
804 /* Only do bin fixup if bin dist was successfully extracted */
805 if ((old_dists & DIST_BIN) && !(Dists & DIST_BIN))
806 status |= installFixupBin(self);
807 if (old_dists & DIST_XF86)
808 status |= installFixupXFree(self);
814 printSelected(buf, Dists, DistTable, &col);
815 dialog_clear_norefresh();
816 msgConfirm("Couldn't extract the following distributions. This may\n"
817 "be because they were not available on the installation\n"
818 "media you've chosen:\n\n\t%s", buf);
819 status |= DITEM_RESTORE;