| 1 | /* |
| 2 | * Copyright (c)2004 The DragonFly Project. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions |
| 6 | * are met: |
| 7 | * |
| 8 | * Redistributions of source code must retain the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer. |
| 10 | * |
| 11 | * Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in |
| 13 | * the documentation and/or other materials provided with the |
| 14 | * distribution. |
| 15 | * |
| 16 | * Neither the name of the DragonFly Project nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived |
| 18 | * from this software without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 24 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| 25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| 31 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
| 32 | */ |
| 33 | |
| 34 | /* |
| 35 | * fn_install.c |
| 36 | * Installer Function : Install OS Files. |
| 37 | * $Id: fn_install.c,v 1.74 2006/04/18 19:43:48 joerg Exp $ |
| 38 | */ |
| 39 | |
| 40 | #include <libgen.h> |
| 41 | #include <string.h> |
| 42 | |
| 43 | #define SOURCES_CONF_FILE "/usr/local/share/dfuibe_installer/sources.conf" |
| 44 | |
| 45 | #ifdef ENABLE_NLS |
| 46 | #include <libintl.h> |
| 47 | #define _(String) gettext (String) |
| 48 | #else |
| 49 | #define _(String) (String) |
| 50 | #endif |
| 51 | |
| 52 | #include "libaura/mem.h" |
| 53 | #include "libaura/buffer.h" |
| 54 | #include "libaura/fspred.h" |
| 55 | |
| 56 | #include "libdfui/dfui.h" |
| 57 | #include "libdfui/system.h" |
| 58 | |
| 59 | #include "libinstaller/commands.h" |
| 60 | #include "libinstaller/confed.h" |
| 61 | #include "libinstaller/diskutil.h" |
| 62 | #include "libinstaller/functions.h" |
| 63 | #include "libinstaller/uiutil.h" |
| 64 | |
| 65 | #include "flow.h" |
| 66 | #include "pathnames.h" |
| 67 | #include "fn.h" |
| 68 | |
| 69 | static const char *pfs_mountpt[5] = {"/var", "/tmp", "/usr", "/home", NULL}; |
| 70 | |
| 71 | /* |
| 72 | * fn_install_os: actually put DragonFly on a disk. |
| 73 | */ |
| 74 | void |
| 75 | fn_install_os(struct i_fn_args *a) |
| 76 | { |
| 77 | struct subpartition *sp; |
| 78 | struct commands *cmds; |
| 79 | struct command *cmd; |
| 80 | int i, seen_it, prefix, j; |
| 81 | FILE *sources_conf; |
| 82 | char line[256]; |
| 83 | char cp_src[64][256]; |
| 84 | char file_path[256]; |
| 85 | int lines = 0; |
| 86 | long mfsbacked_size; |
| 87 | |
| 88 | /* |
| 89 | * If SOURCES_CONF_FILE exists, lets read in and |
| 90 | * populate our copy sources. If it does not exist |
| 91 | * simply set the list by hand. |
| 92 | */ |
| 93 | if (!is_file("%s%s", a->os_root, SOURCES_CONF_FILE)) { |
| 94 | i_log(a, "Using internal copy sources table."); |
| 95 | strcpy(cp_src[0],"/COPYRIGHT"); |
| 96 | strcpy(cp_src[1],"/var"); |
| 97 | strcpy(cp_src[2],"/bin"); |
| 98 | strcpy(cp_src[3],"/boot"); |
| 99 | strcpy(cp_src[4],"/cdrom"); |
| 100 | strcpy(cp_src[5],"/dev"); |
| 101 | strcpy(cp_src[6],"/etc"); |
| 102 | strcpy(cp_src[7],"/libexec"); |
| 103 | strcpy(cp_src[8],"/lib"); |
| 104 | strcpy(cp_src[9],"/kernel"); |
| 105 | strcpy(cp_src[10],"/modules"); |
| 106 | strcpy(cp_src[11],"/root"); |
| 107 | strcpy(cp_src[12],"/sbin"); |
| 108 | strcpy(cp_src[13],"/sys"); |
| 109 | strcpy(cp_src[14],"/tmp"); |
| 110 | strcpy(cp_src[15],"/usr/bin"); |
| 111 | strcpy(cp_src[16],"/usr/games"); |
| 112 | strcpy(cp_src[17],"/usr/include"); |
| 113 | strcpy(cp_src[18],"/usr/lib"); |
| 114 | strcpy(cp_src[19],"/usr/local"); |
| 115 | strcpy(cp_src[20],"/usr/local/OpenOffice.org1.1.3"); |
| 116 | strcpy(cp_src[21],"/usr/X11R6"); |
| 117 | strcpy(cp_src[22],"/usr/libdata"); |
| 118 | strcpy(cp_src[23],"/usr/libexec"); |
| 119 | strcpy(cp_src[24],"/usr/obj"); |
| 120 | strcpy(cp_src[25],"/usr/sbin"); |
| 121 | strcpy(cp_src[26],"/usr/share"); |
| 122 | strcpy(cp_src[27],"/usr/src"); |
| 123 | strcpy(cp_src[28],""); |
| 124 | } else { |
| 125 | snprintf(file_path, 256, "%s%s", a->os_root, SOURCES_CONF_FILE); |
| 126 | sources_conf = fopen(file_path, "r"); |
| 127 | i_log(a, "Reading %s%s", a->os_root, SOURCES_CONF_FILE); |
| 128 | while(fgets(line, 256, sources_conf) != NULL && lines < 63) { |
| 129 | if(strlen(line)>0) |
| 130 | line[strlen(line)-1] = '\0'; |
| 131 | strlcpy(cp_src[lines], line, 256); |
| 132 | i_log(a,"Adding %s to copy source table.", cp_src[lines]); |
| 133 | lines++; |
| 134 | } |
| 135 | i_log(a,"Added %i total items to copy source table.", lines); |
| 136 | strcpy(cp_src[lines], ""); |
| 137 | fclose(sources_conf); |
| 138 | } |
| 139 | |
| 140 | cmds = commands_new(); |
| 141 | |
| 142 | /* |
| 143 | * If swap isn't mounted yet, mount it. |
| 144 | */ |
| 145 | if (measure_activated_swap(a) == 0) { |
| 146 | for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); |
| 147 | sp != NULL; sp = subpartition_next(sp)) { |
| 148 | if (!subpartition_is_swap(sp)) |
| 149 | continue; |
| 150 | command_add(cmds, "%s%s %sdev/%s", |
| 151 | a->os_root, |
| 152 | cmd_name(a, "SWAPON"), |
| 153 | a->os_root, |
| 154 | subpartition_get_device_name(sp)); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | /* |
| 159 | * Unmount anything already mounted on /mnt. |
| 160 | */ |
| 161 | unmount_all_under(a, cmds, "%smnt", a->os_root); |
| 162 | |
| 163 | for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); |
| 164 | sp != NULL; sp = subpartition_next(sp)) { |
| 165 | if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { |
| 166 | command_add(cmds, "%s%s -p %smnt%s", |
| 167 | a->os_root, cmd_name(a, "MKDIR"), |
| 168 | a->os_root, subpartition_get_mountpoint(sp)); |
| 169 | command_add(cmds, "%s%s %sdev/%s %smnt%s", |
| 170 | a->os_root, cmd_name(a, "MOUNT_HAMMER"), |
| 171 | a->os_root, |
| 172 | subpartition_get_device_name(sp), |
| 173 | a->os_root, |
| 174 | subpartition_get_mountpoint(sp)); |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | /* |
| 179 | * Create mount points and mount subpartitions on them. |
| 180 | */ |
| 181 | for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); |
| 182 | sp != NULL; sp = subpartition_next(sp)) { |
| 183 | if (subpartition_is_swap(sp)) { |
| 184 | /* |
| 185 | * Set this subpartition as the dump device. |
| 186 | */ |
| 187 | #ifdef AUTOMATICALLY_ENABLE_CRASH_DUMPS |
| 188 | if (subpartition_get_capacity(sp) < storage_get_memsize(a->s)) |
| 189 | continue; |
| 190 | |
| 191 | command_add(cmds, "%s%s -v %sdev/%s", |
| 192 | a->os_root, cmd_name(a, "DUMPON"), |
| 193 | a->os_root, |
| 194 | subpartition_get_device_name(sp)); |
| 195 | |
| 196 | asprintf(&string, "/dev/%s", |
| 197 | subpartition_get_device_name(sp)); |
| 198 | config_var_set(rc_conf, "dumpdev", string); |
| 199 | free(string); |
| 200 | config_var_set(rc_conf, "dumpdir", "/var/crash"); |
| 201 | #endif |
| 202 | continue; |
| 203 | } |
| 204 | |
| 205 | |
| 206 | /* |
| 207 | * Don't mount it if it's MFS-backed. |
| 208 | */ |
| 209 | |
| 210 | if (subpartition_is_mfsbacked(sp)) { |
| 211 | continue; |
| 212 | } |
| 213 | if (use_hammer == 0 || (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0)) { |
| 214 | command_add(cmds, "%s%s -p %smnt/boot", |
| 215 | a->os_root, cmd_name(a, "MKDIR"), |
| 216 | a->os_root); |
| 217 | command_add(cmds, "%s%s %sdev/%s %smnt%s", |
| 218 | a->os_root, cmd_name(a, "MOUNT"), |
| 219 | a->os_root, |
| 220 | subpartition_get_device_name(sp), |
| 221 | a->os_root, |
| 222 | subpartition_get_mountpoint(sp)); |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | /* Create PFS dir */ |
| 227 | command_add(cmds, "%s%s -p %smnt/pfs", |
| 228 | a->os_root, cmd_name(a, "MKDIR"), |
| 229 | a->os_root); |
| 230 | |
| 231 | /* mount null pfs */ |
| 232 | for (j = 0; pfs_mountpt[j] != NULL; j++) { |
| 233 | command_add(cmds, "%s%s pfs-master %smnt/pfs%s", |
| 234 | a->os_root, cmd_name(a, "HAMMER"), |
| 235 | a->os_root, pfs_mountpt[j]); |
| 236 | command_add(cmds, "%s%s -p %smnt%s", |
| 237 | a->os_root, cmd_name(a, "MKDIR"), |
| 238 | a->os_root, pfs_mountpt[j]); |
| 239 | command_add(cmds, "%s%s %smnt/pfs%s %smnt%s", |
| 240 | a->os_root, cmd_name(a, "MOUNT_NULL"), |
| 241 | a->os_root, pfs_mountpt[j], |
| 242 | a->os_root, pfs_mountpt[j]); |
| 243 | } |
| 244 | |
| 245 | /* |
| 246 | * Actually copy files now. |
| 247 | */ |
| 248 | |
| 249 | for (i = 0; cp_src[i] != NULL && cp_src[i][0] != '\0'; i++) { |
| 250 | char *src, *dest, *dn, *tmp_dest; |
| 251 | |
| 252 | dest = cp_src[i]; |
| 253 | |
| 254 | /* |
| 255 | * If dest would be on an MFS-backed |
| 256 | * mountpoint, don't bother copying it. |
| 257 | */ |
| 258 | sp = subpartition_of(storage_get_selected_slice(a->s), |
| 259 | "%s%s", a->os_root, &dest[1]); |
| 260 | if (sp != NULL && subpartition_is_mfsbacked(sp)) { |
| 261 | continue; |
| 262 | } |
| 263 | |
| 264 | /* |
| 265 | * Create intermediate directories, if needed. |
| 266 | */ |
| 267 | tmp_dest = aura_strdup(dest); |
| 268 | dn = dirname(tmp_dest); |
| 269 | if (is_dir("%s%s", a->os_root, &dn[1]) && |
| 270 | !is_dir("%smnt%s", a->os_root, dn)) { |
| 271 | command_add(cmds, "%s%s -p %smnt%s", |
| 272 | a->os_root, cmd_name(a, "MKDIR"), |
| 273 | a->os_root, dn); |
| 274 | } |
| 275 | aura_free(tmp_dest, "directory name"); |
| 276 | |
| 277 | /* |
| 278 | * If a directory by the same name but with the suffix |
| 279 | * ".hdd" exists on the installation media, cpdup that |
| 280 | * instead. This is particularly useful with /etc, which |
| 281 | * may have significantly different behaviour on the |
| 282 | * live CD compared to a standard HDD boot. |
| 283 | */ |
| 284 | if (is_dir("%s%s.hdd", a->os_root, &dest[1])) |
| 285 | asprintf(&src, "%s.hdd", &dest[1]); |
| 286 | else |
| 287 | asprintf(&src, "%s", &dest[1]); |
| 288 | |
| 289 | if (is_dir("%s%s", a->os_root, src) || is_file("%s%s", a->os_root, src)) { |
| 290 | /* |
| 291 | * Cpdup the chosen file or directory onto the HDD. |
| 292 | * if it exists on the source. |
| 293 | */ |
| 294 | cmd = command_add(cmds, "%s%s %s%s %smnt%s", |
| 295 | a->os_root, cmd_name(a, "CPDUP"), |
| 296 | a->os_root, src, |
| 297 | a->os_root, dest); |
| 298 | command_set_log_mode(cmd, COMMAND_LOG_QUIET); |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | /* |
| 303 | * Now, because cpdup does not cross mount points, |
| 304 | * we must copy anything that the user might've made a |
| 305 | * seperate mount point for (e.g. /usr/libdata/lint.) |
| 306 | */ |
| 307 | for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); |
| 308 | sp != NULL; sp = subpartition_next(sp)) { |
| 309 | /* |
| 310 | * If the subpartition is a swap subpartition or an |
| 311 | * MFS-backed mountpoint, don't try to copy anything |
| 312 | * into it. |
| 313 | */ |
| 314 | if (subpartition_is_swap(sp) || subpartition_is_mfsbacked(sp)) |
| 315 | continue; |
| 316 | |
| 317 | /* |
| 318 | * If the mountpoint doesn't even exist on the installation |
| 319 | * medium, don't try to copy anything from it! We assume |
| 320 | * it's an empty subpartition for the user's needs. |
| 321 | */ |
| 322 | if (!is_dir("%s%s", a->os_root, &subpartition_get_mountpoint(sp)[1])) |
| 323 | continue; |
| 324 | |
| 325 | /* |
| 326 | * Don't bother copying the mountpoint IF: |
| 327 | * - we've already said to copy it, or something besides it |
| 328 | * (it's a prefix of something in cp_src); or |
| 329 | * - we haven't said to copy it |
| 330 | * (nothing in cp_src is a prefix of it.) |
| 331 | */ |
| 332 | seen_it = 0; |
| 333 | prefix = 0; |
| 334 | for (i = 0; cp_src[i] != NULL && cp_src[i][0] != '\0'; i++) { |
| 335 | if (strncmp(subpartition_get_mountpoint(sp), cp_src[i], |
| 336 | strlen(subpartition_get_mountpoint(sp))) == 0) { |
| 337 | seen_it = 1; |
| 338 | break; |
| 339 | } |
| 340 | if (strncmp(cp_src[i], subpartition_get_mountpoint(sp), |
| 341 | strlen(cp_src[i])) == 0) { |
| 342 | prefix = 1; |
| 343 | } |
| 344 | } |
| 345 | if (seen_it || !prefix) |
| 346 | continue; |
| 347 | |
| 348 | /* |
| 349 | * Otherwise, cpdup the subpartition. |
| 350 | * |
| 351 | * XXX check for .hdd-extended source dirs here, too, |
| 352 | * eventually - but for now, /etc.hdd will never be |
| 353 | * the kind of tricky sub-mount-within-a-mount-point |
| 354 | * that this part of the code is meant to handle. |
| 355 | */ |
| 356 | cmd = command_add(cmds, "%s%s %s%s %smnt%s", |
| 357 | a->os_root, cmd_name(a, "CPDUP"), |
| 358 | a->os_root, &subpartition_get_mountpoint(sp)[1], |
| 359 | a->os_root, subpartition_get_mountpoint(sp)); |
| 360 | command_set_log_mode(cmd, COMMAND_LOG_QUIET); |
| 361 | } |
| 362 | |
| 363 | /* |
| 364 | * Create symlinks. |
| 365 | */ |
| 366 | |
| 367 | /* |
| 368 | * If the user has both /var and /tmp subparitions, |
| 369 | * symlink /var/tmp to /tmp. |
| 370 | */ |
| 371 | if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") != NULL && |
| 372 | subpartition_find(storage_get_selected_slice(a->s), "/var") != NULL) { |
| 373 | command_add(cmds, "%s%s 1777 %smnt/tmp", |
| 374 | a->os_root, cmd_name(a, "CHMOD"), a->os_root); |
| 375 | command_add(cmds, "%s%s -rf %smnt/var/tmp", |
| 376 | a->os_root, cmd_name(a, "RM"), a->os_root); |
| 377 | command_add(cmds, "%s%s -s /tmp %smnt/var/tmp", |
| 378 | a->os_root, cmd_name(a, "LN"), a->os_root); |
| 379 | } |
| 380 | |
| 381 | /* |
| 382 | * If the user has /var, but no /tmp, |
| 383 | * symlink /tmp to /var/tmp. |
| 384 | */ |
| 385 | if (subpartition_find(storage_get_selected_slice(a->s), "/tmp") == NULL && |
| 386 | subpartition_find(storage_get_selected_slice(a->s), "/var") != NULL) { |
| 387 | command_add(cmds, "%s%s -rf %smnt/tmp", |
| 388 | a->os_root, cmd_name(a, "RM"), a->os_root); |
| 389 | command_add(cmds, "%s%s -s /var/tmp %smnt/tmp", |
| 390 | a->os_root, cmd_name(a, "LN"), a->os_root); |
| 391 | } |
| 392 | |
| 393 | /* |
| 394 | * If the user has /usr, but no /home, |
| 395 | * symlink /home to /usr/home. |
| 396 | */ |
| 397 | if (subpartition_find(storage_get_selected_slice(a->s), "/home") == NULL && |
| 398 | subpartition_find(storage_get_selected_slice(a->s), "/usr") != NULL) { |
| 399 | command_add(cmds, "%s%s -rf %smnt/home", |
| 400 | a->os_root, cmd_name(a, "RM"), a->os_root); |
| 401 | command_add(cmds, "%s%s %smnt/usr/home", |
| 402 | a->os_root, cmd_name(a, "MKDIR"), a->os_root); |
| 403 | command_add(cmds, "%s%s -s /usr/home %smnt/home", |
| 404 | a->os_root, cmd_name(a, "LN"), a->os_root); |
| 405 | } |
| 406 | |
| 407 | /* |
| 408 | * XXX check for other possible combinations too? |
| 409 | */ |
| 410 | |
| 411 | /* |
| 412 | * Clean up. In case some file didn't make it, use rm -f |
| 413 | */ |
| 414 | #ifdef __DragonFly__ |
| 415 | command_add(cmds, "%s%s -f %smnt/boot/loader.conf", |
| 416 | a->os_root, cmd_name(a, "RM"), a->os_root); |
| 417 | #endif |
| 418 | command_add(cmds, "%s%s -f %smnt/tmp/install.log", |
| 419 | a->os_root, cmd_name(a, "RM"), a->os_root); |
| 420 | |
| 421 | /* |
| 422 | * Copy pristine versions over any files we might have installed. |
| 423 | * This allows the resulting file tree to be customized. |
| 424 | */ |
| 425 | for (i = 0; cp_src[i] != NULL && cp_src[i][0] != '\0'; i++) { |
| 426 | char *src, *dest, *dn, *tmp_dest; |
| 427 | |
| 428 | src = cp_src[i]; |
| 429 | dest = cp_src[i]; |
| 430 | |
| 431 | /* |
| 432 | * Get the directory that the desired thing to |
| 433 | * copy resides in. |
| 434 | */ |
| 435 | tmp_dest = aura_strdup(dest); |
| 436 | dn = dirname(tmp_dest); |
| 437 | |
| 438 | /* |
| 439 | * If this dir doesn't exist in PRISTINE_DIR |
| 440 | * on the install media, just skip it. |
| 441 | */ |
| 442 | if (!is_dir("%s%s%s", a->os_root, PRISTINE_DIR, dn)) { |
| 443 | aura_free(tmp_dest, _("directory name")); |
| 444 | continue; |
| 445 | } |
| 446 | |
| 447 | /* |
| 448 | * Create intermediate directories, if needed. |
| 449 | */ |
| 450 | if (!is_dir("%smnt%s", a->os_root, dn)) { |
| 451 | command_add(cmds, "%s%s -p %smnt%s", |
| 452 | a->os_root, cmd_name(a, "MKDIR"), |
| 453 | a->os_root, dn); |
| 454 | } |
| 455 | aura_free(tmp_dest, "directory name"); |
| 456 | |
| 457 | /* |
| 458 | * Cpdup the chosen file or directory onto the HDD. |
| 459 | */ |
| 460 | cmd = command_add(cmds, "%s%s %s%s %smnt%s", |
| 461 | a->os_root, cmd_name(a, "CPDUP"), |
| 462 | a->os_root, src, |
| 463 | a->os_root, dest); |
| 464 | |
| 465 | cmd = command_add(cmds, |
| 466 | "%s%s %s%s%s %smnt%s", |
| 467 | a->os_root, cmd_name(a, "CPDUP"), |
| 468 | a->os_root, PRISTINE_DIR, src, |
| 469 | a->os_root, dest); |
| 470 | command_set_log_mode(cmd, COMMAND_LOG_QUIET); |
| 471 | } |
| 472 | |
| 473 | /* |
| 474 | * Rebuild the user database, to get rid of any extra users |
| 475 | * from the LiveCD that aren't supposed to be installed |
| 476 | * (copying a pristine master.passwd isn't enough.) |
| 477 | */ |
| 478 | command_add(cmds, "%s%s -p -d %smnt/etc %smnt/etc/master.passwd", |
| 479 | a->os_root, cmd_name(a, "PWD_MKDB"), a->os_root, a->os_root); |
| 480 | |
| 481 | /* Create missing directories. */ |
| 482 | command_add(cmds, "%s%s %smnt/proc", |
| 483 | a->os_root, cmd_name(a, "MKDIR"), a->os_root); |
| 484 | command_add(cmds, "%s%s %smnt/mnt", |
| 485 | a->os_root, cmd_name(a, "MKDIR"), a->os_root); |
| 486 | |
| 487 | /* Write new fstab. */ |
| 488 | |
| 489 | command_add(cmds, "%s%s '%s' >%smnt/etc/fstab", |
| 490 | a->os_root, cmd_name(a, "ECHO"), |
| 491 | "# Device\t\tMountpoint\tFStype\tOptions\t\tDump\tPass#", |
| 492 | a->os_root); |
| 493 | |
| 494 | for (sp = slice_subpartition_first(storage_get_selected_slice(a->s)); |
| 495 | sp != NULL; sp = subpartition_next(sp)) { |
| 496 | if (strcmp(subpartition_get_mountpoint(sp), "swap") == 0) { |
| 497 | command_add(cmds, "%s%s '/dev/%s\t\tnone\t\tswap\tsw\t\t0\t0' >>%smnt/etc/fstab", |
| 498 | a->os_root, cmd_name(a, "ECHO"), |
| 499 | subpartition_get_device_name(sp), |
| 500 | a->os_root); |
| 501 | } |
| 502 | if (use_hammer == 0) { |
| 503 | if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { |
| 504 | command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t1\t1' >>%smnt/etc/fstab", |
| 505 | a->os_root, cmd_name(a, "ECHO"), |
| 506 | subpartition_get_device_name(sp), |
| 507 | subpartition_get_mountpoint(sp), |
| 508 | a->os_root); |
| 509 | } else if (subpartition_is_mfsbacked(sp)) { |
| 510 | mfsbacked_size = slice_get_capacity(storage_get_selected_slice(a->s)) * 2048; |
| 511 | command_add(cmds, "%s%s 'swap\t\t%s\t\t\tmfs\trw,-s%ld\t\t1\t1' >>%smnt/etc/fstab", |
| 512 | a->os_root, cmd_name(a, "ECHO"), |
| 513 | subpartition_get_mountpoint(sp), |
| 514 | mfsbacked_size, |
| 515 | a->os_root); |
| 516 | } else { |
| 517 | command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t2\t2' >>%smnt/etc/fstab", |
| 518 | a->os_root, cmd_name(a, "ECHO"), |
| 519 | subpartition_get_device_name(sp), |
| 520 | subpartition_get_mountpoint(sp), |
| 521 | a->os_root); |
| 522 | } |
| 523 | } else { |
| 524 | if (strcmp(subpartition_get_mountpoint(sp), "/") == 0) { |
| 525 | command_add(cmds, "%s%s '/dev/%s\t\t%s\t\thammer\trw\t\t1\t1' >>%smnt/etc/fstab", |
| 526 | a->os_root, cmd_name(a, "ECHO"), |
| 527 | subpartition_get_device_name(sp), |
| 528 | subpartition_get_mountpoint(sp), |
| 529 | a->os_root); |
| 530 | } else if (strcmp(subpartition_get_mountpoint(sp), "/boot") == 0) { |
| 531 | command_add(cmds, "%s%s '/dev/%s\t\t%s\t\tufs\trw\t\t1\t1' >>%smnt/etc/fstab", |
| 532 | a->os_root, cmd_name(a, "ECHO"), |
| 533 | subpartition_get_device_name(sp), |
| 534 | subpartition_get_mountpoint(sp), |
| 535 | a->os_root); |
| 536 | } |
| 537 | } |
| 538 | } |
| 539 | for (j = 0; pfs_mountpt[j] != NULL; j++) { |
| 540 | command_add(cmds, "%s%s '/pfs%s\t\t%s\t\tnull\trw\t\t0\t0' >>%smnt/etc/fstab", |
| 541 | a->os_root, cmd_name(a, "ECHO"), |
| 542 | pfs_mountpt[j], |
| 543 | pfs_mountpt[j], |
| 544 | a->os_root); |
| 545 | } |
| 546 | |
| 547 | command_add(cmds, "%s%s '%s' >>%smnt/etc/fstab", |
| 548 | a->os_root, cmd_name(a, "ECHO"), |
| 549 | "proc\t\t\t/proc\t\tprocfs\trw\t\t0\t0", |
| 550 | a->os_root); |
| 551 | |
| 552 | /* Backup the disklabel and the log. */ |
| 553 | if (use_hammer == 0) { |
| 554 | command_add(cmds, "%s%s %s > %smnt/etc/disklabel.%s", |
| 555 | a->os_root, cmd_name(a, "DISKLABEL"), |
| 556 | slice_get_device_name(storage_get_selected_slice(a->s)), |
| 557 | a->os_root, |
| 558 | slice_get_device_name(storage_get_selected_slice(a->s))); |
| 559 | } else { |
| 560 | command_add(cmds, "%s%s %s > %smnt/etc/disklabel.%s", |
| 561 | a->os_root, cmd_name(a, "DISKLABEL64"), |
| 562 | slice_get_device_name(storage_get_selected_slice(a->s)), |
| 563 | a->os_root, |
| 564 | slice_get_device_name(storage_get_selected_slice(a->s))); |
| 565 | } |
| 566 | |
| 567 | command_add(cmds, "%s%s %sinstall.log %smnt/var/log/install.log", |
| 568 | a->os_root, cmd_name(a, "CP"), |
| 569 | a->tmp, a->os_root); |
| 570 | command_add(cmds, "%s%s 600 %smnt/var/log/install.log", |
| 571 | a->os_root, cmd_name(a, "CHMOD"), a->os_root); |
| 572 | |
| 573 | /* Customize stuff here */ |
| 574 | if(is_file("%susr/local/bin/after_installation_routines.sh")) { |
| 575 | command_add(cmds, "%susr/local/bin/after_installation_routines.sh", |
| 576 | a->os_root, _("Running after installation custom routines...")); |
| 577 | } |
| 578 | |
| 579 | /* |
| 580 | * Do it! |
| 581 | */ |
| 582 | /* commands_preview(cmds); */ |
| 583 | if (!commands_execute(a, cmds)) { |
| 584 | inform(a->c, _("%s was not fully installed."), OPERATING_SYSTEM_NAME); |
| 585 | a->result = 0; |
| 586 | } else { |
| 587 | a->result = 1; |
| 588 | } |
| 589 | commands_free(cmds); |
| 590 | |
| 591 | /* |
| 592 | * Unmount everything we mounted on /mnt. This is done in a seperate |
| 593 | * command chain, so that partitions are unmounted, even if an error |
| 594 | * occurs in one of the preceding commands, or it is cancelled. |
| 595 | */ |
| 596 | cmds = commands_new(); |
| 597 | unmount_all_under(a, cmds, "%smnt", a->os_root); |
| 598 | |
| 599 | /* |
| 600 | * Once everything is unmounted, if the install went successfully, |
| 601 | * make sure once and for all that the disklabel is bootable. |
| 602 | */ |
| 603 | if (a->result) { |
| 604 | if (use_hammer == 0) { |
| 605 | command_add(cmds, "%s%s -B %s", |
| 606 | a->os_root, cmd_name(a, "DISKLABEL"), |
| 607 | slice_get_device_name(storage_get_selected_slice(a->s))); |
| 608 | } else { |
| 609 | command_add(cmds, "%s%s -B %s", |
| 610 | a->os_root, cmd_name(a, "DISKLABEL64"), |
| 611 | slice_get_device_name(storage_get_selected_slice(a->s))); |
| 612 | } |
| 613 | } |
| 614 | |
| 615 | if (!commands_execute(a, cmds)) |
| 616 | inform(a->c, _("Warning: subpartitions were not correctly unmounted.")); |
| 617 | |
| 618 | commands_free(cmds); |
| 619 | } |
| 620 | |