[BACK]Return to is_tar.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Annotation of src/usr.bin/file/is_tar.c, Revision 1.7

1.7     ! tedu        1: /*     $OpenBSD$ */
        !             2: /*
        !             3:  * Copyright (c) Ian F. Darwin 1986-1995.
        !             4:  * Software written by Ian F. Darwin and others;
        !             5:  * maintained 1995-present by Christos Zoulas and others.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice immediately at the beginning of the file, without modification,
        !            12:  *    this list of conditions, and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            18:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            19:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            20:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
        !            21:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            22:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            23:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            25:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            26:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            27:  * SUCH DAMAGE.
        !            28:  */
1.1       deraadt    29: /*
                     30:  * is_tar() -- figure out whether file is a tar archive.
                     31:  *
                     32:  * Stolen (by the author!) from the public domain tar program:
1.7     ! tedu       33:  * Public Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
1.1       deraadt    34:  *
                     35:  * @(#)list.c 1.18 9/23/86 Public Domain - gnu
                     36:  *
                     37:  * Comments changed and some code/comments reformatted
                     38:  * for file command by Ian Darwin.
                     39:  */
                     40:
1.7     ! tedu       41: #include "file.h"
        !            42: #include "magic.h"
1.1       deraadt    43: #include <string.h>
                     44: #include <ctype.h>
                     45: #include <sys/types.h>
                     46: #include "tar.h"
1.7     ! tedu       47:
        !            48: #ifndef lint
        !            49: FILE_RCSID("@(#)$Id: is_tar.c,v 1.24 2003/11/11 20:01:46 christos Exp $")
        !            50: #endif
1.1       deraadt    51:
                     52: #define        isodigit(c)     ( ((c) >= '0') && ((c) <= '7') )
                     53:
1.7     ! tedu       54: private int is_tar(const unsigned char *, size_t);
        !            55: private int from_oct(int, const char *);       /* Decode octal number */
        !            56:
        !            57: protected int
        !            58: file_is_tar(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
        !            59: {
        !            60:        /*
        !            61:         * Do the tar test first, because if the first file in the tar
        !            62:         * archive starts with a dot, we can confuse it with an nroff file.
        !            63:         */
        !            64:        switch (is_tar(buf, nbytes)) {
        !            65:        case 1:
        !            66:                if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
        !            67:                    "application/x-tar" : "tar archive") == -1)
        !            68:                        return -1;
        !            69:                return 1;
        !            70:        case 2:
        !            71:                if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
        !            72:                    "application/x-tar, POSIX" : "POSIX tar archive") == -1)
        !            73:                        return -1;
        !            74:                return 1;
        !            75:        default:
        !            76:                return 0;
        !            77:        }
        !            78: }
1.1       deraadt    79:
                     80: /*
                     81:  * Return
                     82:  *     0 if the checksum is bad (i.e., probably not a tar archive),
                     83:  *     1 for old UNIX tar file,
                     84:  *     2 for Unix Std (POSIX) tar file.
                     85:  */
1.7     ! tedu       86: private int
        !            87: is_tar(const unsigned char *buf, size_t nbytes)
1.1       deraadt    88: {
1.7     ! tedu       89:        const union record *header = (const union record *)(const void *)buf;
1.4       mpech      90:        int     i;
                     91:        int     sum, recsum;
1.7     ! tedu       92:        const char      *p;
1.1       deraadt    93:
                     94:        if (nbytes < sizeof(union record))
                     95:                return 0;
                     96:
                     97:        recsum = from_oct(8,  header->header.chksum);
                     98:
                     99:        sum = 0;
                    100:        p = header->charptr;
                    101:        for (i = sizeof(union record); --i >= 0;) {
                    102:                /*
1.7     ! tedu      103:                 * We cannot use unsigned char here because of old compilers,
1.1       deraadt   104:                 * e.g. V7.
                    105:                 */
                    106:                sum += 0xFF & *p++;
                    107:        }
                    108:
                    109:        /* Adjust checksum to count the "chksum" field as blanks. */
                    110:        for (i = sizeof(header->header.chksum); --i >= 0;)
                    111:                sum -= 0xFF & header->header.chksum[i];
                    112:        sum += ' '* sizeof header->header.chksum;
                    113:
                    114:        if (sum != recsum)
                    115:                return 0;       /* Not a tar archive */
                    116:
                    117:        if (0==strcmp(header->header.magic, TMAGIC))
                    118:                return 2;               /* Unix Standard tar archive */
                    119:
                    120:        return 1;                       /* Old fashioned tar archive */
                    121: }
                    122:
                    123:
                    124: /*
                    125:  * Quick and dirty octal conversion.
                    126:  *
                    127:  * Result is -1 if the field is invalid (all blank, or nonoctal).
                    128:  */
1.7     ! tedu      129: private int
        !           130: from_oct(int digs, const char *where)
1.1       deraadt   131: {
1.4       mpech     132:        int     value;
1.1       deraadt   133:
1.7     ! tedu      134:        while (isspace((unsigned char)*where)) {        /* Skip spaces */
1.1       deraadt   135:                where++;
                    136:                if (--digs <= 0)
                    137:                        return -1;              /* All blank field */
                    138:        }
                    139:        value = 0;
                    140:        while (digs > 0 && isodigit(*where)) {  /* Scan til nonoctal */
                    141:                value = (value << 3) | (*where++ - '0');
                    142:                --digs;
                    143:        }
                    144:
1.7     ! tedu      145:        if (digs > 0 && *where && !isspace((unsigned char)*where))
1.1       deraadt   146:                return -1;                      /* Ended on non-space/nul */
                    147:
                    148:        return value;
                    149: }