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