install.c revision 14670
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.76 1996/03/02 07:31:54 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 <ctype.h> 46#include <sys/disklabel.h> 47#include <sys/errno.h> 48#include <sys/ioctl.h> 49#include <sys/fcntl.h> 50#include <sys/wait.h> 51#include <sys/param.h> 52#define MSDOSFS 53#include <sys/mount.h> 54#undef MSDOSFS 55#include <sys/stat.h> 56#include <unistd.h> 57#include <sys/mount.h> 58 59static void create_termcap(void); 60 61#define TERMCAP_FILE "/usr/share/misc/termcap" 62 63static Boolean 64checkLabels(Chunk **rdev, Chunk **sdev, Chunk **udev) 65{ 66 Device **devs; 67 Boolean status; 68 Disk *disk; 69 Chunk *c1, *c2, *rootdev, *swapdev, *usrdev; 70 int i; 71 72 status = TRUE; 73 *rdev = *sdev = *udev = rootdev = swapdev = usrdev = NULL; 74 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 75 /* First verify that we have a root device */ 76 for (i = 0; devs[i]; i++) { 77 if (!devs[i]->enabled) 78 continue; 79 disk = (Disk *)devs[i]->private; 80 msgDebug("Scanning disk %s for root filesystem\n", disk->name); 81 if (!disk->chunks) 82 msgFatal("No chunk list found for %s!", disk->name); 83 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 84 if (c1->type == freebsd) { 85 for (c2 = c1->part; c2; c2 = c2->next) { 86 if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 87 if (c2->flags & CHUNK_IS_ROOT) { 88 if (rootdev) { 89 dialog_clear(); 90 msgConfirm("WARNING: You have more than one root device set?!\n" 91 "Using the first one found."); 92 continue; 93 } 94 rootdev = c2; 95 if (isDebug()) 96 msgDebug("Found rootdev at %s!\n", rootdev->name); 97 } 98 else if (!strcmp(((PartInfo *)c2->private)->mountpoint, "/usr")) { 99 if (usrdev) { 100 dialog_clear(); 101 msgConfirm("WARNING: You have more than one /usr filesystem.\n" 102 "Using the first one found."); 103 continue; 104 } 105 usrdev = c2; 106 if (isDebug()) 107 msgDebug("Found usrdev at %s!\n", usrdev->name); 108 } 109 } 110 } 111 } 112 } 113 } 114 115 swapdev = NULL; 116 /* Now check for swap devices */ 117 for (i = 0; devs[i]; i++) { 118 if (!devs[i]->enabled) 119 continue; 120 disk = (Disk *)devs[i]->private; 121 msgDebug("Scanning disk %s for swap partitions\n", disk->name); 122 if (!disk->chunks) 123 msgFatal("No chunk list found for %s!", disk->name); 124 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 125 if (c1->type == freebsd) { 126 for (c2 = c1->part; c2; c2 = c2->next) { 127 if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) { 128 swapdev = c2; 129 if (isDebug()) 130 msgDebug("Found swapdev at %s!\n", swapdev->name); 131 break; 132 } 133 } 134 } 135 } 136 } 137 138 *rdev = rootdev; 139 if (!rootdev) { 140 dialog_clear(); 141 msgConfirm("No root device found - you must label a partition as /\n" 142 "in the label editor."); 143 status = FALSE; 144 } 145 146 *sdev = swapdev; 147 if (!swapdev) { 148 dialog_clear(); 149 msgConfirm("No swap devices found - you must create at least one\n" 150 "swap partition."); 151 status = FALSE; 152 } 153 154 *udev = usrdev; 155 if (!usrdev) { 156 dialog_clear(); 157 msgConfirm("WARNING: No /usr filesystem found. This is not technically\n" 158 "an error if your root filesystem is big enough (or you later\n" 159 "intend to mount your /usr filesystem over NFS), but it may otherwise\n" 160 "cause you trouble if you're not exactly sure what you are doing!"); 161 } 162 return status; 163} 164 165static int 166installInitial(void) 167{ 168 static Boolean alreadyDone = FALSE; 169 170 if (alreadyDone) 171 return RET_SUCCESS; 172 173 if (!variable_get(DISK_LABELLED)) { 174 dialog_clear(); 175 msgConfirm("You need to assign disk labels before you can proceed with\nthe installation."); 176 return RET_FAIL; 177 } 178 /* If it's labelled, assume it's also partitioned */ 179 if (!variable_get(DISK_PARTITIONED)) 180 variable_set2(DISK_PARTITIONED, "yes"); 181 182 /* If we refuse to proceed, bail. */ 183 dialog_clear(); 184 if (msgYesNo("Last Chance! Are you SURE you want continue the installation?\n\n" 185 "If you're running this on a disk with data you wish to save\n" 186 "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n" 187 "proceeding!\n\n" 188 "We can take no responsibility for lost disk contents!")) 189 return RET_FAIL; 190 191 if (diskLabelCommit(NULL) != RET_SUCCESS) { 192 dialog_clear(); 193 msgConfirm("Couldn't make filesystems properly. Aborting."); 194 return RET_FAIL; 195 } 196 197 if (!copySelf()) { 198 dialog_clear(); 199 msgConfirm("Couldn't clone the boot floppy onto the root file system.\n" 200 "Aborting."); 201 return RET_FAIL; 202 } 203 204 dialog_clear(); 205 /* stick a helpful shell over on the 4th VTY */ 206 systemCreateHoloshell(); 207 208 if (chroot("/mnt") == -1) { 209 dialog_clear(); 210 msgConfirm("Unable to chroot to /mnt - this is bad!"); 211 return RET_FAIL; 212 } 213 214 chdir("/"); 215 variable_set2(RUNNING_ON_ROOT, "yes"); 216 217 alreadyDone = TRUE; 218 return RET_SUCCESS; 219} 220 221int 222installFixit(char *str) 223{ 224 struct ufs_args args; 225 pid_t child; 226 int waitstatus; 227 228 memset(&args, 0, sizeof(args)); 229 args.fspec = "/dev/fd0"; 230 Mkdir("/mnt2", NULL); 231 232 while (1) { 233 dialog_clear(); 234 msgConfirm("Please insert a writable fixit floppy and press return"); 235 if (mount(MOUNT_UFS, "/mnt2", 0, (caddr_t)&args) != -1) 236 break; 237 dialog_clear(); 238 if (msgYesNo("Unable to mount the fixit floppy - do you want to try again?")) 239 return RET_FAIL; 240 } 241 dialog_clear(); 242 dialog_update(); 243 end_dialog(); 244 DialogActive = FALSE; 245 if (!directory_exists("/tmp")) 246 (void)symlink("/mnt2/tmp", "/tmp"); 247 if (!directory_exists("/var/tmp/vi.recover")) { 248 if (Mkdir("/var/tmp/vi.recover", NULL) != RET_SUCCESS) { 249 dialog_clear(); 250 msgConfirm("Warning: Was unable to create a /var/tmp/vi.recover directory.\n" 251 "vi will kvetch and moan about it as a result but should still\n" 252 "be essentially usable."); 253 } 254 } 255 /* Link the spwd.db file */ 256 if (Mkdir("/etc", NULL) != RET_SUCCESS) { 257 dialog_clear(); 258 msgConfirm("Unable to create an /etc directory! Things are weird on this floppy.."); 259 } 260 else { 261 if (symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1) { 262 dialog_clear(); 263 msgConfirm("Couldn't symlink the /etc/spwd.db file! I'm not sure I like this.."); 264 } 265 } 266 if (!file_readable(TERMCAP_FILE)) 267 create_termcap(); 268 if (!(child = fork())) { 269 struct termios foo; 270 271 signal(SIGTTOU, SIG_IGN); 272 if (tcgetattr(0, &foo) != -1) { 273 foo.c_cc[VERASE] = '\010'; 274 if (tcsetattr(0, TCSANOW, &foo) == -1) 275 msgDebug("fixit shell: Unable to set erase character.\n"); 276 } 277 else 278 msgDebug("fixit shell: Unable to get terminal attributes!\n"); 279 printf("When you're finished with this shell, please type exit.\n"); 280 printf("The fixit floppy itself is mounted as /mnt2\n"); 281 setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:/mnt2/stand", 1); 282 execlp("sh", "-sh", 0); 283 msgDebug("fixit shell: Failed to execute shell!\n"); 284 return -1; 285 } 286 else 287 (void)waitpid(child, &waitstatus, 0); 288 289 DialogActive = TRUE; 290 clear(); 291 dialog_clear(); 292 dialog_update(); 293 unmount("/mnt2", MNT_FORCE); 294 dialog_clear(); 295 msgConfirm("Please remove the fixit floppy now."); 296 return RET_SUCCESS; 297} 298 299int 300installExpress(char *str) 301{ 302 if (diskPartitionEditor("express") == RET_FAIL) 303 return RET_FAIL; 304 305 if (diskLabelEditor("express") == RET_FAIL) 306 return RET_FAIL; 307 308 if (!Dists) { 309 if (!dmenuOpenSimple(&MenuDistributions)) 310 return RET_FAIL; 311 } 312 313 if (!mediaDevice) { 314 if (!dmenuOpenSimple(&MenuMedia) || !mediaDevice) 315 return RET_FAIL; 316 } 317 318 if (installCommit("express") == RET_FAIL) 319 return RET_FAIL; 320 321 return RET_DONE; 322} 323 324/* Novice mode installation */ 325int 326installNovice(char *str) 327{ 328 dialog_clear(); 329 msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n" 330 "scheme for your hard disk. If you simply wish to devote all disk space\n" 331 "to FreeBSD (overwritting anything else that might be on the disk(s) selected)\n" 332 "then use the (A)ll command to select the default partitioning scheme followed\n" 333 "by a (Q)uit. If you wish to allocate only free space to FreeBSD, move to a\n" 334 "partition marked \"unused\" and use the (C)reate command."); 335 336 if (diskPartitionEditor("novice") == RET_FAIL) 337 return RET_FAIL; 338 339 dialog_clear(); 340 msgConfirm("Next, you need to create BSD partitions inside of the fdisk partition(s)\n" 341 "just created. If you have a reasonable amount of disk space (200MB or more)\n" 342 "and don't have any special requirements, simply use the (A)uto command to\n" 343 "allocate space automatically. If you have more specific needs or just don't\n" 344 "care for the layout chosen by (A)uto, press F1 for more information on\n" 345 "manual layout."); 346 347 if (diskLabelEditor("novice") == RET_FAIL) 348 return RET_FAIL; 349 350 dialog_clear(); 351 msgConfirm("Now it is time to select an installation subset. There are a number of\n" 352 "canned distribution sets, ranging from minimal installation sets to full\n" 353 "X11 developer oriented configurations. You can also select a custom set\n" 354 "of distributions if none of the provided ones are suitable."); 355 while (1) { 356 if (!dmenuOpenSimple(&MenuDistributions)) 357 return RET_FAIL; 358 359 if (Dists || !msgYesNo("No distributions selected. Are you sure you wish to continue?")) 360 break; 361 } 362 363 if (!mediaDevice) { 364 dialog_clear(); 365 msgConfirm("Finally, you must specify an installation medium."); 366 if (!dmenuOpenSimple(&MenuMedia) || !mediaDevice) 367 return RET_FAIL; 368 } 369 370 if (installCommit("novice") == RET_FAIL) 371 return RET_FAIL; 372 373 return RET_DONE; 374} 375 376/* 377 * What happens when we select "Commit" in the custom installation menu. 378 * 379 * This is broken into multiple stages so that the user can do a full installation but come back here 380 * again to load more distributions, perhaps from a different media type. This would allow, for 381 * example, the user to load the majority of the system from CDROM and then use ftp to load just the 382 * DES dist. 383 */ 384int 385installCommit(char *str) 386{ 387 int i; 388 extern int cdromMounted; 389 390 if (!mediaVerify()) 391 return RET_FAIL; 392 393 i = RET_DONE; 394 if (RunningAsInit) { 395 if (installInitial() == RET_FAIL) 396 return RET_FAIL; 397 if (configFstab() == RET_FAIL) 398 return RET_FAIL; 399 if (!rootExtract()) { 400 dialog_clear(); 401 msgConfirm("Failed to load the ROOT distribution. Please correct\n" 402 "this problem and try again."); 403 return RET_FAIL; 404 } 405 } 406 407 if (distExtractAll(NULL) == RET_FAIL) 408 i = RET_FAIL; 409 410 if (installFixup(NULL) == RET_FAIL) 411 i = RET_FAIL; 412 413 if (i != RET_FAIL) 414 variable_set2(SYSTEM_STATE, "base-install"); 415 416 if (i != RET_FAIL && !strcmp(str, "novice")) { 417 dialog_clear(); 418 msgConfirm("Since you're running the novice installation, a few post-configuration\n" 419 "questions will be asked at this point. For any option you do not wish\n" 420 "to configure, select Cancel."); 421 422 if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) { 423 dialog_clear(); 424 if (!msgYesNo("Would you like to configure this machine's network interfaces?")) { 425 Device *save = mediaDevice; 426 427 /* This will also set the media device, which we don't want */ 428 tcpDeviceSelect(); 429 mediaDevice = save; 430 } 431 } 432 433 dialog_clear(); 434 if (!msgYesNo("Would you like to configure Samba for connecting NETBUI clients to this\n" 435 "machine? Windows 95, Windows NT and Windows for Workgroups\n" 436 "machines can use NETBUI transport for disk and printer sharing.")) 437 configSamba(NULL); 438 439 dialog_clear(); 440 if (!msgYesNo("Will this machine be an IP gateway (e.g. will it forward packets\n" 441 "between interfaces)?")) 442 variable_set2("gateway", "YES"); 443 444 dialog_clear(); 445 if (!msgYesNo("Do you want to allow anonymous FTP connections to this machine?")) 446 configAnonFTP(NULL); 447 448 dialog_clear(); 449 if (!msgYesNo("Do you want to configure this machine as an NFS server?")) 450 configNFSServer(NULL); 451 452 dialog_clear(); 453 if (!msgYesNo("Do you want to configure this machine as an NFS client?")) 454 variable_set2("nfs_client", "YES"); 455 456 dialog_clear(); 457 if (!msgYesNo("Do you want to configure this machine as a WEB server?")) 458 configApache(NULL); 459 460 dialog_clear(); 461 if (!msgYesNo("Would you like to customize your system console settings?")) 462 dmenuOpenSimple(&MenuSyscons); 463 464 dialog_clear(); 465 if (!msgYesNo("Would you like to set this machine's time zone now?")) 466 systemExecute("rm -f /etc/wall_cmos_clock /etc/localtime; tzsetup"); 467 468 dialog_clear(); 469 if (!msgYesNo("Does this system have a mouse attached to it?")) 470 dmenuOpenSimple(&MenuMouse); 471 472 if (directory_exists("/usr/X11R6")) { 473 dialog_clear(); 474 if (!msgYesNo("Would you like to configure your X server at this time?")) 475 systemExecute("/usr/X11R6/bin/xf86config"); 476 } 477 478 if (cdromMounted) { 479 dialog_clear(); 480 if (!msgYesNo("Would you like to link to the ports tree on your CDROM?\n\n" 481 "This will require that you have your FreeBSD CD in the CDROM\n" 482 "drive to use the ports collection, but at a substantial savings\n" 483 "in disk space (NOTE: This may take as long as 15 or 20 minutes\n" 484 "depending on the speed of your CDROM drive).")) 485 configPorts(NULL); 486 } 487 488 dialog_clear(); 489 if (!msgYesNo("The FreeBSD package collection is a collection of over 300 ready-to-run\n" 490 "applications, from text editors to games to WEB servers. Would you like\n" 491 "to browse the collection now?")) 492 configPackages(NULL); 493 494 /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */ 495 496 } 497 498 /* Final menu of last resort */ 499 dialog_clear(); 500 if (!msgYesNo("Would you like to go to the general configuration menu for a chance to set\n" 501 "any last configuration options?")) 502 dmenuOpenSimple(&MenuConfigure); 503 504 /* Write out any changes .. */ 505 configResolv(); 506 configSysconfig(); 507 508 variable_set2(SYSTEM_STATE, i == RET_FAIL ? "error-install" : "full-install"); 509 510 /* Don't print this if we're express or novice installing */ 511 if (strcmp(str, "express") && strcmp(str, "novice")) { 512 if (Dists || i == RET_FAIL) { 513 dialog_clear(); 514 msgConfirm("Installation completed with some errors. You may wish to\n" 515 "scroll through the debugging messages on VTY1 with the\n" 516 "scroll-lock feature."); 517 } 518 else { 519 dialog_clear(); 520 msgConfirm("Installation completed successfully.\n\n" 521 "If you have any network devices you have not yet configured,\n" 522 "see the Interfaces configuration item on the Configuration menu."); 523 } 524 } 525 else if (!strcmp(str, "novice")) { 526 if (Dists || i == RET_FAIL) { 527 dialog_clear(); 528 msgConfirm("Installation completed with some errors. You may wish to\n" 529 "scroll through the debugging messages on VTY1 with the\n" 530 "scroll-lock feature. You can also chose \"No\" at the next\n" 531 "prompt and go back into the installation menus to try and retry\n" 532 "whichever operations have failed."); 533 } 534 else { 535 dialog_clear(); 536 msgConfirm("Congradulations! You now have FreeBSD installed on your system.\n" 537 "At this stage, there shouldn't be much left to do from this\n" 538 "installation utility so if you wish to come up from the hard disk\n" 539 "now, simply select \"Yes\" at the next prompt to reboot.\n" 540 "If you wish to re-enter this utility after the system is up, you\n" 541 "may do so by typing: /stand/sysinstall."); 542 } 543 } 544 return i; 545} 546 547int 548installFixup(char *str) 549{ 550 Device **devs; 551 int i; 552 553 if (!file_readable("/kernel")) { 554 if (file_readable("/kernel.GENERIC")) { 555 if (vsystem("cp -p /kernel.GENERIC /kernel")) { 556 dialog_clear(); 557 msgConfirm("Unable to link /kernel into place!"); 558 return RET_FAIL; 559 } 560 } 561 else { 562 dialog_clear(); 563 msgConfirm("Can't find a kernel image to link to on the root file system!\n" 564 "You're going to have a hard time getting this system to\n" 565 "boot from the hard disk, I'm afraid!"); 566 return RET_FAIL; 567 } 568 } 569 /* Resurrect /dev after bin distribution screws it up */ 570 if (RunningAsInit) { 571 msgNotify("Remaking all devices.. Please wait!"); 572 if (vsystem("cd /dev; sh MAKEDEV all")) { 573 dialog_clear(); 574 msgConfirm("MAKEDEV returned non-zero status"); 575 return RET_FAIL; 576 } 577 578 msgNotify("Resurrecting /dev entries for slices.."); 579 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 580 if (!devs) 581 msgFatal("Couldn't get a disk device list!"); 582 583 /* Resurrect the slices that the former clobbered */ 584 for (i = 0; devs[i]; i++) { 585 Disk *disk = (Disk *)devs[i]->private; 586 Chunk *c1; 587 588 if (!devs[i]->enabled) 589 continue; 590 if (!disk->chunks) 591 msgFatal("No chunk list found for %s!", disk->name); 592 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 593 if (c1->type == freebsd) { 594 msgNotify("Making slice entries for %s", c1->name); 595 if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) { 596 dialog_clear(); 597 msgConfirm("Unable to make slice entries for %s!", c1->name); 598 return RET_FAIL; 599 } 600 } 601 } 602 } 603 /* XXX Do all the last ugly work-arounds here which we'll try and excise someday right?? XXX */ 604 605 msgNotify("Fixing permissions.."); 606 /* BOGON #1: XFree86 extracting /usr/X11R6 with root-only perms */ 607 if (directory_exists("/usr/X11R6")) { 608 system("chmod -R a+r /usr/X11R6"); 609 system("find /usr/X11R6 -type d | xargs chmod a+x"); 610 } 611 /* BOGON #2: We leave /etc in a bad state */ 612 chmod("/etc", 0755); 613 614 /* BOGON #3: No /var/db/mountdtab complains */ 615 Mkdir("/var/db", NULL); 616 creat("/var/db/mountdtab", 0644); 617 618 /* Now run all the mtree stuff to fix things up */ 619 vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /"); 620 vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var"); 621 vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr"); 622 } 623 return RET_SUCCESS; 624} 625 626/* Go newfs and/or mount all the filesystems we've been asked to */ 627int 628installFilesystems(char *str) 629{ 630 int i; 631 Disk *disk; 632 Chunk *c1, *c2, *rootdev, *swapdev, *usrdev; 633 Device **devs; 634 PartInfo *root; 635 char dname[80]; 636 extern int MakeDevChunk(Chunk *c, char *n); 637 Boolean upgrade = FALSE; 638 639 if (!(str && !strcmp(str, "script")) && !checkLabels(&rootdev, &swapdev, &usrdev)) 640 return RET_FAIL; 641 642 root = (PartInfo *)rootdev->private; 643 command_clear(); 644 upgrade = str && !strcmp(str, "upgrade"); 645 646 /* As the very first thing, try to get ourselves some swap space */ 647 sprintf(dname, "/dev/%s", swapdev->name); 648 if (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname)) { 649 dialog_clear(); 650 msgConfirm("Unable to make device node for %s in /dev!\n" 651 "The creation of filesystems will be aborted.", dname); 652 return RET_FAIL; 653 } 654 if (!swapon(dname)) 655 msgNotify("Added %s as initial swap device", dname); 656 else 657 msgConfirm("WARNING! Unable to swap to %s: %s\n" 658 "This may cause the installation to fail at some point\n" 659 "if you don't have a lot of memory.", dname, strerror(errno)); 660 661 /* Next, create and/or mount the root device */ 662 sprintf(dname, "/dev/r%sa", rootdev->disk->name); 663 if (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname)) { 664 dialog_clear(); 665 msgConfirm("Unable to make device node for %s in /dev!\n" 666 "The creation of filesystems will be aborted.", dname); 667 return RET_FAIL; 668 } 669 670 if (strcmp(root->mountpoint, "/")) { 671 dialog_clear(); 672 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint); 673 } 674 675 if (root->newfs) { 676 int i; 677 678 msgNotify("Making a new root filesystem on %s", dname); 679 i = vsystem("%s %s", root->newfs_cmd, dname); 680 if (i) { 681 dialog_clear(); 682 msgConfirm("Unable to make new root filesystem on %s!\n" 683 "Command returned status %d", dname, i); 684 return RET_FAIL; 685 } 686 } 687 else { 688 if (!upgrade) { 689 dialog_clear(); 690 msgConfirm("Warning: Root device is selected read-only. It will be assumed\n" 691 "that you have the appropriate device entries already in /dev."); 692 } 693 msgNotify("Checking integrity of existing %s filesystem.", dname); 694 i = vsystem("fsck -y %s", dname); 695 if (i) { 696 dialog_clear(); 697 msgConfirm("Warning: fsck returned status of %d for %s.\n" 698 "This partition may be unsafe to use.", i, dname); 699 } 700 } 701 /* Switch to block device */ 702 sprintf(dname, "/dev/%sa", rootdev->disk->name); 703 if (Mount("/mnt", dname)) { 704 dialog_clear(); 705 msgConfirm("Unable to mount the root file system on %s! Giving up.", dname); 706 return RET_FAIL; 707 } 708 709 /* Now buzz through the rest of the partitions and mount them too */ 710 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 711 for (i = 0; devs[i]; i++) { 712 if (!devs[i]->enabled) 713 continue; 714 715 disk = (Disk *)devs[i]->private; 716 if (!disk->chunks) { 717 dialog_clear(); 718 msgConfirm("No chunk list found for %s!", disk->name); 719 return RET_FAIL; 720 } 721 if (root->newfs || upgrade) { 722 Mkdir("/mnt/dev", NULL); 723 MakeDevDisk(disk, "/mnt/dev"); 724 } 725 726 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 727 if (c1->type == freebsd) { 728 for (c2 = c1->part; c2; c2 = c2->next) { 729 if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 730 PartInfo *tmp = (PartInfo *)c2->private; 731 732 /* Already did root */ 733 if (c2 == rootdev) 734 continue; 735 736 if (tmp->newfs) 737 command_shell_add(tmp->mountpoint, "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name); 738 else 739 command_shell_add(tmp->mountpoint, "fsck -y /mnt/dev/r%s", c2->name); 740 command_func_add(tmp->mountpoint, Mount, c2->name); 741 } 742 else if (c2->type == part && c2->subtype == FS_SWAP) { 743 char fname[80]; 744 int i; 745 746 if (c2 == swapdev) 747 continue; 748 sprintf(fname, "/mnt/dev/%s", c2->name); 749 i = swapon(fname); 750 if (!i) 751 msgNotify("Added %s as an additional swap device", fname); 752 else { 753 dialog_clear(); 754 msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); 755 } 756 } 757 } 758 } 759 else if (c1->type == fat && c1->private && (root->newfs || upgrade)) { 760 char name[FILENAME_MAX]; 761 762 sprintf(name, "/mnt%s", ((PartInfo *)c1->private)->mountpoint); 763 Mkdir(name, NULL); 764 } 765 } 766 } 767 768 msgNotify("Copying initial device files.."); 769 /* Copy the boot floppy's dev files */ 770 if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio -pdumv /mnt")) { 771 dialog_clear(); 772 msgConfirm("Couldn't clone the /dev files!"); 773 return RET_FAIL; 774 } 775 776 command_sort(); 777 command_execute(); 778 return RET_SUCCESS; 779} 780 781int 782installVarDefaults(char *unused) 783{ 784 /* Set default startup options */ 785 variable_set2(VAR_ROUTEDFLAGS, "-q"); 786 variable_set2(VAR_RELNAME, RELEASE_NAME); 787 variable_set2(VAR_CPIO_VERBOSITY, "high"); 788 variable_set2(VAR_TAPE_BLOCKSIZE, DEFAULT_TAPE_BLOCKSIZE); 789 variable_set2(VAR_FTP_USER, "ftp"); 790 variable_set2(VAR_BROWSER_PACKAGE, "lynx-2.4.2"); 791 variable_set2(VAR_BROWSER_BINARY, "/usr/local/bin/lynx"); 792 variable_set2(VAR_CONFIG_FILE, "freebsd.cfg"); 793 variable_set2(VAR_FTP_STATE, "passive"); 794 variable_set2(VAR_FTP_ONERROR, "abort"); 795 variable_set2(VAR_FTP_RETRIES, MAX_FTP_RETRIES); 796 if (getpid() != 1) 797 variable_set2(SYSTEM_STATE, "update"); 798 else 799 variable_set2(SYSTEM_STATE, "init"); 800 return RET_SUCCESS; 801} 802 803/* Copy the boot floppy contents into /stand */ 804Boolean 805copySelf(void) 806{ 807 int i; 808 809 msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem"); 810 i = vsystem("find -x /stand | cpio -pdumv /mnt"); 811 if (i) { 812 dialog_clear(); 813 msgConfirm("Copy returned error status of %d!", i); 814 return FALSE; 815 } 816 817 /* Copy the /etc files into their rightful place */ 818 if (vsystem("cd /mnt/stand; find etc | cpio -pdumv /mnt")) { 819 dialog_clear(); 820 msgConfirm("Couldn't copy up the /etc files!"); 821 return TRUE; 822 } 823 return TRUE; 824} 825 826static Boolean loop_on_root_floppy(void); 827 828Boolean 829rootExtract(void) 830{ 831 int fd; 832 static Boolean alreadyExtracted = FALSE; 833 834 if (alreadyExtracted) 835 return TRUE; 836 837 if (mediaDevice) { 838 if (isDebug()) 839 msgDebug("Attempting to extract root image from %s\n", mediaDevice->name); 840 switch(mediaDevice->type) { 841 842 case DEVICE_TYPE_FLOPPY: 843 alreadyExtracted = loop_on_root_floppy(); 844 break; 845 846 default: 847 if (!mediaDevice->init(mediaDevice)) 848 break; 849 fd = mediaDevice->get(mediaDevice, "floppies/root.flp", FALSE); 850 if (fd < 0) { 851 dialog_clear(); 852 msgConfirm("Couldn't get root image from %s!\n" 853 "Will try to get it from floppy.", mediaDevice->name); 854 mediaDevice->shutdown(mediaDevice); 855 alreadyExtracted = loop_on_root_floppy(); 856 } 857 else { 858 msgNotify("Loading root image from:\n%s", mediaDevice->name); 859 alreadyExtracted = mediaExtractDist("/", fd); 860 mediaDevice->close(mediaDevice, fd); 861 } 862 break; 863 } 864 } 865 else 866 alreadyExtracted = loop_on_root_floppy(); 867 return alreadyExtracted; 868} 869 870static Boolean 871loop_on_root_floppy(void) 872{ 873 int fd; 874 int status = FALSE; 875 876 while (1) { 877 fd = getRootFloppy(); 878 if (fd != -1) { 879 msgNotify("Extracting root floppy.."); 880 status = mediaExtractDist("/", fd); 881 close(fd); 882 break; 883 } 884 } 885 return status; 886} 887 888static void 889create_termcap(void) 890{ 891 FILE *fp; 892 893 const char *caps[] = { 894 termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r, 895 termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m, NULL, 896 }; 897 const char **cp; 898 899 if (!file_readable(TERMCAP_FILE)) { 900 Mkdir("/usr/share/misc", NULL); 901 fp = fopen(TERMCAP_FILE, "w"); 902 if (!fp) { 903 dialog_clear(); 904 msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work."); 905 return; 906 } 907 cp = caps; 908 while (*cp) 909 fprintf(fp, "%s\n", *(cp++)); 910 fclose(fp); 911 } 912} 913 914