/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto doslabel; bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) { error = bp->b_error; goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; doslabel: error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct sun_disklabel *slp; struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; lp->d_flags |= D_VENDOR; /* get a buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto done; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR)); if (error) goto done; slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { error = disklabel_om_to_bsd(slp, lp); goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
int readdpmelabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly) { int i, part_cnt, n, hfspartoff = -1; long long hfspartend = DL_GETDSIZE(lp); struct part_map_entry *part; /* First check for a DPME (HFS) disklabel */ bp->b_blkno = LABELSECTOR; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) return (bp->b_error); /* if successful, wander through DPME partition table */ part = (struct part_map_entry *)bp->b_data; /* if first partition is not valid, assume not HFS/DPME partitioned */ if (part->pmSig != PART_ENTRY_MAGIC) return (EINVAL); /* not a DPME partition */ part_cnt = part->pmMapBlkCnt; n = 8; for (i = 0; i < part_cnt; i++) { struct partition *pp; char *s; bp->b_blkno = LABELSECTOR + i; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) return (bp->b_error); part = (struct part_map_entry *)bp->b_data; /* toupper the string, in case caps are different... */ for (s = part->pmPartType; *s; s++) if ((*s >= 'a') && (*s <= 'z')) *s = (*s - 'a' + 'A'); if (strcmp(part->pmPartType, PART_TYPE_OPENBSD) == 0) { hfspartoff = part->pmPyPartStart; hfspartend = hfspartoff + part->pmPartBlkCnt; if (partoffp) { *partoffp = hfspartoff; return (0); } else { DL_SETBSTART(lp, hfspartoff); DL_SETBEND(lp, hfspartend < DL_GETDSIZE(lp) ? hfspartend : DL_GETDSIZE(lp)); } continue; } if (n >= MAXPARTITIONS || partoffp) continue; /* Currently we spoof HFS partitions only. */ if (strcmp(part->pmPartType, PART_TYPE_MAC) == 0) { pp = &lp->d_partitions[n]; DL_SETPOFFSET(pp, part->pmPyPartStart); DL_SETPSIZE(pp, part->pmPartBlkCnt); pp->p_fstype = FS_HFS; n++; } } if (hfspartoff == -1) return (EINVAL); /* no OpenBSD partition inside DPME label */ if (spoofonly) return (0); /* next, dig out disk label */ bp->b_blkno = hfspartoff; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) return(bp->b_error); /* * Do OpenBSD disklabel validation/adjustment. * * N.B: No matter what the bits are on the disk, we now have the * disklabel for this dpme disk. DO NOT proceed to readdoslabel(), * iso_spooflabel(), * etc. */ checkdisklabel(bp->b_data + LABELOFFSET, lp, hfspartoff, hfspartend); return (0); }
/* * Attempt to read a disk label from a device * using the indicated strategy routine. * The label must be partly set up before this: * secpercyl, secsize and anything required for a block i/o read * operation in the driver's strategy/start routines * must be filled in before calling us. */ int readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, int spoofonly) { struct sun_disklabel *slp; struct buf *bp = NULL; int error; if ((error = initdisklabel(lp))) goto done; lp->d_flags |= D_VENDOR; /* * On sparc64 we check for a CD label first, because our * CD install media contains both sparc & sparc64 labels. * We want the sparc64 machine to find the "CD label", not * the SunOS label, for loading its kernel. */ #if NCD > 0 if (strat == cdstrategy) { #if defined(CD9660) if (iso_disklabelspoof(dev, strat, lp) == 0) goto done; #endif #if defined(UDF) if (udf_disklabelspoof(dev, strat, lp) == 0) goto done; #endif } #endif /* NCD > 0 */ /* get buffer and initialize it */ bp = geteblk((int)lp->d_secsize); bp->b_dev = dev; if (spoofonly) goto doslabel; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR)); if (error) goto done; slp = (struct sun_disklabel *)bp->b_data; if (slp->sl_magic == SUN_DKMAGIC) { error = disklabel_sun_to_bsd(slp, lp); goto done; } error = checkdisklabel(bp->b_data + LABELOFFSET, lp, 0, DL_GETDSIZE(lp)); if (error == 0) goto done; doslabel: error = readdoslabel(bp, strat, lp, NULL, spoofonly); if (error == 0) goto done; /* A CD9660/UDF label may be on a non-CD drive, so recheck */ #if defined(CD9660) error = iso_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif #if defined(UDF) error = udf_disklabelspoof(dev, strat, lp); if (error == 0) goto done; #endif done: if (bp) { bp->b_flags |= B_INVAL; brelse(bp); } disk_change = 1; return (error); }
/* * Given a SunOS disk label, set lp to a BSD disk label. * The BSD label is cleared out before this is called. */ static int disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) { struct sun_preamble *preamble = (struct sun_preamble *)sl; struct sun_partinfo *ppp; struct sun_dkpart *spp; struct partition *npp; u_short cksum = 0, *sp1, *sp2; int i, secpercyl; /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); while (sp1 < sp2) cksum ^= *sp1++; if (cksum != 0) return (EINVAL); /* SunOS disk label, bad checksum */ /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_flags = D_VENDOR; memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); lp->d_secsize = DEV_BSIZE; lp->d_nsectors = sl->sl_nsectors; lp->d_ntracks = sl->sl_ntracks; lp->d_ncylinders = sl->sl_ncylinders; secpercyl = sl->sl_nsectors * sl->sl_ntracks; lp->d_secpercyl = secpercyl; /* If unset or initialized as full disk, permit refinement */ if (DL_GETDSIZE(lp) == 0 || DL_GETDSIZE(lp) == MAXDISKSIZE) DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders); lp->d_version = 1; memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid)); lp->d_acylinders = sl->sl_acylinders; lp->d_npartitions = MAXPARTITIONS; /* These are as defined in <ufs/ffs/fs.h> */ lp->d_bbsize = 8192; /* XXX */ lp->d_sbsize = 8192; /* XXX */ for (i = 0; i < 8; i++) { spp = &sl->sl_part[i]; npp = &lp->d_partitions[i]; DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; } else { npp->p_fstype = sun_fstypes[i]; if (npp->p_fstype == FS_BSDFFS) { /* * The sun label does not store the FFS fields, * so just set them with default values here. */ npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } } /* Clear "extended" partition info, tentatively */ for (i = 0; i < SUNXPART; i++) { npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, 0); DL_SETPSIZE(npp, 0); npp->p_fstype = FS_UNUSED; } /* Check to see if there's an "extended" partition table * SL_XPMAG partitions had checksums up to just before the * (new) sl_types variable, while SL_XPMAGTYP partitions have * checksums up to the just before the (new) sl_xxx1 variable. * Also, disklabels created prior to the addition of sl_uid will * have a checksum to just before the sl_uid variable. */ if ((sl->sl_xpmag == SL_XPMAG && sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) || (sl->sl_xpmag == SL_XPMAGTYP && sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) || (sl->sl_xpmag == SL_XPMAGTYP && sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) { /* * There is. Copy over the "extended" partitions. * This code parallels the loop for partitions a-h. */ for (i = 0; i < SUNXPART; i++) { spp = &sl->sl_xpart[i]; npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; continue; } npp->p_fstype = sun_fstypes[i+8]; if (npp->p_fstype == FS_BSDFFS) { npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } if (sl->sl_xpmag == SL_XPMAGTYP) { for (i = 0; i < MAXPARTITIONS; i++) { npp = &lp->d_partitions[i]; npp->p_fstype = sl->sl_types[i]; npp->p_fragblock = sl->sl_fragblock[i]; npp->p_cpg = sl->sl_cpg[i]; } } } else if (preamble->sl_nparts <= 8) { /* * A more traditional Sun label. Recognise certain filesystem * types from it, if they are available. */ i = preamble->sl_nparts; if (i == 0) i = 8; npp = &lp->d_partitions[i-1]; ppp = &preamble->sl_part[i-1]; for (; i > 0; i--, npp--, ppp--) { if (npp->p_size == 0) continue; if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0)) continue; switch (ppp->spi_tag) { case SPTAG_SUNOS_ROOT: case SPTAG_SUNOS_USR: case SPTAG_SUNOS_VAR: case SPTAG_SUNOS_HOME: npp->p_fstype = FS_BSDFFS; npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; break; case SPTAG_LINUX_EXT2: npp->p_fstype = FS_EXT2FS; break; default: /* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */ npp->p_fstype = FS_UNUSED; break; } } } lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); return (checkdisklabel(lp, lp, 0, DL_GETDSIZE(lp))); }
int readliflabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, int *partoffp, int spoofonly) { struct buf *dbp = NULL; struct lifdir *p; struct lifvol *lvp; int error = 0; int fsoff = 0, openbsdstart = MAXLIFSPACE, i; /* read LIF volume header */ bp->b_blkno = btodb(LIF_VOLSTART); bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) return (bp->b_error); lvp = (struct lifvol *)bp->b_data; if (lvp->vol_id != LIF_VOL_ID) { error = EINVAL; /* no LIF volume header */ goto done; } dbp = geteblk(LIF_DIRSIZE); dbp->b_dev = bp->b_dev; /* read LIF directory */ dbp->b_blkno = lifstodb(lvp->vol_addr); dbp->b_bcount = lp->d_secsize; CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE); SET(dbp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(dbp); if (biowait(dbp)) { error = dbp->b_error; goto done; } /* scan for LIF_DIR_FS dir entry */ for (i=0, p=(struct lifdir *)dbp->b_data; i < LIF_NUMDIR; p++, i++) { if (p->dir_type == LIF_DIR_FS || p->dir_type == LIF_DIR_HPLBL) break; } if (p->dir_type == LIF_DIR_FS) { fsoff = lifstodb(p->dir_addr); openbsdstart = 0; goto finished; } /* Only came here to find the offset... */ if (partoffp) goto finished; if (p->dir_type == LIF_DIR_HPLBL) { struct hpux_label *hl; struct partition *pp; u_int8_t fstype; int i; /* read LIF directory */ dbp->b_blkno = lifstodb(p->dir_addr); dbp->b_bcount = lp->d_secsize; CLR(dbp->b_flags, B_READ | B_WRITE | B_DONE); SET(dbp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(dbp); if (biowait(dbp)) { error = dbp->b_error; goto done; } hl = (struct hpux_label *)dbp->b_data; if (hl->hl_magic1 != hl->hl_magic2 || hl->hl_magic != HPUX_MAGIC || hl->hl_version != 1) { error = EINVAL; /* HPUX label magic mismatch */ goto done; } lp->d_bbsize = 8192; lp->d_sbsize = 8192; for (i = 0; i < MAXPARTITIONS; i++) { DL_SETPSIZE(&lp->d_partitions[i], 0); DL_SETPOFFSET(&lp->d_partitions[i], 0); lp->d_partitions[i].p_fstype = 0; } for (i = 0; i < HPUX_MAXPART; i++) { if (!hl->hl_flags[i]) continue; if (hl->hl_flags[i] == HPUX_PART_ROOT) { pp = &lp->d_partitions[0]; fstype = FS_BSDFFS; } else if (hl->hl_flags[i] == HPUX_PART_SWAP) { pp = &lp->d_partitions[1]; fstype = FS_SWAP; } else if (hl->hl_flags[i] == HPUX_PART_BOOT) { pp = &lp->d_partitions[RAW_PART + 1]; fstype = FS_BSDFFS; } else continue; DL_SETPSIZE(pp, hl->hl_parts[i].hlp_length * 2); DL_SETPOFFSET(pp, hl->hl_parts[i].hlp_start * 2); pp->p_fstype = fstype; } DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp)); DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0); lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; lp->d_npartitions = MAXPARTITIONS; lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_version = 1; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); /* drop through */ } finished: /* record the OpenBSD partition's placement for the caller */ if (partoffp) *partoffp = fsoff; else { DL_SETBSTART(lp, openbsdstart); DL_SETBEND(lp, DL_GETDSIZE(lp)); /* XXX */ } /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly) goto done; bp->b_blkno = fsoff + LABELSECTOR; bp->b_bcount = lp->d_secsize; CLR(bp->b_flags, B_READ | B_WRITE | B_DONE); SET(bp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(bp); if (biowait(bp)) { error = bp->b_error; goto done; } /* * Do OpenBSD disklabel validation/adjustment. * * N.B: No matter what the bits are on the disk, we now have the * OpenBSD disklabel for this lif disk. DO NOT proceed to * readdoslabel(), iso_spooflabel(), etc. */ checkdisklabel(bp->b_data, lp, openbsdstart, DL_GETDSIZE(lp)); error = 0; done: if (dbp) { dbp->b_flags |= B_INVAL; brelse(dbp); } return (error); }
/* * Given a UniOS/ISI disk label, set lp to a BSD disk label. * * The BSD label is cleared out before this is called. */ int disklabel_om_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) { struct partition *npp; struct sun_dkpart *spp; int i, secpercyl; u_short cksum = 0, *sp1, *sp2; /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); while (sp1 < sp2) cksum ^= *sp1++; if (cksum != 0) return (EINVAL); /* UniOS disk label, bad checksum */ /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_flags = D_VENDOR; memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); lp->d_secsize = DEV_BSIZE; lp->d_nsectors = sl->sl_nsectors; lp->d_ntracks = sl->sl_ntracks; lp->d_ncylinders = sl->sl_ncylinders; secpercyl = sl->sl_nsectors * sl->sl_ntracks; lp->d_secpercyl = secpercyl; /* If unset or initialized as full disk, permit refinement */ if (DL_GETDSIZE(lp) == 0 || DL_GETDSIZE(lp) == MAXDISKSIZE) DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders); lp->d_version = 1; memcpy(&lp->d_uid, &sl->sl_uid, sizeof(sl->sl_uid)); lp->d_acylinders = sl->sl_acylinders; lp->d_npartitions = MAXPARTITIONS; /* These are as defined in <ufs/ffs/fs.h> */ lp->d_bbsize = 8192; /* XXX */ lp->d_sbsize = 8192; /* XXX */ for (i = 0; i < 8; i++) { spp = &sl->sl_part[i]; npp = &lp->d_partitions[i]; /* UniOS label uses blkoffset, not cyloffset */ DL_SETPOFFSET(npp, spp->sdkp_cyloffset); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; } else { npp->p_fstype = sun_fstypes[i]; if (npp->p_fstype == FS_BSDFFS) { /* * The sun label does not store the FFS fields, * so just set them with default values here. */ npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } } /* * XXX BandAid XXX * UniOS rootfs sits on part c which don't begin at sect 0, * and impossible to mount. Thus, make it usable as part b. * XXX how to setup a swap partition on disks shared with UniOS??? */ if (sl->sl_rpm == 0 && DL_GETPOFFSET(&lp->d_partitions[2]) != 0) { lp->d_partitions[1] = lp->d_partitions[2]; lp->d_partitions[1].p_fstype = FS_BSDFFS; } /* Clear "extended" partition info, tentatively */ for (i = 0; i < SUNXPART; i++) { npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, 0); DL_SETPSIZE(npp, 0); npp->p_fstype = FS_UNUSED; } /* Check to see if there's an "extended" partition table * SL_XPMAG partitions had checksums up to just before the * (new) sl_types variable, while SL_XPMAGTYP partitions have * checksums up to the just before the (new) sl_xxx1 variable. */ if ((sl->sl_xpmag == SL_XPMAG && sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) || (sl->sl_xpmag == SL_XPMAGTYP && sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) { /* * There is. Copy over the "extended" partitions. * This code parallels the loop for partitions a-h. */ for (i = 0; i < SUNXPART; i++) { spp = &sl->sl_xpart[i]; npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, spp->sdkp_cyloffset); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; continue; } npp->p_fstype = sun_fstypes[i+8]; if (npp->p_fstype == FS_BSDFFS) { npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } if (sl->sl_xpmag == SL_XPMAGTYP) { for (i = 0; i < MAXPARTITIONS; i++) { npp = &lp->d_partitions[i]; npp->p_fstype = sl->sl_types[i]; npp->p_fragblock = sl->sl_fragblock[i]; npp->p_cpg = sl->sl_cpg[i]; } } } lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); return (checkdisklabel(lp, lp, 0, DL_GETDSIZE(lp))); }
int main(int argc, char **argv) { const char *mntfromname, **vfslist, *vfstype; struct fstab *fs; struct statfs *mntbuf; FILE *mountdfp; pid_t pid; int all, ch, i, init_flags, mntsize, rval, have_fstab; char *options; all = init_flags = 0; options = NULL; vfslist = NULL; vfstype = "ufs"; while ((ch = getopt(argc, argv, "adF:fo:prwt:uv")) != -1) { switch (ch) { case 'a': all = 1; break; case 'd': debug = 1; break; case 'F': setfstab(optarg); break; case 'f': init_flags |= MNT_FORCE; break; case 'o': if (*optarg) options = catopt(options, optarg); break; case 'p': fstab_style = 1; verbose = 1; break; case 'r': options = catopt(options, "ro"); break; case 't': if (vfslist != NULL) errx(1, "only one -t option may be specified"); vfslist = makevfslist(optarg); vfstype = optarg; break; case 'u': init_flags |= MNT_UPDATE; break; case 'v': verbose = 1; break; case 'w': options = catopt(options, "noro"); break; case '?': default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; #define BADTYPE(type) \ (strcmp(type, FSTAB_RO) && \ strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) rval = 0; switch (argc) { case 0: if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) err(1, "getmntinfo"); if (all) { while ((fs = getfsent()) != NULL) { if (BADTYPE(fs->fs_type)) continue; if (checkvfsname(fs->fs_vfstype, vfslist)) continue; if (hasopt(fs->fs_mntops, "noauto")) continue; if (!(init_flags & MNT_UPDATE) && ismounted(fs, mntbuf, mntsize)) continue; options = update_options(options, fs->fs_mntops, mntbuf->f_flags); if (mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops)) rval = 1; } } else if (fstab_style) { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; putfsent(&mntbuf[i]); } } else { for (i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; prmount(&mntbuf[i]); } } exit(rval); case 1: if (vfslist != NULL) usage(); rmslashes(*argv, *argv); if (init_flags & MNT_UPDATE) { mntfromname = NULL; have_fstab = 0; if ((mntbuf = getmntpt(*argv)) == NULL) errx(1, "not currently mounted %s", *argv); /* * Only get the mntflags from fstab if both mntpoint * and mntspec are identical. Also handle the special * case where just '/' is mounted and 'spec' is not * identical with the one from fstab ('/dev' is missing * in the spec-string at boot-time). */ if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { if (strcmp(fs->fs_spec, mntbuf->f_mntfromname) == 0 && strcmp(fs->fs_file, mntbuf->f_mntonname) == 0) { have_fstab = 1; mntfromname = mntbuf->f_mntfromname; } else if (argv[0][0] == '/' && argv[0][1] == '\0') { fs = getfsfile("/"); have_fstab = 1; mntfromname = fs->fs_spec; } } if (have_fstab) { options = update_options(options, fs->fs_mntops, mntbuf->f_flags); } else { mntfromname = mntbuf->f_mntfromname; options = update_options(options, NULL, mntbuf->f_flags); } rval = mountfs(mntbuf->f_fstypename, mntfromname, mntbuf->f_mntonname, init_flags, options, 0); break; } if ((fs = getfsfile(*argv)) == NULL && (fs = getfsspec(*argv)) == NULL) errx(1, "%s: unknown special file or file system", *argv); if (BADTYPE(fs->fs_type)) errx(1, "%s has unknown file system type", *argv); rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, init_flags, options, fs->fs_mntops); break; case 2: /* * If -t flag has not been specified, the path cannot be * found. * * If the spec is not a file and contains a ':' then assume * NFS. * * If the spec is a cdev attempt to extract the fstype from * the label. * * When all else fails ufs is assumed. */ if (vfslist == NULL) { if (strpbrk(argv[0], ":") != NULL && access(argv[0], 0) == -1) { vfstype = "nfs"; } else { checkdisklabel(argv[0], &vfstype); } } rval = mountfs(vfstype, getdevpath(argv[0], 0), argv[1], init_flags, options, NULL); break; default: usage(); /* NOTREACHED */ } /* * If the mount was successfully, and done by root, tell mountd the * good news. Pid checks are probably unnecessary, but don't hurt. */ if (rval == 0 && getuid() == 0 && (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { if (fscanf(mountdfp, "%d", &pid) == 1 && pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) err(1, "signal mountd"); fclose(mountdfp); } exit(rval); }
/* * Search for a VDIT volume information. If one is found, search for a * vdmpart instance of name "OpenBSD". If one is found, set the disklabel * bounds to the area it spans, and attempt to read a native label within * it. */ int readvditlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly, struct vdm_boot_info *vbi) { struct buf *sbp = NULL; struct vdit_block_header *vbh; struct vdit_entry_header *veh; char *vdit_storage = NULL, *vdit_end; size_t vdit_size; unsigned int largest_chunk, vdit_blkno; int expected_kind; daddr_t blkno; int error = 0; vdit_id_t *vdmpart_id; struct vdit_vdmpart_instance *bsd_vdmpart; /* * Figure out the size of the first VDIT. */ vdit_size = largest_chunk = 0; expected_kind = VDIT_BLOCK_HEAD_BE; blkno = VDIT_SECTOR; for (;;) { error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, blkno)); if (error) return (error); vbh = (struct vdit_block_header *)bp->b_data; if (VDM_ID_KIND(&vbh->id) != expected_kind || VDM_ID_BLKNO(&vbh->id) != vdit_size || vbh->id.node_number != VDM_NO_NODE_NUMBER) return EINVAL; if (vbi != NULL) { if ((blkno >= vbi->boot_start && blkno < vbi->boot_start + vbi->boot_size) || (blkno + vbh->chunksz - 1 >= vbi->boot_start && blkno + vbh->chunksz - 1 < vbi->boot_start + vbi->boot_size)) return EINVAL; } if (vbh->chunksz > largest_chunk) largest_chunk = vbh->chunksz; vdit_size += vbh->chunksz; if (vbh->nextblk == VDM_NO_BLK_NUMBER) break; blkno = vbh->nextblk; if (blkno >= DL_GETDSIZE(lp)) return EINVAL; expected_kind = VDIT_PORTION_HEADER_BLOCK; } /* * Now read the first VDIT. */ vdit_size *= dbtob(1) - sizeof(struct vdit_block_header); vdit_storage = malloc(vdit_size, M_DEVBUF, M_WAITOK); largest_chunk = dbtob(largest_chunk); sbp = geteblk(largest_chunk); sbp->b_dev = bp->b_dev; vdit_end = vdit_storage; expected_kind = VDIT_BLOCK_HEAD_BE; blkno = VDIT_SECTOR; vdit_blkno = 0; for (;;) { sbp->b_blkno = blkno; sbp->b_bcount = largest_chunk; CLR(sbp->b_flags, B_READ | B_WRITE | B_DONE); SET(sbp->b_flags, B_BUSY | B_READ | B_RAW); (*strat)(sbp); if ((error = biowait(sbp)) != 0) goto done; vbh = (struct vdit_block_header *)sbp->b_data; if (VDM_ID_KIND(&vbh->id) != expected_kind) { error = EINVAL; goto done; } vdit_end = extract_vdit_portion(vdit_end, sbp->b_data, vbh->chunksz, vdit_blkno, expected_kind); if (vdit_end == NULL) { error = EINVAL; goto done; } if (vbh->nextblk == VDM_NO_BLK_NUMBER) break; vdit_blkno += vbh->chunksz; blkno = vbh->nextblk; expected_kind = VDIT_PORTION_HEADER_BLOCK; } /* * Walk the VDIT entries. * * If we find an OpenBSD vdmpart, we'll set our disk area bounds to * its area, and will read a label from there. */ vdmpart_id = NULL; bsd_vdmpart = NULL; veh = (struct vdit_entry_header *)vdit_storage; while ((caddr_t)veh < vdit_end) { switch (veh->type) { case VDIT_ENTRY_SUBDRIVER_INFO: { struct vdit_subdriver_entry *vse; vse = (struct vdit_subdriver_entry *)(veh + 1); if (strcmp(vse->name, VDM_SUBDRIVER_VDMPART) == 0) vdmpart_id = &vse->subdriver_id; } break; case VDIT_ENTRY_INSTANCE: { struct vdit_instance_entry *vie; vie = (struct vdit_instance_entry *)(veh + 1); if (strcmp(vie->name, VDM_INSTANCE_OPENBSD) == 0) { if (vdmpart_id != NULL && memcmp(vdmpart_id, &vie->subdriver_id, sizeof(vdit_id_t)) == 0) { /* found it! */ if (bsd_vdmpart != NULL) { bsd_vdmpart = NULL; veh->type = VDIT_ENTRY_SENTINEL; } else bsd_vdmpart = (struct vdit_vdmpart_instance *)vie; } } } break; } if (veh->type == VDIT_ENTRY_SENTINEL) break; veh = (struct vdit_entry_header *)((char *)veh + veh->size); } if (bsd_vdmpart != NULL) { uint32_t start, size; memcpy(&start, &bsd_vdmpart->start_blkno, sizeof(uint32_t)); memcpy(&size, &bsd_vdmpart->size, sizeof(uint32_t)); if (start >= DL_GETDSIZE(lp) || start + size > DL_GETDSIZE(lp)) { error = EINVAL; goto done; } if (partoffp != NULL) { *partoffp = start; goto done; } else { DL_SETBSTART(lp, start); DL_SETBEND(lp, start + size); } /* * Now read the native label. */ if (spoofonly == 0) { error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, start + LABELSECTOR)); if (error) goto done; error = checkdisklabel(bp->b_data + LABELOFFSET, lp, start, start + size); } } else { /* * VDM label, but no OpenBSD vdmpart partition found. * XXX is it worth registering the whole disk as a * XXX `don't touch' vendor partition in that case? */ error = ENOENT; goto done; } done: free(vdit_storage, M_DEVBUF, vdit_size); if (sbp != NULL) { sbp->b_flags |= B_INVAL; brelse(sbp); } return error; }
/* * Search for a VDM "label" (which does not describe any partition). * If one is found, search for either a VDIT label, or a native OpenBSD * label in the first sector. */ int readvdmlabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly) { struct vdm_label *vdl; struct vdm_boot_info *vbi; int error = 0; /* * Read first sector and check for a VDM label. * Note that a VDM label is only required for bootable disks, and * may not be followed by a VDIT. */ error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, VDM_LABEL_SECTOR)); if (error) return (error); vdl = (struct vdm_label *)(bp->b_data + VDM_LABEL_OFFSET); if (vdl->signature != VDM_LABEL_SIGNATURE) vdl = (struct vdm_label *)(bp->b_data + VDM_LABEL_OFFSET_ALT); if (vdl->signature != VDM_LABEL_SIGNATURE) return EINVAL; /* * If the disk is a bootable disk, remember the boot block area, to * be able to check that the VDIT does not overwrite it. */ vbi = (struct vdm_boot_info *)(bp->b_data + dbtob(1) - sizeof *vbi); if (vbi->signature != VDM_LABEL_SIGNATURE || vbi->boot_start == 0) vbi = NULL; if (vbi != NULL && vbi->boot_start == VDIT_SECTOR) return EINVAL; if (vbi != NULL && vbi->boot_start + vbi->boot_size > DL_GETBSTART(lp)) DL_SETBSTART(lp, vbi->boot_start + vbi->boot_size); error = readvditlabel(bp, strat, lp, partoffp, spoofonly, vbi); if (error == 0) return 0; /* * Valid VDIT information, but no OpenBSD vdmpart found. * Do not try to read a native label. */ if (error == ENOENT) return error; if (partoffp != NULL) *partoffp = 0; /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly != 0) return 0; error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR)); if (error) return (error); return checkdisklabel(bp->b_data + LABELOFFSET, lp, DL_GETBSTART(lp), DL_GETBEND(lp)); }
int readsgilabel(struct buf *bp, void (*strat)(struct buf *), struct disklabel *lp, daddr_t *partoffp, int spoofonly) { struct sgilabel *dlp; int i, *p, cs = 0; daddr_t fsoffs, fsend; int error, offset; /* if successful, locate disk label within block and validate */ error = readdisksector(bp, strat, lp, 0); if (error) return (error); fsoffs = DL_SECTOBLK(lp, DL_GETBSTART(lp)); fsend = DL_SECTOBLK(lp, DL_GETBEND(lp)); dlp = (struct sgilabel *)(bp->b_data + LABELOFFSET); if (dlp->magic != htobe32(SGILABEL_MAGIC)) goto finished; if (dlp->partitions[0].blocks == 0) return (EINVAL); fsoffs = (long long)dlp->partitions[0].first; fsend = fsoffs + dlp->partitions[0].blocks; /* Only came here to find the offset... */ if (partoffp) { *partoffp = fsoffs; goto finished; } p = (int *)dlp; i = sizeof(struct sgilabel) / sizeof(int); while (i--) cs += *p++; if (cs != 0) return (EINVAL); /* sgilabel checksum error */ /* Spoof info from sgi label, in case there is no OpenBSD label. */ lp->d_npartitions = MAXPARTITIONS; for (i = 0; i < 16; i++) { int bsd = maptab[i].m; int type = maptab[i].b; if (spoofonly && type != FS_UNUSED && type != FS_OTHER) continue; DL_SETPOFFSET(&lp->d_partitions[bsd], dlp->partitions[i].first); DL_SETPSIZE(&lp->d_partitions[bsd], dlp->partitions[i].blocks); lp->d_partitions[bsd].p_fstype = type; if (type == FS_BSDFFS) { lp->d_partitions[bsd].p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(1024, 8); lp->d_partitions[bsd].p_cpg = 16; } } DL_SETBSTART(lp, DL_BLKTOSEC(lp, fsoffs)); DL_SETBEND(lp, DL_BLKTOSEC(lp, fsend)); lp->d_version = 1; lp->d_flags = D_VENDOR; lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); finished: /* record the OpenBSD partition's placement for the caller */ if (partoffp) *partoffp = fsoffs; else { DL_SETBSTART(lp, DL_BLKTOSEC(lp, fsoffs)); DL_SETBEND(lp, DL_BLKTOSEC(lp, fsend)); } /* don't read the on-disk label if we are in spoofed-only mode */ if (spoofonly) return (0); error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, fsoffs + LABELSECTOR)); if (error) return (error); offset = DL_BLKOFFSET(lp, fsoffs + LABELSECTOR) + LABELOFFSET; /* * Do OpenBSD disklabel validation/adjustment. * * N.B: No matter what the bits are on the disk, we now have the * OpenBSD disklabel for this sgi disk. DO NOT proceed to * readdoslabel(), iso_spooflabel(), etc. */ checkdisklabel(bp->b_data + offset, lp, fsoffs, fsend); return (0); }