Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/ses/nondestructive.c
39507 views
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
672