Bug Summary

File:src/sbin/restore/interactive.c
Warning:line 688, column 4
3rd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name interactive.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/sbin/restore/obj -resource-dir /usr/local/lib/clang/13.0.0 -D RRESTORE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/restore/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/restore/interactive.c
1/* $OpenBSD: interactive.c,v 1.30 2015/01/20 18:22:21 deraadt Exp $ */
2/* $NetBSD: interactive.c,v 1.10 1997/03/19 08:42:52 lukem Exp $ */
3
4/*
5 * Copyright (c) 1985, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/time.h>
34#include <sys/stat.h>
35
36#include <ufs/ffs/fs.h>
37#include <ufs/ufs/dinode.h>
38#include <ufs/ufs/dir.h>
39#include <protocols/dumprestore.h>
40
41#include <setjmp.h>
42#include <glob.h>
43#include <stdio.h>
44#include <errno(*__errno()).h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48#include <limits.h>
49
50#include "restore.h"
51#include "extern.h"
52
53#define round(a, b)(((a) + (b) - 1) / (b) * (b)) (((a) + (b) - 1) / (b) * (b))
54
55/*
56 * Things to handle interruptions.
57 */
58static int runshell;
59static jmp_buf reset;
60static char *nextarg = NULL((void *)0);
61
62/*
63 * Structure and routines associated with listing directories.
64 */
65struct afile {
66 ino_t fnum; /* inode number of file */
67 char *fname; /* file name */
68 short len; /* name length */
69 char prefix; /* prefix character */
70 char postfix; /* postfix character */
71};
72struct arglist {
73 int freeglob; /* glob structure needs to be freed */
74 int argcnt; /* next globbed argument to return */
75 glob_t glob; /* globbing information */
76 char *cmd; /* the current command */
77};
78
79static char *copynext(char *, char *);
80static int fcmp(const void *, const void *);
81static void formatf(struct afile *, int);
82static void getcmd(char *, char *, size_t, char *, size_t, struct arglist *);
83struct dirent *glob_readdir(RST_DIR *dirp);
84static int glob_stat(const char *, struct stat *);
85static void mkentry(char *, struct direct *, struct afile *);
86static void printlist(char *, char *);
87
88/*
89 * Read and execute commands from the terminal.
90 */
91void
92runcmdshell(void)
93{
94 struct entry *np;
95 ino_t ino;
96 struct arglist arglist;
97 char curdir[PATH_MAX1024];
98 char name[PATH_MAX1024];
99 char cmd[BUFSIZ1024];
100
101 arglist.freeglob = 0;
102 arglist.argcnt = 0;
103 arglist.glob.gl_flags = GLOB_ALTDIRFUNC0x0040;
104 arglist.glob.gl_opendir = (void *)rst_opendir;
105 arglist.glob.gl_readdir = (void *)glob_readdir;
106 arglist.glob.gl_closedir = (void *)rst_closedir;
107 arglist.glob.gl_lstat = glob_stat;
108 arglist.glob.gl_stat = glob_stat;
109 canon("/", curdir, sizeof curdir);
110loop:
111 if (setjmp(reset) != 0) {
1
Assuming the condition is false
2
Taking false branch
112 if (arglist.freeglob != 0) {
113 arglist.freeglob = 0;
114 arglist.argcnt = 0;
115 globfree(&arglist.glob);
116 }
117 nextarg = NULL((void *)0);
118 volno = 0;
119 }
120 runshell = 1;
121 getcmd(curdir, cmd, sizeof cmd, name, sizeof name, &arglist);
122 switch (cmd[0]) {
3
Control jumps to 'case 108:' at line 206
123 /*
124 * Add elements to the extraction list.
125 */
126 case 'a':
127 if (strncmp(cmd, "add", strlen(cmd)) != 0)
128 goto bad;
129 ino = dirlookup(name);
130 if (ino == 0)
131 break;
132 if (mflag)
133 pathcheck(name);
134 treescan(name, ino, addfile);
135 break;
136 /*
137 * Change working directory.
138 */
139 case 'c':
140 if (strncmp(cmd, "cd", strlen(cmd)) != 0)
141 goto bad;
142 ino = dirlookup(name);
143 if (ino == 0)
144 break;
145 if (inodetype(ino) == LEAF1) {
146 fprintf(stderr(&__sF[2]), "%s: not a directory\n", name);
147 break;
148 }
149 (void)strlcpy(curdir, name, sizeof curdir);
150 break;
151 /*
152 * Delete elements from the extraction list.
153 */
154 case 'd':
155 if (strncmp(cmd, "delete", strlen(cmd)) != 0)
156 goto bad;
157 np = lookupname(name);
158 if (np == NULL((void *)0) || (np->e_flags & NEW0x0002) == 0) {
159 fprintf(stderr(&__sF[2]), "%s: not on extraction list\n", name);
160 break;
161 }
162 treescan(name, np->e_ino, deletefile);
163 break;
164 /*
165 * Extract the requested list.
166 */
167 case 'e':
168 if (strncmp(cmd, "extract", strlen(cmd)) != 0)
169 goto bad;
170 createfiles();
171 createlinks();
172 setdirmodes(0);
173 if (dflag)
174 checkrestore();
175 volno = 0;
176 break;
177 /*
178 * List available commands.
179 */
180 case 'h':
181 if (strncmp(cmd, "help", strlen(cmd)) != 0)
182 goto bad;
183 case '?':
184 fprintf(stderr(&__sF[2]), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
185 "Available commands are:\n",
186 "\tls [arg] - list directory\n",
187 "\tcd arg - change directory\n",
188 "\tpwd - print current directory\n",
189 "\tadd [arg] - add `arg' to list of",
190 " files to be extracted\n",
191 "\tdelete [arg] - delete `arg' from",
192 " list of files to be extracted\n",
193 "\textract - extract requested files\n",
194 "\tsetmodes - set modes of requested directories\n",
195 "\tquit - immediately exit program\n",
196 "\twhat - list dump header information\n",
197 "\tverbose - toggle verbose flag",
198 " (useful with ``ls'')\n",
199 "\thelp or `?' - print this list\n",
200 "If no `arg' is supplied, the current",
201 " directory is used\n");
202 break;
203 /*
204 * List a directory.
205 */
206 case 'l':
207 if (strncmp(cmd, "ls", strlen(cmd)) != 0)
4
Assuming the condition is false
5
Taking false branch
208 goto bad;
209 printlist(name, curdir);
6
Calling 'printlist'
210 break;
211 /*
212 * Print current directory.
213 */
214 case 'p':
215 if (strncmp(cmd, "pwd", strlen(cmd)) != 0)
216 goto bad;
217 if (curdir[1] == '\0')
218 fprintf(stderr(&__sF[2]), "/\n");
219 else
220 fprintf(stderr(&__sF[2]), "%s\n", &curdir[1]);
221 break;
222 /*
223 * Quit.
224 */
225 case 'q':
226 if (strncmp(cmd, "quit", strlen(cmd)) != 0)
227 goto bad;
228 return;
229 case 'x':
230 if (strncmp(cmd, "xit", strlen(cmd)) != 0)
231 goto bad;
232 return;
233 /*
234 * Toggle verbose mode.
235 */
236 case 'v':
237 if (strncmp(cmd, "verbose", strlen(cmd)) != 0)
238 goto bad;
239 if (vflag) {
240 fprintf(stderr(&__sF[2]), "verbose mode off\n");
241 vflag = 0;
242 break;
243 }
244 fprintf(stderr(&__sF[2]), "verbose mode on\n");
245 vflag++;
246 break;
247 /*
248 * Just restore requested directory modes.
249 */
250 case 's':
251 if (strncmp(cmd, "setmodes", strlen(cmd)) != 0)
252 goto bad;
253 setdirmodes(FORCE0x0001);
254 break;
255 /*
256 * Print out dump header information.
257 */
258 case 'w':
259 if (strncmp(cmd, "what", strlen(cmd)) != 0)
260 goto bad;
261 printdumpinfo();
262 break;
263 /*
264 * Turn on debugging.
265 */
266 case 'D':
267 if (strncmp(cmd, "Debug", strlen(cmd)) != 0)
268 goto bad;
269 if (dflag) {
270 fprintf(stderr(&__sF[2]), "debugging mode off\n");
271 dflag = 0;
272 break;
273 }
274 fprintf(stderr(&__sF[2]), "debugging mode on\n");
275 dflag++;
276 break;
277 /*
278 * Unknown command.
279 */
280 default:
281 bad:
282 fprintf(stderr(&__sF[2]), "%s: unknown command; type ? for help\n", cmd);
283 break;
284 }
285 goto loop;
286}
287
288/*
289 * Read and parse an interactive command.
290 * The first word on the line is assigned to "cmd". If
291 * there are no arguments on the command line, then "curdir"
292 * is returned as the argument. If there are arguments
293 * on the line they are returned one at a time on each
294 * successive call to getcmd. Each argument is first assigned
295 * to "name". If it does not start with "/" the pathname in
296 * "curdir" is prepended to it. Finally "canon" is called to
297 * eliminate any embedded ".." components.
298 */
299static void
300getcmd(char *curdir, char *cmd, size_t cmdlen, char *name, size_t namelen,
301 struct arglist *ap)
302{
303 char *cp;
304 static char input[BUFSIZ1024];
305 char output[BUFSIZ1024];
306# define rawname input /* save space by reusing input buffer */
307 int globretval;
308
309 /*
310 * Check to see if still processing arguments.
311 */
312 if (ap->argcnt > 0)
313 goto retnext;
314 if (nextarg != NULL((void *)0))
315 goto getnext;
316 /*
317 * Read a command line and trim off trailing white space.
318 */
319 do {
320 (void)fprintf(stderr(&__sF[2]), "%s > ", __progname);
321 (void)fflush(stderr(&__sF[2]));
322 if (fgets(input, sizeof input, terminal) == NULL((void *)0)) {
323 (void)strlcpy(cmd, "quit", cmdlen);
324 return;
325 }
326 } while (input[0] == '\n' || input[0] == '\0');
327 for (cp = &input[strlen(input) - 1];
328 cp >= input && (*cp == ' ' || *cp == '\t' || *cp == '\n'); cp--)
329 /* trim off trailing white space and newline */;
330 *++cp = '\0';
331 /*
332 * Copy the command into "cmd".
333 */
334 cp = copynext(input, cmd);
335 ap->cmd = cmd;
336 /*
337 * If no argument, use curdir as the default.
338 */
339 if (*cp == '\0') {
340 (void)strlcpy(name, curdir, PATH_MAX1024);
341 return;
342 }
343 nextarg = cp;
344 /*
345 * Find the next argument.
346 */
347getnext:
348 cp = copynext(nextarg, rawname);
349 if (*cp == '\0')
350 nextarg = NULL((void *)0);
351 else
352 nextarg = cp;
353 /*
354 * If it is an absolute pathname, canonicalize it and return it.
355 */
356 if (rawname[0] == '/') {
357 canon(rawname, name, namelen);
358 } else {
359 /*
360 * For relative pathnames, prepend the current directory to
361 * it then canonicalize and return it.
362 */
363 snprintf(output, sizeof(output), "%s/%s", curdir, rawname);
364 canon(output, name, namelen);
365 }
366 if ((globretval = glob(name, GLOB_ALTDIRFUNC0x0040 | GLOB_NOESCAPE0x1000,
367 NULL((void *)0), &ap->glob)) < 0) {
368 fprintf(stderr(&__sF[2]), "%s: %s: ", ap->cmd, name);
369 switch (globretval) {
370 case GLOB_NOSPACE(-1):
371 fprintf(stderr(&__sF[2]), "out of memory\n");
372 break;
373 case GLOB_NOMATCH(-3):
374 fprintf(stderr(&__sF[2]), "no filename match.\n");
375 break;
376 case GLOB_ABORTED(-2):
377 fprintf(stderr(&__sF[2]), "glob() aborted.\n");
378 break;
379 default:
380 fprintf(stderr(&__sF[2]), "unknown error!\n");
381 break;
382 }
383 }
384
385 if (ap->glob.gl_pathc == 0)
386 return;
387 ap->freeglob = 1;
388 ap->argcnt = ap->glob.gl_pathc;
389
390retnext:
391 strlcpy(name, ap->glob.gl_pathv[ap->glob.gl_pathc - ap->argcnt],
392 PATH_MAX1024);
393 if (--ap->argcnt == 0) {
394 ap->freeglob = 0;
395 globfree(&ap->glob);
396 }
397# undef rawname
398}
399
400/*
401 * Strip off the next token of the input.
402 */
403static char *
404copynext(char *input, char *output)
405{
406 char *cp, *bp;
407 char quote;
408
409 for (cp = input; *cp == ' ' || *cp == '\t'; cp++)
410 /* skip to argument */;
411 bp = output;
412 while (*cp != ' ' && *cp != '\t' && *cp != '\0') {
413 /*
414 * Handle back slashes.
415 */
416 if (*cp == '\\') {
417 if (*++cp == '\0') {
418 fprintf(stderr(&__sF[2]),
419 "command lines cannot be continued\n");
420 continue;
421 }
422 *bp++ = *cp++;
423 continue;
424 }
425 /*
426 * The usual unquoted case.
427 */
428 if (*cp != '\'' && *cp != '"') {
429 *bp++ = *cp++;
430 continue;
431 }
432 /*
433 * Handle single and double quotes.
434 */
435 quote = *cp++;
436 while (*cp != quote && *cp != '\0')
437 *bp++ = *cp++;
438 if (*cp++ == '\0') {
439 fprintf(stderr(&__sF[2]), "missing %c\n", quote);
440 cp--;
441 continue;
442 }
443 }
444 *bp = '\0';
445 return (cp);
446}
447
448/*
449 * Canonicalize file names to always start with ``./'' and
450 * remove any imbedded "." and ".." components.
451 */
452void
453canon(char *rawname, char *canonname, size_t canonnamelen)
454{
455 char *cp, *np;
456
457 if (strcmp(rawname, ".") == 0 || strncmp(rawname, "./", 2) == 0)
458 (void)strlcpy(canonname, "", canonnamelen);
459 else if (rawname[0] == '/')
460 (void)strlcpy(canonname, ".", canonnamelen);
461 else
462 (void)strlcpy(canonname, "./", canonnamelen);
463 (void)strlcat(canonname, rawname, canonnamelen);
464 /*
465 * Eliminate multiple and trailing '/'s
466 */
467 for (cp = np = canonname; *np != '\0'; cp++) {
468 *cp = *np++;
469 while (*cp == '/' && *np == '/')
470 np++;
471 }
472 *cp = '\0';
473 if (*--cp == '/')
474 *cp = '\0';
475 /*
476 * Eliminate extraneous "." and ".." from pathnames.
477 */
478 for (np = canonname; *np != '\0'; ) {
479 np++;
480 cp = np;
481 while (*np != '/' && *np != '\0')
482 np++;
483 if (np - cp == 1 && *cp == '.') {
484 cp--;
485 (void)strlcpy(cp, np, canonname + canonnamelen - cp);
486 np = cp;
487 }
488 if (np - cp == 2 && strncmp(cp, "..", 2) == 0) {
489 cp--;
490 while (cp > &canonname[1] && *--cp != '/')
491 /* find beginning of name */;
492 (void)strlcpy(cp, np, canonname + canonnamelen - cp);
493 np = cp;
494 }
495 }
496}
497
498/*
499 * Do an "ls" style listing of a directory
500 */
501static void
502printlist(char *name, char *basename)
503{
504 struct afile *fp, *list, *listp = NULL((void *)0);
505 struct direct *dp;
506 struct afile single;
507 RST_DIR *dirp;
508 size_t namelen;
509 int entries, len;
510 char locname[PATH_MAX1024];
511
512 dp = pathsearch(name);
513 if (dp == NULL((void *)0) || (!dflag && TSTINO(dp->d_ino, dumpmap)(dumpmap[(u_int)((dp->d_ino) - 1) / 8] & (1 << (
(u_int)((dp->d_ino) - 1) % 8)))
== 0))
7
Assuming 'dp' is not equal to NULL
8
Assuming 'dflag' is not equal to 0
514 return;
515 if ((dirp = rst_opendir(name)) == NULL((void *)0)) {
9
Assuming the condition is true
10
Taking true branch
516 entries = 1;
517 list = &single;
518 mkentry(name, dp, list);
11
Calling 'mkentry'
17
Returning from 'mkentry'
519 len = strlen(basename) + 1;
520 if (strlen(name) - len > single.len) {
18
Assuming the condition is true
19
Taking true branch
521 freename(single.fname);
522 single.fname = savename(&name[len]);
523 single.len = strlen(single.fname);
524 }
525 } else {
526 entries = 0;
527 while ((dp = rst_readdir(dirp)))
528 entries++;
529 rst_closedir(dirp);
530 list = calloc(entries, sizeof(struct afile));
531 if (list == NULL((void *)0)) {
532 fprintf(stderr(&__sF[2]), "ls: out of memory\n");
533 return;
534 }
535 if ((dirp = rst_opendir(name)) == NULL((void *)0))
536 panic("directory reopen failed\n");
537 fprintf(stderr(&__sF[2]), "%s:\n", name);
538 entries = 0;
539 listp = list;
540 namelen = strlcpy(locname, name, sizeof(locname));
541 if (namelen >= sizeof(locname) - 1)
542 namelen = sizeof(locname) - 2;
543 locname[namelen++] = '/';
544 locname[namelen] = '\0';
545 while ((dp = rst_readdir(dirp))) {
546 if (dp == NULL((void *)0))
547 break;
548 if (!dflag && TSTINO(dp->d_ino, dumpmap)(dumpmap[(u_int)((dp->d_ino) - 1) / 8] & (1 << (
(u_int)((dp->d_ino) - 1) % 8)))
== 0)
549 continue;
550 if (!vflag && (strcmp(dp->d_name, ".") == 0 ||
551 strcmp(dp->d_name, "..") == 0))
552 continue;
553 locname[namelen] = '\0';
554 if (namelen + dp->d_namlen >= PATH_MAX1024) {
555 fprintf(stderr(&__sF[2]), "%s%s: name exceeds %d char\n",
556 locname, dp->d_name, PATH_MAX1024);
557 } else {
558 (void)strncat(locname, dp->d_name,
559 (int)dp->d_namlen);
560 mkentry(locname, dp, listp++);
561 entries++;
562 }
563 }
564 rst_closedir(dirp);
565 if (entries == 0) {
566 fprintf(stderr(&__sF[2]), "\n");
567 free(list);
568 return;
569 }
570 qsort((char *)list, entries, sizeof(struct afile), fcmp);
571 }
572 formatf(list, entries);
20
Calling 'formatf'
573 if (dirp != NULL((void *)0)) {
574 for (fp = listp - 1; fp >= list; fp--)
575 freename(fp->fname);
576 fprintf(stderr(&__sF[2]), "\n");
577 free(list);
578 }
579}
580
581/*
582 * Read the contents of a directory.
583 */
584static void
585mkentry(char *name, struct direct *dp, struct afile *fp)
586{
587 char *cp;
588 struct entry *np;
589
590 fp->fnum = dp->d_ino;
591 fp->fname = savename(dp->d_name);
592 for (cp = fp->fname; *cp; cp++)
12
Loop condition is false. Execution continues on line 595
593 if (!vflag && (*cp < ' ' || *cp >= 0177))
594 *cp = '?';
595 fp->len = cp - fp->fname;
596 if (dflag && TSTINO(fp->fnum, dumpmap)(dumpmap[(u_int)((fp->fnum) - 1) / 8] & (1 << ((
u_int)((fp->fnum) - 1) % 8)))
== 0)
13
Assuming 'dflag' is 0
597 fp->prefix = '^';
598 else if ((np = lookupname(name)) != NULL((void *)0) && (np->e_flags & NEW0x0002))
14
Assuming the condition is false
599 fp->prefix = '*';
600 else
601 fp->prefix = ' ';
602 switch(dp->d_type) {
15
Control jumps to 'case 8:' at line 608
603
604 default:
605 fprintf(stderr(&__sF[2]), "Warning: undefined file type %d\n",
606 dp->d_type);
607 /* fall through */
608 case DT_REG8:
609 fp->postfix = ' ';
610 break;
16
Execution continues on line 634
611
612 case DT_LNK10:
613 fp->postfix = '@';
614 break;
615
616 case DT_FIFO1:
617 case DT_SOCK12:
618 fp->postfix = '=';
619 break;
620
621 case DT_CHR2:
622 case DT_BLK6:
623 fp->postfix = '#';
624 break;
625
626 case DT_UNKNOWN0:
627 case DT_DIR4:
628 if (inodetype(dp->d_ino) == NODE2)
629 fp->postfix = '/';
630 else
631 fp->postfix = ' ';
632 break;
633 }
634 return;
635}
636
637/*
638 * Print out a pretty listing of a directory
639 */
640static void
641formatf(struct afile *list, int nentry)
642{
643 struct afile *fp, *endlist;
644 int width, bigino, haveprefix, havepostfix;
645 int i, j, w, precision = 0, columns, lines;
646
647 width = 0;
648 haveprefix = 0;
649 havepostfix = 0;
650 bigino = ROOTINO((ufsino_t)2);
651 endlist = &list[nentry];
652 for (fp = &list[0]; fp < endlist; fp++) {
21
Loop condition is true. Entering loop body
28
Loop condition is false. Execution continues on line 662
653 if (bigino < fp->fnum)
22
Assuming 'bigino' is >= field 'fnum'
23
Taking false branch
654 bigino = fp->fnum;
655 if (width < fp->len)
24
Assuming 'width' is < field 'len'
25
Taking true branch
656 width = fp->len;
657 if (fp->prefix != ' ')
26
Taking false branch
658 haveprefix = 1;
659 if (fp->postfix != ' ')
27
Taking false branch
660 havepostfix = 1;
661 }
662 if (haveprefix
28.1
'haveprefix' is 0
)
29
Taking false branch
663 width++;
664 if (havepostfix
29.1
'havepostfix' is 0
)
30
Taking false branch
665 width++;
666 if (vflag) {
31
Assuming 'vflag' is 0
32
Taking false branch
667 for (precision = 0, i = bigino; i > 0; i /= 10)
668 precision++;
669 width += precision + 1;
670 }
671 width++;
672 columns = 81 / width;
673 if (columns == 0)
33
Assuming 'columns' is not equal to 0
34
Taking false branch
674 columns = 1;
675 lines = (nentry + columns - 1) / columns;
676 for (i = 0; i < lines; i++) {
35
Assuming 'i' is < 'lines'
36
Loop condition is true. Entering loop body
44
Assuming 'i' is < 'lines'
45
Loop condition is true. Entering loop body
677 for (j = 0; j
45.1
'j' is < 'columns'
< columns
; j++) {
37
Assuming 'j' is < 'columns'
38
Loop condition is true. Entering loop body
46
Loop condition is true. Entering loop body
678 fp = &list[j * lines + i];
679 if (vflag
38.1
'vflag' is 0
46.1
'vflag' is 0
) {
39
Taking false branch
47
Taking false branch
680 fprintf(stderr(&__sF[2]), "%*llu ", precision,
681 (unsigned long long)fp->fnum);
682 fp->len += precision + 1;
683 }
684 if (haveprefix
39.1
'haveprefix' is 0
47.1
'haveprefix' is 0
) {
40
Taking false branch
48
Taking false branch
685 putc(fp->prefix, stderr)(!__isthreaded ? __sputc(fp->prefix, (&__sF[2])) : (putc
)(fp->prefix, (&__sF[2])))
;
686 fp->len++;
687 }
688 fprintf(stderr(&__sF[2]), "%s", fp->fname);
49
3rd function call argument is an uninitialized value
689 if (havepostfix
40.1
'havepostfix' is 0
) {
41
Taking false branch
690 putc(fp->postfix, stderr)(!__isthreaded ? __sputc(fp->postfix, (&__sF[2])) : (putc
)(fp->postfix, (&__sF[2])))
;
691 fp->len++;
692 }
693 if (fp + lines >= endlist) {
42
Taking true branch
694 fprintf(stderr(&__sF[2]), "\n");
695 break;
43
Execution continues on line 676
696 }
697 for (w = fp->len; w < width; w++)
698 putc(' ', stderr)(!__isthreaded ? __sputc(' ', (&__sF[2])) : (putc)(' ', (
&__sF[2])))
;
699 }
700 }
701}
702
703/*
704 * Skip over directory entries that are not on the tape
705 *
706 * First have to get definition of a dirent.
707 */
708#undef DIRBLKSIZ1024
709#include <dirent.h>
710#undef d_ino
711
712struct dirent *
713glob_readdir(RST_DIR *dirp)
714{
715 struct direct *dp;
716 static struct dirent adirent;
717
718 while ((dp = rst_readdir(dirp)) != NULL((void *)0)) {
719 if (dflag || TSTINO(dp->d_ino, dumpmap)(dumpmap[(u_int)((dp->d_ino) - 1) / 8] & (1 << (
(u_int)((dp->d_ino) - 1) % 8)))
)
720 break;
721 }
722 if (dp == NULL((void *)0))
723 return (NULL((void *)0));
724 adirent.d_fileno = dp->d_ino;
725 adirent.d_namlen = dp->d_namlen;
726 memcpy(adirent.d_name, dp->d_name, dp->d_namlen + 1);
727 return (&adirent);
728}
729
730/*
731 * Return st_mode information in response to stat or lstat calls
732 */
733static int
734glob_stat(const char *name, struct stat *stp)
735{
736 struct direct *dp;
737
738 dp = pathsearch(name);
739 if (dp == NULL((void *)0) || (!dflag && TSTINO(dp->d_ino, dumpmap)(dumpmap[(u_int)((dp->d_ino) - 1) / 8] & (1 << (
(u_int)((dp->d_ino) - 1) % 8)))
== 0))
740 return (-1);
741 if (inodetype(dp->d_ino) == NODE2)
742 stp->st_mode = S_IFDIR0040000;
743 else
744 stp->st_mode = S_IFREG0100000;
745 return (0);
746}
747
748/*
749 * Comparison routine for qsort.
750 */
751static int
752fcmp(const void *f1, const void *f2)
753{
754 return (strcmp(((struct afile *)f1)->fname,
755 ((struct afile *)f2)->fname));
756}
757
758/*
759 * respond to interrupts
760 */
761void
762onintr(int signo)
763{
764 int save_errno = errno(*__errno());
765
766 if (command == 'i' && runshell)
767 longjmp(reset, 1); /* XXX signal/longjmp reentrancy */
768 if (reply("restore interrupted, continue") == FAIL0) /* XXX signal race */
769 _exit(1);
770 errno(*__errno()) = save_errno;
771}