示例#1
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 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);
}
示例#2
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;

	/* 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);
}
示例#3
0
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);
}
示例#4
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);
}
示例#5
0
/*
 * 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)));
}
示例#6
0
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);
}
示例#7
0
/*
 * 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)));
}
示例#8
0
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);
}
示例#9
0
/*
 * 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;
}
示例#10
0
/*
 * 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));
}
示例#11
0
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);
}