softmagic.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /*
  2. * softmagic - interpret variable magic from /etc/magic
  3. *
  4. * Copyright (c) Ian F. Darwin, 1987.
  5. * Written by Ian F. Darwin.
  6. *
  7. * This software is not subject to any license of the American Telephone
  8. * and Telegraph Company or of the Regents of the University of California.
  9. *
  10. * Permission is granted to anyone to use this software for any purpose on
  11. * any computer system, and to alter it and redistribute it freely, subject
  12. * to the following restrictions:
  13. *
  14. * 1. The author is not responsible for the consequences of use of this
  15. * software, no matter how awful, even if they arise from flaws in it.
  16. *
  17. * 2. The origin of this software must not be misrepresented, either by
  18. * explicit claim or by omission. Since few users ever read sources,
  19. * credits must appear in the documentation.
  20. *
  21. * 3. Altered versions must be plainly marked as such, and must not be
  22. * misrepresented as being the original software. Since few users
  23. * ever read sources, credits must appear in the documentation.
  24. *
  25. * 4. This notice may not be removed or altered.
  26. */
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <stdlib.h>
  30. #include <time.h>
  31. #include <sys/types.h>
  32. #include "file.h"
  33. #ifndef lint
  34. FILE_RCSID("@(#)$Id: softmagic.c,v 1.39 1999/02/14 17:16:12 christos Exp $")
  35. #endif /* lint */
  36. static int match __P((unsigned char *, int));
  37. static int mget __P((union VALUETYPE *,
  38. unsigned char *, struct magic *, int));
  39. static int mcheck __P((union VALUETYPE *, struct magic *));
  40. static int32 mprint __P((union VALUETYPE *, struct magic *));
  41. static void mdebug __P((int32, char *, int));
  42. static int mconvert __P((union VALUETYPE *, struct magic *));
  43. /*
  44. * softmagic - lookup one file in database
  45. * (already read from /etc/magic by apprentice.c).
  46. * Passed the name and FILE * of one file to be typed.
  47. */
  48. /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
  49. int
  50. softmagic(buf, nbytes)
  51. unsigned char *buf;
  52. int nbytes;
  53. {
  54. if (match(buf, nbytes))
  55. return 1;
  56. return 0;
  57. }
  58. /*
  59. * Go through the whole list, stopping if you find a match. Process all
  60. * the continuations of that match before returning.
  61. *
  62. * We support multi-level continuations:
  63. *
  64. * At any time when processing a successful top-level match, there is a
  65. * current continuation level; it represents the level of the last
  66. * successfully matched continuation.
  67. *
  68. * Continuations above that level are skipped as, if we see one, it
  69. * means that the continuation that controls them - i.e, the
  70. * lower-level continuation preceding them - failed to match.
  71. *
  72. * Continuations below that level are processed as, if we see one,
  73. * it means we've finished processing or skipping higher-level
  74. * continuations under the control of a successful or unsuccessful
  75. * lower-level continuation, and are now seeing the next lower-level
  76. * continuation and should process it. The current continuation
  77. * level reverts to the level of the one we're seeing.
  78. *
  79. * Continuations at the current level are processed as, if we see
  80. * one, there's no lower-level continuation that may have failed.
  81. *
  82. * If a continuation matches, we bump the current continuation level
  83. * so that higher-level continuations are processed.
  84. */
  85. static int
  86. match(s, nbytes)
  87. unsigned char *s;
  88. int nbytes;
  89. {
  90. int magindex = 0;
  91. int cont_level = 0;
  92. int need_separator = 0;
  93. union VALUETYPE p;
  94. static int32 *tmpoff = NULL;
  95. static size_t tmplen = 0;
  96. int32 oldoff = 0;
  97. if (tmpoff == NULL)
  98. if ((tmpoff = (int32 *) malloc(tmplen = 20)) == NULL)
  99. error("out of memory\n");
  100. for (magindex = 0; magindex < nmagic; magindex++) {
  101. /* if main entry matches, print it... */
  102. if (!mget(&p, s, &magic[magindex], nbytes) ||
  103. !mcheck(&p, &magic[magindex])) {
  104. /*
  105. * main entry didn't match,
  106. * flush its continuations
  107. */
  108. while (magindex < nmagic &&
  109. magic[magindex + 1].cont_level != 0)
  110. magindex++;
  111. continue;
  112. }
  113. tmpoff[cont_level] = mprint(&p, &magic[magindex]);
  114. /*
  115. * If we printed something, we'll need to print
  116. * a blank before we print something else.
  117. */
  118. if (magic[magindex].desc[0])
  119. need_separator = 1;
  120. /* and any continuations that match */
  121. if (++cont_level >= tmplen)
  122. if ((tmpoff = (int32 *) realloc(tmpoff,
  123. tmplen += 20)) == NULL)
  124. error("out of memory\n");
  125. while (magic[magindex+1].cont_level != 0 &&
  126. ++magindex < nmagic) {
  127. if (cont_level >= magic[magindex].cont_level) {
  128. if (cont_level > magic[magindex].cont_level) {
  129. /*
  130. * We're at the end of the level
  131. * "cont_level" continuations.
  132. */
  133. cont_level = magic[magindex].cont_level;
  134. }
  135. if (magic[magindex].flag & ADD) {
  136. oldoff=magic[magindex].offset;
  137. magic[magindex].offset += tmpoff[cont_level-1];
  138. }
  139. if (mget(&p, s, &magic[magindex], nbytes) &&
  140. mcheck(&p, &magic[magindex])) {
  141. /*
  142. * This continuation matched.
  143. * Print its message, with
  144. * a blank before it if
  145. * the previous item printed
  146. * and this item isn't empty.
  147. */
  148. /* space if previous printed */
  149. if (need_separator
  150. && (magic[magindex].nospflag == 0)
  151. && (magic[magindex].desc[0] != '\0')
  152. ) {
  153. (void) putchar(' ');
  154. need_separator = 0;
  155. }
  156. tmpoff[cont_level] = mprint(&p, &magic[magindex]);
  157. if (magic[magindex].desc[0])
  158. need_separator = 1;
  159. /*
  160. * If we see any continuations
  161. * at a higher level,
  162. * process them.
  163. */
  164. if (++cont_level >= tmplen)
  165. if ((tmpoff =
  166. (int32 *) realloc(tmpoff,
  167. tmplen += 20)) == NULL)
  168. error("out of memory\n");
  169. }
  170. if (magic[magindex].flag & ADD) {
  171. magic[magindex].offset = oldoff;
  172. }
  173. }
  174. }
  175. return 1; /* all through */
  176. }
  177. return 0; /* no match at all */
  178. }
  179. static int32
  180. mprint(p, m)
  181. union VALUETYPE *p;
  182. struct magic *m;
  183. {
  184. char *pp, *rt;
  185. uint32 v;
  186. time_t curtime;
  187. int32 t=0 ;
  188. switch (m->type) {
  189. case BYTE:
  190. v = p->b;
  191. v = signextend(m, v) & m->mask;
  192. (void) printf(m->desc, (unsigned char) v);
  193. t = m->offset + sizeof(char);
  194. break;
  195. case SHORT:
  196. case BESHORT:
  197. case LESHORT:
  198. v = p->h;
  199. v = signextend(m, v) & m->mask;
  200. (void) printf(m->desc, (unsigned short) v);
  201. t = m->offset + sizeof(short);
  202. break;
  203. case LONG:
  204. case BELONG:
  205. case LELONG:
  206. v = p->l;
  207. v = signextend(m, v) & m->mask;
  208. (void) printf(m->desc, (uint32) v);
  209. t = m->offset + sizeof(int32);
  210. break;
  211. case STRING:
  212. if (m->reln == '=') {
  213. (void) printf(m->desc, m->value.s);
  214. t = m->offset + strlen(m->value.s);
  215. }
  216. else {
  217. if (*m->value.s == '\0') {
  218. char *cp = strchr(p->s,'\n');
  219. if (cp)
  220. *cp = '\0';
  221. }
  222. (void) printf(m->desc, p->s);
  223. t = m->offset + strlen(p->s);
  224. }
  225. break;
  226. case DATE:
  227. case BEDATE:
  228. case LEDATE:
  229. curtime = p->l;
  230. pp = ctime(&curtime);
  231. if ((rt = strchr(pp, '\n')) != NULL)
  232. *rt = '\0';
  233. (void) printf(m->desc, pp);
  234. t = m->offset + sizeof(time_t);
  235. break;
  236. default:
  237. error("invalid m->type (%d) in mprint().\n", m->type);
  238. /*NOTREACHED*/
  239. }
  240. return(t);
  241. }
  242. /*
  243. * Convert the byte order of the data we are looking at
  244. */
  245. static int
  246. mconvert(p, m)
  247. union VALUETYPE *p;
  248. struct magic *m;
  249. {
  250. switch (m->type) {
  251. case BYTE:
  252. case SHORT:
  253. case LONG:
  254. case DATE:
  255. return 1;
  256. case STRING:
  257. {
  258. char *ptr;
  259. /* Null terminate and eat the return */
  260. p->s[sizeof(p->s) - 1] = '\0';
  261. if ((ptr = strchr(p->s, '\n')) != NULL)
  262. *ptr = '\0';
  263. return 1;
  264. }
  265. case BESHORT:
  266. p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
  267. return 1;
  268. case BELONG:
  269. case BEDATE:
  270. p->l = (int32)
  271. ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
  272. return 1;
  273. case LESHORT:
  274. p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
  275. return 1;
  276. case LELONG:
  277. case LEDATE:
  278. p->l = (int32)
  279. ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
  280. return 1;
  281. default:
  282. error("invalid type %d in mconvert().\n", m->type);
  283. return 0;
  284. }
  285. }
  286. static void
  287. mdebug(offset, str, len)
  288. int32 offset;
  289. char *str;
  290. int len;
  291. {
  292. (void) fprintf(stderr, "mget @%d: ", offset);
  293. showstr(stderr, (char *) str, len);
  294. (void) fputc('\n', stderr);
  295. (void) fputc('\n', stderr);
  296. }
  297. static int
  298. mget(p, s, m, nbytes)
  299. union VALUETYPE* p;
  300. unsigned char *s;
  301. struct magic *m;
  302. int nbytes;
  303. {
  304. int32 offset = m->offset;
  305. if (offset + sizeof(union VALUETYPE) <= nbytes)
  306. memcpy(p, s + offset, sizeof(union VALUETYPE));
  307. else {
  308. /*
  309. * the usefulness of padding with zeroes eludes me, it
  310. * might even cause problems
  311. */
  312. int32 have = nbytes - offset;
  313. memset(p, 0, sizeof(union VALUETYPE));
  314. if (have > 0)
  315. memcpy(p, s + offset, have);
  316. }
  317. if (debug) {
  318. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  319. mdump(m);
  320. }
  321. if (m->flag & INDIR) {
  322. switch (m->in.type) {
  323. case BYTE:
  324. offset = p->b + m->in.offset;
  325. break;
  326. case BESHORT:
  327. offset = (short)((p->hs[0]<<8)|(p->hs[1]))+
  328. m->in.offset;
  329. break;
  330. case LESHORT:
  331. offset = (short)((p->hs[1]<<8)|(p->hs[0]))+
  332. m->in.offset;
  333. break;
  334. case SHORT:
  335. offset = p->h + m->in.offset;
  336. break;
  337. case BELONG:
  338. offset = (int32)((p->hl[0]<<24)|(p->hl[1]<<16)|
  339. (p->hl[2]<<8)|(p->hl[3]))+
  340. m->in.offset;
  341. break;
  342. case LELONG:
  343. offset = (int32)((p->hl[3]<<24)|(p->hl[2]<<16)|
  344. (p->hl[1]<<8)|(p->hl[0]))+
  345. m->in.offset;
  346. break;
  347. case LONG:
  348. offset = p->l + m->in.offset;
  349. break;
  350. }
  351. if (offset + sizeof(union VALUETYPE) > nbytes)
  352. return 0;
  353. memcpy(p, s + offset, sizeof(union VALUETYPE));
  354. if (debug) {
  355. mdebug(offset, (char *) p, sizeof(union VALUETYPE));
  356. mdump(m);
  357. }
  358. }
  359. if (!mconvert(p, m))
  360. return 0;
  361. return 1;
  362. }
  363. static int
  364. mcheck(p, m)
  365. union VALUETYPE* p;
  366. struct magic *m;
  367. {
  368. register uint32 l = m->value.l;
  369. register uint32 v;
  370. int matched;
  371. if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
  372. fprintf(stderr, "BOINK");
  373. return 1;
  374. }
  375. switch (m->type) {
  376. case BYTE:
  377. v = p->b;
  378. break;
  379. case SHORT:
  380. case BESHORT:
  381. case LESHORT:
  382. v = p->h;
  383. break;
  384. case LONG:
  385. case BELONG:
  386. case LELONG:
  387. case DATE:
  388. case BEDATE:
  389. case LEDATE:
  390. v = p->l;
  391. break;
  392. case STRING:
  393. l = 0;
  394. /* What we want here is:
  395. * v = strncmp(m->value.s, p->s, m->vallen);
  396. * but ignoring any nulls. bcmp doesn't give -/+/0
  397. * and isn't universally available anyway.
  398. */
  399. v = 0;
  400. {
  401. register unsigned char *a = (unsigned char*)m->value.s;
  402. register unsigned char *b = (unsigned char*)p->s;
  403. register int len = m->vallen;
  404. while (--len >= 0)
  405. if ((v = *b++ - *a++) != '\0')
  406. break;
  407. }
  408. break;
  409. default:
  410. error("invalid type %d in mcheck().\n", m->type);
  411. return 0;/*NOTREACHED*/
  412. }
  413. v = signextend(m, v) & m->mask;
  414. switch (m->reln) {
  415. case 'x':
  416. if (debug)
  417. (void) fprintf(stderr, "%u == *any* = 1\n", v);
  418. matched = 1;
  419. break;
  420. case '!':
  421. matched = v != l;
  422. if (debug)
  423. (void) fprintf(stderr, "%u != %u = %d\n",
  424. v, l, matched);
  425. break;
  426. case '=':
  427. matched = v == l;
  428. if (debug)
  429. (void) fprintf(stderr, "%u == %u = %d\n",
  430. v, l, matched);
  431. break;
  432. case '>':
  433. if (m->flag & UNSIGNED) {
  434. matched = v > l;
  435. if (debug)
  436. (void) fprintf(stderr, "%u > %u = %d\n",
  437. v, l, matched);
  438. }
  439. else {
  440. matched = (int32) v > (int32) l;
  441. if (debug)
  442. (void) fprintf(stderr, "%d > %d = %d\n",
  443. v, l, matched);
  444. }
  445. break;
  446. case '<':
  447. if (m->flag & UNSIGNED) {
  448. matched = v < l;
  449. if (debug)
  450. (void) fprintf(stderr, "%u < %u = %d\n",
  451. v, l, matched);
  452. }
  453. else {
  454. matched = (int32) v < (int32) l;
  455. if (debug)
  456. (void) fprintf(stderr, "%d < %d = %d\n",
  457. v, l, matched);
  458. }
  459. break;
  460. case '&':
  461. matched = (v & l) == l;
  462. if (debug)
  463. (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
  464. v, l, l, matched);
  465. break;
  466. case '^':
  467. matched = (v & l) != l;
  468. if (debug)
  469. (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
  470. v, l, l, matched);
  471. break;
  472. default:
  473. matched = 0;
  474. error("mcheck: can't happen: invalid relation %d.\n", m->reln);
  475. break;/*NOTREACHED*/
  476. }
  477. return matched;
  478. }