install.c revision 8613
1/*
2 * The new sysinstall program.
3 *
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
6 *
7 * $Id: install.c,v 1.25 1995/05/18 16:53:52 jkh Exp $
8 *
9 * Copyright (c) 1995
10 *	Jordan Hubbard.  All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
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
18 *    point in the file.
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.
22 * 3. All advertising materials mentioning features or use of this software
23 *    must display the following acknowledgement:
24 *	This product includes software developed by Jordan Hubbard
25 *	for the FreeBSD Project.
26 * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
27 *    endorse or promote products derived from this software without specific
28 *    prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 */
43
44#include "sysinstall.h"
45#include <sys/disklabel.h>
46#include <sys/errno.h>
47#include <sys/fcntl.h>
48#include <unistd.h>
49
50Boolean SystemWasInstalled;
51
52static void	make_filesystems(void);
53static void	cpio_extract(void);
54static void	install_configuration_files(void);
55static void	do_final_setup(void);
56
57static Boolean
58preInstallCheck(void)
59{
60    if (!getenv(DISK_PARTITIONED)) {
61	msgConfirm("You need to partition your disk before you can proceed with\nthe installation.");
62
63	return FALSE;
64    }
65    if (!getenv(DISK_LABELLED)) {
66	msgConfirm("You need to assign disk labels before you can proceed with\nthe installation.");
67	return FALSE;
68    }
69    if (!Dists) {
70	msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu.");
71	return FALSE;
72    }
73    if (!mediaVerify())
74	return FALSE;
75    return TRUE;
76}
77
78int
79installCommit(char *str)
80{
81    extern u_char boot1[], boot2[];
82    extern u_char mbr[], bteasy17[];
83    u_char *mbrContents;
84    Device **devs;
85    int i;
86
87    /* If things aren't kosher, or we refuse to proceed, bail. */
88    if (!preInstallCheck()
89	|| msgYesNo("Last Chance!  Are you SURE you want continue the installation?\n\nIf you're running this on an existing system, we STRONGLY\nencourage you to make proper backups before proceeding.\nWe take no responsibility for lost disk contents!"))
90	return 0;
91
92    mbrContents = NULL;
93    if (!msgYesNo("Would you like to install a boot manager?\n\nThis will allow you to easily select between other operating systems\non the first disk, or boot from a disk other than the first."))
94	mbrContents = bteasy17;
95    else if (!msgYesNo("Would you like to remove an existing boot manager?"))
96	mbrContents = mbr;
97    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
98    for (i = 0; devs[i]; i++) {
99	Disk *d = (Disk *)devs[i]->private;
100	Chunk *c1;
101
102	if (!devs[i]->enabled)
103	    continue;
104
105	if (mbrContents) {
106	    Set_Boot_Mgr(d, mbrContents);
107	    mbrContents = NULL;
108	}
109	Set_Boot_Blocks(d, boot1, boot2);
110	msgNotify("Writing partition information to drive %s", d->name);
111	Write_Disk(d);
112
113	/* Now scan for bad blocks, if necessary */
114	for (c1 = d->chunks; c1; c1 = c1->next) {
115	    if (c1->flags & CHUNK_BAD144) {
116		int ret;
117
118		msgNotify("Running bad block scan on partition %s", c1->name);
119		ret = vsystem("bad144 /mnt/dev/%s 1234", c1->name);
120		if (ret)
121		    msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret);
122		ret = vsystem("bad144 -v -s /mnt/dev/%s", c1->name);
123		if (ret)
124		    msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret);
125	    }
126	}
127    }
128    make_filesystems();
129    cpio_extract();
130    distExtractAll();
131    install_configuration_files();
132    do_final_setup();
133    return 1;
134}
135
136/* Go newfs and/or mount all the filesystems we've been asked to */
137static void
138make_filesystems(void)
139{
140    int i;
141    Disk *disk;
142    Chunk *c1, *c2;
143    Device **devs;
144
145    command_clear();
146    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
147
148    /* First look for the root device and mount it */
149    for (i = 0; devs[i]; i++) {
150	disk = (Disk *)devs[i]->private;
151	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
152	if (!disk->chunks)
153	    msgFatal("No chunk list found for %s!", disk->name);
154	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
155	    if (c1->type == freebsd) {
156		for (c2 = c1->part; c2; c2 = c2->next) {
157		    if (c2->type == part && c2->subtype != FS_SWAP &&
158			c2->private && c2->flags & CHUNK_IS_ROOT) {
159			char dname[40];
160			PartInfo *p = (PartInfo *)c2->private;
161
162			if (strcmp(p->mountpoint, "/")) {
163			    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint);
164			    continue;
165			}
166			if (p->newfs) {
167			    int i;
168
169			    sprintf(dname, "/dev/r%sa", disk->name);
170			    msgNotify("Making a new root filesystem on %s", dname);
171			    i = vsystem("newfs %s", dname);
172			    if (i) {
173				msgConfirm("Unable to make new root filesystem!  Command returned status %d", i);
174				return;
175			    }
176			}
177			else
178			    msgConfirm("Warning:  You have selected a Read-Only root device\nand may be unable to find the appropriate device entries on it\nif it is from an older pre-slice version of FreeBSD.");
179			sprintf(dname, "/dev/%sa", disk->name);
180			if (Mount("/mnt", dname)) {
181			    msgConfirm("Unable to mount the root file system!  Giving up.");
182			    return;
183			}
184			else {
185			    extern int makedevs(void);
186
187			    if (Mkdir("/mnt/dev", NULL)
188				|| chdir("/mnt/dev")
189				|| makedevs())
190				msgConfirm("Failed to make some of the devices in /mnt!");
191			    chdir("/");
192			    break;
193			}
194		    }
195		}
196	    }
197	}
198    }
199
200    /* Now buzz through the rest of the partitions and mount them too */
201    for (i = 0; devs[i]; i++) {
202	disk = (Disk *)devs[i]->private;
203	if (!disk->chunks)
204	    msgFatal("No chunk list found for %s!", disk->name);
205
206	/* Make the proper device mount points in /mnt/dev */
207	MakeDevDisk(disk, "/mnt/dev");
208
209	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
210	    if (c1->type == freebsd) {
211		for (c2 = c1->part; c2; c2 = c2->next) {
212		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private) {
213			PartInfo *tmp = (PartInfo *)c2->private;
214
215			if (!strcmp(tmp->mountpoint, "/"))
216			    continue;
217
218			if (tmp->newfs)
219			    command_shell_add(tmp->mountpoint,
220					      "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name);
221			command_func_add(tmp->mountpoint, Mount, c2->name);
222		    }
223		}
224	    }
225	}
226    }
227    command_sort();
228    command_execute();
229}
230
231static void
232cpio_extract(void)
233{
234    int i, j, zpid, cpid, pfd[2];
235    extern int wait(int *status);
236
237    while (CpioFD == -1) {
238	msgConfirm("Please Insert CPIO floppy in floppy drive 0");
239	CpioFD = open("/dev/rfd0", O_RDONLY);
240    }
241    msgNotify("Extracting contents of CPIO floppy...");
242    pipe(pfd);
243    zpid = fork();
244    if (!zpid) {
245	close(0); dup(CpioFD); close(CpioFD);
246	close(1); dup(pfd[1]); close(pfd[1]);
247	close(pfd[0]);
248	i = execl("/stand/gunzip", "/stand/gunzip", 0);
249	msgDebug("/stand/gunzip command returns %d status\n", i);
250	exit(i);
251    }
252    cpid = fork();
253    if (!cpid) {
254	close(0); dup(pfd[0]); close(pfd[0]);
255	close(CpioFD);
256	close(pfd[1]);
257	close(1); open("/dev/null", O_WRONLY);
258	i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0);
259	msgDebug("/stand/cpio command returns %d status\n", i);
260	exit(i);
261    }
262    close(pfd[0]);
263    close(pfd[1]);
264    close(CpioFD);
265    i = wait(&j);
266    if (i < 0 || j)
267	msgFatal("Pid %d, status %d, cpio=%d, gunzip=%d.\nerror:%s",
268		 i, j, cpid, zpid, strerror(errno));
269    i = wait(&j);
270    if (i < 0 || j)
271	msgFatal("Pid %d, status %d, cpio=%d, gunzip=%d.\nerror:%s",
272		 i, j, cpid, zpid, strerror(errno));
273}
274
275static void
276install_configuration_files(void)
277{
278}
279
280static void
281do_final_setup(void)
282{
283}
284