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