#include <sys/types.h>
#include <sys/disk.h>
#include <sys/dkio.h>
#define DKTYPENAMES
#include <sys/disklabel.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <fcntl.h>
#include <paths.h>
#include <string.h>
#include <unistd.h>
#include "util.h"
char *
readlabelfs(char *device, int verbose)
{
char rpath[PATH_MAX];
struct dk_diskmap dm;
struct disklabel dk;
char part, *type;
struct stat sbuf;
int fd = -1, partno;
if (isduid(device, 0)) {
if ((fd = open("/dev/diskmap", O_RDONLY|O_CLOEXEC)) != -1) {
bzero(&dm, sizeof(struct dk_diskmap));
strlcpy(rpath, device, sizeof(rpath));
part = rpath[strlen(rpath) - 1];
dm.device = rpath;
dm.fd = fd;
dm.flags = DM_OPENPART;
if (ioctl(fd, DIOCMAP, &dm) == -1)
close(fd);
else
goto disklabel;
}
}
if (stat(device, &sbuf) == -1) {
if (verbose)
warn("%s", device);
return (NULL);
}
switch (sbuf.st_mode & S_IFMT) {
case S_IFCHR:
strlcpy(rpath, device, sizeof(rpath));
part = rpath[strlen(rpath) - 1];
rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
break;
case S_IFBLK:
if (strlen(device) > sizeof(_PATH_DEV) - 1) {
snprintf(rpath, sizeof(rpath), "%sr%s", _PATH_DEV,
&device[sizeof(_PATH_DEV) - 1]);
part = rpath[strlen(rpath) - 1];
rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
break;
}
default:
if (verbose)
warnx("%s: not a device node", device);
return (NULL);
}
fd = open(rpath, O_RDONLY|O_CLOEXEC);
if (fd == -1) {
if (errno == ENOENT) {
rpath[strlen(rpath) - 1] = part;
fd = open(rpath, O_RDONLY|O_CLOEXEC);
if (fd == -1) {
if (verbose)
warn("%s", rpath);
return (NULL);
}
} else {
if (verbose)
warn("%s", rpath);
return (NULL);
}
}
disklabel:
partno = DL_PARTNAME2NUM(part);
if (partno == -1) {
if (verbose)
warn("%s: diskmap provided weird partition", rpath);
close(fd);
return NULL;
}
if (ioctl(fd, DIOCGDINFO, &dk) == -1) {
if (verbose)
warn("%s: couldn't read disklabel", rpath);
close(fd);
return (NULL);
}
close(fd);
if (dk.d_partitions[partno].p_fstype >= FSMAXTYPES) {
if (verbose)
warnx("%s: bad filesystem type in label", rpath);
return (NULL);
}
type = fstypesnames[dk.d_partitions[partno].p_fstype];
return ((type[0] == '\0') ? NULL : type);
}