file_cmds-60.tar.gz
[apple/file_cmds.git] / file / is_tar.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /* $OpenBSD: is_tar.c,v 1.3 1997/02/09 23:58:27 millert Exp $ */
25
26 /*
27 * is_tar() -- figure out whether file is a tar archive.
28 *
29 * Stolen (by the author!) from the public domain tar program:
30 * Pubic Domain version written 26 Aug 1985 John Gilmore (ihnp4!hoptoad!gnu).
31 *
32 * @(#)list.c 1.18 9/23/86 Public Domain - gnu
33 *
34 * Comments changed and some code/comments reformatted
35 * for file command by Ian Darwin.
36 */
37
38 #include <string.h>
39 #include <ctype.h>
40 #include <sys/types.h>
41 #include "tar.h"
42
43 #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') )
44
45 #if defined(__STDC__) || defined(__cplusplus)
46 static int from_oct(int, char*); /* Decode octal number */
47 #else
48 static int from_oct();
49 #endif
50
51 /*
52 * Return
53 * 0 if the checksum is bad (i.e., probably not a tar archive),
54 * 1 for old UNIX tar file,
55 * 2 for Unix Std (POSIX) tar file.
56 */
57 int
58 is_tar(buf, nbytes)
59 unsigned char *buf;
60 int nbytes;
61 {
62 register union record *header = (union record *)buf;
63 register int i;
64 register int sum, recsum;
65 register char *p;
66
67 if (nbytes < sizeof(union record))
68 return 0;
69
70 recsum = from_oct(8, header->header.chksum);
71
72 sum = 0;
73 p = header->charptr;
74 for (i = sizeof(union record); --i >= 0;) {
75 /*
76 * We can't use unsigned char here because of old compilers,
77 * e.g. V7.
78 */
79 sum += 0xFF & *p++;
80 }
81
82 /* Adjust checksum to count the "chksum" field as blanks. */
83 for (i = sizeof(header->header.chksum); --i >= 0;)
84 sum -= 0xFF & header->header.chksum[i];
85 sum += ' '* sizeof header->header.chksum;
86
87 if (sum != recsum)
88 return 0; /* Not a tar archive */
89
90 if (0==strcmp(header->header.magic, TMAGIC))
91 return 2; /* Unix Standard tar archive */
92
93 return 1; /* Old fashioned tar archive */
94 }
95
96
97 /*
98 * Quick and dirty octal conversion.
99 *
100 * Result is -1 if the field is invalid (all blank, or nonoctal).
101 */
102 static int
103 from_oct(digs, where)
104 register int digs;
105 register char *where;
106 {
107 register int value;
108
109 while (isspace(*where)) { /* Skip spaces */
110 where++;
111 if (--digs <= 0)
112 return -1; /* All blank field */
113 }
114 value = 0;
115 while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */
116 value = (value << 3) | (*where++ - '0');
117 --digs;
118 }
119
120 if (digs > 0 && *where && !isspace(*where))
121 return -1; /* Ended on non-space/nul */
122
123 return value;
124 }