i don't think that there is a convinient OS interface to get partition info.
Code:
/*
* Display DOS partitions.
* (reference: fdisk & wikipedia)
*
* Copyright: ephemera @ daemonforums.org
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <libgen.h>
#include <paths.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define SEC_SIZE 512
#define NDOSPART 4
#define DOSPARTSIZE 16
#define DOSPARTOFF 446
#define PRT_FLAG 0
#define PRT_TYPE 4
#define PRT_START 8
#define PRT_SIZE 12
#define u32dec(v) (*(uint32_t *)(v))
static struct part_type {
uint8_t type;
const char *name;
} part_types[] = {
{0x00, "unused"}
,{0x01, "Primary DOS with 12 bit FAT"}
,{0x02, "XENIX / file system"}
,{0x03, "XENIX /usr file system"}
,{0x04, "Primary DOS with 16 bit FAT (< 32MB)"}
,{0x05, "Extended DOS"}
,{0x06, "Primary 'big' DOS (>= 32MB)"}
,{0x07, "OS/2 HPFS, NTFS, QNX-2 (16 bit) or Advanced UNIX"}
,{0x08, "AIX file system or SplitDrive"}
,{0x09, "AIX boot partition or Coherent"}
,{0x0A, "OS/2 Boot Manager, OPUS or Coherent swap"}
,{0x0B, "DOS or Windows 95 with 32 bit FAT"}
,{0x0C, "DOS or Windows 95 with 32 bit FAT (LBA)"}
,{0x0E, "Primary 'big' DOS (>= 32MB, LBA)"}
,{0x0F, "Extended DOS (LBA)"}
,{0x10, "OPUS"}
,{0x11, "OS/2 BM: hidden DOS with 12-bit FAT"}
,{0x12, "Compaq diagnostics"}
,{0x14, "OS/2 BM: hidden DOS with 16-bit FAT (< 32MB)"}
,{0x16, "OS/2 BM: hidden DOS with 16-bit FAT (>= 32MB)"}
,{0x17, "OS/2 BM: hidden IFS (e.g. HPFS)"}
,{0x18, "AST Windows swapfile"}
,{0x24, "NEC DOS"}
,{0x3C, "PartitionMagic recovery"}
,{0x39, "plan9"}
,{0x40, "VENIX 286"}
,{0x41, "Linux/MINIX (sharing disk with DRDOS)"}
,{0x42, "SFS or Linux swap (sharing disk with DRDOS)"}
,{0x43, "Linux native (sharing disk with DRDOS)"}
,{0x4D, "QNX 4.2 Primary"}
,{0x4E, "QNX 4.2 Secondary"}
,{0x4F, "QNX 4.2 Tertiary"}
,{0x50, "DM (disk manager)"}
,{0x51, "DM6 Aux1 (or Novell)"}
,{0x52, "CP/M or Microport SysV/AT"}
,{0x53, "DM6 Aux3"}
,{0x54, "DM6"}
,{0x55, "EZ-Drive (disk manager)"}
,{0x56, "Golden Bow (disk manager)"}
,{0x5c, "Priam Edisk (disk manager)"} /* according to S. Widlake */
,{0x61, "SpeedStor"}
,{0x63, "System V/386 (such as ISC UNIX), GNU HURD or Mach"}
,{0x64, "Novell Netware/286 2.xx"}
,{0x65, "Novell Netware/386 3.xx"}
,{0x70, "DiskSecure Multi-Boot"}
,{0x75, "PCIX"}
,{0x77, "QNX4.x"}
,{0x78, "QNX4.x 2nd part"}
,{0x79, "QNX4.x 3rd part"}
,{0x80, "Minix until 1.4a"}
,{0x81, "Minix since 1.4b, early Linux partition or Mitac disk manager"}
,{0x82, "Linux swap or Solaris x86"}
,{0x83, "Linux native"}
,{0x84, "OS/2 hidden C: drive"}
,{0x85, "Linux extended"}
,{0x86, "NTFS volume set??"}
,{0x87, "NTFS volume set??"}
,{0x93, "Amoeba file system"}
,{0x94, "Amoeba bad block table"}
,{0x9F, "BSD/OS"}
,{0xA0, "Suspend to Disk"}
,{0xA5, "FreeBSD/NetBSD/386BSD"}
,{0xA6, "OpenBSD"}
,{0xA7, "NeXTSTEP"}
,{0xA9, "NetBSD"}
,{0xAC, "IBM JFS"}
,{0xAF, "HFS+"}
,{0xB7, "BSDI BSD/386 file system"}
,{0xB8, "BSDI BSD/386 swap"}
,{0xBE, "Solaris x86 boot"}
,{0xBF, "Solaris x86 (new)"}
,{0xC1, "DRDOS/sec with 12-bit FAT"}
,{0xC4, "DRDOS/sec with 16-bit FAT (< 32MB)"}
,{0xC6, "DRDOS/sec with 16-bit FAT (>= 32MB)"}
,{0xC7, "Syrinx"}
,{0xDB, "CP/M, Concurrent CP/M, Concurrent DOS or CTOS"}
,{0xE1, "DOS access or SpeedStor with 12-bit FAT extended partition"}
,{0xE3, "DOS R/O or SpeedStor"}
,{0xE4, "SpeedStor with 16-bit FAT extended partition < 1024 cyl."}
,{0xEB, "BeOS file system"}
,{0xEE, "EFI GPT"}
,{0xEF, "EFI System Partition"}
,{0xF1, "SpeedStor"}
,{0xF2, "DOS 3.3+ Secondary"}
,{0xF4, "SpeedStor large partition"}
,{0xFE, "SpeedStor >1024 cyl. or LANstep"}
,{0xFF, "Xenix bad blocks table"}
};
static int is_valid_br(const uint8_t *br);
static int is_ext_prt(const uint8_t *prt);
static int is_zero_prt(const uint8_t *pr);
static const char * get_type(int type);
static void printprt(int partno, const uint8_t *part);
int
main(int argc, char *argv[])
{
char *disk;
uint8_t *mbr_prt_ent, *ebr_prt_ent;
uint8_t mbr[SEC_SIZE], ebr[SEC_SIZE];
int i, fd, lpcnt;
off_t ebr_first, ebr_nxt;
if (argc < 2) {
fprintf(stderr, "Usage: %s disk\n", basename(argv[0]));
exit(1);
}
disk = malloc(sizeof(_PATH_DEV) + strlen(argv[1]));
sprintf(disk, "%s%s", argv[1][0] == '/' ? "" : _PATH_DEV, argv[1]);
if (disk == NULL)
errx(1, "Out of memory.");
fd = open(disk, O_RDONLY);
if (fd < 0)
err(1, "Can't open %s", disk);
if (read(fd, mbr, SEC_SIZE) < 0)
err(1, "Can't read %s", disk);
if (!is_valid_br(mbr))
errx(1, "Invalid MBR on %s.", disk);
printf("%-9s %10s %10s %-4s %s\n"
, "Disk:Part", "Start(sect)", "Size(KB)", "Flag", "Type");
printf("%-9s %10s %10s %-4s %s\n"
, "---------", "-----------", "--------", "----", "----");
printf("%s:\n", basename(disk));
for (i = 0; i < NDOSPART; i++) {
mbr_prt_ent = &mbr[DOSPARTOFF + i * DOSPARTSIZE];
if (!is_zero_prt(mbr_prt_ent))
printprt(i + 1, mbr_prt_ent);
if (is_ext_prt(mbr_prt_ent)) {
/* extended partition */
ebr_first = ebr_nxt = u32dec(&mbr_prt_ent[PRT_START]);
lpcnt = NDOSPART + 1;
do {
/* read in EBR for logical partition */
if (pread(fd, ebr, SEC_SIZE
,ebr_nxt * (off_t)SEC_SIZE) < 0)
err(1, "Can't read EBR");
if (!is_valid_br(ebr)) {
if (lpcnt == NDOSPART + 1)
break;
else
errx(1, "Invalid EBR");
}
/* first partition entry in EBR */
ebr_prt_ent = &ebr[DOSPARTOFF];
u32dec(&ebr_prt_ent[PRT_START]) += ebr_nxt;
printprt(lpcnt++, ebr_prt_ent);
/* second partition entry in EBR */
ebr_prt_ent += DOSPARTSIZE;
ebr_nxt = ebr_first + u32dec(&ebr_prt_ent[PRT_START]);
} while (!is_zero_prt(ebr_prt_ent));
}
}
free(disk);
return 0;
}
static int
is_valid_br(const uint8_t *br)
{
return br[SEC_SIZE - 1] == 0xaa && br[SEC_SIZE - 2] == 0x55;
}
static int
is_ext_prt(const uint8_t *prt)
{
return prt[PRT_TYPE] == 0x0f || prt[PRT_TYPE] == 0x05;
}
/* check for empty partition */
static int
is_zero_prt(const uint8_t *pr)
{
uint32_t *tst = (uint32_t *)pr;
return !(tst[0] | tst[1] | tst[2] | tst[3]);
}
static const char *
get_type(int type)
{
int i, npart_types;
struct part_type *ptr = part_types;
npart_types = sizeof(part_types) / sizeof(struct part_type);
for (i = 0; i < npart_types; i++, ptr++)
if (ptr->type == type)
return ptr->name;
return "?";
}
static void
printprt(int partno, const uint8_t *part)
{
printf("%sp%-*d %10u %10u %-4s (0x%02x) %s\n"
,partno > NDOSPART ? " " : " "
,partno > NDOSPART ? 3 : 5
,partno
,u32dec(&part[PRT_START])
,u32dec(&part[PRT_SIZE]) >> 1 /* assuming SEC_SIZE=512 */
,part[PRT_FLAG] == 0x80 ? "boot" : "-"
,part[PRT_TYPE]
,get_type(part[PRT_TYPE]));
return;
}
AFAIK getting fbsd partition info from an fbsd slice will also require getting down and dirty.