install.c revision 8654
12340Sbde/*
250476Speter * The new sysinstall program.
31638Srgrimes *
42340Sbde * This is probably the last program in the `sysinstall' line - the next
578347Sobrien * generation being essentially a complete rewrite.
61638Srgrimes *
7209024Simp * $Id: install.c,v 1.39 1995/05/20 16:22:42 jkh Exp $
8209024Simp *
9209024Simp * Copyright (c) 1995
10215149Sdim *	Jordan Hubbard.  All rights reserved.
11215149Sdim *
12215149Sdim * Redistribution and use in source and binary forms, with or without
13215149Sdim * modification, are permitted provided that the following conditions
14215149Sdim * are met:
15209024Simp * 1. Redistributions of source code must retain the above copyright
16300438Sian *    notice, this list of conditions and the following disclaimer,
17209024Simp *    verbatim and that no modifications are made prior to this
18209024Simp *    point in the file.
19284345Ssjg * 2. Redistributions in binary form must reproduce the above copyright
20284345Ssjg *    notice, this list of conditions and the following disclaimer in the
21284345Ssjg *    documentation and/or other materials provided with the distribution.
22290816Ssjg * 3. All advertising materials mentioning features or use of this software
23290956Ssjg *    must display the following acknowledgement:
24284345Ssjg *	This product includes software developed by Jordan Hubbard
25284345Ssjg *	for the FreeBSD Project.
26290816Ssjg * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to
27290956Ssjg *    endorse or promote products derived from this software without specific
28290816Ssjg *    prior written permission.
29290816Ssjg *
30284345Ssjg * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
31287932Sbdrewery * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32287932Sbdrewery * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33287932Sbdrewery * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
34287932Sbdrewery * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35287932Sbdrewery * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36284598Ssjg * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
37284598Ssjg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38287187Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39287187Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40287187Simp * SUCH DAMAGE.
41287187Simp *
42284345Ssjg */
43287924Sbdrewery
44287924Sbdrewery#include "sysinstall.h"
45301886Sbdrewery#include <sys/disklabel.h>
46301886Sbdrewery#include <sys/errno.h>
47301886Sbdrewery#include <sys/fcntl.h>
48301886Sbdrewery#include <sys/wait.h>
49301886Sbdrewery#include <unistd.h>
50290816Ssjg
51287187SimpBoolean SystemWasInstalled;
52301886Sbdrewery
53296118Sbdrewerystatic void	make_filesystems(void);
54300526Sbdrewerystatic void	copy_self(void);
55301466Sbdrewerystatic void	cpio_extract(void);
56301466Sbdrewerystatic void	install_configuration_files(void);
57301466Sbdrewerystatic void	do_final_setup(void);
58296123Sbdrewery
59296123Sbdrewerystatic Boolean
60296123SbdrewerypreInstallCheck(void)
61296123Sbdrewery{
62294350Sbdrewery    if (!getenv(DISK_PARTITIONED)) {
63296118Sbdrewery	msgConfirm("You need to partition your disk before you can proceed with\nthe installation.");
64284345Ssjg
65301466Sbdrewery	return FALSE;
66301466Sbdrewery    }
67301466Sbdrewery    if (!getenv(DISK_LABELLED)) {
68294350Sbdrewery	msgConfirm("You need to assign disk labels before you can proceed with\nthe installation.");
69301466Sbdrewery	return FALSE;
70296118Sbdrewery    }
71296118Sbdrewery    if (!Dists) {
72296118Sbdrewery	msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu.");
73301467Sbdrewery	return FALSE;
74301467Sbdrewery    }
75301467Sbdrewery    return TRUE;
76301467Sbdrewery}
77301467Sbdrewery
78302073Sbdrewerystatic void
79302073SbdreweryinstallInitial(void)
80301467Sbdrewery{
81301467Sbdrewery    extern u_char boot1[], boot2[];
82301467Sbdrewery    extern u_char mbr[], bteasy17[];
83301467Sbdrewery    u_char *mbrContents;
84301467Sbdrewery    Device **devs;
85301467Sbdrewery    int i;
86301467Sbdrewery    static Boolean alreadyDone = FALSE;
87301467Sbdrewery
88301467Sbdrewery    if (alreadyDone)
89301467Sbdrewery	return;
90301467Sbdrewery
91301467Sbdrewery    /* If things aren't kosher, or we refuse to proceed, bail. */
92294349Sbdrewery    if (!preInstallCheck()
93301467Sbdrewery	|| 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!"))
94301467Sbdrewery	return;
95301467Sbdrewery
96284345Ssjg    mbrContents = NULL;
97284345Ssjg    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."))
98291312Sbdrewery	mbrContents = bteasy17;
99291312Sbdrewery    else if (!msgYesNo("Would you like to remove an existing boot manager?"))
100291312Sbdrewery	mbrContents = mbr;
101287187Simp    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
102284345Ssjg    for (i = 0; devs[i]; i++) {
103287879Sbdrewery	Disk *d = (Disk *)devs[i]->private;
104287924Sbdrewery	Chunk *c1;
105287924Sbdrewery
106287187Simp	if (!devs[i]->enabled)
107287187Simp	    continue;
10819343Ssteve
10919343Ssteve	if (mbrContents) {
11019343Ssteve	    Set_Boot_Mgr(d, mbrContents);
11119343Ssteve	    mbrContents = NULL;
11219343Ssteve	}
11319343Ssteve	Set_Boot_Blocks(d, boot1, boot2);
11419343Ssteve	msgNotify("Writing partition information to drive %s", d->name);
11519343Ssteve	Write_Disk(d);
116292718Scperciva
117292718Scperciva	/* Now scan for bad blocks, if necessary */
118292718Scperciva	for (c1 = d->chunks->part; c1; c1 = c1->next) {
119292718Scperciva	    if (c1->flags & CHUNK_BAD144) {
12019343Ssteve		int ret;
12119343Ssteve
12219343Ssteve		msgNotify("Running bad block scan on partition %s", c1->name);
12319343Ssteve		ret = vsystem("bad144 -v /dev/r%s 1234", c1->name);
124117173Sru		if (ret)
12519343Ssteve		    msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret);
1261638Srgrimes		ret = vsystem("bad144 -v -s /dev/r%s", c1->name);
1272340Sbde		if (ret)
12819343Ssteve		    msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret);
12919343Ssteve	    }
13019343Ssteve	}
131264367Sdes    }
13219343Ssteve    make_filesystems();
1332340Sbde    copy_self();
134264367Sdes    dialog_clear();
135264367Sdes    cpio_extract();
136264367Sdes    alreadyDone = TRUE;
1371638Srgrimes}
1382340Sbde
1392340Sbdestatic void
140217100SkibinstallFinal(void)
1411638Srgrimes{
14219343Ssteve    static Boolean alreadyDone = FALSE;
14319343Ssteve
144125445Sbde    if (alreadyDone)
14519343Ssteve	return;
1462340Sbde    install_configuration_files();
147209024Simp    do_final_setup();
148177865Sobrien    alreadyDone = TRUE;
149173375Scognet}
150177865Sobrien
15119343Ssteveint
152173850SjbinstallCommit(char *str)
153173850Sjb{
154173375Scognet    installInitial();
155173850Sjb    if (!mediaVerify())
156202807Ssepotvin	return 0;
1571638Srgrimes    distExtractAll();
158281258Smarkj    installFinal();
159281258Smarkj    return 0;
160281258Smarkj}
161281258Smarkj
162281258Smarkj/* Go newfs and/or mount all the filesystems we've been asked to */
163281258Smarkjstatic void
164179184Sjbmake_filesystems(void)
165179184Sjb{
166179184Sjb    int i;
167179184Sjb    Disk *disk;
168179184Sjb    Chunk *c1, *c2;
169277273Swill    Device **devs;
170179184Sjb
171179184Sjb    command_clear();
172179184Sjb    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
173179184Sjb
1742419Spaul    /* First look for the root device and mount it */
175204024Smarcel    for (i = 0; devs[i]; i++) {
176202807Ssepotvin	disk = (Disk *)devs[i]->private;
1771638Srgrimes	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
178281258Smarkj	if (!disk->chunks)
179281258Smarkj	    msgFatal("No chunk list found for %s!", disk->name);
1801638Srgrimes	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
181125119Sru	    if (c1->type == freebsd) {
1822340Sbde		for (c2 = c1->part; c2; c2 = c2->next) {
1832340Sbde		    if (c2->type == part && c2->subtype != FS_SWAP &&
1842340Sbde			c2->private && c2->flags & CHUNK_IS_ROOT) {
1852340Sbde			char dname[40];
1862340Sbde			PartInfo *p = (PartInfo *)c2->private;
1872340Sbde
1882340Sbde			if (strcmp(p->mountpoint, "/")) {
1892340Sbde			    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint);
1902340Sbde			    continue;
1912340Sbde			}
1921638Srgrimes			if (p->newfs) {
193289460Sbdrewery			    int i;
194289460Sbdrewery
195289460Sbdrewery			    sprintf(dname, "/dev/r%sa", disk->name);
196289460Sbdrewery			    msgNotify("Making a new root filesystem on %s", dname);
197289460Sbdrewery			    i = vsystem("newfs %s", dname);
198289460Sbdrewery			    if (i) {
199133369Sharti				msgConfirm("Unable to make new root filesystem!  Command returned status %d", i);
200133369Sharti				return;
201133369Sharti			    }
202133369Sharti			}
203133369Sharti			else
20419343Ssteve			    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.");
20519343Ssteve			sprintf(dname, "/dev/%sa", disk->name);
20619343Ssteve			if (Mount("/mnt", dname)) {
20719343Ssteve			    msgConfirm("Unable to mount the root file system!  Giving up.");
2082340Sbde			    return;
2092340Sbde			}
21019343Ssteve			else {
2112340Sbde			    extern int makedevs(void);
2121638Srgrimes
2135257Sache			    msgNotify("Making device files");
2145257Sache			    if (Mkdir("/mnt/dev", NULL)
2152340Sbde				|| chdir("/mnt/dev")
2162340Sbde				|| makedevs())
2171638Srgrimes				msgConfirm("Failed to make some of the devices in /mnt!");
2182340Sbde			    if (Mkdir("/mnt/stand", NULL))
219269114Ssjg				msgConfirm("Unable to make /mnt/stand directory!");
220269114Ssjg			    chdir("/");
2211638Srgrimes			    break;
2222340Sbde			}
22392813Sru		    }
22492491Smarkm		}
22592491Smarkm	    }
226120485Smarkm	}
22792491Smarkm    }
2281638Srgrimes
2292340Sbde    /* Now buzz through the rest of the partitions and mount them too */
2301638Srgrimes    for (i = 0; devs[i]; i++) {
231234575Simp	disk = (Disk *)devs[i]->private;
232234575Simp	if (!disk->chunks)
233286791Srpaulo	    msgFatal("No chunk list found for %s!", disk->name);
234234575Simp
23536054Sbde	/* Make the proper device mount points in /mnt/dev */
23636054Sbde	MakeDevDisk(disk, "/mnt/dev");
23736054Sbde
238244236Semaste	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
239244236Semaste	    if (c1->type == freebsd) {
240274503Sandrew		for (c2 = c1->part; c2; c2 = c2->next) {
241274503Sandrew		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private) {
2422340Sbde			PartInfo *tmp = (PartInfo *)c2->private;
2432340Sbde
2441638Srgrimes			if (!strcmp(tmp->mountpoint, "/"))
2452340Sbde			    continue;
2462340Sbde
247244366Semaste			if (tmp->newfs)
2481638Srgrimes			    command_shell_add(tmp->mountpoint,
2492340Sbde					      "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name);
2502340Sbde			command_func_add(tmp->mountpoint, Mount, c2->name);
251272887Sbapt		    }
252272887Sbapt		}
253272887Sbapt	    }
254272887Sbapt	}
2552340Sbde    }
25619343Ssteve    command_sort();
25719343Ssteve    command_execute();
25819343Ssteve}
2592340Sbde
26019343Ssteve/* Copy the boot floppy contents into /stand */
2612340Sbdestatic void
26219343Sstevecopy_self(void)
263129163Sbde{
26419343Ssteve    int i;
26519343Ssteve
26619343Ssteve    msgNotify("Copying the boot floppy to /stand on root filesystem");
26719343Ssteve    i = vsystem("find -x / | cpio -pdmv /mnt");
26819343Ssteve    if (i)
26919343Ssteve	msgConfirm("Copy returned error status of %d!", i);
27019343Ssteve}
27111613Sbde
27219481Salexstatic void
27319343Sstevecpio_extract(void)
27419343Ssteve{
27519481Salex    int i, j, zpid, cpid, pfd[2];
27619343Ssteve
27719343Ssteve tryagain:
278211243Swill    while (CpioFD == -1) {
27919343Ssteve	msgConfirm("Please Insert CPIO floppy in floppy drive 0");
28019343Ssteve	CpioFD = open("/dev/rfd0", O_RDWR);
28119343Ssteve	if (CpioFD >= 0)
28219343Ssteve	    break;
28319343Ssteve	msgDebug("Error on open of cpio floppy: %s (%d)\n", strerror(errno), errno);
28419481Salex    }
28519343Ssteve    j = fork();
28619343Ssteve    if (!j) {
28719481Salex	chroot("/mnt");	chdir("/");
28819343Ssteve	msgNotify("Extracting contents of CPIO floppy...");
28919343Ssteve	pipe(pfd);
29019481Salex	zpid = fork();
29119481Salex	if (!zpid) {
29239208Sobrien	    dup2(CpioFD, 0); close(CpioFD);
29319343Ssteve	    dup2(pfd[1], 1); close(pfd[1]);
29419343Ssteve	    close(pfd[0]);
29519343Ssteve	    i = execl("/stand/gunzip", "/stand/gunzip", 0);
29619481Salex	    msgDebug("/stand/gunzip command returns %d status\n", i);
29719481Salex	    exit(i);
29839208Sobrien	}
29919343Ssteve	cpid = fork();
30019343Ssteve	if (!cpid) {
30119343Ssteve	    dup2(pfd[0], 0); close(pfd[0]);
30219481Salex	    close(CpioFD);
30319343Ssteve	    close(pfd[1]);
30419343Ssteve	    if (DebugFD != -1) {
30519343Ssteve		dup2(DebugFD, 1);
30619481Salex		dup2(DebugFD, 2);
30719343Ssteve	    }
30819343Ssteve	    else {
30919343Ssteve		close(1); open("/dev/null", O_WRONLY);
31019481Salex		dup2(1, 2);
31119481Salex	    }
31239208Sobrien	    i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0);
31319343Ssteve	    msgDebug("/stand/cpio command returns %d status\n", i);
31419343Ssteve	    exit(i);
31519481Salex	}
31619481Salex	close(pfd[0]);
31739208Sobrien	close(pfd[1]);
31819343Ssteve	close(CpioFD);
31919343Ssteve
32019343Ssteve	i = waitpid(zpid, &j, 0);
32119343Ssteve	if (i < 0 || j) {
32219343Ssteve	    msgConfirm("gunzip returned status of %d, error was: %s (%d)!", j, strerror(errno), errno);
323301284Sbdrewery	    exit(1);
324296119Sbdrewery	}
32511613Sbde	i = waitpid(cpid, &j, 0);
32611613Sbde	if (i < 0 || j) {
327301284Sbdrewery	    msgConfirm("cpio returned status of %d, error was: %s (%d)!", j, strerror(errno), errno);
328103713Smarkm	    exit(2);
329103713Smarkm	}
330103713Smarkm	exit(0);
331301284Sbdrewery    }
332103713Smarkm    else
333103713Smarkm	i = wait(&j);
334103713Smarkm    if (i < 0 || j || access("/mnt/OK", R_OK) == -1) {
335301284Sbdrewery	msgConfirm("CPIO floppy did not extract properly!  Please verify\nthat your media is correct and try again");
33677817Sobrien	close(CpioFD);
337228137Sfjoe	CpioFD = -1;
33877817Sobrien	goto tryagain;
339301284Sbdrewery    }
340279980Sdim    unlink("/mnt/OK");
341228137Sfjoe}
3421638Srgrimes
343301284Sbdrewerystatic void
34477817Sobrieninstall_configuration_files(void)
34577817Sobrien{
346301284Sbdrewery}
347279980Sdim
3481844Swollmanstatic void
349301284Sbdrewerydo_final_setup(void)
350279980Sdim{
351228137Sfjoe}
35236054Sbde