xref: /aosp_15_r20/external/sg3_utils/testing/sg_chk_asc.c (revision 44704f698541f6367e81f991ef8bb54ccbf3fc18)
1 /*
2  * Copyright (c) 2006-2021 Douglas Gilbert.
3  * All rights reserved.
4  * Use of this source code is governed by a BSD-style
5  * license that can be found in the BSD_LICENSE file.
6  *
7  * SPDX-License-Identifier: BSD-2-Clause
8  */
9 
10 #include <unistd.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <getopt.h>
16 #include <ctype.h>
17 #include <errno.h>
18 
19 #include "sg_lib.h"
20 
21 /* A utility program for the Linux OS SCSI subsystem.
22  *
23  * This program takes a asc_ascq.txt file from www.t10.org and
24  * checks it against the additional sense codes held in the
25  * sg_lib.c file.
26  * The online version of the asc_ascq codes can be found at:
27  * https://www.t10.org/lists/asc-num.txt
28  */
29 
30 static const char * version_str = "1.09 20210226";
31 
32 
33 #define MAX_LINE_LEN 1024
34 
35 
36 static struct option long_options[] = {
37         {"help", 0, 0, 'h'},
38         {"verbose", 0, 0, 'v'},
39         {"version", 0, 0, 'V'},
40         {0, 0, 0, 0},
41 };
42 
usage()43 static void usage()
44 {
45     fprintf(stderr, "Usage: "
46             "sg_chk_asc [--help] [--offset=POS] [--verbose] [--version]\n"
47             "                  <asc_ascq_file>\n"
48             "  where:\n"
49             "    --help|-h          print out usage message\n"
50             "    --offset=POS|-o POS    line position in file where "
51             "text starts\n"
52             "                           origin 0 (def: 24 (was 25))\n"
53             "    --verbose|-v       increase verbosity\n"
54             "    --version|-V       print version string and exit\n\n"
55             "Checks asc/ascq codes in <asc_ascq_file> against the sg3_utils "
56             "library.\nThe additional sense codes (asc_ascq) can be found "
57             "at\nwww.t10.org/lists/asc-num.txt .\n"
58            );
59 
60 }
61 
main(int argc,char * argv[])62 int main(int argc, char * argv[])
63 {
64     int k, j, res, c, num, len;
65     unsigned int asc, ascq;
66     FILE * fp;
67     int offset = 24;
68     int verbose = 0;
69     char file_name[256];
70     char line[MAX_LINE_LEN];
71     char b[MAX_LINE_LEN];
72     char bb[MAX_LINE_LEN];
73     char * cp;
74     int ret = 1;
75 
76     memset(file_name, 0, sizeof file_name);
77     memset(line, 0, sizeof file_name);
78     while (1) {
79         int option_index = 0;
80 
81         c = getopt_long(argc, argv, "ho:vV", long_options,
82                         &option_index);
83         if (c == -1)
84             break;
85 
86         switch (c) {
87         case 'h':
88         case '?':
89             usage();
90             return 0;
91         case 'o':
92             offset = sg_get_num(optarg);
93             if (offset < 0) {
94                 fprintf(stderr, "bad argument to --offset\n");
95                 return 1;
96             }
97             break;
98         case 'v':
99             ++verbose;
100             break;
101         case 'V':
102             fprintf(stderr, "version: %s\n", version_str);
103             return 0;
104         default:
105             fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
106             usage();
107             return 1;
108         }
109     }
110     if (optind < argc) {
111         if ('\0' == file_name[0]) {
112             strncpy(file_name, argv[optind], sizeof(file_name) - 1);
113             file_name[sizeof(file_name) - 1] = '\0';
114             ++optind;
115         }
116         if (optind < argc) {
117             for (; optind < argc; ++optind)
118                 fprintf(stderr, "Unexpected extra argument: %s\n",
119                         argv[optind]);
120             usage();
121             return 1;
122         }
123     }
124 
125     if (0 == file_name[0]) {
126         fprintf(stderr, "missing file name!\n");
127         usage();
128         return 1;
129     }
130     fp = fopen(file_name, "r");
131     if (NULL == fp) {
132         fprintf(stderr, "open error: %s: %s\n", file_name,
133                 safe_strerror(errno));
134         return 1;
135     }
136     for (k = 0; (cp = fgets(line, sizeof(line) - 1, fp)); ++k) {
137         len = strlen(line);
138         if (len < 1)
139             continue;
140         if (! isdigit(line[0]))
141             continue;
142         num = sscanf(line, "%xh/%xh", &asc, &ascq);
143         if (1 == num)
144             ascq = 999;
145         if (num < 1) {
146             if (verbose)
147                 fprintf(stderr, "Badly formed line number %d (num=%d)\n",
148                         k + 1, num);
149             continue;
150         }
151         if (len < 26)
152             continue;
153 #if 0
154 strncpy(b , line, sizeof(b) - 1);
155 b[sizeof(b) - 1] = '\0';
156 num = strlen(b);
157 if (0xd == b[num - 2]) {
158     b[num - 2] = '\0';
159     b[num - 1] = '\0';
160 }
161 printf("\"%s\",\n", b);
162 #endif
163         strncpy(b , line + offset, sizeof(b) - 1);
164         b[sizeof(b) - 1] = '\0';
165         num = strlen(b);
166         if (0xd == b[num - 2])
167             b[num - 2] = '\0';
168         b[num - 1] = '\0';
169         num = strlen(b);
170         for (j = 0; j < num; ++j)
171             b[j] = toupper(b[j]);
172 
173         bb[0] = '\0';
174         if (ascq < 999) {
175             cp = sg_get_asc_ascq_str(asc, ascq, sizeof(bb) - 1, bb);
176             if (NULL == cp) {
177                 fprintf(stderr, "no entry for %x,%x : %s\n", asc, ascq, b);
178                 continue;
179             }
180             num = strlen(cp);
181 // fprintf(stderr, "file: asc=%x  acsq=%x  strlen=%d %s\n", asc, ascq, num,
182 //         cp);
183 //            if (num < 20)
184 //                continue;
185             if ((num > 6) &&
186                 ((0 == memcmp("ASC", cp, 3)) ||
187                  (0 == memcmp("vendor", cp, 6)))) {
188                 fprintf(stderr, "%x,%x differ, ref: %s, sg_lib_data: "
189                         "<missing>\n", asc, ascq, b);
190                 continue;
191             }
192             if (num > 20) {
193                 cp += 18;
194                 num -= 18;
195                 for (j = 0; j < num; ++j)
196                     cp[j] = toupper(cp[j]);
197             }
198             if (0 != strcmp(b, cp))
199                 fprintf(stderr, "%x,%x differ, ref: %s, sg_lib_data: "
200                         "%s\n", asc, ascq, b, cp);
201         }
202     }
203     if (NULL == cp) {
204         if (feof(fp)) {
205             if (verbose > 2)
206                 fprintf(stderr, "EOF detected\n");
207         } else
208             fprintf(stderr, "fgets: %s\n", safe_strerror(errno));
209     } else
210         fprintf(stderr, "%s\n", line);
211 
212     res = fclose(fp);
213     if (EOF == res) {
214         fprintf(stderr, "close error: %s\n", safe_strerror(errno));
215         return 1;
216     }
217     return ret;
218 }
219