1 /* @(#)file.c 1.10 09/08/04 joerg */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static UConst char sccsid[] =
5 "@(#)file.c 1.10 09/08/04 joerg";
6 #endif
7 /*
8 ** find file types by using a modified "magic" file
9 **
10 ** based on file v3.22 by Ian F. Darwin (see below)
11 **
12 ** For each entry in the magic file, the message MUST start with
13 ** two 4 character strings which are the CREATOR and TYPE for the
14 ** Mac file. Any continuation lines are ignored. e.g magic entry
15 ** for a GIF file:
16 **
17 ** 0 string GIF8 8BIM GIFf
18 ** >4 string 7a \b, version 8%s,
19 ** >4 string 9a \b, version 8%s,
20 ** >6 leshort >0 %hd x
21 ** >8 leshort >0 %hd,
22 ** #>10 byte &0x80 color mapped,
23 ** #>10 byte&0x07 =0x00 2 colors
24 ** #>10 byte&0x07 =0x01 4 colors
25 ** #>10 byte&0x07 =0x02 8 colors
26 ** #>10 byte&0x07 =0x03 16 colors
27 ** #>10 byte&0x07 =0x04 32 colors
28 ** #>10 byte&0x07 =0x05 64 colors
29 ** #>10 byte&0x07 =0x06 128 colors
30 ** #>10 byte&0x07 =0x07 256 colors
31 **
32 ** Just the "8BIM" "GIFf" will be used whatever the type GIF file
33 ** it is.
34 **
35 ** Modified for mkhybrid James Pearson 19/5/98
36 */
37
38 /*
39 * file - find type of a file or files - main program.
40 *
41 * Copyright (c) Ian F. Darwin, 1987.
42 * Written by Ian F. Darwin.
43 *
44 * This software is not subject to any export provision of the United States
45 * Department of Commerce, and may be exported to any country or planet.
46 *
47 * Redistribution and use in source and binary forms, with or without
48 * modification, are permitted provided that the following conditions
49 * are met:
50 * 1. Redistributions of source code must retain the above copyright
51 * notice immediately at the beginning of the file, without modification,
52 * this list of conditions, and the following disclaimer.
53 * 2. Redistributions in binary form must reproduce the above copyright
54 * notice, this list of conditions and the following disclaimer in the
55 * documentation and/or other materials provided with the distribution.
56 *
57 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
61 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67 * SUCH DAMAGE.
68 */
69 #ifndef lint
70 static UConst char moduleid[] =
71 "@(#)$Id: file.c,v 1.38 1997/01/15 19:28:35 christos Exp $";
72 #endif /* lint */
73
74 #include <schily/stdio.h>
75 #include <schily/stdlib.h>
76 #include <schily/unistd.h> /* for read() */
77 #include <schily/stat.h>
78 #include <schily/fcntl.h> /* for open() */
79
80 #ifdef RESTORE_TIME
81 #include <schily/utime.h>
82 #ifdef HAVE_UTIMES
83 #define USE_UTIMES
84 #endif
85 #endif
86
87 #if 0
88 #include <schily/in.h> /* for byte swapping */
89 #endif
90
91 #include "patchlevel.h"
92 #include "file.h"
93
94 #ifdef MAIN
95 /* Global command-line options */
96 #ifdef DEBUG
97 int debug = 1; /* debugging */
98 #else
99 int debug = 0; /* debugging */
100 #endif /* DEBUG */
101 int lflag = 0; /* follow Symlinks (BSD only) */
102 int zflag = 0; /* follow (uncompress) compressed files */
103
104 /* Misc globals */
105 char *magicfile; /* where magic be found */
106
107 char *progname; /* used throughout */
108 #endif
109
110 char * get_magic_match __PR((const char *inname));
111 void clean_magic __PR((void));
112
113 #if 0
114 static int byteconv4 __P((int, int, int));
115 static short byteconv2 __P((int, int, int));
116 #endif
117
118 #if 0
119 /*
120 * byteconv4
121 * Input:
122 * from 4 byte quantity to convert
123 * same whether to perform byte swapping
124 * big_endian whether we are a big endian host
125 */
126 static int
127 byteconv4(from, same, big_endian)
128 int from;
129 int same;
130 int big_endian;
131 {
132 if (same)
133 return from;
134 else if (big_endian) /* lsb -> msb conversion on msb */
135 {
136 union {
137 int i;
138 char c[4];
139 } retval, tmpval;
140
141 tmpval.i = from;
142 retval.c[0] = tmpval.c[3];
143 retval.c[1] = tmpval.c[2];
144 retval.c[2] = tmpval.c[1];
145 retval.c[3] = tmpval.c[0];
146
147 return retval.i;
148 }
149 else
150 return ntohl(from); /* msb -> lsb conversion on lsb */
151 }
152
153 /*
154 * byteconv2
155 * Same as byteconv4, but for shorts
156 */
157 static short
158 byteconv2(from, same, big_endian)
159 int from;
160 int same;
161 int big_endian;
162 {
163 if (same)
164 return from;
165 else if (big_endian) /* lsb -> msb conversion on msb */
166 {
167 union {
168 short s;
169 char c[2];
170 } retval, tmpval;
171
172 tmpval.s = (short) from;
173 retval.c[0] = tmpval.c[1];
174 retval.c[1] = tmpval.c[0];
175
176 return retval.s;
177 }
178 else
179 return ntohs(from); /* msb -> lsb conversion on lsb */
180 }
181 #endif
182
183 /*
184 * get_magic_match - get the CREATOR/TYPE string
185 * based on the original process()
186 */
187 char *
get_magic_match(inname)188 get_magic_match(inname)
189 const char *inname;
190 {
191 int fd = 0;
192 unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */
193 struct stat sb;
194 int nbytes = 0; /* number of bytes read from a datafile */
195 char *match;
196
197 /* check the file is regular and non-zero length */
198 if (stat(inname, &sb) != 0)
199 return 0;
200
201 if (sb.st_size == 0 || ! S_ISREG(sb.st_mode))
202 return 0;
203
204 if ((fd = open(inname, O_RDONLY)) < 0)
205 return 0;
206
207 /*
208 * try looking at the first HOWMANY bytes
209 */
210 if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1)
211 return 0;
212
213 if (nbytes == 0)
214 return 0;
215 else {
216 buf[nbytes++] = '\0'; /* null-terminate it */
217 match = softmagic(buf, nbytes);
218 }
219
220 #ifdef RESTORE_TIME
221 /* really no point as we going to access the file later anyway */
222 {
223 /*
224 * Try to restore access, modification times if read it.
225 */
226 # ifdef USE_UTIMES
227 struct timeval utsbuf[2];
228 utsbuf[0].tv_sec = sb.st_atime;
229 utsbuf[1].tv_sec = sb.st_mtime;
230
231 (void) utimes(inname, utsbuf); /* don't care if loses */
232 # else
233 struct utimbuf utbuf;
234
235 utbuf.actime = sb.st_atime;
236 utbuf.modtime = sb.st_mtime;
237 (void) utime(inname, &utbuf); /* don't care if loses */
238 # endif
239 }
240 #endif
241 (void) close(fd);
242
243 return(match);
244 }
245
246 /*
247 * clean_magic - deallocate memory used
248 */
249 void
clean_magic()250 clean_magic()
251 {
252 if (__f_magic)
253 free(__f_magic);
254 }
255
256
257 #ifdef MAIN
main(argc,argv)258 main(argc, argv)
259 int argc;
260 char **argv;
261 {
262 char *ret;
263 char creator[5];
264 char type[5];
265
266 if (argc < 3)
267 exit(1);
268
269 init_magic(argv[1]);
270
271 ret = get_magic_match(argv[2]);
272
273 if (!ret)
274 ret = "unixTEXT";
275
276 sscanf(ret, "%4s%4s", creator, type);
277
278 creator[4] = type[4] = '\0';
279
280 printf("%s %s\n", creator, type);
281
282
283 exit(0);
284 }
285 #endif /* MAIN */
286
287