root/ext/fileinfo/libmagic/is_tar.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. file_is_tar
  2. is_tar
  3. from_oct

   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.36 2009/02/03 20:27:51 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(int, const char *);        /* Decode octal number */
  55 
  56 static const char tartype[][32] = {
  57         "tar archive",
  58         "POSIX tar archive",
  59         "POSIX tar archive (GNU)",
  60 };
  61 
  62 protected int
  63 file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
  64 {
  65         /*
  66          * Do the tar test first, because if the first file in the tar
  67          * archive starts with a dot, we can confuse it with an nroff file.
  68          */
  69         int tar;
  70         int mime = ms->flags & MAGIC_MIME;
  71 
  72         if ((ms->flags & MAGIC_APPLE) != 0)
  73                 return 0;
  74 
  75         tar = is_tar(buf, nbytes);
  76         if (tar < 1 || tar > 3)
  77                 return 0;
  78 
  79         if (file_printf(ms, "%s", mime ? "application/x-tar" :
  80             tartype[tar - 1]) == -1)
  81                 return -1;
  82         return 1;
  83 }
  84 
  85 /*
  86  * Return
  87  *      0 if the checksum is bad (i.e., probably not a tar archive),
  88  *      1 for old UNIX tar file,
  89  *      2 for Unix Std (POSIX) tar file,
  90  *      3 for GNU tar file.
  91  */
  92 private int
  93 is_tar(const unsigned char *buf, size_t nbytes)
  94 {
  95         const union record *header = (const union record *)(const void *)buf;
  96         int     i;
  97         int     sum, recsum;
  98         const unsigned char     *p;
  99 
 100         if (nbytes < sizeof(union record))
 101                 return 0;
 102 
 103         recsum = from_oct(8,  header->header.chksum);
 104 
 105         sum = 0;
 106         p = header->charptr;
 107         for (i = sizeof(union record); --i >= 0;)
 108                 sum += *p++;
 109 
 110         /* Adjust checksum to count the "chksum" field as blanks. */
 111         for (i = sizeof(header->header.chksum); --i >= 0;)
 112                 sum -= header->header.chksum[i];
 113         sum += ' ' * sizeof header->header.chksum;
 114 
 115         if (sum != recsum)
 116                 return 0;       /* Not a tar archive */
 117 
 118         if (strcmp(header->header.magic, GNUTMAGIC) == 0)
 119                 return 3;               /* GNU Unix Standard tar archive */
 120         if (strcmp(header->header.magic, TMAGIC) == 0)
 121                 return 2;               /* Unix Standard tar archive */
 122 
 123         return 1;                       /* Old fashioned tar archive */
 124 }
 125 
 126 
 127 /*
 128  * Quick and dirty octal conversion.
 129  *
 130  * Result is -1 if the field is invalid (all blank, or non-octal).
 131  */
 132 private int
 133 from_oct(int digs, const char *where)
 134 {
 135         int     value;
 136 
 137         while (isspace((unsigned char)*where)) {        /* Skip spaces */
 138                 where++;
 139                 if (--digs <= 0)
 140                         return -1;              /* All blank field */
 141         }
 142         value = 0;
 143         while (digs > 0 && isodigit(*where)) {  /* Scan til non-octal */
 144                 value = (value << 3) | (*where++ - '0');
 145                 --digs;
 146         }
 147 
 148         if (digs > 0 && *where && !isspace((unsigned char)*where))
 149                 return -1;                      /* Ended on non-(space/NUL) */
 150 
 151         return value;
 152 }

/* [<][>][^][v][top][bottom][index][help] */