install.c revision 8677
1230557Sjimharris/* 2230557Sjimharris * The new sysinstall program. 3230557Sjimharris * 4230557Sjimharris * This is probably the last program in the `sysinstall' line - the next 5230557Sjimharris * generation being essentially a complete rewrite. 6230557Sjimharris * 7230557Sjimharris * $Id: install.c,v 1.45 1995/05/21 01:56:01 phk Exp $ 8230557Sjimharris * 9230557Sjimharris * Copyright (c) 1995 10230557Sjimharris * Jordan Hubbard. All rights reserved. 11230557Sjimharris * 12230557Sjimharris * Redistribution and use in source and binary forms, with or without 13230557Sjimharris * modification, are permitted provided that the following conditions 14230557Sjimharris * are met: 15230557Sjimharris * 1. Redistributions of source code must retain the above copyright 16230557Sjimharris * notice, this list of conditions and the following disclaimer, 17230557Sjimharris * verbatim and that no modifications are made prior to this 18230557Sjimharris * point in the file. 19230557Sjimharris * 2. Redistributions in binary form must reproduce the above copyright 20230557Sjimharris * notice, this list of conditions and the following disclaimer in the 21230557Sjimharris * documentation and/or other materials provided with the distribution. 22230557Sjimharris * 3. All advertising materials mentioning features or use of this software 23230557Sjimharris * must display the following acknowledgement: 24230557Sjimharris * This product includes software developed by Jordan Hubbard 25230557Sjimharris * for the FreeBSD Project. 26230557Sjimharris * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 27230557Sjimharris * endorse or promote products derived from this software without specific 28230557Sjimharris * prior written permission. 29230557Sjimharris * 30230557Sjimharris * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 31230557Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32230557Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33230557Sjimharris * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 34230557Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35230557Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36230557Sjimharris * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 37230557Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38230557Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39230557Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40230557Sjimharris * SUCH DAMAGE. 41230557Sjimharris * 42230557Sjimharris */ 43230557Sjimharris 44230557Sjimharris#include "sysinstall.h" 45230557Sjimharris#include <sys/disklabel.h> 46230557Sjimharris#include <sys/errno.h> 47230557Sjimharris#include <sys/fcntl.h> 48230557Sjimharris#include <sys/wait.h> 49230557Sjimharris#include <unistd.h> 50230557Sjimharris 51230557SjimharrisBoolean SystemWasInstalled; 52230557Sjimharris 53230557Sjimharrisstatic void make_filesystems(void); 54230557Sjimharrisstatic void copy_self(void); 55230557Sjimharrisstatic void cpio_extract(void); 56230557Sjimharrisstatic void install_configuration_files(void); 57230557Sjimharrisstatic void do_final_setup(void); 58230557Sjimharris 59230557Sjimharrisstatic void 60230557SjimharrisinstallInitial(void) 61230557Sjimharris{ 62230557Sjimharris extern u_char boot1[], boot2[]; 63230557Sjimharris extern u_char mbr[], bteasy17[]; 64230557Sjimharris u_char *mbrContents; 65230557Sjimharris Device **devs; 66230557Sjimharris int i; 67230557Sjimharris static Boolean alreadyDone = FALSE; 68230557Sjimharris char *cp; 69240514Sjimharris 70230557Sjimharris if (alreadyDone) 71230557Sjimharris return; 72230557Sjimharris 73230557Sjimharris if (!getenv(DISK_PARTITIONED)) { 74230557Sjimharris msgConfirm("You need to partition your disk before you can proceed with\nthe installation."); 75230557Sjimharris return; 76230557Sjimharris } 77230557Sjimharris if (!getenv(DISK_LABELLED)) { 78230557Sjimharris msgConfirm("You need to assign disk labels before you can proceed with\nthe installation."); 79230557Sjimharris return; 80230557Sjimharris } 81230557Sjimharris 82230557Sjimharris /* Figure out what kind of MBR the user wants */ 83230557Sjimharris dmenuOpenSimple(&MenuMBRType); 84230557Sjimharris mbrContents = NULL; 85230557Sjimharris cp = getenv("bootManager"); 86230557Sjimharris if (cp) { 87230557Sjimharris if (!strcmp(cp, "bteasy")) 88230557Sjimharris mbrContents = bteasy17; 89230557Sjimharris else if (!strcmp(cp, "mbr")) 90230557Sjimharris mbrContents = mbr; 91230557Sjimharris } 92240514Sjimharris 93230557Sjimharris /* If we refuse to proceed, bail. */ 94230557Sjimharris if (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!")) 95230557Sjimharris return; 96230557Sjimharris 97230557Sjimharris devs = deviceFind(NULL, DEVICE_TYPE_DISK); 98230557Sjimharris for (i = 0; devs[i]; i++) { 99230557Sjimharris Disk *d = (Disk *)devs[i]->private; 100230557Sjimharris Chunk *c1; 101230557Sjimharris 102230557Sjimharris if (!devs[i]->enabled) 103230557Sjimharris continue; 104240514Sjimharris 105230557Sjimharris if (mbrContents) { 106230557Sjimharris Set_Boot_Mgr(d, mbrContents); 107230557Sjimharris mbrContents = NULL; 108230557Sjimharris } 109240514Sjimharris Set_Boot_Blocks(d, boot1, boot2); 110240514Sjimharris msgNotify("Writing partition information to drive %s", d->name); 111230557Sjimharris Write_Disk(d); 112230557Sjimharris 113230557Sjimharris /* Now scan for bad blocks, if necessary */ 114230557Sjimharris for (c1 = d->chunks->part; c1; c1 = c1->next) { 115230557Sjimharris if (c1->flags & CHUNK_BAD144) { 116230557Sjimharris int ret; 117230557Sjimharris 118230557Sjimharris msgNotify("Running bad block scan on partition %s", c1->name); 119230557Sjimharris ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 120230557Sjimharris if (ret) 121230557Sjimharris msgConfirm("Bad144 init on %s returned status of %d!", 122230557Sjimharris c1->name, ret); 123230557Sjimharris ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 124230557Sjimharris if (ret) 125230557Sjimharris msgConfirm("Bad144 scan on %s returned status of %d!", 126230557Sjimharris c1->name, ret); 127230557Sjimharris } 128230557Sjimharris } 129230557Sjimharris } 130230557Sjimharris make_filesystems(); 131230557Sjimharris copy_self(); 132230557Sjimharris dialog_clear(); 133230557Sjimharris chroot("/mnt"); 134230557Sjimharris chdir("/"); 135230557Sjimharris cpio_extract(); 136230557Sjimharris alreadyDone = TRUE; 137230557Sjimharris} 138230557Sjimharris 139230557Sjimharrisstatic void 140230557SjimharrisinstallFinal(void) 141230557Sjimharris{ 142230557Sjimharris static Boolean alreadyDone = FALSE; 143230557Sjimharris 144230557Sjimharris if (alreadyDone) 145230557Sjimharris return; 146230557Sjimharris install_configuration_files(); 147230557Sjimharris do_final_setup(); 148230557Sjimharris alreadyDone = TRUE; 149230557Sjimharris} 150230557Sjimharris 151230557Sjimharris/* 152240514Sjimharris * What happens when we select "GO". This is broken into a 3 stage installation so that 153240514Sjimharris * the user can do a full installation but come back here again to load more distributions, 154240514Sjimharris * perhaps from a different media type. This would allow, for example, the user to load the 155230557Sjimharris * majority of the system from CDROM and then use ftp to load just the DES dist. 156230557Sjimharris */ 157230557Sjimharrisint 158230557SjimharrisinstallCommit(char *str) 159230557Sjimharris{ 160230557Sjimharris if (!Dists) { 161230557Sjimharris msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu."); 162230557Sjimharris return 0; 163230557Sjimharris } 164230557Sjimharris if (!mediaVerify()) 165230557Sjimharris return 0; 166230557Sjimharris 167230557Sjimharris installInitial(); 168230557Sjimharris distExtractAll(); 169230557Sjimharris installFinal(); 170230557Sjimharris return 0; 171230557Sjimharris} 172230557Sjimharris 173230557Sjimharris/* Go newfs and/or mount all the filesystems we've been asked to */ 174230557Sjimharrisstatic void 175230557Sjimharrismake_filesystems(void) 176230557Sjimharris{ 177230557Sjimharris int i; 178230557Sjimharris Disk *disk; 179230557Sjimharris Chunk *c1, *c2; 180230557Sjimharris Device **devs; 181230557Sjimharris 182230557Sjimharris command_clear(); 183230557Sjimharris devs = deviceFind(NULL, DEVICE_TYPE_DISK); 184230557Sjimharris 185230557Sjimharris /* First look for the root device and mount it */ 186230557Sjimharris for (i = 0; devs[i]; i++) { 187230557Sjimharris disk = (Disk *)devs[i]->private; 188230557Sjimharris msgDebug("Scanning disk %s for root filesystem\n", disk->name); 189230557Sjimharris if (!disk->chunks) 190230557Sjimharris msgFatal("No chunk list found for %s!", disk->name); 191230557Sjimharris for (c1 = disk->chunks->part; c1; c1 = c1->next) { 192230557Sjimharris if (c1->type == freebsd) { 193230557Sjimharris for (c2 = c1->part; c2; c2 = c2->next) { 194230557Sjimharris if (c2->type == part && c2->subtype != FS_SWAP && 195230557Sjimharris c2->private && c2->flags & CHUNK_IS_ROOT) { 196230557Sjimharris char dname[40]; 197230557Sjimharris PartInfo *p = (PartInfo *)c2->private; 198230557Sjimharris 199230557Sjimharris if (strcmp(p->mountpoint, "/")) { 200230557Sjimharris msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint); 201230557Sjimharris continue; 202230557Sjimharris } 203230557Sjimharris if (p->newfs) { 204230557Sjimharris int i; 205230557Sjimharris 206230557Sjimharris sprintf(dname, "/dev/r%sa", disk->name); 207230557Sjimharris msgNotify("Making a new root filesystem on %s", dname); 208230557Sjimharris i = vsystem("%s %s", p->newfs_cmd,dname); 209230557Sjimharris if (i) { 210230557Sjimharris msgConfirm("Unable to make new root filesystem! Command returned status %d", i); 211230557Sjimharris return; 212230557Sjimharris } 213230557Sjimharris } 214230557Sjimharris else 215230557Sjimharris 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."); 216230557Sjimharris sprintf(dname, "/dev/%sa", disk->name); 217230557Sjimharris if (Mount("/mnt", dname)) { 218230557Sjimharris msgConfirm("Unable to mount the root file system! Giving up."); 219230557Sjimharris return; 220230557Sjimharris } 221230557Sjimharris else { 222230557Sjimharris extern int makedevs(void); 223230557Sjimharris 224230557Sjimharris msgNotify("Making device files"); 225230557Sjimharris if (Mkdir("/mnt/dev", NULL) 226230557Sjimharris || chdir("/mnt/dev") 227230557Sjimharris || makedevs()) 228230557Sjimharris msgConfirm("Failed to make some of the devices in /mnt!"); 229230557Sjimharris if (Mkdir("/mnt/stand", NULL)) 230230557Sjimharris msgConfirm("Unable to make /mnt/stand directory!"); 231230557Sjimharris chdir("/"); 232230557Sjimharris break; 233230557Sjimharris } 234230557Sjimharris } 235230557Sjimharris } 236230557Sjimharris } 237230557Sjimharris } 238230557Sjimharris } 239230557Sjimharris 240230557Sjimharris /* Now buzz through the rest of the partitions and mount them too */ 241230557Sjimharris for (i = 0; devs[i]; i++) { 242230557Sjimharris disk = (Disk *)devs[i]->private; 243230557Sjimharris if (!disk->chunks) 244230557Sjimharris msgFatal("No chunk list found for %s!", disk->name); 245230557Sjimharris 246230557Sjimharris /* Make the proper device mount points in /mnt/dev */ 247230557Sjimharris MakeDevDisk(disk, "/mnt/dev"); 248230557Sjimharris 249230557Sjimharris for (c1 = disk->chunks->part; c1; c1 = c1->next) { 250230557Sjimharris if (c1->type == freebsd) { 251230557Sjimharris for (c2 = c1->part; c2; c2 = c2->next) { 252230557Sjimharris if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 253230557Sjimharris PartInfo *tmp = (PartInfo *)c2->private; 254230557Sjimharris 255230557Sjimharris if (!strcmp(tmp->mountpoint, "/")) 256230557Sjimharris continue; 257230557Sjimharris 258230557Sjimharris if (tmp->newfs) 259 command_shell_add(tmp->mountpoint, 260 "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name); 261 command_func_add(tmp->mountpoint, Mount, c2->name); 262 } 263 } 264 } 265 } 266 } 267 command_sort(); 268 command_execute(); 269} 270 271/* Copy the boot floppy contents into /stand */ 272static void 273copy_self(void) 274{ 275 int i; 276 277 msgNotify("Copying the boot floppy to /stand on root filesystem"); 278 i = vsystem("find -x /stand | cpio -pdmv /mnt"); 279 if (i) 280 msgConfirm("Copy returned error status of %d!", i); 281} 282 283static void 284cpio_extract(void) 285{ 286 int i, j, zpid, cpid, pfd[2]; 287 288 tryagain: 289 while (CpioFD == -1) { 290 msgConfirm("Please Insert CPIO floppy in floppy drive 0"); 291 CpioFD = open("/dev/rfd0", O_RDWR); 292 if (CpioFD >= 0) 293 break; 294 msgDebug("Error on open of cpio floppy: %s (%d)\n", strerror(errno), errno); 295 } 296 j = fork(); 297 if (!j) { 298 chdir("/"); 299 msgNotify("Extracting contents of CPIO floppy..."); 300 pipe(pfd); 301 zpid = fork(); 302 if (!zpid) { 303 dup2(CpioFD, 0); close(CpioFD); 304 dup2(pfd[1], 1); close(pfd[1]); 305 close(pfd[0]); 306 i = execl("/stand/gunzip", "/stand/gunzip", 0); 307 msgDebug("/stand/gunzip command returns %d status\n", i); 308 exit(i); 309 } 310 cpid = fork(); 311 if (!cpid) { 312 dup2(pfd[0], 0); close(pfd[0]); 313 close(CpioFD); 314 close(pfd[1]); 315 if (DebugFD != -1) { 316 dup2(DebugFD, 1); 317 dup2(DebugFD, 2); 318 } 319 else { 320 close(1); open("/dev/null", O_WRONLY); 321 dup2(1, 2); 322 } 323 i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0); 324 msgDebug("/stand/cpio command returns %d status\n", i); 325 exit(i); 326 } 327 close(pfd[0]); 328 close(pfd[1]); 329 close(CpioFD); 330 331 i = waitpid(zpid, &j, 0); 332 if (i < 0 || _WSTATUS(j)) { 333 dialog_clear(); 334 msgConfirm("gunzip returned error status of %d!", _WSTATUS(j)); 335 exit(1); 336 } 337 i = waitpid(cpid, &j, 0); 338 if (i < 0 || _WSTATUS(j)) { 339 dialog_clear(); 340 msgConfirm("cpio returned error status of %d!", _WSTATUS(j)); 341 exit(2); 342 } 343 exit(0); 344 } 345 else 346 i = wait(&j); 347 if (i < 0 || _WSTATUS(j) || access("/OK", R_OK) == -1) { 348 dialog_clear(); 349 msgConfirm("CPIO floppy did not extract properly! Please verify\nthat your media is correct and try again."); 350 close(CpioFD); 351 CpioFD = -1; 352 goto tryagain; 353 } 354 unlink("/OK"); 355} 356 357static void 358install_configuration_files(void) 359{ 360} 361 362static void 363do_final_setup(void) 364{ 365} 366