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: }