#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libdevinfo.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "amdzen_common.h"
int
amdzen_open_device(const char *driver, const char *arg, int oflag)
{
struct stat st;
di_node_t root, node;
di_minor_t minor;
const char *errstr, *id;
char mname[64];
char *bpath, *path;
size_t drvlen;
int df, fd;
id = arg;
drvlen = strlen(driver);
if (strncmp(id, driver, drvlen) == 0)
id += drvlen;
df = (int)strtonumx(id, 0, INT_MAX, &errstr, 0);
if (errstr != NULL) {
if ((fd = open(arg, oflag)) < 0) {
warn("failed to open %s", arg);
return (-1);
}
if (fstat(fd, &st) != 0) {
warn("failed to stat %s", arg);
(void) close(fd);
return (-1);
}
if (!S_ISCHR(st.st_mode)) {
warnx("%s is not a character device", arg);
(void) close(fd);
return (-1);
}
return (fd);
}
root = di_init_driver(driver, DINFOSUBTREE | DINFOMINOR);
if (root == DI_NODE_NIL) {
warn("failed to take a devinfo snapshot with %s attached",
driver);
return (-1);
}
node = di_drv_first_node(driver, root);
if (node == DI_NODE_NIL) {
warnx("failed to find a devinfo node for %s", driver);
di_fini(root);
return (-1);
}
(void) snprintf(mname, sizeof (mname), "%s.%d", driver, df);
minor = DI_MINOR_NIL;
while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
if (strcmp(di_minor_name(minor), mname) == 0)
break;
}
if (minor == DI_MINOR_NIL) {
warnx("failed to find minor %s on %s%d -- no such DF?",
mname, di_driver_name(node), di_instance(node));
di_fini(root);
return (-1);
}
bpath = di_devfs_minor_path(minor);
if (bpath == NULL) {
warn("failed to get minor path for %s%d:%s",
di_driver_name(node), di_instance(node),
di_minor_name(minor));
di_fini(root);
return (-1);
}
if (asprintf(&path, "/devices%s", bpath) < 0) {
warn("failed to construct full path for %s", bpath);
di_devfs_path_free(bpath);
di_fini(root);
return (-1);
}
di_devfs_path_free(bpath);
di_fini(root);
if ((fd = open(path, oflag)) < 0)
warn("failed to open %s", path);
free(path);
return (fd);
}