install.c revision 8640
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.32 1995/05/20 00:13:10 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	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
79static void
80installInitial(void)
81{
82    extern u_char boot1[], boot2[];
83    extern u_char mbr[], bteasy17[];
84    u_char *mbrContents;
85    Device **devs;
86    int i;
87    static Boolean alreadyDone = FALSE;
88
89    if (alreadyDone)
90	return;
91
92    /* If things aren't kosher, or we refuse to proceed, bail. */
93    if (!preInstallCheck()
94	|| 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!"))
95	return 0;
96
97    mbrContents = NULL;
98    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."))
99	mbrContents = bteasy17;
100    else if (!msgYesNo("Would you like to remove an existing boot manager?"))
101	mbrContents = mbr;
102    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
103    for (i = 0; devs[i]; i++) {
104	Disk *d = (Disk *)devs[i]->private;
105	Chunk *c1;
106
107	if (!devs[i]->enabled)
108	    continue;
109
110	if (mbrContents) {
111	    Set_Boot_Mgr(d, mbrContents);
112	    mbrContents = NULL;
113	}
114	Set_Boot_Blocks(d, boot1, boot2);
115	msgNotify("Writing partition information to drive %s", d->name);
116	Write_Disk(d);
117
118	/* Now scan for bad blocks, if necessary */
119	for (c1 = d->chunks->part; c1; c1 = c1->next) {
120	    if (c1->flags & CHUNK_BAD144) {
121		int ret;
122
123		msgNotify("Running bad block scan on partition %s", c1->name);
124		ret = vsystem("bad144 -v /dev/r%s 1234", c1->name);
125		if (ret)
126		    msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret);
127		ret = vsystem("bad144 -v -s /dev/r%s", c1->name);
128		if (ret)
129		    msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret);
130	    }
131	}
132    }
133    make_filesystems();
134    copy_self();
135    cpio_extract();
136    alreadyDone = TRUE;
137}
138
139static void
140installFinal(void)
141{
142    static Boolean alreadyDone = FALSE;
143
144    if (alreadyDone)
145	return;
146    install_configuration_files();
147    do_final_setup();
148    alreadyDone = TRUE;
149}
150
151int
152installCommit(char *str)
153{
154    installInitial();
155    distExtractAll();
156    installFinal();
157    return 0;
158}
159
160/* Go newfs and/or mount all the filesystems we've been asked to */
161static void
162make_filesystems(void)
163{
164    int i;
165    Disk *disk;
166    Chunk *c1, *c2;
167    Device **devs;
168
169    command_clear();
170    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
171
172    /* First look for the root device and mount it */
173    for (i = 0; devs[i]; i++) {
174	disk = (Disk *)devs[i]->private;
175	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
176	if (!disk->chunks)
177	    msgFatal("No chunk list found for %s!", disk->name);
178	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
179	    if (c1->type == freebsd) {
180		for (c2 = c1->part; c2; c2 = c2->next) {
181		    if (c2->type == part && c2->subtype != FS_SWAP &&
182			c2->private && c2->flags & CHUNK_IS_ROOT) {
183			char dname[40];
184			PartInfo *p = (PartInfo *)c2->private;
185
186			if (strcmp(p->mountpoint, "/")) {
187			    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint);
188			    continue;
189			}
190			if (p->newfs) {
191			    int i;
192
193			    sprintf(dname, "/dev/r%sa", disk->name);
194			    msgNotify("Making a new root filesystem on %s", dname);
195			    i = vsystem("newfs %s", dname);
196			    if (i) {
197				msgConfirm("Unable to make new root filesystem!  Command returned status %d", i);
198				return;
199			    }
200			}
201			else
202			    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.");
203			sprintf(dname, "/dev/%sa", disk->name);
204			if (Mount("/mnt", dname)) {
205			    msgConfirm("Unable to mount the root file system!  Giving up.");
206			    return;
207			}
208			else {
209			    extern int makedevs(void);
210
211			    msgNotify("Making device files");
212			    if (Mkdir("/mnt/dev", NULL)
213				|| chdir("/mnt/dev")
214				|| makedevs())
215				msgConfirm("Failed to make some of the devices in /mnt!");
216			    if (Mkdir("/mnt/stand", NULL))
217				msgConfirm("Unable to make /mnt/stand directory!");
218			    chdir("/");
219			    break;
220			}
221		    }
222		}
223	    }
224	}
225    }
226
227    /* Now buzz through the rest of the partitions and mount them too */
228    for (i = 0; devs[i]; i++) {
229	disk = (Disk *)devs[i]->private;
230	if (!disk->chunks)
231	    msgFatal("No chunk list found for %s!", disk->name);
232
233	/* Make the proper device mount points in /mnt/dev */
234	MakeDevDisk(disk, "/mnt/dev");
235
236	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
237	    if (c1->type == freebsd) {
238		for (c2 = c1->part; c2; c2 = c2->next) {
239		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private) {
240			PartInfo *tmp = (PartInfo *)c2->private;
241
242			if (!strcmp(tmp->mountpoint, "/"))
243			    continue;
244
245			if (tmp->newfs)
246			    command_shell_add(tmp->mountpoint,
247					      "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name);
248			command_func_add(tmp->mountpoint, Mount, c2->name);
249		    }
250		}
251	    }
252	}
253    }
254    command_sort();
255    command_execute();
256}
257
258/* Copy the boot floppy contents into /stand */
259static void
260copy_self(void)
261{
262    int i;
263
264    msgNotify("Copying the boot floppy to /stand on root filesystem");
265    chdir("/");
266    i = vsystem("find -x . | cpio -pdmv /mnt/stand");
267    if (i)
268	msgConfirm("Copy returned error status of %d!", i);
269}
270
271static void
272cpio_extract(void)
273{
274    int i, j, zpid, cpid, pfd[2];
275    extern int wait(int *status);
276
277    tryagain:
278    j = fork();
279    if (!j) {
280	while (CpioFD == -1) {
281	    msgConfirm("Please Insert CPIO floppy in floppy drive 0");
282	    CpioFD = open("/dev/rfd0", O_RDONLY);
283	}
284	chroot("/mnt");	chdir("/");
285	msgNotify("Extracting contents of CPIO floppy...");
286	pipe(pfd);
287	zpid = fork();
288	if (!zpid) {
289	    dup2(CpioFD, 0); close(CpioFD);
290	    dup2(pfd[1], 1); close(pfd[1]);
291	    close(pfd[0]);
292	    i = execl("/stand/gunzip", "/stand/gunzip", 0);
293	    msgDebug("/stand/gunzip command returns %d status\n", i);
294	    exit(i);
295	}
296	cpid = fork();
297	if (!cpid) {
298	    dup2(pfd[0], 0); close(pfd[0]);
299	    close(CpioFD);
300	    close(pfd[1]);
301	    if (DebugFD != -1) {
302		dup2(DebugFD, 1);
303		dup2(DebugFD, 2);
304	    }
305	    else {
306		close(1); open("/dev/null", O_WRONLY);
307		dup2(1, 2);
308	    }
309	    i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0);
310	    msgDebug("/stand/cpio command returns %d status\n", i);
311	    exit(i);
312	}
313	close(pfd[0]);
314	close(pfd[1]);
315	close(CpioFD);
316
317	i = waitpid(zpid, &j, 0);
318	if (i < 0 || j) {
319	    msgConfirm("gunzip returned status of %d, error was: %s (%d)!  Help!", j, strerror(errno), errno);
320	    exit(1);
321	}
322	i = waitpid(cpid, &j);
323	if (i < 0 || j) {
324	    msgConfirm("cpio returned status of %d, error was: %s (%d)!  Help!", j, strerror(errno), errno);
325	    exit(2);
326	}
327	exit(0);
328    }
329    else
330	i = wait(&j);
331    if (i < 0 || j || access("/mnt/OK", R_OK) == -1) {
332	msgConfirm("CPIO floppy did not extract properly!  Please verify\n\that your media is correct and try again");
333	goto tryagain;
334    }
335    unlink("/mnt/OK");
336}
337
338static void
339install_configuration_files(void)
340{
341}
342
343static void
344do_final_setup(void)
345{
346}
347