xref: /386bsd/usr/src/usr.bin/file/is_tar.c (revision a2142627)
1 /*
2  * is_tar() -- figure out whether file is a tar archive.
3  *
4  * Stolen (by the author!) from the public domain tar program:
5  * Pubic Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
6  *
7  * @(#)list.c 1.18 9/23/86 Public Domain - gnu
8  *
9  * Comments changed and some code/comments reformatted
10  * for file command by Ian Darwin.
11  */
12 
13 #include <ctype.h>
14 #include <sys/types.h>
15 #include "tar.h"
16 
17 #define	isodigit(c)	( ((c) >= '0') && ((c) <= '7') )
18 
19 long from_oct();			/* Decode octal number */
20 
21 /*
22  * Return
23  *	0 if the checksum is bad (i.e., probably not a tar archive),
24  *	1 for old UNIX tar file,
25  *	2 for Unix Std (POSIX) tar file.
26  */
27 int
is_tar(header)28 is_tar(header)
29 	register union record *header;
30 {
31 	register int	i;
32 	register long	sum, recsum;
33 	register char	*p;
34 
35 	recsum = from_oct(8,  header->header.chksum);
36 
37 	sum = 0;
38 	p = header->charptr;
39 	for (i = sizeof(*header); --i >= 0;) {
40 		/*
41 		 * We can't use unsigned char here because of old compilers,
42 		 * e.g. V7.
43 		 */
44 		sum += 0xFF & *p++;
45 	}
46 
47 	/* Adjust checksum to count the "chksum" field as blanks. */
48 	for (i = sizeof(header->header.chksum); --i >= 0;)
49 		sum -= 0xFF & header->header.chksum[i];
50 	sum += ' '* sizeof header->header.chksum;
51 
52 	if (sum != recsum)
53 		return 0;	/* Not a tar archive */
54 
55 	if (0==strcmp(header->header.magic, TMAGIC))
56 		return 2;		/* Unix Standard tar archive */
57 
58 	return 1;			/* Old fashioned tar archive */
59 }
60 
61 
62 /*
63  * Quick and dirty octal conversion.
64  *
65  * Result is -1 if the field is invalid (all blank, or nonoctal).
66  */
67 long
from_oct(digs,where)68 from_oct(digs, where)
69 	register int	digs;
70 	register char	*where;
71 {
72 	register long	value;
73 
74 	while (isspace(*where)) {		/* Skip spaces */
75 		where++;
76 		if (--digs <= 0)
77 			return -1;		/* All blank field */
78 	}
79 	value = 0;
80 	while (digs > 0 && isodigit(*where)) {	/* Scan til nonoctal */
81 		value = (value << 3) | (*where++ - '0');
82 		--digs;
83 	}
84 
85 	if (digs > 0 && *where && !isspace(*where))
86 		return -1;			/* Ended on non-space/nul */
87 
88 	return value;
89 }
90