install.c revision 8628
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.29 1995/05/19 01:49:57 gpalmer 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	copy_self(void);
54static void	cpio_extract(void);
55static void	install_configuration_files(void);
56static void	do_final_setup(void);
57
58static Boolean
59preInstallCheck(void)
60{
61    if (!getenv(DISK_PARTITIONED)) {
62	msgConfirm("You need to partition your disk before you can proceed with\nthe installation.");
63
64	return FALSE;
65    }
66    if (!getenv(DISK_LABELLED)) {
67	msgConfirm("You need to assign disk labels before you can proceed with\nthe installation.");
68	return FALSE;
69    }
70    if (!Dists) {
71	msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu.");
72	return FALSE;
73    }
74    if (!mediaVerify())
75	return FALSE;
76    return TRUE;
77}
78
79int
80installCommit(char *str)
81{
82    extern u_char boot1[], boot2[];
83    extern u_char mbr[], bteasy17[];
84    u_char *mbrContents;
85    Device **devs;
86    int i;
87
88    /* If things aren't kosher, or we refuse to proceed, bail. */
89    if (!preInstallCheck()
90	|| 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!"))
91	return 0;
92
93    mbrContents = NULL;
94    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."))
95	mbrContents = bteasy17;
96    else if (!msgYesNo("Would you like to remove an existing boot manager?"))
97	mbrContents = mbr;
98    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
99    for (i = 0; devs[i]; i++) {
100	Disk *d = (Disk *)devs[i]->private;
101	Chunk *c1;
102
103	if (!devs[i]->enabled)
104	    continue;
105
106	if (mbrContents) {
107	    Set_Boot_Mgr(d, mbrContents);
108	    mbrContents = NULL;
109	}
110	Set_Boot_Blocks(d, boot1, boot2);
111	msgNotify("Writing partition information to drive %s", d->name);
112	Write_Disk(d);
113
114	/* Now scan for bad blocks, if necessary */
115	for (c1 = d->chunks->part; c1; c1 = c1->next) {
116	    if (c1->flags & CHUNK_BAD144) {
117		int ret;
118
119		msgNotify("Running bad block scan on partition %s", c1->name);
120		ret = vsystem("bad144 -v /dev/r%s 1234", c1->name);
121		if (ret)
122		    msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret);
123		ret = vsystem("bad144 -v -s /dev/r%s", c1->name);
124		if (ret)
125		    msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret);
126	    }
127	}
128    }
129    make_filesystems();
130    copy_self();
131    cpio_extract();
132    distExtractAll();
133    install_configuration_files();
134    do_final_setup();
135    return 1;
136}
137
138/* Go newfs and/or mount all the filesystems we've been asked to */
139static void
140make_filesystems(void)
141{
142    int i;
143    Disk *disk;
144    Chunk *c1, *c2;
145    Device **devs;
146
147    command_clear();
148    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
149
150    /* First look for the root device and mount it */
151    for (i = 0; devs[i]; i++) {
152	disk = (Disk *)devs[i]->private;
153	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
154	if (!disk->chunks)
155	    msgFatal("No chunk list found for %s!", disk->name);
156	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
157	    if (c1->type == freebsd) {
158		for (c2 = c1->part; c2; c2 = c2->next) {
159		    if (c2->type == part && c2->subtype != FS_SWAP &&
160			c2->private && c2->flags & CHUNK_IS_ROOT) {
161			char dname[40];
162			PartInfo *p = (PartInfo *)c2->private;
163
164			if (strcmp(p->mountpoint, "/")) {
165			    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint);
166			    continue;
167			}
168			if (p->newfs) {
169			    int i;
170
171			    sprintf(dname, "/dev/r%sa", disk->name);
172			    msgNotify("Making a new root filesystem on %s", dname);
173			    i = vsystem("newfs %s", dname);
174			    if (i) {
175				msgConfirm("Unable to make new root filesystem!  Command returned status %d", i);
176				return;
177			    }
178			}
179			else
180			    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.");
181			sprintf(dname, "/dev/%sa", disk->name);
182			if (Mount("/mnt", dname)) {
183			    msgConfirm("Unable to mount the root file system!  Giving up.");
184			    return;
185			}
186			else {
187			    extern int makedevs(void);
188
189			    if (Mkdir("/mnt/dev", NULL)
190				|| chdir("/mnt/dev")
191				|| makedevs())
192				msgConfirm("Failed to make some of the devices in /mnt!");
193			    if (Mkdir("/mnt/stand", NULL))
194				msgConfirm("Unable to make /mnt/stand directory!");
195			    chdir("/");
196			    break;
197			}
198		    }
199		}
200	    }
201	}
202    }
203
204    /* Now buzz through the rest of the partitions and mount them too */
205    for (i = 0; devs[i]; i++) {
206	disk = (Disk *)devs[i]->private;
207	if (!disk->chunks)
208	    msgFatal("No chunk list found for %s!", disk->name);
209
210	/* Make the proper device mount points in /mnt/dev */
211	MakeDevDisk(disk, "/mnt/dev");
212
213	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
214	    if (c1->type == freebsd) {
215		for (c2 = c1->part; c2; c2 = c2->next) {
216		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private) {
217			PartInfo *tmp = (PartInfo *)c2->private;
218
219			if (!strcmp(tmp->mountpoint, "/"))
220			    continue;
221
222			if (tmp->newfs)
223			    command_shell_add(tmp->mountpoint,
224					      "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name);
225			command_func_add(tmp->mountpoint, Mount, c2->name);
226		    }
227		}
228	    }
229	}
230    }
231    command_sort();
232    command_execute();
233}
234
235/* Copy the boot floppy contents into /stand */
236static void
237copy_self(void)
238{
239    int i;
240
241    msgNotify("Copying the boot floppy to /stand on root filesystem");
242    chdir("/");
243    i = vsystem("find -x . | cpio -pdmv /mnt/stand");
244    if (i)
245	msgConfirm("Copy returned error status of %d!", i);
246}
247
248static void
249cpio_extract(void)
250{
251    int i, j, zpid, cpid, pfd[2];
252    extern int wait(int *status);
253
254    while (CpioFD == -1) {
255	msgConfirm("Please Insert CPIO floppy in floppy drive 0");
256	CpioFD = open("/dev/rfd0", O_RDONLY);
257    }
258    msgNotify("Extracting contents of CPIO floppy...");
259    pipe(pfd);
260    zpid = fork();
261    if (!zpid) {
262	close(0); dup(CpioFD); close(CpioFD);
263	close(1); dup(pfd[1]); close(pfd[1]);
264	close(pfd[0]);
265	i = execl("/stand/gunzip", "/stand/gunzip", 0);
266	msgDebug("/stand/gunzip command returns %d status\n", i);
267	exit(i);
268    }
269    cpid = fork();
270    if (!cpid) {
271	close(0); dup(pfd[0]); close(pfd[0]);
272	close(CpioFD);
273	close(pfd[1]);
274        if (DebugFD != -1) {
275	    dup2(DebugFD, 1);
276	    dup2(DebugFD, 2);
277	}
278	else {
279		close(1); open("/dev/null", O_WRONLY);
280		dup2(1, 2);
281	}
282	chdir("/mnt");
283	i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0);
284	msgDebug("/stand/cpio command returns %d status\n", i);
285	exit(i);
286    }
287    close(pfd[0]);
288    close(pfd[1]);
289    close(CpioFD);
290    i = wait(&j);
291    if (i < 0 || j)
292	msgFatal("Pid %d, status %d, cpio=%d, gunzip=%d.\nerror:%s",
293		 i, j, cpid, zpid, strerror(errno));
294    i = wait(&j);
295    if (i < 0 || j)
296	msgFatal("Pid %d, status %d, cpio=%d, gunzip=%d.\nerror:%s",
297		 i, j, cpid, zpid, strerror(errno));
298}
299
300static void
301install_configuration_files(void)
302{
303}
304
305static void
306do_final_setup(void)
307{
308}
309