magic.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*
  2. * Copyright (c) Christos Zoulas 2003.
  3. * All Rights Reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice immediately at the beginning of the file, without modification,
  10. * this list of conditions, and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  19. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include "file.h"
  28. #include "magic.h"
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <unistd.h>
  32. #include <string.h>
  33. #include <sys/types.h>
  34. #include <sys/param.h> /* for MAXPATHLEN */
  35. #include <sys/stat.h>
  36. #ifdef QUICK
  37. #include <sys/mman.h>
  38. #endif
  39. #if defined(HAVE_UTIMES)
  40. # include <sys/time.h>
  41. #elif defined(HAVE_UTIME)
  42. # if defined(HAVE_SYS_UTIME_H)
  43. # include <sys/utime.h>
  44. # elif defined(HAVE_UTIME_H)
  45. # include <utime.h>
  46. # endif
  47. #endif
  48. #ifdef HAVE_UNISTD_H
  49. #include <unistd.h> /* for read() */
  50. #endif
  51. #ifdef HAVE_LOCALE_H
  52. #include <locale.h>
  53. #endif
  54. #include <netinet/in.h> /* for byte swapping */
  55. #include "patchlevel.h"
  56. #ifndef lint
  57. FILE_RCSID("@(#)$Id: magic.c,v 1.32 2005/10/17 15:31:10 christos Exp $")
  58. #endif /* lint */
  59. #ifdef __EMX__
  60. private char *apptypeName = NULL;
  61. protected int file_os2_apptype(struct magic_set *ms, const char *fn,
  62. const void *buf, size_t nb);
  63. #endif /* __EMX__ */
  64. private void free_mlist(struct mlist *);
  65. private void close_and_restore(const struct magic_set *, const char *, int,
  66. const struct stat *);
  67. #ifndef STDIN_FILENO
  68. #define STDIN_FILENO 0
  69. #endif
  70. public struct magic_set *
  71. magic_open(int flags)
  72. {
  73. struct magic_set *ms;
  74. if ((ms = malloc(sizeof(struct magic_set))) == NULL)
  75. return NULL;
  76. if (magic_setflags(ms, flags) == -1) {
  77. errno = EINVAL;
  78. goto free1;
  79. }
  80. ms->o.ptr = ms->o.buf = malloc(ms->o.size = 1024);
  81. if (ms->o.buf == NULL)
  82. goto free1;
  83. ms->o.pbuf = malloc(ms->o.psize = 1024);
  84. if (ms->o.pbuf == NULL)
  85. goto free2;
  86. ms->c.off = malloc((ms->c.len = 10) * sizeof(*ms->c.off));
  87. if (ms->c.off == NULL)
  88. goto free3;
  89. ms->o.len = 0;
  90. ms->haderr = 0;
  91. ms->error = -1;
  92. ms->mlist = NULL;
  93. return ms;
  94. free3:
  95. free(ms->o.pbuf);
  96. free2:
  97. free(ms->o.buf);
  98. free1:
  99. free(ms);
  100. return NULL;
  101. }
  102. private void
  103. free_mlist(struct mlist *mlist)
  104. {
  105. struct mlist *ml;
  106. if (mlist == NULL)
  107. return;
  108. for (ml = mlist->next; ml != mlist;) {
  109. struct mlist *next = ml->next;
  110. struct magic *mg = ml->magic;
  111. file_delmagic(mg, ml->mapped, ml->nmagic);
  112. free(ml);
  113. ml = next;
  114. }
  115. free(ml);
  116. }
  117. public void
  118. magic_close(ms)
  119. struct magic_set *ms;
  120. {
  121. free_mlist(ms->mlist);
  122. free(ms->o.pbuf);
  123. free(ms->o.buf);
  124. free(ms->c.off);
  125. free(ms);
  126. }
  127. /*
  128. * load a magic file
  129. */
  130. public int
  131. magic_load(struct magic_set *ms, const char *magicfile)
  132. {
  133. struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
  134. if (ml) {
  135. free_mlist(ms->mlist);
  136. ms->mlist = ml;
  137. return 0;
  138. }
  139. return -1;
  140. }
  141. public int
  142. magic_compile(struct magic_set *ms, const char *magicfile)
  143. {
  144. struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
  145. free_mlist(ml);
  146. return ml ? 0 : -1;
  147. }
  148. public int
  149. magic_check(struct magic_set *ms, const char *magicfile)
  150. {
  151. struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK);
  152. free_mlist(ml);
  153. return ml ? 0 : -1;
  154. }
  155. private void
  156. close_and_restore(const struct magic_set *ms, const char *name, int fd,
  157. const struct stat *sb)
  158. {
  159. if (fd == STDIN_FILENO)
  160. return;
  161. (void) close(fd);
  162. if ((ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
  163. /*
  164. * Try to restore access, modification times if read it.
  165. * This is really *bad* because it will modify the status
  166. * time of the file... And of course this will affect
  167. * backup programs
  168. */
  169. #ifdef HAVE_UTIMES
  170. struct timeval utsbuf[2];
  171. utsbuf[0].tv_sec = sb->st_atime;
  172. utsbuf[1].tv_sec = sb->st_mtime;
  173. (void) utimes(name, utsbuf); /* don't care if loses */
  174. #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
  175. struct utimbuf utbuf;
  176. utbuf.actime = sb->st_atime;
  177. utbuf.modtime = sb->st_mtime;
  178. (void) utime(name, &utbuf); /* don't care if loses */
  179. #endif
  180. }
  181. }
  182. #ifndef COMPILE_ONLY
  183. /*
  184. * find type of named file
  185. */
  186. public const char *
  187. magic_file(struct magic_set *ms, const char *inname)
  188. {
  189. int fd = 0;
  190. int rv = -1;
  191. unsigned char *buf;
  192. struct stat sb;
  193. ssize_t nbytes = 0; /* number of bytes read from a datafile */
  194. /*
  195. * one extra for terminating '\0', and
  196. * some overlapping space for matches near EOF
  197. */
  198. #define SLOP (1 + sizeof(union VALUETYPE))
  199. if ((buf = malloc(HOWMANY + SLOP)) == NULL)
  200. return NULL;
  201. if (file_reset(ms) == -1)
  202. goto done;
  203. switch (file_fsmagic(ms, inname, &sb)) {
  204. case -1:
  205. goto done;
  206. case 0:
  207. break;
  208. default:
  209. rv = 0;
  210. goto done;
  211. }
  212. if (inname == NULL)
  213. fd = STDIN_FILENO;
  214. else if ((fd = open(inname, O_RDONLY|O_BINARY)) < 0) {
  215. #ifdef __CYGWIN__
  216. char *tmp = alloca(strlen(inname) + 5);
  217. (void)strcat(strcpy(tmp, inname), ".exe");
  218. if ((fd = open(tmp, O_RDONLY|O_BINARY)) < 0) {
  219. #endif
  220. /* We cannot open it, but we were able to stat it. */
  221. if (sb.st_mode & 0222)
  222. if (file_printf(ms, "writable, ") == -1)
  223. goto done;
  224. if (sb.st_mode & 0111)
  225. if (file_printf(ms, "executable, ") == -1)
  226. goto done;
  227. if (S_ISREG(sb.st_mode))
  228. if (file_printf(ms, "regular file, ") == -1)
  229. goto done;
  230. if (file_printf(ms, "no read permission") == -1)
  231. goto done;
  232. rv = 0;
  233. goto done;
  234. #ifdef __CYGWIN__
  235. }
  236. #endif
  237. }
  238. /*
  239. * try looking at the first HOWMANY bytes
  240. */
  241. if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
  242. file_error(ms, errno, "cannot read `%s'", inname);
  243. goto done;
  244. }
  245. if (nbytes == 0) {
  246. if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
  247. "application/x-empty" : "empty") == -1)
  248. goto done;
  249. } else if (nbytes == 1) {
  250. if (file_printf(ms, "very short file (no magic)") == -1)
  251. goto done;
  252. } else {
  253. (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
  254. #ifdef __EMX__
  255. switch (file_os2_apptype(ms, inname, buf, nbytes)) {
  256. case -1:
  257. goto done;
  258. case 0:
  259. break;
  260. default:
  261. rv = 0;
  262. goto done;
  263. }
  264. #endif
  265. if (file_buffer(ms, fd, buf, (size_t)nbytes) == -1)
  266. goto done;
  267. #ifdef BUILTIN_ELF
  268. if (nbytes > 5) {
  269. /*
  270. * We matched something in the file, so this *might*
  271. * be an ELF file, and the file is at least 5 bytes
  272. * long, so if it's an ELF file it has at least one
  273. * byte past the ELF magic number - try extracting
  274. * information from the ELF headers that cannot easily
  275. * be extracted with rules in the magic file.
  276. */
  277. file_tryelf(ms, fd, buf, (size_t)nbytes);
  278. }
  279. #endif
  280. }
  281. rv = 0;
  282. done:
  283. free(buf);
  284. close_and_restore(ms, inname, fd, &sb);
  285. return rv == 0 ? file_getbuffer(ms) : NULL;
  286. }
  287. public const char *
  288. magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
  289. {
  290. if (file_reset(ms) == -1)
  291. return NULL;
  292. /*
  293. * The main work is done here!
  294. * We have the file name and/or the data buffer to be identified.
  295. */
  296. if (file_buffer(ms, -1, buf, nb) == -1) {
  297. return NULL;
  298. }
  299. return file_getbuffer(ms);
  300. }
  301. #endif
  302. public const char *
  303. magic_error(struct magic_set *ms)
  304. {
  305. return ms->haderr ? ms->o.buf : NULL;
  306. }
  307. public int
  308. magic_errno(struct magic_set *ms)
  309. {
  310. return ms->haderr ? ms->error : 0;
  311. }
  312. public int
  313. magic_setflags(struct magic_set *ms, int flags)
  314. {
  315. #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
  316. if (flags & MAGIC_PRESERVE_ATIME)
  317. return -1;
  318. #endif
  319. ms->flags = flags;
  320. return 0;
  321. }