install.c revision 8702
1192836Sed/* 2192836Sed * The new sysinstall program. 3192836Sed * 4192836Sed * This is probably the last program in the `sysinstall' line - the next 5192836Sed * generation being essentially a complete rewrite. 6192836Sed * 7192836Sed * $Id: install.c,v 1.46 1995/05/21 15:40:48 jkh Exp $ 8192836Sed * 9192836Sed * Copyright (c) 1995 10192836Sed * Jordan Hubbard. All rights reserved. 11192834Sed * 12192834Sed * Redistribution and use in source and binary forms, with or without 13192834Sed * modification, are permitted provided that the following conditions 14192834Sed * are met: 15192834Sed * 1. Redistributions of source code must retain the above copyright 16192834Sed * notice, this list of conditions and the following disclaimer, 17192834Sed * verbatim and that no modifications are made prior to this 18192834Sed * point in the file. 19192834Sed * 2. Redistributions in binary form must reproduce the above copyright 20192834Sed * notice, this list of conditions and the following disclaimer in the 21192834Sed * documentation and/or other materials provided with the distribution. 22192834Sed * 3. All advertising materials mentioning features or use of this software 23192834Sed * must display the following acknowledgement: 24192834Sed * This product includes software developed by Jordan Hubbard 25192834Sed * 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 Disk *rootdisk; 60static Chunk *rootdev; 61 62static Boolean 63checkLabels(void) 64{ 65 Device **devs; 66 Disk *disk; 67 Chunk *c1, *c2, *swapdev = NULL; 68 int i; 69 70 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 71 /* First verify that we have a root device */ 72 for (i = 0; devs[i]; i++) { 73 if (!devs[i]->enabled) 74 continue; 75 disk = (Disk *)devs[i]->private; 76 msgDebug("Scanning disk %s for root filesystem\n", disk->name); 77 if (!disk->chunks) 78 msgFatal("No chunk list found for %s!", disk->name); 79 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 80 if (c1->type == freebsd) { 81 for (c2 = c1->part; c2; c2 = c2->next) { 82 if (c2->type == part && c2->subtype != FS_SWAP && 83 c2->private && c2->flags & CHUNK_IS_ROOT) { 84 rootdisk = disk; 85 rootdev = c2; 86 break; 87 } 88 } 89 } 90 } 91 } 92 93 /* Now register the swap devices */ 94 for (i = 0; devs[i]; i++) { 95 disk = (Disk *)devs[i]->private; 96 msgDebug("Scanning disk %s for swap partitions\n", disk->name); 97 if (!disk->chunks) 98 msgFatal("No chunk list found for %s!", disk->name); 99 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 100 if (c1->type == freebsd) { 101 for (c2 = c1->part; c2; c2 = c2->next) { 102 if (c2->type == part && c2->subtype == FS_SWAP) { 103 swapdev = c2; 104 break; 105 } 106 } 107 } 108 } 109 } 110 111 if (!rootdev) { 112 msgConfirm("No root device found - you must label a partition as /\n in the label editor."); 113 return FALSE; 114 } 115 if (!swapdev) { 116 msgConfirm("No swap devices found - you must create at least one\nswap partition."); 117 return FALSE; 118 } 119 return TRUE; 120} 121 122static void 123installInitial(void) 124{ 125 extern u_char boot1[], boot2[]; 126 extern u_char mbr[], bteasy17[]; 127 u_char *mbrContents; 128 Device **devs; 129 int i; 130 static Boolean alreadyDone = FALSE; 131 char *cp; 132 133 if (alreadyDone) 134 return; 135 136 if (!getenv(DISK_PARTITIONED)) { 137 msgConfirm("You need to partition your disk before you can proceed with\nthe installation."); 138 return; 139 } 140 if (!getenv(DISK_LABELLED)) { 141 msgConfirm("You need to assign disk labels before you can proceed with\nthe installation."); 142 return; 143 } 144 if (!checkLabels()) 145 return; 146 147 /* Figure out what kind of MBR the user wants */ 148 dmenuOpenSimple(&MenuMBRType); 149 mbrContents = NULL; 150 cp = getenv("bootManager"); 151 if (cp) { 152 if (!strcmp(cp, "bteasy")) 153 mbrContents = bteasy17; 154 else if (!strcmp(cp, "mbr")) 155 mbrContents = mbr; 156 } 157 158 /* If we refuse to proceed, bail. */ 159 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!")) 160 return; 161 162 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 163 for (i = 0; devs[i]; i++) { 164 Chunk *c1; 165 Disk *d = (Disk *)devs[i]->private; 166 167 if (!devs[i]->enabled) 168 continue; 169 170 if (mbrContents) { 171 Set_Boot_Mgr(d, mbrContents); 172 mbrContents = NULL; 173 } 174 Set_Boot_Blocks(d, boot1, boot2); 175 msgNotify("Writing partition information to drive %s", d->name); 176 Write_Disk(d); 177 178 /* Now scan for bad blocks, if necessary */ 179 for (c1 = d->chunks->part; c1; c1 = c1->next) { 180 if (c1->flags & CHUNK_BAD144) { 181 int ret; 182 183 msgNotify("Running bad block scan on partition %s", c1->name); 184 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 185 if (ret) 186 msgConfirm("Bad144 init on %s returned status of %d!", 187 c1->name, ret); 188 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 189 if (ret) 190 msgConfirm("Bad144 scan on %s returned status of %d!", 191 c1->name, ret); 192 } 193 } 194 } 195 make_filesystems(); 196 copy_self(); 197 dialog_clear(); 198 chroot("/mnt"); 199 chdir("/"); 200 cpio_extract(); 201 alreadyDone = TRUE; 202} 203 204static void 205installFinal(void) 206{ 207 static Boolean alreadyDone = FALSE; 208 209 if (alreadyDone) 210 return; 211 install_configuration_files(); 212 do_final_setup(); 213 alreadyDone = TRUE; 214} 215 216/* 217 * What happens when we select "GO". This is broken into a 3 stage installation so that 218 * the user can do a full installation but come back here again to load more distributions, 219 * perhaps from a different media type. This would allow, for example, the user to load the 220 * majority of the system from CDROM and then use ftp to load just the DES dist. 221 */ 222int 223installCommit(char *str) 224{ 225 if (!Dists) { 226 msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu."); 227 return 0; 228 } 229 if (!mediaVerify()) 230 return 0; 231 232 installInitial(); 233 distExtractAll(); 234 installFinal(); 235 return 0; 236} 237 238/* Go newfs and/or mount all the filesystems we've been asked to */ 239static void 240make_filesystems(void) 241{ 242 int i; 243 Disk *disk; 244 Chunk *c1, *c2; 245 Device **devs; 246 char dname[40]; 247 PartInfo *p = (PartInfo *)rootdev->private; 248 249 command_clear(); 250 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 251 252 /* First, create and mount the root device */ 253 if (strcmp(p->mountpoint, "/")) 254 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, p->mountpoint); 255 256 if (p->newfs) { 257 int i; 258 259 sprintf(dname, "/dev/r%sa", rootdisk->name); 260 msgNotify("Making a new root filesystem on %s", dname); 261 i = vsystem("%s %s", p->newfs_cmd, dname); 262 if (i) { 263 msgConfirm("Unable to make new root filesystem! Command returned status %d", i); 264 return; 265 } 266 } 267 else 268 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."); 269 sprintf(dname, "/dev/%sa", rootdisk->name); 270 if (Mount("/mnt", dname)) { 271 msgConfirm("Unable to mount the root file system! Giving up."); 272 return; 273 } 274 else { 275 extern int makedevs(void); 276 277 msgNotify("Making device files"); 278 if (Mkdir("/mnt/dev", NULL) || chdir("/mnt/dev") || makedevs()) 279 msgConfirm("Failed to make some of the devices in /mnt!"); 280 if (Mkdir("/mnt/stand", NULL)) { 281 msgConfirm("Unable to make /mnt/stand directory!"); 282 return; 283 } 284 chdir("/"); 285 } 286 287 /* Now buzz through the rest of the partitions and mount them too */ 288 for (i = 0; devs[i]; i++) { 289 disk = (Disk *)devs[i]->private; 290 if (!disk->chunks) 291 msgFatal("No chunk list found for %s!", disk->name); 292 293 /* Make the proper device mount points in /mnt/dev */ 294 MakeDevDisk(disk, "/mnt/dev"); 295 296 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 297 if (c1->type == freebsd) { 298 for (c2 = c1->part; c2; c2 = c2->next) { 299 if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 300 PartInfo *tmp = (PartInfo *)c2->private; 301 302 if (!strcmp(tmp->mountpoint, "/")) 303 continue; 304 305 if (tmp->newfs) 306 command_shell_add(tmp->mountpoint, "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name); 307 command_func_add(tmp->mountpoint, Mount, c2->name); 308 } 309 else if (c2->type == part && c2->subtype == FS_SWAP) { 310 char fname[80]; 311 int i; 312 313 sprintf(fname, "/mnt/dev/%s", c2->name); 314 i = swapon(fname); 315 if (!i) 316 msgNotify("Added %s as a swap device", fname); 317 else 318 msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); 319 } 320 } 321 } 322 } 323 } 324 command_sort(); 325 command_execute(); 326} 327 328/* Copy the boot floppy contents into /stand */ 329static void 330copy_self(void) 331{ 332 int i; 333 334 msgNotify("Copying the boot floppy to /stand on root filesystem"); 335 i = vsystem("find -x /stand | cpio -pdmv /mnt"); 336 if (i) 337 msgConfirm("Copy returned error status of %d!", i); 338} 339 340static void 341cpio_extract(void) 342{ 343 int i, j, zpid, cpid, pfd[2]; 344 345#if 0 346 if (mediaDevice && mediaDevice->type == DEVICE_TYPE_CDROM) { 347 if (mediaDevice->init) { 348 if ((*mediaDevice->init)(mediaDevice)) { 349 CpioFD = open("/cdrom/floppies/cpio.flp", O_RDONLY); 350 if (CpioFD != -1) 351 msgNotify("Loading CPIO floppy from CDROM"); 352 } 353 } 354 } 355#endif 356 tryagain: 357 while (CpioFD == -1) { 358 msgConfirm("Please Insert CPIO floppy in floppy drive 0"); 359 CpioFD = open("/dev/rfd0", O_RDONLY); 360 if (CpioFD >= 0) 361 break; 362 msgDebug("Error on open of cpio floppy: %s (%d)\n", strerror(errno), errno); 363 } 364 j = fork(); 365 if (!j) { 366 chdir("/"); 367 msgNotify("Extracting contents of CPIO floppy..."); 368 pipe(pfd); 369 zpid = fork(); 370 if (!zpid) { 371 dup2(CpioFD, 0); close(CpioFD); 372 dup2(pfd[1], 1); close(pfd[1]); 373 if (DebugFD != -1) 374 dup2(DebugFD, 2); 375 close(pfd[0]); 376 i = execl("/stand/gunzip", "/stand/gunzip", 0); 377 msgDebug("/stand/gunzip command returns %d status\n", i); 378 exit(i); 379 } 380 cpid = fork(); 381 if (!cpid) { 382 dup2(pfd[0], 0); close(pfd[0]); 383 close(CpioFD); 384 close(pfd[1]); 385 if (DebugFD != -1) { 386 dup2(DebugFD, 1); 387 dup2(DebugFD, 2); 388 } 389 else { 390 close(1); open("/dev/null", O_WRONLY); 391 dup2(1, 2); 392 } 393 i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0); 394 msgDebug("/stand/cpio command returns %d status\n", i); 395 exit(i); 396 } 397 close(pfd[0]); 398 close(pfd[1]); 399 close(CpioFD); 400 401 i = waitpid(zpid, &j, 0); 402 if (i < 0 || _WSTATUS(j)) { 403 dialog_clear(); 404 msgConfirm("gunzip returned error status of %d!", _WSTATUS(j)); 405 exit(1); 406 } 407 i = waitpid(cpid, &j, 0); 408 if (i < 0 || _WSTATUS(j)) { 409 dialog_clear(); 410 msgConfirm("cpio returned error status of %d!", _WSTATUS(j)); 411 exit(2); 412 } 413 exit(0); 414 } 415 else 416 i = wait(&j); 417 if (i < 0 || _WSTATUS(j) || access("/OK", R_OK) == -1) { 418 dialog_clear(); 419 msgConfirm("CPIO floppy did not extract properly! Please verify\nthat your media is correct and try again."); 420 close(CpioFD); 421 CpioFD = -1; 422 goto tryagain; 423 } 424 unlink("/OK"); 425} 426 427static void 428install_configuration_files(void) 429{ 430} 431 432static void 433do_final_setup(void) 434{ 435} 436