]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - usr.sbin/sesutil/sesutil.c
MFC 287473,287485,287493,287494
[FreeBSD/stable/10.git] / usr.sbin / sesutil / sesutil.c
1 /*-
2  * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
14  *
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.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/ioctl.h>
32
33 #include <err.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <glob.h>
37 #include <stdbool.h>
38 #include <stddef.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <unistd.h>
44
45 #include <cam/scsi/scsi_all.h>
46 #include <cam/scsi/scsi_enc.h>
47
48 static int locate(int argc, char **argv);
49
50 static struct command {
51         const char *name;
52         const char *desc;
53         int (*exec)(int argc, char **argv);
54 } cmds[] = {
55         { "locate", "Change the state of the external LED associated with a"
56             " disk", locate} ,
57 };
58
59 static const int nbcmds = nitems(cmds);
60
61 static void
62 do_locate(int fd, unsigned int idx, bool onoff)
63 {
64         encioc_elm_status_t o;
65
66         o.elm_idx = idx;
67         if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) {
68                 close(fd);
69                 err(EXIT_FAILURE, "ENCIOC_GETELMSTAT");
70         }
71         o.cstat[0] |= 0x80;
72         if (onoff)
73                 o.cstat[2] |= 0x02;
74         else
75                 o.cstat[2] &= 0xfd;
76
77         if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) {
78                 close(fd);
79                 err(EXIT_FAILURE, "ENCIOC_SETELMSTAT");
80         }
81 }
82
83 static bool
84 disk_match(const char *devnames, const char *disk, size_t len)
85 {
86         const char *dname;
87
88         dname = devnames;
89         while ((dname = strstr(dname, disk)) != NULL) {
90                 if (dname[len] == '\0' || dname[len] == ',')
91                         return (true);
92                 dname++;
93         }
94         return (false);
95 }
96
97 static int
98 locate(int argc, char **argv)
99 {
100         encioc_elm_devnames_t objdn;
101         encioc_element_t *objp;
102         glob_t g;
103         char *disk;
104         size_t len, i;
105         int fd, nobj, j;
106         bool all = false;
107         bool onoff;
108
109         if (argc != 2) {
110                 errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
111                     getprogname());
112         }
113
114         disk = argv[0];
115
116         if (strcmp(argv[1], "on") == 0) {
117                 onoff = true;
118         } else if (strcmp(argv[1], "off") == 0) {
119                 onoff = false;
120         } else {
121                 errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]",
122                     getprogname());
123         }
124
125         if (strcmp(disk, "all") == 0) {
126                 all = true;
127         }
128         len = strlen(disk);
129
130         /* Get the list of ses devices */
131         if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) {
132                 globfree(&g);
133                 errx(EXIT_FAILURE, "No SES devices found");
134         }
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))
139                         continue;
140                 if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) {
141                         if (errno == EACCES)
142                                 err(EXIT_FAILURE, "enable to access SES device");
143                         break;
144                 }
145
146                 if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0)
147                         err(EXIT_FAILURE, "ENCIOC_GETNELM");
148
149                 objp = calloc(nobj, sizeof(encioc_element_t));
150                 if (objp == NULL)
151                         err(EXIT_FAILURE, "calloc()");
152
153                 if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0)
154                         err(EXIT_FAILURE, "ENCIOC_GETELMMAP");
155
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)
165                                 continue;
166                         if (objdn.elm_names_len > 0) {
167                                 if (all) {
168                                         do_locate(fd, objdn.elm_idx, onoff);
169                                         continue;
170                                 }
171                                 if (disk_match(objdn.elm_devnames, disk, len)) {
172                                         do_locate(fd, objdn.elm_idx, onoff);
173                                         break;
174                                 }
175                         }
176                 }       
177                 close(fd);
178         }
179         globfree(&g);
180
181         return (EXIT_SUCCESS);
182 }
183
184 static void
185 usage(FILE *out)
186 {
187         int i;
188
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);
193 }
194
195 int
196 main(int argc, char **argv)
197 {
198         int i;
199         struct command *cmd = NULL;
200
201         if (argc < 2) {
202                 warnx("Missing command");
203                 usage(stderr);
204                 return (EXIT_FAILURE);
205         }
206
207         for (i = 0; i < nbcmds; i++) {
208                 if (strcmp(argv[1], cmds[i].name) == 0) {
209                         cmd = &cmds[i];
210                         break;
211                 }
212         }
213
214         if (cmd == NULL) {
215                 warnx("unknown command %s", argv[1]);
216                 usage(stderr);
217                 return (EXIT_FAILURE);
218         }
219
220         argc-=2;
221         argv+=2;
222
223         return (cmd->exec(argc, argv));
224 }