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