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