static int init_dev(dev_info_t* dev) { char buffer[BSD_LABEL_BUFFER]; struct disklabel *dl; uint64_t bs; int ok; devinfo = dev; dmadat = &__dmadat; /* * First try offset 0. This is the typical GPT case where we have no * further partitioning (as well as the degenerate MBR case where * the bsdlabel has a 0 offset). */ devinfo->partoff = 0; ok = fsread(0, NULL, 0); if (ok >= 0) return (ok); /* * Next, we look for a bsdlabel. This is technically located in sector * 1. For 4k sectors, this offset is 4096, for 512b sectors it's * 512. However, we have to fall back to 512 here because we create * images that assume 512 byte blocks, but these can be put on devices * who have 4k (or other) block sizes. If there's a crazy block size, we * skip the 'at one sector' and go stright to checking at 512 bytes. * There are other offsets that are historic, but we don't probe those * since they were never used for MBR disks on FreeBSD on systems that * could boot UEFI. UEFI is little endian only, as are BSD labels. We * will retry fsread(0) only if there's a label found with a non-zero * offset. */ if (dskread(buffer, 0, BSD_LABEL_BUFFER / DEV_BSIZE) != 0) return (-1); dl = NULL; bs = devinfo->dev->Media->BlockSize; if (bs != 0 && bs <= BSD_LABEL_BUFFER / 2) dl = (struct disklabel *)&buffer[bs]; if (dl == NULL || dl->d_magic != BSD_MAGIC || dl->d_magic2 != BSD_MAGIC) dl = (struct disklabel *)&buffer[BSD_LABEL_OFFSET]; if (dl->d_magic != BSD_MAGIC || dl->d_magic2 != BSD_MAGIC || dl->d_partitions[0].p_offset == 0) return (-1); devinfo->partoff = dl->d_partitions[0].p_offset; return (fsread(0, NULL, 0)); }
static ssize_t fsstat(ufs_ino_t inode) { #ifndef UFS2_ONLY static struct ufs1_dinode dp1; #endif #ifndef UFS1_ONLY static struct ufs2_dinode dp2; #endif static struct fs fs; static ufs_ino_t inomap; char *blkbuf; void *indbuf; size_t n, size; static ufs2_daddr_t blkmap, indmap; blkbuf = dmadat->blkbuf; indbuf = dmadat->indbuf; if (!dsk_meta) { inomap = 0; for (n = 0; sblock_try[n] != -1; n++) { if (dskread(dmadat->sbbuf, sblock_try[n] / DEV_BSIZE, SBLOCKSIZE / DEV_BSIZE)) return -1; memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); if (( #if defined(UFS1_ONLY) fs.fs_magic == FS_UFS1_MAGIC #elif defined(UFS2_ONLY) (fs.fs_magic == FS_UFS2_MAGIC && fs.fs_sblockloc == sblock_try[n]) #else fs.fs_magic == FS_UFS1_MAGIC || (fs.fs_magic == FS_UFS2_MAGIC && fs.fs_sblockloc == sblock_try[n]) #endif ) && fs.fs_bsize <= MAXBSIZE && fs.fs_bsize >= (int32_t)sizeof(struct fs)) break; } if (sblock_try[n] == -1) { return -1; } dsk_meta++; } else memcpy(&fs, dmadat->sbbuf, sizeof(struct fs)); if (!inode) return 0; if (inomap != inode) { n = IPERVBLK(&fs); if (dskread(blkbuf, INO_TO_VBA(&fs, n, inode), DBPERVBLK)) return -1; n = INO_TO_VBO(n, inode); #if defined(UFS1_ONLY) memcpy(&dp1, (struct ufs1_dinode *)blkbuf + n, sizeof(struct ufs1_dinode)); #elif defined(UFS2_ONLY) memcpy(&dp2, (struct ufs2_dinode *)blkbuf + n, sizeof(struct ufs2_dinode)); #else if (fs.fs_magic == FS_UFS1_MAGIC) memcpy(&dp1, (struct ufs1_dinode *)(void *)blkbuf + n, sizeof(struct ufs1_dinode)); else memcpy(&dp2, (struct ufs2_dinode *)(void *)blkbuf + n, sizeof(struct ufs2_dinode)); #endif inomap = inode; fs_off = 0; blkmap = indmap = 0; } size = DIP(di_size); n = size - fs_off; return (n); }