File: | src/usr.bin/file/file.c |
Warning: | line 680, column 3 Value stored to 'stop' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: file.c,v 1.69 2019/11/30 14:01:45 mestre Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org> |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
15 | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
16 | * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | #include <sys/types.h> |
20 | #include <sys/ioctl.h> |
21 | #include <sys/mman.h> |
22 | #include <sys/queue.h> |
23 | #include <sys/socket.h> |
24 | #include <sys/stat.h> |
25 | #include <sys/uio.h> |
26 | #include <sys/wait.h> |
27 | |
28 | #include <err.h> |
29 | #include <errno(*__errno()).h> |
30 | #include <fcntl.h> |
31 | #include <getopt.h> |
32 | #include <imsg.h> |
33 | #include <libgen.h> |
34 | #include <limits.h> |
35 | #include <pwd.h> |
36 | #include <stdlib.h> |
37 | #include <string.h> |
38 | #include <time.h> |
39 | #include <unistd.h> |
40 | |
41 | #include "file.h" |
42 | #include "magic.h" |
43 | #include "xmalloc.h" |
44 | |
45 | struct input_msg { |
46 | int idx; |
47 | |
48 | struct stat sb; |
49 | int error; |
50 | |
51 | char link_path[PATH_MAX1024]; |
52 | int link_error; |
53 | int link_target; |
54 | }; |
55 | |
56 | struct input_ack { |
57 | int idx; |
58 | }; |
59 | |
60 | struct input_file { |
61 | struct magic *m; |
62 | struct input_msg *msg; |
63 | |
64 | const char *path; |
65 | int fd; |
66 | |
67 | void *base; |
68 | size_t size; |
69 | int mapped; |
70 | char *result; |
71 | }; |
72 | |
73 | extern char *__progname; |
74 | |
75 | __dead__attribute__((__noreturn__)) void usage(void); |
76 | |
77 | static int prepare_message(struct input_msg *, int, const char *); |
78 | static void send_message(struct imsgbuf *, void *, size_t, int); |
79 | static int read_message(struct imsgbuf *, struct imsg *, pid_t); |
80 | |
81 | static void read_link(struct input_msg *, const char *); |
82 | |
83 | static __dead__attribute__((__noreturn__)) void child(int, pid_t, int, char **); |
84 | |
85 | static void test_file(struct input_file *, size_t); |
86 | |
87 | static int try_stat(struct input_file *); |
88 | static int try_empty(struct input_file *); |
89 | static int try_access(struct input_file *); |
90 | static int try_text(struct input_file *); |
91 | static int try_magic(struct input_file *); |
92 | static int try_unknown(struct input_file *); |
93 | |
94 | static int bflag; |
95 | static int cflag; |
96 | static int iflag; |
97 | static int Lflag; |
98 | static int sflag; |
99 | static int Wflag; |
100 | |
101 | static char *magicpath; |
102 | static FILE *magicfp; |
103 | |
104 | static struct option longopts[] = { |
105 | { "brief", no_argument0, NULL((void *)0), 'b' }, |
106 | { "dereference", no_argument0, NULL((void *)0), 'L' }, |
107 | { "mime", no_argument0, NULL((void *)0), 'i' }, |
108 | { "mime-type", no_argument0, NULL((void *)0), 'i' }, |
109 | { NULL((void *)0), 0, NULL((void *)0), 0 } |
110 | }; |
111 | |
112 | __dead__attribute__((__noreturn__)) void |
113 | usage(void) |
114 | { |
115 | fprintf(stderr(&__sF[2]), "usage: %s [-bchiLsW] file ...\n", __progname); |
116 | exit(1); |
117 | } |
118 | |
119 | int |
120 | main(int argc, char **argv) |
121 | { |
122 | int opt, pair[2], fd, idx; |
123 | char *home; |
124 | struct passwd *pw; |
125 | struct imsgbuf ibuf; |
126 | struct imsg imsg; |
127 | struct input_msg msg; |
128 | struct input_ack *ack; |
129 | pid_t pid, parent; |
130 | |
131 | tzset(); |
132 | |
133 | for (;;) { |
134 | opt = getopt_long(argc, argv, "bchiLsW", longopts, NULL((void *)0)); |
135 | if (opt == -1) |
136 | break; |
137 | switch (opt) { |
138 | case 'b': |
139 | bflag = 1; |
140 | break; |
141 | case 'c': |
142 | cflag = 1; |
143 | break; |
144 | case 'h': |
145 | Lflag = 0; |
146 | break; |
147 | case 'i': |
148 | iflag = 1; |
149 | break; |
150 | case 'L': |
151 | Lflag = 1; |
152 | break; |
153 | case 's': |
154 | sflag = 1; |
155 | break; |
156 | case 'W': |
157 | Wflag = 1; |
158 | break; |
159 | default: |
160 | usage(); |
161 | } |
162 | } |
163 | argc -= optind; |
164 | argv += optind; |
165 | if (cflag) { |
166 | if (argc != 0) |
167 | usage(); |
168 | } else if (argc == 0) |
169 | usage(); |
170 | |
171 | if (pledge("stdio rpath getpw recvfd sendfd id proc", NULL((void *)0)) == -1) |
172 | err(1, "pledge"); |
173 | |
174 | magicfp = NULL((void *)0); |
175 | if (geteuid() != 0 && !issetugid()) { |
176 | home = getenv("HOME"); |
177 | if (home == NULL((void *)0) || *home == '\0') { |
178 | pw = getpwuid(getuid()); |
179 | if (pw != NULL((void *)0)) |
180 | home = pw->pw_dir; |
181 | else |
182 | home = NULL((void *)0); |
183 | } |
184 | if (home != NULL((void *)0)) { |
185 | xasprintf(&magicpath, "%s/.magic", home); |
186 | magicfp = fopen(magicpath, "r"); |
187 | if (magicfp == NULL((void *)0)) |
188 | free(magicpath); |
189 | } |
190 | } |
191 | if (magicfp == NULL((void *)0)) { |
192 | magicpath = xstrdup("/etc/magic"); |
193 | magicfp = fopen(magicpath, "r"); |
194 | } |
195 | if (magicfp == NULL((void *)0)) |
196 | err(1, "%s", magicpath); |
197 | |
198 | parent = getpid(); |
199 | if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, pair) != 0) |
200 | err(1, "socketpair"); |
201 | switch (pid = fork()) { |
202 | case -1: |
203 | err(1, "fork"); |
204 | case 0: |
205 | close(pair[0]); |
206 | child(pair[1], parent, argc, argv); |
207 | } |
208 | close(pair[1]); |
209 | |
210 | if (pledge("stdio rpath sendfd", NULL((void *)0)) == -1) |
211 | err(1, "pledge"); |
212 | |
213 | fclose(magicfp); |
214 | magicfp = NULL((void *)0); |
215 | |
216 | if (cflag) |
217 | goto wait_for_child; |
218 | |
219 | imsg_init(&ibuf, pair[0]); |
220 | for (idx = 0; idx < argc; idx++) { |
221 | fd = prepare_message(&msg, idx, argv[idx]); |
222 | send_message(&ibuf, &msg, sizeof msg, fd); |
223 | |
224 | if (read_message(&ibuf, &imsg, pid) == 0) |
225 | break; |
226 | if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof *ack) |
227 | errx(1, "message too small"); |
228 | ack = imsg.data; |
229 | if (ack->idx != idx) |
230 | errx(1, "index not expected"); |
231 | imsg_free(&imsg); |
232 | } |
233 | |
234 | wait_for_child: |
235 | close(pair[0]); |
236 | while (wait(NULL((void *)0)) == -1 && errno(*__errno()) != ECHILD10) { |
237 | if (errno(*__errno()) != EINTR4) |
238 | err(1, "wait"); |
239 | } |
240 | _exit(0); /* let the child flush */ |
241 | } |
242 | |
243 | static int |
244 | prepare_message(struct input_msg *msg, int idx, const char *path) |
245 | { |
246 | int fd, mode, error; |
247 | |
248 | memset(msg, 0, sizeof *msg); |
249 | msg->idx = idx; |
250 | |
251 | if (strcmp(path, "-") == 0) { |
252 | if (fstat(STDIN_FILENO0, &msg->sb) == -1) { |
253 | msg->error = errno(*__errno()); |
254 | return (-1); |
255 | } |
256 | return (STDIN_FILENO0); |
257 | } |
258 | |
259 | if (Lflag) |
260 | error = stat(path, &msg->sb); |
261 | else |
262 | error = lstat(path, &msg->sb); |
263 | if (error == -1) { |
264 | msg->error = errno(*__errno()); |
265 | return (-1); |
266 | } |
267 | |
268 | /* |
269 | * pledge(2) doesn't let us pass directory file descriptors around - |
270 | * but in fact we don't need them, so just don't open directories or |
271 | * symlinks (which could be to directories). |
272 | */ |
273 | mode = msg->sb.st_mode; |
274 | if (!S_ISDIR(mode)((mode & 0170000) == 0040000) && !S_ISLNK(mode)((mode & 0170000) == 0120000)) { |
275 | fd = open(path, O_RDONLY0x0000|O_NONBLOCK0x0004); |
276 | if (fd == -1 && (errno(*__errno()) == ENFILE23 || errno(*__errno()) == EMFILE24)) |
277 | err(1, "open"); |
278 | } else |
279 | fd = -1; |
280 | if (S_ISLNK(mode)((mode & 0170000) == 0120000)) |
281 | read_link(msg, path); |
282 | return (fd); |
283 | |
284 | } |
285 | |
286 | static void |
287 | send_message(struct imsgbuf *ibuf, void *msg, size_t msglen, int fd) |
288 | { |
289 | if (imsg_compose(ibuf, -1, -1, 0, fd, msg, msglen) != 1) |
290 | err(1, "imsg_compose"); |
291 | if (imsg_flush(ibuf) != 0) |
292 | err(1, "imsg_flush"); |
293 | } |
294 | |
295 | static int |
296 | read_message(struct imsgbuf *ibuf, struct imsg *imsg, pid_t from) |
297 | { |
298 | int n; |
299 | |
300 | while ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) == EAGAIN35) |
301 | /* nothing */ ; |
302 | if (n == -1) |
303 | err(1, "imsg_read"); |
304 | if (n == 0) |
305 | return (0); |
306 | |
307 | if ((n = imsg_get(ibuf, imsg)) == -1) |
308 | err(1, "imsg_get"); |
309 | if (n == 0) |
310 | return (0); |
311 | |
312 | if ((pid_t)imsg->hdr.pid != from) |
313 | errx(1, "PIDs don't match"); |
314 | |
315 | return (n); |
316 | |
317 | } |
318 | |
319 | static void |
320 | read_link(struct input_msg *msg, const char *path) |
321 | { |
322 | struct stat sb; |
323 | char lpath[PATH_MAX1024]; |
324 | char *copy, *root; |
325 | int used; |
326 | ssize_t size; |
327 | |
328 | size = readlink(path, lpath, sizeof lpath - 1); |
329 | if (size == -1) { |
330 | msg->link_error = errno(*__errno()); |
331 | return; |
332 | } |
333 | lpath[size] = '\0'; |
334 | |
335 | if (*lpath == '/') |
336 | strlcpy(msg->link_path, lpath, sizeof msg->link_path); |
337 | else { |
338 | copy = xstrdup(path); |
339 | |
340 | root = dirname(copy); |
341 | if (*root == '\0' || strcmp(root, ".") == 0 || |
342 | strcmp (root, "/") == 0) |
343 | strlcpy(msg->link_path, lpath, sizeof msg->link_path); |
344 | else { |
345 | used = snprintf(msg->link_path, sizeof msg->link_path, |
346 | "%s/%s", root, lpath); |
347 | if (used < 0 || (size_t)used >= sizeof msg->link_path) { |
348 | msg->link_error = ENAMETOOLONG63; |
349 | free(copy); |
350 | return; |
351 | } |
352 | } |
353 | |
354 | free(copy); |
355 | } |
356 | |
357 | if (!Lflag && stat(path, &sb) == -1) |
358 | msg->link_target = errno(*__errno()); |
359 | } |
360 | |
361 | static __dead__attribute__((__noreturn__)) void |
362 | child(int fd, pid_t parent, int argc, char **argv) |
363 | { |
364 | struct passwd *pw; |
365 | struct magic *m; |
366 | struct imsgbuf ibuf; |
367 | struct imsg imsg; |
368 | struct input_msg *msg; |
369 | struct input_ack ack; |
370 | struct input_file inf; |
371 | int i, idx; |
372 | size_t len, width = 0; |
373 | |
374 | if (pledge("stdio getpw recvfd id", NULL((void *)0)) == -1) |
375 | err(1, "pledge"); |
376 | |
377 | if (geteuid() == 0) { |
378 | pw = getpwnam(FILE_USER"_file"); |
379 | if (pw == NULL((void *)0)) |
380 | errx(1, "unknown user %s", FILE_USER"_file"); |
381 | if (setgroups(1, &pw->pw_gid) != 0) |
382 | err(1, "setgroups"); |
383 | if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0) |
384 | err(1, "setresgid"); |
385 | if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0) |
386 | err(1, "setresuid"); |
387 | } |
388 | |
389 | if (pledge("stdio recvfd", NULL((void *)0)) == -1) |
390 | err(1, "pledge"); |
391 | |
392 | m = magic_load(magicfp, magicpath, cflag || Wflag); |
393 | if (cflag) { |
394 | magic_dump(m); |
395 | exit(0); |
396 | } |
397 | |
398 | for (i = 0; i < argc; i++) { |
399 | len = strlen(argv[i]) + 1; |
400 | if (len > width) |
401 | width = len; |
402 | } |
403 | |
404 | imsg_init(&ibuf, fd); |
405 | for (;;) { |
406 | if (read_message(&ibuf, &imsg, parent) == 0) |
407 | break; |
408 | if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + sizeof *msg) |
409 | errx(1, "message too small"); |
410 | msg = imsg.data; |
411 | |
412 | idx = msg->idx; |
413 | if (idx < 0 || idx >= argc) |
414 | errx(1, "index out of range"); |
415 | |
416 | memset(&inf, 0, sizeof inf); |
417 | inf.m = m; |
418 | inf.msg = msg; |
419 | |
420 | inf.path = argv[idx]; |
421 | inf.fd = imsg.fd; |
422 | |
423 | test_file(&inf, width); |
424 | |
425 | if (imsg.fd != -1) |
426 | close(imsg.fd); |
427 | imsg_free(&imsg); |
428 | |
429 | ack.idx = idx; |
430 | send_message(&ibuf, &ack, sizeof ack, -1); |
431 | } |
432 | exit(0); |
433 | } |
434 | |
435 | static void * |
436 | fill_buffer(int fd, size_t size, size_t *used) |
437 | { |
438 | static void *buffer; |
439 | ssize_t got; |
440 | size_t left; |
441 | void *next; |
442 | |
443 | if (buffer == NULL((void *)0)) |
444 | buffer = xmalloc(FILE_READ_SIZE(256 * 1024)); |
445 | |
446 | next = buffer; |
447 | left = size; |
448 | while (left != 0) { |
449 | got = read(fd, next, left); |
450 | if (got == -1) { |
451 | if (errno(*__errno()) == EINTR4) |
452 | continue; |
453 | return (NULL((void *)0)); |
454 | } |
455 | if (got == 0) |
456 | break; |
457 | next = (char *)next + got; |
458 | left -= got; |
459 | } |
460 | *used = size - left; |
461 | return (buffer); |
462 | } |
463 | |
464 | static int |
465 | load_file(struct input_file *inf) |
466 | { |
467 | size_t used; |
468 | |
469 | if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode)((inf->msg->sb.st_mode & 0170000) == 0100000)) |
470 | return (0); /* empty file */ |
471 | if (inf->msg->sb.st_size == 0 || inf->msg->sb.st_size > FILE_READ_SIZE(256 * 1024)) |
472 | inf->size = FILE_READ_SIZE(256 * 1024); |
473 | else |
474 | inf->size = inf->msg->sb.st_size; |
475 | |
476 | if (!S_ISREG(inf->msg->sb.st_mode)((inf->msg->sb.st_mode & 0170000) == 0100000)) |
477 | goto try_read; |
478 | |
479 | inf->base = mmap(NULL((void *)0), inf->size, PROT_READ0x01, MAP_PRIVATE0x0002, inf->fd, 0); |
480 | if (inf->base == MAP_FAILED((void *)-1)) |
481 | goto try_read; |
482 | inf->mapped = 1; |
483 | return (0); |
484 | |
485 | try_read: |
486 | inf->base = fill_buffer(inf->fd, inf->size, &used); |
487 | if (inf->base == NULL((void *)0)) { |
488 | xasprintf(&inf->result, "cannot read '%s' (%s)", inf->path, |
489 | strerror(errno(*__errno()))); |
490 | return (1); |
491 | } |
492 | inf->size = used; |
493 | return (0); |
494 | } |
495 | |
496 | static int |
497 | try_stat(struct input_file *inf) |
498 | { |
499 | if (inf->msg->error != 0) { |
500 | xasprintf(&inf->result, "cannot stat '%s' (%s)", inf->path, |
501 | strerror(inf->msg->error)); |
502 | return (1); |
503 | } |
504 | if (sflag || strcmp(inf->path, "-") == 0) { |
505 | switch (inf->msg->sb.st_mode & S_IFMT0170000) { |
506 | case S_IFIFO0010000: |
507 | if (strcmp(inf->path, "-") != 0) |
508 | break; |
509 | case S_IFBLK0060000: |
510 | case S_IFCHR0020000: |
511 | case S_IFREG0100000: |
512 | return (0); |
513 | } |
514 | } |
515 | |
516 | if (iflag && (inf->msg->sb.st_mode & S_IFMT0170000) != S_IFREG0100000) { |
517 | xasprintf(&inf->result, "application/x-not-regular-file"); |
518 | return (1); |
519 | } |
520 | |
521 | switch (inf->msg->sb.st_mode & S_IFMT0170000) { |
522 | case S_IFDIR0040000: |
523 | xasprintf(&inf->result, "directory"); |
524 | return (1); |
525 | case S_IFLNK0120000: |
526 | if (inf->msg->link_error != 0) { |
527 | xasprintf(&inf->result, "unreadable symlink '%s' (%s)", |
528 | inf->path, strerror(inf->msg->link_error)); |
529 | return (1); |
530 | } |
531 | if (inf->msg->link_target == ELOOP62) |
532 | xasprintf(&inf->result, "symbolic link in a loop"); |
533 | else if (inf->msg->link_target != 0) { |
534 | xasprintf(&inf->result, "broken symbolic link to '%s'", |
535 | inf->msg->link_path); |
536 | } else { |
537 | xasprintf(&inf->result, "symbolic link to '%s'", |
538 | inf->msg->link_path); |
539 | } |
540 | return (1); |
541 | case S_IFSOCK0140000: |
542 | xasprintf(&inf->result, "socket"); |
543 | return (1); |
544 | case S_IFBLK0060000: |
545 | xasprintf(&inf->result, "block special (%lu/%lu)", |
546 | (long)major(inf->msg->sb.st_rdev)(((unsigned)(inf->msg->sb.st_rdev) >> 8) & 0xff ), |
547 | (long)minor(inf->msg->sb.st_rdev)((unsigned)((inf->msg->sb.st_rdev) & 0xff) | (((inf ->msg->sb.st_rdev) & 0xffff0000) >> 8))); |
548 | return (1); |
549 | case S_IFCHR0020000: |
550 | xasprintf(&inf->result, "character special (%lu/%lu)", |
551 | (long)major(inf->msg->sb.st_rdev)(((unsigned)(inf->msg->sb.st_rdev) >> 8) & 0xff ), |
552 | (long)minor(inf->msg->sb.st_rdev)((unsigned)((inf->msg->sb.st_rdev) & 0xff) | (((inf ->msg->sb.st_rdev) & 0xffff0000) >> 8))); |
553 | return (1); |
554 | case S_IFIFO0010000: |
555 | xasprintf(&inf->result, "fifo (named pipe)"); |
556 | return (1); |
557 | } |
558 | return (0); |
559 | } |
560 | |
561 | static int |
562 | try_empty(struct input_file *inf) |
563 | { |
564 | if (inf->size != 0) |
565 | return (0); |
566 | |
567 | if (iflag) |
568 | xasprintf(&inf->result, "application/x-empty"); |
569 | else |
570 | xasprintf(&inf->result, "empty"); |
571 | return (1); |
572 | } |
573 | |
574 | static int |
575 | try_access(struct input_file *inf) |
576 | { |
577 | char tmp[256] = ""; |
578 | |
579 | if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode)((inf->msg->sb.st_mode & 0170000) == 0100000)) |
580 | return (0); /* empty file */ |
581 | if (inf->fd != -1) |
582 | return (0); |
583 | |
584 | if (inf->msg->sb.st_mode & (S_IWUSR0000200|S_IWGRP0000020|S_IWOTH0000002)) |
585 | strlcat(tmp, "writable, ", sizeof tmp); |
586 | if (inf->msg->sb.st_mode & (S_IXUSR0000100|S_IXGRP0000010|S_IXOTH0000001)) |
587 | strlcat(tmp, "executable, ", sizeof tmp); |
588 | if (S_ISREG(inf->msg->sb.st_mode)((inf->msg->sb.st_mode & 0170000) == 0100000)) |
589 | strlcat(tmp, "regular file, ", sizeof tmp); |
590 | strlcat(tmp, "no read permission", sizeof tmp); |
591 | |
592 | inf->result = xstrdup(tmp); |
593 | return (1); |
594 | } |
595 | |
596 | static int |
597 | try_text(struct input_file *inf) |
598 | { |
599 | const char *type, *s; |
600 | int flags; |
601 | |
602 | flags = MAGIC_TEST_TEXT0x1; |
603 | if (iflag) |
604 | flags |= MAGIC_TEST_MIME0x2; |
605 | |
606 | type = text_get_type(inf->base, inf->size); |
607 | if (type == NULL((void *)0)) |
608 | return (0); |
609 | |
610 | s = magic_test(inf->m, inf->base, inf->size, flags); |
611 | if (s != NULL((void *)0)) { |
612 | inf->result = xstrdup(s); |
613 | return (1); |
614 | } |
615 | |
616 | s = text_try_words(inf->base, inf->size, flags); |
617 | if (s != NULL((void *)0)) { |
618 | if (iflag) |
619 | inf->result = xstrdup(s); |
620 | else |
621 | xasprintf(&inf->result, "%s %s text", type, s); |
622 | return (1); |
623 | } |
624 | |
625 | if (iflag) |
626 | inf->result = xstrdup("text/plain"); |
627 | else |
628 | xasprintf(&inf->result, "%s text", type); |
629 | return (1); |
630 | } |
631 | |
632 | static int |
633 | try_magic(struct input_file *inf) |
634 | { |
635 | const char *s; |
636 | int flags; |
637 | |
638 | flags = 0; |
639 | if (iflag) |
640 | flags |= MAGIC_TEST_MIME0x2; |
641 | |
642 | s = magic_test(inf->m, inf->base, inf->size, flags); |
643 | if (s != NULL((void *)0)) { |
644 | inf->result = xstrdup(s); |
645 | return (1); |
646 | } |
647 | return (0); |
648 | } |
649 | |
650 | static int |
651 | try_unknown(struct input_file *inf) |
652 | { |
653 | if (iflag) |
654 | xasprintf(&inf->result, "application/octet-stream"); |
655 | else |
656 | xasprintf(&inf->result, "data"); |
657 | return (1); |
658 | } |
659 | |
660 | static void |
661 | test_file(struct input_file *inf, size_t width) |
662 | { |
663 | char *label; |
664 | int stop; |
665 | |
666 | stop = 0; |
667 | if (!stop) |
668 | stop = try_stat(inf); |
669 | if (!stop) |
670 | stop = try_access(inf); |
671 | if (!stop) |
672 | stop = load_file(inf); |
673 | if (!stop) |
674 | stop = try_empty(inf); |
675 | if (!stop) |
676 | stop = try_magic(inf); |
677 | if (!stop) |
678 | stop = try_text(inf); |
679 | if (!stop) |
680 | stop = try_unknown(inf); |
Value stored to 'stop' is never read | |
681 | |
682 | if (bflag) |
683 | printf("%s\n", inf->result); |
684 | else { |
685 | if (strcmp(inf->path, "-") == 0) |
686 | xasprintf(&label, "/dev/stdin:"); |
687 | else |
688 | xasprintf(&label, "%s:", inf->path); |
689 | printf("%-*s %s\n", (int)width, label, inf->result); |
690 | free(label); |
691 | } |
692 | free(inf->result); |
693 | |
694 | if (inf->mapped && inf->base != NULL((void *)0)) |
695 | munmap(inf->base, inf->size); |
696 | } |