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