Annotation of src/distrib/utils/sysinst/disks.c, Revision 1.104
1.104 ! tsutsui 1: /* $NetBSD: disks.c,v 1.103 2009/02/23 23:12:24 ad Exp $ */
1.1 phil 2:
3: /*
4: * Copyright 1997 Piermont Information Systems Inc.
5: * All rights reserved.
6: *
7: * Written by Philip A. Nelson for Piermont Information Systems Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
1.27 cgd 19: * This product includes software developed for the NetBSD Project by
1.1 phil 20: * Piermont Information Systems Inc.
21: * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.51 dsl 28: * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1.1 phil 31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1.51 dsl 34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1.1 phil 35: * THE POSSIBILITY OF SUCH DAMAGE.
36: *
37: */
38:
39: /* disks.c -- routines to deal with finding disks and labeling disks. */
40:
41:
1.11 jonathan 42: #include <errno.h>
1.1 phil 43: #include <stdio.h>
44: #include <stdlib.h>
1.3 phil 45: #include <unistd.h>
46: #include <fcntl.h>
1.9 jonathan 47: #include <util.h>
1.3 phil 48:
49: #include <sys/param.h>
1.58 dsl 50: #include <sys/swap.h>
1.3 phil 51: #include <ufs/ufs/dinode.h>
52: #include <ufs/ffs/fs.h>
1.48 christos 53: #define FSTYPENAMES
1.74 dsl 54: #define MOUNTNAMES
1.49 christos 55: #define static
1.48 christos 56: #include <sys/disklabel.h>
1.49 christos 57: #undef static
1.3 phil 58:
1.1 phil 59: #include "defs.h"
1.6 phil 60: #include "md.h"
1.1 phil 61: #include "msg_defs.h"
62: #include "menu_defs.h"
63: #include "txtwalk.h"
64:
1.64 dsl 65: /* Disk descriptions */
66: #define MAX_DISKS 15
67: struct disk_desc {
1.85 dsl 68: char dd_name[SSTRSIZE];
69: uint dd_no_mbr;
70: uint dd_cyl;
71: uint dd_head;
72: uint dd_sec;
73: uint dd_secsize;
74: uint dd_totsec;
1.64 dsl 75: };
1.8 jonathan 76:
1.2 phil 77: /* Local prototypes */
1.74 dsl 78: static int foundffs(struct data *, size_t);
1.91 tsutsui 79: #ifdef USE_SYSVBFS
80: static int foundsysvbfs(struct data *, size_t);
81: #endif
1.74 dsl 82: static int fsck_preen(const char *, int, const char *);
1.82 dbj 83: static void fixsb(const char *, const char *, char);
1.11 jonathan 84:
1.52 dsl 85: #ifndef DISK_NAMES
1.88 tron 86: #define DISK_NAMES "wd", "sd", "ld", "raid"
1.52 dsl 87: #endif
88:
1.65 dsl 89: static const char *disk_names[] = { DISK_NAMES, "vnd", NULL };
1.8 jonathan 90:
1.64 dsl 91: static int
92: get_disks(struct disk_desc *dd)
1.4 phil 93: {
1.65 dsl 94: const char **xd;
1.85 dsl 95: char *cp;
1.4 phil 96: struct disklabel l;
97: int i;
1.64 dsl 98: int numdisks;
1.4 phil 99:
1.51 dsl 100: /* initialize */
101: numdisks = 0;
102:
103: for (xd = disk_names; *xd != NULL; xd++) {
104: for (i = 0; i < MAX_DISKS; i++) {
1.85 dsl 105: strlcpy(dd->dd_name, *xd, sizeof dd->dd_name - 2);
106: cp = strchr(dd->dd_name, ':');
107: if (cp != NULL)
1.92 dsl 108: dd->dd_no_mbr = !strcmp(cp, ":no_mbr");
1.86 cube 109: else {
110: dd->dd_no_mbr = 0;
1.85 dsl 111: cp = strchr(dd->dd_name, 0);
1.86 cube 112: }
1.85 dsl 113:
114: snprintf(cp, 2 + 1, "%d", i);
115: if (!get_geom(dd->dd_name, &l)) {
1.52 dsl 116: if (errno == ENOENT)
117: break;
1.51 dsl 118: continue;
1.52 dsl 119: }
1.51 dsl 120: dd->dd_cyl = l.d_ncylinders;
121: dd->dd_head = l.d_ntracks;
122: dd->dd_sec = l.d_nsectors;
123: dd->dd_secsize = l.d_secsize;
124: dd->dd_totsec = l.d_secperunit;
125: dd++;
126: numdisks++;
127: if (numdisks >= MAX_DISKS)
1.64 dsl 128: return numdisks;
1.4 phil 129: }
1.3 phil 130: }
1.64 dsl 131: return numdisks;
1.3 phil 132: }
1.51 dsl 133:
1.64 dsl 134: static int
1.66 dsl 135: set_dsk_select(menudesc *m, void *arg)
1.64 dsl 136: {
137: *(int *)arg = m->cursel;
138: return 1;
139: }
1.3 phil 140:
1.38 mrg 141: int
1.61 dsl 142: find_disks(const char *doingwhat)
1.1 phil 143: {
1.64 dsl 144: struct disk_desc disks[MAX_DISKS];
145: menu_ent dsk_menu[nelem(disks)];
146: struct disk_desc *disk;
147: int i;
148: int numdisks;
149: int selected_disk = 0;
150: int menu_no;
1.1 phil 151:
1.4 phil 152: /* Find disks. */
1.64 dsl 153: numdisks = get_disks(disks);
1.1 phil 154:
1.20 garbled 155: /* need a redraw here, kernel messages hose everything */
156: touchwin(stdscr);
157: refresh();
1.94 dsl 158: /* Kill typeahead, it won't be what the user had in mind */
159: fpurge(stdin);
1.20 garbled 160:
1.1 phil 161: if (numdisks == 0) {
162: /* No disks found! */
1.23 fvdl 163: msg_display(MSG_nodisk);
1.53 dsl 164: process_menu(MENU_ok, NULL);
1.20 garbled 165: /*endwin();*/
1.1 phil 166: return -1;
1.51 dsl 167: }
168:
169: if (numdisks == 1) {
1.1 phil 170: /* One disk found! */
1.64 dsl 171: msg_display(MSG_onedisk, disks[0].dd_name, doingwhat);
1.53 dsl 172: process_menu(MENU_ok, NULL);
1.1 phil 173: } else {
174: /* Multiple disks found! */
1.64 dsl 175: for (i = 0; i < numdisks; i++) {
176: dsk_menu[i].opt_name = disks[i].dd_name;
177: dsk_menu[i].opt_menu = OPT_NOMENU;
178: dsk_menu[i].opt_flags = OPT_EXIT;
179: dsk_menu[i].opt_action = set_dsk_select;
180: }
181: menu_no = new_menu(MSG_Available_disks,
182: dsk_menu, numdisks, -1, 4, 0, 0,
183: MC_SCROLL | MC_NOEXITOPT,
184: NULL, NULL, NULL, NULL, NULL);
185: if (menu_no == -1)
186: return -1;
187: msg_display(MSG_ask_disk);
188: process_menu(menu_no, &selected_disk);
189: free_menu(menu_no);
1.1 phil 190: }
1.51 dsl 191:
1.64 dsl 192: disk = disks + selected_disk;
193: strlcpy(diskdev, disk->dd_name, sizeof diskdev);
1.3 phil 194:
1.92 dsl 195: /* Use as a default disk if the user has the sets on a local disk */
196: strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev);
197:
1.22 fvdl 198: sectorsize = disk->dd_secsize;
1.23 fvdl 199: dlcyl = disk->dd_cyl;
200: dlhead = disk->dd_head;
201: dlsec = disk->dd_sec;
202: dlsize = disk->dd_totsec;
1.85 dsl 203: no_mbr = disk->dd_no_mbr;
1.64 dsl 204: if (dlsize == 0)
205: dlsize = disk->dd_cyl * disk->dd_head * disk->dd_sec;
1.23 fvdl 206: dlcylsize = dlhead * dlsec;
1.1 phil 207:
1.62 dsl 208: /* Get existing/default label */
1.76 dsl 209: memset(&oldlabel, 0, sizeof oldlabel);
1.62 dsl 210: incorelabel(diskdev, oldlabel);
211:
1.75 dsl 212: /* Set 'target' label to current label in case we don't change it */
213: memcpy(&bsdlabel, &oldlabel, sizeof bsdlabel);
214:
1.1 phil 215: return numdisks;
216: }
217:
1.57 dsl 218: void
1.62 dsl 219: fmt_fspart(menudesc *m, int ptn, void *arg)
1.57 dsl 220: {
221: int poffset, psize, pend;
222: const char *desc;
1.62 dsl 223: static const char *Yes, *No;
1.74 dsl 224: partinfo *p = bsdlabel + ptn;
1.62 dsl 225:
226: if (Yes == NULL) {
227: Yes = msg_string(MSG_Yes);
228: No = msg_string(MSG_No);
229: }
1.57 dsl 230:
1.74 dsl 231: poffset = p->pi_offset / sizemult;
232: psize = p->pi_size / sizemult;
1.57 dsl 233: if (psize == 0)
234: pend = 0;
235: else
1.74 dsl 236: pend = (p->pi_offset + p->pi_size) / sizemult - 1;
237:
238: if (p->pi_fstype == FS_BSDFFS)
239: if (p->pi_flags & PIF_FFSv2)
240: desc = "FFSv2";
241: else
242: desc = "FFSv1";
243: else
244: desc = fstypenames[p->pi_fstype];
1.57 dsl 245:
246: #ifdef PART_BOOT
247: if (ptn == PART_BOOT)
248: desc = msg_string(MSG_Boot_partition_cant_change);
249: #endif
250: if (ptn == getrawpartition())
251: desc = msg_string(MSG_Whole_disk_cant_change);
252: else {
1.74 dsl 253: if (ptn == PART_C)
1.57 dsl 254: desc = msg_string(MSG_NetBSD_partition_cant_change);
255: }
256:
1.62 dsl 257: wprintw(m->mw, msg_string(MSG_fspart_row),
258: poffset, pend, psize, desc,
1.74 dsl 259: p->pi_flags & PIF_NEWFS ? Yes : "",
260: p->pi_flags & PIF_MOUNT ? Yes : "",
261: p->pi_mount);
1.1 phil 262: }
263:
1.13 jonathan 264: /*
265: * Label a disk using an MD-specific string DISKLABEL_CMD for
1.60 dsl 266: * to invoke disklabel.
1.13 jonathan 267: * if MD code does not define DISKLABEL_CMD, this is a no-op.
268: *
1.60 dsl 269: * i386 port uses "/sbin/disklabel -w -r", just like i386
1.13 jonathan 270: * miniroot scripts, though this may leave a bogus incore label.
271: *
1.60 dsl 272: * Sun ports should use DISKLABEL_CMD "/sbin/disklabel -w"
273: * to get incore to ondisk inode translation for the Sun proms.
1.13 jonathan 274: */
1.38 mrg 275: int
276: write_disklabel (void)
1.1 phil 277: {
1.13 jonathan 278:
279: #ifdef DISKLABEL_CMD
1.1 phil 280: /* disklabel the disk */
1.74 dsl 281: return run_program(RUN_DISPLAY, "%s -f /tmp/disktab %s '%s'",
1.73 dsl 282: DISKLABEL_CMD, diskdev, bsddiskname);
1.48 christos 283: #else
284: return 0;
1.13 jonathan 285: #endif
1.1 phil 286: }
287:
1.62 dsl 288:
289: static int
290: ptn_sort(const void *a, const void *b)
291: {
1.65 dsl 292: return strcmp(bsdlabel[*(const int *)a].pi_mount,
293: bsdlabel[*(const int *)b].pi_mount);
1.62 dsl 294: }
295:
1.38 mrg 296: int
297: make_filesystems(void)
1.1 phil 298: {
299: int i;
1.62 dsl 300: int ptn;
301: int ptn_order[nelem(bsdlabel)];
1.74 dsl 302: int error = 0;
1.62 dsl 303: int maxpart = getmaxpartitions();
1.74 dsl 304: char *newfs;
305: const char *mnt_opts;
306: const char *fsname;
307: partinfo *lbl;
1.62 dsl 308:
309: if (maxpart > nelem(bsdlabel))
310: maxpart = nelem(bsdlabel);
311:
312: /* Making new file systems and mounting them */
313:
314: /* sort to ensure /usr/local is mounted after /usr (etc) */
315: for (i = 0; i < maxpart; i++)
316: ptn_order[i] = i;
317: qsort(ptn_order, maxpart, sizeof ptn_order[0], ptn_sort);
1.1 phil 318:
1.62 dsl 319: for (i = 0; i < maxpart; i++) {
1.9 jonathan 320: /*
1.51 dsl 321: * newfs and mount. For now, process only BSD filesystems.
1.40 mrg 322: * but if this is the mounted-on root, has no mount
1.51 dsl 323: * point defined, or is marked preserve, don't touch it!
1.9 jonathan 324: */
1.62 dsl 325: ptn = ptn_order[i];
1.74 dsl 326: lbl = bsdlabel + ptn;
327:
1.72 dsl 328: if (is_active_rootpart(diskdev, ptn))
329: continue;
1.1 phil 330:
1.74 dsl 331: if (*lbl->pi_mount == 0)
332: /* No mount point */
333: continue;
1.57 dsl 334:
1.74 dsl 335: newfs = NULL;
336: mnt_opts = NULL;
337: fsname = NULL;
338: switch (lbl->pi_fstype) {
339: case FS_APPLEUFS:
340: asprintf(&newfs, "/sbin/newfs %s%.0d",
341: lbl->pi_isize != 0 ? "-i" : "", lbl->pi_isize);
342: mnt_opts = "-tffs -o async";
343: fsname = "ffs";
344: break;
1.57 dsl 345: case FS_BSDFFS:
1.93 dsl 346: asprintf(&newfs,
347: "/sbin/newfs -V2 -O %d -b %d -f %d%s%.0d",
348: lbl->pi_flags & PIF_FFSv2 ? 2 : 1,
349: lbl->pi_fsize * lbl->pi_frag, lbl->pi_fsize,
350: lbl->pi_isize != 0 ? " -i " : "", lbl->pi_isize);
1.100 simonb 351: if (lbl->pi_flags & PIF_LOG)
352: mnt_opts = "-tffs -o log";
353: else
354: mnt_opts = "-tffs -o async";
1.74 dsl 355: fsname = "ffs";
1.57 dsl 356: break;
357: case FS_BSDLFS:
1.74 dsl 358: asprintf(&newfs, "/sbin/newfs_lfs -b %d",
359: lbl->pi_fsize * lbl->pi_frag);
360: mnt_opts = "-tlfs";
361: fsname = "lfs";
362: break;
363: case FS_MSDOS:
1.98 tsutsui 364: #ifdef USE_NEWFS_MSDOS
365: asprintf(&newfs, "/sbin/newfs_msdos");
366: #endif
1.74 dsl 367: mnt_opts = "-tmsdos";
368: fsname = "msdos";
1.57 dsl 369: break;
1.91 tsutsui 370: #ifdef USE_SYSVBFS
371: case FS_SYSVBFS:
372: asprintf(&newfs, "/sbin/newfs_sysvbfs");
373: mnt_opts = "-tsysvbfs";
374: fsname = "sysvbfs";
375: break;
376: #endif
1.99 tsutsui 377: #ifdef USE_EXT2FS
378: case FS_EX2FS:
379: asprintf(&newfs, "/sbin/newfs_ext2fs");
380: mnt_opts = "-text2fs";
381: fsname = "ext2fs";
382: break;
383: #endif
1.57 dsl 384: }
1.74 dsl 385: if (lbl->pi_flags & PIF_NEWFS && newfs != NULL) {
1.98 tsutsui 386: #ifdef USE_NEWFS_MSDOS
387: if (lbl->pi_fstype == FS_MSDOS) {
388: /* newfs only if mount fails */
389: if (run_program(RUN_SILENT | RUN_ERROR_OK,
390: "mount -rt msdos /dev/%s%c /mnt2",
391: diskdev, 'a' + ptn) != 0)
392: error = run_program(
393: RUN_DISPLAY | RUN_PROGRESS,
394: "%s /dev/r%s%c",
395: newfs, diskdev, 'a' + ptn);
396: else {
397: run_program(RUN_SILENT | RUN_ERROR_OK,
398: "umount /mnt2");
399: error = 0;
400: }
401: } else
402: #endif
1.74 dsl 403: error = run_program(RUN_DISPLAY | RUN_PROGRESS,
404: "%s /dev/r%s%c", newfs, diskdev, 'a' + ptn);
405: } else {
406: /* We'd better check it isn't dirty */
407: error = fsck_preen(diskdev, ptn, fsname);
408: }
409: free(newfs);
410: if (error != 0)
411: return error;
412:
413: if (lbl->pi_flags & PIF_MOUNT && mnt_opts != NULL) {
414: make_target_dir(lbl->pi_mount);
415: error = target_mount(mnt_opts, diskdev, ptn,
416: lbl->pi_mount);
417: if (error) {
418: msg_display(MSG_mountfail,
419: diskdev, 'a' + ptn, lbl->pi_mount);
420: process_menu(MENU_ok, NULL);
421: return error;
422: }
1.25 bouyer 423: }
1.9 jonathan 424: }
1.74 dsl 425: return 0;
1.1 phil 426: }
427:
1.38 mrg 428: int
429: make_fstab(void)
1.1 phil 430: {
431: FILE *f;
1.48 christos 432: int i, swap_dev = -1;
1.1 phil 433:
434: /* Create the fstab. */
1.8 jonathan 435: make_target_dir("/etc");
1.23 fvdl 436: f = target_fopen("/etc/fstab", "w");
1.20 garbled 437: if (logging)
1.47 fvdl 438: (void)fprintf(logfp,
439: "Creating %s/etc/fstab.\n", target_prefix());
1.40 mrg 440: scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix());
1.20 garbled 441:
1.1 phil 442: if (f == NULL) {
443: #ifndef DEBUG
1.24 bouyer 444: msg_display(MSG_createfstab);
1.20 garbled 445: if (logging)
1.47 fvdl 446: (void)fprintf(logfp, "Failed to make /etc/fstab!\n");
1.53 dsl 447: process_menu(MENU_ok, NULL);
1.25 bouyer 448: return 1;
1.1 phil 449: #else
450: f = stdout;
1.51 dsl 451: #endif
1.1 phil 452: }
1.40 mrg 453:
1.90 christos 454: scripting_fprintf(f, "# NetBSD /etc/fstab\n# See /usr/share/examples/"
455: "fstab/ for more examples.\n", target_prefix());
1.57 dsl 456: for (i = 0; i < getmaxpartitions(); i++) {
457: const char *s = "";
458: const char *mp = bsdlabel[i].pi_mount;
459: const char *fstype = "ffs";
1.69 dsl 460: int fsck_pass = 0, dump_freq = 0;
1.57 dsl 461:
462: if (!*mp) {
463: /*
464: * No mount point specified, comment out line and
465: * use /mnt as a placeholder for the mount point.
466: */
467: s = "# ";
468: mp = "/mnt";
469: }
470:
471: switch (bsdlabel[i].pi_fstype) {
1.69 dsl 472: case FS_UNUSED:
473: continue;
1.57 dsl 474: case FS_BSDLFS:
1.40 mrg 475: /* If there is no LFS, just comment it out. */
1.95 dsl 476: if (!check_lfs_progs())
1.57 dsl 477: s = "# ";
478: fstype = "lfs";
479: /* FALLTHROUGH */
480: case FS_BSDFFS:
1.74 dsl 481: fsck_pass = (strcmp(mp, "/") == 0) ? 1 : 2;
1.69 dsl 482: dump_freq = 1;
1.57 dsl 483: break;
484: case FS_MSDOS:
1.69 dsl 485: fstype = "msdos";
1.57 dsl 486: break;
487: case FS_SWAP:
1.48 christos 488: if (swap_dev == -1)
489: swap_dev = i;
1.90 christos 490: scripting_fprintf(f, "/dev/%s%c\t\tnone\tswap\tsw\t\t 0 0\n",
1.51 dsl 491: diskdev, 'a' + i);
1.69 dsl 492: continue;
1.91 tsutsui 493: #ifdef USE_SYSVBFS
494: case FS_SYSVBFS:
495: fstype = "sysvbfs";
496: make_target_dir("/stand");
497: break;
498: #endif
1.69 dsl 499: default:
500: fstype = "???";
501: s = "# ";
1.57 dsl 502: break;
1.20 garbled 503: }
1.89 dsl 504: /* The code that remounts root rw doesn't check the partition */
505: if (strcmp(mp, "/") == 0 && !(bsdlabel[i].pi_flags & PIF_MOUNT))
506: s = "# ";
507:
1.100 simonb 508: scripting_fprintf(f,
1.101 ad 509: "%s/dev/%s%c\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n",
1.69 dsl 510: s, diskdev, 'a' + i, mp, fstype,
1.100 simonb 511: bsdlabel[i].pi_flags & PIF_LOG ? ",log" : "",
1.69 dsl 512: bsdlabel[i].pi_flags & PIF_MOUNT ? "" : ",noauto",
513: bsdlabel[i].pi_flags & PIF_ASYNC ? ",async" : "",
514: bsdlabel[i].pi_flags & PIF_NOATIME ? ",noatime" : "",
1.71 dsl 515: bsdlabel[i].pi_flags & PIF_NODEV ? ",nodev" : "",
1.69 dsl 516: bsdlabel[i].pi_flags & PIF_NODEVMTIME ? ",nodevmtime" : "",
1.71 dsl 517: bsdlabel[i].pi_flags & PIF_NOEXEC ? ",noexec" : "",
518: bsdlabel[i].pi_flags & PIF_NOSUID ? ",nosuid" : "",
1.69 dsl 519: dump_freq, fsck_pass);
1.57 dsl 520: }
521:
1.56 dsl 522: if (tmp_mfs_size != 0) {
1.48 christos 523: if (swap_dev != -1)
1.90 christos 524: scripting_fprintf(f, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%d\n",
1.56 dsl 525: diskdev, 'a' + swap_dev, tmp_mfs_size);
1.40 mrg 526: else
1.90 christos 527: scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%d\n",
1.68 skrll 528: tmp_mfs_size);
1.20 garbled 529: }
1.57 dsl 530:
1.96 xtraeme 531: /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */
1.103 ad 532: scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n");
1.96 xtraeme 533: scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n");
1.102 ad 534: scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n");
1.97 hubertf 535: scripting_fprintf(f, "/dev/cd0a\t\t/cdrom\tcd9660\tro,noauto\n");
1.57 dsl 536: make_target_dir("/kern");
1.69 dsl 537: make_target_dir("/proc");
1.96 xtraeme 538: make_target_dir("/dev/pts");
1.97 hubertf 539: make_target_dir("/cdrom");
1.57 dsl 540:
1.40 mrg 541: scripting_fprintf(NULL, "EOF\n");
542:
1.1 phil 543: #ifndef DEBUG
544: fclose(f);
1.20 garbled 545: fflush(NULL);
1.1 phil 546: #endif
1.24 bouyer 547: return 0;
1.1 phil 548: }
1.14 jonathan 549:
1.40 mrg 550:
1.1 phil 551:
1.74 dsl 552: static int
1.48 christos 553: /*ARGSUSED*/
554: foundffs(struct data *list, size_t num)
1.3 phil 555: {
1.74 dsl 556: int error;
1.3 phil 557:
1.74 dsl 558: if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 ||
559: strstr(list[2].u.s_val, "noauto") != NULL)
560: return 0;
1.3 phil 561:
1.74 dsl 562: error = fsck_preen(list[0].u.s_val, ' '-'a', "ffs");
563: if (error != 0)
564: return error;
1.2 phil 565:
1.74 dsl 566: error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val);
567: if (error != 0)
568: return error;
569: return 0;
1.2 phil 570: }
571:
1.91 tsutsui 572: #ifdef USE_SYSVBFS
573: static int
574: /*ARGSUSED*/
575: foundsysvbfs(struct data *list, size_t num)
576: {
577: int error;
578:
579: if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 ||
580: strstr(list[2].u.s_val, "noauto") != NULL)
581: return 0;
582:
583: error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val);
584: if (error != 0)
585: return error;
586: return 0;
587: }
588: #endif
589:
1.11 jonathan 590: /*
1.81 dsl 591: * Do an fsck. On failure, inform the user by showing a warning
1.11 jonathan 592: * message and doing menu_ok() before proceeding.
1.74 dsl 593: * Returns 0 on success, or nonzero return code from fsck() on failure.
1.11 jonathan 594: */
1.74 dsl 595: static int
596: fsck_preen(const char *disk, int ptn, const char *fsname)
1.10 jonathan 597: {
1.74 dsl 598: char *prog;
1.40 mrg 599: int error;
1.74 dsl 600:
601: ptn += 'a';
602: if (fsname == NULL)
603: return 0;
604: /* first check fsck program exists, if not assue ok */
605: asprintf(&prog, "/sbin/fsck_%s", fsname);
606: if (prog == NULL)
607: return 0;
608: if (access(prog, X_OK) != 0)
609: return 0;
1.77 dbj 610: if (!strcmp(fsname,"ffs"))
1.82 dbj 611: fixsb(prog, disk, ptn);
1.74 dsl 612: error = run_program(0, "%s -p -q /dev/r%s%c", prog, disk, ptn);
613: free(prog);
614: if (error != 0) {
615: msg_display(MSG_badfs, disk, ptn, error);
1.53 dsl 616: process_menu(MENU_ok, NULL);
1.81 dsl 617: /* XXX at this point maybe we should run a full fsck? */
1.3 phil 618: }
1.11 jonathan 619: return error;
620: }
621:
1.82 dbj 622: /* This performs the same function as the etc/rc.d/fixsb script
623: * which attempts to correct problems with ffs1 filesystems
624: * which may have been introduced by booting a netbsd-current kernel
625: * from between April of 2003 and January 2004. For more information
626: * This script was developed as a response to NetBSD pr install/25138
627: * Additional prs regarding the original issue include:
628: * bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926
1.81 dsl 629: */
1.77 dbj 630: static void
1.82 dbj 631: fixsb(const char *prog, const char *disk, char ptn)
1.77 dbj 632: {
633: int fd;
1.78 dbj 634: int rval;
1.82 dbj 635: union {
636: struct fs fs;
637: char buf[SBLOCKSIZE];
638: } sblk;
639: struct fs *fs = &sblk.fs;
640:
1.84 dsl 641: snprintf(sblk.buf, sizeof(sblk.buf), "/dev/r%s%c",
642: disk, ptn == ' ' ? 0 : ptn);
1.82 dbj 643: fd = open(sblk.buf, O_RDONLY);
1.77 dbj 644: if (fd == -1)
645: return;
1.81 dsl 646:
647: /* Read ffsv1 main superblock */
1.82 dbj 648: rval = pread(fd, sblk.buf, sizeof sblk.buf, SBLOCK_UFS1);
1.77 dbj 649: close(fd);
1.82 dbj 650: if (rval != sizeof sblk.buf)
1.77 dbj 651: return;
652:
653: if (fs->fs_magic != FS_UFS1_MAGIC &&
654: fs->fs_magic != FS_UFS1_MAGIC_SWAPPED)
1.81 dsl 655: /* Not FFSv1 */
1.77 dbj 656: return;
657: if (fs->fs_old_flags & FS_FLAGS_UPDATED)
1.81 dsl 658: /* properly updated fslevel 4 */
1.77 dbj 659: return;
660: if (fs->fs_bsize != fs->fs_maxbsize)
1.81 dsl 661: /* not messed up */
1.77 dbj 662: return;
663:
1.81 dsl 664: /*
665: * OK we have a munged fs, first 'upgrade' to fslevel 4,
666: * We specify -b16 in order to stop fsck bleating that the
667: * sb doesn't match the first alternate.
668: */
1.82 dbj 669: run_program(RUN_DISPLAY | RUN_PROGRESS,
1.83 dbj 670: "%s -p -b 16 -c 4 /dev/r%s%c", prog, disk, ptn);
1.81 dsl 671: /* Then downgrade to fslevel 3 */
1.82 dbj 672: run_program(RUN_DISPLAY | RUN_PROGRESS,
673: "%s -p -c 3 /dev/r%s%c", prog, disk, ptn);
1.77 dbj 674: }
675:
1.11 jonathan 676: /*
677: * fsck and mount the root partition.
678: */
1.92 dsl 679: static int
1.74 dsl 680: mount_root(void)
1.11 jonathan 681: {
1.60 dsl 682: int error;
1.11 jonathan 683:
1.74 dsl 684: error = fsck_preen(diskdev, rootpart, "ffs");
1.11 jonathan 685: if (error != 0)
686: return error;
687:
1.60 dsl 688: /* Mount /dev/<diskdev>a on target's "".
1.51 dsl 689: * If we pass "" as mount-on, Prefixing will DTRT.
1.11 jonathan 690: * for now, use no options.
691: * XXX consider -o remount in case target root is
1.60 dsl 692: * current root, still readonly from single-user?
1.11 jonathan 693: */
1.74 dsl 694: return target_mount("", diskdev, rootpart, "");
695: }
1.11 jonathan 696:
1.74 dsl 697: /* Get information on the file systems mounted from the root filesystem.
698: * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD
699: * inodes. Fsck them. Mount them.
700: */
1.10 jonathan 701:
702: int
1.74 dsl 703: mount_disks(void)
1.59 dsl 704: {
705: char *fstab;
1.10 jonathan 706: int fstabsize;
1.11 jonathan 707: int error;
1.10 jonathan 708:
1.74 dsl 709: static struct lookfor fstabbuf[] = {
710: {"/dev/", "/dev/%s %s ffs %s", "c", NULL, 0, 0, foundffs},
711: {"/dev/", "/dev/%s %s ufs %s", "c", NULL, 0, 0, foundffs},
1.91 tsutsui 712: #ifdef USE_SYSVBFS
713: {"/dev/", "/dev/%s %s sysvbfs %s", "c", NULL, 0, 0,
714: foundsysvbfs},
715: #endif
1.74 dsl 716: };
717: static size_t numfstabbuf = sizeof(fstabbuf) / sizeof(struct lookfor);
718:
1.10 jonathan 719: /* First the root device. */
1.92 dsl 720: if (target_already_root())
721: /* avoid needing to call target_already_root() again */
722: targetroot_mnt[0] = 0;
723: else {
1.74 dsl 724: error = mount_root();
1.51 dsl 725: if (error != 0 && error != EBUSY)
1.10 jonathan 726: return 0;
1.2 phil 727: }
728:
1.11 jonathan 729: /* Check the target /etc/fstab exists before trying to parse it. */
1.51 dsl 730: if (target_dir_exists_p("/etc") == 0 ||
1.16 jonathan 731: target_file_exists_p("/etc/fstab") == 0) {
1.11 jonathan 732: msg_display(MSG_noetcfstab, diskdev);
1.53 dsl 733: process_menu(MENU_ok, NULL);
1.11 jonathan 734: return 0;
735: }
736:
737:
1.10 jonathan 738: /* Get fstab entries from the target-root /etc/fstab. */
1.23 fvdl 739: fstabsize = target_collect_file(T_FILE, &fstab, "/etc/fstab");
1.2 phil 740: if (fstabsize < 0) {
741: /* error ! */
1.11 jonathan 742: msg_display(MSG_badetcfstab, diskdev);
1.53 dsl 743: process_menu(MENU_ok, NULL);
1.2 phil 744: return 0;
745: }
1.74 dsl 746: error = walk(fstab, (size_t)fstabsize, fstabbuf, numfstabbuf);
1.2 phil 747: free(fstab);
748:
1.74 dsl 749: return error;
1.32 fvdl 750: }
751:
752: int
1.65 dsl 753: set_swap(const char *disk, partinfo *pp)
1.32 fvdl 754: {
1.62 dsl 755: int i;
1.58 dsl 756: char *cp;
757: int rval;
1.32 fvdl 758:
1.62 dsl 759: if (pp == NULL)
760: pp = oldlabel;
1.32 fvdl 761:
1.62 dsl 762: for (i = 0; i < MAXPARTITIONS; i++) {
1.58 dsl 763: if (pp[i].pi_fstype != FS_SWAP)
764: continue;
1.65 dsl 765: asprintf(&cp, "/dev/%s%c", disk, 'a' + i);
1.58 dsl 766: rval = swapctl(SWAP_ON, cp, 0);
767: free(cp);
768: if (rval != 0)
769: return -1;
770: }
771:
772: return 0;
773: }
774:
775: int
1.65 dsl 776: check_swap(const char *disk, int remove_swap)
1.58 dsl 777: {
778: struct swapent *swap;
779: char *cp;
780: int nswap;
781: int l;
782: int rval = 0;
783:
784: nswap = swapctl(SWAP_NSWAP, 0, 0);
785: if (nswap <= 0)
786: return 0;
787:
788: swap = malloc(nswap * sizeof *swap);
789: if (swap == NULL)
790: return -1;
791:
792: nswap = swapctl(SWAP_STATS, swap, nswap);
793: if (nswap < 0)
794: goto bad_swap;
795:
1.65 dsl 796: l = strlen(disk);
1.58 dsl 797: while (--nswap >= 0) {
798: /* Should we check the se_dev or se_path? */
799: cp = swap[nswap].se_path;
800: if (memcmp(cp, "/dev/", 5) != 0)
801: continue;
1.65 dsl 802: if (memcmp(cp + 5, disk, l) != 0)
1.58 dsl 803: continue;
804: if (!isalpha(*(unsigned char *)(cp + 5 + l)))
805: continue;
806: if (cp[5 + l + 1] != 0)
807: continue;
808: /* ok path looks like it is for this device */
1.65 dsl 809: if (!remove_swap) {
1.58 dsl 810: /* count active swap areas */
811: rval++;
812: continue;
1.32 fvdl 813: }
1.58 dsl 814: if (swapctl(SWAP_OFF, cp, 0) == -1)
815: rval = -1;
1.32 fvdl 816: }
817:
1.58 dsl 818: done:
819: free(swap);
820: return rval;
821:
822: bad_swap:
823: rval = -1;
824: goto done;
1.1 phil 825: }
1.104 ! tsutsui 826:
! 827: #ifdef HAVE_BOOTXX_xFS
! 828: char *
! 829: bootxx_name(void)
! 830: {
! 831: int fstype;
! 832: const char *bootxxname;
! 833: char *bootxx;
! 834:
! 835: /* check we have boot code for the root partition type */
! 836: fstype = bsdlabel[rootpart].pi_fstype;
! 837: switch (fstype) {
! 838: #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2)
! 839: case FS_BSDFFS:
! 840: if (bsdlabel[rootpart].pi_flags & PIF_FFSv2) {
! 841: #ifdef BOOTXX_FFSV2
! 842: bootxxname = BOOTXX_FFSV2;
! 843: #else
! 844: bootxxname = NULL;
! 845: #endif
! 846: } else {
! 847: #ifdef BOOTXX_FFSV1
! 848: bootxxname = BOOTXX_FFSV1;
! 849: #else
! 850: bootxxname = NULL;
! 851: #endif
! 852: }
! 853: break;
! 854: #endif
! 855: #ifdef BOOTXX_LFS
! 856: case FS_BSDLFS:
! 857: bootxxname = BOOTXX_LFS;
! 858: break;
! 859: #endif
! 860: default:
! 861: bootxxname = NULL;
! 862: break;
! 863: }
! 864:
! 865: if (bootxxname == NULL)
! 866: return NULL;
! 867:
! 868: asprintf(&bootxx, "%s/%s", BOOTXXDIR, bootxxname);
! 869: return bootxx;
! 870: }
! 871: #endif
CVSweb <webmaster@jp.NetBSD.org>