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