"Fossies" - the Fresh Open Source Software Archive

Member "file-5.35/src/file.c" (1 Oct 2018, 15643 Bytes) of package /linux/misc/file-5.35.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "file.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.34_vs_5.35.

    1 /*
    2  * Copyright (c) Ian F. Darwin 1986-1995.
    3  * Software written by Ian F. Darwin and others;
    4  * maintained 1995-present by Christos Zoulas and others.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice immediately at the beginning of the file, without modification,
   11  *    this list of conditions, and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 /*
   29  * file - find type of a file or files - main program.
   30  */
   31 
   32 #include "file.h"
   33 
   34 #ifndef lint
   35 FILE_RCSID("@(#)$File: file.c,v 1.178 2018/10/01 18:50:31 christos Exp $")
   36 #endif  /* lint */
   37 
   38 #include "magic.h"
   39 
   40 #include <stdlib.h>
   41 #include <unistd.h>
   42 #include <string.h>
   43 #ifdef RESTORE_TIME
   44 # if (__COHERENT__ >= 0x420)
   45 #  include <sys/utime.h>
   46 # else
   47 #  ifdef USE_UTIMES
   48 #   include <sys/time.h>
   49 #  else
   50 #   include <utime.h>
   51 #  endif
   52 # endif
   53 #endif
   54 #ifdef HAVE_UNISTD_H
   55 #include <unistd.h> /* for read() */
   56 #endif
   57 #ifdef HAVE_WCHAR_H
   58 #include <wchar.h>
   59 #endif
   60 
   61 #if defined(HAVE_GETOPT_H) && defined(HAVE_STRUCT_OPTION)
   62 # include <getopt.h>
   63 # ifndef HAVE_GETOPT_LONG
   64 int getopt_long(int, char * const *, const char *,
   65     const struct option *, int *);
   66 # endif
   67 # else
   68 #  include "mygetopt.h"
   69 #endif
   70 
   71 #ifdef S_IFLNK
   72 # define IFLNK_h "h"
   73 # define IFLNK_L "L"
   74 #else
   75 # define IFLNK_h ""
   76 # define IFLNK_L ""
   77 #endif
   78 
   79 #ifdef HAVE_LIBSECCOMP
   80 # define SECCOMP_S "S"
   81 #else
   82 # define SECCOMP_S ""
   83 #endif
   84 
   85 #define FILE_FLAGS  "bcCdE" IFLNK_h "ik" IFLNK_L "lNnprs" SECCOMP_S "vzZ0"
   86 #define OPTSTRING   "bcCde:Ef:F:hiklLm:nNpP:rsSvzZ0"
   87 
   88 # define USAGE  \
   89     "Usage: %s [-" FILE_FLAGS "] [--apple] [--extension] [--mime-encoding]\n" \
   90     "            [--mime-type] [-e <testname>] [-F <separator>] " \
   91     " [-f <namefile>]\n" \
   92     "            [-m <magicfiles>] [-P <parameter=value>] <file> ...\n" \
   93     "       %s -C [-m <magicfiles>]\n" \
   94     "       %s [--help]\n"
   95 
   96 private int         /* Global command-line options      */
   97     bflag = 0,  /* brief output format          */
   98     nopad = 0,  /* Don't pad output         */
   99     nobuffer = 0,   /* Do not buffer stdout         */
  100     nulsep = 0; /* Append '\0' to the separator     */
  101 
  102 private const char *separator = ":";    /* Default field separator  */
  103 private const struct option long_options[] = {
  104 #define OPT_HELP        1
  105 #define OPT_APPLE       2
  106 #define OPT_EXTENSIONS      3
  107 #define OPT_MIME_TYPE       4
  108 #define OPT_MIME_ENCODING   5
  109 #define OPT(shortname, longname, opt, def, doc)      \
  110     {longname, opt, NULL, shortname},
  111 #define OPT_LONGONLY(longname, opt, def, doc, id)        \
  112     {longname, opt, NULL, id},
  113 #include "file_opts.h"
  114 #undef OPT
  115 #undef OPT_LONGONLY
  116     {0, 0, NULL, 0}
  117     };
  118 
  119 private const struct {
  120     const char *name;
  121     int value;
  122 } nv[] = {
  123     { "apptype",    MAGIC_NO_CHECK_APPTYPE },
  124     { "ascii",  MAGIC_NO_CHECK_ASCII },
  125     { "cdf",    MAGIC_NO_CHECK_CDF },
  126     { "compress",   MAGIC_NO_CHECK_COMPRESS },
  127     { "elf",    MAGIC_NO_CHECK_ELF },
  128     { "encoding",   MAGIC_NO_CHECK_ENCODING },
  129     { "soft",   MAGIC_NO_CHECK_SOFT },
  130     { "tar",    MAGIC_NO_CHECK_TAR },
  131     { "json",   MAGIC_NO_CHECK_JSON },
  132     { "text",   MAGIC_NO_CHECK_TEXT },  /* synonym for ascii */
  133     { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */
  134 };
  135 
  136 private struct {
  137     const char *name;
  138     int tag;
  139     size_t value;
  140     int set;
  141 } pm[] = {
  142     { "indir",  MAGIC_PARAM_INDIR_MAX, 0, 0 },
  143     { "name",   MAGIC_PARAM_NAME_MAX, 0, 0 },
  144     { "elf_phnum",  MAGIC_PARAM_ELF_PHNUM_MAX, 0, 0 },
  145     { "elf_shnum",  MAGIC_PARAM_ELF_SHNUM_MAX, 0, 0 },
  146     { "elf_notes",  MAGIC_PARAM_ELF_NOTES_MAX, 0, 0 },
  147     { "regex",  MAGIC_PARAM_REGEX_MAX, 0, 0 },
  148     { "bytes",  MAGIC_PARAM_BYTES_MAX, 0, 0 },
  149 };
  150 
  151 private int posixly;
  152 
  153 #ifdef __dead
  154 __dead
  155 #endif
  156 private void usage(void);
  157 private void docprint(const char *, int);
  158 #ifdef __dead
  159 __dead
  160 #endif
  161 private void help(void);
  162 
  163 private int unwrap(struct magic_set *, const char *);
  164 private int process(struct magic_set *ms, const char *, int);
  165 private struct magic_set *load(const char *, int);
  166 private void setparam(const char *);
  167 private void applyparam(magic_t);
  168 
  169 
  170 /*
  171  * main - parse arguments and handle options
  172  */
  173 int
  174 main(int argc, char *argv[])
  175 {
  176     int c;
  177     size_t i;
  178     int action = 0, didsomefiles = 0, errflg = 0;
  179     int flags = 0, e = 0;
  180 #ifdef HAVE_LIBSECCOMP
  181     int sandbox = 1;
  182 #endif
  183     struct magic_set *magic = NULL;
  184     int longindex;
  185     const char *magicfile = NULL;       /* where the magic is   */
  186     char *progname;
  187 
  188     /* makes islower etc work for other langs */
  189 #ifdef HAVE_SETLOCALE
  190     (void)setlocale(LC_CTYPE, "");
  191 #endif
  192 
  193 #ifdef __EMX__
  194     /* sh-like wildcard expansion! Shouldn't hurt at least ... */
  195     _wildcard(&argc, &argv);
  196 #endif
  197 
  198     if ((progname = strrchr(argv[0], '/')) != NULL)
  199         progname++;
  200     else
  201         progname = argv[0];
  202 
  203     file_setprogname(progname);
  204 
  205 
  206 #ifdef S_IFLNK
  207     posixly = getenv("POSIXLY_CORRECT") != NULL;
  208     flags |=  posixly ? MAGIC_SYMLINK : 0;
  209 #endif
  210     while ((c = getopt_long(argc, argv, OPTSTRING, long_options,
  211         &longindex)) != -1)
  212         switch (c) {
  213         case OPT_HELP:
  214             help();
  215             break;
  216         case OPT_APPLE:
  217             flags |= MAGIC_APPLE;
  218             break;
  219         case OPT_EXTENSIONS:
  220             flags |= MAGIC_EXTENSION;
  221             break;
  222         case OPT_MIME_TYPE:
  223             flags |= MAGIC_MIME_TYPE;
  224             break;
  225         case OPT_MIME_ENCODING:
  226             flags |= MAGIC_MIME_ENCODING;
  227             break;
  228         case '0':
  229             nulsep++;
  230             break;
  231         case 'b':
  232             bflag++;
  233             break;
  234         case 'c':
  235             action = FILE_CHECK;
  236             break;
  237         case 'C':
  238             action = FILE_COMPILE;
  239             break;
  240         case 'd':
  241             flags |= MAGIC_DEBUG|MAGIC_CHECK;
  242             break;
  243         case 'E':
  244             flags |= MAGIC_ERROR;
  245             break;
  246         case 'e':
  247             for (i = 0; i < sizeof(nv) / sizeof(nv[0]); i++)
  248                 if (strcmp(nv[i].name, optarg) == 0)
  249                     break;
  250 
  251             if (i == sizeof(nv) / sizeof(nv[0]))
  252                 errflg++;
  253             else
  254                 flags |= nv[i].value;
  255             break;
  256 
  257         case 'f':
  258             if(action)
  259                 usage();
  260             if (magic == NULL)
  261                 if ((magic = load(magicfile, flags)) == NULL)
  262                     return 1;
  263             applyparam(magic);
  264             e |= unwrap(magic, optarg);
  265             ++didsomefiles;
  266             break;
  267         case 'F':
  268             separator = optarg;
  269             break;
  270         case 'i':
  271             flags |= MAGIC_MIME;
  272             break;
  273         case 'k':
  274             flags |= MAGIC_CONTINUE;
  275             break;
  276         case 'l':
  277             action = FILE_LIST;
  278             break;
  279         case 'm':
  280             magicfile = optarg;
  281             break;
  282         case 'n':
  283             ++nobuffer;
  284             break;
  285         case 'N':
  286             ++nopad;
  287             break;
  288 #if defined(HAVE_UTIME) || defined(HAVE_UTIMES)
  289         case 'p':
  290             flags |= MAGIC_PRESERVE_ATIME;
  291             break;
  292 #endif
  293         case 'P':
  294             setparam(optarg);
  295             break;
  296         case 'r':
  297             flags |= MAGIC_RAW;
  298             break;
  299         case 's':
  300             flags |= MAGIC_DEVICES;
  301             break;
  302 #ifdef HAVE_LIBSECCOMP
  303         case 'S':
  304             sandbox = 0;
  305             break;
  306 #endif
  307         case 'v':
  308             if (magicfile == NULL)
  309                 magicfile = magic_getpath(magicfile, action);
  310             (void)fprintf(stdout, "%s-%s\n", file_getprogname(),
  311                 VERSION);
  312             (void)fprintf(stdout, "magic file from %s\n",
  313                 magicfile);
  314             return 0;
  315         case 'z':
  316             flags |= MAGIC_COMPRESS;
  317             break;
  318 
  319         case 'Z':
  320             flags |= MAGIC_COMPRESS|MAGIC_COMPRESS_TRANSP;
  321             break;
  322 #ifdef S_IFLNK
  323         case 'L':
  324             flags |= MAGIC_SYMLINK;
  325             break;
  326         case 'h':
  327             flags &= ~MAGIC_SYMLINK;
  328             break;
  329 #endif
  330         case '?':
  331         default:
  332             errflg++;
  333             break;
  334         }
  335 
  336     if (errflg) {
  337         usage();
  338     }
  339     if (e)
  340         return e;
  341 
  342 #ifdef HAVE_LIBSECCOMP
  343 #if 0
  344     if (sandbox && enable_sandbox_basic() == -1)
  345 #else
  346     if (sandbox && enable_sandbox_full() == -1)
  347 #endif
  348         file_err(EXIT_FAILURE, "SECCOMP initialisation failed");
  349 #endif /* HAVE_LIBSECCOMP */
  350 
  351     if (MAGIC_VERSION != magic_version())
  352         file_warnx("Compiled magic version [%d] "
  353             "does not match with shared library magic version [%d]\n",
  354             MAGIC_VERSION, magic_version());
  355 
  356     switch(action) {
  357     case FILE_CHECK:
  358     case FILE_COMPILE:
  359     case FILE_LIST:
  360         /*
  361          * Don't try to check/compile ~/.magic unless we explicitly
  362          * ask for it.
  363          */
  364         magic = magic_open(flags|MAGIC_CHECK);
  365         if (magic == NULL) {
  366             file_warn("Can't create magic");
  367             return 1;
  368         }
  369 
  370 
  371         switch(action) {
  372         case FILE_CHECK:
  373             c = magic_check(magic, magicfile);
  374             break;
  375         case FILE_COMPILE:
  376             c = magic_compile(magic, magicfile);
  377             break;
  378         case FILE_LIST:
  379             c = magic_list(magic, magicfile);
  380             break;
  381         default:
  382             abort();
  383         }
  384         if (c == -1) {
  385             file_warnx("%s", magic_error(magic));
  386             e = 1;
  387             goto out;
  388         }
  389         goto out;
  390     default:
  391         if (magic == NULL)
  392             if ((magic = load(magicfile, flags)) == NULL)
  393                 return 1;
  394         applyparam(magic);
  395     }
  396 
  397     if (optind == argc) {
  398         if (!didsomefiles)
  399             usage();
  400     }
  401     else {
  402         size_t j, wid, nw;
  403         for (wid = 0, j = (size_t)optind; j < (size_t)argc; j++) {
  404             nw = file_mbswidth(argv[j]);
  405             if (nw > wid)
  406                 wid = nw;
  407         }
  408         /*
  409          * If bflag is only set twice, set it depending on
  410          * number of files [this is undocumented, and subject to change]
  411          */
  412         if (bflag == 2) {
  413             bflag = optind >= argc - 1;
  414         }
  415         for (; optind < argc; optind++)
  416             e |= process(magic, argv[optind], wid);
  417     }
  418 
  419 out:
  420     if (magic)
  421         magic_close(magic);
  422     return e;
  423 }
  424 
  425 private void
  426 applyparam(magic_t magic)
  427 {
  428     size_t i;
  429 
  430     for (i = 0; i < __arraycount(pm); i++) {
  431         if (!pm[i].set)
  432             continue;
  433         if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1)
  434             file_err(EXIT_FAILURE, "Can't set %s", pm[i].name);
  435     }
  436 }
  437 
  438 private void
  439 setparam(const char *p)
  440 {
  441     size_t i;
  442     char *s;
  443 
  444     if ((s = strchr(p, '=')) == NULL)
  445         goto badparm;
  446 
  447     for (i = 0; i < __arraycount(pm); i++) {
  448         if (strncmp(p, pm[i].name, s - p) != 0)
  449             continue;
  450         pm[i].value = atoi(s + 1);
  451         pm[i].set = 1;
  452         return;
  453     }
  454 badparm:
  455     file_errx(EXIT_FAILURE, "Unknown param %s", p);
  456 }
  457 
  458 private struct magic_set *
  459 /*ARGSUSED*/
  460 load(const char *magicfile, int flags)
  461 {
  462     struct magic_set *magic = magic_open(flags);
  463     const char *e;
  464 
  465     if (magic == NULL) {
  466         file_warn("Can't create magic");
  467         return NULL;
  468     }
  469     if (magic_load(magic, magicfile) == -1) {
  470         file_warn("%s", magic_error(magic));
  471         magic_close(magic);
  472         return NULL;
  473     }
  474     if ((e = magic_error(magic)) != NULL)
  475         file_warn("%s", e);
  476     return magic;
  477 }
  478 
  479 /*
  480  * unwrap -- read a file of filenames, do each one.
  481  */
  482 private int
  483 unwrap(struct magic_set *ms, const char *fn)
  484 {
  485     FILE *f;
  486     ssize_t len;
  487     char *line = NULL;
  488     size_t llen = 0;
  489     int wid = 0, cwid;
  490     int e = 0;
  491 
  492     if (strcmp("-", fn) == 0) {
  493         f = stdin;
  494         wid = 1;
  495     } else {
  496         if ((f = fopen(fn, "r")) == NULL) {
  497             file_warn("Cannot open `%s'", fn);
  498             return 1;
  499         }
  500 
  501         while ((len = getline(&line, &llen, f)) > 0) {
  502             if (line[len - 1] == '\n')
  503                 line[len - 1] = '\0';
  504             cwid = file_mbswidth(line);
  505             if (cwid > wid)
  506                 wid = cwid;
  507         }
  508 
  509         rewind(f);
  510     }
  511 
  512     while ((len = getline(&line, &llen, f)) > 0) {
  513         if (line[len - 1] == '\n')
  514             line[len - 1] = '\0';
  515         e |= process(ms, line, wid);
  516         if(nobuffer)
  517             (void)fflush(stdout);
  518     }
  519 
  520     free(line);
  521     (void)fclose(f);
  522     return e;
  523 }
  524 
  525 /*
  526  * Called for each input file on the command line (or in a list of files)
  527  */
  528 private int
  529 process(struct magic_set *ms, const char *inname, int wid)
  530 {
  531     const char *type, c = nulsep > 1 ? '\0' : '\n';
  532     int std_in = strcmp(inname, "-") == 0;
  533 
  534     if (wid > 0 && !bflag) {
  535         (void)printf("%s", std_in ? "/dev/stdin" : inname);
  536         if (nulsep)
  537             (void)putc('\0', stdout);
  538         if (nulsep < 2) {
  539             (void)printf("%s", separator);
  540             (void)printf("%*s ",
  541                 (int) (nopad ? 0 : (wid - file_mbswidth(inname))),
  542                 "");
  543         }
  544     }
  545 
  546     type = magic_file(ms, std_in ? NULL : inname);
  547 
  548     if (type == NULL) {
  549         (void)printf("ERROR: %s%c", magic_error(ms), c);
  550         return 1;
  551     } else {
  552         (void)printf("%s%c", type, c);
  553         return 0;
  554     }
  555 }
  556 
  557 protected size_t
  558 file_mbswidth(const char *s)
  559 {
  560 #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
  561     size_t bytesconsumed, old_n, n, width = 0;
  562     mbstate_t state;
  563     wchar_t nextchar;
  564     (void)memset(&state, 0, sizeof(mbstate_t));
  565     old_n = n = strlen(s);
  566 
  567     while (n > 0) {
  568         bytesconsumed = mbrtowc(&nextchar, s, n, &state);
  569         if (bytesconsumed == (size_t)(-1) ||
  570             bytesconsumed == (size_t)(-2)) {
  571             /* Something went wrong, return something reasonable */
  572             return old_n;
  573         }
  574         if (s[0] == '\n') {
  575             /*
  576              * do what strlen() would do, so that caller
  577              * is always right
  578              */
  579             width++;
  580         } else {
  581             int w = wcwidth(nextchar);
  582             if (w > 0)
  583                 width += w;
  584         }
  585 
  586         s += bytesconsumed, n -= bytesconsumed;
  587     }
  588     return width;
  589 #else
  590     return strlen(s);
  591 #endif
  592 }
  593 
  594 private void
  595 usage(void)
  596 {
  597     const char *pn = file_getprogname();
  598     (void)fprintf(stderr, USAGE, pn, pn, pn);
  599     exit(EXIT_FAILURE);
  600 }
  601 
  602 private void
  603 defprint(int def)
  604 {
  605     if (!def)
  606         return;
  607     if (((def & 1) && posixly) || ((def & 2) && !posixly))
  608         fprintf(stdout, " (default)");
  609     fputc('\n', stdout);
  610 }
  611 
  612 private void
  613 docprint(const char *opts, int def)
  614 {
  615     size_t i;
  616     int comma;
  617     char *sp, *p;
  618 
  619     p = strstr(opts, "%o");
  620     if (p == NULL) {
  621         fprintf(stdout, "%s", opts);
  622         defprint(def);
  623         return;
  624     }
  625 
  626     for (sp = p - 1; sp > opts && *sp == ' '; sp--)
  627         continue;
  628 
  629     fprintf(stdout, "%.*s", (int)(p - opts), opts);
  630 
  631     comma = 0;
  632     for (i = 0; i < __arraycount(nv); i++) {
  633         fprintf(stdout, "%s%s", comma++ ? ", " : "", nv[i].name);
  634         if (i && i % 5 == 0 && i != __arraycount(nv) - 1) {
  635             fprintf(stdout, ",\n%*s", (int)(p - sp - 1), "");
  636             comma = 0;
  637         }
  638     }
  639 
  640     fprintf(stdout, "%s", opts + (p - opts) + 2);
  641 }
  642 
  643 private void
  644 help(void)
  645 {
  646     (void)fputs(
  647 "Usage: file [OPTION...] [FILE...]\n"
  648 "Determine type of FILEs.\n"
  649 "\n", stdout);
  650 #define OPT(shortname, longname, opt, def, doc)      \
  651     fprintf(stdout, "  -%c, --" longname, shortname), \
  652     docprint(doc, def);
  653 #define OPT_LONGONLY(longname, opt, def, doc, id)        \
  654     fprintf(stdout, "      --" longname),   \
  655     docprint(doc, def);
  656 #include "file_opts.h"
  657 #undef OPT
  658 #undef OPT_LONGONLY
  659     fprintf(stdout, "\nReport bugs to https://bugs.astron.com/\n");
  660     exit(EXIT_SUCCESS);
  661 }
  662 
  663 private const char *file_progname;
  664 
  665 protected void
  666 file_setprogname(const char *progname)
  667 {
  668     file_progname = progname;
  669 }
  670 
  671 protected const char *
  672 file_getprogname(void)
  673 {
  674     return file_progname;
  675 }
  676 
  677 protected void
  678 file_err(int e, const char *fmt, ...)
  679 {
  680     va_list ap;
  681     int se = errno;
  682 
  683     va_start(ap, fmt);
  684     fprintf(stderr, "%s: ", file_progname);
  685     vfprintf(stderr, fmt, ap);
  686     va_end(ap);
  687     fprintf(stderr, " (%s)\n", strerror(se));
  688     exit(e);
  689 }
  690 
  691 protected void
  692 file_errx(int e, const char *fmt, ...)
  693 {
  694     va_list ap;
  695 
  696     va_start(ap, fmt);
  697     fprintf(stderr, "%s: ", file_progname);
  698     vfprintf(stderr, fmt, ap);
  699     va_end(ap);
  700     fprintf(stderr, "\n");
  701     exit(e);
  702 }
  703 
  704 protected void
  705 file_warn(const char *fmt, ...)
  706 {
  707     va_list ap;
  708     int se = errno;
  709 
  710     va_start(ap, fmt);
  711     fprintf(stderr, "%s: ", file_progname);
  712     vfprintf(stderr, fmt, ap);
  713     va_end(ap);
  714     fprintf(stderr, " (%s)\n", strerror(se));
  715     errno = se;
  716 }
  717 
  718 protected void
  719 file_warnx(const char *fmt, ...)
  720 {
  721     va_list ap;
  722     int se = errno;
  723 
  724     va_start(ap, fmt);
  725     fprintf(stderr, "%s: ", file_progname);
  726     vfprintf(stderr, fmt, ap);
  727     va_end(ap);
  728     fprintf(stderr, "\n");
  729     errno = se;
  730 }