1 /*
2 ** find file types by using a modified "magic" file
3 **
4 ** based on file v3.22 by Ian F. Darwin (see below)
5 **
6 ** For each entry in the magic file, the message MUST start with
7 ** two 4 character strings which are the CREATOR and TYPE for the
8 ** Mac file. Any continuation lines are ignored. e.g magic entry
9 ** for a GIF file:
10 **
11 ** 0 string GIF8 8BIM GIFf
12 ** >4 string 7a \b, version 8%s,
13 ** >4 string 9a \b, version 8%s,
14 ** >6 leshort >0 %hd x
15 ** >8 leshort >0 %hd,
16 ** #>10 byte &0x80 color mapped,
17 ** #>10 byte&0x07 =0x00 2 colors
18 ** #>10 byte&0x07 =0x01 4 colors
19 ** #>10 byte&0x07 =0x02 8 colors
20 ** #>10 byte&0x07 =0x03 16 colors
21 ** #>10 byte&0x07 =0x04 32 colors
22 ** #>10 byte&0x07 =0x05 64 colors
23 ** #>10 byte&0x07 =0x06 128 colors
24 ** #>10 byte&0x07 =0x07 256 colors
25 **
26 ** Just the "8BIM" "GIFf" will be used whatever the type GIF file
27 ** it is.
28 **
29 ** Modified for mkhybrid James Pearson 19/5/98
30 */
31
32 /*
33 * file - find type of a file or files - main program.
34 *
35 * Copyright (c) Ian F. Darwin, 1987.
36 * Written by Ian F. Darwin.
37 *
38 * This software is not subject to any license of the American Telephone
39 * and Telegraph Company or of the Regents of the University of California.
40 *
41 * Permission is granted to anyone to use this software for any purpose on
42 * any computer system, and to alter it and redistribute it freely, subject
43 * to the following restrictions:
44 *
45 * 1. The author is not responsible for the consequences of use of this
46 * software, no matter how awful, even if they arise from flaws in it.
47 *
48 * 2. The origin of this software must not be misrepresented, either by
49 * explicit claim or by omission. Since few users ever read sources,
50 * credits must appear in the documentation.
51 *
52 * 3. Altered versions must be plainly marked as such, and must not be
53 * misrepresented as being the original software. Since few users
54 * ever read sources, credits must appear in the documentation.
55 *
56 * 4. This notice may not be removed or altered.
57 */
58 #include <stdio.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <sys/types.h>
62 #include <sys/param.h> /* for MAXPATHLEN */
63 #include <sys/stat.h>
64 #include <fcntl.h> /* for open() */
65 #if (__COHERENT__ >= 0x420)
66 # include <sys/utime.h>
67 #else
68 # ifdef USE_UTIMES
69 # include <sys/time.h>
70 # else
71 # include <utime.h>
72 # endif
73 #endif
74 #include <unistd.h> /* for read() */
75
76 #include <netinet/in.h> /* for byte swapping */
77
78 #include "patchlevel.h"
79 #include "file.h"
80 #include "proto.h"
81
82 int /* Global command-line options */
83 #ifdef DEBUG
84 debug = 1, /* debugging */
85 #else
86 debug = 0, /* debugging */
87 #endif /* DEBUG */
88 lflag = 0, /* follow Symlinks (BSD only) */
89 zflag = 0; /* follow (uncompress) compressed files */
90
91 int /* Misc globals */
92 nmagic = 0; /* number of valid magic[]s */
93
94 struct magic *magic; /* array of magic entries */
95
96 char *magicfile; /* where magic be found */
97
98 char *progname; /* used throughout */
99 int lineno; /* line number in the magic file */
100
101 #if 0
102 static int byteconv4 __P((int, int, int));
103 static short byteconv2 __P((int, int, int));
104 #endif
105
106 #if 0
107 /*
108 * byteconv4
109 * Input:
110 * from 4 byte quantity to convert
111 * same whether to perform byte swapping
112 * big_endian whether we are a big endian host
113 */
114 static int
byteconv4(from,same,big_endian)115 byteconv4(from, same, big_endian)
116 int from;
117 int same;
118 int big_endian;
119 {
120 if (same)
121 return from;
122 else if (big_endian) /* lsb -> msb conversion on msb */
123 {
124 union {
125 int i;
126 char c[4];
127 } retval, tmpval;
128
129 tmpval.i = from;
130 retval.c[0] = tmpval.c[3];
131 retval.c[1] = tmpval.c[2];
132 retval.c[2] = tmpval.c[1];
133 retval.c[3] = tmpval.c[0];
134
135 return retval.i;
136 }
137 else
138 return ntohl(from); /* msb -> lsb conversion on lsb */
139 }
140
141 /*
142 * byteconv2
143 * Same as byteconv4, but for shorts
144 */
145 static short
byteconv2(from,same,big_endian)146 byteconv2(from, same, big_endian)
147 int from;
148 int same;
149 int big_endian;
150 {
151 if (same)
152 return from;
153 else if (big_endian) /* lsb -> msb conversion on msb */
154 {
155 union {
156 short s;
157 char c[2];
158 } retval, tmpval;
159
160 tmpval.s = (short) from;
161 retval.c[0] = tmpval.c[1];
162 retval.c[1] = tmpval.c[0];
163
164 return retval.s;
165 }
166 else
167 return ntohs(from); /* msb -> lsb conversion on lsb */
168 }
169 #endif
170
171 /*
172 * get_magic_match - get the CREATOR/TYPE string
173 * based on the original process()
174 */
175 char *
get_magic_match(inname)176 get_magic_match(inname)
177 const char *inname;
178 {
179 int fd = 0;
180 unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */
181 struct stat sb;
182 int nbytes = 0; /* number of bytes read from a datafile */
183 char *match;
184
185 /* check the file is regular and non-zero length */
186 if (stat(inname, &sb) != 0)
187 return 0;
188
189 if (sb.st_size == 0 || ! S_ISREG(sb.st_mode))
190 return 0;
191
192 if ((fd = open(inname, O_RDONLY)) < 0)
193 return 0;
194
195 /*
196 * try looking at the first HOWMANY bytes
197 */
198 if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1)
199 return 0;
200
201 if (nbytes == 0)
202 return 0;
203 else {
204 buf[nbytes++] = '\0'; /* null-terminate it */
205 match = softmagic(buf, nbytes);
206 }
207
208 #ifdef RESTORE_TIME
209 /* really no point as we going to access the file later anyway */
210 {
211 /*
212 * Try to restore access, modification times if read it.
213 */
214 # ifdef USE_UTIMES
215 struct timeval utsbuf[2];
216 utsbuf[0].tv_sec = sb.st_atime;
217 utsbuf[1].tv_sec = sb.st_mtime;
218
219 (void) utimes(inname, utsbuf); /* don't care if loses */
220 # else
221 struct utimbuf utbuf;
222
223 utbuf.actime = sb.st_atime;
224 utbuf.modtime = sb.st_mtime;
225 (void) utime(inname, &utbuf); /* don't care if loses */
226 # endif
227 #endif
228 (void) close(fd);
229
230 return(match);
231 }
232
233 /*
234 * clean_magic - deallocate memory used
235 */
236 void
237 clean_magic()
238 {
239 if (magic)
240 free(magic);
241 }
242
243
244 #ifdef MAIN
245 main(argc, argv)
246 int argc;
247 char **argv;
248 {
249 char *ret;
250 char creator[5];
251 char type[5];
252
253 if (argc < 3)
254 exit(1);
255
256 init_magic(argv[1]);
257
258 ret = get_magic_match(argv[2]);
259
260 if (!ret)
261 ret = "unixTEXT";
262
263 sscanf(ret, "%4s%4s", creator, type);
264
265 creator[4] = type[4] = '\0';
266
267 printf("%s %s\n", creator, type);
268
269
270 exit(0);
271 }
272 #endif /* MAIN */
273
274