1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2019, Joyent, Inc.
14  * Copyright 2020 Oxide Computer Company
15  */
16 
17 /*
18  * Create /devices links for various sensors. The sensor series of node types
19  * all begin with ddi_sensor. After which, there is a series of : delineated
20  * paths in the node type. Those represent the directory under /dev/sensors that
21  * the nodes should ultimately be created.
22  *
23  * For example, ddi_sensor:temperature:cpu would cause us to place the named
24  * minor under /dev/sensors/temperature/cpu/. Currently it is up to drivers to
25  * not conflict in names or if there is a fear of conflicting, make sure their
26  * minor is unique.
27  */
28 
29 #include <devfsadm.h>
30 #include <string.h>
31 
32 #define	SENSORS_BASE	"sensors"
33 
34 static int
sensor_link(di_minor_t minor,di_node_t node)35 sensor_link(di_minor_t minor, di_node_t node)
36 {
37 	const char *t, *dir_path = NULL;
38 	char *type, *name, *c;
39 	char buf[PATH_MAX];
40 	size_t len;
41 
42 	if ((t = di_minor_nodetype(minor)) == NULL) {
43 		return (DEVFSADM_CONTINUE);
44 	}
45 
46 	if ((type = strdup(t)) == NULL) {
47 		return (DEVFSADM_TERMINATE);
48 	}
49 
50 	c = type;
51 	while ((c = strchr(c, ':')) != NULL) {
52 		if (dir_path == NULL) {
53 			dir_path = c + 1;
54 		}
55 		*c = '/';
56 	}
57 
58 	if ((t = di_minor_name(minor)) == NULL) {
59 		free(type);
60 		return (DEVFSADM_CONTINUE);
61 	}
62 
63 	if ((name = strdup(t)) == NULL) {
64 		free(type);
65 		return (DEVFSADM_TERMINATE);
66 	}
67 
68 	c = name;
69 	while ((c = strchr(c, ':')) != NULL) {
70 		*c = '/';
71 	}
72 
73 
74 	if (dir_path == NULL || *dir_path == '\0') {
75 		len = snprintf(buf, sizeof (buf), "%s/%s", SENSORS_BASE,
76 		    name);
77 	} else {
78 		len = snprintf(buf, sizeof (buf), "%s/%s/%s", SENSORS_BASE,
79 		    dir_path, name);
80 	}
81 
82 	if (len < sizeof (buf)) {
83 		(void) devfsadm_mklink(buf, node, minor, 0);
84 	}
85 
86 	free(type);
87 	free(name);
88 	return (DEVFSADM_CONTINUE);
89 }
90 
91 static devfsadm_create_t sensor_create_cbt[] = {
92 	{ NULL, "ddi_sensor", NULL, TYPE_PARTIAL, ILEVEL_0, sensor_link }
93 };
94 DEVFSADM_CREATE_INIT_V0(sensor_create_cbt);
95