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); }
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); }
/* * 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); }