xref: /freebsd/usr.sbin/sesutil/sesutil.c (revision 4569e7cfe25b562e09629471fc645262bc726f8c)
1cddcb259SBaptiste Daroussin /*-
2cddcb259SBaptiste Daroussin  * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
3cddcb259SBaptiste Daroussin  * All rights reserved.
4cddcb259SBaptiste Daroussin  *
5cddcb259SBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
6cddcb259SBaptiste Daroussin  * modification, are permitted provided that the following conditions
7cddcb259SBaptiste Daroussin  * are met:
8cddcb259SBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
9cddcb259SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer
10cddcb259SBaptiste Daroussin  *    in this position and unchanged.
11cddcb259SBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
12cddcb259SBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
13cddcb259SBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
14cddcb259SBaptiste Daroussin  *
15cddcb259SBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16cddcb259SBaptiste Daroussin  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17cddcb259SBaptiste Daroussin  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18cddcb259SBaptiste Daroussin  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19cddcb259SBaptiste Daroussin  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20cddcb259SBaptiste Daroussin  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21cddcb259SBaptiste Daroussin  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22cddcb259SBaptiste Daroussin  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23cddcb259SBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24cddcb259SBaptiste Daroussin  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25cddcb259SBaptiste Daroussin  */
26cddcb259SBaptiste Daroussin 
27cddcb259SBaptiste Daroussin #include <sys/cdefs.h>
28cddcb259SBaptiste Daroussin __FBSDID("$FreeBSD$");
29cddcb259SBaptiste Daroussin 
30cddcb259SBaptiste Daroussin #include <sys/param.h>
31cddcb259SBaptiste Daroussin #include <sys/ioctl.h>
32cddcb259SBaptiste Daroussin 
33cddcb259SBaptiste Daroussin #include <err.h>
34cddcb259SBaptiste Daroussin #include <errno.h>
35cddcb259SBaptiste Daroussin #include <fcntl.h>
36cddcb259SBaptiste Daroussin #include <glob.h>
37cddcb259SBaptiste Daroussin #include <stdbool.h>
38cddcb259SBaptiste Daroussin #include <stddef.h>
39cddcb259SBaptiste Daroussin #include <stdint.h>
40cddcb259SBaptiste Daroussin #include <stdio.h>
41cddcb259SBaptiste Daroussin #include <stdlib.h>
42cddcb259SBaptiste Daroussin #include <string.h>
43cddcb259SBaptiste Daroussin #include <unistd.h>
44cddcb259SBaptiste Daroussin 
45cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_all.h>
46cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h>
47cddcb259SBaptiste Daroussin 
48cddcb259SBaptiste Daroussin static int locate(int argc, char **argv);
49cddcb259SBaptiste Daroussin 
50cddcb259SBaptiste Daroussin static struct command {
51cddcb259SBaptiste Daroussin 	const char *name;
52cddcb259SBaptiste Daroussin 	const char *desc;
53cddcb259SBaptiste Daroussin 	int (*exec)(int argc, char **argv);
54cddcb259SBaptiste Daroussin } cmds[] = {
55cddcb259SBaptiste Daroussin 	{ "locate", "Change the state of the external LED associated with a"
56cddcb259SBaptiste Daroussin 	    " disk", locate} ,
57cddcb259SBaptiste Daroussin };
58cddcb259SBaptiste Daroussin 
59cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds);
60cddcb259SBaptiste Daroussin 
61cddcb259SBaptiste Daroussin static void
62cddcb259SBaptiste Daroussin do_locate(int fd, unsigned int idx, bool onoff)
63cddcb259SBaptiste Daroussin {
64cddcb259SBaptiste Daroussin 	encioc_elm_status_t o;
65cddcb259SBaptiste Daroussin 
66cddcb259SBaptiste Daroussin 	o.elm_idx = idx;
67cddcb259SBaptiste Daroussin 	if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) {
68cddcb259SBaptiste Daroussin 		close(fd);
69cddcb259SBaptiste Daroussin 		err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
70cddcb259SBaptiste Daroussin 	}
71cddcb259SBaptiste Daroussin 	o.cstat[0] |= 0x80;
72cddcb259SBaptiste Daroussin 	if (onoff)
73cddcb259SBaptiste Daroussin 		o.cstat[2] |= 0x02;
74cddcb259SBaptiste Daroussin 	else
75cddcb259SBaptiste Daroussin 		o.cstat[2] &= 0xfd;
76cddcb259SBaptiste Daroussin 
77cddcb259SBaptiste Daroussin 	if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
78cddcb259SBaptiste Daroussin 		close(fd);
79cddcb259SBaptiste Daroussin 		err(EXIT_FAILURE, "ENCIOC_SETELMSTAT");
80cddcb259SBaptiste Daroussin 	}
81cddcb259SBaptiste Daroussin }
82cddcb259SBaptiste Daroussin 
83cddcb259SBaptiste Daroussin static bool
84cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len)
85cddcb259SBaptiste Daroussin {
86cddcb259SBaptiste Daroussin 	const char *devname;
87cddcb259SBaptiste Daroussin 
88cddcb259SBaptiste Daroussin 	devname = devnames;
89cddcb259SBaptiste Daroussin 	while ((devname = strstr(devname, disk)) != NULL) {
90cddcb259SBaptiste Daroussin 		if (devname[len] == '\0' || devname[len] == ',')
91cddcb259SBaptiste Daroussin 			return (true);
92cddcb259SBaptiste Daroussin 		devname++;
93cddcb259SBaptiste Daroussin 	}
94cddcb259SBaptiste Daroussin 	return (false);
95cddcb259SBaptiste Daroussin }
96cddcb259SBaptiste Daroussin 
97cddcb259SBaptiste Daroussin static int
98cddcb259SBaptiste Daroussin locate(int argc, char **argv)
99cddcb259SBaptiste Daroussin {
100cddcb259SBaptiste Daroussin 	encioc_elm_devnames_t objdn;
101cddcb259SBaptiste Daroussin 	encioc_element_t *objp;
102cddcb259SBaptiste Daroussin 	glob_t g;
103cddcb259SBaptiste Daroussin 	char *disk;
104cddcb259SBaptiste Daroussin 	size_t len, i;
105cddcb259SBaptiste Daroussin 	int fd, nobj, j;
106cddcb259SBaptiste Daroussin 	bool all = false;
107*4569e7cfSBaptiste Daroussin 	bool onoff;
108cddcb259SBaptiste Daroussin 
109cddcb259SBaptiste Daroussin 	if (argc != 2) {
110cddcb259SBaptiste Daroussin 		errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
111cddcb259SBaptiste Daroussin 		    getprogname());
112cddcb259SBaptiste Daroussin 	}
113cddcb259SBaptiste Daroussin 
114cddcb259SBaptiste Daroussin 	disk = argv[0];
115cddcb259SBaptiste Daroussin 
116cddcb259SBaptiste Daroussin 	if (strcmp(argv[1], "on") == 0) {
117*4569e7cfSBaptiste Daroussin 		onoff = true;
118cddcb259SBaptiste Daroussin 	} else if (strcmp(argv[1], "off") == 0) {
119*4569e7cfSBaptiste Daroussin 		onoff = false;
120cddcb259SBaptiste Daroussin 	} else {
121cddcb259SBaptiste Daroussin 		errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
122cddcb259SBaptiste Daroussin 		    getprogname());
123cddcb259SBaptiste Daroussin 	}
124cddcb259SBaptiste Daroussin 
125cddcb259SBaptiste Daroussin 	if (strcmp(disk, "all") == 0) {
126cddcb259SBaptiste Daroussin 		all = true;
127cddcb259SBaptiste Daroussin 	}
128cddcb259SBaptiste Daroussin 	len = strlen(disk);
129cddcb259SBaptiste Daroussin 
130cddcb259SBaptiste Daroussin 	/* Get the list of ses devices */
131cddcb259SBaptiste Daroussin 	if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) {
132cddcb259SBaptiste Daroussin 		globfree(&g);
133cddcb259SBaptiste Daroussin 		errx(EXIT_FAILURE, "No SES devices found");
134cddcb259SBaptiste Daroussin 	}
135cddcb259SBaptiste Daroussin 	for (i = 0; i < g.gl_pathc; i++) {
136cddcb259SBaptiste Daroussin 		/* ensure we only got numbers after ses */
137cddcb259SBaptiste Daroussin 		if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
138cddcb259SBaptiste Daroussin 		    strlen(g.gl_pathv[i] + 8))
139cddcb259SBaptiste Daroussin 			continue;
140cddcb259SBaptiste Daroussin 		if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
141cddcb259SBaptiste Daroussin 			if (errno == EACCES)
142cddcb259SBaptiste Daroussin 				err(EXIT_FAILURE, "enable to access SES device");
143cddcb259SBaptiste Daroussin 			break;
144cddcb259SBaptiste Daroussin 		}
145cddcb259SBaptiste Daroussin 
146cddcb259SBaptiste Daroussin 		if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0)
147cddcb259SBaptiste Daroussin 			err(EXIT_FAILURE, "ENCIOC_GETNELM");
148cddcb259SBaptiste Daroussin 
149cddcb259SBaptiste Daroussin 		objp = calloc(nobj, sizeof(encioc_element_t));
150cddcb259SBaptiste Daroussin 		if (objp == NULL)
151cddcb259SBaptiste Daroussin 			err(EXIT_FAILURE, "calloc()");
152cddcb259SBaptiste Daroussin 
153cddcb259SBaptiste Daroussin 		if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0)
154cddcb259SBaptiste Daroussin 			err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
155cddcb259SBaptiste Daroussin 
156cddcb259SBaptiste Daroussin 		for (j = 0; j < nobj; j++) {
157cddcb259SBaptiste Daroussin 			memset(&objdn, 0, sizeof(objdn));
158cddcb259SBaptiste Daroussin 			objdn.elm_idx = objp[j].elm_idx;
159cddcb259SBaptiste Daroussin 			objdn.elm_names_size = 128;
160cddcb259SBaptiste Daroussin 			objdn.elm_devnames = calloc(128, sizeof(char));
161cddcb259SBaptiste Daroussin 			if (objdn.elm_devnames == NULL)
162cddcb259SBaptiste Daroussin 				err(EXIT_FAILURE, "calloc()");
163cddcb259SBaptiste Daroussin 			if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
164cddcb259SBaptiste Daroussin 			    (caddr_t) &objdn) <0)
165cddcb259SBaptiste Daroussin 				continue;
166cddcb259SBaptiste Daroussin 			if (objdn.elm_names_len > 0) {
167cddcb259SBaptiste Daroussin 				if (all) {
168*4569e7cfSBaptiste Daroussin 					do_locate(fd, objdn.elm_idx, onoff);
169cddcb259SBaptiste Daroussin 					continue;
170cddcb259SBaptiste Daroussin 				}
171cddcb259SBaptiste Daroussin 				if (disk_match(objdn.elm_devnames, disk, len)) {
172*4569e7cfSBaptiste Daroussin 					do_locate(fd, objdn.elm_idx, onoff);
173cddcb259SBaptiste Daroussin 					break;
174cddcb259SBaptiste Daroussin 				}
175cddcb259SBaptiste Daroussin 			}
176cddcb259SBaptiste Daroussin 		}
177cddcb259SBaptiste Daroussin 		close(fd);
178cddcb259SBaptiste Daroussin 		i++;
179cddcb259SBaptiste Daroussin 	}
180cddcb259SBaptiste Daroussin 	globfree(&g);
181cddcb259SBaptiste Daroussin 
182cddcb259SBaptiste Daroussin 	return (EXIT_SUCCESS);
183cddcb259SBaptiste Daroussin }
184cddcb259SBaptiste Daroussin 
185cddcb259SBaptiste Daroussin static void
186cddcb259SBaptiste Daroussin usage(FILE *out)
187cddcb259SBaptiste Daroussin {
188cddcb259SBaptiste Daroussin 	int i;
189cddcb259SBaptiste Daroussin 
190cddcb259SBaptiste Daroussin 	fprintf(out, "Usage: %s [command] [options]\n", getprogname());
191cddcb259SBaptiste Daroussin 	fprintf(out, "Commands supported:\n");
192cddcb259SBaptiste Daroussin 	for (i = 0; i < nbcmds; i++)
193cddcb259SBaptiste Daroussin 		fprintf(out, "\t%-15s%s\n", cmds[i].name, cmds[i].desc);
194cddcb259SBaptiste Daroussin }
195cddcb259SBaptiste Daroussin 
196cddcb259SBaptiste Daroussin int
197cddcb259SBaptiste Daroussin main(int argc, char **argv)
198cddcb259SBaptiste Daroussin {
199cddcb259SBaptiste Daroussin 	int i;
200cddcb259SBaptiste Daroussin 	struct command *cmd = NULL;
201cddcb259SBaptiste Daroussin 
202cddcb259SBaptiste Daroussin 	if (argc < 2) {
203cddcb259SBaptiste Daroussin 		warnx("Missing command");
204cddcb259SBaptiste Daroussin 		usage(stderr);
205cddcb259SBaptiste Daroussin 		return (EXIT_FAILURE);
206cddcb259SBaptiste Daroussin 	}
207cddcb259SBaptiste Daroussin 
208cddcb259SBaptiste Daroussin 	for (i = 0; i < nbcmds; i++) {
209cddcb259SBaptiste Daroussin 		if (strcmp(argv[1], cmds[i].name) == 0) {
210cddcb259SBaptiste Daroussin 			cmd = &cmds[i];
211cddcb259SBaptiste Daroussin 			break;
212cddcb259SBaptiste Daroussin 		}
213cddcb259SBaptiste Daroussin 	}
214cddcb259SBaptiste Daroussin 
215cddcb259SBaptiste Daroussin 	if (cmd == NULL) {
216cddcb259SBaptiste Daroussin 		warnx("unknown command %s", argv[1]);
217cddcb259SBaptiste Daroussin 		usage(stderr);
218cddcb259SBaptiste Daroussin 		return (EXIT_FAILURE);
219cddcb259SBaptiste Daroussin 	}
220cddcb259SBaptiste Daroussin 
221cddcb259SBaptiste Daroussin 	argc-=2;
222cddcb259SBaptiste Daroussin 	argv+=2;
223cddcb259SBaptiste Daroussin 
224cddcb259SBaptiste Daroussin 	return (cmd->exec(argc, argv));
225cddcb259SBaptiste Daroussin }
226