magic.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. #include <fcntl.h> /* for open() */
  37. #ifdef QUICK
  38. #include <sys/mman.h>
  39. #endif
  40. #if defined(HAVE_UTIMES)
  41. # include <sys/time.h>
  42. #elif defined(HAVE_UTIME)
  43. # if defined(HAVE_SYS_UTIME_H)
  44. # include <sys/utime.h>
  45. # elif defined(HAVE_UTIME_H)
  46. # include <utime.h>
  47. # endif
  48. #endif
  49. #ifdef HAVE_UNISTD_H
  50. #include <unistd.h> /* for read() */
  51. #endif
  52. #ifdef HAVE_LOCALE_H
  53. #include <locale.h>
  54. #endif
  55. #include <netinet/in.h> /* for byte swapping */
  56. #include "patchlevel.h"
  57. #ifndef lint
  58. FILE_RCSID("@(#)$Id: magic.c,v 1.24 2004/09/27 15:28:37 christos Exp $")
  59. #endif /* lint */
  60. #ifdef __EMX__
  61. private char *apptypeName = NULL;
  62. protected int file_os2_apptype(struct magic_set *ms, const char *fn,
  63. const void *buf, size_t nb);
  64. #endif /* __EMX__ */
  65. private void free_mlist(struct mlist *);
  66. private void close_and_restore(const struct magic_set *, const char *, int,
  67. const struct stat *);
  68. public struct magic_set *
  69. magic_open(int flags)
  70. {
  71. struct magic_set *ms;
  72. if ((ms = malloc(sizeof(struct magic_set))) == NULL)
  73. return NULL;
  74. if (magic_setflags(ms, flags) == -1) {
  75. errno = EINVAL;
  76. goto free1;
  77. }
  78. ms->o.ptr = ms->o.buf = malloc(ms->o.size = 1024);
  79. if (ms->o.buf == NULL)
  80. goto free1;
  81. ms->o.pbuf = malloc(ms->o.psize = 1024);
  82. if (ms->o.pbuf == NULL)
  83. goto free2;
  84. ms->c.off = malloc((ms->c.len = 10) * sizeof(*ms->c.off));
  85. if (ms->c.off == NULL)
  86. goto free3;
  87. ms->o.len = 0;
  88. ms->haderr = 0;
  89. ms->error = -1;
  90. ms->mlist = NULL;
  91. return ms;
  92. free3:
  93. free(ms->o.pbuf);
  94. free2:
  95. free(ms->o.buf);
  96. free1:
  97. free(ms);
  98. return NULL;
  99. }
  100. private void
  101. free_mlist(struct mlist *mlist)
  102. {
  103. struct mlist *ml;
  104. if (mlist == NULL)
  105. return;
  106. for (ml = mlist->next; ml != mlist;) {
  107. struct mlist *next = ml->next;
  108. struct magic *mg = ml->magic;
  109. file_delmagic(mg, ml->mapped, ml->nmagic);
  110. free(ml);
  111. ml = next;
  112. }
  113. free(ml);
  114. }
  115. public void
  116. magic_close(ms)
  117. struct magic_set *ms;
  118. {
  119. free_mlist(ms->mlist);
  120. free(ms->o.pbuf);
  121. free(ms->o.buf);
  122. free(ms->c.off);
  123. free(ms);
  124. }
  125. /*
  126. * load a magic file
  127. */
  128. public int
  129. magic_load(struct magic_set *ms, const char *magicfile)
  130. {
  131. struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
  132. if (ml) {
  133. free_mlist(ms->mlist);
  134. ms->mlist = ml;
  135. return 0;
  136. }
  137. return -1;
  138. }
  139. public int
  140. magic_compile(struct magic_set *ms, const char *magicfile)
  141. {
  142. struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
  143. free_mlist(ml);
  144. return ml ? 0 : -1;
  145. }
  146. public int
  147. magic_check(struct magic_set *ms, const char *magicfile)
  148. {
  149. struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK);
  150. free_mlist(ml);
  151. return ml ? 0 : -1;
  152. }
  153. private void
  154. close_and_restore(const struct magic_set *ms, const char *name, int fd,
  155. const struct stat *sb)
  156. {
  157. (void) close(fd);
  158. if (fd != STDIN_FILENO && (ms->flags & MAGIC_PRESERVE_ATIME) != 0) {
  159. /*
  160. * Try to restore access, modification times if read it.
  161. * This is really *bad* because it will modify the status
  162. * time of the file... And of course this will affect
  163. * backup programs
  164. */
  165. #ifdef HAVE_UTIMES
  166. struct timeval utsbuf[2];
  167. utsbuf[0].tv_sec = sb->st_atime;
  168. utsbuf[1].tv_sec = sb->st_mtime;
  169. (void) utimes(name, utsbuf); /* don't care if loses */
  170. #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
  171. struct utimbuf utbuf;
  172. utbuf.actime = sb->st_atime;
  173. utbuf.modtime = sb->st_mtime;
  174. (void) utime(name, &utbuf); /* don't care if loses */
  175. #endif
  176. }
  177. }
  178. #ifndef COMPILE_ONLY
  179. /*
  180. * find type of named file
  181. */
  182. public const char *
  183. magic_file(struct magic_set *ms, const char *inname)
  184. {
  185. int fd = 0;
  186. unsigned char buf[HOWMANY+1]; /* one extra for terminating '\0' */
  187. struct stat sb;
  188. ssize_t nbytes = 0; /* number of bytes read from a datafile */
  189. if (file_reset(ms) == -1)
  190. return NULL;
  191. switch (file_fsmagic(ms, inname, &sb)) {
  192. case -1:
  193. return NULL;
  194. case 0:
  195. break;
  196. default:
  197. return file_getbuffer(ms);
  198. }
  199. #ifndef STDIN_FILENO
  200. #define STDIN_FILENO 0
  201. #endif
  202. if (inname == NULL)
  203. fd = STDIN_FILENO;
  204. else if ((fd = open(inname, O_RDONLY)) < 0) {
  205. /* We cannot open it, but we were able to stat it. */
  206. if (sb.st_mode & 0222)
  207. if (file_printf(ms, "writable, ") == -1)
  208. return NULL;
  209. if (sb.st_mode & 0111)
  210. if (file_printf(ms, "executable, ") == -1)
  211. return NULL;
  212. if (S_ISREG(sb.st_mode))
  213. if (file_printf(ms, "regular file, ") == -1)
  214. return NULL;
  215. if (file_printf(ms, "no read permission") == -1)
  216. return NULL;
  217. return file_getbuffer(ms);
  218. }
  219. /*
  220. * try looking at the first HOWMANY bytes
  221. */
  222. if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
  223. file_error(ms, errno, "cannot read `%s'", inname);
  224. goto done;
  225. }
  226. if (nbytes == 0) {
  227. if (file_printf(ms, (ms->flags & MAGIC_MIME) ?
  228. "application/x-empty" : "empty") == -1)
  229. goto done;
  230. goto gotit;
  231. } else if (nbytes == 1) {
  232. if (file_printf(ms, "very short file (no magic)") == -1)
  233. goto done;
  234. goto gotit;
  235. } else {
  236. buf[nbytes] = '\0'; /* null-terminate it */
  237. #ifdef __EMX__
  238. switch (file_os2_apptype(ms, inname, buf, nbytes)) {
  239. case -1:
  240. goto done;
  241. case 0:
  242. break;
  243. default:
  244. goto gotit;
  245. }
  246. #endif
  247. if (file_buffer(ms, buf, (size_t)nbytes) == -1)
  248. goto done;
  249. #ifdef BUILTIN_ELF
  250. if (nbytes > 5) {
  251. /*
  252. * We matched something in the file, so this *might*
  253. * be an ELF file, and the file is at least 5 bytes
  254. * long, so if it's an ELF file it has at least one
  255. * byte past the ELF magic number - try extracting
  256. * information from the ELF headers that cannot easily
  257. * be extracted with rules in the magic file.
  258. */
  259. file_tryelf(ms, fd, buf, (size_t)nbytes);
  260. }
  261. #endif
  262. }
  263. gotit:
  264. close_and_restore(ms, inname, fd, &sb);
  265. return file_getbuffer(ms);
  266. done:
  267. close_and_restore(ms, inname, fd, &sb);
  268. return NULL;
  269. }
  270. public const char *
  271. magic_buffer(struct magic_set *ms, const void *buf, size_t nb)
  272. {
  273. if (file_reset(ms) == -1)
  274. return NULL;
  275. /*
  276. * The main work is done here!
  277. * We have the file name and/or the data buffer to be identified.
  278. */
  279. if (file_buffer(ms, buf, nb) == -1) {
  280. return NULL;
  281. }
  282. return file_getbuffer(ms);
  283. }
  284. #endif
  285. public const char *
  286. magic_error(struct magic_set *ms)
  287. {
  288. return ms->haderr ? ms->o.buf : NULL;
  289. }
  290. public int
  291. magic_errno(struct magic_set *ms)
  292. {
  293. return ms->haderr ? ms->error : 0;
  294. }
  295. public int
  296. magic_setflags(struct magic_set *ms, int flags)
  297. {
  298. #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
  299. if (flags & MAGIC_PRESERVE_ATIME)
  300. return -1;
  301. #endif
  302. ms->flags = flags;
  303. return 0;
  304. }