apprentice.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410
  1. /*
  2. * Copyright (c) Ian F. Darwin 1986-1995.
  3. * Software written by Ian F. Darwin and others;
  4. * maintained 1995-present by Christos Zoulas and others.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice immediately at the beginning of the file, without modification,
  11. * this list of conditions, and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  20. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. /*
  29. * apprentice - make one pass through /etc/magic, learning its secrets.
  30. */
  31. #include "file.h"
  32. #include "magic.h"
  33. #include <stdlib.h>
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include <fcntl.h>
  40. #include <sys/stat.h>
  41. #include <sys/param.h>
  42. #ifdef QUICK
  43. #include <sys/mman.h>
  44. #endif
  45. #ifndef lint
  46. FILE_RCSID("@(#)$Id: apprentice.c,v 1.87 2006/03/02 22:08:57 christos Exp $")
  47. #endif /* lint */
  48. #define EATAB {while (isascii((unsigned char) *l) && \
  49. isspace((unsigned char) *l)) ++l;}
  50. #define LOWCASE(l) (isupper((unsigned char) (l)) ? \
  51. tolower((unsigned char) (l)) : (l))
  52. /*
  53. * Work around a bug in headers on Digital Unix.
  54. * At least confirmed for: OSF1 V4.0 878
  55. */
  56. #if defined(__osf__) && defined(__DECC)
  57. #ifdef MAP_FAILED
  58. #undef MAP_FAILED
  59. #endif
  60. #endif
  61. #ifndef MAP_FAILED
  62. #define MAP_FAILED (void *) -1
  63. #endif
  64. #ifndef MAP_FILE
  65. #define MAP_FILE 0
  66. #endif
  67. #ifndef MAXPATHLEN
  68. #define MAXPATHLEN 1024
  69. #endif
  70. #define IS_PLAINSTRING(t) ((t) == FILE_STRING || (t) == FILE_PSTRING || \
  71. (t) == FILE_BESTRING16 || (t) == FILE_LESTRING16)
  72. #define IS_STRING(t) (IS_PLAINSTRING(t) || (t) == FILE_REGEX || \
  73. (t) == FILE_SEARCH)
  74. struct magic_entry {
  75. struct magic *mp;
  76. uint32_t cont_count;
  77. uint32_t max_count;
  78. };
  79. private int getvalue(struct magic_set *ms, struct magic *, const char **);
  80. private int hextoint(int);
  81. private const char *getstr(struct magic_set *, const char *, char *, int,
  82. int *);
  83. private int parse(struct magic_set *, struct magic_entry **, uint32_t *,
  84. const char *, int);
  85. private void eatsize(const char **);
  86. private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);
  87. private size_t apprentice_magic_strength(const struct magic *);
  88. private int apprentice_sort(const void *, const void *);
  89. private int apprentice_file(struct magic_set *, struct magic **, uint32_t *,
  90. const char *, int);
  91. private void byteswap(struct magic *, uint32_t);
  92. private void bs1(struct magic *);
  93. private uint16_t swap2(uint16_t);
  94. private uint32_t swap4(uint32_t);
  95. private char *mkdbname(const char *, char *, size_t, int);
  96. private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
  97. const char *);
  98. private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
  99. const char *);
  100. private int check_format(struct magic_set *, struct magic *);
  101. private size_t maxmagic = 0;
  102. private size_t magicsize = sizeof(struct magic);
  103. #ifdef COMPILE_ONLY
  104. int main(int, char *[]);
  105. int
  106. main(int argc, char *argv[])
  107. {
  108. int ret;
  109. struct magic_set *ms;
  110. char *progname;
  111. if ((progname = strrchr(argv[0], '/')) != NULL)
  112. progname++;
  113. else
  114. progname = argv[0];
  115. if (argc != 2) {
  116. (void)fprintf(stderr, "Usage: %s file\n", progname);
  117. return 1;
  118. }
  119. if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
  120. (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
  121. return 1;
  122. }
  123. ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
  124. if (ret == 1)
  125. (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
  126. magic_close(ms);
  127. return ret;
  128. }
  129. #endif /* COMPILE_ONLY */
  130. /*
  131. * Handle one file.
  132. */
  133. private int
  134. apprentice_1(struct magic_set *ms, const char *fn, int action,
  135. struct mlist *mlist)
  136. {
  137. struct magic *magic = NULL;
  138. uint32_t nmagic = 0;
  139. struct mlist *ml;
  140. int rv = -1;
  141. int mapped;
  142. if (magicsize != FILE_MAGICSIZE) {
  143. file_error(ms, 0, "magic element size %lu != %lu",
  144. (unsigned long)sizeof(*magic),
  145. (unsigned long)FILE_MAGICSIZE);
  146. return -1;
  147. }
  148. if (action == FILE_COMPILE) {
  149. rv = apprentice_file(ms, &magic, &nmagic, fn, action);
  150. if (rv != 0)
  151. return -1;
  152. rv = apprentice_compile(ms, &magic, &nmagic, fn);
  153. free(magic);
  154. return rv;
  155. }
  156. #ifndef COMPILE_ONLY
  157. if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
  158. if (ms->flags & MAGIC_CHECK)
  159. file_magwarn(ms, "using regular magic file `%s'", fn);
  160. rv = apprentice_file(ms, &magic, &nmagic, fn, action);
  161. if (rv != 0)
  162. return -1;
  163. mapped = 0;
  164. }
  165. if (rv == -1)
  166. return rv;
  167. mapped = rv;
  168. if (magic == NULL || nmagic == 0) {
  169. file_delmagic(magic, mapped, nmagic);
  170. return -1;
  171. }
  172. if ((ml = malloc(sizeof(*ml))) == NULL) {
  173. file_delmagic(magic, mapped, nmagic);
  174. file_oomem(ms);
  175. return -1;
  176. }
  177. ml->magic = magic;
  178. ml->nmagic = nmagic;
  179. ml->mapped = mapped;
  180. mlist->prev->next = ml;
  181. ml->prev = mlist->prev;
  182. ml->next = mlist;
  183. mlist->prev = ml;
  184. return 0;
  185. #endif /* COMPILE_ONLY */
  186. }
  187. protected void
  188. file_delmagic(struct magic *p, int type, size_t entries)
  189. {
  190. if (p == NULL)
  191. return;
  192. switch (type) {
  193. case 2:
  194. p--;
  195. (void)munmap((void *)p, sizeof(*p) * (entries + 1));
  196. break;
  197. case 1:
  198. p--;
  199. /*FALLTHROUGH*/
  200. case 0:
  201. free(p);
  202. break;
  203. default:
  204. abort();
  205. }
  206. }
  207. /* const char *fn: list of magic files */
  208. protected struct mlist *
  209. file_apprentice(struct magic_set *ms, const char *fn, int action)
  210. {
  211. char *p, *mfn, *afn = NULL;
  212. int file_err, errs = -1;
  213. struct mlist *mlist;
  214. if (fn == NULL)
  215. fn = getenv("MAGIC");
  216. if (fn == NULL)
  217. fn = MAGIC;
  218. if ((fn = mfn = strdup(fn)) == NULL) {
  219. file_oomem(ms);
  220. return NULL;
  221. }
  222. if ((mlist = malloc(sizeof(*mlist))) == NULL) {
  223. free(mfn);
  224. file_oomem(ms);
  225. return NULL;
  226. }
  227. mlist->next = mlist->prev = mlist;
  228. while (fn) {
  229. p = strchr(fn, PATHSEP);
  230. if (p)
  231. *p++ = '\0';
  232. if (*fn == '\0')
  233. break;
  234. if (ms->flags & MAGIC_MIME) {
  235. if ((afn = malloc(strlen(fn) + 5 + 1)) == NULL) {
  236. free(mfn);
  237. free(mlist);
  238. file_oomem(ms);
  239. return NULL;
  240. }
  241. (void)strcpy(afn, fn);
  242. (void)strcat(afn, ".mime");
  243. fn = afn;
  244. }
  245. file_err = apprentice_1(ms, fn, action, mlist);
  246. if (file_err > errs)
  247. errs = file_err;
  248. if (afn) {
  249. free(afn);
  250. afn = NULL;
  251. }
  252. fn = p;
  253. }
  254. if (errs == -1) {
  255. free(mfn);
  256. free(mlist);
  257. mlist = NULL;
  258. file_error(ms, 0, "could not find any magic files!");
  259. return NULL;
  260. }
  261. free(mfn);
  262. return mlist;
  263. }
  264. private size_t
  265. apprentice_magic_strength(const struct magic *m)
  266. {
  267. switch (m->type) {
  268. case FILE_BYTE:
  269. return 1;
  270. case FILE_SHORT:
  271. case FILE_LESHORT:
  272. case FILE_BESHORT:
  273. return 2;
  274. case FILE_LONG:
  275. case FILE_LELONG:
  276. case FILE_BELONG:
  277. case FILE_MELONG:
  278. return 4;
  279. case FILE_PSTRING:
  280. case FILE_STRING:
  281. case FILE_REGEX:
  282. case FILE_BESTRING16:
  283. case FILE_LESTRING16:
  284. case FILE_SEARCH:
  285. return m->vallen;
  286. case FILE_DATE:
  287. case FILE_LEDATE:
  288. case FILE_BEDATE:
  289. case FILE_MEDATE:
  290. return 4;
  291. case FILE_LDATE:
  292. case FILE_LELDATE:
  293. case FILE_BELDATE:
  294. case FILE_MELDATE:
  295. return 8;
  296. default:
  297. return 0;
  298. }
  299. }
  300. private int
  301. apprentice_sort(const void *a, const void *b)
  302. {
  303. const struct magic_entry *ma = a;
  304. const struct magic_entry *mb = b;
  305. size_t sa = apprentice_magic_strength(ma->mp);
  306. size_t sb = apprentice_magic_strength(mb->mp);
  307. if (sa == sb)
  308. return 0;
  309. else if (sa > sb)
  310. return -1;
  311. else
  312. return 1;
  313. }
  314. /*
  315. * parse from a file
  316. * const char *fn: name of magic file
  317. */
  318. private int
  319. apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
  320. const char *fn, int action)
  321. {
  322. private const char hdr[] =
  323. "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
  324. FILE *f;
  325. char line[BUFSIZ+1];
  326. int errs = 0;
  327. struct magic_entry *marray;
  328. uint32_t marraycount, i, mentrycount;
  329. f = fopen(ms->file = fn, "r");
  330. if (f == NULL) {
  331. if (errno != ENOENT)
  332. file_error(ms, errno, "cannot read magic file `%s'",
  333. fn);
  334. return -1;
  335. }
  336. maxmagic = MAXMAGIS;
  337. if ((marray = malloc(maxmagic * sizeof(*marray))) == NULL) {
  338. (void)fclose(f);
  339. file_oomem(ms);
  340. return -1;
  341. }
  342. marraycount = 0;
  343. /* print silly verbose header for USG compat. */
  344. if (action == FILE_CHECK)
  345. (void)fprintf(stderr, "%s\n", hdr);
  346. /* parse it */
  347. for (ms->line = 1; fgets(line, BUFSIZ, f) != NULL; ms->line++) {
  348. size_t len;
  349. if (line[0] == '#') /* comment, do not parse */
  350. continue;
  351. len = strlen(line);
  352. if (len < 2) /* null line, garbage, etc */
  353. continue;
  354. if (line[len - 1] == '\n')
  355. line[len - 1] = '\0'; /* delete newline */
  356. if (parse(ms, &marray, &marraycount, line, action) != 0)
  357. errs++;
  358. }
  359. (void)fclose(f);
  360. if (errs)
  361. goto out;
  362. #ifndef NOORDER
  363. qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
  364. #endif
  365. for (i = 0, mentrycount = 0; i < marraycount; i++)
  366. mentrycount += marray[i].cont_count;
  367. if ((*magicp = malloc(sizeof(**magicp) * mentrycount)) == NULL) {
  368. file_oomem(ms);
  369. errs++;
  370. goto out;
  371. }
  372. mentrycount = 0;
  373. for (i = 0; i < marraycount; i++) {
  374. (void)memcpy(*magicp + mentrycount, marray[i].mp,
  375. marray[i].cont_count * sizeof(**magicp));
  376. mentrycount += marray[i].cont_count;
  377. }
  378. out:
  379. for (i = 0; i < marraycount; i++)
  380. free(marray[i].mp);
  381. free(marray);
  382. if (errs) {
  383. *magicp = NULL;
  384. *nmagicp = 0;
  385. return errs;
  386. } else {
  387. *nmagicp = mentrycount;
  388. return 0;
  389. }
  390. }
  391. /*
  392. * extend the sign bit if the comparison is to be signed
  393. */
  394. protected uint32_t
  395. file_signextend(struct magic_set *ms, struct magic *m, uint32_t v)
  396. {
  397. if (!(m->flag & UNSIGNED))
  398. switch(m->type) {
  399. /*
  400. * Do not remove the casts below. They are
  401. * vital. When later compared with the data,
  402. * the sign extension must have happened.
  403. */
  404. case FILE_BYTE:
  405. v = (char) v;
  406. break;
  407. case FILE_SHORT:
  408. case FILE_BESHORT:
  409. case FILE_LESHORT:
  410. v = (short) v;
  411. break;
  412. case FILE_DATE:
  413. case FILE_BEDATE:
  414. case FILE_LEDATE:
  415. case FILE_MEDATE:
  416. case FILE_LDATE:
  417. case FILE_BELDATE:
  418. case FILE_LELDATE:
  419. case FILE_MELDATE:
  420. case FILE_LONG:
  421. case FILE_BELONG:
  422. case FILE_LELONG:
  423. case FILE_MELONG:
  424. v = (int32_t) v;
  425. break;
  426. case FILE_STRING:
  427. case FILE_PSTRING:
  428. case FILE_BESTRING16:
  429. case FILE_LESTRING16:
  430. case FILE_REGEX:
  431. case FILE_SEARCH:
  432. break;
  433. default:
  434. if (ms->flags & MAGIC_CHECK)
  435. file_magwarn(ms, "cannot happen: m->type=%d\n",
  436. m->type);
  437. return ~0U;
  438. }
  439. return v;
  440. }
  441. /*
  442. * parse one line from magic file, put into magic[index++] if valid
  443. */
  444. private int
  445. parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
  446. const char *line, int action)
  447. {
  448. int i = 0;
  449. struct magic_entry *me;
  450. struct magic *m;
  451. const char *l = line;
  452. char *t;
  453. private const char *fops = FILE_OPS;
  454. uint32_t val;
  455. uint32_t cont_level, cont_count;
  456. cont_level = 0;
  457. while (*l == '>') {
  458. ++l; /* step over */
  459. cont_level++;
  460. }
  461. #define ALLOC_CHUNK (size_t)10
  462. #define ALLOC_INCR (size_t)200
  463. if (cont_level != 0) {
  464. if (*nmentryp == 0) {
  465. file_error(ms, 0, "No current entry for continuation");
  466. return -1;
  467. }
  468. me = &(*mentryp)[*nmentryp - 1];
  469. if (me->cont_count == me->max_count) {
  470. struct magic *nm;
  471. size_t cnt = me->max_count + ALLOC_CHUNK;
  472. if ((nm = realloc(me->mp, sizeof(*nm) * cnt)) == NULL) {
  473. file_oomem(ms);
  474. return -1;
  475. }
  476. me->mp = m = nm;
  477. me->max_count = cnt;
  478. }
  479. m = &me->mp[me->cont_count++];
  480. memset(m, 0, sizeof(*m));
  481. m->cont_level = cont_level;
  482. } else {
  483. if (*nmentryp == maxmagic) {
  484. struct magic_entry *mp;
  485. maxmagic += ALLOC_INCR;
  486. if ((mp = realloc(*mentryp, sizeof(*mp) * maxmagic)) ==
  487. NULL) {
  488. file_oomem(ms);
  489. return -1;
  490. }
  491. (void)memset(&mp[*nmentryp], 0, sizeof(*mp) *
  492. ALLOC_INCR);
  493. *mentryp = mp;
  494. }
  495. me = &(*mentryp)[*nmentryp];
  496. if (me->mp == NULL) {
  497. if ((m = malloc(sizeof(*m) * ALLOC_CHUNK)) == NULL) {
  498. file_oomem(ms);
  499. return -1;
  500. }
  501. me->mp = m;
  502. me->max_count = ALLOC_CHUNK;
  503. } else
  504. m = me->mp;
  505. memset(m, 0, sizeof(*m));
  506. m->cont_level = 0;
  507. me->cont_count = 1;
  508. }
  509. if (m->cont_level != 0 && *l == '&') {
  510. ++l; /* step over */
  511. m->flag |= OFFADD;
  512. }
  513. if (m->cont_level != 0 && *l == '(') {
  514. ++l; /* step over */
  515. m->flag |= INDIR;
  516. if (m->flag & OFFADD)
  517. m->flag = (m->flag & ~OFFADD) | INDIROFFADD;
  518. }
  519. if (m->cont_level != 0 && *l == '&') {
  520. ++l; /* step over */
  521. m->flag |= OFFADD;
  522. }
  523. /* get offset, then skip over it */
  524. m->offset = (uint32_t)strtoul(l, &t, 0);
  525. if (l == t)
  526. if (ms->flags & MAGIC_CHECK)
  527. file_magwarn(ms, "offset `%s' invalid", l);
  528. l = t;
  529. if (m->flag & INDIR) {
  530. m->in_type = FILE_LONG;
  531. m->in_offset = 0;
  532. /*
  533. * read [.lbs][+-]nnnnn)
  534. */
  535. if (*l == '.') {
  536. l++;
  537. switch (*l) {
  538. case 'l':
  539. m->in_type = FILE_LELONG;
  540. break;
  541. case 'L':
  542. m->in_type = FILE_BELONG;
  543. break;
  544. case 'm':
  545. m->in_type = FILE_MELONG;
  546. break;
  547. case 'h':
  548. case 's':
  549. m->in_type = FILE_LESHORT;
  550. break;
  551. case 'H':
  552. case 'S':
  553. m->in_type = FILE_BESHORT;
  554. break;
  555. case 'c':
  556. case 'b':
  557. case 'C':
  558. case 'B':
  559. m->in_type = FILE_BYTE;
  560. break;
  561. default:
  562. if (ms->flags & MAGIC_CHECK)
  563. file_magwarn(ms,
  564. "indirect offset type `%c' invalid",
  565. *l);
  566. break;
  567. }
  568. l++;
  569. }
  570. if (*l == '~') {
  571. m->in_op |= FILE_OPINVERSE;
  572. l++;
  573. }
  574. switch (*l) {
  575. case '&':
  576. m->in_op |= FILE_OPAND;
  577. l++;
  578. break;
  579. case '|':
  580. m->in_op |= FILE_OPOR;
  581. l++;
  582. break;
  583. case '^':
  584. m->in_op |= FILE_OPXOR;
  585. l++;
  586. break;
  587. case '+':
  588. m->in_op |= FILE_OPADD;
  589. l++;
  590. break;
  591. case '-':
  592. m->in_op |= FILE_OPMINUS;
  593. l++;
  594. break;
  595. case '*':
  596. m->in_op |= FILE_OPMULTIPLY;
  597. l++;
  598. break;
  599. case '/':
  600. m->in_op |= FILE_OPDIVIDE;
  601. l++;
  602. break;
  603. case '%':
  604. m->in_op |= FILE_OPMODULO;
  605. l++;
  606. break;
  607. }
  608. if (*l == '(') {
  609. m->in_op |= FILE_OPINDIRECT;
  610. l++;
  611. }
  612. if (isdigit((unsigned char)*l) || *l == '-') {
  613. m->in_offset = (int32_t)strtol(l, &t, 0);
  614. l = t;
  615. }
  616. if (*l++ != ')' ||
  617. ((m->in_op & FILE_OPINDIRECT) && *l++ != ')'))
  618. if (ms->flags & MAGIC_CHECK)
  619. file_magwarn(ms,
  620. "missing ')' in indirect offset");
  621. }
  622. while (isascii((unsigned char)*l) && isdigit((unsigned char)*l))
  623. ++l;
  624. EATAB;
  625. #define NBYTE 4
  626. #define NSHORT 5
  627. #define NLONG 4
  628. #define NSTRING 6
  629. #define NDATE 4
  630. #define NBESHORT 7
  631. #define NBELONG 6
  632. #define NBEDATE 6
  633. #define NLESHORT 7
  634. #define NLELONG 6
  635. #define NMELONG 6
  636. #define NLEDATE 6
  637. #define NMEDATE 6
  638. #define NPSTRING 7
  639. #define NLDATE 5
  640. #define NBELDATE 7
  641. #define NLELDATE 7
  642. #define NMELDATE 7
  643. #define NREGEX 5
  644. #define NBESTRING16 10
  645. #define NLESTRING16 10
  646. #define NSEARCH 6
  647. if (*l == 'u') {
  648. ++l;
  649. m->flag |= UNSIGNED;
  650. }
  651. /* get type, skip it */
  652. if (strncmp(l, "char", NBYTE)==0) { /* HP/UX compat */
  653. m->type = FILE_BYTE;
  654. l += NBYTE;
  655. } else if (strncmp(l, "byte", NBYTE)==0) {
  656. m->type = FILE_BYTE;
  657. l += NBYTE;
  658. } else if (strncmp(l, "short", NSHORT)==0) {
  659. m->type = FILE_SHORT;
  660. l += NSHORT;
  661. } else if (strncmp(l, "long", NLONG)==0) {
  662. m->type = FILE_LONG;
  663. l += NLONG;
  664. } else if (strncmp(l, "string", NSTRING)==0) {
  665. m->type = FILE_STRING;
  666. l += NSTRING;
  667. } else if (strncmp(l, "date", NDATE)==0) {
  668. m->type = FILE_DATE;
  669. l += NDATE;
  670. } else if (strncmp(l, "beshort", NBESHORT)==0) {
  671. m->type = FILE_BESHORT;
  672. l += NBESHORT;
  673. } else if (strncmp(l, "belong", NBELONG)==0) {
  674. m->type = FILE_BELONG;
  675. l += NBELONG;
  676. } else if (strncmp(l, "bedate", NBEDATE)==0) {
  677. m->type = FILE_BEDATE;
  678. l += NBEDATE;
  679. } else if (strncmp(l, "leshort", NLESHORT)==0) {
  680. m->type = FILE_LESHORT;
  681. l += NLESHORT;
  682. } else if (strncmp(l, "lelong", NLELONG)==0) {
  683. m->type = FILE_LELONG;
  684. l += NLELONG;
  685. } else if (strncmp(l, "melong", NMELONG)==0) {
  686. m->type = FILE_MELONG;
  687. l += NMELONG;
  688. } else if (strncmp(l, "ledate", NLEDATE)==0) {
  689. m->type = FILE_LEDATE;
  690. l += NLEDATE;
  691. } else if (strncmp(l, "medate", NMEDATE)==0) {
  692. m->type = FILE_MEDATE;
  693. l += NMEDATE;
  694. } else if (strncmp(l, "pstring", NPSTRING)==0) {
  695. m->type = FILE_PSTRING;
  696. l += NPSTRING;
  697. } else if (strncmp(l, "ldate", NLDATE)==0) {
  698. m->type = FILE_LDATE;
  699. l += NLDATE;
  700. } else if (strncmp(l, "beldate", NBELDATE)==0) {
  701. m->type = FILE_BELDATE;
  702. l += NBELDATE;
  703. } else if (strncmp(l, "leldate", NLELDATE)==0) {
  704. m->type = FILE_LELDATE;
  705. l += NLELDATE;
  706. } else if (strncmp(l, "meldate", NMELDATE)==0) {
  707. m->type = FILE_MELDATE;
  708. l += NMELDATE;
  709. } else if (strncmp(l, "regex", NREGEX)==0) {
  710. m->type = FILE_REGEX;
  711. l += NREGEX;
  712. } else if (strncmp(l, "bestring16", NBESTRING16)==0) {
  713. m->type = FILE_BESTRING16;
  714. l += NBESTRING16;
  715. } else if (strncmp(l, "lestring16", NLESTRING16)==0) {
  716. m->type = FILE_LESTRING16;
  717. l += NLESTRING16;
  718. } else if (strncmp(l, "search", NSEARCH)==0) {
  719. m->type = FILE_SEARCH;
  720. l += NSEARCH;
  721. } else {
  722. if (ms->flags & MAGIC_CHECK)
  723. file_magwarn(ms, "type `%s' invalid", l);
  724. return -1;
  725. }
  726. /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
  727. /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */
  728. if (*l == '~') {
  729. if (!IS_STRING(m->type))
  730. m->mask_op |= FILE_OPINVERSE;
  731. ++l;
  732. }
  733. if ((t = strchr(fops, *l)) != NULL) {
  734. uint32_t op = (uint32_t)(t - fops);
  735. if (op != FILE_OPDIVIDE || !IS_PLAINSTRING(m->type)) {
  736. ++l;
  737. m->mask_op |= op;
  738. val = (uint32_t)strtoul(l, &t, 0);
  739. l = t;
  740. m->mask = file_signextend(ms, m, val);
  741. eatsize(&l);
  742. } else {
  743. m->mask = 0L;
  744. while (!isspace((unsigned char)*++l)) {
  745. switch (*l) {
  746. case CHAR_IGNORE_LOWERCASE:
  747. m->mask |= STRING_IGNORE_LOWERCASE;
  748. break;
  749. case CHAR_COMPACT_BLANK:
  750. m->mask |= STRING_COMPACT_BLANK;
  751. break;
  752. case CHAR_COMPACT_OPTIONAL_BLANK:
  753. m->mask |=
  754. STRING_COMPACT_OPTIONAL_BLANK;
  755. break;
  756. default:
  757. if (ms->flags & MAGIC_CHECK)
  758. file_magwarn(ms,
  759. "string extension `%c' invalid",
  760. *l);
  761. return -1;
  762. }
  763. }
  764. ++l;
  765. }
  766. }
  767. /*
  768. * We used to set mask to all 1's here, instead let's just not do
  769. * anything if mask = 0 (unless you have a better idea)
  770. */
  771. EATAB;
  772. switch (*l) {
  773. case '>':
  774. case '<':
  775. /* Old-style anding: "0 byte &0x80 dynamically linked" */
  776. case '&':
  777. case '^':
  778. case '=':
  779. m->reln = *l;
  780. ++l;
  781. if (*l == '=') {
  782. /* HP compat: ignore &= etc. */
  783. ++l;
  784. }
  785. break;
  786. case '!':
  787. m->reln = *l;
  788. ++l;
  789. break;
  790. default:
  791. if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
  792. isspace((unsigned char)l[1])) || !l[1])) {
  793. m->reln = *l;
  794. ++l;
  795. goto GetDesc; /* Bill The Cat */
  796. }
  797. m->reln = '=';
  798. break;
  799. }
  800. EATAB;
  801. if (getvalue(ms, m, &l))
  802. return -1;
  803. /*
  804. * TODO finish this macro and start using it!
  805. * #define offsetcheck {if (offset > HOWMANY-1)
  806. * magwarn("offset too big"); }
  807. */
  808. /*
  809. * now get last part - the description
  810. */
  811. GetDesc:
  812. EATAB;
  813. if (l[0] == '\b') {
  814. ++l;
  815. m->nospflag = 1;
  816. } else if ((l[0] == '\\') && (l[1] == 'b')) {
  817. ++l;
  818. ++l;
  819. m->nospflag = 1;
  820. } else
  821. m->nospflag = 0;
  822. while ((m->desc[i++] = *l++) != '\0' && i < MAXDESC)
  823. /* NULLBODY */;
  824. if (ms->flags & MAGIC_CHECK) {
  825. if (!check_format(ms, m))
  826. return -1;
  827. }
  828. #ifndef COMPILE_ONLY
  829. if (action == FILE_CHECK) {
  830. file_mdump(m);
  831. }
  832. #endif
  833. if (m->cont_level == 0)
  834. ++(*nmentryp); /* make room for next */
  835. return 0;
  836. }
  837. /*
  838. * Check that the optional printf format in description matches
  839. * the type of the magic.
  840. */
  841. private int
  842. check_format(struct magic_set *ms, struct magic *m)
  843. {
  844. static const char *formats[] = { FILE_FORMAT_STRING };
  845. static const char *names[] = { FILE_FORMAT_NAME };
  846. char *ptr;
  847. for (ptr = m->desc; *ptr; ptr++)
  848. if (*ptr == '%')
  849. break;
  850. if (*ptr == '\0') {
  851. /* No format string; ok */
  852. return 1;
  853. }
  854. if (m->type >= sizeof(formats)/sizeof(formats[0])) {
  855. file_magwarn(ms, "Internal error inconsistency between m->type"
  856. " and format strings");
  857. return 0;
  858. }
  859. if (formats[m->type] == NULL) {
  860. file_magwarn(ms, "No format string for `%s' with description "
  861. "`%s'", m->desc, names[m->type]);
  862. return 0;
  863. }
  864. for (; *ptr; ptr++) {
  865. if (*ptr == 'l' || *ptr == 'h') {
  866. /* XXX: we should really fix this one day */
  867. continue;
  868. }
  869. if (islower((unsigned char)*ptr) || *ptr == 'X')
  870. break;
  871. }
  872. if (*ptr == '\0') {
  873. /* Missing format string; bad */
  874. file_magwarn(ms, "Invalid format `%s' for type `%s'",
  875. m->desc, names[m->type]);
  876. return 0;
  877. }
  878. if (strchr(formats[m->type], *ptr) == NULL) {
  879. file_magwarn(ms, "Printf format `%c' is not valid for type `%s'"
  880. " in description `%s'",
  881. *ptr, names[m->type], m->desc);
  882. return 0;
  883. }
  884. return 1;
  885. }
  886. /*
  887. * Read a numeric value from a pointer, into the value union of a magic
  888. * pointer, according to the magic type. Update the string pointer to point
  889. * just after the number read. Return 0 for success, non-zero for failure.
  890. */
  891. private int
  892. getvalue(struct magic_set *ms, struct magic *m, const char **p)
  893. {
  894. int slen;
  895. switch (m->type) {
  896. case FILE_BESTRING16:
  897. case FILE_LESTRING16:
  898. case FILE_STRING:
  899. case FILE_PSTRING:
  900. case FILE_REGEX:
  901. case FILE_SEARCH:
  902. *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen);
  903. if (*p == NULL) {
  904. if (ms->flags & MAGIC_CHECK)
  905. file_magwarn(ms, "cannot get string from `%s'",
  906. m->value.s);
  907. return -1;
  908. }
  909. m->vallen = slen;
  910. return 0;
  911. default:
  912. if (m->reln != 'x') {
  913. char *ep;
  914. m->value.l = file_signextend(ms, m,
  915. (uint32_t)strtoul(*p, &ep, 0));
  916. *p = ep;
  917. eatsize(p);
  918. }
  919. return 0;
  920. }
  921. }
  922. /*
  923. * Convert a string containing C character escapes. Stop at an unescaped
  924. * space or tab.
  925. * Copy the converted version to "p", returning its length in *slen.
  926. * Return updated scan pointer as function result.
  927. */
  928. private const char *
  929. getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen)
  930. {
  931. const char *origs = s;
  932. char *origp = p;
  933. char *pmax = p + plen - 1;
  934. int c;
  935. int val;
  936. while ((c = *s++) != '\0') {
  937. if (isspace((unsigned char) c))
  938. break;
  939. if (p >= pmax) {
  940. file_error(ms, 0, "string too long: `%s'", origs);
  941. return NULL;
  942. }
  943. if(c == '\\') {
  944. switch(c = *s++) {
  945. case '\0':
  946. goto out;
  947. default:
  948. *p++ = (char) c;
  949. break;
  950. case 'n':
  951. *p++ = '\n';
  952. break;
  953. case 'r':
  954. *p++ = '\r';
  955. break;
  956. case 'b':
  957. *p++ = '\b';
  958. break;
  959. case 't':
  960. *p++ = '\t';
  961. break;
  962. case 'f':
  963. *p++ = '\f';
  964. break;
  965. case 'v':
  966. *p++ = '\v';
  967. break;
  968. /* \ and up to 3 octal digits */
  969. case '0':
  970. case '1':
  971. case '2':
  972. case '3':
  973. case '4':
  974. case '5':
  975. case '6':
  976. case '7':
  977. val = c - '0';
  978. c = *s++; /* try for 2 */
  979. if(c >= '0' && c <= '7') {
  980. val = (val<<3) | (c - '0');
  981. c = *s++; /* try for 3 */
  982. if(c >= '0' && c <= '7')
  983. val = (val<<3) | (c-'0');
  984. else
  985. --s;
  986. }
  987. else
  988. --s;
  989. *p++ = (char)val;
  990. break;
  991. /* \x and up to 2 hex digits */
  992. case 'x':
  993. val = 'x'; /* Default if no digits */
  994. c = hextoint(*s++); /* Get next char */
  995. if (c >= 0) {
  996. val = c;
  997. c = hextoint(*s++);
  998. if (c >= 0)
  999. val = (val << 4) + c;
  1000. else
  1001. --s;
  1002. } else
  1003. --s;
  1004. *p++ = (char)val;
  1005. break;
  1006. }
  1007. } else
  1008. *p++ = (char)c;
  1009. }
  1010. out:
  1011. *p = '\0';
  1012. *slen = p - origp;
  1013. return s;
  1014. }
  1015. /* Single hex char to int; -1 if not a hex char. */
  1016. private int
  1017. hextoint(int c)
  1018. {
  1019. if (!isascii((unsigned char) c))
  1020. return -1;
  1021. if (isdigit((unsigned char) c))
  1022. return c - '0';
  1023. if ((c >= 'a')&&(c <= 'f'))
  1024. return c + 10 - 'a';
  1025. if (( c>= 'A')&&(c <= 'F'))
  1026. return c + 10 - 'A';
  1027. return -1;
  1028. }
  1029. /*
  1030. * Print a string containing C character escapes.
  1031. */
  1032. protected void
  1033. file_showstr(FILE *fp, const char *s, size_t len)
  1034. {
  1035. char c;
  1036. for (;;) {
  1037. c = *s++;
  1038. if (len == ~0U) {
  1039. if (c == '\0')
  1040. break;
  1041. }
  1042. else {
  1043. if (len-- == 0)
  1044. break;
  1045. }
  1046. if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */
  1047. (void) fputc(c, fp);
  1048. else {
  1049. (void) fputc('\\', fp);
  1050. switch (c) {
  1051. case '\n':
  1052. (void) fputc('n', fp);
  1053. break;
  1054. case '\r':
  1055. (void) fputc('r', fp);
  1056. break;
  1057. case '\b':
  1058. (void) fputc('b', fp);
  1059. break;
  1060. case '\t':
  1061. (void) fputc('t', fp);
  1062. break;
  1063. case '\f':
  1064. (void) fputc('f', fp);
  1065. break;
  1066. case '\v':
  1067. (void) fputc('v', fp);
  1068. break;
  1069. default:
  1070. (void) fprintf(fp, "%.3o", c & 0377);
  1071. break;
  1072. }
  1073. }
  1074. }
  1075. }
  1076. /*
  1077. * eatsize(): Eat the size spec from a number [eg. 10UL]
  1078. */
  1079. private void
  1080. eatsize(const char **p)
  1081. {
  1082. const char *l = *p;
  1083. if (LOWCASE(*l) == 'u')
  1084. l++;
  1085. switch (LOWCASE(*l)) {
  1086. case 'l': /* long */
  1087. case 's': /* short */
  1088. case 'h': /* short */
  1089. case 'b': /* char/byte */
  1090. case 'c': /* char/byte */
  1091. l++;
  1092. /*FALLTHROUGH*/
  1093. default:
  1094. break;
  1095. }
  1096. *p = l;
  1097. }
  1098. /*
  1099. * handle a compiled file.
  1100. */
  1101. private int
  1102. apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
  1103. const char *fn)
  1104. {
  1105. int fd;
  1106. struct stat st;
  1107. uint32_t *ptr;
  1108. uint32_t version;
  1109. int needsbyteswap;
  1110. char buf[MAXPATHLEN];
  1111. char *dbname = mkdbname(fn, buf, sizeof(buf), 0);
  1112. void *mm = NULL;
  1113. if (dbname == NULL)
  1114. return -1;
  1115. if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
  1116. return -1;
  1117. if (fstat(fd, &st) == -1) {
  1118. file_error(ms, errno, "cannot stat `%s'", dbname);
  1119. goto error;
  1120. }
  1121. if (st.st_size < 16) {
  1122. file_error(ms, 0, "file `%s' is too small", dbname);
  1123. goto error;
  1124. }
  1125. #ifdef QUICK
  1126. if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
  1127. MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
  1128. file_error(ms, errno, "cannot map `%s'", dbname);
  1129. goto error;
  1130. }
  1131. #define RET 2
  1132. #else
  1133. if ((mm = malloc((size_t)st.st_size)) == NULL) {
  1134. file_oomem(ms);
  1135. goto error;
  1136. }
  1137. if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
  1138. file_badread(ms);
  1139. goto error;
  1140. }
  1141. #define RET 1
  1142. #endif
  1143. *magicp = mm;
  1144. (void)close(fd);
  1145. fd = -1;
  1146. ptr = (uint32_t *)(void *)*magicp;
  1147. if (*ptr != MAGICNO) {
  1148. if (swap4(*ptr) != MAGICNO) {
  1149. file_error(ms, 0, "bad magic in `%s'");
  1150. goto error;
  1151. }
  1152. needsbyteswap = 1;
  1153. } else
  1154. needsbyteswap = 0;
  1155. if (needsbyteswap)
  1156. version = swap4(ptr[1]);
  1157. else
  1158. version = ptr[1];
  1159. if (version != VERSIONNO) {
  1160. file_error(ms, 0, "version mismatch (%d != %d) in `%s'",
  1161. version, VERSIONNO, dbname);
  1162. goto error;
  1163. }
  1164. *nmagicp = (uint32_t)(st.st_size / sizeof(struct magic)) - 1;
  1165. (*magicp)++;
  1166. if (needsbyteswap)
  1167. byteswap(*magicp, *nmagicp);
  1168. return RET;
  1169. error:
  1170. if (fd != -1)
  1171. (void)close(fd);
  1172. if (mm) {
  1173. #ifdef QUICK
  1174. (void)munmap((void *)mm, (size_t)st.st_size);
  1175. #else
  1176. free(mm);
  1177. #endif
  1178. } else {
  1179. *magicp = NULL;
  1180. *nmagicp = 0;
  1181. }
  1182. return -1;
  1183. }
  1184. private const uint32_t ar[] = {
  1185. MAGICNO, VERSIONNO
  1186. };
  1187. /*
  1188. * handle an mmaped file.
  1189. */
  1190. private int
  1191. apprentice_compile(struct magic_set *ms, struct magic **magicp,
  1192. uint32_t *nmagicp, const char *fn)
  1193. {
  1194. int fd;
  1195. char buf[MAXPATHLEN];
  1196. char *dbname = mkdbname(fn, buf, sizeof(buf), 1);
  1197. if (dbname == NULL)
  1198. return -1;
  1199. if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) {
  1200. file_error(ms, errno, "cannot open `%s'", dbname);
  1201. return -1;
  1202. }
  1203. if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
  1204. file_error(ms, errno, "error writing `%s'", dbname);
  1205. return -1;
  1206. }
  1207. if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET)
  1208. != sizeof(struct magic)) {
  1209. file_error(ms, errno, "error seeking `%s'", dbname);
  1210. return -1;
  1211. }
  1212. if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp))
  1213. != (ssize_t)(sizeof(struct magic) * *nmagicp)) {
  1214. file_error(ms, errno, "error writing `%s'", dbname);
  1215. return -1;
  1216. }
  1217. (void)close(fd);
  1218. return 0;
  1219. }
  1220. private const char ext[] = ".mgc";
  1221. /*
  1222. * make a dbname
  1223. */
  1224. private char *
  1225. mkdbname(const char *fn, char *buf, size_t bufsiz, int strip)
  1226. {
  1227. if (strip) {
  1228. const char *p;
  1229. if ((p = strrchr(fn, '/')) != NULL)
  1230. fn = ++p;
  1231. }
  1232. (void)snprintf(buf, bufsiz, "%s%s", fn, ext);
  1233. return buf;
  1234. }
  1235. /*
  1236. * Byteswap an mmap'ed file if needed
  1237. */
  1238. private void
  1239. byteswap(struct magic *magic, uint32_t nmagic)
  1240. {
  1241. uint32_t i;
  1242. for (i = 0; i < nmagic; i++)
  1243. bs1(&magic[i]);
  1244. }
  1245. /*
  1246. * swap a short
  1247. */
  1248. private uint16_t
  1249. swap2(uint16_t sv)
  1250. {
  1251. uint16_t rv;
  1252. uint8_t *s = (uint8_t *)(void *)&sv;
  1253. uint8_t *d = (uint8_t *)(void *)&rv;
  1254. d[0] = s[1];
  1255. d[1] = s[0];
  1256. return rv;
  1257. }
  1258. /*
  1259. * swap an int
  1260. */
  1261. private uint32_t
  1262. swap4(uint32_t sv)
  1263. {
  1264. uint32_t rv;
  1265. uint8_t *s = (uint8_t *)(void *)&sv;
  1266. uint8_t *d = (uint8_t *)(void *)&rv;
  1267. d[0] = s[3];
  1268. d[1] = s[2];
  1269. d[2] = s[1];
  1270. d[3] = s[0];
  1271. return rv;
  1272. }
  1273. /*
  1274. * byteswap a single magic entry
  1275. */
  1276. private void
  1277. bs1(struct magic *m)
  1278. {
  1279. m->cont_level = swap2(m->cont_level);
  1280. m->offset = swap4((uint32_t)m->offset);
  1281. m->in_offset = swap4((uint32_t)m->in_offset);
  1282. if (!IS_STRING(m->type))
  1283. m->value.l = swap4(m->value.l);
  1284. m->mask = swap4(m->mask);
  1285. }