install.c revision 8643
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.34 1995/05/20 10:33:03 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 <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 Boolean 60preInstallCheck(void) 61{ 62 if (!getenv(DISK_PARTITIONED)) { 63 msgConfirm("You need to partition your disk before you can proceed with\nthe installation."); 64 65 return FALSE; 66 } 67 if (!getenv(DISK_LABELLED)) { 68 msgConfirm("You need to assign disk labels before you can proceed with\nthe installation."); 69 return FALSE; 70 } 71 if (!Dists) { 72 msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu."); 73 return FALSE; 74 } 75 return TRUE; 76} 77 78static void 79installInitial(void) 80{ 81 extern u_char boot1[], boot2[]; 82 extern u_char mbr[], bteasy17[]; 83 u_char *mbrContents; 84 Device **devs; 85 int i; 86 static Boolean alreadyDone = FALSE; 87 88 if (alreadyDone) 89 return; 90 91 /* If things aren't kosher, or we refuse to proceed, bail. */ 92 if (!preInstallCheck() 93 || 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!")) 94 return; 95 96 mbrContents = NULL; 97 if (!msgYesNo("Would you like to install a boot manager?\n\nThis will allow you to easily select between other operating systems\non the first disk, or boot from a disk other than the first.")) 98 mbrContents = bteasy17; 99 else if (!msgYesNo("Would you like to remove an existing boot manager?")) 100 mbrContents = mbr; 101 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 102 for (i = 0; devs[i]; i++) { 103 Disk *d = (Disk *)devs[i]->private; 104 Chunk *c1; 105 106 if (!devs[i]->enabled) 107 continue; 108 109 if (mbrContents) { 110 Set_Boot_Mgr(d, mbrContents); 111 mbrContents = NULL; 112 } 113 Set_Boot_Blocks(d, boot1, boot2); 114 msgNotify("Writing partition information to drive %s", d->name); 115 Write_Disk(d); 116 117 /* Now scan for bad blocks, if necessary */ 118 for (c1 = d->chunks->part; c1; c1 = c1->next) { 119 if (c1->flags & CHUNK_BAD144) { 120 int ret; 121 122 msgNotify("Running bad block scan on partition %s", c1->name); 123 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 124 if (ret) 125 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 126 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 127 if (ret) 128 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 129 } 130 } 131 } 132 make_filesystems(); 133 copy_self(); 134 cpio_extract(); 135 alreadyDone = TRUE; 136} 137 138static void 139installFinal(void) 140{ 141 static Boolean alreadyDone = FALSE; 142 143 if (alreadyDone) 144 return; 145 install_configuration_files(); 146 do_final_setup(); 147 alreadyDone = TRUE; 148} 149 150int 151installCommit(char *str) 152{ 153 installInitial(); 154 if (!mediaVerify()) 155 return 0; 156 distExtractAll(); 157 installFinal(); 158 return 0; 159} 160 161/* Go newfs and/or mount all the filesystems we've been asked to */ 162static void 163make_filesystems(void) 164{ 165 int i; 166 Disk *disk; 167 Chunk *c1, *c2; 168 Device **devs; 169 170 command_clear(); 171 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 172 173 /* First look for the root device and mount it */ 174 for (i = 0; devs[i]; i++) { 175 disk = (Disk *)devs[i]->private; 176 msgDebug("Scanning disk %s for root filesystem\n", disk->name); 177 if (!disk->chunks) 178 msgFatal("No chunk list found for %s!", disk->name); 179 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 180 if (c1->type == freebsd) { 181 for (c2 = c1->part; c2; c2 = c2->next) { 182 if (c2->type == part && c2->subtype != FS_SWAP && 183 c2->private && c2->flags & CHUNK_IS_ROOT) { 184 char dname[40]; 185 PartInfo *p = (PartInfo *)c2->private; 186 187 if (strcmp(p->mountpoint, "/")) { 188 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint); 189 continue; 190 } 191 if (p->newfs) { 192 int i; 193 194 sprintf(dname, "/dev/r%sa", disk->name); 195 msgNotify("Making a new root filesystem on %s", dname); 196 i = vsystem("newfs %s", dname); 197 if (i) { 198 msgConfirm("Unable to make new root filesystem! Command returned status %d", i); 199 return; 200 } 201 } 202 else 203 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."); 204 sprintf(dname, "/dev/%sa", disk->name); 205 if (Mount("/mnt", dname)) { 206 msgConfirm("Unable to mount the root file system! Giving up."); 207 return; 208 } 209 else { 210 extern int makedevs(void); 211 212 msgNotify("Making device files"); 213 if (Mkdir("/mnt/dev", NULL) 214 || chdir("/mnt/dev") 215 || makedevs()) 216 msgConfirm("Failed to make some of the devices in /mnt!"); 217 if (Mkdir("/mnt/stand", NULL)) 218 msgConfirm("Unable to make /mnt/stand directory!"); 219 chdir("/"); 220 break; 221 } 222 } 223 } 224 } 225 } 226 } 227 228 /* Now buzz through the rest of the partitions and mount them too */ 229 for (i = 0; devs[i]; i++) { 230 disk = (Disk *)devs[i]->private; 231 if (!disk->chunks) 232 msgFatal("No chunk list found for %s!", disk->name); 233 234 /* Make the proper device mount points in /mnt/dev */ 235 MakeDevDisk(disk, "/mnt/dev"); 236 237 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 238 if (c1->type == freebsd) { 239 for (c2 = c1->part; c2; c2 = c2->next) { 240 if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 241 PartInfo *tmp = (PartInfo *)c2->private; 242 243 if (!strcmp(tmp->mountpoint, "/")) 244 continue; 245 246 if (tmp->newfs) 247 command_shell_add(tmp->mountpoint, 248 "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name); 249 command_func_add(tmp->mountpoint, Mount, c2->name); 250 } 251 } 252 } 253 } 254 } 255 command_sort(); 256 command_execute(); 257} 258 259/* Copy the boot floppy contents into /stand */ 260static void 261copy_self(void) 262{ 263 int i; 264 265 msgNotify("Copying the boot floppy to /stand on root filesystem"); 266 chdir("/"); 267 i = vsystem("find -x . | cpio -pdmv /mnt/stand"); 268 if (i) 269 msgConfirm("Copy returned error status of %d!", i); 270} 271 272static void 273cpio_extract(void) 274{ 275 int i, j, zpid, cpid, pfd[2]; 276 277 tryagain: 278 j = fork(); 279 if (!j) { 280 while (CpioFD == -1) { 281 msgConfirm("Please Insert CPIO floppy in floppy drive 0"); 282 CpioFD = open("/dev/rfd0", O_RDONLY); 283 } 284 chroot("/mnt"); chdir("/"); 285 msgNotify("Extracting contents of CPIO floppy..."); 286 pipe(pfd); 287 zpid = fork(); 288 if (!zpid) { 289 dup2(CpioFD, 0); close(CpioFD); 290 dup2(pfd[1], 1); close(pfd[1]); 291 close(pfd[0]); 292 i = execl("/stand/gunzip", "/stand/gunzip", 0); 293 msgDebug("/stand/gunzip command returns %d status\n", i); 294 exit(i); 295 } 296 cpid = fork(); 297 if (!cpid) { 298 dup2(pfd[0], 0); close(pfd[0]); 299 close(CpioFD); 300 close(pfd[1]); 301 if (DebugFD != -1) { 302 dup2(DebugFD, 1); 303 dup2(DebugFD, 2); 304 } 305 else { 306 close(1); open("/dev/null", O_WRONLY); 307 dup2(1, 2); 308 } 309 i = execl("/stand/cpio", "/stand/cpio", "-iduvm", 0); 310 msgDebug("/stand/cpio command returns %d status\n", i); 311 exit(i); 312 } 313 close(pfd[0]); 314 close(pfd[1]); 315 close(CpioFD); 316 317 i = waitpid(zpid, &j, 0); 318 if (i < 0 || j) { 319 msgConfirm("gunzip returned status of %d, error was: %s (%d)! Help!", j, strerror(errno), errno); 320 exit(1); 321 } 322 i = waitpid(cpid, &j, 0); 323 if (i < 0 || j) { 324 msgConfirm("cpio returned status of %d, error was: %s (%d)! Help!", j, strerror(errno), errno); 325 exit(2); 326 } 327 exit(0); 328 } 329 else 330 i = wait(&j); 331 if (i < 0 || j || access("/mnt/OK", R_OK) == -1) { 332 msgConfirm("CPIO floppy did not extract properly! Please verify\n\that your media is correct and try again"); 333 goto tryagain; 334 } 335 unlink("/mnt/OK"); 336} 337 338static void 339install_configuration_files(void) 340{ 341} 342 343static void 344do_final_setup(void) 345{ 346} 347