1cddcb259SBaptiste Daroussin /*- 2cddcb259SBaptiste Daroussin * Copyright (c) 2015 Baptiste Daroussin <bapt@FreeBSD.org> 38729f5ecSAllan Jude * Copyright (c) 2015 Allan Jude <allanjude@FreeBSD.org> 48729f5ecSAllan Jude * Copyright (c) 2000 by Matthew Jacob 5cddcb259SBaptiste Daroussin * All rights reserved. 6cddcb259SBaptiste Daroussin * 7cddcb259SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 8cddcb259SBaptiste Daroussin * modification, are permitted provided that the following conditions 9cddcb259SBaptiste Daroussin * are met: 10cddcb259SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 11cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer 12cddcb259SBaptiste Daroussin * in this position and unchanged. 13cddcb259SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 14cddcb259SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 15cddcb259SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 16cddcb259SBaptiste Daroussin * 17cddcb259SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 18cddcb259SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19cddcb259SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20cddcb259SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 21cddcb259SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22cddcb259SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23cddcb259SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24cddcb259SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25cddcb259SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26cddcb259SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27cddcb259SBaptiste Daroussin */ 28cddcb259SBaptiste Daroussin 29cddcb259SBaptiste Daroussin #include <sys/cdefs.h> 30cddcb259SBaptiste Daroussin __FBSDID("$FreeBSD$"); 31cddcb259SBaptiste Daroussin 32cddcb259SBaptiste Daroussin #include <sys/param.h> 33cddcb259SBaptiste Daroussin #include <sys/ioctl.h> 34d7654478SBaptiste Daroussin #include <sys/types.h> 35d7654478SBaptiste Daroussin #include <sys/sbuf.h> 36cddcb259SBaptiste Daroussin 37cddcb259SBaptiste Daroussin #include <err.h> 38cddcb259SBaptiste Daroussin #include <errno.h> 39cddcb259SBaptiste Daroussin #include <fcntl.h> 408729f5ecSAllan Jude #include <getopt.h> 41cddcb259SBaptiste Daroussin #include <glob.h> 42cddcb259SBaptiste Daroussin #include <stdbool.h> 43cddcb259SBaptiste Daroussin #include <stddef.h> 44cddcb259SBaptiste Daroussin #include <stdint.h> 45cddcb259SBaptiste Daroussin #include <stdio.h> 46cddcb259SBaptiste Daroussin #include <stdlib.h> 47cddcb259SBaptiste Daroussin #include <string.h> 48cddcb259SBaptiste Daroussin #include <unistd.h> 49cddcb259SBaptiste Daroussin 50cddcb259SBaptiste Daroussin #include <cam/scsi/scsi_enc.h> 51cddcb259SBaptiste Daroussin 528729f5ecSAllan Jude #include "eltsub.h" 538729f5ecSAllan Jude 548729f5ecSAllan Jude static int encstatus(int argc, char **argv); 558729f5ecSAllan Jude static int fault(int argc, char **argv); 56cddcb259SBaptiste Daroussin static int locate(int argc, char **argv); 578729f5ecSAllan Jude static int objmap(int argc, char **argv); 588729f5ecSAllan Jude static int sesled(int argc, char **argv, bool fault); 59cddcb259SBaptiste Daroussin 60cddcb259SBaptiste Daroussin static struct command { 61cddcb259SBaptiste Daroussin const char *name; 628729f5ecSAllan Jude const char *param; 63cddcb259SBaptiste Daroussin const char *desc; 64cddcb259SBaptiste Daroussin int (*exec)(int argc, char **argv); 65cddcb259SBaptiste Daroussin } cmds[] = { 668729f5ecSAllan Jude { "fault", 678729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 688729f5ecSAllan Jude "Change the state of the fault LED associated with a disk", 698729f5ecSAllan Jude fault }, 708729f5ecSAllan Jude { "locate", 718729f5ecSAllan Jude "(<disk>|<sesid>|all) (on|off)", 728729f5ecSAllan Jude "Change the state of the locate LED associated with a disk", 738729f5ecSAllan Jude locate }, 748729f5ecSAllan Jude { "map", "", 758729f5ecSAllan Jude "Print a map of the devices managed by the enclosure", objmap } , 768729f5ecSAllan Jude { "status", "", "Print the status of the enclosure", 778729f5ecSAllan Jude encstatus }, 78cddcb259SBaptiste Daroussin }; 79cddcb259SBaptiste Daroussin 80cddcb259SBaptiste Daroussin static const int nbcmds = nitems(cmds); 818729f5ecSAllan Jude static const char *uflag; 82cddcb259SBaptiste Daroussin 83cddcb259SBaptiste Daroussin static void 848729f5ecSAllan Jude usage(FILE *out, const char *subcmd) 858729f5ecSAllan Jude { 868729f5ecSAllan Jude int i; 878729f5ecSAllan Jude 888729f5ecSAllan Jude if (subcmd == NULL) { 898729f5ecSAllan Jude fprintf(out, "Usage: %s [-u /dev/ses<N>] <command> [options]\n", 908729f5ecSAllan Jude getprogname()); 918729f5ecSAllan Jude fprintf(out, "Commands supported:\n"); 928729f5ecSAllan Jude } 938729f5ecSAllan Jude for (i = 0; i < nbcmds; i++) { 948729f5ecSAllan Jude if (subcmd != NULL) { 958729f5ecSAllan Jude if (strcmp(subcmd, cmds[i].name) == 0) { 968729f5ecSAllan Jude fprintf(out, "Usage: %s %s [-u /dev/ses<N>] " 978729f5ecSAllan Jude "%s\n\t%s\n", getprogname(), subcmd, 988729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 998729f5ecSAllan Jude break; 1008729f5ecSAllan Jude } 1018729f5ecSAllan Jude continue; 1028729f5ecSAllan Jude } 1038729f5ecSAllan Jude fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, 1048729f5ecSAllan Jude cmds[i].param, cmds[i].desc); 1058729f5ecSAllan Jude } 1068729f5ecSAllan Jude 1078729f5ecSAllan Jude exit(EXIT_FAILURE); 1088729f5ecSAllan Jude } 1098729f5ecSAllan Jude 1108729f5ecSAllan Jude static void 1116af5d161SAllan Jude do_led(int fd, unsigned int idx, bool onoff, bool setfault) 112cddcb259SBaptiste Daroussin { 113cddcb259SBaptiste Daroussin encioc_elm_status_t o; 114cddcb259SBaptiste Daroussin 115cddcb259SBaptiste Daroussin o.elm_idx = idx; 116cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { 117cddcb259SBaptiste Daroussin close(fd); 118cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 119cddcb259SBaptiste Daroussin } 120cddcb259SBaptiste Daroussin o.cstat[0] |= 0x80; 1218729f5ecSAllan Jude if (onoff) { 1226af5d161SAllan Jude o.cstat[2] |= (setfault ? 0x20 : 0x02); 1238729f5ecSAllan Jude } else { 1246af5d161SAllan Jude o.cstat[2] &= (setfault ? 0xdf : 0xfd); 1258729f5ecSAllan Jude } 126cddcb259SBaptiste Daroussin 127cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { 128cddcb259SBaptiste Daroussin close(fd); 129cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); 130cddcb259SBaptiste Daroussin } 131cddcb259SBaptiste Daroussin } 132cddcb259SBaptiste Daroussin 133cddcb259SBaptiste Daroussin static bool 134cddcb259SBaptiste Daroussin disk_match(const char *devnames, const char *disk, size_t len) 135cddcb259SBaptiste Daroussin { 1361bc54324SBaptiste Daroussin const char *dname; 137cddcb259SBaptiste Daroussin 1381bc54324SBaptiste Daroussin dname = devnames; 1391bc54324SBaptiste Daroussin while ((dname = strstr(dname, disk)) != NULL) { 1408729f5ecSAllan Jude if (dname[len] == '\0' || dname[len] == ',') { 141cddcb259SBaptiste Daroussin return (true); 1428729f5ecSAllan Jude } 1431bc54324SBaptiste Daroussin dname++; 144cddcb259SBaptiste Daroussin } 1458729f5ecSAllan Jude 146cddcb259SBaptiste Daroussin return (false); 147cddcb259SBaptiste Daroussin } 148cddcb259SBaptiste Daroussin 149cddcb259SBaptiste Daroussin static int 1506af5d161SAllan Jude sesled(int argc, char **argv, bool setfault) 151cddcb259SBaptiste Daroussin { 152cddcb259SBaptiste Daroussin encioc_elm_devnames_t objdn; 153cddcb259SBaptiste Daroussin encioc_element_t *objp; 154cddcb259SBaptiste Daroussin glob_t g; 1558729f5ecSAllan Jude char *disk, *endptr; 1568729f5ecSAllan Jude size_t len, i, ndisks; 1578729f5ecSAllan Jude int fd; 1588729f5ecSAllan Jude unsigned int nobj, j, sesid; 1598729f5ecSAllan Jude bool all, isses, onoff; 160cddcb259SBaptiste Daroussin 1618729f5ecSAllan Jude isses = false; 1628729f5ecSAllan Jude all = false; 1638729f5ecSAllan Jude onoff = false; 1648729f5ecSAllan Jude 1658729f5ecSAllan Jude if (argc != 3) { 1666af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 167cddcb259SBaptiste Daroussin } 168cddcb259SBaptiste Daroussin 1698729f5ecSAllan Jude disk = argv[1]; 170cddcb259SBaptiste Daroussin 1718729f5ecSAllan Jude sesid = strtoul(disk, &endptr, 10); 1728729f5ecSAllan Jude if (*endptr == '\0') { 1738729f5ecSAllan Jude endptr = strrchr(uflag, '*'); 17496e6c444SBaptiste Daroussin if (endptr != NULL && *endptr == '*') { 1758729f5ecSAllan Jude warnx("Must specifying a SES device (-u) to use a SES " 1768729f5ecSAllan Jude "id# to identify a disk"); 1776af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 1788729f5ecSAllan Jude } 1798729f5ecSAllan Jude isses = true; 1808729f5ecSAllan Jude } 1818729f5ecSAllan Jude 1828729f5ecSAllan Jude if (strcmp(argv[2], "on") == 0) { 1834569e7cfSBaptiste Daroussin onoff = true; 1848729f5ecSAllan Jude } else if (strcmp(argv[2], "off") == 0) { 1854569e7cfSBaptiste Daroussin onoff = false; 186cddcb259SBaptiste Daroussin } else { 1876af5d161SAllan Jude usage(stderr, (setfault ? "fault" : "locate")); 188cddcb259SBaptiste Daroussin } 189cddcb259SBaptiste Daroussin 190cddcb259SBaptiste Daroussin if (strcmp(disk, "all") == 0) { 191cddcb259SBaptiste Daroussin all = true; 192cddcb259SBaptiste Daroussin } 193cddcb259SBaptiste Daroussin len = strlen(disk); 194cddcb259SBaptiste Daroussin 195cddcb259SBaptiste Daroussin /* Get the list of ses devices */ 1968729f5ecSAllan Jude if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == 1978729f5ecSAllan Jude GLOB_NOMATCH) { 1988729f5ecSAllan Jude globfree(&g); 1998729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 2008729f5ecSAllan Jude } 2018729f5ecSAllan Jude 2028729f5ecSAllan Jude ndisks = 0; 2038729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 2048729f5ecSAllan Jude /* ensure we only got numbers after ses */ 2058729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 2068729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 2078729f5ecSAllan Jude continue; 2088729f5ecSAllan Jude } 2098729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 2108729f5ecSAllan Jude /* 2118729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 2128729f5ecSAllan Jude * accessing all devices 2138729f5ecSAllan Jude */ 2148729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 2158729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 2168729f5ecSAllan Jude } 2178729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 2188729f5ecSAllan Jude continue; 2198729f5ecSAllan Jude } 2208729f5ecSAllan Jude 2218729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 2228729f5ecSAllan Jude close(fd); 2238729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETNELM"); 2248729f5ecSAllan Jude } 2258729f5ecSAllan Jude 2268729f5ecSAllan Jude objp = calloc(nobj, sizeof(encioc_element_t)); 2278729f5ecSAllan Jude if (objp == NULL) { 2288729f5ecSAllan Jude close(fd); 2298729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2308729f5ecSAllan Jude } 2318729f5ecSAllan Jude 2328729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { 2338729f5ecSAllan Jude close(fd); 2348729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 2358729f5ecSAllan Jude } 2368729f5ecSAllan Jude 2378729f5ecSAllan Jude if (isses) { 2388729f5ecSAllan Jude if (sesid > nobj) { 2398729f5ecSAllan Jude close(fd); 2408729f5ecSAllan Jude errx(EXIT_FAILURE, 2418729f5ecSAllan Jude "Requested SES ID does not exist"); 2428729f5ecSAllan Jude } 2436af5d161SAllan Jude do_led(fd, sesid, onoff, setfault); 2448729f5ecSAllan Jude ndisks++; 2458729f5ecSAllan Jude close(fd); 2468729f5ecSAllan Jude break; 2478729f5ecSAllan Jude } 2488729f5ecSAllan Jude for (j = 0; j < nobj; j++) { 2498729f5ecSAllan Jude memset(&objdn, 0, sizeof(objdn)); 2508729f5ecSAllan Jude objdn.elm_idx = objp[j].elm_idx; 2518729f5ecSAllan Jude objdn.elm_names_size = 128; 2528729f5ecSAllan Jude objdn.elm_devnames = calloc(128, sizeof(char)); 2538729f5ecSAllan Jude if (objdn.elm_devnames == NULL) { 2548729f5ecSAllan Jude close(fd); 2558729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 2568729f5ecSAllan Jude } 2578729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 2588729f5ecSAllan Jude (caddr_t) &objdn) <0) { 2598729f5ecSAllan Jude continue; 2608729f5ecSAllan Jude } 2618729f5ecSAllan Jude if (objdn.elm_names_len > 0) { 2628729f5ecSAllan Jude if (all) { 2638729f5ecSAllan Jude do_led(fd, objdn.elm_idx, 2646af5d161SAllan Jude onoff, setfault); 2658729f5ecSAllan Jude continue; 2668729f5ecSAllan Jude } 2678729f5ecSAllan Jude if (disk_match(objdn.elm_devnames, disk, len)) { 2688729f5ecSAllan Jude do_led(fd, objdn.elm_idx, 2696af5d161SAllan Jude onoff, setfault); 2708729f5ecSAllan Jude ndisks++; 2718729f5ecSAllan Jude break; 2728729f5ecSAllan Jude } 2738729f5ecSAllan Jude } 2748729f5ecSAllan Jude } 275*f734685eSBaptiste Daroussin free(objp); 2768729f5ecSAllan Jude close(fd); 2778729f5ecSAllan Jude } 2788729f5ecSAllan Jude globfree(&g); 2798729f5ecSAllan Jude if (ndisks == 0 && all == false) { 2808729f5ecSAllan Jude errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", 2818729f5ecSAllan Jude disk); 2828729f5ecSAllan Jude } 2838729f5ecSAllan Jude 2848729f5ecSAllan Jude return (EXIT_SUCCESS); 2858729f5ecSAllan Jude } 2868729f5ecSAllan Jude 2878729f5ecSAllan Jude static int 2888729f5ecSAllan Jude locate(int argc, char **argv) 2898729f5ecSAllan Jude { 2908729f5ecSAllan Jude 2918729f5ecSAllan Jude return (sesled(argc, argv, false)); 2928729f5ecSAllan Jude } 2938729f5ecSAllan Jude 2948729f5ecSAllan Jude static int 2958729f5ecSAllan Jude fault(int argc, char **argv) 2968729f5ecSAllan Jude { 2978729f5ecSAllan Jude 2988729f5ecSAllan Jude return (sesled(argc, argv, true)); 2998729f5ecSAllan Jude } 3008729f5ecSAllan Jude 3018729f5ecSAllan Jude static int 3028729f5ecSAllan Jude objmap(int argc, char **argv __unused) 3038729f5ecSAllan Jude { 304d7654478SBaptiste Daroussin struct sbuf *extra; 30560f46640SBaptiste Daroussin encioc_string_t stri; 3068729f5ecSAllan Jude encioc_elm_devnames_t e_devname; 3078729f5ecSAllan Jude encioc_elm_status_t e_status; 3088729f5ecSAllan Jude encioc_elm_desc_t e_desc; 3098729f5ecSAllan Jude encioc_element_t *e_ptr; 3108729f5ecSAllan Jude glob_t g; 3118729f5ecSAllan Jude int fd; 3128729f5ecSAllan Jude unsigned int j, nobj; 3138729f5ecSAllan Jude size_t i; 31460f46640SBaptiste Daroussin char str[32]; 3158729f5ecSAllan Jude 3168729f5ecSAllan Jude if (argc != 1) { 3178729f5ecSAllan Jude usage(stderr, "map"); 3188729f5ecSAllan Jude } 3198729f5ecSAllan Jude 3208729f5ecSAllan Jude /* Get the list of ses devices */ 3218729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 322cddcb259SBaptiste Daroussin globfree(&g); 323cddcb259SBaptiste Daroussin errx(EXIT_FAILURE, "No SES devices found"); 324cddcb259SBaptiste Daroussin } 325cddcb259SBaptiste Daroussin for (i = 0; i < g.gl_pathc; i++) { 326cddcb259SBaptiste Daroussin /* ensure we only got numbers after ses */ 327cddcb259SBaptiste Daroussin if (strspn(g.gl_pathv[i] + 8, "0123456789") != 3288729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 329cddcb259SBaptiste Daroussin continue; 3308729f5ecSAllan Jude } 331cddcb259SBaptiste Daroussin if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 3328729f5ecSAllan Jude /* 3338729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 3348729f5ecSAllan Jude * accessing all devices 3358729f5ecSAllan Jude */ 3368729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 3378729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 3388729f5ecSAllan Jude } 3398729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 3408729f5ecSAllan Jude continue; 341cddcb259SBaptiste Daroussin } 342cddcb259SBaptiste Daroussin 3438729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { 3448729f5ecSAllan Jude close(fd); 345cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETNELM"); 3468729f5ecSAllan Jude } 347cddcb259SBaptiste Daroussin 3488729f5ecSAllan Jude e_ptr = calloc(nobj, sizeof(encioc_element_t)); 3498729f5ecSAllan Jude if (e_ptr == NULL) { 3508729f5ecSAllan Jude close(fd); 351cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 3528729f5ecSAllan Jude } 353cddcb259SBaptiste Daroussin 3548729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { 3558729f5ecSAllan Jude close(fd); 356cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); 3578729f5ecSAllan Jude } 358cddcb259SBaptiste Daroussin 3598729f5ecSAllan Jude printf("%s:\n", g.gl_pathv[i] + 5); 36060f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 36160f46640SBaptiste Daroussin stri.buf = &str[0]; 36260f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri) == 0) 36360f46640SBaptiste Daroussin printf("\tEnclosure Name: %s\n", stri.buf); 36460f46640SBaptiste Daroussin stri.bufsiz = sizeof(str); 36560f46640SBaptiste Daroussin stri.buf = &str[0]; 36660f46640SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri) == 0) 36760f46640SBaptiste Daroussin printf("\tEnclosure ID: %s\n", stri.buf); 36860f46640SBaptiste Daroussin 369cddcb259SBaptiste Daroussin for (j = 0; j < nobj; j++) { 3708729f5ecSAllan Jude /* Get the status of the element */ 3718729f5ecSAllan Jude memset(&e_status, 0, sizeof(e_status)); 3728729f5ecSAllan Jude e_status.elm_idx = e_ptr[j].elm_idx; 3738729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMSTAT, 3748729f5ecSAllan Jude (caddr_t) &e_status) < 0) { 3758729f5ecSAllan Jude close(fd); 3768729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); 3778729f5ecSAllan Jude } 3788729f5ecSAllan Jude /* Get the description of the element */ 3798729f5ecSAllan Jude memset(&e_desc, 0, sizeof(e_desc)); 3808729f5ecSAllan Jude e_desc.elm_idx = e_ptr[j].elm_idx; 3818729f5ecSAllan Jude e_desc.elm_desc_len = UINT16_MAX; 3828729f5ecSAllan Jude e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); 3838729f5ecSAllan Jude if (e_desc.elm_desc_str == NULL) { 3848729f5ecSAllan Jude close(fd); 385cddcb259SBaptiste Daroussin err(EXIT_FAILURE, "calloc()"); 3868729f5ecSAllan Jude } 3878729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETELMDESC, 3888729f5ecSAllan Jude (caddr_t) &e_desc) < 0) { 3898729f5ecSAllan Jude close(fd); 3908729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); 3918729f5ecSAllan Jude } 3928729f5ecSAllan Jude /* Get the device name(s) of the element */ 3938729f5ecSAllan Jude memset(&e_devname, 0, sizeof(e_devname)); 3948729f5ecSAllan Jude e_devname.elm_idx = e_ptr[j].elm_idx; 3958729f5ecSAllan Jude e_devname.elm_names_size = 128; 3968729f5ecSAllan Jude e_devname.elm_devnames = calloc(128, sizeof(char)); 3978729f5ecSAllan Jude if (e_devname.elm_devnames == NULL) { 3988729f5ecSAllan Jude close(fd); 3998729f5ecSAllan Jude err(EXIT_FAILURE, "calloc()"); 4008729f5ecSAllan Jude } 401cddcb259SBaptiste Daroussin if (ioctl(fd, ENCIOC_GETELMDEVNAMES, 4028729f5ecSAllan Jude (caddr_t) &e_devname) <0) { 4038729f5ecSAllan Jude /* We don't care if this fails */ 4048729f5ecSAllan Jude e_devname.elm_devnames[0] = '\0'; 405cddcb259SBaptiste Daroussin } 4068729f5ecSAllan Jude printf("\tElement %u, Type: %s\n", e_ptr[j].elm_idx, 4078729f5ecSAllan Jude geteltnm(e_ptr[j].elm_type)); 408d7654478SBaptiste Daroussin printf("\t\tStatus: %s (0x%02x 0x%02x 0x%02x 0x%02x)\n", 409d7654478SBaptiste Daroussin scode2ascii(e_status.cstat[0]), e_status.cstat[0], 410d7654478SBaptiste Daroussin e_status.cstat[1], e_status.cstat[2], 411d7654478SBaptiste Daroussin e_status.cstat[3]); 4128729f5ecSAllan Jude if (e_desc.elm_desc_len > 0) { 4138729f5ecSAllan Jude printf("\t\tDescription: %s\n", 4148729f5ecSAllan Jude e_desc.elm_desc_str); 415cddcb259SBaptiste Daroussin } 4168729f5ecSAllan Jude if (e_devname.elm_names_len > 0) { 4178729f5ecSAllan Jude printf("\t\tDevice Names: %s\n", 4188729f5ecSAllan Jude e_devname.elm_devnames); 419cddcb259SBaptiste Daroussin } 420d7654478SBaptiste Daroussin extra = stat2sbuf(e_ptr[j].elm_type, e_status.cstat); 421d7654478SBaptiste Daroussin if (sbuf_len(extra) > 0) { 422d7654478SBaptiste Daroussin printf("\t\tExtra status:\n%s", 423d7654478SBaptiste Daroussin sbuf_data(extra)); 424d7654478SBaptiste Daroussin } 425d7654478SBaptiste Daroussin sbuf_delete(extra); 4268729f5ecSAllan Jude free(e_devname.elm_devnames); 427cddcb259SBaptiste Daroussin } 428*f734685eSBaptiste Daroussin free(e_ptr); 429cddcb259SBaptiste Daroussin close(fd); 430cddcb259SBaptiste Daroussin } 431cddcb259SBaptiste Daroussin globfree(&g); 432cddcb259SBaptiste Daroussin 433cddcb259SBaptiste Daroussin return (EXIT_SUCCESS); 434cddcb259SBaptiste Daroussin } 435cddcb259SBaptiste Daroussin 4368729f5ecSAllan Jude static int 4378729f5ecSAllan Jude encstatus(int argc, char **argv __unused) 438cddcb259SBaptiste Daroussin { 4398729f5ecSAllan Jude glob_t g; 4408729f5ecSAllan Jude int fd, status; 4418729f5ecSAllan Jude size_t i, e; 4428729f5ecSAllan Jude u_char estat; 443cddcb259SBaptiste Daroussin 4448729f5ecSAllan Jude status = 0; 4458729f5ecSAllan Jude if (argc != 1) { 4468729f5ecSAllan Jude usage(stderr, "status"); 4478729f5ecSAllan Jude } 4488729f5ecSAllan Jude 4498729f5ecSAllan Jude /* Get the list of ses devices */ 4508729f5ecSAllan Jude if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { 4518729f5ecSAllan Jude globfree(&g); 4528729f5ecSAllan Jude errx(EXIT_FAILURE, "No SES devices found"); 4538729f5ecSAllan Jude } 4548729f5ecSAllan Jude for (i = 0; i < g.gl_pathc; i++) { 4558729f5ecSAllan Jude /* ensure we only got numbers after ses */ 4568729f5ecSAllan Jude if (strspn(g.gl_pathv[i] + 8, "0123456789") != 4578729f5ecSAllan Jude strlen(g.gl_pathv[i] + 8)) { 4588729f5ecSAllan Jude continue; 4598729f5ecSAllan Jude } 4608729f5ecSAllan Jude if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { 4618729f5ecSAllan Jude /* 4628729f5ecSAllan Jude * Don't treat non-access errors as critical if we are 4638729f5ecSAllan Jude * accessing all devices 4648729f5ecSAllan Jude */ 4658729f5ecSAllan Jude if (errno == EACCES && g.gl_pathc > 1) { 4668729f5ecSAllan Jude err(EXIT_FAILURE, "unable to access SES device"); 4678729f5ecSAllan Jude } 4688729f5ecSAllan Jude warn("unable to access SES device: %s", g.gl_pathv[i]); 4698729f5ecSAllan Jude continue; 4708729f5ecSAllan Jude } 4718729f5ecSAllan Jude 4728729f5ecSAllan Jude if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { 4738729f5ecSAllan Jude close(fd); 4748729f5ecSAllan Jude err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); 4758729f5ecSAllan Jude } 4768729f5ecSAllan Jude 4778729f5ecSAllan Jude printf("%s: ", g.gl_pathv[i] + 5); 4788729f5ecSAllan Jude e = 0; 4798729f5ecSAllan Jude if (estat == 0) { 4808729f5ecSAllan Jude if (status == 0) { 4818729f5ecSAllan Jude status = 1; 4828729f5ecSAllan Jude } 4838729f5ecSAllan Jude printf("OK"); 4848729f5ecSAllan Jude } else { 4858729f5ecSAllan Jude if (estat & SES_ENCSTAT_INFO) { 4868729f5ecSAllan Jude printf("INFO"); 4878729f5ecSAllan Jude e++; 4888729f5ecSAllan Jude } 4898729f5ecSAllan Jude if (estat & SES_ENCSTAT_NONCRITICAL) { 4908729f5ecSAllan Jude if (e) 4918729f5ecSAllan Jude printf(","); 4928729f5ecSAllan Jude printf("NONCRITICAL"); 4938729f5ecSAllan Jude e++; 4948729f5ecSAllan Jude } 4958729f5ecSAllan Jude if (estat & SES_ENCSTAT_CRITICAL) { 4968729f5ecSAllan Jude if (e) 4978729f5ecSAllan Jude printf(","); 4988729f5ecSAllan Jude printf("CRITICAL"); 4998729f5ecSAllan Jude e++; 5008729f5ecSAllan Jude status = -1; 5018729f5ecSAllan Jude } 5028729f5ecSAllan Jude if (estat & SES_ENCSTAT_UNRECOV) { 5038729f5ecSAllan Jude if (e) 5048729f5ecSAllan Jude printf(","); 5058729f5ecSAllan Jude printf("UNRECOV"); 5068729f5ecSAllan Jude e++; 5078729f5ecSAllan Jude status = -1; 5088729f5ecSAllan Jude } 5098729f5ecSAllan Jude } 5108729f5ecSAllan Jude printf("\n"); 5118729f5ecSAllan Jude 5128729f5ecSAllan Jude close(fd); 5138729f5ecSAllan Jude } 5148729f5ecSAllan Jude globfree(&g); 5158729f5ecSAllan Jude 5168729f5ecSAllan Jude if (status == 1) { 5178729f5ecSAllan Jude return (EXIT_SUCCESS); 5188729f5ecSAllan Jude } else { 5198729f5ecSAllan Jude return (EXIT_FAILURE); 5208729f5ecSAllan Jude } 521cddcb259SBaptiste Daroussin } 522cddcb259SBaptiste Daroussin 523cddcb259SBaptiste Daroussin int 524cddcb259SBaptiste Daroussin main(int argc, char **argv) 525cddcb259SBaptiste Daroussin { 5268729f5ecSAllan Jude int i, ch; 527cddcb259SBaptiste Daroussin struct command *cmd = NULL; 528cddcb259SBaptiste Daroussin 5298729f5ecSAllan Jude uflag = "/dev/ses[0-9]*"; 5308729f5ecSAllan Jude while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { 5318729f5ecSAllan Jude switch (ch) { 5328729f5ecSAllan Jude case 'u': 5338729f5ecSAllan Jude uflag = optarg; 5348729f5ecSAllan Jude break; 5358729f5ecSAllan Jude case '?': 5368729f5ecSAllan Jude default: 5378729f5ecSAllan Jude usage(stderr, NULL); 5388729f5ecSAllan Jude } 5398729f5ecSAllan Jude } 5408729f5ecSAllan Jude argc -= optind; 5418729f5ecSAllan Jude argv += optind; 5428729f5ecSAllan Jude 5438729f5ecSAllan Jude if (argc < 1) { 544cddcb259SBaptiste Daroussin warnx("Missing command"); 5458729f5ecSAllan Jude usage(stderr, NULL); 546cddcb259SBaptiste Daroussin } 547cddcb259SBaptiste Daroussin 548cddcb259SBaptiste Daroussin for (i = 0; i < nbcmds; i++) { 5498729f5ecSAllan Jude if (strcmp(argv[0], cmds[i].name) == 0) { 550cddcb259SBaptiste Daroussin cmd = &cmds[i]; 551cddcb259SBaptiste Daroussin break; 552cddcb259SBaptiste Daroussin } 553cddcb259SBaptiste Daroussin } 554cddcb259SBaptiste Daroussin 555cddcb259SBaptiste Daroussin if (cmd == NULL) { 5568729f5ecSAllan Jude warnx("unknown command %s", argv[0]); 5578729f5ecSAllan Jude usage(stderr, NULL); 558cddcb259SBaptiste Daroussin } 559cddcb259SBaptiste Daroussin 560cddcb259SBaptiste Daroussin return (cmd->exec(argc, argv)); 561cddcb259SBaptiste Daroussin } 562