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