Annotation of src/usr.bin/file/file.c, Revision 1.59
1.59 ! nicm 1: /* $OpenBSD: file.c,v 1.58 2016/05/01 20:34:26 nicm Exp $ */
1.27 nicm 2:
1.14 tedu 3: /*
1.27 nicm 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.
1.14 tedu 17: */
1.11 ian 18:
1.20 deraadt 19: #include <sys/types.h>
1.27 nicm 20: #include <sys/ioctl.h>
21: #include <sys/mman.h>
1.58 nicm 22: #include <sys/queue.h>
1.35 nicm 23: #include <sys/socket.h>
1.58 nicm 24: #include <sys/stat.h>
1.35 nicm 25: #include <sys/uio.h>
26: #include <sys/wait.h>
1.20 deraadt 27:
1.58 nicm 28: #include <err.h>
1.27 nicm 29: #include <errno.h>
1.58 nicm 30: #include <fcntl.h>
31: #include <getopt.h>
1.35 nicm 32: #include <imsg.h>
1.27 nicm 33: #include <libgen.h>
1.58 nicm 34: #include <limits.h>
1.27 nicm 35: #include <pwd.h>
1.1 deraadt 36: #include <stdlib.h>
1.58 nicm 37: #include <stdlib.h>
38: #include <string.h>
1.44 nicm 39: #include <time.h>
1.14 tedu 40: #include <unistd.h>
41:
1.27 nicm 42: #include "file.h"
43: #include "magic.h"
44: #include "xmalloc.h"
1.1 deraadt 45:
1.59 ! nicm 46: struct input_msg {
1.35 nicm 47: int idx;
48:
49: struct stat sb;
50: int error;
51:
52: char link_path[PATH_MAX];
53: int link_error;
54: int link_target;
55: };
56:
1.59 ! nicm 57: struct input_ack {
1.35 nicm 58: int idx;
59: };
60:
1.59 ! nicm 61: struct input_file {
1.35 nicm 62: struct magic *m;
63: struct input_msg *msg;
1.1 deraadt 64:
1.35 nicm 65: const char *path;
66: int fd;
1.14 tedu 67:
1.35 nicm 68: void *base;
69: size_t size;
70: int mapped;
71: char *result;
1.27 nicm 72: };
1.1 deraadt 73:
1.27 nicm 74: extern char *__progname;
1.1 deraadt 75:
1.27 nicm 76: __dead void usage(void);
1.1 deraadt 77:
1.55 nicm 78: static int prepare_message(struct input_msg *, int, const char *);
1.35 nicm 79: static void send_message(struct imsgbuf *, void *, size_t, int);
80: static int read_message(struct imsgbuf *, struct imsg *, pid_t);
81:
82: static void read_link(struct input_msg *, const char *);
83:
84: static __dead void child(int, pid_t, int, char **);
85:
86: static void test_file(struct input_file *, size_t);
1.27 nicm 87:
88: static int try_stat(struct input_file *);
89: static int try_empty(struct input_file *);
90: static int try_access(struct input_file *);
91: static int try_text(struct input_file *);
92: static int try_magic(struct input_file *);
93: static int try_unknown(struct input_file *);
94:
95: static int bflag;
96: static int cflag;
97: static int iflag;
98: static int Lflag;
99: static int sflag;
100: static int Wflag;
101:
1.35 nicm 102: static char *magicpath;
103: static FILE *magicfp;
104:
1.27 nicm 105: static struct option longopts[] = {
1.57 jca 106: { "brief", no_argument, NULL, 'b' },
107: { "dereference", no_argument, NULL, 'L' },
108: { "mime", no_argument, NULL, 'i' },
109: { "mime-type", no_argument, NULL, 'i' },
110: { NULL, 0, NULL, 0 }
1.27 nicm 111: };
1.14 tedu 112:
1.27 nicm 113: __dead void
114: usage(void)
115: {
1.39 jmc 116: fprintf(stderr, "usage: %s [-bchiLsW] file ...\n", __progname);
1.27 nicm 117: exit(1);
118: }
1.14 tedu 119:
1.1 deraadt 120: int
1.27 nicm 121: main(int argc, char **argv)
1.1 deraadt 122: {
1.55 nicm 123: int opt, pair[2], fd, idx;
1.35 nicm 124: char *home;
1.27 nicm 125: struct passwd *pw;
1.35 nicm 126: struct imsgbuf ibuf;
127: struct imsg imsg;
128: struct input_msg msg;
129: struct input_ack *ack;
130: pid_t pid, parent;
1.44 nicm 131:
132: tzset();
1.27 nicm 133:
134: for (;;) {
135: opt = getopt_long(argc, argv, "bchiLsW", longopts, NULL);
136: if (opt == -1)
1.18 chl 137: break;
1.27 nicm 138: switch (opt) {
1.9 millert 139: case 'b':
1.27 nicm 140: bflag = 1;
1.9 millert 141: break;
1.1 deraadt 142: case 'c':
1.27 nicm 143: cflag = 1;
1.14 tedu 144: break;
1.27 nicm 145: case 'h':
146: Lflag = 0;
1.14 tedu 147: break;
1.19 chl 148: case 'i':
1.27 nicm 149: iflag = 1;
1.19 chl 150: break;
1.27 nicm 151: case 'L':
152: Lflag = 1;
1.14 tedu 153: break;
154: case 's':
1.27 nicm 155: sflag = 1;
1.14 tedu 156: break;
1.27 nicm 157: case 'W':
158: Wflag = 1;
1.18 chl 159: break;
1.1 deraadt 160: default:
1.27 nicm 161: usage();
1.1 deraadt 162: }
1.27 nicm 163: }
164: argc -= optind;
165: argv += optind;
166: if (cflag) {
167: if (argc != 0)
168: usage();
169: } else if (argc == 0)
170: usage();
1.1 deraadt 171:
1.35 nicm 172: magicfp = NULL;
1.32 nicm 173: if (geteuid() != 0 && !issetugid()) {
174: home = getenv("HOME");
175: if (home == NULL || *home == '\0') {
176: pw = getpwuid(getuid());
177: if (pw != NULL)
178: home = pw->pw_dir;
179: else
180: home = NULL;
181: }
182: if (home != NULL) {
1.35 nicm 183: xasprintf(&magicpath, "%s/.magic", home);
184: magicfp = fopen(magicpath, "r");
185: if (magicfp == NULL)
186: free(magicpath);
1.32 nicm 187: }
1.27 nicm 188: }
1.35 nicm 189: if (magicfp == NULL) {
190: magicpath = xstrdup("/etc/magic");
191: magicfp = fopen(magicpath, "r");
192: }
193: if (magicfp == NULL)
194: err(1, "%s", magicpath);
195:
196: parent = getpid();
197: if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
198: err(1, "socketpair");
1.49 nicm 199: switch (pid = fork()) {
200: case -1:
201: err(1, "fork");
202: case 0:
1.35 nicm 203: close(pair[0]);
204: child(pair[1], parent, argc, argv);
205: }
206: close(pair[1]);
207:
208: fclose(magicfp);
209: magicfp = NULL;
210:
211: if (cflag)
212: goto wait_for_child;
213:
214: imsg_init(&ibuf, pair[0]);
215: for (idx = 0; idx < argc; idx++) {
1.55 nicm 216: fd = prepare_message(&msg, idx, argv[idx]);
1.35 nicm 217: send_message(&ibuf, &msg, sizeof msg, fd);
1.1 deraadt 218:
1.35 nicm 219: if (read_message(&ibuf, &imsg, pid) == 0)
220: break;
221: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof *ack)
222: errx(1, "message too small");
223: ack = imsg.data;
224: if (ack->idx != idx)
225: errx(1, "index not expected");
226: imsg_free(&imsg);
1.1 deraadt 227: }
228:
1.35 nicm 229: wait_for_child:
230: close(pair[0]);
231: while (wait(NULL) == -1 && errno != ECHILD) {
232: if (errno != EINTR)
233: err(1, "wait");
1.30 nicm 234: }
1.35 nicm 235: _exit(0); /* let the child flush */
1.55 nicm 236: }
237:
238: static int
239: prepare_message(struct input_msg *msg, int idx, const char *path)
240: {
241: int fd, mode, error;
242:
243: memset(msg, 0, sizeof *msg);
244: msg->idx = idx;
245:
246: if (strcmp(path, "-") == 0) {
247: if (fstat(STDIN_FILENO, &msg->sb) == -1) {
248: msg->error = errno;
249: return (-1);
250: }
251: return (STDIN_FILENO);
252: }
253:
254: if (Lflag)
255: error = stat(path, &msg->sb);
256: else
257: error = lstat(path, &msg->sb);
258: if (error == -1) {
259: msg->error = errno;
260: return (-1);
261: }
262:
263: /*
264: * pledge(2) doesn't let us pass directory file descriptors around -
265: * but in fact we don't need them, so just don't open directories or
266: * symlinks (which could be to directories).
267: */
268: mode = msg->sb.st_mode;
269: if (!S_ISDIR(mode) && !S_ISLNK(mode)) {
270: fd = open(path, O_RDONLY|O_NONBLOCK);
271: if (fd == -1 && (errno == ENFILE || errno == EMFILE))
272: err(1, "open");
273: } else
274: fd = -1;
275: if (S_ISLNK(mode))
276: read_link(msg, path);
277: return (fd);
278:
1.1 deraadt 279: }
280:
1.27 nicm 281: static void
1.35 nicm 282: send_message(struct imsgbuf *ibuf, void *msg, size_t msglen, int fd)
283: {
284: if (imsg_compose(ibuf, -1, -1, 0, fd, msg, msglen) != 1)
285: err(1, "imsg_compose");
286: if (imsg_flush(ibuf) != 0)
287: err(1, "imsg_flush");
288: }
289:
290: static int
291: read_message(struct imsgbuf *ibuf, struct imsg *imsg, pid_t from)
1.27 nicm 292: {
1.35 nicm 293: int n;
1.1 deraadt 294:
1.56 claudio 295: while ((n = imsg_read(ibuf)) == -1 && errno == EAGAIN)
296: /* nothing */ ;
297: if (n == -1)
1.35 nicm 298: err(1, "imsg_read");
299: if (n == 0)
300: return (0);
1.27 nicm 301:
1.35 nicm 302: if ((n = imsg_get(ibuf, imsg)) == -1)
303: err(1, "imsg_get");
304: if (n == 0)
305: return (0);
1.31 nicm 306:
1.35 nicm 307: if ((pid_t)imsg->hdr.pid != from)
308: errx(1, "PIDs don't match");
1.27 nicm 309:
1.35 nicm 310: return (n);
1.27 nicm 311:
312: }
313:
314: static void
1.35 nicm 315: read_link(struct input_msg *msg, const char *path)
1.14 tedu 316: {
1.27 nicm 317: struct stat sb;
1.35 nicm 318: char lpath[PATH_MAX];
1.27 nicm 319: char *copy, *root;
320: int used;
321: ssize_t size;
322:
1.47 tobias 323: size = readlink(path, lpath, sizeof lpath - 1);
1.27 nicm 324: if (size == -1) {
1.35 nicm 325: msg->link_error = errno;
1.14 tedu 326: return;
1.27 nicm 327: }
1.35 nicm 328: lpath[size] = '\0';
1.27 nicm 329:
1.35 nicm 330: if (*lpath == '/')
331: strlcpy(msg->link_path, lpath, sizeof msg->link_path);
1.27 nicm 332: else {
1.35 nicm 333: copy = xstrdup(path);
1.27 nicm 334:
335: root = dirname(copy);
336: if (*root == '\0' || strcmp(root, ".") == 0 ||
337: strcmp (root, "/") == 0)
1.35 nicm 338: strlcpy(msg->link_path, lpath, sizeof msg->link_path);
1.27 nicm 339: else {
1.35 nicm 340: used = snprintf(msg->link_path, sizeof msg->link_path,
341: "%s/%s", root, lpath);
342: if (used < 0 || (size_t)used >= sizeof msg->link_path) {
343: msg->link_error = ENAMETOOLONG;
1.37 lteo 344: free(copy);
1.27 nicm 345: return;
346: }
347: }
348:
349: free(copy);
350: }
351:
1.54 nicm 352: if (!Lflag && stat(path, &sb) == -1)
353: msg->link_target = errno;
1.14 tedu 354: }
355:
1.35 nicm 356: static __dead void
357: child(int fd, pid_t parent, int argc, char **argv)
358: {
1.49 nicm 359: struct passwd *pw;
1.35 nicm 360: struct magic *m;
361: struct imsgbuf ibuf;
362: struct imsg imsg;
363: struct input_msg *msg;
364: struct input_ack ack;
365: struct input_file inf;
366: int i, idx;
367: size_t len, width = 0;
368:
1.53 deraadt 369: if (pledge("stdio getpw recvfd id", NULL) == -1)
1.52 deraadt 370: err(1, "pledge");
1.49 nicm 371:
372: if (geteuid() == 0) {
373: pw = getpwnam(FILE_USER);
374: if (pw == NULL)
375: errx(1, "unknown user %s", FILE_USER);
376: if (setgroups(1, &pw->pw_gid) != 0)
377: err(1, "setgroups");
378: if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) != 0)
379: err(1, "setresgid");
380: if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) != 0)
381: err(1, "setresuid");
382: }
383:
1.52 deraadt 384: if (pledge("stdio recvfd", NULL) == -1)
385: err(1, "pledge");
1.49 nicm 386:
1.35 nicm 387: m = magic_load(magicfp, magicpath, cflag || Wflag);
388: if (cflag) {
389: magic_dump(m);
390: exit(0);
391: }
392:
393: for (i = 0; i < argc; i++) {
394: len = strlen(argv[i]) + 1;
395: if (len > width)
396: width = len;
397: }
398:
399: imsg_init(&ibuf, fd);
400: for (;;) {
401: if (read_message(&ibuf, &imsg, parent) == 0)
402: break;
403: if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof *msg)
404: errx(1, "message too small");
405: msg = imsg.data;
406:
407: idx = msg->idx;
408: if (idx < 0 || idx >= argc)
409: errx(1, "index out of range");
410:
411: memset(&inf, 0, sizeof inf);
412: inf.m = m;
413: inf.msg = msg;
414:
415: inf.path = argv[idx];
416: inf.fd = imsg.fd;
417:
418: test_file(&inf, width);
419:
420: if (imsg.fd != -1)
421: close(imsg.fd);
422: imsg_free(&imsg);
423:
424: ack.idx = idx;
425: send_message(&ibuf, &ack, sizeof ack, -1);
426: }
427: exit(0);
428: }
429:
1.27 nicm 430: static void *
1.42 nicm 431: fill_buffer(int fd, size_t size, size_t *used)
1.1 deraadt 432: {
1.27 nicm 433: static void *buffer;
434: ssize_t got;
435: size_t left;
436: void *next;
437:
438: if (buffer == NULL)
439: buffer = xmalloc(FILE_READ_SIZE);
440:
441: next = buffer;
1.42 nicm 442: left = size;
1.27 nicm 443: while (left != 0) {
1.42 nicm 444: got = read(fd, next, left);
1.27 nicm 445: if (got == -1) {
446: if (errno == EINTR)
447: continue;
1.59 ! nicm 448: return (NULL);
1.5 millert 449: }
1.27 nicm 450: if (got == 0)
451: break;
1.30 nicm 452: next = (char *)next + got;
1.27 nicm 453: left -= got;
454: }
1.42 nicm 455: *used = size - left;
1.59 ! nicm 456: return (buffer);
1.27 nicm 457: }
458:
459: static int
460: load_file(struct input_file *inf)
461: {
1.42 nicm 462: size_t used;
463:
1.46 tobias 464: if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode))
1.43 nicm 465: return (0); /* empty file */
1.46 tobias 466: if (inf->msg->sb.st_size == 0 || inf->msg->sb.st_size > FILE_READ_SIZE)
1.27 nicm 467: inf->size = FILE_READ_SIZE;
1.46 tobias 468: else
469: inf->size = inf->msg->sb.st_size;
1.43 nicm 470:
471: if (!S_ISREG(inf->msg->sb.st_mode))
472: goto try_read;
1.27 nicm 473:
474: inf->base = mmap(NULL, inf->size, PROT_READ, MAP_PRIVATE, inf->fd, 0);
1.43 nicm 475: if (inf->base == MAP_FAILED)
476: goto try_read;
477: inf->mapped = 1;
478: return (0);
479:
480: try_read:
481: inf->base = fill_buffer(inf->fd, inf->size, &used);
482: if (inf->base == NULL) {
483: xasprintf(&inf->result, "cannot read '%s' (%s)", inf->path,
484: strerror(errno));
485: return (1);
486: }
487: inf->size = used;
1.27 nicm 488: return (0);
489: }
1.5 millert 490:
1.27 nicm 491: static int
492: try_stat(struct input_file *inf)
493: {
1.35 nicm 494: if (inf->msg->error != 0) {
1.27 nicm 495: xasprintf(&inf->result, "cannot stat '%s' (%s)", inf->path,
1.35 nicm 496: strerror(inf->msg->error));
1.27 nicm 497: return (1);
498: }
1.45 nicm 499: if (sflag || strcmp(inf->path, "-") == 0) {
1.35 nicm 500: switch (inf->msg->sb.st_mode & S_IFMT) {
1.45 nicm 501: case S_IFIFO:
502: if (strcmp(inf->path, "-") != 0)
503: break;
1.27 nicm 504: case S_IFBLK:
505: case S_IFCHR:
506: case S_IFREG:
507: return (0);
1.5 millert 508: }
1.27 nicm 509: }
1.1 deraadt 510:
1.35 nicm 511: if (iflag && (inf->msg->sb.st_mode & S_IFMT) != S_IFREG) {
1.27 nicm 512: xasprintf(&inf->result, "application/x-not-regular-file");
513: return (1);
1.1 deraadt 514: }
515:
1.35 nicm 516: switch (inf->msg->sb.st_mode & S_IFMT) {
1.27 nicm 517: case S_IFDIR:
518: xasprintf(&inf->result, "directory");
519: return (1);
520: case S_IFLNK:
1.35 nicm 521: if (inf->msg->link_error != 0) {
1.27 nicm 522: xasprintf(&inf->result, "unreadable symlink '%s' (%s)",
1.35 nicm 523: inf->path, strerror(inf->msg->link_error));
1.27 nicm 524: return (1);
525: }
1.35 nicm 526: if (inf->msg->link_target == ELOOP)
1.27 nicm 527: xasprintf(&inf->result, "symbolic link in a loop");
1.35 nicm 528: else if (inf->msg->link_target != 0) {
1.27 nicm 529: xasprintf(&inf->result, "broken symbolic link to '%s'",
1.35 nicm 530: inf->msg->link_path);
1.27 nicm 531: } else {
532: xasprintf(&inf->result, "symbolic link to '%s'",
1.35 nicm 533: inf->msg->link_path);
1.27 nicm 534: }
535: return (1);
536: case S_IFSOCK:
537: xasprintf(&inf->result, "socket");
538: return (1);
539: case S_IFBLK:
540: xasprintf(&inf->result, "block special (%ld/%ld)",
1.35 nicm 541: (long)major(inf->msg->sb.st_rdev),
542: (long)minor(inf->msg->sb.st_rdev));
1.27 nicm 543: return (1);
544: case S_IFCHR:
545: xasprintf(&inf->result, "character special (%ld/%ld)",
1.35 nicm 546: (long)major(inf->msg->sb.st_rdev),
547: (long)minor(inf->msg->sb.st_rdev));
1.27 nicm 548: return (1);
549: case S_IFIFO:
550: xasprintf(&inf->result, "fifo (named pipe)");
551: return (1);
1.1 deraadt 552: }
1.27 nicm 553: return (0);
554: }
555:
556: static int
557: try_empty(struct input_file *inf)
558: {
559: if (inf->size != 0)
560: return (0);
561:
562: if (iflag)
563: xasprintf(&inf->result, "application/x-empty");
564: else
565: xasprintf(&inf->result, "empty");
566: return (1);
567: }
568:
569: static int
570: try_access(struct input_file *inf)
571: {
572: char tmp[256] = "";
573:
1.49 nicm 574: if (inf->msg->sb.st_size == 0 && S_ISREG(inf->msg->sb.st_mode))
575: return (0); /* empty file */
1.27 nicm 576: if (inf->fd != -1)
577: return (0);
1.1 deraadt 578:
1.35 nicm 579: if (inf->msg->sb.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))
1.27 nicm 580: strlcat(tmp, "writable, ", sizeof tmp);
1.35 nicm 581: if (inf->msg->sb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))
1.27 nicm 582: strlcat(tmp, "executable, ", sizeof tmp);
1.35 nicm 583: if (S_ISREG(inf->msg->sb.st_mode))
1.27 nicm 584: strlcat(tmp, "regular file, ", sizeof tmp);
585: strlcat(tmp, "no read permission", sizeof tmp);
586:
587: inf->result = xstrdup(tmp);
588: return (1);
1.1 deraadt 589: }
590:
1.27 nicm 591: static int
592: try_text(struct input_file *inf)
1.14 tedu 593: {
1.27 nicm 594: const char *type, *s;
595: int flags;
596:
597: flags = MAGIC_TEST_TEXT;
598: if (iflag)
599: flags |= MAGIC_TEST_MIME;
600:
601: type = text_get_type(inf->base, inf->size);
602: if (type == NULL)
603: return (0);
1.14 tedu 604:
1.27 nicm 605: s = magic_test(inf->m, inf->base, inf->size, flags);
606: if (s != NULL) {
607: inf->result = xstrdup(s);
608: return (1);
609: }
610:
611: s = text_try_words(inf->base, inf->size, flags);
612: if (s != NULL) {
613: if (iflag)
614: inf->result = xstrdup(s);
1.18 chl 615: else
1.27 nicm 616: xasprintf(&inf->result, "%s %s text", type, s);
617: return (1);
1.18 chl 618: }
1.14 tedu 619:
1.27 nicm 620: if (iflag)
621: inf->result = xstrdup("text/plain");
1.14 tedu 622: else
1.27 nicm 623: xasprintf(&inf->result, "%s text", type);
624: return (1);
1.14 tedu 625: }
626:
1.27 nicm 627: static int
628: try_magic(struct input_file *inf)
1.1 deraadt 629: {
1.27 nicm 630: const char *s;
631: int flags;
1.1 deraadt 632:
1.27 nicm 633: flags = 0;
634: if (iflag)
635: flags |= MAGIC_TEST_MIME;
636:
637: s = magic_test(inf->m, inf->base, inf->size, flags);
638: if (s != NULL) {
639: inf->result = xstrdup(s);
640: return (1);
1.1 deraadt 641: }
1.27 nicm 642: return (0);
1.14 tedu 643: }
1.1 deraadt 644:
1.27 nicm 645: static int
646: try_unknown(struct input_file *inf)
1.14 tedu 647: {
1.27 nicm 648: if (iflag)
649: xasprintf(&inf->result, "application/x-not-regular-file");
650: else
651: xasprintf(&inf->result, "data");
652: return (1);
1.1 deraadt 653: }
654:
1.27 nicm 655: static void
1.35 nicm 656: test_file(struct input_file *inf, size_t width)
1.1 deraadt 657: {
1.35 nicm 658: char *label;
659: int stop;
1.27 nicm 660:
661: stop = 0;
662: if (!stop)
663: stop = try_stat(inf);
664: if (!stop)
665: stop = try_access(inf);
666: if (!stop)
667: stop = load_file(inf);
668: if (!stop)
669: stop = try_empty(inf);
670: if (!stop)
671: stop = try_magic(inf);
672: if (!stop)
673: stop = try_text(inf);
674: if (!stop)
675: stop = try_unknown(inf);
676:
677: if (bflag)
678: printf("%s\n", inf->result);
1.35 nicm 679: else {
1.45 nicm 680: if (strcmp(inf->path, "-") == 0)
681: xasprintf(&label, "/dev/stdin:");
682: else
683: xasprintf(&label, "%s:", inf->path);
1.35 nicm 684: printf("%-*s %s\n", (int)width, label, inf->result);
685: free(label);
686: }
1.30 nicm 687: free(inf->result);
1.27 nicm 688:
689: if (inf->mapped && inf->base != NULL)
690: munmap(inf->base, inf->size);
1.1 deraadt 691: }