Пример #1
0
void
display(FILE *f, struct disklabel *lp, char unit, int all)
{
	int i, j;
	double d;

	unit = canonical_unit(lp, unit);

	fprintf(f, "# %s:\n", specname);

	if (lp->d_type < DKMAXTYPES)
		fprintf(f, "type: %s\n", dktypenames[lp->d_type]);
	else
		fprintf(f, "type: %d\n", lp->d_type);
	fprintf(f, "disk: %.*s\n", (int)sizeof(lp->d_typename),
	    lp->d_typename);
	fprintf(f, "label: %.*s\n", (int)sizeof(lp->d_packname),
	    lp->d_packname);
	fprintf(f, "duid: %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
            lp->d_uid[0], lp->d_uid[1], lp->d_uid[2], lp->d_uid[3],
            lp->d_uid[4], lp->d_uid[5], lp->d_uid[6], lp->d_uid[7]);
	fprintf(f, "flags:");
	if (lp->d_flags & D_BADSECT)
		fprintf(f, " badsect");
	if (lp->d_flags & D_VENDOR)
		fprintf(f, " vendor");
	putc('\n', f);

	fprintf(f, "bytes/sector: %u\n", lp->d_secsize);
	fprintf(f, "sectors/track: %u\n", lp->d_nsectors);
	fprintf(f, "tracks/cylinder: %u\n", lp->d_ntracks);
	fprintf(f, "sectors/cylinder: %u\n", lp->d_secpercyl);
	fprintf(f, "cylinders: %u\n", lp->d_ncylinders);
	fprintf(f, "total sectors: %llu", DL_GETDSIZE(lp));
	d = scale(DL_GETDSIZE(lp), unit, lp);
	if (d > 0)
		fprintf(f, " # total bytes: %.*f%c", unit == 'B' ? 0 : 1,
		    d, unit);
	fprintf(f, "\n");

	fprintf(f, "boundstart: %llu\n", DL_GETBSTART(lp));
	fprintf(f, "boundend: %llu\n", DL_GETBEND(lp));
	fprintf(f, "drivedata: ");
	for (i = NDDATA - 1; i >= 0; i--)
		if (lp->d_drivedata[i])
			break;
	if (i < 0)
		i = 0;
	for (j = 0; j <= i; j++)
		fprintf(f, "%d ", lp->d_drivedata[j]);
	fprintf(f, "\n");
	if (all) {
		fprintf(f, "\n%hu partitions:\n", lp->d_npartitions);
		fprintf(f, "#    %16.16s %16.16s  fstype [fsize bsize  cpg]\n",
		    "size", "offset");
		for (i = 0; i < lp->d_npartitions; i++)
			display_partition(f, lp, i, unit);
	}
	fflush(f);
}
Пример #2
0
int
edit(struct disklabel *lp, int f)
{
	int first, ch, fd, error = 0;
	struct disklabel label;
	FILE *fp;
	u_int64_t total_sectors, starting_sector, ending_sector;

	if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) {
		if (fd != -1)
			close(fd);
		warn("%s", tmpfil);
		return (1);
	}
	display(fp, lp, 0, 1);
	fprintf(fp, "\n# Notes:\n");
	fprintf(fp,
"# Up to 16 partitions are valid, named from 'a' to 'p'.  Partition 'a' is\n"
"# your root filesystem, 'b' is your swap, and 'c' should cover your whole\n"
"# disk. Any other partition is free for any use.  'size' and 'offset' are\n"
"# in 512-byte blocks. fstype should be '4.2BSD', 'swap', or 'none' or some\n"
"# other values.  fsize/bsize/cpg should typically be '2048 16384 16' for a\n"
"# 4.2BSD filesystem (or '512 4096 16' except on alpha, sun4, ...)\n");
	fclose(fp);
	for (;;) {
		if (editit(tmpfil) == -1)
			break;
		fp = fopen(tmpfil, "r");
		if (fp == NULL) {
			warn("%s", tmpfil);
			break;
		}
		/* Get values set by OS and not the label. */
		if (ioctl(f, DIOCGPDINFO, &label) < 0)
			err(4, "ioctl DIOCGPDINFO");
		ending_sector = DL_GETBEND(&label);
		starting_sector = DL_GETBSTART(&label);
		total_sectors = DL_GETDSIZE(&label);
		memset(&label, 0, sizeof(label));
		error = getasciilabel(fp, &label);
		DL_SETBEND(&label, ending_sector);
		DL_SETBSTART(&label, starting_sector);
		DL_SETDSIZE(&label, total_sectors);

		if (error == 0) {
			if (cmplabel(lp, &label) == 0) {
				puts("No changes.");
				fclose(fp);
				(void) unlink(tmpfil);
				return (0);
			}
			*lp = label;
			if (writelabel(f, bootarea, lp) == 0) {
				fclose(fp);
				(void) unlink(tmpfil);
				return (0);
			}
		}
		fclose(fp);
		printf("re-edit the label? [y]: ");
		fflush(stdout);
		first = ch = getchar();
		while (ch != '\n' && ch != EOF)
			ch = getchar();
		if (first == 'n' || first == 'N')
			break;
	}
	(void)unlink(tmpfil);
	return (1);
}
Пример #3
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));
}
Пример #4
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);
}