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 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 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 * 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