#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/disklabel.h>
#include <sys/disk.h>
int readdpmelabel(struct buf *, void (*)(struct buf *),
struct disklabel *, daddr_t *, int);
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;
bp = geteblk(lp->d_secsize);
bp->b_dev = dev;
error = readdpmelabel(bp, strat, lp, NULL, spoofonly);
if (error == 0)
goto done;
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);
}
int
readdpmelabel(struct buf *bp, void (*strat)(struct buf *),
struct disklabel *lp, daddr_t *partoffp, int spoofonly)
{
int error, i, part_cnt, n, hfspartoff = -1;
long long hfspartend = DL_GETDSIZE(lp);
struct part_map_entry *part;
error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, LABELSECTOR));
if (error)
return (error);
part = (struct part_map_entry *)bp->b_data;
if (part->pmSig != PART_ENTRY_MAGIC)
return (EINVAL);
part_cnt = part->pmMapBlkCnt;
n = 8;
for (i = 0; i < part_cnt; i++) {
struct partition *pp;
char *s;
error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp,
LABELSECTOR + i));
if (error)
return (error);
part = (struct part_map_entry *)bp->b_data;
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;
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);
if (spoofonly)
return (0);
error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, hfspartoff));
if (error)
return (error);
error = checkdisklabel(bp->b_dev, bp->b_data + LABELOFFSET, lp,
hfspartoff, hfspartend);
return (error);
}
int
writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
{
daddr_t partoff = -1;
int error = EIO;
int offset;
struct disklabel *dlp;
struct buf *bp = NULL;
bp = geteblk(lp->d_secsize);
bp->b_dev = dev;
if (readdpmelabel(bp, strat, lp, &partoff, 1) == 0) {
error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, partoff));
offset = 0;
} else if (readdoslabel(bp, strat, lp, &partoff, 1) == 0) {
error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp,
partoff + DOS_LABELSECTOR));
offset = DL_BLKOFFSET(lp, partoff + DOS_LABELSECTOR);
} else
goto done;
if (error)
goto done;
dlp = (struct disklabel *)(bp->b_data + offset);
*dlp = *lp;
CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
(*strat)(bp);
error = biowait(bp);
done:
if (bp) {
bp->b_flags |= B_INVAL;
brelse(bp);
}
disk_change = 1;
return (error);
}