Print this page
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/common/brand/lx/tools/gen_errno.c
+++ new/usr/src/common/brand/lx/tools/gen_errno.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2015 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Take the error number definitions from a foreign system and generate a
18 18 * translation table that converts illumos native error numbers to foreign
19 19 * system error numbers.
20 20 */
21 21
22 22 #include <ctype.h>
23 23 #include <stdlib.h>
24 24 #include <stdio.h>
25 25 #include <unistd.h>
26 26 #include <errno.h>
27 27 #include <err.h>
28 28 #include <sys/sysmacros.h>
29 29 #include <libcmdutils.h>
30 30 #include <libnvpair.h>
31 31
32 32 nvlist_t *native_errors;
33 33 nvlist_t *foreign_errors;
34 34
35 35 struct override {
36 36 const char *ovr_from;
37 37 const char *ovr_to;
38 38 } overrides[] = {
39 39 { "ENOTSUP", "ENOSYS" },
40 40 { 0 }
41 41 };
42 42
43 43 static const char *
44 44 lookup_override(const char *from)
45 45 {
46 46 int i;
47 47
48 48 for (i = 0; overrides[i].ovr_from != NULL; i++) {
49 49 if (strcmp(overrides[i].ovr_from, from) == 0) {
50 50 return (overrides[i].ovr_to);
51 51 }
52 52 }
53 53
54 54 return (NULL);
55 55 }
56 56
57 57 static int
58 58 parse_int(const char *number, int *rval)
59 59 {
60 60 long n;
61 61 char *endpos;
62 62
63 63 errno = 0;
64 64 if ((n = strtol(number, &endpos, 10)) == 0 && errno != 0) {
65 65 return (-1);
66 66 }
67 67
68 68 if (endpos != NULL && *endpos != '\0') {
69 69 errno = EINVAL;
70 70 return (-1);
71 71 }
72 72
73 73 if (n > INT_MAX || n < INT_MIN) {
74 74 errno = EOVERFLOW;
75 75 return (-1);
76 76 }
77 77
78 78 *rval = (int)n;
79 79 return (0);
80 80 }
81 81
82 82 static int
83 83 errnum_add(nvlist_t *nvl, const char *name, const char *number)
84 84 {
85 85 int val;
86 86
87 87 if (nvlist_exists(nvl, name)) {
88 88 (void) fprintf(stderr, "ERROR: duplicate definition: %s -> "
89 89 "%s\n", name, number);
90 90 errno = EEXIST;
91 91 return (-1);
92 92 }
93 93
94 94 /*
95 95 * Try and parse the error number:
96 96 */
97 97 if (parse_int(number, &val) == 0) {
98 98 /*
99 99 * The name refers to a number.
100 100 */
101 101 if (nvlist_add_int32(nvl, name, val) != 0) {
102 102 (void) fprintf(stderr, "ERROR: nvlist_add_int32: %s\n",
103 103 strerror(errno));
104 104 return (-1);
105 105 }
106 106 } else {
107 107 /*
108 108 * The name refers to another definition.
109 109 */
110 110 if (nvlist_add_string(nvl, name, number) != 0) {
111 111 (void) fprintf(stderr, "ERROR: nvlist_add_string: %s\n",
112 112 strerror(errno));
113 113 return (-1);
114 114 }
115 115 }
116 116
117 117 return (0);
118 118 }
119 119
120 120 static int
121 121 errnum_max(nvlist_t *nvl)
122 122 {
123 123 int max = 0;
124 124 nvpair_t *nvp = NULL;
125 125
126 126 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
127 127 if (nvpair_type(nvp) != DATA_TYPE_INT32) {
128 128 continue;
129 129 }
130 130
131 131 max = MAX(fnvpair_value_int32(nvp), max);
132 132 }
133 133
134 134 return (max);
135 135 }
136 136
137 137 static int
138 138 errname_by_num(nvlist_t *nvl, int num, const char **name)
139 139 {
140 140 nvpair_t *nvp = NULL;
141 141
142 142 while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
143 143 if (nvpair_type(nvp) != DATA_TYPE_INT32) {
144 144 continue;
145 145 }
146 146
147 147 if (fnvpair_value_int32(nvp) == num) {
148 148 *name = nvpair_name(nvp);
149 149 return (0);
150 150 }
151 151 }
152 152
153 153 errno = ENOENT;
154 154 return (-1);
155 155 }
156 156
157 157 static int
158 158 errno_by_name(nvlist_t *nvl, const char *name, int *rval, const char **rname)
159 159 {
160 160 nvpair_t *nvp = NULL;
161 161
162 162 if (nvlist_lookup_nvpair(nvl, name, &nvp) != 0) {
163 163 errno = ENOENT;
164 164 return (-1);
165 165 }
166 166
167 167 if (nvpair_type(nvp) == DATA_TYPE_STRING) {
168 168 return (errno_by_name(nvl, fnvpair_value_string(nvp), rval,
169 169 rname));
170 170 } else {
171 171 *rval = fnvpair_value_int32(nvp);
172 172 if (rname != NULL) {
173 173 *rname = name;
174 174 }
175 175 return (0);
176 176 }
177 177 }
178 178
179 179 static int
180 180 process_line(const char *line, nvlist_t *nvl)
181 181 {
182 182 custr_t *nam = NULL, *num = NULL;
183 183 const char *c = line;
184 184
185 185 if (custr_alloc(&nam) != 0 || custr_alloc(&num) != 0) {
186 186 int en = errno;
187 187
188 188 custr_free(nam);
189 189 custr_free(num);
190 190
191 191 errno = en;
192 192 return (-1);
193 193 }
194 194
195 195 /*
196 196 * Valid lines begin with "#define":
197 197 */
198 198 if (*c++ != '#' || *c++ != 'd' || *c++ != 'e' || *c++ != 'f' ||
199 199 *c++ != 'i' || *c++ != 'n' || *c++ != 'e') {
200 200 return (0);
201 201 }
202 202
203 203 /*
204 204 * Eat whitespace:
205 205 */
206 206 for (;;) {
207 207 if (*c == '\0') {
208 208 return (0);
209 209 }
210 210
211 211 if (*c != ' ' && *c != '\t') {
212 212 break;
213 213 }
214 214
215 215 c++;
216 216 }
217 217
218 218 /*
219 219 * Read error number token:
220 220 */
221 221 for (;;) {
222 222 if (*c == '\0') {
223 223 return (0);
224 224 }
225 225
226 226 if (*c == ' ' || *c == '\t') {
227 227 break;
228 228 }
229 229
230 230 if (custr_appendc(nam, *c) != 0) {
231 231 return (-1);
232 232 }
233 233
234 234 c++;
235 235 }
236 236
237 237 /*
238 238 * Eat whitespace:
239 239 */
240 240 for (;;) {
241 241 if (*c == '\0') {
242 242 return (0);
243 243 }
244 244
245 245 if (*c != ' ' && *c != '\t') {
246 246 break;
247 247 }
248 248
249 249 c++;
250 250 }
251 251
252 252 /*
253 253 * Read error number token:
254 254 */
255 255 for (;;) {
256 256 if (*c == '\0') {
257 257 break;
258 258 }
259 259
260 260 if (*c == ' ' || *c == '\t') {
261 261 break;
262 262 }
263 263
264 264 if (custr_appendc(num, *c) != 0) {
265 265 return (-1);
266 266 }
267 267
268 268 c++;
269 269 }
270 270
271 271 return (errnum_add(nvl, custr_cstr(nam), custr_cstr(num)));
272 272 }
273 273
274 274 static int
275 275 read_file_into_list(const char *path, nvlist_t *nvl)
276 276 {
277 277 int rval = 0, en = 0;
278 278 FILE *f;
279 279 custr_t *cu = NULL;
280 280
281 281 if (custr_alloc(&cu) != 0) {
282 282 return (-1);
283 283 }
284 284
285 285 if ((f = fopen(path, "r")) == NULL) {
286 286 custr_free(cu);
287 287 return (-1);
288 288 }
289 289
290 290 for (;;) {
291 291 int c;
292 292
293 293 errno = 0;
294 294 switch (c = fgetc(f)) {
295 295 case '\n':
296 296 case EOF:
297 297 if (errno != 0) {
298 298 en = errno;
299 299 rval = -1;
300 300 goto out;
301 301 }
302 302 if (process_line(custr_cstr(cu), nvl) != 0) {
303 303 en = errno;
304 304 rval = -1;
305 305 goto out;
306 306 }
307 307 custr_reset(cu);
308 308 if (c == EOF) {
309 309 goto out;
310 310 }
311 311 break;
312 312
313 313 case '\r':
314 314 case '\0':
315 315 /*
316 316 * Ignore these characters.
317 317 */
318 318 break;
319 319
320 320 default:
321 321 if (custr_appendc(cu, c) != 0) {
322 322 en = errno;
323 323 rval = -1;
324 324 goto out;
325 325 }
326 326 break;
327 327 }
328 328 }
329 329
330 330 out:
331 331 (void) fclose(f);
332 332 custr_free(cu);
333 333 errno = en;
334 334 return (rval);
335 335 }
336 336
337 337 int
338 338 main(int argc, char **argv)
339 339 {
340 340 int max;
341 341 int fval;
342 342 int c;
343 343
344 344 if (nvlist_alloc(&native_errors, NV_UNIQUE_NAME, 0) != 0 ||
345 345 nvlist_alloc(&foreign_errors, NV_UNIQUE_NAME, 0) != 0) {
346 346 err(1, "could not allocate memory");
347 347 }
348 348
349 349 while ((c = getopt(argc, argv, ":N:F:")) != -1) {
350 350 switch (c) {
351 351 case 'N':
352 352 if (read_file_into_list(optarg, native_errors) != 0) {
353 353 err(1, "could not read file: %s", optarg);
354 354 }
355 355 break;
356 356
357 357 case 'F':
358 358 if (read_file_into_list(optarg, foreign_errors) != 0) {
359 359 err(1, "could not read file: %s", optarg);
360 360 }
361 361 break;
362 362
363 363 case ':':
364 364 errx(1, "option -%c requires an operand", c);
365 365 break;
366 366
367 367 case '?':
368 368 errx(1, "option -%c unrecognised", c);
369 369 break;
370 370 }
371 371 }
372 372
373 373 /*
374 374 * Print an array entry for each error number:
375 375 */
376 376 max = errnum_max(native_errors);
377 377 for (fval = 0; fval <= max; fval++) {
378 378 const char *fname;
379 379 const char *tname = NULL;
380 380 int32_t tval;
381 381 const char *msg = NULL;
382 382 const char *comma = (fval != max) ? "," : "";
383 383
384 384 if (errname_by_num(native_errors, fval, &fname) == -1) {
385 385 fname = NULL;
386 386 }
387 387
388 388 if (fval == 0) {
389 389 /*
390 390 * The error number "0" is special: it means no worries.
391 391 */
392 392 msg = "No Error";
393 393 tval = 0;
394 394 } else if (fname == NULL) {
395 395 /*
396 396 * There is no defined name for this error number; it
397 397 * is unused.
398 398 */
399 399 msg = "Unused Number";
400 400 tval = -1;
401 401 } else {
402 402 /*
403 403 * Check if we want to override the name of this error
404 404 * in the foreign error number lookup:
405 405 */
406 406 const char *oname = lookup_override(fname);
407 407
408 408 /*
409 409 * Do the lookup:
410 410 */
411 411 if (errno_by_name(foreign_errors, oname != NULL ?
412 412 oname : fname, &tval, &tname) != 0) {
413 413 /*
414 414 * There was no foreign error number by that
415 415 * name.
416 416 */
417 417 tname = "No Analogue";
418 418 tval = -2;
419 419 }
420 420 }
421 421
422 422 if (msg == NULL) {
423 423 size_t flen = strlen(fname);
424 424 size_t tlen = strlen(tname);
425 425 const char *t = flen > 7 ? "\t" : "\t\t";
426 426 const char *tt = tlen < 7 ? "\t\t\t" : tlen < 15 ?
427 427 "\t\t" : "\t";
428 428
429 429 (void) fprintf(stdout, "\t%d%s\t/* %3d: %s%s--> %3d: "
430 430 "%s%s*/\n", tval, comma, fval, fname, t, tval,
431 431 tname, tt);
432 432 } else {
433 433 const char *t = "\t\t\t\t\t";
434 434
435 435 (void) fprintf(stdout, "\t%d%s\t/* %3d: %s%s*/\n", tval,
436 436 comma, fval, msg, t);
437 437 }
438 438 }
439 439
440 440 (void) nvlist_free(native_errors);
441 441 (void) nvlist_free(foreign_errors);
442 442
443 443 return (0);
444 444 }
|
↓ open down ↓ |
444 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX