1 /*- 2 * Copyright (C) 2021 Axcient, Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 * $FreeBSD$ 26 */ 27 28 /* Basic smoke test of the ioctl interface */ 29 30 #include <sys/types.h> 31 #include <sys/ioctl.h> 32 33 #include <atf-c.h> 34 #include <fcntl.h> 35 #include <glob.h> 36 #include <regex.h> 37 #include <stdint.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 41 #include <cam/scsi/scsi_enc.h> 42 43 #include "common.h" 44 45 static bool do_getelmdesc(const char *devname, int fd) { 46 regex_t re; 47 FILE *pipe; 48 char cmd[256]; 49 char line[256]; 50 char *actual; 51 unsigned nobj; 52 unsigned elm_idx = 0; 53 int r; 54 55 actual = calloc(UINT16_MAX, sizeof(char)); 56 ATF_REQUIRE(actual != NULL); 57 r = regcomp(&re, "(Overall|Element [0-9]+) descriptor: ", REG_EXTENDED); 58 ATF_REQUIRE_EQ(r, 0); 59 60 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 61 ATF_REQUIRE_EQ(r, 0); 62 63 snprintf(cmd, sizeof(cmd), "sg_ses -p7 %s", devname); 64 pipe = popen(cmd, "r"); 65 ATF_REQUIRE(pipe != NULL); 66 while(NULL != fgets(line, sizeof(line), pipe)) { 67 regmatch_t matches[1]; 68 encioc_elm_desc_t e_desc; 69 char *expected; 70 size_t elen; 71 72 if (regexec(&re, line, 1, matches, 0) == REG_NOMATCH) { 73 continue; 74 } 75 76 expected = &line[matches[0].rm_eo]; 77 /* Remove trailing newline */ 78 elen = strnlen(expected, sizeof(line) - matches[0].rm_eo); 79 expected[elen - 1] = '\0'; 80 /* 81 * Zero the result string. XXX we wouldn't have to do this if 82 * the kernel would nul-terminate the result. 83 */ 84 memset(actual, 0, UINT16_MAX); 85 e_desc.elm_idx = elm_idx; 86 e_desc.elm_desc_len = UINT16_MAX; 87 e_desc.elm_desc_str = actual; 88 r = ioctl(fd, ENCIOC_GETELMDESC, (caddr_t) &e_desc); 89 ATF_REQUIRE_EQ(r, 0); 90 if (0 == strcmp("<empty>", expected)) { 91 /* sg_ses replaces "" with "<empty>" */ 92 ATF_CHECK_STREQ("", actual); 93 } else 94 ATF_CHECK_STREQ(expected, actual); 95 elm_idx++; 96 } 97 98 r = pclose(pipe); 99 regfree(&re); 100 free(actual); 101 if (r != 0) { 102 /* Probably an SGPIO device */ 103 104 return (false); 105 } else { 106 ATF_CHECK_EQ_MSG(nobj, elm_idx, 107 "Did not find the expected number of element " 108 "descriptors in sg_ses's output"); 109 return (true); 110 } 111 } 112 113 ATF_TC(getelmdesc); 114 ATF_TC_HEAD(getelmdesc, tc) 115 { 116 atf_tc_set_md_var(tc, "descr", 117 "Compare ENCIOC_GETELMDESC's output to sg3_utils'"); 118 atf_tc_set_md_var(tc, "require.user", "root"); 119 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 120 } 121 ATF_TC_BODY(getelmdesc, tc) 122 { 123 if (!has_ses()) 124 atf_tc_skip("No ses devices found"); 125 for_each_ses_dev(do_getelmdesc, O_RDONLY); 126 } 127 128 static bool do_getelmdevnames(const char *devname __unused, int fd) { 129 encioc_element_t *map; 130 unsigned nobj; 131 const size_t namesize = 128; 132 int r; 133 char *namebuf; 134 unsigned elm_idx; 135 136 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 137 ATF_REQUIRE_EQ(r, 0); 138 139 namebuf = calloc(namesize, sizeof(char)); 140 ATF_REQUIRE(namebuf != NULL); 141 map = calloc(nobj, sizeof(encioc_element_t)); 142 ATF_REQUIRE(map != NULL); 143 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 144 ATF_REQUIRE_EQ(r, 0); 145 146 for (elm_idx = 0; elm_idx < nobj; elm_idx++) { 147 /* 148 * devnames should be present if: 149 * * The element is of type Device Slot or Array Device Slot 150 * * It isn't an Overall Element 151 * * The element's status is not "Not Installed" 152 */ 153 encioc_elm_status_t e_status; 154 encioc_elm_devnames_t elmdn; 155 156 memset(&e_status, 0, sizeof(e_status)); 157 e_status.elm_idx = elm_idx; 158 r = ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t)&e_status); 159 ATF_REQUIRE_EQ(r, 0); 160 161 memset(&elmdn, 0, sizeof(elmdn)); 162 elmdn.elm_idx = elm_idx; 163 elmdn.elm_names_size = namesize; 164 elmdn.elm_devnames = namebuf; 165 namebuf[0] = '\0'; 166 r = ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t) &elmdn); 167 if (e_status.cstat[0] != SES_OBJSTAT_UNSUPPORTED && 168 e_status.cstat[0] != SES_OBJSTAT_NOTINSTALLED && 169 (map[elm_idx].elm_type == ELMTYP_DEVICE || 170 map[elm_idx].elm_type == ELMTYP_ARRAY_DEV)) 171 { 172 ATF_CHECK_EQ_MSG(r, 0, "devnames not found. This could be due to a buggy ses driver, buggy ses controller, dead HDD, or an ATA HDD in a SAS slot"); 173 } else { 174 ATF_CHECK(r != 0); 175 } 176 177 if (r == 0) { 178 size_t z = 0; 179 int da = 0, ada = 0, pass = 0, nvd = 0; 180 int nvme = 0, unknown = 0; 181 182 while(elmdn.elm_devnames[z] != '\0') { 183 size_t e; 184 char *s; 185 186 if (elmdn.elm_devnames[z] == ',') 187 z++; /* Skip the comma */ 188 s = elmdn.elm_devnames + z; 189 e = strcspn(s, "0123456789"); 190 if (0 == strncmp("da", s, e)) 191 da++; 192 else if (0 == strncmp("ada", s, e)) 193 ada++; 194 else if (0 == strncmp("pass", s, e)) 195 pass++; 196 else if (0 == strncmp("nvd", s, e)) 197 nvd++; 198 else if (0 == strncmp("nvme", s, e)) 199 nvme++; 200 else 201 unknown++; 202 z += strcspn(elmdn.elm_devnames + z, ","); 203 } 204 /* There should be one pass dev for each non-pass dev */ 205 ATF_CHECK_EQ(pass, da + ada + nvd + nvme); 206 ATF_CHECK_EQ_MSG(0, unknown, 207 "Unknown device names %s", elmdn.elm_devnames); 208 } 209 } 210 free(map); 211 free(namebuf); 212 213 return (true); 214 } 215 216 ATF_TC(getelmdevnames); 217 ATF_TC_HEAD(getelmdevnames, tc) 218 { 219 atf_tc_set_md_var(tc, "descr", 220 "Compare ENCIOC_GETELMDEVNAMES's output to sg3_utils'"); 221 atf_tc_set_md_var(tc, "require.user", "root"); 222 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 223 } 224 ATF_TC_BODY(getelmdevnames, tc) 225 { 226 if (!has_ses()) 227 atf_tc_skip("No ses devices found"); 228 for_each_ses_dev(do_getelmdevnames, O_RDONLY); 229 } 230 231 static int 232 elm_type_name2int(const char *name) { 233 const char *elm_type_names[] = ELM_TYPE_NAMES; 234 int i; 235 236 for (i = 0; i <= ELMTYP_LAST; i++) { 237 /* sg_ses uses different case than ses(4) */ 238 if (0 == strcasecmp(name, elm_type_names[i])) 239 return i; 240 } 241 return (-1); 242 } 243 244 static bool do_getelmmap(const char *devname, int fd) { 245 encioc_element_t *map; 246 FILE *pipe; 247 char cmd[256]; 248 char line[256]; 249 unsigned elm_idx = 0; 250 unsigned nobj, subenc_id; 251 int r, elm_type; 252 253 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 254 ATF_REQUIRE_EQ(r, 0); 255 256 map = calloc(nobj, sizeof(encioc_element_t)); 257 ATF_REQUIRE(map != NULL); 258 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 259 ATF_REQUIRE_EQ(r, 0); 260 261 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 262 pipe = popen(cmd, "r"); 263 ATF_REQUIRE(pipe != NULL); 264 while(NULL != fgets(line, sizeof(line), pipe)) { 265 char elm_type_name[80]; 266 int i, num_elm; 267 268 r = sscanf(line, 269 " Element type: %[a-zA-Z0-9_ /], subenclosure id: %d", 270 elm_type_name, &subenc_id); 271 if (r == 2) { 272 elm_type = elm_type_name2int(elm_type_name); 273 continue; 274 } else { 275 r = sscanf(line, 276 " Element type: vendor specific [0x%x], subenclosure id: %d", 277 &elm_type, &subenc_id); 278 if (r == 2) 279 continue; 280 } 281 r = sscanf(line, " number of possible elements: %d", 282 &num_elm); 283 if (r != 1) 284 continue; 285 286 /* Skip the Overall elements */ 287 elm_idx++; 288 for (i = 0; i < num_elm; i++, elm_idx++) { 289 ATF_CHECK_EQ(map[elm_idx].elm_idx, elm_idx); 290 ATF_CHECK_EQ(map[elm_idx].elm_subenc_id, subenc_id); 291 ATF_CHECK_EQ((int)map[elm_idx].elm_type, elm_type); 292 } 293 } 294 295 free(map); 296 r = pclose(pipe); 297 if (r != 0) { 298 /* Probably an SGPIO device */ 299 return (false); 300 } else { 301 ATF_CHECK_EQ_MSG(nobj, elm_idx, 302 "Did not find the expected number of element " 303 "descriptors in sg_ses's output"); 304 return (true); 305 } 306 } 307 308 ATF_TC(getelmmap); 309 ATF_TC_HEAD(getelmmap, tc) 310 { 311 atf_tc_set_md_var(tc, "descr", 312 "Compare ENCIOC_GETELMMAP's output to sg3_utils'"); 313 atf_tc_set_md_var(tc, "require.user", "root"); 314 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 315 } 316 ATF_TC_BODY(getelmmap, tc) 317 { 318 if (!has_ses()) 319 atf_tc_skip("No ses devices found"); 320 for_each_ses_dev(do_getelmmap, O_RDONLY); 321 } 322 323 static bool do_getelmstat(const char *devname, int fd) { 324 encioc_element_t *map; 325 unsigned elm_idx; 326 unsigned nobj; 327 int r, elm_subidx; 328 elm_type_t last_elm_type = -1; 329 330 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 331 ATF_REQUIRE_EQ(r, 0); 332 333 map = calloc(nobj, sizeof(encioc_element_t)); 334 ATF_REQUIRE(map != NULL); 335 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 336 337 for (elm_idx = 0; elm_idx < nobj; elm_subidx++, elm_idx++) { 338 encioc_elm_status_t e_status; 339 FILE *pipe; 340 char cmd[256]; 341 uint32_t status; 342 int pr; 343 344 if (last_elm_type != map[elm_idx].elm_type) 345 elm_subidx = -1; 346 last_elm_type = map[elm_idx].elm_type; 347 348 snprintf(cmd, sizeof(cmd), 349 "sg_ses -Hp2 --index=_%d,%d --get=0:7:32 %s", 350 map[elm_idx].elm_type, elm_subidx, devname); 351 pipe = popen(cmd, "r"); 352 ATF_REQUIRE(pipe != NULL); 353 r = fscanf(pipe, "0x%x", &status); 354 pr = pclose(pipe); 355 if (pr != 0) { 356 /* Probably an SGPIO device */ 357 free(map); 358 return (false); 359 } 360 ATF_REQUIRE_EQ(r, 1); 361 362 memset(&e_status, 0, sizeof(e_status)); 363 e_status.elm_idx = map[elm_idx].elm_idx; 364 r = ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t)&e_status); 365 ATF_REQUIRE_EQ(r, 0); 366 367 // Compare the common status field 368 ATF_CHECK_EQ(e_status.cstat[0], status >> 24); 369 /* 370 * Ignore the other fields, because some have values that can 371 * change frequently (voltage, temperature, etc) 372 */ 373 } 374 free(map); 375 376 return (true); 377 } 378 379 ATF_TC(getelmstat); 380 ATF_TC_HEAD(getelmstat, tc) 381 { 382 atf_tc_set_md_var(tc, "descr", 383 "Compare ENCIOC_GETELMSTAT's output to sg3_utils'"); 384 atf_tc_set_md_var(tc, "require.user", "root"); 385 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 386 } 387 ATF_TC_BODY(getelmstat, tc) 388 { 389 if (!has_ses()) 390 atf_tc_skip("No ses devices found"); 391 for_each_ses_dev(do_getelmstat, O_RDONLY); 392 } 393 394 static bool do_getencid(const char *devname, int fd) { 395 encioc_string_t stri; 396 FILE *pipe; 397 char cmd[256]; 398 char encid[32]; 399 char line[256]; 400 char sg_encid[32]; 401 int r, sg_ses_r; 402 403 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 404 pipe = popen(cmd, "r"); 405 ATF_REQUIRE(pipe != NULL); 406 sg_encid[0] = '\0'; 407 while(NULL != fgets(line, sizeof(line), pipe)) { 408 const char *f = " enclosure logical identifier (hex): %s"; 409 410 if (1 == fscanf(pipe, f, sg_encid)) 411 break; 412 } 413 sg_ses_r = pclose(pipe); 414 415 stri.bufsiz = sizeof(encid); 416 stri.buf = &encid[0]; 417 r = ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri); 418 ATF_REQUIRE_EQ(r, 0); 419 if (sg_ses_r == 0) { 420 ATF_REQUIRE(sg_encid[0] != '\0'); 421 ATF_CHECK_STREQ(sg_encid, (char*)stri.buf); 422 return (true); 423 } else { 424 /* Probably SGPIO; sg_ses unsupported */ 425 return (false); 426 } 427 } 428 429 ATF_TC(getencid); 430 ATF_TC_HEAD(getencid, tc) 431 { 432 atf_tc_set_md_var(tc, "descr", 433 "Compare ENCIOC_GETENCID's output to sg3_utils'"); 434 atf_tc_set_md_var(tc, "require.user", "root"); 435 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 436 } 437 ATF_TC_BODY(getencid, tc) 438 { 439 if (!has_ses()) 440 atf_tc_skip("No ses devices found"); 441 for_each_ses_dev(do_getencid, O_RDONLY); 442 } 443 444 static bool do_getencname(const char *devname, int fd) { 445 encioc_string_t stri; 446 FILE *pipe; 447 char cmd[256]; 448 char encname[32]; 449 char line[256]; 450 int r; 451 452 snprintf(cmd, sizeof(cmd), "sg_inq -o %s | awk '" 453 "/Vendor identification/ {vi=$NF} " 454 "/Product identification/ {pi=$NF} " 455 "/Product revision level/ {prl=$NF} " 456 "END {printf(vi \" \" pi \" \" prl)}'", devname); 457 pipe = popen(cmd, "r"); 458 ATF_REQUIRE(pipe != NULL); 459 ATF_REQUIRE(NULL != fgets(line, sizeof(line), pipe)); 460 pclose(pipe); 461 462 stri.bufsiz = sizeof(encname); 463 stri.buf = &encname[0]; 464 r = ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri); 465 ATF_REQUIRE_EQ(r, 0); 466 if (strlen(line) < 3) { 467 // Probably an SGPIO device, INQUIRY unsupported 468 return (false); 469 } else { 470 ATF_CHECK_STREQ(line, (char*)stri.buf); 471 return (true); 472 } 473 } 474 475 ATF_TC(getencname); 476 ATF_TC_HEAD(getencname, tc) 477 { 478 atf_tc_set_md_var(tc, "descr", 479 "Compare ENCIOC_GETENCNAME's output to sg3_utils'"); 480 atf_tc_set_md_var(tc, "require.user", "root"); 481 atf_tc_set_md_var(tc, "require.progs", "sg_inq"); 482 } 483 ATF_TC_BODY(getencname, tc) 484 { 485 if (!has_ses()) 486 atf_tc_skip("No ses devices found"); 487 for_each_ses_dev(do_getencname, O_RDONLY); 488 } 489 490 static bool do_getencstat(const char *devname, int fd) { 491 FILE *pipe; 492 char cmd[256]; 493 unsigned char e, estat, invop, info, noncrit, crit, unrecov; 494 int r; 495 496 snprintf(cmd, sizeof(cmd), "sg_ses -p2 %s " 497 "| grep 'INVOP='", 498 devname); 499 pipe = popen(cmd, "r"); 500 ATF_REQUIRE(pipe != NULL); 501 r = fscanf(pipe, 502 " INVOP=%hhu, INFO=%hhu, NON-CRIT=%hhu, CRIT=%hhu, UNRECOV=%hhu", 503 &invop, &info, &noncrit, &crit, &unrecov); 504 pclose(pipe); 505 if (r != 5) { 506 /* Probably on SGPIO device */ 507 return (false); 508 } else { 509 r = ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat); 510 ATF_REQUIRE_EQ(r, 0); 511 /* Exclude the info bit because it changes frequently */ 512 e = (invop << 4) | (noncrit << 2) | (crit << 1) | unrecov; 513 ATF_CHECK_EQ(estat & ~0x08, e); 514 return (true); 515 } 516 } 517 518 ATF_TC(getencstat); 519 ATF_TC_HEAD(getencstat, tc) 520 { 521 atf_tc_set_md_var(tc, "descr", 522 "Compare ENCIOC_GETENCSTAT's output to sg3_utils'"); 523 atf_tc_set_md_var(tc, "require.user", "root"); 524 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 525 } 526 ATF_TC_BODY(getencstat, tc) 527 { 528 if (!has_ses()) 529 atf_tc_skip("No ses devices found"); 530 for_each_ses_dev(do_getencstat, O_RDONLY); 531 } 532 533 static bool do_getnelm(const char *devname, int fd) { 534 FILE *pipe; 535 char cmd[256]; 536 char line[256]; 537 unsigned nobj, expected = 0; 538 int r, sg_ses_r; 539 540 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 541 pipe = popen(cmd, "r"); 542 ATF_REQUIRE(pipe != NULL); 543 544 while(NULL != fgets(line, sizeof(line), pipe)) { 545 unsigned nelm; 546 547 if (1 == fscanf(pipe, " number of possible elements: %u", 548 &nelm)) 549 { 550 expected += 1 + nelm; // +1 for the Overall element 551 } 552 } 553 sg_ses_r = pclose(pipe); 554 555 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 556 ATF_REQUIRE_EQ(r, 0); 557 if (sg_ses_r == 0) { 558 ATF_CHECK_EQ(expected, nobj); 559 return (true); 560 } else { 561 /* Probably SGPIO, sg_ses unsupported */ 562 return (false); 563 } 564 } 565 566 ATF_TC(getnelm); 567 ATF_TC_HEAD(getnelm, tc) 568 { 569 atf_tc_set_md_var(tc, "descr", 570 "Compare ENCIOC_GETNELM's output to sg3_utils'"); 571 atf_tc_set_md_var(tc, "require.user", "root"); 572 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 573 } 574 ATF_TC_BODY(getnelm, tc) 575 { 576 if (!has_ses()) 577 atf_tc_skip("No ses devices found"); 578 for_each_ses_dev(do_getnelm, O_RDONLY); 579 } 580 581 static bool do_getstring(const char *devname, int fd) { 582 FILE *pipe; 583 char cmd[256]; 584 char *sg_ses_buf, *ses_buf; 585 ssize_t sg_ses_count; 586 encioc_string_t str_in; 587 int r; 588 589 sg_ses_buf = malloc(65535); 590 ATF_REQUIRE(sg_ses_buf != NULL); 591 ses_buf = malloc(65535); 592 ATF_REQUIRE(ses_buf != NULL); 593 594 snprintf(cmd, sizeof(cmd), "sg_ses -p4 -rr %s", devname); 595 pipe = popen(cmd, "r"); 596 ATF_REQUIRE(pipe != NULL); 597 sg_ses_count = fread(sg_ses_buf, 1, 65535, pipe); 598 r = pclose(pipe); 599 if (r != 0) { 600 // This SES device does not support the STRINGIN diagnostic page 601 return (false); 602 } 603 ATF_REQUIRE(sg_ses_count > 0); 604 605 str_in.bufsiz = 65535; 606 str_in.buf = ses_buf; 607 r = ioctl(fd, ENCIOC_GETSTRING, (caddr_t) &str_in); 608 ATF_REQUIRE_EQ(r, 0); 609 ATF_CHECK_EQ(sg_ses_count, (ssize_t)str_in.bufsiz); 610 ATF_CHECK_EQ(0, memcmp(sg_ses_buf, ses_buf, str_in.bufsiz)); 611 612 free(ses_buf); 613 free(sg_ses_buf); 614 615 return (true); 616 } 617 618 ATF_TC(getstring); 619 ATF_TC_HEAD(getstring, tc) 620 { 621 atf_tc_set_md_var(tc, "descr", 622 "Compare ENCIOC_GETSTRING's output to sg3_utils'"); 623 atf_tc_set_md_var(tc, "require.user", "root"); 624 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 625 } 626 ATF_TC_BODY(getstring, tc) 627 { 628 if (!has_ses()) 629 atf_tc_skip("No ses devices found"); 630 atf_tc_expect_fail("Bug 258188 ENCIO_GETSTRING does not set the string's returned size"); 631 for_each_ses_dev(do_getstring, O_RDWR); 632 } 633 634 ATF_TP_ADD_TCS(tp) 635 { 636 637 /* 638 * Untested ioctls: 639 * 640 * * ENCIOC_GETTEXT because it was never implemented 641 * 642 */ 643 ATF_TP_ADD_TC(tp, getelmdesc); 644 ATF_TP_ADD_TC(tp, getelmdevnames); 645 ATF_TP_ADD_TC(tp, getelmmap); 646 ATF_TP_ADD_TC(tp, getelmstat); 647 ATF_TP_ADD_TC(tp, getencid); 648 ATF_TP_ADD_TC(tp, getencname); 649 ATF_TP_ADD_TC(tp, getencstat); 650 ATF_TP_ADD_TC(tp, getnelm); 651 ATF_TP_ADD_TC(tp, getstring); 652 653 return (atf_no_error()); 654 } 655