00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "file.h"
00029 #include "magic.h"
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <unistd.h>
00034 #include <string.h>
00035 #include <sys/types.h>
00036 #include <sys/param.h>
00037 #include <sys/stat.h>
00038 #ifdef QUICK
00039 #include <sys/mman.h>
00040 #endif
00041 #include <limits.h>
00042
00043 #if defined(HAVE_UTIMES)
00044 # include <sys/time.h>
00045 #elif defined(HAVE_UTIME)
00046 # if defined(HAVE_SYS_UTIME_H)
00047 # include <sys/utime.h>
00048 # elif defined(HAVE_UTIME_H)
00049 # include <utime.h>
00050 # endif
00051 #endif
00052
00053 #ifdef HAVE_UNISTD_H
00054 #include <unistd.h>
00055 #endif
00056
00057 #ifdef HAVE_LOCALE_H
00058 #include <locale.h>
00059 #endif
00060
00061 #include <netinet/in.h>
00062
00063 #include "patchlevel.h"
00064
00065 #ifndef lint
00066 FILE_RCSID("@(#)$File: magic.c,v 1.41 2007/03/26 17:59:50 christos Exp $")
00067 #endif
00068
00069 #ifdef __EMX__
00070 private char *apptypeName = NULL;
00071 protected int file_os2_apptype(struct magic_set *ms, const char *fn,
00072 const void *buf, size_t nb);
00073 #endif
00074
00075 private void free_mlist(struct mlist *mlist)
00076
00077 ;
00078 private void close_and_restore(const struct magic_set *ms, const char *name,
00079 int fd, const struct stat *sb)
00080
00081 ;
00082 private int info_from_stat(struct magic_set *ms, mode_t md)
00083 ;
00084
00085 #ifndef STDIN_FILENO
00086 #define STDIN_FILENO 0
00087 #endif
00088
00089 public struct magic_set *
00090 magic_open(int flags)
00091 {
00092 struct magic_set *ms;
00093
00094 if ((ms = calloc((size_t)1, sizeof(struct magic_set))) == NULL)
00095 return NULL;
00096
00097 if (magic_setflags(ms, flags) == -1) {
00098 errno = EINVAL;
00099 goto free1;
00100 }
00101
00102 ms->o.ptr = ms->o.buf = malloc(ms->o.left = ms->o.size = 1024);
00103 if (ms->o.buf == NULL)
00104 goto free1;
00105
00106 ms->o.pbuf = malloc(ms->o.psize = 1024);
00107 if (ms->o.pbuf == NULL)
00108 goto free2;
00109
00110 ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li));
00111 if (ms->c.li == NULL)
00112 goto free3;
00113
00114 ms->haderr = 0;
00115 ms->error = -1;
00116 ms->mlist = NULL;
00117 ms->file = "unknown";
00118 ms->line = 0;
00119 return ms;
00120 free3:
00121 free(ms->o.pbuf);
00122 free2:
00123 free(ms->o.buf);
00124 free1:
00125 free(ms);
00126 return NULL;
00127 }
00128
00129 private void
00130 free_mlist(struct mlist *mlist)
00131 {
00132 struct mlist *ml;
00133
00134 if (mlist == NULL)
00135 return;
00136
00137 for (ml = mlist->next; ml != mlist;) {
00138 struct mlist *next = ml->next;
00139 struct magic *mg = ml->magic;
00140 file_delmagic(mg, ml->mapped, ml->nmagic);
00141 free(ml);
00142 ml = next;
00143 }
00144 free(ml);
00145 }
00146
00147 private int
00148 info_from_stat(struct magic_set *ms, mode_t md)
00149 {
00150
00151 if (md & 0222)
00152 if (file_printf(ms, "writable, ") == -1)
00153 return -1;
00154 if (md & 0111)
00155 if (file_printf(ms, "executable, ") == -1)
00156 return -1;
00157 if (S_ISREG(md))
00158 if (file_printf(ms, "regular file, ") == -1)
00159 return -1;
00160 if (file_printf(ms, "no read permission") == -1)
00161 return -1;
00162 return 0;
00163 }
00164
00165 public void
00166 magic_close(struct magic_set *ms)
00167 {
00168 free_mlist(ms->mlist);
00169 free(ms->o.pbuf);
00170 free(ms->o.buf);
00171 free(ms->c.li);
00172 free(ms);
00173 }
00174
00175
00176
00177
00178 public int
00179 magic_load(struct magic_set *ms, const char *magicfile)
00180 {
00181 struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
00182 if (ml) {
00183 free_mlist(ms->mlist);
00184 ms->mlist = ml;
00185 return 0;
00186 }
00187 return -1;
00188 }
00189
00190 public int
00191 magic_compile(struct magic_set *ms, const char *magicfile)
00192 {
00193 struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
00194 free_mlist(ml);
00195 return ml ? 0 : -1;
00196 }
00197
00198 public int
00199 magic_check(struct magic_set *ms, const char *magicfile)
00200 {
00201 struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK);
00202 free_mlist(ml);
00203 return ml ? 0 : -1;
00204 }
00205
00206 private void
00207 close_and_restore(const struct magic_set *ms, const char *name, int fd,
00208 const struct stat *sb)
00209 {
00210 if (fd == STDIN_FILENO)
00211 return;
00212 (void) close(fd);
00213
00214 if (name != NULL && (ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
00215
00216
00217
00218
00219
00220
00221 #ifdef HAVE_UTIMES
00222 struct timeval utsbuf[2];
00223 utsbuf[0].tv_sec = sb->st_atime;
00224 utsbuf[1].tv_sec = sb->st_mtime;
00225
00226 (void) utimes(name, utsbuf);
00227 #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
00228 struct utimbuf utbuf;
00229
00230 utbuf.actime = sb->st_atime;
00231 utbuf.modtime = sb->st_mtime;
00232 (void) utime(name, &utbuf);
00233 #endif
00234 }
00235 }
00236
00237 #ifndef COMPILE_ONLY
00238
00239
00240
00241 public const char *
00242 magic_file(struct magic_set *ms, const char *inname)
00243 {
00244 int fd = 0;
00245 int rv = -1;
00246 unsigned char *buf;
00247 struct stat sb, *st = &sb;
00248 ssize_t nbytes = 0;
00249 int ispipe = 0;
00250
00251
00252
00253
00254
00255 #define SLOP (1 + sizeof(union VALUETYPE))
00256 if ((buf = malloc(HOWMANY + SLOP)) == NULL)
00257 return NULL;
00258
00259 if (file_reset(ms) == -1)
00260 goto done;
00261
00262 switch (file_fsmagic(ms, inname, st)) {
00263 case -1:
00264 goto done;
00265 case 0:
00266 break;
00267 default:
00268 rv = 0;
00269 goto done;
00270 }
00271
00272 if (inname == NULL) {
00273 fd = STDIN_FILENO;
00274 if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
00275 ispipe = 1;
00276 } else {
00277 int flags = O_RDONLY|O_BINARY;
00278
00279 if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
00280 flags |= O_NONBLOCK;
00281 ispipe = 1;
00282 }
00283
00284 errno = 0;
00285 if ((fd = open(inname, flags)) < 0) {
00286 #ifdef __CYGWIN__
00287 char *tmp = alloca(strlen(inname) + 5);
00288 (void)strcat(strcpy(tmp, inname), ".exe");
00289 if ((fd = open(tmp, flags)) < 0) {
00290 #endif
00291 if (info_from_stat(ms, sb.st_mode) == -1)
00292 goto done;
00293 rv = 0;
00294 goto done;
00295 #ifdef __CYGWIN__
00296 }
00297 #endif
00298 }
00299 #ifdef O_NONBLOCK
00300 if ((flags = fcntl(fd, F_GETFL)) != -1) {
00301 flags &= ~O_NONBLOCK;
00302 (void)fcntl(fd, F_SETFL, flags);
00303 }
00304 #endif
00305 }
00306
00307
00308
00309
00310 if (ispipe) {
00311 ssize_t r = 0;
00312
00313 while ((r = sread(fd, (void *)&buf[nbytes],
00314 (size_t)(HOWMANY - nbytes), 1)) > 0) {
00315 nbytes += r;
00316 if (r < PIPE_BUF) break;
00317 }
00318
00319 if (nbytes == 0) {
00320
00321 if (info_from_stat(ms, sb.st_mode) == -1)
00322 goto done;
00323 rv = 0;
00324 goto done;
00325 }
00326
00327 } else {
00328 if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
00329 file_error(ms, errno, "cannot read `%s'", inname);
00330 goto done;
00331 }
00332 }
00333
00334 if (nbytes == 0) {
00335 if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
00336 "application/x-empty" : "empty") == -1)
00337 goto done;
00338 } else if (nbytes == 1) {
00339 if (file_printf(ms, "very short file (no magic)") == -1)
00340 goto done;
00341 } else {
00342 (void)memset(buf + nbytes, 0, SLOP);
00343 if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
00344 goto done;
00345 }
00346 rv = 0;
00347 done:
00348 free(buf);
00349 close_and_restore(ms, inname, fd, &sb);
00350 return rv == 0 ? file_getbuffer(ms) : NULL;
00351 }
00352
00353
00354 public const char *
00355 magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
00356 {
00357 if (file_reset(ms) == -1)
00358 return NULL;
00359
00360
00361
00362
00363 if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
00364 return NULL;
00365 }
00366 return file_getbuffer(ms);
00367 }
00368 #endif
00369
00370 public const char *
00371 magic_error(struct magic_set *ms)
00372 {
00373 return ms->haderr ? ms->o.buf : NULL;
00374 }
00375
00376 public int
00377 magic_errno(struct magic_set *ms)
00378 {
00379 return ms->haderr ? ms->error : 0;
00380 }
00381
00382 public int
00383 magic_setflags(struct magic_set *ms, int flags)
00384 {
00385 #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
00386 if (flags & MAGIC_PRESERVE_ATIME)
00387 return -1;
00388 #endif
00389 ms->flags = flags;
00390 return 0;
00391 }