Commit | Line | Data |
---|---|---|
15637ed4 RG |
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 | |
286a6f32 | 8 | * is_tar.c,v 1.2 1993/06/10 00:38:12 jtc Exp |
15637ed4 RG |
9 | * |
10 | * Comments changed and some code/comments reformatted | |
11 | * for file command by Ian Darwin. | |
12 | */ | |
13 | ||
286a6f32 | 14 | #include <string.h> |
15637ed4 RG |
15 | #include <ctype.h> |
16 | #include <sys/types.h> | |
17 | #include "tar.h" | |
18 | ||
19 | #define isodigit(c) ( ((c) >= '0') && ((c) <= '7') ) | |
20 | ||
286a6f32 C |
21 | #if defined(__STDC__) || defined(__cplusplus) |
22 | static long from_oct(int, char*); /* Decode octal number */ | |
23 | #else | |
24 | static long from_oct(); | |
25 | #endif | |
15637ed4 RG |
26 | |
27 | /* | |
28 | * Return | |
29 | * 0 if the checksum is bad (i.e., probably not a tar archive), | |
30 | * 1 for old UNIX tar file, | |
31 | * 2 for Unix Std (POSIX) tar file. | |
32 | */ | |
33 | int | |
286a6f32 C |
34 | is_tar(buf) |
35 | unsigned char *buf; | |
15637ed4 | 36 | { |
286a6f32 | 37 | register union record *header = (union record *)buf; |
15637ed4 RG |
38 | register int i; |
39 | register long sum, recsum; | |
40 | register char *p; | |
41 | ||
42 | recsum = from_oct(8, header->header.chksum); | |
43 | ||
44 | sum = 0; | |
45 | p = header->charptr; | |
286a6f32 | 46 | for (i = sizeof(union record); --i >= 0;) { |
15637ed4 RG |
47 | /* |
48 | * We can't use unsigned char here because of old compilers, | |
49 | * e.g. V7. | |
50 | */ | |
51 | sum += 0xFF & *p++; | |
52 | } | |
53 | ||
54 | /* Adjust checksum to count the "chksum" field as blanks. */ | |
55 | for (i = sizeof(header->header.chksum); --i >= 0;) | |
56 | sum -= 0xFF & header->header.chksum[i]; | |
57 | sum += ' '* sizeof header->header.chksum; | |
58 | ||
59 | if (sum != recsum) | |
60 | return 0; /* Not a tar archive */ | |
61 | ||
62 | if (0==strcmp(header->header.magic, TMAGIC)) | |
63 | return 2; /* Unix Standard tar archive */ | |
64 | ||
65 | return 1; /* Old fashioned tar archive */ | |
66 | } | |
67 | ||
68 | ||
69 | /* | |
70 | * Quick and dirty octal conversion. | |
71 | * | |
72 | * Result is -1 if the field is invalid (all blank, or nonoctal). | |
73 | */ | |
286a6f32 | 74 | static long |
15637ed4 RG |
75 | from_oct(digs, where) |
76 | register int digs; | |
77 | register char *where; | |
78 | { | |
79 | register long value; | |
80 | ||
81 | while (isspace(*where)) { /* Skip spaces */ | |
82 | where++; | |
83 | if (--digs <= 0) | |
84 | return -1; /* All blank field */ | |
85 | } | |
86 | value = 0; | |
87 | while (digs > 0 && isodigit(*where)) { /* Scan til nonoctal */ | |
88 | value = (value << 3) | (*where++ - '0'); | |
89 | --digs; | |
90 | } | |
91 | ||
92 | if (digs > 0 && *where && !isspace(*where)) | |
93 | return -1; /* Ended on non-space/nul */ | |
94 | ||
95 | return value; | |
96 | } |