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 26 /* Basic smoke test of the ioctl interface */ 27 28 #include <sys/types.h> 29 #include <sys/ioctl.h> 30 31 #include <atf-c.h> 32 #include <fcntl.h> 33 #include <glob.h> 34 #include <regex.h> 35 #include <stdint.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 39 #include <cam/scsi/scsi_enc.h> 40 41 #include "common.h" 42 43 static bool 44 do_getelmdesc(const char *devname, int fd) 45 { 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 129 do_getelmdevnames(const char *devname __unused, int fd) 130 { 131 encioc_element_t *map; 132 unsigned nobj; 133 const size_t namesize = 128; 134 int r, status; 135 char *namebuf; 136 unsigned elm_idx; 137 138 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 139 ATF_REQUIRE_EQ(r, 0); 140 141 namebuf = calloc(namesize, sizeof(char)); 142 ATF_REQUIRE(namebuf != NULL); 143 map = calloc(nobj, sizeof(encioc_element_t)); 144 ATF_REQUIRE(map != NULL); 145 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 146 ATF_REQUIRE_EQ(r, 0); 147 148 for (elm_idx = 0; elm_idx < nobj; elm_idx++) { 149 /* 150 * devnames should be present if: 151 * * The element is of type Device Slot or Array Device Slot 152 * * It isn't an Overall Element 153 * * The element's status is not "Not Installed" 154 */ 155 encioc_elm_status_t e_status; 156 encioc_elm_devnames_t elmdn; 157 158 memset(&e_status, 0, sizeof(e_status)); 159 e_status.elm_idx = elm_idx; 160 r = ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t)&e_status); 161 ATF_REQUIRE_EQ(r, 0); 162 163 memset(&elmdn, 0, sizeof(elmdn)); 164 elmdn.elm_idx = elm_idx; 165 elmdn.elm_names_size = namesize; 166 elmdn.elm_devnames = namebuf; 167 namebuf[0] = '\0'; 168 r = ioctl(fd, ENCIOC_GETELMDEVNAMES, (caddr_t) &elmdn); 169 status = ses_status_common_get_element_status_code( 170 (struct ses_status_common*)&e_status.cstat[0]); 171 if (status != SES_OBJSTAT_UNSUPPORTED && 172 status != SES_OBJSTAT_NOTINSTALLED && 173 (map[elm_idx].elm_type == ELMTYP_DEVICE || 174 map[elm_idx].elm_type == ELMTYP_ARRAY_DEV)) 175 { 176 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"); 177 } else { 178 ATF_CHECK(r != 0); 179 } 180 181 if (r == 0) { 182 size_t z = 0; 183 int da = 0, ada = 0, pass = 0, nda = 0, unknown = 0; 184 185 while(elmdn.elm_devnames[z] != '\0') { 186 size_t e; 187 char *s; 188 189 if (elmdn.elm_devnames[z] == ',') 190 z++; /* Skip the comma */ 191 s = elmdn.elm_devnames + z; 192 e = strcspn(s, "0123456789"); 193 if (0 == strncmp("da", s, e)) 194 da++; 195 else if (0 == strncmp("ada", s, e)) 196 ada++; 197 else if (0 == strncmp("pass", s, e)) 198 pass++; 199 else if (0 == strncmp("nda", s, e)) 200 nda++; 201 else 202 unknown++; 203 z += strcspn(elmdn.elm_devnames + z, ","); 204 } 205 /* There should be one pass dev for each non-pass dev */ 206 ATF_CHECK_EQ(pass, da + ada + nda); 207 ATF_CHECK_EQ_MSG(0, unknown, 208 "Unknown device names %s", elmdn.elm_devnames); 209 } 210 } 211 free(map); 212 free(namebuf); 213 214 return (true); 215 } 216 217 ATF_TC(getelmdevnames); 218 ATF_TC_HEAD(getelmdevnames, tc) 219 { 220 atf_tc_set_md_var(tc, "descr", 221 "Compare ENCIOC_GETELMDEVNAMES's output to sg3_utils'"); 222 atf_tc_set_md_var(tc, "require.user", "root"); 223 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 224 } 225 ATF_TC_BODY(getelmdevnames, tc) 226 { 227 if (!has_ses()) 228 atf_tc_skip("No ses devices found"); 229 for_each_ses_dev(do_getelmdevnames, O_RDONLY); 230 } 231 232 static int 233 elm_type_name2int(const char *name) 234 { 235 const char *elm_type_names[] = ELM_TYPE_NAMES; 236 int i; 237 238 for (i = 0; i <= ELMTYP_LAST; i++) { 239 /* sg_ses uses different case than ses(4) */ 240 if (0 == strcasecmp(name, elm_type_names[i])) 241 return i; 242 } 243 return (-1); 244 } 245 246 static bool 247 do_getelmmap(const char *devname, int fd) 248 { 249 encioc_element_t *map; 250 FILE *pipe; 251 char cmd[256]; 252 char line[256]; 253 unsigned elm_idx = 0; 254 unsigned nobj, subenc_id; 255 int r, elm_type; 256 257 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 258 ATF_REQUIRE_EQ(r, 0); 259 260 map = calloc(nobj, sizeof(encioc_element_t)); 261 ATF_REQUIRE(map != NULL); 262 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 263 ATF_REQUIRE_EQ(r, 0); 264 265 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 266 pipe = popen(cmd, "r"); 267 ATF_REQUIRE(pipe != NULL); 268 while(NULL != fgets(line, sizeof(line), pipe)) { 269 char elm_type_name[80]; 270 int i, num_elm; 271 272 r = sscanf(line, 273 " Element type: %[a-zA-Z0-9_ /], subenclosure id: %d", 274 elm_type_name, &subenc_id); 275 if (r == 2) { 276 elm_type = elm_type_name2int(elm_type_name); 277 continue; 278 } else { 279 r = sscanf(line, 280 " Element type: vendor specific [0x%x], subenclosure id: %d", 281 &elm_type, &subenc_id); 282 if (r == 2) 283 continue; 284 } 285 r = sscanf(line, " number of possible elements: %d", 286 &num_elm); 287 if (r != 1) 288 continue; 289 290 /* Skip the Overall elements */ 291 elm_idx++; 292 for (i = 0; i < num_elm; i++, elm_idx++) { 293 ATF_CHECK_EQ(map[elm_idx].elm_idx, elm_idx); 294 ATF_CHECK_EQ(map[elm_idx].elm_subenc_id, subenc_id); 295 ATF_CHECK_EQ((int)map[elm_idx].elm_type, elm_type); 296 } 297 } 298 299 free(map); 300 r = pclose(pipe); 301 if (r != 0) { 302 /* Probably an SGPIO device */ 303 return (false); 304 } else { 305 ATF_CHECK_EQ_MSG(nobj, elm_idx, 306 "Did not find the expected number of element " 307 "descriptors in sg_ses's output"); 308 return (true); 309 } 310 } 311 312 ATF_TC(getelmmap); 313 ATF_TC_HEAD(getelmmap, tc) 314 { 315 atf_tc_set_md_var(tc, "descr", 316 "Compare ENCIOC_GETELMMAP's output to sg3_utils'"); 317 atf_tc_set_md_var(tc, "require.user", "root"); 318 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 319 } 320 ATF_TC_BODY(getelmmap, tc) 321 { 322 if (!has_ses()) 323 atf_tc_skip("No ses devices found"); 324 for_each_ses_dev(do_getelmmap, O_RDONLY); 325 } 326 327 static bool 328 do_getelmstat(const char *devname, int fd) 329 { 330 encioc_element_t *map; 331 unsigned elm_idx; 332 unsigned nobj; 333 int r, elm_subidx; 334 elm_type_t last_elm_type = -1; 335 336 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 337 ATF_REQUIRE_EQ(r, 0); 338 339 map = calloc(nobj, sizeof(encioc_element_t)); 340 ATF_REQUIRE(map != NULL); 341 r = ioctl(fd, ENCIOC_GETELMMAP, (caddr_t) map); 342 343 for (elm_idx = 0; elm_idx < nobj; elm_subidx++, elm_idx++) { 344 encioc_elm_status_t e_status; 345 FILE *pipe; 346 char cmd[256]; 347 uint32_t status; 348 int pr; 349 350 if (last_elm_type != map[elm_idx].elm_type) 351 elm_subidx = -1; 352 last_elm_type = map[elm_idx].elm_type; 353 354 snprintf(cmd, sizeof(cmd), 355 "sg_ses -Hp2 --index=_%d,%d --get=0:7:32 %s", 356 map[elm_idx].elm_type, elm_subidx, devname); 357 pipe = popen(cmd, "r"); 358 ATF_REQUIRE(pipe != NULL); 359 r = fscanf(pipe, "0x%x", &status); 360 pr = pclose(pipe); 361 if (pr != 0) { 362 /* Probably an SGPIO device */ 363 free(map); 364 return (false); 365 } 366 ATF_REQUIRE_EQ(r, 1); 367 368 memset(&e_status, 0, sizeof(e_status)); 369 e_status.elm_idx = map[elm_idx].elm_idx; 370 r = ioctl(fd, ENCIOC_GETELMSTAT, (caddr_t)&e_status); 371 ATF_REQUIRE_EQ(r, 0); 372 373 // Compare the common status field 374 ATF_CHECK_EQ(e_status.cstat[0], status >> 24); 375 /* 376 * Ignore the other fields, because some have values that can 377 * change frequently (voltage, temperature, etc) 378 */ 379 } 380 free(map); 381 382 return (true); 383 } 384 385 ATF_TC(getelmstat); 386 ATF_TC_HEAD(getelmstat, tc) 387 { 388 atf_tc_set_md_var(tc, "descr", 389 "Compare ENCIOC_GETELMSTAT's output to sg3_utils'"); 390 atf_tc_set_md_var(tc, "require.user", "root"); 391 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 392 } 393 ATF_TC_BODY(getelmstat, tc) 394 { 395 if (!has_ses()) 396 atf_tc_skip("No ses devices found"); 397 for_each_ses_dev(do_getelmstat, O_RDONLY); 398 } 399 400 static bool 401 do_getencid(const char *devname, int fd) 402 { 403 encioc_string_t stri; 404 FILE *pipe; 405 char cmd[256]; 406 char encid[32]; 407 char line[256]; 408 char sg_encid[32]; 409 int r, sg_ses_r; 410 411 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 412 pipe = popen(cmd, "r"); 413 ATF_REQUIRE(pipe != NULL); 414 sg_encid[0] = '\0'; 415 while(NULL != fgets(line, sizeof(line), pipe)) { 416 const char *f = " enclosure logical identifier (hex): %s"; 417 418 if (1 == fscanf(pipe, f, sg_encid)) 419 break; 420 } 421 sg_ses_r = pclose(pipe); 422 423 stri.bufsiz = sizeof(encid); 424 stri.buf = &encid[0]; 425 r = ioctl(fd, ENCIOC_GETENCID, (caddr_t) &stri); 426 ATF_REQUIRE_EQ(r, 0); 427 if (sg_ses_r == 0) { 428 ATF_REQUIRE(sg_encid[0] != '\0'); 429 ATF_CHECK_STREQ(sg_encid, (char*)stri.buf); 430 return (true); 431 } else { 432 /* Probably SGPIO; sg_ses unsupported */ 433 return (false); 434 } 435 } 436 437 ATF_TC(getencid); 438 ATF_TC_HEAD(getencid, tc) 439 { 440 atf_tc_set_md_var(tc, "descr", 441 "Compare ENCIOC_GETENCID's output to sg3_utils'"); 442 atf_tc_set_md_var(tc, "require.user", "root"); 443 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 444 } 445 ATF_TC_BODY(getencid, tc) 446 { 447 if (!has_ses()) 448 atf_tc_skip("No ses devices found"); 449 for_each_ses_dev(do_getencid, O_RDONLY); 450 } 451 452 static bool 453 do_getencname(const char *devname, int fd) 454 { 455 encioc_string_t stri; 456 FILE *pipe; 457 char cmd[256]; 458 char encname[32]; 459 char line[256]; 460 int r; 461 462 snprintf(cmd, sizeof(cmd), "sg_inq -o %s | awk '" 463 "/Vendor identification/ {vi=$NF} " 464 "/Product identification/ {pi=$NF} " 465 "/Product revision level/ {prl=$NF} " 466 "END {printf(vi \" \" pi \" \" prl)}'", devname); 467 pipe = popen(cmd, "r"); 468 ATF_REQUIRE(pipe != NULL); 469 ATF_REQUIRE(NULL != fgets(line, sizeof(line), pipe)); 470 pclose(pipe); 471 472 stri.bufsiz = sizeof(encname); 473 stri.buf = &encname[0]; 474 r = ioctl(fd, ENCIOC_GETENCNAME, (caddr_t) &stri); 475 ATF_REQUIRE_EQ(r, 0); 476 if (strlen(line) < 3) { 477 // Probably an SGPIO device, INQUIRY unsupported 478 return (false); 479 } else { 480 ATF_CHECK_STREQ(line, (char*)stri.buf); 481 return (true); 482 } 483 } 484 485 ATF_TC(getencname); 486 ATF_TC_HEAD(getencname, tc) 487 { 488 atf_tc_set_md_var(tc, "descr", 489 "Compare ENCIOC_GETENCNAME's output to sg3_utils'"); 490 atf_tc_set_md_var(tc, "require.user", "root"); 491 atf_tc_set_md_var(tc, "require.progs", "sg_inq"); 492 } 493 ATF_TC_BODY(getencname, tc) 494 { 495 if (!has_ses()) 496 atf_tc_skip("No ses devices found"); 497 for_each_ses_dev(do_getencname, O_RDONLY); 498 } 499 500 static bool 501 do_getencstat(const char *devname, int fd) 502 { 503 FILE *pipe; 504 char cmd[256]; 505 unsigned char e, estat, invop, info, noncrit, crit, unrecov; 506 int r; 507 508 snprintf(cmd, sizeof(cmd), "sg_ses -p2 %s " 509 "| grep 'INVOP='", 510 devname); 511 pipe = popen(cmd, "r"); 512 ATF_REQUIRE(pipe != NULL); 513 r = fscanf(pipe, 514 " INVOP=%hhu, INFO=%hhu, NON-CRIT=%hhu, CRIT=%hhu, UNRECOV=%hhu", 515 &invop, &info, &noncrit, &crit, &unrecov); 516 pclose(pipe); 517 if (r != 5) { 518 /* Probably on SGPIO device */ 519 return (false); 520 } else { 521 r = ioctl(fd, ENCIOC_GETENCSTAT, (caddr_t) &estat); 522 ATF_REQUIRE_EQ(r, 0); 523 /* Exclude the info bit because it changes frequently */ 524 e = (invop << 4) | (noncrit << 2) | (crit << 1) | unrecov; 525 ATF_CHECK_EQ(estat & ~0x08, e); 526 return (true); 527 } 528 } 529 530 ATF_TC(getencstat); 531 ATF_TC_HEAD(getencstat, tc) 532 { 533 atf_tc_set_md_var(tc, "descr", 534 "Compare ENCIOC_GETENCSTAT's output to sg3_utils'"); 535 atf_tc_set_md_var(tc, "require.user", "root"); 536 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 537 } 538 ATF_TC_BODY(getencstat, tc) 539 { 540 if (!has_ses()) 541 atf_tc_skip("No ses devices found"); 542 for_each_ses_dev(do_getencstat, O_RDONLY); 543 } 544 545 static bool 546 do_getnelm(const char *devname, int fd) 547 { 548 FILE *pipe; 549 char cmd[256]; 550 char line[256]; 551 unsigned nobj, expected = 0; 552 int r, sg_ses_r; 553 554 snprintf(cmd, sizeof(cmd), "sg_ses -p1 %s", devname); 555 pipe = popen(cmd, "r"); 556 ATF_REQUIRE(pipe != NULL); 557 558 while(NULL != fgets(line, sizeof(line), pipe)) { 559 unsigned nelm; 560 561 if (1 == fscanf(pipe, " number of possible elements: %u", 562 &nelm)) 563 { 564 expected += 1 + nelm; // +1 for the Overall element 565 } 566 } 567 sg_ses_r = pclose(pipe); 568 569 r = ioctl(fd, ENCIOC_GETNELM, (caddr_t) &nobj); 570 ATF_REQUIRE_EQ(r, 0); 571 if (sg_ses_r == 0) { 572 ATF_CHECK_EQ(expected, nobj); 573 return (true); 574 } else { 575 /* Probably SGPIO, sg_ses unsupported */ 576 return (false); 577 } 578 } 579 580 ATF_TC(getnelm); 581 ATF_TC_HEAD(getnelm, tc) 582 { 583 atf_tc_set_md_var(tc, "descr", 584 "Compare ENCIOC_GETNELM's output to sg3_utils'"); 585 atf_tc_set_md_var(tc, "require.user", "root"); 586 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 587 } 588 ATF_TC_BODY(getnelm, tc) 589 { 590 if (!has_ses()) 591 atf_tc_skip("No ses devices found"); 592 for_each_ses_dev(do_getnelm, O_RDONLY); 593 } 594 595 static bool 596 do_getstring(const char *devname, int fd) 597 { 598 FILE *pipe; 599 char cmd[256]; 600 char *sg_ses_buf, *ses_buf; 601 ssize_t sg_ses_count; 602 encioc_string_t str_in; 603 int r; 604 605 sg_ses_buf = malloc(65535); 606 ATF_REQUIRE(sg_ses_buf != NULL); 607 ses_buf = malloc(65535); 608 ATF_REQUIRE(ses_buf != NULL); 609 610 snprintf(cmd, sizeof(cmd), "sg_ses -p4 -rr %s", devname); 611 pipe = popen(cmd, "r"); 612 ATF_REQUIRE(pipe != NULL); 613 sg_ses_count = fread(sg_ses_buf, 1, 65535, pipe); 614 r = pclose(pipe); 615 if (r != 0) { 616 // This SES device does not support the STRINGIN diagnostic page 617 return (false); 618 } 619 ATF_REQUIRE(sg_ses_count > 0); 620 621 str_in.bufsiz = 65535; 622 str_in.buf = ses_buf; 623 r = ioctl(fd, ENCIOC_GETSTRING, (caddr_t) &str_in); 624 ATF_REQUIRE_EQ(r, 0); 625 ATF_CHECK_EQ(sg_ses_count, (ssize_t)str_in.bufsiz); 626 ATF_CHECK_EQ(0, memcmp(sg_ses_buf, ses_buf, str_in.bufsiz)); 627 628 free(ses_buf); 629 free(sg_ses_buf); 630 631 return (true); 632 } 633 634 ATF_TC(getstring); 635 ATF_TC_HEAD(getstring, tc) 636 { 637 atf_tc_set_md_var(tc, "descr", 638 "Compare ENCIOC_GETSTRING's output to sg3_utils'"); 639 atf_tc_set_md_var(tc, "require.user", "root"); 640 atf_tc_set_md_var(tc, "require.progs", "sg_ses"); 641 } 642 ATF_TC_BODY(getstring, tc) 643 { 644 if (!has_ses()) 645 atf_tc_skip("No ses devices found"); 646 atf_tc_expect_fail("Bug 258188 ENCIO_GETSTRING does not set the string's returned size"); 647 for_each_ses_dev(do_getstring, O_RDWR); 648 } 649 650 ATF_TP_ADD_TCS(tp) 651 { 652 653 /* 654 * Untested ioctls: 655 * 656 * * ENCIOC_GETTEXT because it was never implemented 657 * 658 */ 659 ATF_TP_ADD_TC(tp, getelmdesc); 660 ATF_TP_ADD_TC(tp, getelmdevnames); 661 ATF_TP_ADD_TC(tp, getelmmap); 662 ATF_TP_ADD_TC(tp, getelmstat); 663 ATF_TP_ADD_TC(tp, getencid); 664 ATF_TP_ADD_TC(tp, getencname); 665 ATF_TP_ADD_TC(tp, getencstat); 666 ATF_TP_ADD_TC(tp, getnelm); 667 ATF_TP_ADD_TC(tp, getstring); 668 669 return (atf_no_error()); 670 } 671