sesutil.c revision 287485
1287473Sbapt/*- 2287473Sbapt * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org> 3287473Sbapt * All rights reserved. 4287473Sbapt * 5287473Sbapt * Redistribution and use in source and binary forms, with or without 6287473Sbapt * modification, are permitted provided that the following conditions 7287473Sbapt * are met: 8287473Sbapt * 1. Redistributions of source code must retain the above copyright 9287473Sbapt * notice, this list of conditions and the following disclaimer 10287473Sbapt * in this position and unchanged. 11287473Sbapt * 2. Redistributions in binary form must reproduce the above copyright 12287473Sbapt * notice, this list of conditions and the following disclaimer in the 13287473Sbapt * documentation and/or other materials provided with the distribution. 14287473Sbapt * 15287473Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16287473Sbapt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17287473Sbapt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18287473Sbapt * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19287473Sbapt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20287473Sbapt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21287473Sbapt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22287473Sbapt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23287473Sbapt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24287473Sbapt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25287473Sbapt */ 26287473Sbapt 27287473Sbapt#include <sys/cdefs.h> 28287473Sbapt__FBSDID("$FreeBSD: head/usr.sbin/sesutil/sesutil.c 287485 2015-09-05 16:59:30Z bapt $"); 29287473Sbapt 30287473Sbapt#include <sys/param.h> 31287473Sbapt#include <sys/ioctl.h> 32287473Sbapt 33287473Sbapt#include <err.h> 34287473Sbapt#include <errno.h> 35287473Sbapt#include <fcntl.h> 36287473Sbapt#include <glob.h> 37287473Sbapt#include <stdbool.h> 38287473Sbapt#include <stddef.h> 39287473Sbapt#include <stdint.h> 40287473Sbapt#include <stdio.h> 41287473Sbapt#include <stdlib.h> 42287473Sbapt#include <string.h> 43287473Sbapt#include <unistd.h> 44287473Sbapt 45287473Sbapt#include <cam/scsi/scsi_all.h> 46287473Sbapt#include <cam/scsi/scsi_enc.h> 47287473Sbapt 48287473Sbaptstatic int locate(int argc, char **argv); 49287473Sbapt 50287473Sbaptstatic struct command { 51287473Sbapt const char *name; 52287473Sbapt const char *desc; 53287473Sbapt int (*exec)(int argc, char **argv); 54287473Sbapt} cmds[] = { 55287473Sbapt { "locate", "Change the state of the external LED associated with a" 56287473Sbapt " disk", locate} , 57287473Sbapt}; 58287473Sbapt 59287473Sbaptstatic const int nbcmds = nitems(cmds); 60287473Sbapt 61287473Sbaptstatic void 62287473Sbaptdo_locate(int fd, unsigned int idx, bool onoff) 63287473Sbapt{ 64287473Sbapt encioc_elm_status_t o; 65287473Sbapt 66287473Sbapt o.elm_idx = idx; 67287473Sbapt if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 68287473Sbapt close(fd); 69287473Sbapt err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 70287473Sbapt } 71287473Sbapt o.cstat[0] |= 0x80; 72287473Sbapt if (onoff) 73287473Sbapt o.cstat[2] |= 0x02; 74287473Sbapt else 75287473Sbapt o.cstat[2] &= 0xfd; 76287473Sbapt 77287473Sbapt if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 78287473Sbapt close(fd); 79287473Sbapt err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 80287473Sbapt } 81287473Sbapt} 82287473Sbapt 83287473Sbaptstatic bool 84287473Sbaptdisk_match(const char *devnames, const char *disk, size_t len) 85287473Sbapt{ 86287473Sbapt const char *devname; 87287473Sbapt 88287473Sbapt devname = devnames; 89287473Sbapt while ((devname = strstr(devname, disk)) != NULL) { 90287473Sbapt if (devname[len] == '\0' || devname[len] == ',') 91287473Sbapt return (true); 92287473Sbapt devname++; 93287473Sbapt } 94287473Sbapt return (false); 95287473Sbapt} 96287473Sbapt 97287473Sbaptstatic int 98287473Sbaptlocate(int argc, char **argv) 99287473Sbapt{ 100287473Sbapt encioc_elm_devnames_t objdn; 101287473Sbapt encioc_element_t *objp; 102287473Sbapt glob_t g; 103287473Sbapt char *disk; 104287473Sbapt size_t len, i; 105287473Sbapt int fd, nobj, j; 106287473Sbapt bool all = false; 107287485Sbapt bool onoff; 108287473Sbapt 109287473Sbapt if (argc != 2) { 110287473Sbapt errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]", 111287473Sbapt getprogname()); 112287473Sbapt } 113287473Sbapt 114287473Sbapt disk = argv[0]; 115287473Sbapt 116287473Sbapt if (strcmp(argv[1], "on") == 0) { 117287485Sbapt onoff = true; 118287473Sbapt } else if (strcmp(argv[1], "off") == 0) { 119287485Sbapt onoff = false; 120287473Sbapt } else { 121287473Sbapt errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]", 122287473Sbapt getprogname()); 123287473Sbapt } 124287473Sbapt 125287473Sbapt if (strcmp(disk, "all") == 0) { 126287473Sbapt all = true; 127287473Sbapt } 128287473Sbapt len = strlen(disk); 129287473Sbapt 130287473Sbapt /* Get the list of ses devices */ 131287473Sbapt if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) { 132287473Sbapt globfree(&g); 133287473Sbapt errx(EXIT_FAILURE, "No SES devices found"); 134287473Sbapt } 135287473Sbapt for (i = 0; i < g.gl_pathc; i++) { 136287473Sbapt /* ensure we only got numbers after ses */ 137287473Sbapt if (strspn(g.gl_pathv[i] + 8, "0123456789") != 138287473Sbapt strlen(g.gl_pathv[i] + 8)) 139287473Sbapt continue; 140287473Sbapt if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 141287473Sbapt if (errno == EACCES) 142287473Sbapt err(EXIT_FAILURE, "enable to access SES device"); 143287473Sbapt break; 144287473Sbapt } 145287473Sbapt 146287473Sbapt if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) 147287473Sbapt err(EXIT_FAILURE, "ENCIOC_GETNELM"); 148287473Sbapt 149287473Sbapt objp = calloc(nobj, sizeof(encioc_element_t)); 150287473Sbapt if (objp == NULL) 151287473Sbapt err(EXIT_FAILURE, "calloc()"); 152287473Sbapt 153287473Sbapt if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) 154287473Sbapt err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 155287473Sbapt 156287473Sbapt for (j = 0; j < nobj; j++) { 157287473Sbapt memset(&objdn, 0, sizeof(objdn)); 158287473Sbapt objdn.elm_idx = objp[j].elm_idx; 159287473Sbapt objdn.elm_names_size = 128; 160287473Sbapt objdn.elm_devnames = calloc(128, sizeof(char)); 161287473Sbapt if (objdn.elm_devnames == NULL) 162287473Sbapt err(EXIT_FAILURE, "calloc()"); 163287473Sbapt if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 164287473Sbapt (caddr_t) &objdn) <0) 165287473Sbapt continue; 166287473Sbapt if (objdn.elm_names_len > 0) { 167287473Sbapt if (all) { 168287485Sbapt do_locate(fd, objdn.elm_idx, onoff); 169287473Sbapt continue; 170287473Sbapt } 171287473Sbapt if (disk_match(objdn.elm_devnames, disk, len)) { 172287485Sbapt do_locate(fd, objdn.elm_idx, onoff); 173287473Sbapt break; 174287473Sbapt } 175287473Sbapt } 176287473Sbapt } 177287473Sbapt close(fd); 178287473Sbapt i++; 179287473Sbapt } 180287473Sbapt globfree(&g); 181287473Sbapt 182287473Sbapt return (EXIT_SUCCESS); 183287473Sbapt} 184287473Sbapt 185287473Sbaptstatic void 186287473Sbaptusage(FILE *out) 187287473Sbapt{ 188287473Sbapt int i; 189287473Sbapt 190287473Sbapt fprintf(out, "Usage: %s [command] [options]\n", getprogname()); 191287473Sbapt fprintf(out, "Commands supported:\n"); 192287473Sbapt for (i = 0; i < nbcmds; i++) 193287473Sbapt fprintf(out, "\t%-15s%s\n", cmds[i].name, cmds[i].desc); 194287473Sbapt} 195287473Sbapt 196287473Sbaptint 197287473Sbaptmain(int argc, char **argv) 198287473Sbapt{ 199287473Sbapt int i; 200287473Sbapt struct command *cmd = NULL; 201287473Sbapt 202287473Sbapt if (argc < 2) { 203287473Sbapt warnx("Missing command"); 204287473Sbapt usage(stderr); 205287473Sbapt return (EXIT_FAILURE); 206287473Sbapt } 207287473Sbapt 208287473Sbapt for (i = 0; i < nbcmds; i++) { 209287473Sbapt if (strcmp(argv[1], cmds[i].name) == 0) { 210287473Sbapt cmd = &cmds[i]; 211287473Sbapt break; 212287473Sbapt } 213287473Sbapt } 214287473Sbapt 215287473Sbapt if (cmd == NULL) { 216287473Sbapt warnx("unknown command %s", argv[1]); 217287473Sbapt usage(stderr); 218287473Sbapt return (EXIT_FAILURE); 219287473Sbapt } 220287473Sbapt 221287473Sbapt argc-=2; 222287473Sbapt argv+=2; 223287473Sbapt 224287473Sbapt return (cmd->exec(argc, argv)); 225287473Sbapt} 226