/* $NetBSD: disks.c,v 1.16 1997/12/05 14:01:01 jonathan Exp $ */ /* * Copyright 1997 Piermont Information Systems Inc. * All rights reserved. * * Written by Philip A. Nelson for Piermont Information Systems Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software develooped for the NetBSD Project by * Piermont Information Systems Inc. * 4. The name of Piermont Information Systems Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * */ /* disks.c -- routines to deal with finding disks and labeling disks. */ #include #include #include #include #include #include #include #include #include #include #include "defs.h" #include "md.h" #include "msg_defs.h" #include "menu_defs.h" #include "txtwalk.h" /* Local prototypes */ static void get_disks (void); static void foundffs (struct data *list, int num); static int do_fsck(const char *diskpart); static int fsck_root __P((void)); static void do_ffs_newfs(const char *partname, int part, const char *mountpoint); static int fsck_with_error_menu(const char *diskpart); static int target_mount_with_error_menu(const char *opt, char *diskpart, const char *mntpt); static void get_disks(void) { char **xd = disk_names; char d_name[SSTRSIZE]; struct disklabel l; int i; while (*xd != NULL) { for (i=0; i<5; i++) { sprintf (d_name, "%s%d", *xd, i); if (get_geom (d_name, &l) && numdisks < MAX_DISKS) { strncpy (disks[numdisks].name, d_name, SSTRSIZE); strncat (disknames, d_name, SSTRSIZE-1-strlen(disknames)); strncat (disknames, " ", SSTRSIZE-1-strlen(disknames)); disks[numdisks].geom[0] = l.d_ncylinders; disks[numdisks].geom[1] = l.d_ntracks; disks[numdisks].geom[2] = l.d_nsectors; disks[numdisks].geom[3] = l.d_secsize; disks[numdisks].geom[4] = l.d_secperunit; numdisks++; } } xd++; } } int find_disks (void) { char *tp; char defname[STRSIZE]; int i; /* initialize */ disknames[0] = 0; numdisks = 0; /* Find disks. */ get_disks(); if (numdisks == 0) { /* No disks found! */ msg_display (MSG_nodisk); process_menu (MENU_ok); endwin(); return -1; } else if (numdisks == 1) { /* One disk found! */ /* Remove that space we added. */ disknames[strlen(disknames)-1] = 0; msg_display (MSG_onedisk, disknames, doingwhat); process_menu (MENU_ok); strcpy (diskdev, disknames); } else { /* Multiple disks found! */ strcpy (defname, disknames); tp = defname; strsep(&tp, " "); msg_prompt (MSG_askdisk, defname, diskdev, 10, disknames); tp = diskdev; strsep(&tp, " "); diskdev[strlen(diskdev)+1] = 0; diskdev[strlen(diskdev)] = ' '; while (!ISDISKSTART(*diskdev) || strstr(disknames, diskdev) == NULL) { msg_prompt (MSG_badname, defname, diskdev, 10, disknames); tp = diskdev; strsep(&tp, " "); diskdev[strlen(diskdev)+1] = 0; diskdev[strlen(diskdev)] = ' '; } /* Remove that space we added. */ diskdev[strlen(diskdev)-1] = 0; } /* Set disk. */ for (i=0; igeom[3]; if (disk->geom[4] == 0) disk->geom[4] = disk->geom[0] * disk->geom[1] * disk->geom[2]; return numdisks; } void disp_cur_fspart (int disp, int showall) { int i; int start, stop; if (disp < 0) { start = 0; stop = getmaxpartitions(); } else { start = disp; stop = disp+1; } msg_display_add (MSG_fspart_head); for (i=start; i 0) { msg_printf_add (" %c: %9d %9d %9d %6s", 'a'+i, bsdlabel[i][D_SIZE]/sizemult , bsdlabel[i][D_OFFSET]/sizemult, (bsdlabel[i][D_OFFSET] + bsdlabel[i][D_SIZE])/sizemult, fstype[bsdlabel[i][D_FSTYPE]]); if (bsdlabel[i][D_FSTYPE] == T_42BSD) msg_printf_add ("%6d%6d %s", bsdlabel[i][D_BSIZE], bsdlabel[i][D_FSIZE], fsmount[i]); else if (bsdlabel[i][D_FSTYPE] == T_MSDOS) msg_printf_add ("%12s %s", "", fsmount[i]); msg_printf_add("\n"); } } msg_printf_add("\n"); } /* choose a fake geometry. */ void scsi_fake (void) { long fact[20]; int numf; int geom[5][4] = {{0}}; int i, j; int sects = disk->geom[4]; int head, sec; int stop = disk->geom[0]*disk->geom[1]*disk->geom[2]; i=0; while (i < 4 && sects > stop) { factor (sects, fact, 20, &numf); if (numf >= 3) { head = fact[0]; j = 1; while (j < numf-2 && head*fact[j] < 50) head *= fact[j++]; sec = fact[j++]; while (j < numf-1 && sec*fact[j] < 500) sec *= fact[j++]; if (head >= 5 && sec >= 50) { geom[i][0] = sects / (head*sec); geom[i][1] = head; geom[i][2] = sec; geom[i][3] = head * sec * geom[i][0]; i++; } } sects--; } while (i < 5) { geom[i][0] = disk->geom[0]; geom[i][1] = disk->geom[1]; geom[i][2] = disk->geom[2]; geom[i][3] = stop; i++; } msg_display (MSG_scsi_fake, disk->geom[4], geom[0][0], geom[0][1], geom[0][2], geom[0][3], geom[1][0], geom[1][1], geom[1][2], geom[1][3], geom[2][0], geom[2][1], geom[2][2], geom[2][3], geom[3][0], geom[3][1], geom[3][2], geom[3][3], geom[4][0], geom[4][1], geom[4][2], geom[4][3]); process_menu (MENU_scsi_fake); if (fake_sel >= 0) { dlcyl = disk->geom[0] = geom[fake_sel][0]; dlhead = disk->geom[1] = geom[fake_sel][1]; dlsec = disk->geom[2] = geom[fake_sel][2]; dlsize = disk->geom[4] = geom[fake_sel][3]; } } /* * Label a disk using an MD-specific string DISKLABEL_CMD for * to invoke disklabel. * if MD code does not define DISKLABEL_CMD, this is a no-op. * * i386 port uses "/sbin/disklabel -w -r", just like i386 * miniroot scripts, though this may leave a bogus incore label. * * Sun ports should use DISKLABEL_CMD "/sbin/disklabel -w" * to get incore to ondisk inode translation for the Sun proms. */ void write_disklabel (void) { #ifdef DISKLABEL_CMD /* disklabel the disk */ printf ("%s", msg_string (MSG_dodisklabel)); run_prog_or_continue ("%s %s \"%s\"", DISKLABEL_CMD, diskdev, bsddiskname); #endif } void make_filesystems (void) { int i; char partname[STRSIZE]; /* Making new file systems and mounting them*/ printf ("%s", msg_string (MSG_donewfs)); for (i=0; i 0) { make_target_dir(mountpoint); target_mount("-v", devname, mountpoint); } else target_mount("-v", devname, mountpoint); } } void make_fstab (void) { FILE *f; int i; /* Create the fstab. */ make_target_dir("/etc"); f = target_fopen ("/etc/fstab", "w"); if (f == NULL) { #ifndef DEBUG (void)fprintf (stderr, msg_string (MSG_createfstab)); exit(1); #else f = stdout; #endif } (void)fprintf (f, "/dev/%sa / ffs rw 1 1\n", diskdev); (void)fprintf (f, "/dev/%sb none swap sw 0 0\n", diskdev); for (i=getrawpartition()+1; ia on target's "". * If we pass "" as mount-on, Prefixing will DTRT. * for now, use no options. * XXX consider -o remount in case target root is * current root, still readonly from single-user? */ error = target_mount_with_error_menu("", rootdev, ""); #ifdef DEBUG printf("fsck_root: mount of %s returns %d\n", rootdev, error); #endif return (error); } int fsck_disks (void) { char *fstab; int fstabsize; int i; int error; /* First the root device. */ if (!target_already_root()) { error = fsck_root(); if (error != 0 && error != EBUSY) { return 0; } } /* Check the target /etc/fstab exists before trying to parse it. */ if (target_dir_exists_p("/etc") == 0 || target_file_exists_p("/etc/fstab") == 0) { msg_display(MSG_noetcfstab, diskdev); process_menu(MENU_ok); return 0; } /* Get fstab entries from the target-root /etc/fstab. */ fs_num = 0; fstabsize = target_collect_file (T_FILE, &fstab, "/etc/fstab"); if (fstabsize < 0) { /* error ! */ msg_display(MSG_badetcfstab, diskdev); process_menu(MENU_ok); return 0; } walk (fstab, fstabsize, fstabbuf, numfstabbuf); free(fstab); for (i=0; i < devcnt; i++) { if (fsck_with_error_menu(dev[i])) return 0; #ifdef DEBUG printf("sysinst: mount %s\n", dev[i]); #endif if (target_mount_with_error_menu("", dev[i], mnt[i]) != 0) { return 0; } } return 1; }