install.c revision 8640
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.32 1995/05/20 00:13:10 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 <unistd.h> 49 50Boolean SystemWasInstalled; 51 52static void make_filesystems(void); 53static void copy_self(void); 54static void cpio_extract(void); 55static void install_configuration_files(void); 56static void do_final_setup(void); 57 58static Boolean 59preInstallCheck(void) 60{ 61 if (!getenv(DISK_PARTITIONED)) { 62 msgConfirm("You need to partition your disk before you can proceed with\nthe installation."); 63 64 return FALSE; 65 } 66 if (!getenv(DISK_LABELLED)) { 67 msgConfirm("You need to assign disk labels before you can proceed with\nthe installation."); 68 return FALSE; 69 } 70 if (!Dists) { 71 msgConfirm("You haven't told me what distributions to load yet!\nPlease select a distribution from the Distributions menu."); 72 return FALSE; 73 } 74 if (!mediaVerify()) 75 return FALSE; 76 return TRUE; 77} 78 79static void 80installInitial(void) 81{ 82 extern u_char boot1[], boot2[]; 83 extern u_char mbr[], bteasy17[]; 84 u_char *mbrContents; 85 Device **devs; 86 int i; 87 static Boolean alreadyDone = FALSE; 88 89 if (alreadyDone) 90 return; 91 92 /* If things aren't kosher, or we refuse to proceed, bail. */ 93 if (!preInstallCheck() 94 || 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!")) 95 return 0; 96 97 mbrContents = NULL; 98 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.")) 99 mbrContents = bteasy17; 100 else if (!msgYesNo("Would you like to remove an existing boot manager?")) 101 mbrContents = mbr; 102 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 103 for (i = 0; devs[i]; i++) { 104 Disk *d = (Disk *)devs[i]->private; 105 Chunk *c1; 106 107 if (!devs[i]->enabled) 108 continue; 109 110 if (mbrContents) { 111 Set_Boot_Mgr(d, mbrContents); 112 mbrContents = NULL; 113 } 114 Set_Boot_Blocks(d, boot1, boot2); 115 msgNotify("Writing partition information to drive %s", d->name); 116 Write_Disk(d); 117 118 /* Now scan for bad blocks, if necessary */ 119 for (c1 = d->chunks->part; c1; c1 = c1->next) { 120 if (c1->flags & CHUNK_BAD144) { 121 int ret; 122 123 msgNotify("Running bad block scan on partition %s", c1->name); 124 ret = vsystem("bad144 -v /dev/r%s 1234", c1->name); 125 if (ret) 126 msgConfirm("Bad144 init on %s returned status of %d!", c1->name, ret); 127 ret = vsystem("bad144 -v -s /dev/r%s", c1->name); 128 if (ret) 129 msgConfirm("Bad144 scan on %s returned status of %d!", c1->name, ret); 130 } 131 } 132 } 133 make_filesystems(); 134 copy_self(); 135 cpio_extract(); 136 alreadyDone = TRUE; 137} 138 139static void 140installFinal(void) 141{ 142 static Boolean alreadyDone = FALSE; 143 144 if (alreadyDone) 145 return; 146 install_configuration_files(); 147 do_final_setup(); 148 alreadyDone = TRUE; 149} 150 151int 152installCommit(char *str) 153{ 154 installInitial(); 155 distExtractAll(); 156 installFinal(); 157 return 0; 158} 159 160/* Go newfs and/or mount all the filesystems we've been asked to */ 161static void 162make_filesystems(void) 163{ 164 int i; 165 Disk *disk; 166 Chunk *c1, *c2; 167 Device **devs; 168 169 command_clear(); 170 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 171 172 /* First look for the root device and mount it */ 173 for (i = 0; devs[i]; i++) { 174 disk = (Disk *)devs[i]->private; 175 msgDebug("Scanning disk %s for root filesystem\n", disk->name); 176 if (!disk->chunks) 177 msgFatal("No chunk list found for %s!", disk->name); 178 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 179 if (c1->type == freebsd) { 180 for (c2 = c1->part; c2; c2 = c2->next) { 181 if (c2->type == part && c2->subtype != FS_SWAP && 182 c2->private && c2->flags & CHUNK_IS_ROOT) { 183 char dname[40]; 184 PartInfo *p = (PartInfo *)c2->private; 185 186 if (strcmp(p->mountpoint, "/")) { 187 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", c2->name, p->mountpoint); 188 continue; 189 } 190 if (p->newfs) { 191 int i; 192 193 sprintf(dname, "/dev/r%sa", disk->name); 194 msgNotify("Making a new root filesystem on %s", dname); 195 i = vsystem("newfs %s", dname); 196 if (i) { 197 msgConfirm("Unable to make new root filesystem! Command returned status %d", i); 198 return; 199 } 200 } 201 else 202 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."); 203 sprintf(dname, "/dev/%sa", disk->name); 204 if (Mount("/mnt", dname)) { 205 msgConfirm("Unable to mount the root file system! Giving up."); 206 return; 207 } 208 else { 209 extern int makedevs(void); 210 211 msgNotify("Making device files"); 212 if (Mkdir("/mnt/dev", NULL) 213 || chdir("/mnt/dev") 214 || makedevs()) 215 msgConfirm("Failed to make some of the devices in /mnt!"); 216 if (Mkdir("/mnt/stand", NULL)) 217 msgConfirm("Unable to make /mnt/stand directory!"); 218 chdir("/"); 219 break; 220 } 221 } 222 } 223 } 224 } 225 } 226 227 /* Now buzz through the rest of the partitions and mount them too */ 228 for (i = 0; devs[i]; i++) { 229 disk = (Disk *)devs[i]->private; 230 if (!disk->chunks) 231 msgFatal("No chunk list found for %s!", disk->name); 232 233 /* Make the proper device mount points in /mnt/dev */ 234 MakeDevDisk(disk, "/mnt/dev"); 235 236 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 237 if (c1->type == freebsd) { 238 for (c2 = c1->part; c2; c2 = c2->next) { 239 if (c2->type == part && c2->subtype != FS_SWAP && c2->private) { 240 PartInfo *tmp = (PartInfo *)c2->private; 241 242 if (!strcmp(tmp->mountpoint, "/")) 243 continue; 244 245 if (tmp->newfs) 246 command_shell_add(tmp->mountpoint, 247 "%s /mnt/dev/r%s", tmp->newfs_cmd, c2->name); 248 command_func_add(tmp->mountpoint, Mount, c2->name); 249 } 250 } 251 } 252 } 253 } 254 command_sort(); 255 command_execute(); 256} 257 258/* Copy the boot floppy contents into /stand */ 259static void 260copy_self(void) 261{ 262 int i; 263 264 msgNotify("Copying the boot floppy to /stand on root filesystem"); 265 chdir("/"); 266 i = vsystem("find -x . | cpio -pdmv /mnt/stand"); 267 if (i) 268 msgConfirm("Copy returned error status of %d!", i); 269} 270 271static void 272cpio_extract(void) 273{ 274 int i, j, zpid, cpid, pfd[2]; 275 extern int wait(int *status); 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); 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