2 * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer
10 * in this position and unchanged.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_enc.h>
48 static int locate(int argc, char **argv);
50 static struct command {
53 int (*exec)(int argc, char **argv);
55 { "locate", "Change the state of the external LED associated with a"
59 static const int nbcmds = nitems(cmds);
62 do_locate(int fd, unsigned int idx, bool onoff)
64 encioc_elm_status_t o;
67 if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) {
69 err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
77 if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
79 err(EXIT_FAILURE, "ENCIOC_SETELMSTAT");
84 disk_match(const char *devnames, const char *disk, size_t len)
89 while ((dname = strstr(dname, disk)) != NULL) {
90 if (dname[len] == '\0' || dname[len] == ',')
98 locate(int argc, char **argv)
100 encioc_elm_devnames_t objdn;
101 encioc_element_t *objp;
110 errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
116 if (strcmp(argv[1], "on") == 0) {
118 } else if (strcmp(argv[1], "off") == 0) {
121 errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
125 if (strcmp(disk, "all") == 0) {
130 /* Get the list of ses devices */
131 if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) {
133 errx(EXIT_FAILURE, "No SES devices found");
135 for (i = 0; i < g.gl_pathc; i++) {
136 /* ensure we only got numbers after ses */
137 if (strspn(g.gl_pathv[i] + 8, "0123456789") !=
138 strlen(g.gl_pathv[i] + 8))
140 if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
142 err(EXIT_FAILURE, "enable to access SES device");
146 if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0)
147 err(EXIT_FAILURE, "ENCIOC_GETNELM");
149 objp = calloc(nobj, sizeof(encioc_element_t));
151 err(EXIT_FAILURE, "calloc()");
153 if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0)
154 err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
156 for (j = 0; j < nobj; j++) {
157 memset(&objdn, 0, sizeof(objdn));
158 objdn.elm_idx = objp[j].elm_idx;
159 objdn.elm_names_size = 128;
160 objdn.elm_devnames = calloc(128, sizeof(char));
161 if (objdn.elm_devnames == NULL)
162 err(EXIT_FAILURE, "calloc()");
163 if (ioctl(fd, ENCIOC_GETELMDEVNAMES,
164 (caddr_t) &objdn) <0)
166 if (objdn.elm_names_len > 0) {
168 do_locate(fd, objdn.elm_idx, onoff);
171 if (disk_match(objdn.elm_devnames, disk, len)) {
172 do_locate(fd, objdn.elm_idx, onoff);
181 return (EXIT_SUCCESS);
189 fprintf(out, "Usage: %s [command] [options]\n", getprogname());
190 fprintf(out, "Commands supported:\n");
191 for (i = 0; i < nbcmds; i++)
192 fprintf(out, "\t%-15s%s\n", cmds[i].name, cmds[i].desc);
196 main(int argc, char **argv)
199 struct command *cmd = NULL;
202 warnx("Missing command");
204 return (EXIT_FAILURE);
207 for (i = 0; i < nbcmds; i++) {
208 if (strcmp(argv[1], cmds[i].name) == 0) {
215 warnx("unknown command %s", argv[1]);
217 return (EXIT_FAILURE);
223 return (cmd->exec(argc, argv));