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