"Fossies" - the Fresh Open Source Software Archive

Member "file-5.35/src/is_tar.c" (15 Oct 2018, 4825 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 "is_tar.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  * is_tar() -- figure out whether file is a tar archive.
   30  *
   31  * Stolen (by the author!) from the public domain tar program:
   32  * Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
   33  *
   34  * @(#)list.c 1.18 9/23/86 Public Domain - gnu
   35  *
   36  * Comments changed and some code/comments reformatted
   37  * for file command by Ian Darwin.
   38  */
   39 
   40 #include "file.h"
   41 
   42 #ifndef lint
   43 FILE_RCSID("@(#)$File: is_tar.c,v 1.43 2018/10/15 16:29:16 christos Exp $")
   44 #endif
   45 
   46 #include "magic.h"
   47 #include <string.h>
   48 #include <ctype.h>
   49 #include "tar.h"
   50 
   51 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
   52 
   53 private int is_tar(const unsigned char *, size_t);
   54 private int from_oct(const char *, size_t); /* Decode octal number */
   55 
   56 static const char tartype[][32] = { /* should be equal to messages */
   57     "tar archive",          /* found in ../magic/Magdir/archive */
   58     "POSIX tar archive",
   59     "POSIX tar archive (GNU)",  /*  */
   60 };
   61 
   62 protected int
   63 file_is_tar(struct magic_set *ms, const struct buffer *b)
   64 {
   65     const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
   66     size_t nbytes = b->flen;
   67     /*
   68      * Do the tar test first, because if the first file in the tar
   69      * archive starts with a dot, we can confuse it with an nroff file.
   70      */
   71     int tar;
   72     int mime = ms->flags & MAGIC_MIME;
   73 
   74     if ((ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION)) != 0)
   75         return 0;
   76 
   77     tar = is_tar(buf, nbytes);
   78     if (tar < 1 || tar > 3)
   79         return 0;
   80 
   81     if (mime == MAGIC_MIME_ENCODING)
   82         return 1;
   83 
   84     if (file_printf(ms, "%s", mime ? "application/x-tar" :
   85         tartype[tar - 1]) == -1)
   86         return -1;
   87 
   88     return 1;
   89 }
   90 
   91 /*
   92  * Return
   93  *  0 if the checksum is bad (i.e., probably not a tar archive),
   94  *  1 for old UNIX tar file,
   95  *  2 for Unix Std (POSIX) tar file,
   96  *  3 for GNU tar file.
   97  */
   98 private int
   99 is_tar(const unsigned char *buf, size_t nbytes)
  100 {
  101     const union record *header = (const union record *)(const void *)buf;
  102     size_t i;
  103     int sum, recsum;
  104     const unsigned char *p, *ep;
  105 
  106     if (nbytes < sizeof(*header))
  107         return 0;
  108 
  109     recsum = from_oct(header->header.chksum, sizeof(header->header.chksum));
  110 
  111     sum = 0;
  112     p = header->charptr;
  113     ep = header->charptr + sizeof(*header);
  114     while (p < ep)
  115         sum += *p++;
  116 
  117     /* Adjust checksum to count the "chksum" field as blanks. */
  118     for (i = 0; i < sizeof(header->header.chksum); i++)
  119         sum -= header->header.chksum[i];
  120     sum += ' ' * sizeof(header->header.chksum);
  121 
  122     if (sum != recsum)
  123         return 0;   /* Not a tar archive */
  124 
  125     if (strncmp(header->header.magic, GNUTMAGIC,
  126         sizeof(header->header.magic)) == 0)
  127         return 3;       /* GNU Unix Standard tar archive */
  128 
  129     if (strncmp(header->header.magic, TMAGIC,
  130         sizeof(header->header.magic)) == 0)
  131         return 2;       /* Unix Standard tar archive */
  132 
  133     return 1;           /* Old fashioned tar archive */
  134 }
  135 
  136 
  137 /*
  138  * Quick and dirty octal conversion.
  139  *
  140  * Result is -1 if the field is invalid (all blank, or non-octal).
  141  */
  142 private int
  143 from_oct(const char *where, size_t digs)
  144 {
  145     int value;
  146 
  147     if (digs == 0)
  148         return -1;
  149 
  150     while (isspace((unsigned char)*where)) {    /* Skip spaces */
  151         where++;
  152         if (digs-- == 0)
  153             return -1;      /* All blank field */
  154     }
  155     value = 0;
  156     while (digs > 0 && isodigit(*where)) {  /* Scan til non-octal */
  157         value = (value << 3) | (*where++ - '0');
  158         digs--;
  159     }
  160 
  161     if (digs > 0 && *where && !isspace((unsigned char)*where))
  162         return -1;          /* Ended on non-(space/NUL) */
  163 
  164     return value;
  165 }