"Fossies" - the Fresh Open Source Software Archive

Member "file-5.35/src/magic.c" (1 Oct 2018, 14929 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 "magic.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) Christos Zoulas 2003.
    3  * All Rights Reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice immediately at the beginning of the file, without modification,
   10  *    this list of conditions, and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 #ifdef WIN32
   29 #include <windows.h>
   30 #include <shlwapi.h>
   31 #endif
   32 
   33 #include "file.h"
   34 
   35 #ifndef lint
   36 FILE_RCSID("@(#)$File: magic.c,v 1.106 2018/10/01 18:45:39 christos Exp $")
   37 #endif  /* lint */
   38 
   39 #include "magic.h"
   40 
   41 #include <stdlib.h>
   42 #include <unistd.h>
   43 #include <string.h>
   44 #ifdef QUICK
   45 #include <sys/mman.h>
   46 #endif
   47 #include <limits.h> /* for PIPE_BUF */
   48 
   49 #if defined(HAVE_UTIMES)
   50 # include <sys/time.h>
   51 #elif defined(HAVE_UTIME)
   52 # if defined(HAVE_SYS_UTIME_H)
   53 #  include <sys/utime.h>
   54 # elif defined(HAVE_UTIME_H)
   55 #  include <utime.h>
   56 # endif
   57 #endif
   58 
   59 #ifdef HAVE_UNISTD_H
   60 #include <unistd.h> /* for read() */
   61 #endif
   62 
   63 #ifndef PIPE_BUF
   64 /* Get the PIPE_BUF from pathconf */
   65 #ifdef _PC_PIPE_BUF
   66 #define PIPE_BUF pathconf(".", _PC_PIPE_BUF)
   67 #else
   68 #define PIPE_BUF 512
   69 #endif
   70 #endif
   71 
   72 private void close_and_restore(const struct magic_set *, const char *, int,
   73     const struct stat *);
   74 private int unreadable_info(struct magic_set *, mode_t, const char *);
   75 private const char* get_default_magic(void);
   76 #ifndef COMPILE_ONLY
   77 private const char *file_or_fd(struct magic_set *, const char *, int);
   78 #endif
   79 
   80 #ifndef STDIN_FILENO
   81 #define STDIN_FILENO    0
   82 #endif
   83 
   84 #ifdef WIN32
   85 /* HINSTANCE of this shared library. Needed for get_default_magic() */
   86 static HINSTANCE _w32_dll_instance = NULL;
   87 
   88 static void
   89 _w32_append_path(char **hmagicpath, const char *fmt, ...)
   90 {
   91     char *tmppath;
   92         char *newpath;
   93     va_list ap;
   94 
   95     va_start(ap, fmt);
   96     if (vasprintf(&tmppath, fmt, ap) < 0) {
   97         va_end(ap);
   98         return;
   99     }
  100     va_end(ap);
  101 
  102     if (access(tmppath, R_OK) == -1)
  103         goto out;
  104 
  105     if (*hmagicpath == NULL) {
  106         *hmagicpath = tmppath;
  107         return;
  108     }
  109 
  110     if (asprintf(&newpath, "%s%c%s", *hmagicpath, PATHSEP, tmppath) < 0)
  111         goto out;
  112 
  113     free(*hmagicpath);
  114     free(tmppath);
  115     *hmagicpath = newpath;
  116     return;
  117 out:
  118     free(tmppath);
  119 }
  120 
  121 static void
  122 _w32_get_magic_relative_to(char **hmagicpath, HINSTANCE module)
  123 {
  124     static const char *trypaths[] = {
  125         "%s/share/misc/magic.mgc",
  126         "%s/magic.mgc",
  127     };
  128     LPSTR dllpath;
  129     size_t sp;
  130 
  131     dllpath = calloc(MAX_PATH + 1, sizeof(*dllpath));
  132 
  133     if (!GetModuleFileNameA(module, dllpath, MAX_PATH))
  134         goto out;
  135 
  136     PathRemoveFileSpecA(dllpath);
  137 
  138     if (module) {
  139         char exepath[MAX_PATH];
  140         GetModuleFileNameA(NULL, exepath, MAX_PATH);
  141         PathRemoveFileSpecA(exepath);
  142         if (stricmp(exepath, dllpath) == 0)
  143             goto out;
  144     }
  145 
  146     sp = strlen(dllpath);
  147     if (sp > 3 && stricmp(&dllpath[sp - 3], "bin") == 0) {
  148         _w32_append_path(hmagicpath,
  149             "%s/../share/misc/magic.mgc", dllpath);
  150         goto out;
  151     }
  152 
  153     for (sp = 0; sp < __arraycount(trypaths); sp++)
  154         _w32_append_path(hmagicpath, trypaths[sp], dllpath);
  155 out:
  156     free(dllpath);
  157 }
  158 
  159 /* Placate GCC by offering a sacrificial previous prototype */
  160 BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID);
  161 
  162 BOOL WINAPI
  163 DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
  164     LPVOID lpvReserved __attribute__((__unused__)))
  165 {
  166     if (fdwReason == DLL_PROCESS_ATTACH)
  167         _w32_dll_instance = hinstDLL;
  168     return 1;
  169 }
  170 #endif
  171 
  172 private const char *
  173 get_default_magic(void)
  174 {
  175     static const char hmagic[] = "/.magic/magic.mgc";
  176     static char *default_magic;
  177     char *home, *hmagicpath;
  178 
  179 #ifndef WIN32
  180     struct stat st;
  181 
  182     if (default_magic) {
  183         free(default_magic);
  184         default_magic = NULL;
  185     }
  186     if ((home = getenv("HOME")) == NULL)
  187         return MAGIC;
  188 
  189     if (asprintf(&hmagicpath, "%s/.magic.mgc", home) < 0)
  190         return MAGIC;
  191     if (stat(hmagicpath, &st) == -1) {
  192         free(hmagicpath);
  193         if (asprintf(&hmagicpath, "%s/.magic", home) < 0)
  194             return MAGIC;
  195         if (stat(hmagicpath, &st) == -1)
  196             goto out;
  197         if (S_ISDIR(st.st_mode)) {
  198             free(hmagicpath);
  199             if (asprintf(&hmagicpath, "%s/%s", home, hmagic) < 0)
  200                 return MAGIC;
  201             if (access(hmagicpath, R_OK) == -1)
  202                 goto out;
  203         }
  204     }
  205 
  206     if (asprintf(&default_magic, "%s:%s", hmagicpath, MAGIC) < 0)
  207         goto out;
  208     free(hmagicpath);
  209     return default_magic;
  210 out:
  211     default_magic = NULL;
  212     free(hmagicpath);
  213     return MAGIC;
  214 #else
  215     hmagicpath = NULL;
  216 
  217     if (default_magic) {
  218         free(default_magic);
  219         default_magic = NULL;
  220     }
  221 
  222     /* First, try to get a magic file from user-application data */
  223     if ((home = getenv("LOCALAPPDATA")) != NULL)
  224         _w32_append_path(&hmagicpath, "%s%s", home, hmagic);
  225 
  226     /* Second, try to get a magic file from the user profile data */
  227     if ((home = getenv("USERPROFILE")) != NULL)
  228         _w32_append_path(&hmagicpath,
  229             "%s/Local Settings/Application Data%s", home, hmagic);
  230 
  231     /* Third, try to get a magic file from Common Files */
  232     if ((home = getenv("COMMONPROGRAMFILES")) != NULL)
  233         _w32_append_path(&hmagicpath, "%s%s", home, hmagic);
  234 
  235     /* Fourth, try to get magic file relative to exe location */
  236         _w32_get_magic_relative_to(&hmagicpath, NULL);
  237 
  238     /* Fifth, try to get magic file relative to dll location */
  239         _w32_get_magic_relative_to(&hmagicpath, _w32_dll_instance);
  240 
  241     /* Avoid MAGIC constant - it likely points to a file within MSys tree */
  242     default_magic = hmagicpath;
  243     return default_magic;
  244 #endif
  245 }
  246 
  247 public const char *
  248 magic_getpath(const char *magicfile, int action)
  249 {
  250     if (magicfile != NULL)
  251         return magicfile;
  252 
  253     magicfile = getenv("MAGIC");
  254     if (magicfile != NULL)
  255         return magicfile;
  256 
  257     return action == FILE_LOAD ? get_default_magic() : MAGIC;
  258 }
  259 
  260 public struct magic_set *
  261 magic_open(int flags)
  262 {
  263     return file_ms_alloc(flags);
  264 }
  265 
  266 private int
  267 unreadable_info(struct magic_set *ms, mode_t md, const char *file)
  268 {
  269     if (file) {
  270         /* We cannot open it, but we were able to stat it. */
  271         if (access(file, W_OK) == 0)
  272             if (file_printf(ms, "writable, ") == -1)
  273                 return -1;
  274         if (access(file, X_OK) == 0)
  275             if (file_printf(ms, "executable, ") == -1)
  276                 return -1;
  277     }
  278     if (S_ISREG(md))
  279         if (file_printf(ms, "regular file, ") == -1)
  280             return -1;
  281     if (file_printf(ms, "no read permission") == -1)
  282         return -1;
  283     return 0;
  284 }
  285 
  286 public void
  287 magic_close(struct magic_set *ms)
  288 {
  289     if (ms == NULL)
  290         return;
  291     file_ms_free(ms);
  292 }
  293 
  294 /*
  295  * load a magic file
  296  */
  297 public int
  298 magic_load(struct magic_set *ms, const char *magicfile)
  299 {
  300     if (ms == NULL)
  301         return -1;
  302     return file_apprentice(ms, magicfile, FILE_LOAD);
  303 }
  304 
  305 #ifndef COMPILE_ONLY
  306 /*
  307  * Install a set of compiled magic buffers.
  308  */
  309 public int
  310 magic_load_buffers(struct magic_set *ms, void **bufs, size_t *sizes,
  311     size_t nbufs)
  312 {
  313     if (ms == NULL)
  314         return -1;
  315     return buffer_apprentice(ms, (struct magic **)bufs, sizes, nbufs);
  316 }
  317 #endif
  318 
  319 public int
  320 magic_compile(struct magic_set *ms, const char *magicfile)
  321 {
  322     if (ms == NULL)
  323         return -1;
  324     return file_apprentice(ms, magicfile, FILE_COMPILE);
  325 }
  326 
  327 public int
  328 magic_check(struct magic_set *ms, const char *magicfile)
  329 {
  330     if (ms == NULL)
  331         return -1;
  332     return file_apprentice(ms, magicfile, FILE_CHECK);
  333 }
  334 
  335 public int
  336 magic_list(struct magic_set *ms, const char *magicfile)
  337 {
  338     if (ms == NULL)
  339         return -1;
  340     return file_apprentice(ms, magicfile, FILE_LIST);
  341 }
  342 
  343 private void
  344 close_and_restore(const struct magic_set *ms, const char *name, int fd,
  345     const struct stat *sb)
  346 {
  347     if (fd == STDIN_FILENO || name == NULL)
  348         return;
  349     (void) close(fd);
  350 
  351     if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
  352         /*
  353          * Try to restore access, modification times if read it.
  354          * This is really *bad* because it will modify the status
  355          * time of the file... And of course this will affect
  356          * backup programs
  357          */
  358 #ifdef HAVE_UTIMES
  359         struct timeval  utsbuf[2];
  360         (void)memset(utsbuf, 0, sizeof(utsbuf));
  361         utsbuf[0].tv_sec = sb->st_atime;
  362         utsbuf[1].tv_sec = sb->st_mtime;
  363 
  364         (void) utimes(name, utsbuf); /* don't care if loses */
  365 #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
  366         struct utimbuf  utbuf;
  367 
  368         (void)memset(&utbuf, 0, sizeof(utbuf));
  369         utbuf.actime = sb->st_atime;
  370         utbuf.modtime = sb->st_mtime;
  371         (void) utime(name, &utbuf); /* don't care if loses */
  372 #endif
  373     }
  374 }
  375 
  376 #ifndef COMPILE_ONLY
  377 
  378 /*
  379  * find type of descriptor
  380  */
  381 public const char *
  382 magic_descriptor(struct magic_set *ms, int fd)
  383 {
  384     if (ms == NULL)
  385         return NULL;
  386     return file_or_fd(ms, NULL, fd);
  387 }
  388 
  389 /*
  390  * find type of named file
  391  */
  392 public const char *
  393 magic_file(struct magic_set *ms, const char *inname)
  394 {
  395     if (ms == NULL)
  396         return NULL;
  397     return file_or_fd(ms, inname, STDIN_FILENO);
  398 }
  399 
  400 private const char *
  401 file_or_fd(struct magic_set *ms, const char *inname, int fd)
  402 {
  403     int rv = -1;
  404     unsigned char *buf;
  405     struct stat sb;
  406     ssize_t nbytes = 0; /* number of bytes read from a datafile */
  407     int ispipe = 0;
  408     off_t   pos = (off_t)-1;
  409 
  410     if (file_reset(ms, 1) == -1)
  411         goto out;
  412 
  413     /*
  414      * one extra for terminating '\0', and
  415      * some overlapping space for matches near EOF
  416      */
  417 #define SLOP (1 + sizeof(union VALUETYPE))
  418     if ((buf = CAST(unsigned char *, malloc(ms->bytes_max + SLOP))) == NULL)
  419         return NULL;
  420 
  421     switch (file_fsmagic(ms, inname, &sb)) {
  422     case -1:        /* error */
  423         goto done;
  424     case 0:         /* nothing found */
  425         break;
  426     default:        /* matched it and printed type */
  427         rv = 0;
  428         goto done;
  429     }
  430 
  431 #ifdef WIN32
  432     /* Place stdin in binary mode, so EOF (Ctrl+Z) doesn't stop early. */
  433     if (fd == STDIN_FILENO)
  434         _setmode(STDIN_FILENO, O_BINARY);
  435 #endif
  436     if (inname != NULL) {
  437         int flags = O_RDONLY|O_BINARY|O_NONBLOCK;
  438         errno = 0;
  439         if ((fd = open(inname, flags)) < 0) {
  440             int okstat = stat(inname, &sb) == 0;
  441             if (okstat && S_ISFIFO(sb.st_mode))
  442                 ispipe = 1;
  443 #ifdef WIN32
  444             /*
  445              * Can't stat, can't open.  It may have been opened in
  446              * fsmagic, so if the user doesn't have read permission,
  447              * allow it to say so; otherwise an error was probably
  448              * displayed in fsmagic.
  449              */
  450             if (!okstat && errno == EACCES) {
  451                 sb.st_mode = S_IFBLK;
  452                 okstat = 1;
  453             }
  454 #endif
  455             if (okstat &&
  456                 unreadable_info(ms, sb.st_mode, inname) == -1)
  457                 goto done;
  458             rv = 0;
  459             goto done;
  460         }
  461     }
  462 
  463     if (fd != -1) {
  464         if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
  465             ispipe = 1;
  466         if (inname == NULL)
  467             pos = lseek(fd, (off_t)0, SEEK_CUR);
  468     }
  469 
  470     /*
  471      * try looking at the first ms->bytes_max bytes
  472      */
  473     if (ispipe) {
  474         ssize_t r = 0;
  475 
  476         while ((r = sread(fd, (void *)&buf[nbytes],
  477             (size_t)(ms->bytes_max - nbytes), 1)) > 0) {
  478             nbytes += r;
  479             if (r < PIPE_BUF) break;
  480         }
  481 
  482         if (nbytes == 0 && inname) {
  483             /* We can not read it, but we were able to stat it. */
  484             if (unreadable_info(ms, sb.st_mode, inname) == -1)
  485                 goto done;
  486             rv = 0;
  487             goto done;
  488         }
  489 
  490     } else {
  491         /* Windows refuses to read from a big console buffer. */
  492         size_t howmany =
  493 #if defined(WIN32)
  494                 _isatty(fd) ? 8 * 1024 :
  495 #endif
  496                 ms->bytes_max;
  497         if ((nbytes = read(fd, (char *)buf, howmany)) == -1) {
  498             if (inname == NULL && fd != STDIN_FILENO)
  499                 file_error(ms, errno, "cannot read fd %d", fd);
  500             else
  501                 file_error(ms, errno, "cannot read `%s'",
  502                     inname == NULL ? "/dev/stdin" : inname);
  503             goto done;
  504         }
  505     }
  506 
  507     (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
  508     if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
  509         goto done;
  510     rv = 0;
  511 done:
  512     free(buf);
  513     if (fd != -1) {
  514         if (pos != (off_t)-1)
  515             (void)lseek(fd, pos, SEEK_SET);
  516         close_and_restore(ms, inname, fd, &sb);
  517     }
  518 out:
  519     return rv == 0 ? file_getbuffer(ms) : NULL;
  520 }
  521 
  522 
  523 public const char *
  524 magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
  525 {
  526     if (ms == NULL)
  527         return NULL;
  528     if (file_reset(ms, 1) == -1)
  529         return NULL;
  530     /*
  531      * The main work is done here!
  532      * We have the file name and/or the data buffer to be identified.
  533      */
  534     if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
  535         return NULL;
  536     }
  537     return file_getbuffer(ms);
  538 }
  539 #endif
  540 
  541 public const char *
  542 magic_error(struct magic_set *ms)
  543 {
  544     if (ms == NULL)
  545         return "Magic database is not open";
  546     return (ms->event_flags & EVENT_HAD_ERR) ? ms->o.buf : NULL;
  547 }
  548 
  549 public int
  550 magic_errno(struct magic_set *ms)
  551 {
  552     if (ms == NULL)
  553         return EINVAL;
  554     return (ms->event_flags & EVENT_HAD_ERR) ? ms->error : 0;
  555 }
  556 
  557 public int
  558 magic_getflags(struct magic_set *ms)
  559 {
  560     if (ms == NULL)
  561         return -1;
  562 
  563     return ms->flags;
  564 }
  565 
  566 public int
  567 magic_setflags(struct magic_set *ms, int flags)
  568 {
  569     if (ms == NULL)
  570         return -1;
  571 #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
  572     if (flags & MAGIC_PRESERVE_ATIME)
  573         return -1;
  574 #endif
  575     ms->flags = flags;
  576     return 0;
  577 }
  578 
  579 public int
  580 magic_version(void)
  581 {
  582     return MAGIC_VERSION;
  583 }
  584 
  585 public int
  586 magic_setparam(struct magic_set *ms, int param, const void *val)
  587 {
  588     if (ms == NULL)
  589         return -1;
  590     switch (param) {
  591     case MAGIC_PARAM_INDIR_MAX:
  592         ms->indir_max = (uint16_t)*(const size_t *)val;
  593         return 0;
  594     case MAGIC_PARAM_NAME_MAX:
  595         ms->name_max = (uint16_t)*(const size_t *)val;
  596         return 0;
  597     case MAGIC_PARAM_ELF_PHNUM_MAX:
  598         ms->elf_phnum_max = (uint16_t)*(const size_t *)val;
  599         return 0;
  600     case MAGIC_PARAM_ELF_SHNUM_MAX:
  601         ms->elf_shnum_max = (uint16_t)*(const size_t *)val;
  602         return 0;
  603     case MAGIC_PARAM_ELF_NOTES_MAX:
  604         ms->elf_notes_max = (uint16_t)*(const size_t *)val;
  605         return 0;
  606     case MAGIC_PARAM_REGEX_MAX:
  607         ms->elf_notes_max = (uint16_t)*(const size_t *)val;
  608         return 0;
  609     case MAGIC_PARAM_BYTES_MAX:
  610         ms->bytes_max = *(const size_t *)val;
  611         return 0;
  612     default:
  613         errno = EINVAL;
  614         return -1;
  615     }
  616 }
  617 
  618 public int
  619 magic_getparam(struct magic_set *ms, int param, void *val)
  620 {
  621     if (ms == NULL)
  622         return -1;
  623     switch (param) {
  624     case MAGIC_PARAM_INDIR_MAX:
  625         *(size_t *)val = ms->indir_max;
  626         return 0;
  627     case MAGIC_PARAM_NAME_MAX:
  628         *(size_t *)val = ms->name_max;
  629         return 0;
  630     case MAGIC_PARAM_ELF_PHNUM_MAX:
  631         *(size_t *)val = ms->elf_phnum_max;
  632         return 0;
  633     case MAGIC_PARAM_ELF_SHNUM_MAX:
  634         *(size_t *)val = ms->elf_shnum_max;
  635         return 0;
  636     case MAGIC_PARAM_ELF_NOTES_MAX:
  637         *(size_t *)val = ms->elf_notes_max;
  638         return 0;
  639     case MAGIC_PARAM_REGEX_MAX:
  640         *(size_t *)val = ms->regex_max;
  641         return 0;
  642     case MAGIC_PARAM_BYTES_MAX:
  643         *(size_t *)val = ms->bytes_max;
  644         return 0;
  645     default:
  646         errno = EINVAL;
  647         return -1;
  648     }
  649 }