clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name main.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/config/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/config -I . -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/config/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/config/main.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | #include <sys/types.h> |
45 | #include <sys/stat.h> |
46 | |
47 | #include <ctype.h> |
48 | #include <err.h> |
49 | #include <errno.h> |
50 | #include <stdio.h> |
51 | #include <stdlib.h> |
52 | #include <string.h> |
53 | #include <unistd.h> |
54 | #include <limits.h> |
55 | |
56 | #include "config.h" |
57 | |
58 | int firstfile(const char *); |
59 | int yyparse(void); |
60 | |
61 | static struct hashtab *mkopttab; |
62 | static struct nvlist **nextopt; |
63 | static struct nvlist **nextdefopt; |
64 | static struct nvlist **nextmkopt; |
65 | |
66 | static __dead void stop(void); |
67 | static int do_option(struct hashtab *, struct nvlist ***, |
68 | const char *, const char *, const char *); |
69 | static int crosscheck(void); |
70 | static int badstar(void); |
71 | static int mksymlinks(void); |
72 | static int hasparent(struct devi *); |
73 | static int cfcrosscheck(struct config *, const char *, struct nvlist *); |
74 | static void optiondelta(void); |
75 | |
76 | int verbose; |
77 | |
78 | const char *conffile; |
79 | const char *last_component; |
80 | const char *machine; |
81 | const char *machinearch; |
82 | const char *srcdir; |
83 | const char *builddir; |
84 | const char *defbuilddir; |
85 | int errors; |
86 | int minmaxusers; |
87 | int defmaxusers; |
88 | int maxmaxusers; |
89 | int maxusers; |
90 | int maxpartitions; |
91 | struct nvlist *options; |
92 | struct nvlist *defoptions; |
93 | struct nvlist *mkoptions; |
94 | struct hashtab *devbasetab; |
95 | struct hashtab *devatab; |
96 | struct hashtab *selecttab; |
97 | struct hashtab *needcnttab; |
98 | struct hashtab *opttab; |
99 | struct hashtab *defopttab; |
100 | struct devbase *allbases; |
101 | struct deva *alldevas; |
102 | struct config *allcf; |
103 | struct devi *alldevi; |
104 | struct devi *allpseudo; |
105 | int ndevi; |
106 | int npseudo; |
107 | |
108 | struct files *allfiles; |
109 | struct objects *allobjects; |
110 | |
111 | struct devi **packed; |
112 | int npacked; |
113 | |
114 | struct parents parents; |
115 | struct locators locators; |
116 | |
117 | __dead void |
118 | usage(void) |
119 | { |
120 | extern char *__progname; |
121 | |
122 | fprintf(stderr, |
123 | "usage: %s [-p] [-b builddir] [-s srcdir] [config-file]\n" |
124 | " %s -e [-u] [-c cmdfile] [-f | -o outfile] infile\n", |
125 | __progname, __progname); |
126 | |
127 | exit(1); |
128 | } |
129 | |
130 | int pflag = 0; |
131 | char *sflag = NULL; |
132 | char *bflag = NULL; |
133 | char *startdir; |
134 | char *cmdfile = NULL; |
135 | FILE *cmdfp = NULL; |
136 | |
137 | int |
138 | main(int argc, char *argv[]) |
139 | { |
140 | char *p; |
141 | char *outfile = NULL; |
142 | int ch, eflag, uflag, fflag; |
143 | char dirbuffer[PATH_MAX]; |
144 | |
145 | if (pledge("stdio rpath wpath cpath flock proc exec", NULL) == -1) |
| 1 | Assuming the condition is false | |
|
| |
146 | err(1, "pledge"); |
147 | |
148 | pflag = eflag = uflag = fflag = 0; |
149 | while ((ch = getopt(argc, argv, "c:epfb:s:o:u")) != -1) { |
| 3 | | Assuming the condition is false | |
|
| 4 | | Loop condition is false. Execution continues on line 199 | |
|
150 | switch (ch) { |
151 | case 'c': |
152 | cmdfile = optarg; |
153 | break; |
154 | case 'o': |
155 | outfile = optarg; |
156 | break; |
157 | case 'u': |
158 | uflag = 1; |
159 | break; |
160 | case 'f': |
161 | fflag = 1; |
162 | break; |
163 | |
164 | case 'e': |
165 | eflag = 1; |
166 | if (!isatty(STDIN_FILENO)) |
167 | verbose = 1; |
168 | break; |
169 | |
170 | case 'p': |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | pflag = 1; |
182 | break; |
183 | |
184 | case 'b': |
185 | bflag = optarg; |
186 | builddir = optarg; |
187 | break; |
188 | |
189 | case 's': |
190 | sflag = optarg; |
191 | srcdir = optarg; |
192 | break; |
193 | |
194 | default: |
195 | usage(); |
196 | } |
197 | } |
198 | |
199 | argc -= optind; |
200 | argv += optind; |
201 | if (argc > 1 || (eflag && argv[0] == NULL)) |
| |
202 | usage(); |
203 | if (bflag) { |
| |
204 | startdir = getcwd(dirbuffer, sizeof dirbuffer); |
205 | if (startdir == NULL) |
206 | warn("Use of -b and can't getcwd, no make config"); |
207 | } else { |
208 | startdir = "../../conf"; |
209 | } |
210 | |
211 | if (eflag) { |
212 | #ifdef MAKE_BOOTSTRAP |
213 | errx(1, "UKC not available in this binary"); |
214 | #else |
215 | if (cmdfile != NULL) { |
216 | cmdfp = fopen(cmdfile, "r"); |
217 | if (cmdfp == NULL) |
218 | err(1, "open %s", cmdfile); |
219 | } |
220 | return (ukc(argv[0], outfile, uflag, fflag)); |
221 | #endif |
222 | } |
223 | |
224 | conffile = (argc == 1) ? argv[0] : "CONFIG"; |
| 7 | | Assuming 'argc' is not equal to 1 | |
|
| |
225 | if (firstfile(conffile)) |
| 9 | | Assuming the condition is false | |
|
| |
226 | err(2, "cannot read %s", conffile); |
227 | |
228 | |
229 | |
230 | |
231 | minmaxusers = 1; |
232 | maxmaxusers = 10000; |
233 | initintern(); |
234 | initfiles(); |
235 | initsem(); |
236 | devbasetab = ht_new(); |
237 | devatab = ht_new(); |
238 | selecttab = ht_new(); |
239 | needcnttab = ht_new(); |
240 | opttab = ht_new(); |
241 | mkopttab = ht_new(); |
242 | defopttab = ht_new(); |
243 | nextopt = &options; |
244 | nextmkopt = &mkoptions; |
245 | nextdefopt = &defoptions; |
246 | |
247 | |
248 | |
249 | |
250 | |
251 | last_component = strrchr(conffile, '/'); |
252 | last_component = (last_component) ? last_component + 1 : conffile; |
| 11 | | Assuming 'last_component' is null | |
|
| |
253 | if (pflag) { |
| |
254 | if (asprintf(&p, "../compile/%s.PROF", last_component) == -1) |
255 | err(1, NULL); |
256 | (void)addmkoption(intern("PROF"), "-pg"); |
257 | (void)addoption(intern("GPROF"), NULL); |
258 | } else { |
259 | if (asprintf(&p, "../compile/%s", last_component) == -1) |
| 14 | | Assuming the condition is false | |
|
260 | err(1, NULL); |
261 | } |
262 | defbuilddir = (argc == 0) ? "." : p; |
| 15 | | Assuming 'argc' is not equal to 0 | |
|
| |
263 | |
264 | |
265 | |
266 | |
267 | if (yyparse()) |
| 17 | | Assuming the condition is false | |
|
| |
268 | stop(); |
269 | |
270 | |
271 | |
272 | |
273 | if (fixfiles()) |
| 19 | | Assuming the condition is false | |
|
| |
274 | stop(); |
275 | |
276 | |
277 | |
278 | |
279 | if (fixobjects()) |
| 21 | | Assuming the condition is false | |
|
| |
280 | stop(); |
281 | |
282 | |
283 | |
284 | |
285 | if (maxusers == 0) { |
| 23 | | Assuming 'maxusers' is not equal to 0 | |
|
286 | if (defmaxusers) { |
287 | (void)printf("maxusers not specified; %d assumed\n", |
288 | defmaxusers); |
289 | maxusers = defmaxusers; |
290 | } else { |
291 | warnx("need \"maxusers\" line"); |
292 | errors++; |
293 | } |
294 | } |
295 | if (crosscheck() || errors) |
| |
| |
296 | stop(); |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | pack(); |
303 | if (badstar()) |
| 26 | | Assuming the condition is false | |
|
304 | stop(); |
305 | |
306 | |
307 | |
308 | |
309 | if (mksymlinks() || mkmakefile() || mkheaders() || mkswap() || |
| 27 | | Assuming the condition is false | |
|
| 28 | | Assuming the condition is false | |
|
| 29 | | Assuming the condition is false | |
|
| |
310 | mkioconf()) |
| 30 | | Assuming the condition is false | |
|
311 | stop(); |
312 | optiondelta(); |
| |
313 | return (0); |
314 | } |
315 | |
316 | static int |
317 | mksymlink(const char *value, const char *path) |
318 | { |
319 | int ret = 0; |
320 | |
321 | if (remove(path) && errno != ENOENT) { |
322 | warn("remove(%s)", path); |
323 | ret = 1; |
324 | } |
325 | if (symlink(value, path)) { |
326 | warn("symlink(%s -> %s)", path, value); |
327 | ret = 1; |
328 | } |
329 | return (ret); |
330 | } |
331 | |
332 | |
333 | |
334 | |
335 | |
336 | |
337 | static int |
338 | mksymlinks(void) |
339 | { |
340 | int ret; |
341 | char *p, buf[PATH_MAX]; |
342 | const char *q; |
343 | |
344 | snprintf(buf, sizeof buf, "arch/%s/include", machine); |
345 | p = sourcepath(buf); |
346 | ret = mksymlink(p, "machine"); |
347 | if (machinearch != NULL) { |
348 | snprintf(buf, sizeof buf, "arch/%s/include", machinearch); |
349 | p = sourcepath(buf); |
350 | q = machinearch; |
351 | } else { |
352 | p = strdup("machine"); |
353 | if (!p) |
354 | errx(1, "out of memory"); |
355 | q = machine; |
356 | } |
357 | ret |= mksymlink(p, q); |
358 | free(p); |
359 | |
360 | return (ret); |
361 | } |
362 | |
363 | static __dead void |
364 | stop(void) |
365 | { |
366 | (void)fprintf(stderr, "*** Stop.\n"); |
367 | exit(1); |
368 | } |
369 | |
370 | |
371 | |
372 | |
373 | void |
374 | defoption(const char *name) |
375 | { |
376 | char *p, *low, c; |
377 | const char *n; |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | |
386 | low = emalloc(strlen(name) + 1); |
387 | for (n = name, p = low; (c = *n) != '\0'; n++) |
388 | *p++ = isupper((unsigned char)c) ? |
389 | tolower((unsigned char)c) : c; |
390 | *p = 0; |
391 | |
392 | n = intern(low); |
393 | free(low); |
394 | (void)do_option(defopttab, &nextdefopt, n, name, "defopt"); |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | (void)ht_insert(defopttab, name, (void *)name); |
401 | } |
402 | |
403 | |
404 | |
405 | |
406 | void |
407 | removeoption(const char *name) |
408 | { |
409 | struct nvlist *nv, *nvt; |
410 | char *p, *low, c; |
411 | const char *n; |
412 | |
413 | if ((nv = ht_lookup(opttab, name)) != NULL) { |
414 | if (options == nv) { |
415 | options = nv->nv_next; |
416 | nvfree(nv); |
417 | } else { |
418 | nvt = options; |
419 | while (nvt->nv_next != NULL) { |
420 | if (nvt->nv_next == nv) { |
421 | nvt->nv_next = nvt->nv_next->nv_next; |
422 | nvfree(nv); |
423 | break; |
424 | } else |
425 | nvt = nvt->nv_next; |
426 | } |
427 | } |
428 | } |
429 | |
430 | (void)ht_remove(opttab, name); |
431 | |
432 | low = emalloc(strlen(name) + 1); |
433 | |
434 | for (n = name, p = low; (c = *n) != '\0'; n++) |
435 | *p++ = isupper((unsigned char)c) ? |
436 | tolower((unsigned char)c) : c; |
437 | *p = 0; |
438 | n = intern(low); |
439 | free(low); |
440 | (void)ht_remove(selecttab, n); |
441 | } |
442 | |
443 | |
444 | |
445 | |
446 | |
447 | void |
448 | addoption(const char *name, const char *value) |
449 | { |
450 | char *p, *low, c; |
451 | const char *n; |
452 | |
453 | if (do_option(opttab, &nextopt, name, value, "options")) |
454 | return; |
455 | |
456 | low = emalloc(strlen(name) + 1); |
457 | |
458 | for (n = name, p = low; (c = *n) != '\0'; n++) |
459 | *p++ = isupper((unsigned char)c) ? |
460 | tolower((unsigned char)c) : c; |
461 | *p = 0; |
462 | n = intern(low); |
463 | free(low); |
464 | (void)ht_insert(selecttab, n, (void *)n); |
465 | } |
466 | |
467 | |
468 | |
469 | |
470 | void |
471 | addmkoption(const char *name, const char *value) |
472 | { |
473 | |
474 | (void)do_option(mkopttab, &nextmkopt, name, value, "mkoptions"); |
475 | } |
476 | |
477 | |
478 | |
479 | |
480 | static int |
481 | do_option(struct hashtab *ht, struct nvlist ***nppp, const char *name, |
482 | const char *value, const char *type) |
483 | { |
484 | struct nvlist *nv; |
485 | |
486 | |
487 | nv = newnv(name, value, NULL, 0, NULL); |
488 | if (ht_insert(ht, name, nv) == 0) { |
489 | **nppp = nv; |
490 | *nppp = &nv->nv_next; |
491 | return (0); |
492 | } |
493 | |
494 | |
495 | nvfree(nv); |
496 | if ((nv = ht_lookup(ht, name)) == NULL) |
497 | panic("do_option"); |
498 | if (nv->nv_str != NULL) |
499 | error("already have %s `%s=%s'", type, name, nv->nv_str); |
500 | else |
501 | error("already have %s `%s'", type, name); |
502 | return (1); |
503 | } |
504 | |
505 | |
506 | |
507 | |
508 | |
509 | int |
510 | deva_has_instances(struct deva *deva, int unit) |
511 | { |
512 | struct devi *i; |
513 | |
514 | if (unit == WILD) |
515 | return (deva->d_ihead != NULL); |
516 | for (i = deva->d_ihead; i != NULL; i = i->i_asame) |
517 | if (unit == i->i_unit) |
518 | return (1); |
519 | return (0); |
520 | } |
521 | |
522 | |
523 | |
524 | |
525 | |
526 | int |
527 | devbase_has_instances(struct devbase *dev, int unit) |
528 | { |
529 | struct deva *da; |
530 | |
531 | for (da = dev->d_ahead; da != NULL; da = da->d_bsame) |
532 | if (deva_has_instances(da, unit)) |
533 | return (1); |
534 | return (0); |
535 | } |
536 | |
537 | static int |
538 | hasparent(struct devi *i) |
539 | { |
540 | struct nvlist *nv; |
541 | int atunit = i->i_atunit; |
542 | |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | |
555 | |
556 | |
557 | |
558 | if (i->i_atdev != NULL) |
559 | return (devbase_has_instances(i->i_atdev, atunit)); |
560 | |
561 | |
562 | |
563 | |
564 | if (i->i_atattr != NULL) |
565 | for (nv = i->i_atattr->a_refs; nv != NULL; nv = nv->nv_next) |
566 | if (devbase_has_instances(nv->nv_ptr, atunit)) |
567 | return (1); |
568 | return (0); |
569 | } |
570 | |
571 | static int |
572 | cfcrosscheck(struct config *cf, const char *what, struct nvlist *nv) |
573 | { |
574 | struct devbase *dev; |
575 | struct devi *pd; |
576 | int errs, devminor; |
577 | |
578 | if (maxpartitions <= 0) |
579 | panic("cfcrosscheck"); |
580 | |
581 | for (errs = 0; nv != NULL; nv = nv->nv_next) { |
582 | if (nv->nv_name == NULL) |
583 | continue; |
584 | dev = ht_lookup(devbasetab, nv->nv_name); |
585 | if (dev == NULL) |
586 | panic("cfcrosscheck(%s)", nv->nv_name); |
587 | devminor = minor(nv->nv_int) / maxpartitions; |
588 | if (devbase_has_instances(dev, devminor)) |
589 | continue; |
590 | if (devbase_has_instances(dev, STAR) && |
591 | devminor >= dev->d_umax) |
592 | continue; |
593 | for (pd = allpseudo; pd != NULL; pd = pd->i_next) |
594 | if (pd->i_base == dev && devminor < dev->d_umax && |
595 | devminor >= 0) |
596 | goto loop; |
597 | (void)fprintf(stderr, |
598 | "%s:%d: %s says %s on %s, but there's no %s\n", |
599 | conffile, cf->cf_lineno, |
600 | cf->cf_name, what, nv->nv_str, nv->nv_str); |
601 | errs++; |
602 | loop: |
603 | ; |
604 | } |
605 | return (errs); |
606 | } |
607 | |
608 | |
609 | |
610 | |
611 | |
612 | |
613 | |
614 | int |
615 | crosscheck(void) |
616 | { |
617 | struct devi *i; |
618 | struct config *cf; |
619 | int errs; |
620 | |
621 | errs = 0; |
622 | for (i = alldevi; i != NULL; i = i->i_next) { |
623 | if (i->i_at == NULL || hasparent(i)) |
624 | continue; |
625 | xerror(conffile, i->i_lineno, |
626 | "%s at %s is orphaned", i->i_name, i->i_at); |
627 | (void)fprintf(stderr, " (%s %s declared)\n", |
628 | i->i_atunit == WILD ? "nothing matching" : "no", |
629 | i->i_at); |
630 | errs++; |
631 | } |
632 | if (allcf == NULL) { |
633 | (void)fprintf(stderr, "%s has no configurations!\n", |
634 | conffile); |
635 | errs++; |
636 | } |
637 | for (cf = allcf; cf != NULL; cf = cf->cf_next) { |
638 | if (cf->cf_root != NULL) { |
639 | errs += cfcrosscheck(cf, "root", cf->cf_root); |
640 | errs += cfcrosscheck(cf, "swap", cf->cf_swap); |
641 | errs += cfcrosscheck(cf, "dumps", cf->cf_dump); |
642 | } |
643 | } |
644 | return (errs); |
645 | } |
646 | |
647 | |
648 | |
649 | |
650 | int |
651 | badstar(void) |
652 | { |
653 | struct devbase *d; |
654 | struct deva *da; |
655 | struct devi *i; |
656 | int errs, n; |
657 | |
658 | errs = 0; |
659 | for (d = allbases; d != NULL; d = d->d_next) { |
660 | for (da = d->d_ahead; da != NULL; da = da->d_bsame) |
661 | for (i = da->d_ihead; i != NULL; i = i->i_asame) { |
662 | if (i->i_unit == STAR) |
663 | goto foundstar; |
664 | } |
665 | continue; |
666 | foundstar: |
667 | if (ht_lookup(needcnttab, d->d_name)) { |
668 | warnx("%s's cannot be *'d until its driver is fixed", |
669 | d->d_name); |
670 | errs++; |
671 | continue; |
672 | } |
673 | for (n = 0; i != NULL; i = i->i_alias) |
674 | if (!i->i_collapsed) |
675 | n++; |
676 | if (n < 1) |
677 | panic("badstar() n<1"); |
678 | } |
679 | return (errs); |
680 | } |
681 | |
682 | |
683 | |
684 | |
685 | |
686 | void |
687 | setupdirs(void) |
688 | { |
689 | struct stat st; |
690 | FILE *fp; |
691 | |
692 | |
693 | |
694 | if ((builddir || strcmp(defbuilddir, ".") == 0) && !srcdir) { |
695 | error("source directory must be specified"); |
696 | exit(1); |
697 | } |
698 | |
699 | if (srcdir == NULL) |
700 | srcdir = "../../../.."; |
701 | if (builddir == NULL) |
702 | builddir = defbuilddir; |
703 | |
704 | if (stat(builddir, &st) != 0) { |
705 | if (mkdir(builddir, 0777)) |
706 | err(2, "cannot create %s", builddir); |
707 | } else if (!S_ISDIR(st.st_mode)) |
708 | errc(2, ENOTDIR, "%s", builddir); |
709 | if (chdir(builddir) != 0) |
710 | errx(2, "cannot change to %s", builddir); |
711 | if (stat(srcdir, &st) != 0 || !S_ISDIR(st.st_mode)) |
712 | errc(2, ENOTDIR, "%s", srcdir); |
713 | |
714 | if (bflag) { |
715 | if (pledge("stdio rpath wpath cpath flock", NULL) == -1) |
716 | err(1, "pledge"); |
717 | return; |
718 | } |
719 | |
720 | if (stat("obj", &st) == 0) |
721 | goto reconfig; |
722 | |
723 | fp = fopen("Makefile", "w"); |
724 | if (!fp) |
725 | errx(2, "cannot create Makefile"); |
726 | if (fprintf(fp, ".include \"../Makefile.inc\"\n") < 0 || |
727 | fclose(fp) == EOF) |
728 | errx(2, "cannot write Makefile"); |
729 | |
730 | reconfig: |
731 | if (system("make obj") != 0) |
732 | exit(2); |
733 | if (system("make config") != 0) |
734 | exit(2); |
735 | exit(0); |
736 | } |
737 | |
738 | struct opt { |
739 | const char *name; |
740 | const char *val; |
741 | }; |
742 | |
743 | int |
744 | optcmp(const void *v1, const void *v2) |
745 | { |
746 | const struct opt *sp1 = v1, *sp2 = v2; |
747 | int r; |
748 | |
749 | r = strcmp(sp1->name, sp2->name); |
750 | if (r == 0) { |
751 | if (!sp1->val && !sp2->val) |
752 | r = 0; |
753 | else if (sp1->val && !sp2->val) |
754 | r = -1; |
755 | else if (sp2->val && !sp1->val) |
756 | r = 1; |
757 | else r = strcmp(sp1->val, sp2->val); |
758 | } |
759 | return (r); |
760 | } |
761 | |
762 | void |
763 | optiondelta(void) |
764 | { |
765 | struct nvlist *nv; |
766 | char nbuf[BUFSIZ], obuf[BUFSIZ]; |
767 | int nnewopts, ret = 0, i; |
768 | struct opt *newopts; |
769 | FILE *fp; |
770 | |
771 | for (nnewopts = 0, nv = options; nv != NULL; nv = nv->nv_next) |
| 33 | | Assuming 'nv' is not equal to NULL | |
|
| 34 | | Loop condition is true. Entering loop body | |
|
| 35 | | Assuming 'nv' is equal to NULL | |
|
| 36 | | Loop condition is false. Execution continues on line 773 | |
|
772 | nnewopts++; |
773 | newopts = ereallocarray(NULL, nnewopts, sizeof(struct opt)); |
| 37 | | Value assigned to 'newopts' | |
|
774 | if (newopts == NULL) |
| 38 | | Assuming 'newopts' is equal to NULL | |
|
| |
775 | ret = 0; |
776 | for (i = 0, nv = options; nv != NULL; nv = nv->nv_next, i++) { |
| 40 | | Assuming 'nv' is equal to NULL | |
|
| 41 | | Loop condition is false. Execution continues on line 780 | |
|
777 | newopts[i].name = nv->nv_name; |
778 | newopts[i].val = nv->nv_str; |
779 | } |
780 | qsort(newopts, nnewopts, sizeof (struct opt), optcmp); |
781 | |
782 | |
783 | if ((fp = fopen("options", "r"))) { |
| 42 | | Assuming 'fp' is non-null | |
|
| |
784 | for (i = 0; !feof(fp) && i < nnewopts && ret == 0; i++) { |
| 44 | | Assuming '__isthreaded' is 0 | |
|
| |
| 46 | | Assuming the condition is false | |
|
| 47 | | Loop condition is true. Entering loop body | |
|
785 | if (newopts[i].val) |
| 48 | | Dereference of null pointer |
|
786 | snprintf(nbuf, sizeof nbuf, "%s=%s\n", |
787 | newopts[i].name, newopts[i].val); |
788 | else |
789 | snprintf(nbuf, sizeof nbuf, "%s\n", |
790 | newopts[i].name); |
791 | if (fgets(obuf, sizeof obuf, fp) == NULL || |
792 | strcmp(nbuf, obuf)) |
793 | ret = 1; |
794 | } |
795 | fclose(fp); |
796 | fp = NULL; |
797 | } else if (access("options", F_OK) == 0) |
798 | ret = 1; |
799 | |
800 | |
801 | if ((fp = fopen("options", "w+"))) { |
802 | rewind(fp); |
803 | for (i = 0; i < nnewopts; i++) { |
804 | if (newopts[i].val) |
805 | fprintf(fp, "%s=%s\n", newopts[i].name, |
806 | newopts[i].val); |
807 | else |
808 | fprintf(fp, "%s\n", newopts[i].name); |
809 | } |
810 | fclose(fp); |
811 | } |
812 | free(newopts); |
813 | if (ret == 0) |
814 | return; |
815 | (void)printf("Kernel options have changed -- you must run \"make clean\"\n"); |
816 | } |