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.40 2007/03/01 22:14:55 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 = malloc(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 return ms;
00118 free3:
00119 free(ms->o.pbuf);
00120 free2:
00121 free(ms->o.buf);
00122 free1:
00123 free(ms);
00124 return NULL;
00125 }
00126
00127 private void
00128 free_mlist(struct mlist *mlist)
00129 {
00130 struct mlist *ml;
00131
00132 if (mlist == NULL)
00133 return;
00134
00135 for (ml = mlist->next; ml != mlist;) {
00136 struct mlist *next = ml->next;
00137 struct magic *mg = ml->magic;
00138 file_delmagic(mg, ml->mapped, ml->nmagic);
00139 free(ml);
00140 ml = next;
00141 }
00142 free(ml);
00143 }
00144
00145 private int
00146 info_from_stat(struct magic_set *ms, mode_t md)
00147 {
00148
00149 if (md & 0222)
00150 if (file_printf(ms, "writable, ") == -1)
00151 return -1;
00152 if (md & 0111)
00153 if (file_printf(ms, "executable, ") == -1)
00154 return -1;
00155 if (S_ISREG(md))
00156 if (file_printf(ms, "regular file, ") == -1)
00157 return -1;
00158 if (file_printf(ms, "no read permission") == -1)
00159 return -1;
00160 return 0;
00161 }
00162
00163 public void
00164 magic_close(struct magic_set *ms)
00165 {
00166 free_mlist(ms->mlist);
00167 free(ms->o.pbuf);
00168 free(ms->o.buf);
00169 free(ms->c.li);
00170 free(ms);
00171 }
00172
00173
00174
00175
00176 public int
00177 magic_load(struct magic_set *ms, const char *magicfile)
00178 {
00179 struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
00180 if (ml) {
00181 free_mlist(ms->mlist);
00182 ms->mlist = ml;
00183 return 0;
00184 }
00185 return -1;
00186 }
00187
00188 public int
00189 magic_compile(struct magic_set *ms, const char *magicfile)
00190 {
00191 struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
00192 free_mlist(ml);
00193 return ml ? 0 : -1;
00194 }
00195
00196 public int
00197 magic_check(struct magic_set *ms, const char *magicfile)
00198 {
00199 struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK);
00200 free_mlist(ml);
00201 return ml ? 0 : -1;
00202 }
00203
00204 private void
00205 close_and_restore(const struct magic_set *ms, const char *name, int fd,
00206 const struct stat *sb)
00207 {
00208 if (fd == STDIN_FILENO)
00209 return;
00210 (void) close(fd);
00211
00212 if (name != NULL && (ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
00213
00214
00215
00216
00217
00218
00219 #ifdef HAVE_UTIMES
00220 struct timeval utsbuf[2];
00221 utsbuf[0].tv_sec = sb->st_atime;
00222 utsbuf[1].tv_sec = sb->st_mtime;
00223
00224 (void) utimes(name, utsbuf);
00225 #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
00226 struct utimbuf utbuf;
00227
00228 utbuf.actime = sb->st_atime;
00229 utbuf.modtime = sb->st_mtime;
00230 (void) utime(name, &utbuf);
00231 #endif
00232 }
00233 }
00234
00235 #ifndef COMPILE_ONLY
00236
00237
00238
00239 public const char *
00240 magic_file(struct magic_set *ms, const char *inname)
00241 {
00242 int fd = 0;
00243 int rv = -1;
00244 unsigned char *buf;
00245 struct stat sb, *st = &sb;
00246 ssize_t nbytes = 0;
00247 int ispipe = 0;
00248
00249
00250
00251
00252
00253 #define SLOP (1 + sizeof(union VALUETYPE))
00254 if ((buf = malloc(HOWMANY + SLOP)) == NULL)
00255 return NULL;
00256
00257 if (file_reset(ms) == -1)
00258 goto done;
00259
00260 switch (file_fsmagic(ms, inname, st)) {
00261 case -1:
00262 goto done;
00263 case 0:
00264 break;
00265 default:
00266 rv = 0;
00267 goto done;
00268 }
00269
00270 if (inname == NULL) {
00271 fd = STDIN_FILENO;
00272 if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode))
00273 ispipe = 1;
00274 } else {
00275 int flags = O_RDONLY|O_BINARY;
00276
00277 if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
00278 flags |= O_NONBLOCK;
00279 ispipe = 1;
00280 }
00281
00282 errno = 0;
00283 if ((fd = open(inname, flags)) < 0) {
00284 #ifdef __CYGWIN__
00285 char *tmp = alloca(strlen(inname) + 5);
00286 (void)strcat(strcpy(tmp, inname), ".exe");
00287 if ((fd = open(tmp, flags)) < 0) {
00288 #endif
00289 if (info_from_stat(ms, sb.st_mode) == -1)
00290 goto done;
00291 rv = 0;
00292 goto done;
00293 #ifdef __CYGWIN__
00294 }
00295 #endif
00296 }
00297 #ifdef O_NONBLOCK
00298 if ((flags = fcntl(fd, F_GETFL)) != -1) {
00299 flags &= ~O_NONBLOCK;
00300 (void)fcntl(fd, F_SETFL, flags);
00301 }
00302 #endif
00303 }
00304
00305
00306
00307
00308 if (ispipe) {
00309 ssize_t r = 0;
00310
00311 while ((r = sread(fd, (void *)&buf[nbytes],
00312 (size_t)(HOWMANY - nbytes), 1)) > 0) {
00313 nbytes += r;
00314 if (r < PIPE_BUF) break;
00315 }
00316
00317 if (nbytes == 0) {
00318
00319 if (info_from_stat(ms, sb.st_mode) == -1)
00320 goto done;
00321 rv = 0;
00322 goto done;
00323 }
00324
00325 } else {
00326 if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
00327 file_error(ms, errno, "cannot read `%s'", inname);
00328 goto done;
00329 }
00330 }
00331
00332 if (nbytes == 0) {
00333 if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
00334 "application/x-empty" : "empty") == -1)
00335 goto done;
00336 } else if (nbytes == 1) {
00337 if (file_printf(ms, "very short file (no magic)") == -1)
00338 goto done;
00339 } else {
00340 (void)memset(buf + nbytes, 0, SLOP);
00341 if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1)
00342 goto done;
00343 }
00344 rv = 0;
00345 done:
00346 free(buf);
00347 close_and_restore(ms, inname, fd, &sb);
00348 return rv == 0 ? file_getbuffer(ms) : NULL;
00349 }
00350
00351
00352 public const char *
00353 magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
00354 {
00355 if (file_reset(ms) == -1)
00356 return NULL;
00357
00358
00359
00360
00361 if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
00362 return NULL;
00363 }
00364 return file_getbuffer(ms);
00365 }
00366 #endif
00367
00368 public const char *
00369 magic_error(struct magic_set *ms)
00370 {
00371 return ms->haderr ? ms->o.buf : NULL;
00372 }
00373
00374 public int
00375 magic_errno(struct magic_set *ms)
00376 {
00377 return ms->haderr ? ms->error : 0;
00378 }
00379
00380 public int
00381 magic_setflags(struct magic_set *ms, int flags)
00382 {
00383 #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
00384 if (flags & MAGIC_PRESERVE_ATIME)
00385 return -1;
00386 #endif
00387 ms->flags = flags;
00388 return 0;
00389 }