Index: head/usr.sbin/sesutil/Makefile =================================================================== --- head/usr.sbin/sesutil/Makefile (revision 287987) +++ head/usr.sbin/sesutil/Makefile (revision 287988) @@ -1,6 +1,7 @@ # $FreeBSD$ PROG= sesutil +SRCS= sesutil.c eltsub.c MAN= sesutil.8 .include Index: head/usr.sbin/sesutil/eltsub.c =================================================================== --- head/usr.sbin/sesutil/eltsub.c (nonexistent) +++ head/usr.sbin/sesutil/eltsub.c (revision 287988) @@ -0,0 +1,194 @@ +/* $FreeBSD$ */ +/* + * Copyright (c) 2000 by Matthew Jacob + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * the GNU Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Matthew Jacob + * Feral Software + * mjacob@feral.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "eltsub.h" + +char * +geteltnm(int type) +{ + static char rbuf[132]; + + switch (type) { + case ELMTYP_UNSPECIFIED: + sprintf(rbuf, "Unspecified"); + break; + case ELMTYP_DEVICE: + sprintf(rbuf, "Device Slot"); + break; + case ELMTYP_POWER: + sprintf(rbuf, "Power Supply"); + break; + case ELMTYP_FAN: + sprintf(rbuf, "Cooling"); + break; + case ELMTYP_THERM: + sprintf(rbuf, "Temperature Sensors"); + break; + case ELMTYP_DOORLOCK: + sprintf(rbuf, "Door Lock"); + break; + case ELMTYP_ALARM: + sprintf(rbuf, "Audible alarm"); + break; + case ELMTYP_ESCC: + sprintf(rbuf, "Enclosure Services Controller Electronics"); + break; + case ELMTYP_SCC: + sprintf(rbuf, "SCC Controller Electronics"); + break; + case ELMTYP_NVRAM: + sprintf(rbuf, "Nonvolatile Cache"); + break; + case ELMTYP_INV_OP_REASON: + sprintf(rbuf, "Invalid Operation Reason"); + break; + case ELMTYP_UPS: + sprintf(rbuf, "Uninterruptible Power Supply"); + break; + case ELMTYP_DISPLAY: + sprintf(rbuf, "Display"); + break; + case ELMTYP_KEYPAD: + sprintf(rbuf, "Key Pad Entry"); + break; + case ELMTYP_ENCLOSURE: + sprintf(rbuf, "Enclosure"); + break; + case ELMTYP_SCSIXVR: + sprintf(rbuf, "SCSI Port/Transceiver"); + break; + case ELMTYP_LANGUAGE: + sprintf(rbuf, "Language"); + break; + case ELMTYP_COMPORT: + sprintf(rbuf, "Communication Port"); + break; + case ELMTYP_VOM: + sprintf(rbuf, "Voltage Sensor"); + break; + case ELMTYP_AMMETER: + sprintf(rbuf, "Current Sensor"); + break; + case ELMTYP_SCSI_TGT: + sprintf(rbuf, "SCSI Target Port"); + break; + case ELMTYP_SCSI_INI: + sprintf(rbuf, "SCSI Initiator Port"); + break; + case ELMTYP_SUBENC: + sprintf(rbuf, "Simple Subenclosure"); + break; + case ELMTYP_ARRAY_DEV: + sprintf(rbuf, "Array Device Slot"); + break; + case ELMTYP_SAS_EXP: + sprintf(rbuf, "SAS Expander"); + break; + case ELMTYP_SAS_CONN: + sprintf(rbuf, "SAS Connector"); + break; + default: + (void) sprintf(rbuf, "", type); + break; + } + return (rbuf); +} + +static char * +scode2ascii(u_char code) +{ + static char rbuf[32]; + switch (code & 0xf) { + case SES_OBJSTAT_UNSUPPORTED: + sprintf(rbuf, "Unsupported"); + break; + case SES_OBJSTAT_OK: + sprintf(rbuf, "OK"); + break; + case SES_OBJSTAT_CRIT: + sprintf(rbuf, "Critical"); + break; + case SES_OBJSTAT_NONCRIT: + sprintf(rbuf, "Noncritical"); + break; + case SES_OBJSTAT_UNRECOV: + sprintf(rbuf, "Unrecoverable"); + break; + case SES_OBJSTAT_NOTINSTALLED: + sprintf(rbuf, "Not Installed"); + break; + case SES_OBJSTAT_UNKNOWN: + sprintf(rbuf, "Unknown"); + break; + case SES_OBJSTAT_NOTAVAIL: + sprintf(rbuf, "Not Available"); + break; + case SES_OBJSTAT_NOACCESS: + sprintf(rbuf, "No Access Allowed"); + break; + default: + sprintf(rbuf, "", code & 0xf); + break; + } + return (rbuf); +} + + +char * +stat2ascii(int eletype, u_char *cstat) +{ + static char ebuf[256], *scode; + + scode = scode2ascii(cstat[0]); + sprintf(ebuf, "%s%s%s%s%s%s (0x%02x 0x%02x 0x%02x 0x%02x)", + scode, + (cstat[0] & 0x40) ? ", Prd.Fail" : "", + (cstat[0] & 0x20) ? ", Disabled" : "", + (cstat[0] & 0x10) ? ", Swapped" : "", + (eletype == ELMTYP_DEVICE && (cstat[2] & 0x02)) ? + ", LED=Locate" : "", + (eletype == ELMTYP_DEVICE && (cstat[3] & 0x20)) ? + ", LED=Fault" : "", + cstat[0], cstat[1], cstat[2], cstat[3]); + return (ebuf); +} Property changes on: head/usr.sbin/sesutil/eltsub.c ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Index: head/usr.sbin/sesutil/eltsub.h =================================================================== --- head/usr.sbin/sesutil/eltsub.h (nonexistent) +++ head/usr.sbin/sesutil/eltsub.h (revision 287988) @@ -0,0 +1,36 @@ +/* $FreeBSD$ */ +/* + * Copyright (c) 2000 by Matthew Jacob + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification, immediately at the beginning of the file. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, this software may be distributed under the terms of the + * the GNU Public License ("GPL"). + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Matthew Jacob + * Feral Software + * mjacob@feral.com + */ + +char * geteltnm(int); +char * stat2ascii(int, u_char *); Property changes on: head/usr.sbin/sesutil/eltsub.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: head/usr.sbin/sesutil/sesutil.8 =================================================================== --- head/usr.sbin/sesutil/sesutil.8 (revision 287987) +++ head/usr.sbin/sesutil/sesutil.8 (revision 287988) @@ -1,73 +1,130 @@ .\" Copyright (c) 2015 Baptiste Daroussin .\" All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" -.Dd September 1, 2015 +.Dd September 6, 2015 .Dt SESUTIL 8 .Os .Sh NAME .Nm sesutil .Nd Utility for managing SCSI Enclosure Services (SES) device .Sh SYNOPSIS .Nm -.Cm locate Ar disk Bq on|off +.Cm fault +.Op Fl u Ar /dev/sesN +.Aq Ar disk | Ar sesid | Li all +.Op on | off +.Nm +.Cm locate +.Op Fl u Ar /dev/sesN +.Aq Ar disk | Ar sesid | Li all +.Op on | off +.Nm +.Cm map +.Op Fl u Ar /dev/sesN +.Nm +.Cm status +.Op Fl u Ar /dev/sesN .Sh DESCRIPTION The .Nm -utility can be used to modify various parameter on SCSI Enclosure Services -(SES) device. +utility can be used to query and modify various parameter of SCSI Enclosure +Services (SES) devices. .Pp List of supported commands: .Bl -tag -width indent -.It Cm locate Ar disk Bq on|off -Change the state of the external LED associated with +.It Cm fault Oo Fl u Ar /dev/sesN Oc Ao Ar disk | Li all Ac Op on | off +Change the state of the external fault LED associated with .Ar disk . .Ar disk can be the device name of the disk, like .Cm da12 , or -.Cm all . +.Ql all . to indicate all disks attached to SES controllers. +.It Cm fault Fl u Ar /dev/sesN Ar sesid Op on | off +Change the state of the external fault LED associated with an element +connected to the SES controller. +.Ar sesid +must be the element ID of a valid item attached to the controller. +Use the +.Cm map +command to list the elements attached to a controller. +.It Cm locate Oo Fl u Ar /dev/sesN Oc Ao Ar disk | Li all Ac Op on | off +Change the state of the external locate LED associated with +.Ar disk . +.Ar disk +can be the device name of the disk, like +.Cm da12 , +or +.Ql all . +to indicate all disks attached to SES controllers. +.It Cm locate Fl u Ar /dev/sesN Ar sesid Op on | off +Change the state of the external locate LED associated with an element +connected to the SES controller. +.Ar sesid +must be the element ID of a valid item attached to the controller. +Use the +.Cm map +command to list the elements attached to a controller. +.It Cm map Op Fl u Ar /dev/sesN +Display a map of all elements connected to the specified +.Xr ses 4 +controller. +If no controller is specified, all controllers are mapped. +.It Cm status Op Fl u Ar /dev/sesN +Display the status of the specified +.Xr ses 4 +controller. +If no controller is specified, the status of each controller is returned. .El .Sh EXAMPLES -Turn off all external LEDs: +Turn off all locate LEDs: .Pp .Dl Nm Cm locate all off .Pp -Turn on the external LED of drive +Turn on the locate LED for the drive bay corresponding to .Pa da15 : .Pp .Dl Nm Cm locate da15 on +.Pp +Turn on the fault LED for a drive bay not associated with a device: +.Pp +.Dl Nm Cm fault -u /dev/ses2 7 on .Sh SEE ALSO .Xr ses 4 .Sh HISTORY The .Nm utility first appeared in .Fx 11.0 . .Sh AUTHORS +.An -nosplit The -.Nm utility was written by -.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org . +.Nm +utility was written by +.An Baptiste Daroussin Aq Mt bapt@FreeBSD.org +and +.An Allan Jude Aq Mt allanjude@FreeBSD.org . Index: head/usr.sbin/sesutil/sesutil.c =================================================================== --- head/usr.sbin/sesutil/sesutil.c (revision 287987) +++ head/usr.sbin/sesutil/sesutil.c (revision 287988) @@ -1,224 +1,538 @@ /*- * Copyright (c) 2015 Baptiste Daroussin + * Copyright (c) 2015 Allan Jude + * Copyright (c) 2000 by Matthew Jacob * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include +#include "eltsub.h" + +static int encstatus(int argc, char **argv); +static int fault(int argc, char **argv); static int locate(int argc, char **argv); +static int objmap(int argc, char **argv); +static int sesled(int argc, char **argv, bool fault); static struct command { const char *name; + const char *param; const char *desc; int (*exec)(int argc, char **argv); } cmds[] = { - { "locate", "Change the state of the external LED associated with a" - " disk", locate} , + { "fault", + "(||all) (on|off)", + "Change the state of the fault LED associated with a disk", + fault }, + { "locate", + "(||all) (on|off)", + "Change the state of the locate LED associated with a disk", + locate }, + { "map", "", + "Print a map of the devices managed by the enclosure", objmap } , + { "status", "", "Print the status of the enclosure", + encstatus }, }; static const int nbcmds = nitems(cmds); +static const char *uflag; static void -do_locate(int fd, unsigned int idx, bool onoff) +usage(FILE *out, const char *subcmd) { + int i; + + if (subcmd == NULL) { + fprintf(out, "Usage: %s [-u /dev/ses] [options]\n", + getprogname()); + fprintf(out, "Commands supported:\n"); + } + for (i = 0; i < nbcmds; i++) { + if (subcmd != NULL) { + if (strcmp(subcmd, cmds[i].name) == 0) { + fprintf(out, "Usage: %s %s [-u /dev/ses] " + "%s\n\t%s\n", getprogname(), subcmd, + cmds[i].param, cmds[i].desc); + break; + } + continue; + } + fprintf(out, " %-12s%s\n\t\t%s\n\n", cmds[i].name, + cmds[i].param, cmds[i].desc); + } + + exit(EXIT_FAILURE); +} + +static void +do_led(int fd, unsigned int idx, bool onoff, bool fault) +{ encioc_elm_status_t o; o.elm_idx = idx; if (ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t) &o) < 0) { close(fd); err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); } o.cstat[0] |= 0x80; - if (onoff) - o.cstat[2] |= 0x02; - else - o.cstat[2] &= 0xfd; + if (onoff) { + o.cstat[2] |= (fault ? 0x20 : 0x02); + } else { + o.cstat[2] &= (fault ? 0xdf : 0xfd); + } if (ioctl(fd, ENCIOC_SETELMSTAT, (caddr_t) &o) < 0) { close(fd); err(EXIT_FAILURE, "ENCIOC_SETELMSTAT"); } } static bool disk_match(const char *devnames, const char *disk, size_t len) { const char *dname; dname = devnames; while ((dname = strstr(dname, disk)) != NULL) { - if (dname[len] == '\0' || dname[len] == ',') + if (dname[len] == '\0' || dname[len] == ',') { return (true); + } dname++; } + return (false); } static int -locate(int argc, char **argv) +sesled(int argc, char **argv, bool fault) { encioc_elm_devnames_t objdn; encioc_element_t *objp; glob_t g; - char *disk; - size_t len, i; - int fd, nobj, j; - bool all = false; - bool onoff; + char *disk, *endptr; + size_t len, i, ndisks; + int fd; + unsigned int nobj, j, sesid; + bool all, isses, onoff; - if (argc != 2) { - errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]", - getprogname()); + isses = false; + all = false; + onoff = false; + + if (argc != 3) { + usage(stderr, (fault ? "fault" : "locate")); } - disk = argv[0]; + disk = argv[1]; - if (strcmp(argv[1], "on") == 0) { + sesid = strtoul(disk, &endptr, 10); + if (*endptr == '\0') { + endptr = strrchr(uflag, '*'); + if (*endptr == '*') { + warnx("Must specifying a SES device (-u) to use a SES " + "id# to identify a disk"); + usage(stderr, (fault ? "fault" : "locate")); + } + isses = true; + } + + if (strcmp(argv[2], "on") == 0) { onoff = true; - } else if (strcmp(argv[1], "off") == 0) { + } else if (strcmp(argv[2], "off") == 0) { onoff = false; } else { - errx(EXIT_FAILURE, "usage: %s locate [disk] [on|off]", - getprogname()); + usage(stderr, (fault ? "fault" : "locate")); } if (strcmp(disk, "all") == 0) { all = true; } len = strlen(disk); /* Get the list of ses devices */ - if (glob("/dev/ses[0-9]*", 0, NULL, &g) == GLOB_NOMATCH) { + if (glob((uflag != NULL ? uflag : "/dev/ses[0-9]*"), 0, NULL, &g) == + GLOB_NOMATCH) { globfree(&g); errx(EXIT_FAILURE, "No SES devices found"); } + + ndisks = 0; for (i = 0; i < g.gl_pathc; i++) { /* ensure we only got numbers after ses */ if (strspn(g.gl_pathv[i] + 8, "0123456789") != - strlen(g.gl_pathv[i] + 8)) + strlen(g.gl_pathv[i] + 8)) { continue; + } if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { - if (errno == EACCES) - err(EXIT_FAILURE, "enable to access SES device"); - break; + /* + * Don't treat non-access errors as critical if we are + * accessing all devices + */ + if (errno == EACCES && g.gl_pathc > 1) { + err(EXIT_FAILURE, "unable to access SES device"); + } + warn("unable to access SES device: %s", g.gl_pathv[i]); + continue; } - if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) + if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { + close(fd); err(EXIT_FAILURE, "ENCIOC_GETNELM"); + } objp = calloc(nobj, sizeof(encioc_element_t)); - if (objp == NULL) + if (objp == NULL) { + close(fd); err(EXIT_FAILURE, "calloc()"); + } - if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) + if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) objp) < 0) { + close(fd); err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); + } + if (isses) { + if (sesid > nobj) { + close(fd); + errx(EXIT_FAILURE, + "Requested SES ID does not exist"); + } + do_led(fd, sesid, onoff, fault); + ndisks++; + close(fd); + break; + } for (j = 0; j < nobj; j++) { memset(&objdn, 0, sizeof(objdn)); objdn.elm_idx = objp[j].elm_idx; objdn.elm_names_size = 128; objdn.elm_devnames = calloc(128, sizeof(char)); - if (objdn.elm_devnames == NULL) + if (objdn.elm_devnames == NULL) { + close(fd); err(EXIT_FAILURE, "calloc()"); + } if (ioctl(fd, ENCIOC_GETELMDEVNAMES, - (caddr_t) &objdn) <0) + (caddr_t) &objdn) <0) { continue; + } if (objdn.elm_names_len > 0) { if (all) { - do_locate(fd, objdn.elm_idx, onoff); + do_led(fd, objdn.elm_idx, + onoff, fault); continue; } if (disk_match(objdn.elm_devnames, disk, len)) { - do_locate(fd, objdn.elm_idx, onoff); + do_led(fd, objdn.elm_idx, + onoff, fault); + ndisks++; break; } } - } + } close(fd); } globfree(&g); + if (ndisks == 0 && all == false) { + errx(EXIT_FAILURE, "Count not find the SES id of device '%s'", + disk); + } return (EXIT_SUCCESS); } -static void -usage(FILE *out) +static int +locate(int argc, char **argv) { - int i; - fprintf(out, "Usage: %s [command] [options]\n", getprogname()); - fprintf(out, "Commands supported:\n"); - for (i = 0; i < nbcmds; i++) - fprintf(out, "\t%-15s%s\n", cmds[i].name, cmds[i].desc); + return (sesled(argc, argv, false)); } +static int +fault(int argc, char **argv) +{ + + return (sesled(argc, argv, true)); +} + +static int +objmap(int argc, char **argv __unused) +{ + encioc_elm_devnames_t e_devname; + encioc_elm_status_t e_status; + encioc_elm_desc_t e_desc; + encioc_element_t *e_ptr; + glob_t g; + int fd; + unsigned int j, nobj; + size_t i; + + if (argc != 1) { + usage(stderr, "map"); + } + + /* Get the list of ses devices */ + if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { + globfree(&g); + errx(EXIT_FAILURE, "No SES devices found"); + } + for (i = 0; i < g.gl_pathc; i++) { + /* ensure we only got numbers after ses */ + if (strspn(g.gl_pathv[i] + 8, "0123456789") != + strlen(g.gl_pathv[i] + 8)) { + continue; + } + if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { + /* + * Don't treat non-access errors as critical if we are + * accessing all devices + */ + if (errno == EACCES && g.gl_pathc > 1) { + err(EXIT_FAILURE, "unable to access SES device"); + } + warn("unable to access SES device: %s", g.gl_pathv[i]); + continue; + } + + if (ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj) < 0) { + close(fd); + err(EXIT_FAILURE, "ENCIOC_GETNELM"); + } + + e_ptr = calloc(nobj, sizeof(encioc_element_t)); + if (e_ptr == NULL) { + close(fd); + err(EXIT_FAILURE, "calloc()"); + } + + if (ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) e_ptr) < 0) { + close(fd); + err(EXIT_FAILURE, "ENCIOC_GETELMMAP"); + } + + printf("%s:\n", g.gl_pathv[i] + 5); + for (j = 0; j < nobj; j++) { + /* Get the status of the element */ + memset(&e_status, 0, sizeof(e_status)); + e_status.elm_idx = e_ptr[j].elm_idx; + if (ioctl(fd, ENCIOC_GETELMSTAT, + (caddr_t) &e_status) < 0) { + close(fd); + err(EXIT_FAILURE, "ENCIOC_GETELMSTAT"); + } + /* Get the description of the element */ + memset(&e_desc, 0, sizeof(e_desc)); + e_desc.elm_idx = e_ptr[j].elm_idx; + e_desc.elm_desc_len = UINT16_MAX; + e_desc.elm_desc_str = calloc(UINT16_MAX, sizeof(char)); + if (e_desc.elm_desc_str == NULL) { + close(fd); + err(EXIT_FAILURE, "calloc()"); + } + if (ioctl(fd, ENCIOC_GETELMDESC, + (caddr_t) &e_desc) < 0) { + close(fd); + err(EXIT_FAILURE, "ENCIOC_GETELMDESC"); + } + /* Get the device name(s) of the element */ + memset(&e_devname, 0, sizeof(e_devname)); + e_devname.elm_idx = e_ptr[j].elm_idx; + e_devname.elm_names_size = 128; + e_devname.elm_devnames = calloc(128, sizeof(char)); + if (e_devname.elm_devnames == NULL) { + close(fd); + err(EXIT_FAILURE, "calloc()"); + } + if (ioctl(fd, ENCIOC_GETELMDEVNAMES, + (caddr_t) &e_devname) <0) { + /* We don't care if this fails */ + e_devname.elm_devnames[0] = '\0'; + } + printf("\tElement %u, Type: %s\n", e_ptr[j].elm_idx, + geteltnm(e_ptr[j].elm_type)); + printf("\t\tStatus: %s\n", + stat2ascii(e_ptr[i].elm_type, e_status.cstat)); + if (e_desc.elm_desc_len > 0) { + printf("\t\tDescription: %s\n", + e_desc.elm_desc_str); + } + if (e_devname.elm_names_len > 0) { + printf("\t\tDevice Names: %s\n", + e_devname.elm_devnames); + } + free(e_devname.elm_devnames); + } + close(fd); + } + globfree(&g); + + return (EXIT_SUCCESS); +} + +static int +encstatus(int argc, char **argv __unused) +{ + glob_t g; + int fd, status; + size_t i, e; + u_char estat; + + status = 0; + if (argc != 1) { + usage(stderr, "status"); + } + + /* Get the list of ses devices */ + if (glob(uflag, 0, NULL, &g) == GLOB_NOMATCH) { + globfree(&g); + errx(EXIT_FAILURE, "No SES devices found"); + } + for (i = 0; i < g.gl_pathc; i++) { + /* ensure we only got numbers after ses */ + if (strspn(g.gl_pathv[i] + 8, "0123456789") != + strlen(g.gl_pathv[i] + 8)) { + continue; + } + if ((fd = open(g.gl_pathv[i], O_RDWR)) < 0) { + /* + * Don't treat non-access errors as critical if we are + * accessing all devices + */ + if (errno == EACCES && g.gl_pathc > 1) { + err(EXIT_FAILURE, "unable to access SES device"); + } + warn("unable to access SES device: %s", g.gl_pathv[i]); + continue; + } + + if (ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat) < 0) { + close(fd); + err(EXIT_FAILURE, "ENCIOC_GETENCSTAT"); + } + + printf("%s: ", g.gl_pathv[i] + 5); + e = 0; + if (estat == 0) { + if (status == 0) { + status = 1; + } + printf("OK"); + } else { + if (estat & SES_ENCSTAT_INFO) { + printf("INFO"); + e++; + } + if (estat & SES_ENCSTAT_NONCRITICAL) { + if (e) + printf(","); + printf("NONCRITICAL"); + e++; + } + if (estat & SES_ENCSTAT_CRITICAL) { + if (e) + printf(","); + printf("CRITICAL"); + e++; + status = -1; + } + if (estat & SES_ENCSTAT_UNRECOV) { + if (e) + printf(","); + printf("UNRECOV"); + e++; + status = -1; + } + } + printf("\n"); + + close(fd); + } + globfree(&g); + + if (status == 1) { + return (EXIT_SUCCESS); + } else { + return (EXIT_FAILURE); + } +} + int main(int argc, char **argv) { - int i; + int i, ch; struct command *cmd = NULL; - if (argc < 2) { + uflag = "/dev/ses[0-9]*"; + while ((ch = getopt_long(argc, argv, "u:", NULL, NULL)) != -1) { + switch (ch) { + case 'u': + uflag = optarg; + break; + case '?': + default: + usage(stderr, NULL); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { warnx("Missing command"); - usage(stderr); - return (EXIT_FAILURE); + usage(stderr, NULL); } for (i = 0; i < nbcmds; i++) { - if (strcmp(argv[1], cmds[i].name) == 0) { + if (strcmp(argv[0], cmds[i].name) == 0) { cmd = &cmds[i]; break; } } if (cmd == NULL) { - warnx("unknown command %s", argv[1]); - usage(stderr); - return (EXIT_FAILURE); + warnx("unknown command %s", argv[0]); + usage(stderr, NULL); } - - argc-=2; - argv+=2; return (cmd->exec(argc, argv)); }