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.
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 CRYPTODists;
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 CRYPTODistTable[];
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 { "crypto", "/", &Dists, DIST_CRYPTO, CRYPTODistTable },
77 { "compat1x", "/", &Dists, DIST_COMPAT1X, NULL },
78 { "compat20", "/", &Dists, DIST_COMPAT20, NULL },
79 { "compat21", "/", &Dists, DIST_COMPAT21, NULL },
80 { "compat22", "/", &Dists, DIST_COMPAT22, NULL },
81 { "compat3x", "/", &Dists, DIST_COMPAT3X, NULL },
83 { "ports", "/usr", &Dists, DIST_PORTS, NULL },
84 { "local", "/", &Dists, DIST_LOCAL, NULL },
85 { "XF86336", "/usr", &Dists, DIST_XF86, XF86DistTable },
89 /* The CRYPTO distribution */
90 static Distribution CRYPTODistTable[] = {
91 { "crypto", "/", &CRYPTODists, DIST_CRYPTO_CRYPTO, NULL },
92 { "krb4", "/", &CRYPTODists, DIST_CRYPTO_KERBEROS4, NULL },
93 { "krb5", "/", &CRYPTODists, DIST_CRYPTO_KERBEROS5, NULL },
94 { "ssecure", "/usr/src", &CRYPTODists, DIST_CRYPTO_SSECURE, NULL },
95 { "scrypto", "/usr/src", &CRYPTODists, DIST_CRYPTO_SCRYPTO, NULL },
96 { "skrb4", "/usr/src", &CRYPTODists, DIST_CRYPTO_SKERBEROS4, NULL },
97 { "skrb5", "/usr/src", &CRYPTODists, DIST_CRYPTO_SKERBEROS5, NULL },
101 /* The /usr/src distribution */
102 static Distribution SrcDistTable[] = {
103 { "sbase", "/usr/src", &SrcDists, DIST_SRC_BASE, NULL },
104 { "scontrib", "/usr/src", &SrcDists, DIST_SRC_CONTRIB, NULL },
105 { "sgnu", "/usr/src", &SrcDists, DIST_SRC_GNU, NULL },
106 { "setc", "/usr/src", &SrcDists, DIST_SRC_ETC, NULL },
107 { "sgames", "/usr/src", &SrcDists, DIST_SRC_GAMES, NULL },
108 { "sinclude", "/usr/src", &SrcDists, DIST_SRC_INCLUDE, NULL },
109 { "slib", "/usr/src", &SrcDists, DIST_SRC_LIB, NULL },
110 { "slibexec", "/usr/src", &SrcDists, DIST_SRC_LIBEXEC, NULL },
111 { "srelease", "/usr/src", &SrcDists, DIST_SRC_RELEASE, NULL },
112 { "sbin", "/usr/src", &SrcDists, DIST_SRC_BIN, NULL },
113 { "ssbin", "/usr/src", &SrcDists, DIST_SRC_SBIN, NULL },
114 { "sshare", "/usr/src", &SrcDists, DIST_SRC_SHARE, NULL },
115 { "ssys", "/usr/src", &SrcDists, DIST_SRC_SYS, NULL },
116 { "subin", "/usr/src", &SrcDists, DIST_SRC_UBIN, NULL },
117 { "susbin", "/usr/src", &SrcDists, DIST_SRC_USBIN, NULL },
118 { "stools", "/usr/src", &SrcDists, DIST_SRC_TOOLS, NULL },
122 /* The XFree86 distribution */
123 static Distribution XF86DistTable[] = {
124 { "XF86336", "/usr/X11R6", &XF86Dists, DIST_XF86_FONTS, XF86FontDistTable },
125 { "XF86336", "/usr/X11R6", &XF86Dists, DIST_XF86_SERVER, XF86ServerDistTable },
126 { "Xbin", "/usr/X11R6", &XF86Dists, DIST_XF86_BIN, NULL },
127 { "Xcfg", "/usr/X11R6", &XF86Dists, DIST_XF86_CFG, NULL },
128 { "Xdoc", "/usr/X11R6", &XF86Dists, DIST_XF86_DOC, NULL },
129 { "Xhtml", "/usr/X11R6", &XF86Dists, DIST_XF86_HTML, NULL },
130 { "Xlib", "/usr/X11R6", &XF86Dists, DIST_XF86_LIB, NULL },
131 { "Xlk98", "/usr/X11R6", &XF86Dists, DIST_XF86_LKIT98, NULL },
132 { "Xlkit", "/usr/X11R6", &XF86Dists, DIST_XF86_LKIT, NULL },
133 { "Xman", "/usr/X11R6", &XF86Dists, DIST_XF86_MAN, NULL },
134 { "Xprog", "/usr/X11R6", &XF86Dists, DIST_XF86_PROG, NULL },
135 { "Xps", "/usr/X11R6", &XF86Dists, DIST_XF86_PS, NULL },
136 { "Xset", "/usr/X11R6", &XF86Dists, DIST_XF86_SET, NULL },
137 { "X9set", "/usr/X11R6", &XF86Dists, DIST_XF86_9SET, NULL },
141 /* The XFree86 server distribution */
142 static Distribution XF86ServerDistTable[] = {
144 { "PC98-Servers/X9480", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9480, NULL },
145 { "PC98-Servers/X9EGC", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9EGC, NULL },
146 { "PC98-Servers/X9GA9", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9GA9, NULL },
147 { "PC98-Servers/X9GAN", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9GAN, NULL },
148 { "PC98-Servers/X9LPW", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9LPW, NULL },
149 { "PC98-Servers/X9MGA", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9MGA, NULL },
150 { "PC98-Servers/X9NKV", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9NKV, NULL },
151 { "PC98-Servers/X9NS3", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9NS3, NULL },
152 { "PC98-Servers/X9SPW", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9SPW, NULL },
153 { "PC98-Servers/X9SVG", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9SVG, NULL },
154 { "PC98-Servers/X9TGU", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9TGU, NULL },
155 { "PC98-Servers/X9WEP", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WEP, NULL },
156 { "PC98-Servers/X9WS", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WS, NULL },
157 { "PC98-Servers/X9WSN", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_9WSN, NULL },
159 { "Servers/X3DL", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_3DL, NULL },
160 { "Servers/X8514", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_8514, NULL },
161 { "Servers/XAGX", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_AGX, NULL },
162 { "Servers/XI128", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_I128, NULL },
163 { "Servers/XMa8", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH8, NULL },
164 { "Servers/XMa32", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH32,NULL },
165 { "Servers/XMa64", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MACH64,NULL },
166 { "Servers/XMono", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_MONO, NULL },
167 { "Servers/XP9K", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_P9000, NULL },
168 { "Servers/XS3", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_S3, NULL },
169 { "Servers/XS3V", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_S3V, NULL },
170 { "Servers/XSVGA", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_SVGA, NULL },
171 { "Servers/XVG16", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_VGA16, NULL },
172 { "Servers/XW32", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_W32, NULL },
174 { "Servers/XTGA", "/usr/X11R6", &XF86ServerDists, DIST_XF86_SERVER_TGA, NULL },
179 /* The XFree86 font distribution */
180 static Distribution XF86FontDistTable[] = {
181 { "Xfnts", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_MISC, NULL },
182 { "Xf100", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_100, NULL },
183 { "Xfcyr", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_CYR, NULL },
184 { "Xfscl", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_SCALE, NULL },
185 { "Xfnon", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_NON, NULL },
186 { "Xfsrv", "/usr/X11R6", &XF86FontDists, DIST_XF86_FONTS_SERVER, NULL },
190 static int distMaybeSetCRYPTO(dialogMenuItem *self);
191 static int distMaybeSetPorts(dialogMenuItem *self);
194 distVerifyFlags(void)
199 if (CRYPTODists & (DIST_CRYPTO_KERBEROS4 | DIST_CRYPTO_KERBEROS5))
200 CRYPTODists |= DIST_CRYPTO_CRYPTO;
201 Dists |= DIST_CRYPTO;
203 if (XF86Dists & DIST_XF86_SET)
204 XF86ServerDists |= DIST_XF86_SERVER_VGA16;
206 XF86Dists |= DIST_XF86_SERVER;
208 XF86Dists |= DIST_XF86_FONTS;
209 if (XF86Dists || XF86ServerDists || XF86FontDists) {
212 Dists |= DIST_COMPAT22; /* For certain old X applications */
214 Dists |= DIST_COMPAT3X;
219 msgDebug("Dist Masks: Dists: %0x, CRYPTO: %0x, Srcs: %0x\nXServer: %0x, XFonts: %0x, XDists: %0x\n",
220 Dists, CRYPTODists, SrcDists, XF86ServerDists, XF86FontDists, XF86Dists);
224 distReset(dialogMenuItem *self)
232 return DITEM_SUCCESS | DITEM_REDRAW;
236 distConfig(dialogMenuItem *self)
242 if ((cp = variable_get(VAR_DIST_MAIN)) != NULL)
245 if ((cp = variable_get(VAR_DIST_CRYPTO)) != NULL)
246 CRYPTODists = atoi(cp);
248 if ((cp = variable_get(VAR_DIST_SRC)) != NULL)
251 if ((cp = variable_get(VAR_DIST_X11)) != NULL)
252 XF86Dists = atoi(cp);
254 if ((cp = variable_get(VAR_DIST_XSERVER)) != NULL)
255 XF86ServerDists = atoi(cp);
257 if ((cp = variable_get(VAR_DIST_XFONTS)) != NULL)
258 XF86FontDists = atoi(cp);
260 return DITEM_SUCCESS | DITEM_REDRAW;
267 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;
268 XF86ServerDists = DIST_XF86_SERVER_SVGA | DIST_XF86_SERVER_VGA16;
269 XF86FontDists = DIST_XF86_FONTS_MISC;
271 return distSetXF86(NULL);
273 return DITEM_SUCCESS;
277 distSetDeveloper(dialogMenuItem *self)
282 Dists = _DIST_DEVELOPER;
283 SrcDists = DIST_SRC_ALL;
284 i = distMaybeSetCRYPTO(self) | distMaybeSetPorts(self);
290 distSetXDeveloper(dialogMenuItem *self)
294 i = distSetDeveloper(self);
301 distSetKernDeveloper(dialogMenuItem *self)
306 Dists = _DIST_DEVELOPER;
307 SrcDists = DIST_SRC_SYS;
308 i = distMaybeSetCRYPTO(self) | distMaybeSetPorts(self);
314 distSetXKernDeveloper(dialogMenuItem *self)
318 i = distSetKernDeveloper(self);
325 distSetUser(dialogMenuItem *self)
331 i = distMaybeSetCRYPTO(self) | distMaybeSetPorts(self);
337 distSetXUser(dialogMenuItem *self)
341 i = distSetUser(self);
348 distSetMinimum(dialogMenuItem *self)
352 return DITEM_SUCCESS | DITEM_REDRAW;
356 distSetEverything(dialogMenuItem *self)
360 Dists = DIST_ALL | DIST_XF86;
361 SrcDists = DIST_SRC_ALL;
362 XF86Dists = DIST_XF86_ALL;
363 XF86ServerDists = DIST_XF86_SERVER_ALL;
364 XF86FontDists = DIST_XF86_FONTS_ALL;
365 i = distMaybeSetCRYPTO(self) | distMaybeSetPorts(self);
371 distSetCRYPTO(dialogMenuItem *self)
375 dialog_clear_norefresh();
376 if (!dmenuOpenSimple(&MenuCRYPTODistributions, FALSE))
381 return i | DITEM_REDRAW | DITEM_RESTORE;
385 distMaybeSetCRYPTO(dialogMenuItem *self)
387 int i = DITEM_SUCCESS | DITEM_REDRAW;
389 dialog_clear_norefresh();
390 if (!msgYesNo("Do you wish to install cryptographic software?\n\n"
391 "If you choose No, FreeBSD will use an MD5 based password scheme which,\n"
392 "while perhaps more secure, is not interoperable with the traditional\n"
393 "DES-based passwords on other Unix systems. There will also be some\n"
394 "differences in the type of RSA code you use.\n\n"
395 "Please do NOT choose Yes at this point if you are outside the\n"
396 "United States and Canada and are installing from a U.S. FTP server.\n"
397 "Instead, install everything but the crypto bits from the U.S. site\n"
398 "and then switch to an international FTP server to install crypto on\n"
399 "a second pass with the Custom Installation option.")) {
400 if (!dmenuOpenSimple(&MenuCRYPTODistributions, FALSE))
404 dialog_clear_norefresh();
405 USAResident = !msgYesNo("Are you actually resident in the United States?");
408 return i | DITEM_REDRAW | DITEM_RESTORE;
412 distMaybeSetPorts(dialogMenuItem *self)
414 dialog_clear_norefresh();
415 if (!msgYesNo("Would you like to install the FreeBSD ports collection?\n\n"
416 "This will give you ready access to over 3000 ported software packages,\n"
417 "at a cost of around 70MB of disk space when \"clean\" and possibly\n"
418 "much more than that when a lot of the distribution tarballs are loaded\n"
419 "(unless you have the extra CDs available from a FreeBSD CDROM distribution\n"
420 "and can mount them on /cdrom, in which case this is far less of a problem).\n\n"
421 "The ports collection is a very valuable resource and well worth having\n"
422 "on your /usr partition, so it is advisable to say Yes to this option.\n\n"
423 "For more information on the ports collection & the latest ports, visit:\n"
424 " http://www.freebsd.org/ports\n"))
427 Dists &= ~DIST_PORTS;
428 return DITEM_SUCCESS | DITEM_RESTORE;
432 distSetByName(Distribution *dist, char *name)
434 int i, status = FALSE;
436 /* Loop through current set */
437 for (i = 0; dist[i].my_name; i++) {
438 /* This is shorthand for "dist currently disabled" */
441 if (!strcmp(dist[i].my_name, name)) {
442 *(dist[i].my_mask) |= dist[i].my_bit;
445 if (dist[i].my_dist) {
446 if (distSetByName(dist[i].my_dist, name)) {
456 distUnsetByName(Distribution *dist, char *name)
458 int i, status = FALSE;
460 /* Loop through current set */
461 for (i = 0; dist[i].my_name; i++) {
462 /* This is shorthand for "dist currently disabled" */
465 if (!strcmp(dist[i].my_name, name)) {
466 *(dist[i].my_mask) &= ~(dist[i].my_bit);
469 if (dist[i].my_dist) {
470 if (distUnsetByName(dist[i].my_dist, name)) {
478 /* Just for the dispatch stuff */
480 distSetCustom(dialogMenuItem *self)
482 char *cp, *cp2, *tmp;
484 if (!(tmp = variable_get(VAR_DISTS))) {
485 msgDebug("distSetCustom() called without %s variable set.\n", VAR_DISTS);
486 return DITEM_FAILURE;
489 cp = alloca(strlen(tmp) + 1);
491 msgFatal("Couldn't alloca() %d bytes!\n", strlen(tmp) + 1);
494 if ((cp2 = index(cp, ' ')) != NULL)
496 if (!distSetByName(DistTable, cp))
497 msgDebug("distSetCustom: Warning, no such release \"%s\"\n", cp);
501 return DITEM_SUCCESS;
504 /* Just for the dispatch stuff */
506 distUnsetCustom(dialogMenuItem *self)
508 char *cp, *cp2, *tmp;
510 if (!(tmp = variable_get(VAR_DISTS))) {
511 msgDebug("distUnsetCustom() called without %s variable set.\n", VAR_DISTS);
512 return DITEM_FAILURE;
515 cp = alloca(strlen(tmp) + 1);
517 msgFatal("Couldn't alloca() %d bytes!\n", strlen(tmp) + 1);
520 if ((cp2 = index(cp, ' ')) != NULL)
522 if (!distUnsetByName(DistTable, cp))
523 msgDebug("distUnsetCustom: Warning, no such release \"%s\"\n", cp);
526 return DITEM_SUCCESS;
530 distSetSrc(dialogMenuItem *self)
534 dialog_clear_norefresh();
535 if (!dmenuOpenSimple(&MenuSrcDistributions, FALSE))
540 return i | DITEM_RESTORE;
544 distSetXF86(dialogMenuItem *self)
546 int i = DITEM_SUCCESS;
548 dialog_clear_norefresh();
549 if (!dmenuOpenSimple(&MenuXF86Select, FALSE))
552 return i | DITEM_RESTORE;
555 static Boolean got_intr = FALSE;
557 /* timeout handler */
561 msgDebug("User generated interrupt.\n");
566 check_for_interrupt(void)
576 distExtract(char *parent, Distribution *me)
578 int i,j, status, total, intr;
579 int cpid, zpid, fd2, chunk, numchunks;
580 char *path, *dist, buf[300000];
583 WINDOW *w = savescr();
584 struct timeval start, stop;
585 struct sigaction old, new;
586 properties dist_attr = NULL;
590 msgDebug("distExtract: parent: %s, me: %s\n", parent ? parent : "(none)", me->my_name);
592 /* Make ^C fake a sudden timeout */
593 new.sa_handler = handle_intr;
595 (void)sigemptyset(&new.sa_mask);
596 dialog_clear_norefresh();
597 dialog_msgbox("Please Wait", "Extracting all requested distributions...", -1, -1, 0);
598 sigaction(SIGINT, &new, &old);
600 /* Loop through to see if we're in our parent's plans */
601 for (i = 0; me[i].my_name; i++) {
602 dist = me[i].my_name;
603 path = parent ? parent : dist;
605 /* If our bit isn't set, go to the next */
606 if (!(me[i].my_bit & *(me[i].my_mask)))
609 /* This is shorthand for "dist currently disabled" */
611 *(me[i].my_mask) &= ~(me[i].my_bit);
615 /* Recurse if we actually have a sub-distribution */
617 if ((status = distExtract(dist, me[i].my_dist)) == TRUE)
618 *(me[i].my_mask) &= ~(me[i].my_bit);
623 * Try to get distribution as multiple pieces, locating and parsing an
624 * info file which tells us how many we need for this distribution.
627 snprintf(buf, sizeof buf, "%s/%s.inf", path, dist);
630 fp = mediaDevice->get(mediaDevice, buf, TRUE);
631 intr = check_for_interrupt();
632 if (fp == (FILE *)IO_ERROR || intr || !mediaDevice) {
633 /* Hard error, can't continue */
634 if (!msgYesNo("Unable to open %s: %s.\nReinitialize media?",
635 buf, !intr ? "I/O error." : "User interrupt.")) {
636 mediaDevice->shutdown(mediaDevice);
637 if (!mediaDevice->init(mediaDevice)) {
651 msgDebug("Parsing attributes file for distribution %s\n", dist);
653 dist_attr = properties_read(fileno(fp));
654 intr = check_for_interrupt();
655 if (intr || !dist_attr) {
656 msgConfirm("Cannot parse information file for the %s distribution: %s\n"
657 "Please verify that your media is valid and try again.",
658 dist, !intr ? "I/O error" : "User interrupt");
661 tmp = property_find(dist_attr, "Pieces");
663 numchunks = strtol(tmp, 0, 0);
670 /* Try to get the distribution as a single file */
671 snprintf(buf, sizeof buf, "%s/%s.tgz", path, dist);
673 * Passing TRUE as 3rd parm to get routine makes this a "probing" get, for which errors
674 * are not considered too significant.
677 fp = mediaDevice->get(mediaDevice, buf, TRUE);
678 intr = check_for_interrupt();
679 if (fp == (FILE *)IO_ERROR || intr || !mediaDevice) {
680 /* Hard error, can't continue */
681 if (intr) /* result of an interrupt */
682 msgConfirm("Unable to open %s: User interrupt", buf);
684 msgConfirm("Unable to open %s: I/O error", buf);
685 mediaDevice->shutdown(mediaDevice);
686 if (!mediaDevice->init(mediaDevice)) {
694 char *dir = root_bias(me[i].my_dir);
696 dialog_clear_norefresh();
697 msgNotify("Extracting %s into %s directory...", dist, dir);
698 status = mediaExtractDist(dir, dist, fp);
708 /* Fall through from "we got the attribute file, now get the pieces" step */
713 msgDebug("Attempting to extract distribution from %u chunks.\n", numchunks);
716 (void)gettimeofday(&start, (struct timezone *)0);
718 /* We have one or more chunks, initialize unpackers... */
719 mediaExtractDistBegin(root_bias(me[i].my_dir), &fd2, &zpid, &cpid);
721 /* And go for all the chunks */
722 dialog_clear_norefresh();
723 for (chunk = 0; chunk < numchunks; chunk++) {
724 int n, retval, last_msg, chunksize, realsize;
730 snprintf(buf, sizeof buf, "cksum.%c%c", (chunk / 26) + 'a', (chunk % 26) + 'a');
731 tmp = property_find(dist_attr, buf);
735 chunksize = strtol(tmp, 0, 0);
737 snprintf(buf, sizeof buf, "%s/%s.%c%c", path, dist, (chunk / 26) + 'a', (chunk % 26) + 'a');
739 msgDebug("trying for piece %d of %d: %s\n", chunk + 1, numchunks, buf);
740 fp = mediaDevice->get(mediaDevice, buf, FALSE);
741 intr = check_for_interrupt();
742 if (fp <= (FILE *)0 || intr) {
744 msgConfirm("Failed to find %s on this media. Reinitializing media.", buf);
746 msgConfirm("failed to retreive piece file %s.\n"
747 "%s: Reinitializing media.", buf, !intr ? "I/O error" : "User interrupt");
748 mediaDevice->shutdown(mediaDevice);
749 if (!mediaDevice->init(mediaDevice))
755 snprintf(prompt, sizeof prompt, "Extracting %s into %s directory...", dist, root_bias(me[i].my_dir));
756 dialog_gauge("Progress", prompt, 8, 15, 6, 50, (int)((float)(chunk + 1) / numchunks * 100));
762 n = fread(buf + realsize, 1, BUFSIZ, fp);
763 if (check_for_interrupt()) {
764 msgConfirm("Media read error: User interrupt.");
773 /* Print statistics about how we're doing */
774 (void) gettimeofday(&stop, (struct timezone *)0);
775 stop.tv_sec = stop.tv_sec - start.tv_sec;
776 stop.tv_usec = stop.tv_usec - start.tv_usec;
777 if (stop.tv_usec < 0)
778 stop.tv_sec--, stop.tv_usec += 1000000;
779 seconds = stop.tv_sec + (stop.tv_usec / 1000000.0);
783 if (seconds != last_msg) {
785 msgInfo("%10d bytes read from %s dist, chunk %2d of %2d @ %.1f KB/sec.",
786 total, dist, chunk + 1, numchunks, (total / seconds) / 1024.0);
791 if (!chunksize || (realsize == chunksize)) {
792 /* No substitution necessary */
793 retval = write(fd2, buf, realsize);
794 if (retval != realsize) {
796 dialog_clear_norefresh();
797 msgConfirm("Write failure on transfer! (wrote %d bytes of %d bytes)", retval, realsize);
801 for (j = 0; j < realsize; j++) {
802 /* On finding CRLF, skip the CR; don't exceed end of buffer. */
803 if ((buf[j] != 0x0d) || (j == total - 1) || (buf[j + 1] != 0x0a)) {
804 retval = write(fd2, buf + j, 1);
807 dialog_clear_norefresh();
808 msgConfirm("Write failure on transfer! (wrote %d bytes of %d bytes)", j, chunksize);
816 status = mediaExtractDistEnd(zpid, cpid);
821 mediaExtractDistEnd(zpid, cpid);
826 dialog_clear_norefresh();
828 msgConfirm("Unable to transfer all components of the %s distribution.\n"
829 "You may wish to switch media types and try again.\n", me[i].my_name);
831 else if (me[i].my_bit != DIST_LOCAL) {
832 status = msgYesNo("Unable to transfer the %s distribution from\n%s.\n\n"
833 "Do you want to try to retrieve it again?",
834 me[i].my_name, mediaDevice->name);
839 /* If extract was successful, remove ourselves from further consideration */
841 *(me[i].my_mask) &= ~(me[i].my_bit);
845 properties_free(dist_attr);
846 sigaction(SIGINT, &old, NULL); /* Restore signal handler */
852 printSelected(char *buf, int selected, Distribution *me, int *col)
856 /* Loop through to see if we're in our parent's plans */
857 for (i = 0; me[i].my_name; i++) {
859 /* If our bit isn't set, go to the next */
860 if (!(me[i].my_bit & selected))
863 /* This is shorthand for "dist currently disabled" */
867 *col += strlen(me[i].my_name);
872 sprintf(&buf[strlen(buf)], " %s", me[i].my_name);
873 /* Recurse if have a sub-distribution */
875 printSelected(buf, *(me[i].my_mask), me[i].my_dist, col);
880 distExtractAll(dialogMenuItem *self)
882 int old_dists, retries = 0, status = DITEM_SUCCESS;
886 int want_x_package = 0;
891 if (!dmenuOpenSimple(&MenuSubDistributions, FALSE) || !Dists)
892 return DITEM_FAILURE;
895 if (!mediaVerify() || !mediaDevice->init(mediaDevice))
896 return DITEM_FAILURE;
901 dialog_clear_norefresh();
903 msgNotify("Attempting to install all selected distributions..");
906 /* Clear any XFree86 dist flags, but remember they were present. */
907 if(Dists & DIST_XF86)
910 /*Dists &= ~(DIST_XF86 | XF86Dists | XF86ServerDists | XF86FontDists);*/
913 /* Try for 3 times around the loop, then give up. */
914 while (Dists && ++retries < 3)
915 distExtract(NULL, DistTable);
919 status |= installX11package(NULL);
922 dialog_clear_norefresh();
923 /* Only do bin fixup if bin dist was successfully extracted */
924 if ((old_dists & DIST_BIN) && !(Dists & DIST_BIN))
925 status |= installFixupBin(self);
926 if (old_dists & DIST_XF86)
927 status |= installFixupXFree(self);
929 /* Clear any local dist flags now */
930 Dists &= ~DIST_LOCAL;
936 dialog_clear_norefresh();
937 printSelected(buf, Dists, DistTable, &col);
938 dialog_clear_norefresh();
940 msgConfirm("Couldn't extract the following distributions. This may\n"
941 "be because they were not available on the installation\n"
942 "media you've chosen:\n\n\t%s", buf);