apprentice.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932
  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 "patchlevel.h"
  34. #include <stdlib.h>
  35. #ifdef HAVE_UNISTD_H
  36. #include <unistd.h>
  37. #endif
  38. #include <string.h>
  39. #include <assert.h>
  40. #include <ctype.h>
  41. #include <fcntl.h>
  42. #include <sys/stat.h>
  43. #include <sys/param.h>
  44. #ifdef QUICK
  45. #include <sys/mman.h>
  46. #endif
  47. #ifndef lint
  48. FILE_RCSID("@(#)$File: apprentice.c,v 1.109 2007/12/27 20:52:36 christos Exp $")
  49. #endif /* lint */
  50. #define EATAB {while (isascii((unsigned char) *l) && \
  51. isspace((unsigned char) *l)) ++l;}
  52. #define LOWCASE(l) (isupper((unsigned char) (l)) ? \
  53. tolower((unsigned char) (l)) : (l))
  54. /*
  55. * Work around a bug in headers on Digital Unix.
  56. * At least confirmed for: OSF1 V4.0 878
  57. */
  58. #if defined(__osf__) && defined(__DECC)
  59. #ifdef MAP_FAILED
  60. #undef MAP_FAILED
  61. #endif
  62. #endif
  63. #ifndef MAP_FAILED
  64. #define MAP_FAILED (void *) -1
  65. #endif
  66. #ifndef MAP_FILE
  67. #define MAP_FILE 0
  68. #endif
  69. #ifndef MAXPATHLEN
  70. #define MAXPATHLEN 1024
  71. #endif
  72. struct magic_entry {
  73. struct magic *mp;
  74. uint32_t cont_count;
  75. uint32_t max_count;
  76. };
  77. int file_formats[FILE_NAMES_SIZE];
  78. const size_t file_nformats = FILE_NAMES_SIZE;
  79. const char *file_names[FILE_NAMES_SIZE];
  80. const size_t file_nnames = FILE_NAMES_SIZE;
  81. private int getvalue(struct magic_set *ms, struct magic *, const char **, int);
  82. private int hextoint(int);
  83. private const char *getstr(struct magic_set *, const char *, char *, int,
  84. int *, int);
  85. private int parse(struct magic_set *, struct magic_entry **, uint32_t *,
  86. const char *, size_t, int);
  87. private void eatsize(const char **);
  88. private int apprentice_1(struct magic_set *, const char *, int, struct mlist *);
  89. private size_t apprentice_magic_strength(const struct magic *);
  90. private int apprentice_sort(const void *, const void *);
  91. private int apprentice_file(struct magic_set *, struct magic **, uint32_t *,
  92. const char *, int);
  93. private void byteswap(struct magic *, uint32_t);
  94. private void bs1(struct magic *);
  95. private uint16_t swap2(uint16_t);
  96. private uint32_t swap4(uint32_t);
  97. private uint64_t swap8(uint64_t);
  98. private char *mkdbname(const char *, char *, size_t, int);
  99. private int apprentice_map(struct magic_set *, struct magic **, uint32_t *,
  100. const char *);
  101. private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *,
  102. const char *);
  103. private int check_format_type(const char *, int);
  104. private int check_format(struct magic_set *, struct magic *);
  105. private int get_op(char);
  106. private size_t maxmagic = 0;
  107. private size_t magicsize = sizeof(struct magic);
  108. #ifdef COMPILE_ONLY
  109. int main(int, char *[]);
  110. int
  111. main(int argc, char *argv[])
  112. {
  113. int ret;
  114. struct magic_set *ms;
  115. char *progname;
  116. if ((progname = strrchr(argv[0], '/')) != NULL)
  117. progname++;
  118. else
  119. progname = argv[0];
  120. if (argc != 2) {
  121. (void)fprintf(stderr, "Usage: %s file\n", progname);
  122. return 1;
  123. }
  124. if ((ms = magic_open(MAGIC_CHECK)) == NULL) {
  125. (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno));
  126. return 1;
  127. }
  128. ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0;
  129. if (ret == 1)
  130. (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms));
  131. magic_close(ms);
  132. return ret;
  133. }
  134. #endif /* COMPILE_ONLY */
  135. static const struct type_tbl_s {
  136. const char *name;
  137. const size_t len;
  138. const int type;
  139. const int format;
  140. } type_tbl[] = {
  141. # define XX(s) s, (sizeof(s) - 1)
  142. # define XX_NULL NULL, 0
  143. { XX("byte"), FILE_BYTE, FILE_FMT_NUM },
  144. { XX("short"), FILE_SHORT, FILE_FMT_NUM },
  145. { XX("default"), FILE_DEFAULT, FILE_FMT_STR },
  146. { XX("long"), FILE_LONG, FILE_FMT_NUM },
  147. { XX("string"), FILE_STRING, FILE_FMT_STR },
  148. { XX("date"), FILE_DATE, FILE_FMT_STR },
  149. { XX("beshort"), FILE_BESHORT, FILE_FMT_NUM },
  150. { XX("belong"), FILE_BELONG, FILE_FMT_NUM },
  151. { XX("bedate"), FILE_BEDATE, FILE_FMT_STR },
  152. { XX("leshort"), FILE_LESHORT, FILE_FMT_NUM },
  153. { XX("lelong"), FILE_LELONG, FILE_FMT_NUM },
  154. { XX("ledate"), FILE_LEDATE, FILE_FMT_STR },
  155. { XX("pstring"), FILE_PSTRING, FILE_FMT_STR },
  156. { XX("ldate"), FILE_LDATE, FILE_FMT_STR },
  157. { XX("beldate"), FILE_BELDATE, FILE_FMT_STR },
  158. { XX("leldate"), FILE_LELDATE, FILE_FMT_STR },
  159. { XX("regex"), FILE_REGEX, FILE_FMT_STR },
  160. { XX("bestring16"), FILE_BESTRING16, FILE_FMT_STR },
  161. { XX("lestring16"), FILE_LESTRING16, FILE_FMT_STR },
  162. { XX("search"), FILE_SEARCH, FILE_FMT_STR },
  163. { XX("medate"), FILE_MEDATE, FILE_FMT_STR },
  164. { XX("meldate"), FILE_MELDATE, FILE_FMT_STR },
  165. { XX("melong"), FILE_MELONG, FILE_FMT_NUM },
  166. { XX("quad"), FILE_QUAD, FILE_FMT_QUAD },
  167. { XX("lequad"), FILE_LEQUAD, FILE_FMT_QUAD },
  168. { XX("bequad"), FILE_BEQUAD, FILE_FMT_QUAD },
  169. { XX("qdate"), FILE_QDATE, FILE_FMT_STR },
  170. { XX("leqdate"), FILE_LEQDATE, FILE_FMT_STR },
  171. { XX("beqdate"), FILE_BEQDATE, FILE_FMT_STR },
  172. { XX("qldate"), FILE_QLDATE, FILE_FMT_STR },
  173. { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR },
  174. { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR },
  175. { XX("float"), FILE_FLOAT, FILE_FMT_FLOAT },
  176. { XX("befloat"), FILE_BEFLOAT, FILE_FMT_FLOAT },
  177. { XX("lefloat"), FILE_LEFLOAT, FILE_FMT_FLOAT },
  178. { XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE },
  179. { XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE },
  180. { XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE },
  181. { XX_NULL, FILE_INVALID, FILE_FMT_NONE },
  182. # undef XX
  183. # undef XX_NULL
  184. };
  185. private int
  186. get_type(const char *l, const char **t)
  187. {
  188. const struct type_tbl_s *p;
  189. for (p = type_tbl; p->name; p++) {
  190. if (strncmp(l, p->name, p->len) == 0) {
  191. if (t)
  192. *t = l + p->len;
  193. break;
  194. }
  195. }
  196. return p->type;
  197. }
  198. private void
  199. init_file_tables(void)
  200. {
  201. static int done = 0;
  202. const struct type_tbl_s *p;
  203. if (done)
  204. return;
  205. done++;
  206. for (p = type_tbl; p->name; p++) {
  207. assert(p->type < FILE_NAMES_SIZE);
  208. file_names[p->type] = p->name;
  209. file_formats[p->type] = p->format;
  210. }
  211. }
  212. /*
  213. * Handle one file.
  214. */
  215. private int
  216. apprentice_1(struct magic_set *ms, const char *fn, int action,
  217. struct mlist *mlist)
  218. {
  219. struct magic *magic = NULL;
  220. uint32_t nmagic = 0;
  221. struct mlist *ml;
  222. int rv = -1;
  223. int mapped;
  224. if (magicsize != FILE_MAGICSIZE) {
  225. file_error(ms, 0, "magic element size %lu != %lu",
  226. (unsigned long)sizeof(*magic),
  227. (unsigned long)FILE_MAGICSIZE);
  228. return -1;
  229. }
  230. if (action == FILE_COMPILE) {
  231. rv = apprentice_file(ms, &magic, &nmagic, fn, action);
  232. if (rv != 0)
  233. return -1;
  234. rv = apprentice_compile(ms, &magic, &nmagic, fn);
  235. free(magic);
  236. return rv;
  237. }
  238. #ifndef COMPILE_ONLY
  239. if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
  240. if (ms->flags & MAGIC_CHECK)
  241. file_magwarn(ms, "using regular magic file `%s'", fn);
  242. rv = apprentice_file(ms, &magic, &nmagic, fn, action);
  243. if (rv != 0)
  244. return -1;
  245. }
  246. mapped = rv;
  247. if (magic == NULL || nmagic == 0) {
  248. file_delmagic(magic, mapped, nmagic);
  249. return -1;
  250. }
  251. if ((ml = malloc(sizeof(*ml))) == NULL) {
  252. file_delmagic(magic, mapped, nmagic);
  253. file_oomem(ms, sizeof(*ml));
  254. return -1;
  255. }
  256. ml->magic = magic;
  257. ml->nmagic = nmagic;
  258. ml->mapped = mapped;
  259. mlist->prev->next = ml;
  260. ml->prev = mlist->prev;
  261. ml->next = mlist;
  262. mlist->prev = ml;
  263. return 0;
  264. #endif /* COMPILE_ONLY */
  265. }
  266. protected void
  267. file_delmagic(struct magic *p, int type, size_t entries)
  268. {
  269. if (p == NULL)
  270. return;
  271. switch (type) {
  272. #ifdef QUICK
  273. case 2:
  274. p--;
  275. (void)munmap((void *)p, sizeof(*p) * (entries + 1));
  276. break;
  277. #endif
  278. case 1:
  279. p--;
  280. /*FALLTHROUGH*/
  281. case 0:
  282. free(p);
  283. break;
  284. default:
  285. abort();
  286. }
  287. }
  288. /* const char *fn: list of magic files */
  289. protected struct mlist *
  290. file_apprentice(struct magic_set *ms, const char *fn, int action)
  291. {
  292. char *p, *mfn, *afn = NULL;
  293. int file_err, errs = -1;
  294. struct mlist *mlist;
  295. static const char mime[] = ".mime";
  296. init_file_tables();
  297. if (fn == NULL)
  298. fn = getenv("MAGIC");
  299. if (fn == NULL)
  300. fn = MAGIC;
  301. if ((mfn = strdup(fn)) == NULL) {
  302. file_oomem(ms, strlen(fn));
  303. return NULL;
  304. }
  305. fn = mfn;
  306. if ((mlist = malloc(sizeof(*mlist))) == NULL) {
  307. free(mfn);
  308. file_oomem(ms, sizeof(*mlist));
  309. return NULL;
  310. }
  311. mlist->next = mlist->prev = mlist;
  312. while (fn) {
  313. p = strchr(fn, PATHSEP);
  314. if (p)
  315. *p++ = '\0';
  316. if (*fn == '\0')
  317. break;
  318. if (ms->flags & MAGIC_MIME) {
  319. size_t len = strlen(fn) + sizeof(mime);
  320. if ((afn = malloc(len)) == NULL) {
  321. free(mfn);
  322. free(mlist);
  323. file_oomem(ms, len);
  324. return NULL;
  325. }
  326. (void)strcpy(afn, fn);
  327. (void)strcat(afn, mime);
  328. fn = afn;
  329. }
  330. file_err = apprentice_1(ms, fn, action, mlist);
  331. if (file_err > errs)
  332. errs = file_err;
  333. if (afn) {
  334. free(afn);
  335. afn = NULL;
  336. }
  337. fn = p;
  338. }
  339. if (errs == -1) {
  340. free(mfn);
  341. free(mlist);
  342. mlist = NULL;
  343. file_error(ms, 0, "could not find any magic files!");
  344. return NULL;
  345. }
  346. free(mfn);
  347. return mlist;
  348. }
  349. /*
  350. * Get weight of this magic entry, for sorting purposes.
  351. */
  352. private size_t
  353. apprentice_magic_strength(const struct magic *m)
  354. {
  355. #define MULT 10
  356. size_t val = 2 * MULT; /* baseline strength */
  357. switch (m->type) {
  358. case FILE_DEFAULT: /* make sure this sorts last */
  359. return 0;
  360. case FILE_BYTE:
  361. val += 1 * MULT;
  362. break;
  363. case FILE_SHORT:
  364. case FILE_LESHORT:
  365. case FILE_BESHORT:
  366. val += 2 * MULT;
  367. break;
  368. case FILE_LONG:
  369. case FILE_LELONG:
  370. case FILE_BELONG:
  371. case FILE_MELONG:
  372. val += 4 * MULT;
  373. break;
  374. case FILE_PSTRING:
  375. case FILE_STRING:
  376. val += m->vallen * MULT;
  377. break;
  378. case FILE_BESTRING16:
  379. case FILE_LESTRING16:
  380. val += m->vallen * MULT / 2;
  381. break;
  382. case FILE_SEARCH:
  383. case FILE_REGEX:
  384. val += m->vallen;
  385. break;
  386. case FILE_DATE:
  387. case FILE_LEDATE:
  388. case FILE_BEDATE:
  389. case FILE_MEDATE:
  390. case FILE_LDATE:
  391. case FILE_LELDATE:
  392. case FILE_BELDATE:
  393. case FILE_MELDATE:
  394. case FILE_FLOAT:
  395. case FILE_BEFLOAT:
  396. case FILE_LEFLOAT:
  397. val += 4 * MULT;
  398. break;
  399. case FILE_QUAD:
  400. case FILE_BEQUAD:
  401. case FILE_LEQUAD:
  402. case FILE_QDATE:
  403. case FILE_LEQDATE:
  404. case FILE_BEQDATE:
  405. case FILE_QLDATE:
  406. case FILE_LEQLDATE:
  407. case FILE_BEQLDATE:
  408. case FILE_DOUBLE:
  409. case FILE_BEDOUBLE:
  410. case FILE_LEDOUBLE:
  411. val += 8 * MULT;
  412. break;
  413. default:
  414. val = 0;
  415. (void)fprintf(stderr, "Bad type %d\n", m->type);
  416. abort();
  417. }
  418. switch (m->reln) {
  419. case 'x': /* matches anything penalize */
  420. val = 0;
  421. break;
  422. case '!':
  423. case '=': /* Exact match, prefer */
  424. val += MULT;
  425. break;
  426. case '>':
  427. case '<': /* comparison match reduce strength */
  428. val -= 2 * MULT;
  429. break;
  430. case '^':
  431. case '&': /* masking bits, we could count them too */
  432. val -= MULT;
  433. break;
  434. default:
  435. (void)fprintf(stderr, "Bad relation %c\n", m->reln);
  436. abort();
  437. }
  438. if (val == 0) /* ensure we only return 0 for FILE_DEFAULT */
  439. val = 1;
  440. return val;
  441. }
  442. /*
  443. * Sort callback for sorting entries by "strength" (basically length)
  444. */
  445. private int
  446. apprentice_sort(const void *a, const void *b)
  447. {
  448. const struct magic_entry *ma = a;
  449. const struct magic_entry *mb = b;
  450. size_t sa = apprentice_magic_strength(ma->mp);
  451. size_t sb = apprentice_magic_strength(mb->mp);
  452. if (sa == sb)
  453. return 0;
  454. else if (sa > sb)
  455. return -1;
  456. else
  457. return 1;
  458. }
  459. /*
  460. * parse from a file
  461. * const char *fn: name of magic file
  462. */
  463. private int
  464. apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
  465. const char *fn, int action)
  466. {
  467. private const char hdr[] =
  468. "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
  469. FILE *f;
  470. char line[BUFSIZ];
  471. int errs = 0;
  472. struct magic_entry *marray;
  473. uint32_t marraycount, i, mentrycount = 0;
  474. size_t lineno = 0;
  475. ms->flags |= MAGIC_CHECK; /* Enable checks for parsed files */
  476. f = fopen(ms->file = fn, "r");
  477. if (f == NULL) {
  478. if (errno != ENOENT)
  479. file_error(ms, errno, "cannot read magic file `%s'",
  480. fn);
  481. return -1;
  482. }
  483. maxmagic = MAXMAGIS;
  484. if ((marray = calloc(maxmagic, sizeof(*marray))) == NULL) {
  485. (void)fclose(f);
  486. file_oomem(ms, maxmagic * sizeof(*marray));
  487. return -1;
  488. }
  489. marraycount = 0;
  490. /* print silly verbose header for USG compat. */
  491. if (action == FILE_CHECK)
  492. (void)fprintf(stderr, "%s\n", hdr);
  493. /* read and parse this file */
  494. for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; ms->line++) {
  495. size_t len;
  496. len = strlen(line);
  497. if (len == 0) /* null line, garbage, etc */
  498. continue;
  499. if (line[len - 1] == '\n') {
  500. lineno++;
  501. line[len - 1] = '\0'; /* delete newline */
  502. }
  503. if (line[0] == '\0') /* empty, do not parse */
  504. continue;
  505. if (line[0] == '#') /* comment, do not parse */
  506. continue;
  507. if (parse(ms, &marray, &marraycount, line, lineno, action) != 0)
  508. errs++;
  509. }
  510. (void)fclose(f);
  511. if (errs)
  512. goto out;
  513. #ifndef NOORDER
  514. qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
  515. /*
  516. * Make sure that any level 0 "default" line is last (if one exists).
  517. */
  518. for (i = 0; i < marraycount; i++) {
  519. if (marray[i].mp->cont_level == 0 &&
  520. marray[i].mp->type == FILE_DEFAULT) {
  521. while (++i < marraycount)
  522. if (marray[i].mp->cont_level == 0)
  523. break;
  524. if (i != marraycount) {
  525. ms->line = marray[i].mp->lineno; /* XXX - Ugh! */
  526. file_magwarn(ms,
  527. "level 0 \"default\" did not sort last");
  528. }
  529. break;
  530. }
  531. }
  532. #endif
  533. for (i = 0; i < marraycount; i++)
  534. mentrycount += marray[i].cont_count;
  535. if ((*magicp = malloc(sizeof(**magicp) * mentrycount)) == NULL) {
  536. file_oomem(ms, sizeof(**magicp) * mentrycount);
  537. errs++;
  538. goto out;
  539. }
  540. mentrycount = 0;
  541. for (i = 0; i < marraycount; i++) {
  542. (void)memcpy(*magicp + mentrycount, marray[i].mp,
  543. marray[i].cont_count * sizeof(**magicp));
  544. mentrycount += marray[i].cont_count;
  545. }
  546. out:
  547. for (i = 0; i < marraycount; i++)
  548. free(marray[i].mp);
  549. free(marray);
  550. if (errs) {
  551. *magicp = NULL;
  552. *nmagicp = 0;
  553. return errs;
  554. } else {
  555. *nmagicp = mentrycount;
  556. return 0;
  557. }
  558. }
  559. /*
  560. * extend the sign bit if the comparison is to be signed
  561. */
  562. protected uint64_t
  563. file_signextend(struct magic_set *ms, struct magic *m, uint64_t v)
  564. {
  565. if (!(m->flag & UNSIGNED)) {
  566. switch(m->type) {
  567. /*
  568. * Do not remove the casts below. They are
  569. * vital. When later compared with the data,
  570. * the sign extension must have happened.
  571. */
  572. case FILE_BYTE:
  573. v = (char) v;
  574. break;
  575. case FILE_SHORT:
  576. case FILE_BESHORT:
  577. case FILE_LESHORT:
  578. v = (short) v;
  579. break;
  580. case FILE_DATE:
  581. case FILE_BEDATE:
  582. case FILE_LEDATE:
  583. case FILE_MEDATE:
  584. case FILE_LDATE:
  585. case FILE_BELDATE:
  586. case FILE_LELDATE:
  587. case FILE_MELDATE:
  588. case FILE_LONG:
  589. case FILE_BELONG:
  590. case FILE_LELONG:
  591. case FILE_MELONG:
  592. case FILE_FLOAT:
  593. case FILE_BEFLOAT:
  594. case FILE_LEFLOAT:
  595. v = (int32_t) v;
  596. break;
  597. case FILE_QUAD:
  598. case FILE_BEQUAD:
  599. case FILE_LEQUAD:
  600. case FILE_QDATE:
  601. case FILE_QLDATE:
  602. case FILE_BEQDATE:
  603. case FILE_BEQLDATE:
  604. case FILE_LEQDATE:
  605. case FILE_LEQLDATE:
  606. case FILE_DOUBLE:
  607. case FILE_BEDOUBLE:
  608. case FILE_LEDOUBLE:
  609. v = (int64_t) v;
  610. break;
  611. case FILE_STRING:
  612. case FILE_PSTRING:
  613. case FILE_BESTRING16:
  614. case FILE_LESTRING16:
  615. case FILE_REGEX:
  616. case FILE_SEARCH:
  617. case FILE_DEFAULT:
  618. break;
  619. default:
  620. if (ms->flags & MAGIC_CHECK)
  621. file_magwarn(ms, "cannot happen: m->type=%d\n",
  622. m->type);
  623. return ~0U;
  624. }
  625. }
  626. return v;
  627. }
  628. private int
  629. string_modifier_check(struct magic_set *ms, struct magic const *m)
  630. {
  631. if ((ms->flags & MAGIC_CHECK) == 0)
  632. return 0;
  633. switch (m->type) {
  634. case FILE_BESTRING16:
  635. case FILE_LESTRING16:
  636. if (m->str_flags != 0) {
  637. file_magwarn(ms, "no modifiers allowed for 16-bit strings\n");
  638. return -1;
  639. }
  640. break;
  641. case FILE_STRING:
  642. case FILE_PSTRING:
  643. if ((m->str_flags & REGEX_OFFSET_START) != 0) {
  644. file_magwarn(ms, "'/%c' only allowed on regex and search\n",
  645. CHAR_REGEX_OFFSET_START);
  646. return -1;
  647. }
  648. break;
  649. case FILE_SEARCH:
  650. break;
  651. case FILE_REGEX:
  652. if ((m->str_flags & STRING_COMPACT_BLANK) != 0) {
  653. file_magwarn(ms, "'/%c' not allowed on regex\n",
  654. CHAR_COMPACT_BLANK);
  655. return -1;
  656. }
  657. if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) {
  658. file_magwarn(ms, "'/%c' not allowed on regex\n",
  659. CHAR_COMPACT_OPTIONAL_BLANK);
  660. return -1;
  661. }
  662. break;
  663. default:
  664. file_magwarn(ms, "coding error: m->type=%d\n",
  665. m->type);
  666. return -1;
  667. }
  668. return 0;
  669. }
  670. private int
  671. get_op(char c)
  672. {
  673. switch (c) {
  674. case '&':
  675. return FILE_OPAND;
  676. case '|':
  677. return FILE_OPOR;
  678. case '^':
  679. return FILE_OPXOR;
  680. case '+':
  681. return FILE_OPADD;
  682. case '-':
  683. return FILE_OPMINUS;
  684. case '*':
  685. return FILE_OPMULTIPLY;
  686. case '/':
  687. return FILE_OPDIVIDE;
  688. case '%':
  689. return FILE_OPMODULO;
  690. default:
  691. return -1;
  692. }
  693. }
  694. #ifdef ENABLE_CONDITIONALS
  695. private int
  696. get_cond(const char *l, const char **t)
  697. {
  698. static struct cond_tbl_s {
  699. const char *name;
  700. const size_t len;
  701. const int cond;
  702. } cond_tbl[] = {
  703. { "if", 2, COND_IF },
  704. { "elif", 4, COND_ELIF },
  705. { "else", 4, COND_ELSE },
  706. { NULL, 0, COND_NONE },
  707. };
  708. struct cond_tbl_s *p;
  709. for (p = cond_tbl; p->name; p++) {
  710. if (strncmp(l, p->name, p->len) == 0 &&
  711. isspace((unsigned char)l[p->len])) {
  712. if (t)
  713. *t = l + p->len;
  714. break;
  715. }
  716. }
  717. return p->cond;
  718. }
  719. private int
  720. check_cond(struct magic_set *ms, int cond, uint32_t cont_level)
  721. {
  722. int last_cond;
  723. last_cond = ms->c.li[cont_level].last_cond;
  724. switch (cond) {
  725. case COND_IF:
  726. if (last_cond != COND_NONE && last_cond != COND_ELIF) {
  727. if (ms->flags & MAGIC_CHECK)
  728. file_magwarn(ms, "syntax error: `if'");
  729. return -1;
  730. }
  731. last_cond = COND_IF;
  732. break;
  733. case COND_ELIF:
  734. if (last_cond != COND_IF && last_cond != COND_ELIF) {
  735. if (ms->flags & MAGIC_CHECK)
  736. file_magwarn(ms, "syntax error: `elif'");
  737. return -1;
  738. }
  739. last_cond = COND_ELIF;
  740. break;
  741. case COND_ELSE:
  742. if (last_cond != COND_IF && last_cond != COND_ELIF) {
  743. if (ms->flags & MAGIC_CHECK)
  744. file_magwarn(ms, "syntax error: `else'");
  745. return -1;
  746. }
  747. last_cond = COND_NONE;
  748. break;
  749. case COND_NONE:
  750. last_cond = COND_NONE;
  751. break;
  752. }
  753. ms->c.li[cont_level].last_cond = last_cond;
  754. return 0;
  755. }
  756. #endif /* ENABLE_CONDITIONALS */
  757. /*
  758. * parse one line from magic file, put into magic[index++] if valid
  759. */
  760. private int
  761. parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp,
  762. const char *line, size_t lineno, int action)
  763. {
  764. #ifdef ENABLE_CONDITIONALS
  765. static uint32_t last_cont_level = 0;
  766. #endif
  767. size_t i;
  768. struct magic_entry *me;
  769. struct magic *m;
  770. const char *l = line;
  771. char *t;
  772. int op;
  773. uint32_t cont_level;
  774. cont_level = 0;
  775. while (*l == '>') {
  776. ++l; /* step over */
  777. cont_level++;
  778. }
  779. #ifdef ENABLE_CONDITIONALS
  780. if (cont_level == 0 || cont_level > last_cont_level)
  781. if (file_check_mem(ms, cont_level) == -1)
  782. return -1;
  783. last_cont_level = cont_level;
  784. #endif
  785. #define ALLOC_CHUNK (size_t)10
  786. #define ALLOC_INCR (size_t)200
  787. if (cont_level != 0) {
  788. if (*nmentryp == 0) {
  789. file_error(ms, 0, "No current entry for continuation");
  790. return -1;
  791. }
  792. me = &(*mentryp)[*nmentryp - 1];
  793. if (me->cont_count == me->max_count) {
  794. struct magic *nm;
  795. size_t cnt = me->max_count + ALLOC_CHUNK;
  796. if ((nm = realloc(me->mp, sizeof(*nm) * cnt)) == NULL) {
  797. file_oomem(ms, sizeof(*nm) * cnt);
  798. return -1;
  799. }
  800. me->mp = m = nm;
  801. me->max_count = cnt;
  802. }
  803. m = &me->mp[me->cont_count++];
  804. (void)memset(m, 0, sizeof(*m));
  805. m->cont_level = cont_level;
  806. } else {
  807. if (*nmentryp == maxmagic) {
  808. struct magic_entry *mp;
  809. maxmagic += ALLOC_INCR;
  810. if ((mp = realloc(*mentryp, sizeof(*mp) * maxmagic)) ==
  811. NULL) {
  812. file_oomem(ms, sizeof(*mp) * maxmagic);
  813. return -1;
  814. }
  815. (void)memset(&mp[*nmentryp], 0, sizeof(*mp) *
  816. ALLOC_INCR);
  817. *mentryp = mp;
  818. }
  819. me = &(*mentryp)[*nmentryp];
  820. if (me->mp == NULL) {
  821. if ((m = malloc(sizeof(*m) * ALLOC_CHUNK)) == NULL) {
  822. file_oomem(ms, sizeof(*m) * ALLOC_CHUNK);
  823. return -1;
  824. }
  825. me->mp = m;
  826. me->max_count = ALLOC_CHUNK;
  827. } else
  828. m = me->mp;
  829. (void)memset(m, 0, sizeof(*m));
  830. m->cont_level = 0;
  831. me->cont_count = 1;
  832. }
  833. m->lineno = lineno;
  834. if (*l == '&') { /* m->cont_level == 0 checked below. */
  835. ++l; /* step over */
  836. m->flag |= OFFADD;
  837. }
  838. if (*l == '(') {
  839. ++l; /* step over */
  840. m->flag |= INDIR;
  841. if (m->flag & OFFADD)
  842. m->flag = (m->flag & ~OFFADD) | INDIROFFADD;
  843. if (*l == '&') { /* m->cont_level == 0 checked below */
  844. ++l; /* step over */
  845. m->flag |= OFFADD;
  846. }
  847. }
  848. /* Indirect offsets are not valid at level 0. */
  849. if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD)))
  850. if (ms->flags & MAGIC_CHECK)
  851. file_magwarn(ms, "relative offset at level 0");
  852. /* get offset, then skip over it */
  853. m->offset = (uint32_t)strtoul(l, &t, 0);
  854. if (l == t)
  855. if (ms->flags & MAGIC_CHECK)
  856. file_magwarn(ms, "offset `%s' invalid", l);
  857. l = t;
  858. if (m->flag & INDIR) {
  859. m->in_type = FILE_LONG;
  860. m->in_offset = 0;
  861. /*
  862. * read [.lbs][+-]nnnnn)
  863. */
  864. if (*l == '.') {
  865. l++;
  866. switch (*l) {
  867. case 'l':
  868. m->in_type = FILE_LELONG;
  869. break;
  870. case 'L':
  871. m->in_type = FILE_BELONG;
  872. break;
  873. case 'm':
  874. m->in_type = FILE_MELONG;
  875. break;
  876. case 'h':
  877. case 's':
  878. m->in_type = FILE_LESHORT;
  879. break;
  880. case 'H':
  881. case 'S':
  882. m->in_type = FILE_BESHORT;
  883. break;
  884. case 'c':
  885. case 'b':
  886. case 'C':
  887. case 'B':
  888. m->in_type = FILE_BYTE;
  889. break;
  890. case 'e':
  891. case 'f':
  892. case 'g':
  893. m->in_type = FILE_LEDOUBLE;
  894. break;
  895. case 'E':
  896. case 'F':
  897. case 'G':
  898. m->in_type = FILE_BEDOUBLE;
  899. break;
  900. default:
  901. if (ms->flags & MAGIC_CHECK)
  902. file_magwarn(ms,
  903. "indirect offset type `%c' invalid",
  904. *l);
  905. break;
  906. }
  907. l++;
  908. }
  909. m->in_op = 0;
  910. if (*l == '~') {
  911. m->in_op |= FILE_OPINVERSE;
  912. l++;
  913. }
  914. if ((op = get_op(*l)) != -1) {
  915. m->in_op |= op;
  916. l++;
  917. }
  918. if (*l == '(') {
  919. m->in_op |= FILE_OPINDIRECT;
  920. l++;
  921. }
  922. if (isdigit((unsigned char)*l) || *l == '-') {
  923. m->in_offset = (int32_t)strtol(l, &t, 0);
  924. if (l == t)
  925. if (ms->flags & MAGIC_CHECK)
  926. file_magwarn(ms,
  927. "in_offset `%s' invalid", l);
  928. l = t;
  929. }
  930. if (*l++ != ')' ||
  931. ((m->in_op & FILE_OPINDIRECT) && *l++ != ')'))
  932. if (ms->flags & MAGIC_CHECK)
  933. file_magwarn(ms,
  934. "missing ')' in indirect offset");
  935. }
  936. EATAB;
  937. #ifdef ENABLE_CONDITIONALS
  938. m->cond = get_cond(l, &l);
  939. if (check_cond(ms, m->cond, cont_level) == -1)
  940. return -1;
  941. EATAB;
  942. #endif
  943. if (*l == 'u') {
  944. ++l;
  945. m->flag |= UNSIGNED;
  946. }
  947. m->type = get_type(l, &l);
  948. if (m->type == FILE_INVALID) {
  949. if (ms->flags & MAGIC_CHECK)
  950. file_magwarn(ms, "type `%s' invalid", l);
  951. return -1;
  952. }
  953. /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
  954. /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */
  955. m->mask_op = 0;
  956. if (*l == '~') {
  957. if (!IS_STRING(m->type))
  958. m->mask_op |= FILE_OPINVERSE;
  959. else if (ms->flags & MAGIC_CHECK)
  960. file_magwarn(ms, "'~' invalid for string types");
  961. ++l;
  962. }
  963. m->str_count = 0;
  964. m->str_flags = 0;
  965. m->num_mask = 0;
  966. if ((op = get_op(*l)) != -1) {
  967. if (!IS_STRING(m->type)) {
  968. uint64_t val;
  969. ++l;
  970. m->mask_op |= op;
  971. val = (uint64_t)strtoull(l, &t, 0);
  972. l = t;
  973. m->num_mask = file_signextend(ms, m, val);
  974. eatsize(&l);
  975. }
  976. else if (op == FILE_OPDIVIDE) {
  977. int have_count = 0;
  978. while (!isspace((unsigned char)*++l)) {
  979. switch (*l) {
  980. /* for portability avoid "case '0' ... '9':" */
  981. case '0': case '1': case '2':
  982. case '3': case '4': case '5':
  983. case '6': case '7': case '8':
  984. case '9': {
  985. if (have_count && ms->flags & MAGIC_CHECK)
  986. file_magwarn(ms,
  987. "multiple counts");
  988. have_count = 1;
  989. m->str_count = strtoul(l, &t, 0);
  990. l = t - 1;
  991. break;
  992. }
  993. case CHAR_COMPACT_BLANK:
  994. m->str_flags |= STRING_COMPACT_BLANK;
  995. break;
  996. case CHAR_COMPACT_OPTIONAL_BLANK:
  997. m->str_flags |=
  998. STRING_COMPACT_OPTIONAL_BLANK;
  999. break;
  1000. case CHAR_IGNORE_LOWERCASE:
  1001. m->str_flags |= STRING_IGNORE_LOWERCASE;
  1002. break;
  1003. case CHAR_IGNORE_UPPERCASE:
  1004. m->str_flags |= STRING_IGNORE_UPPERCASE;
  1005. break;
  1006. case CHAR_REGEX_OFFSET_START:
  1007. m->str_flags |= REGEX_OFFSET_START;
  1008. break;
  1009. default:
  1010. if (ms->flags & MAGIC_CHECK)
  1011. file_magwarn(ms,
  1012. "string extension `%c' invalid",
  1013. *l);
  1014. return -1;
  1015. }
  1016. /* allow multiple '/' for readability */
  1017. if (l[1] == '/' && !isspace((unsigned char)l[2]))
  1018. l++;
  1019. }
  1020. if (string_modifier_check(ms, m) == -1)
  1021. return -1;
  1022. }
  1023. else {
  1024. if (ms->flags & MAGIC_CHECK)
  1025. file_magwarn(ms, "invalid string op: %c", *t);
  1026. return -1;
  1027. }
  1028. }
  1029. /*
  1030. * We used to set mask to all 1's here, instead let's just not do
  1031. * anything if mask = 0 (unless you have a better idea)
  1032. */
  1033. EATAB;
  1034. switch (*l) {
  1035. case '>':
  1036. case '<':
  1037. /* Old-style anding: "0 byte &0x80 dynamically linked" */
  1038. case '&':
  1039. case '^':
  1040. case '=':
  1041. m->reln = *l;
  1042. ++l;
  1043. if (*l == '=') {
  1044. /* HP compat: ignore &= etc. */
  1045. ++l;
  1046. }
  1047. break;
  1048. case '!':
  1049. m->reln = *l;
  1050. ++l;
  1051. break;
  1052. default:
  1053. m->reln = '='; /* the default relation */
  1054. if (*l == 'x' && ((isascii((unsigned char)l[1]) &&
  1055. isspace((unsigned char)l[1])) || !l[1])) {
  1056. m->reln = *l;
  1057. ++l;
  1058. }
  1059. break;
  1060. }
  1061. /*
  1062. * Grab the value part, except for an 'x' reln.
  1063. */
  1064. if (m->reln != 'x' && getvalue(ms, m, &l, action))
  1065. return -1;
  1066. /*
  1067. * TODO finish this macro and start using it!
  1068. * #define offsetcheck {if (offset > HOWMANY-1)
  1069. * magwarn("offset too big"); }
  1070. */
  1071. /*
  1072. * Now get last part - the description
  1073. */
  1074. EATAB;
  1075. if (l[0] == '\b') {
  1076. ++l;
  1077. m->nospflag = 1;
  1078. } else if ((l[0] == '\\') && (l[1] == 'b')) {
  1079. ++l;
  1080. ++l;
  1081. m->nospflag = 1;
  1082. } else
  1083. m->nospflag = 0;
  1084. for (i = 0; (m->desc[i++] = *l++) != '\0' && i < sizeof(m->desc); )
  1085. continue;
  1086. if (i == sizeof(m->desc)) {
  1087. m->desc[sizeof(m->desc) - 1] = '\0';
  1088. if (ms->flags & MAGIC_CHECK)
  1089. file_magwarn(ms, "description `%s' truncated", m->desc);
  1090. }
  1091. /*
  1092. * We only do this check while compiling, or if any of the magic
  1093. * files were not compiled.
  1094. */
  1095. if (ms->flags & MAGIC_CHECK) {
  1096. if (check_format(ms, m) == -1)
  1097. return -1;
  1098. }
  1099. #ifndef COMPILE_ONLY
  1100. if (action == FILE_CHECK) {
  1101. file_mdump(m);
  1102. }
  1103. #endif
  1104. if (m->cont_level == 0)
  1105. ++(*nmentryp); /* make room for next */
  1106. return 0;
  1107. }
  1108. private int
  1109. check_format_type(const char *ptr, int type)
  1110. {
  1111. int quad = 0;
  1112. if (*ptr == '\0') {
  1113. /* Missing format string; bad */
  1114. return -1;
  1115. }
  1116. switch (type) {
  1117. case FILE_FMT_QUAD:
  1118. quad = 1;
  1119. /*FALLTHROUGH*/
  1120. case FILE_FMT_NUM:
  1121. if (*ptr == '-')
  1122. ptr++;
  1123. if (*ptr == '.')
  1124. ptr++;
  1125. while (isdigit((unsigned char)*ptr)) ptr++;
  1126. if (*ptr == '.')
  1127. ptr++;
  1128. while (isdigit((unsigned char)*ptr)) ptr++;
  1129. if (quad) {
  1130. if (*ptr++ != 'l')
  1131. return -1;
  1132. if (*ptr++ != 'l')
  1133. return -1;
  1134. }
  1135. switch (*ptr++) {
  1136. case 'l':
  1137. switch (*ptr++) {
  1138. case 'i':
  1139. case 'd':
  1140. case 'u':
  1141. case 'x':
  1142. case 'X':
  1143. return 0;
  1144. default:
  1145. return -1;
  1146. }
  1147. case 'h':
  1148. switch (*ptr++) {
  1149. case 'h':
  1150. switch (*ptr++) {
  1151. case 'i':
  1152. case 'd':
  1153. case 'u':
  1154. case 'x':
  1155. case 'X':
  1156. return 0;
  1157. default:
  1158. return -1;
  1159. }
  1160. case 'd':
  1161. return 0;
  1162. default:
  1163. return -1;
  1164. }
  1165. case 'i':
  1166. case 'c':
  1167. case 'd':
  1168. case 'u':
  1169. case 'x':
  1170. case 'X':
  1171. return 0;
  1172. default:
  1173. return -1;
  1174. }
  1175. case FILE_FMT_FLOAT:
  1176. case FILE_FMT_DOUBLE:
  1177. if (*ptr == '-')
  1178. ptr++;
  1179. if (*ptr == '.')
  1180. ptr++;
  1181. while (isdigit((unsigned char)*ptr)) ptr++;
  1182. if (*ptr == '.')
  1183. ptr++;
  1184. while (isdigit((unsigned char)*ptr)) ptr++;
  1185. switch (*ptr++) {
  1186. case 'e':
  1187. case 'E':
  1188. case 'f':
  1189. case 'F':
  1190. case 'g':
  1191. case 'G':
  1192. return 0;
  1193. default:
  1194. return -1;
  1195. }
  1196. case FILE_FMT_STR:
  1197. if (*ptr == '-')
  1198. ptr++;
  1199. while (isdigit((unsigned char )*ptr))
  1200. ptr++;
  1201. if (*ptr == '.') {
  1202. ptr++;
  1203. while (isdigit((unsigned char )*ptr))
  1204. ptr++;
  1205. }
  1206. switch (*ptr++) {
  1207. case 's':
  1208. return 0;
  1209. default:
  1210. return -1;
  1211. }
  1212. default:
  1213. /* internal error */
  1214. abort();
  1215. }
  1216. /*NOTREACHED*/
  1217. return -1;
  1218. }
  1219. /*
  1220. * Check that the optional printf format in description matches
  1221. * the type of the magic.
  1222. */
  1223. private int
  1224. check_format(struct magic_set *ms, struct magic *m)
  1225. {
  1226. char *ptr;
  1227. for (ptr = m->desc; *ptr; ptr++)
  1228. if (*ptr == '%')
  1229. break;
  1230. if (*ptr == '\0') {
  1231. /* No format string; ok */
  1232. return 1;
  1233. }
  1234. assert(file_nformats == file_nnames);
  1235. if (m->type >= file_nformats) {
  1236. file_error(ms, 0, "Internal error inconsistency between "
  1237. "m->type and format strings");
  1238. return -1;
  1239. }
  1240. if (file_formats[m->type] == FILE_FMT_NONE) {
  1241. file_error(ms, 0, "No format string for `%s' with description "
  1242. "`%s'", m->desc, file_names[m->type]);
  1243. return -1;
  1244. }
  1245. ptr++;
  1246. if (check_format_type(ptr, file_formats[m->type]) == -1) {
  1247. /*
  1248. * TODO: this error message is unhelpful if the format
  1249. * string is not one character long
  1250. */
  1251. file_error(ms, 0, "Printf format `%c' is not valid for type "
  1252. " `%s' in description `%s'", *ptr,
  1253. file_names[m->type], m->desc);
  1254. return -1;
  1255. }
  1256. for (; *ptr; ptr++) {
  1257. if (*ptr == '%') {
  1258. file_error(ms, 0,
  1259. "Too many format strings (should have at most one) "
  1260. "for `%s' with description `%s'",
  1261. file_names[m->type], m->desc);
  1262. return -1;
  1263. }
  1264. }
  1265. return 0;
  1266. }
  1267. /*
  1268. * Read a numeric value from a pointer, into the value union of a magic
  1269. * pointer, according to the magic type. Update the string pointer to point
  1270. * just after the number read. Return 0 for success, non-zero for failure.
  1271. */
  1272. private int
  1273. getvalue(struct magic_set *ms, struct magic *m, const char **p, int action)
  1274. {
  1275. int slen;
  1276. switch (m->type) {
  1277. case FILE_BESTRING16:
  1278. case FILE_LESTRING16:
  1279. case FILE_STRING:
  1280. case FILE_PSTRING:
  1281. case FILE_REGEX:
  1282. case FILE_SEARCH:
  1283. *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen, action);
  1284. if (*p == NULL) {
  1285. if (ms->flags & MAGIC_CHECK)
  1286. file_magwarn(ms, "cannot get string from `%s'",
  1287. m->value.s);
  1288. return -1;
  1289. }
  1290. m->vallen = slen;
  1291. return 0;
  1292. case FILE_FLOAT:
  1293. case FILE_BEFLOAT:
  1294. case FILE_LEFLOAT:
  1295. if (m->reln != 'x') {
  1296. char *ep;
  1297. #ifdef HAVE_STRTOF
  1298. m->value.f = strtof(*p, &ep);
  1299. #else
  1300. m->value.f = (float)strtod(*p, &ep);
  1301. #endif
  1302. *p = ep;
  1303. }
  1304. return 0;
  1305. case FILE_DOUBLE:
  1306. case FILE_BEDOUBLE:
  1307. case FILE_LEDOUBLE:
  1308. if (m->reln != 'x') {
  1309. char *ep;
  1310. m->value.d = strtod(*p, &ep);
  1311. *p = ep;
  1312. }
  1313. return 0;
  1314. default:
  1315. if (m->reln != 'x') {
  1316. char *ep;
  1317. m->value.q = file_signextend(ms, m,
  1318. (uint64_t)strtoull(*p, &ep, 0));
  1319. *p = ep;
  1320. eatsize(p);
  1321. }
  1322. return 0;
  1323. }
  1324. }
  1325. /*
  1326. * Convert a string containing C character escapes. Stop at an unescaped
  1327. * space or tab.
  1328. * Copy the converted version to "p", returning its length in *slen.
  1329. * Return updated scan pointer as function result.
  1330. */
  1331. private const char *
  1332. getstr(struct magic_set *ms, const char *s, char *p, int plen, int *slen, int action)
  1333. {
  1334. const char *origs = s;
  1335. char *origp = p;
  1336. char *pmax = p + plen - 1;
  1337. int c;
  1338. int val;
  1339. while ((c = *s++) != '\0') {
  1340. if (isspace((unsigned char) c))
  1341. break;
  1342. if (p >= pmax) {
  1343. file_error(ms, 0, "string too long: `%s'", origs);
  1344. return NULL;
  1345. }
  1346. if (c == '\\') {
  1347. switch(c = *s++) {
  1348. case '\0':
  1349. if (action == FILE_COMPILE)
  1350. file_magwarn(ms, "incomplete escape");
  1351. goto out;
  1352. case '\t':
  1353. if (action == FILE_COMPILE) {
  1354. file_magwarn(ms,
  1355. "escaped tab found, use \\t instead");
  1356. action++;
  1357. }
  1358. /*FALLTHROUGH*/
  1359. default:
  1360. if (action == FILE_COMPILE) {
  1361. if (isprint((unsigned char)c))
  1362. file_magwarn(ms,
  1363. "no need to escape `%c'", c);
  1364. else
  1365. file_magwarn(ms,
  1366. "unknown escape sequence: \\%03o", c);
  1367. }
  1368. /*FALLTHROUGH*/
  1369. /* space, perhaps force people to use \040? */
  1370. case ' ':
  1371. #if 0
  1372. /*
  1373. * Other things people escape, but shouldn't need to,
  1374. * so we disallow them
  1375. */
  1376. case '\'':
  1377. case '"':
  1378. case '?':
  1379. #endif
  1380. /* Relations */
  1381. case '>':
  1382. case '<':
  1383. case '&':
  1384. case '^':
  1385. case '=':
  1386. case '!':
  1387. /* and baskslash itself */
  1388. case '\\':
  1389. *p++ = (char) c;
  1390. break;
  1391. case 'a':
  1392. *p++ = '\a';
  1393. break;
  1394. case 'b':
  1395. *p++ = '\b';
  1396. break;
  1397. case 'f':
  1398. *p++ = '\f';
  1399. break;
  1400. case 'n':
  1401. *p++ = '\n';
  1402. break;
  1403. case 'r':
  1404. *p++ = '\r';
  1405. break;
  1406. case 't':
  1407. *p++ = '\t';
  1408. break;
  1409. case 'v':
  1410. *p++ = '\v';
  1411. break;
  1412. /* \ and up to 3 octal digits */
  1413. case '0':
  1414. case '1':
  1415. case '2':
  1416. case '3':
  1417. case '4':
  1418. case '5':
  1419. case '6':
  1420. case '7':
  1421. val = c - '0';
  1422. c = *s++; /* try for 2 */
  1423. if (c >= '0' && c <= '7') {
  1424. val = (val << 3) | (c - '0');
  1425. c = *s++; /* try for 3 */
  1426. if (c >= '0' && c <= '7')
  1427. val = (val << 3) | (c-'0');
  1428. else
  1429. --s;
  1430. }
  1431. else
  1432. --s;
  1433. *p++ = (char)val;
  1434. break;
  1435. /* \x and up to 2 hex digits */
  1436. case 'x':
  1437. val = 'x'; /* Default if no digits */
  1438. c = hextoint(*s++); /* Get next char */
  1439. if (c >= 0) {
  1440. val = c;
  1441. c = hextoint(*s++);
  1442. if (c >= 0)
  1443. val = (val << 4) + c;
  1444. else
  1445. --s;
  1446. } else
  1447. --s;
  1448. *p++ = (char)val;
  1449. break;
  1450. }
  1451. } else
  1452. *p++ = (char)c;
  1453. }
  1454. out:
  1455. *p = '\0';
  1456. *slen = p - origp;
  1457. return s;
  1458. }
  1459. /* Single hex char to int; -1 if not a hex char. */
  1460. private int
  1461. hextoint(int c)
  1462. {
  1463. if (!isascii((unsigned char) c))
  1464. return -1;
  1465. if (isdigit((unsigned char) c))
  1466. return c - '0';
  1467. if ((c >= 'a') && (c <= 'f'))
  1468. return c + 10 - 'a';
  1469. if (( c>= 'A') && (c <= 'F'))
  1470. return c + 10 - 'A';
  1471. return -1;
  1472. }
  1473. /*
  1474. * Print a string containing C character escapes.
  1475. */
  1476. protected void
  1477. file_showstr(FILE *fp, const char *s, size_t len)
  1478. {
  1479. char c;
  1480. for (;;) {
  1481. c = *s++;
  1482. if (len == ~0U) {
  1483. if (c == '\0')
  1484. break;
  1485. }
  1486. else {
  1487. if (len-- == 0)
  1488. break;
  1489. }
  1490. if (c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */
  1491. (void) fputc(c, fp);
  1492. else {
  1493. (void) fputc('\\', fp);
  1494. switch (c) {
  1495. case '\a':
  1496. (void) fputc('a', fp);
  1497. break;
  1498. case '\b':
  1499. (void) fputc('b', fp);
  1500. break;
  1501. case '\f':
  1502. (void) fputc('f', fp);
  1503. break;
  1504. case '\n':
  1505. (void) fputc('n', fp);
  1506. break;
  1507. case '\r':
  1508. (void) fputc('r', fp);
  1509. break;
  1510. case '\t':
  1511. (void) fputc('t', fp);
  1512. break;
  1513. case '\v':
  1514. (void) fputc('v', fp);
  1515. break;
  1516. default:
  1517. (void) fprintf(fp, "%.3o", c & 0377);
  1518. break;
  1519. }
  1520. }
  1521. }
  1522. }
  1523. /*
  1524. * eatsize(): Eat the size spec from a number [eg. 10UL]
  1525. */
  1526. private void
  1527. eatsize(const char **p)
  1528. {
  1529. const char *l = *p;
  1530. if (LOWCASE(*l) == 'u')
  1531. l++;
  1532. switch (LOWCASE(*l)) {
  1533. case 'l': /* long */
  1534. case 's': /* short */
  1535. case 'h': /* short */
  1536. case 'b': /* char/byte */
  1537. case 'c': /* char/byte */
  1538. l++;
  1539. /*FALLTHROUGH*/
  1540. default:
  1541. break;
  1542. }
  1543. *p = l;
  1544. }
  1545. /*
  1546. * handle a compiled file.
  1547. */
  1548. private int
  1549. apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp,
  1550. const char *fn)
  1551. {
  1552. int fd;
  1553. struct stat st;
  1554. uint32_t *ptr;
  1555. uint32_t version;
  1556. int needsbyteswap;
  1557. char buf[MAXPATHLEN];
  1558. char *dbname = mkdbname(fn, buf, sizeof(buf), 0);
  1559. void *mm = NULL;
  1560. if (dbname == NULL)
  1561. return -1;
  1562. if ((fd = open(dbname, O_RDONLY|O_BINARY)) == -1)
  1563. return -1;
  1564. if (fstat(fd, &st) == -1) {
  1565. file_error(ms, errno, "cannot stat `%s'", dbname);
  1566. goto error;
  1567. }
  1568. if (st.st_size < 16) {
  1569. file_error(ms, 0, "file `%s' is too small", dbname);
  1570. goto error;
  1571. }
  1572. #ifdef QUICK
  1573. if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE,
  1574. MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
  1575. file_error(ms, errno, "cannot map `%s'", dbname);
  1576. goto error;
  1577. }
  1578. #define RET 2
  1579. #else
  1580. if ((mm = malloc((size_t)st.st_size)) == NULL) {
  1581. file_oomem(ms, (size_t)st.st_size);
  1582. goto error;
  1583. }
  1584. if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
  1585. file_badread(ms);
  1586. goto error;
  1587. }
  1588. #define RET 1
  1589. #endif
  1590. *magicp = mm;
  1591. (void)close(fd);
  1592. fd = -1;
  1593. ptr = (uint32_t *)(void *)*magicp;
  1594. if (*ptr != MAGICNO) {
  1595. if (swap4(*ptr) != MAGICNO) {
  1596. file_error(ms, 0, "bad magic in `%s'");
  1597. goto error;
  1598. }
  1599. needsbyteswap = 1;
  1600. } else
  1601. needsbyteswap = 0;
  1602. if (needsbyteswap)
  1603. version = swap4(ptr[1]);
  1604. else
  1605. version = ptr[1];
  1606. if (version != VERSIONNO) {
  1607. file_error(ms, 0, "File %d.%d supports only %d version magic "
  1608. "files. `%s' is version %d", FILE_VERSION_MAJOR, patchlevel,
  1609. VERSIONNO, dbname, version);
  1610. goto error;
  1611. }
  1612. *nmagicp = (uint32_t)(st.st_size / sizeof(struct magic)) - 1;
  1613. (*magicp)++;
  1614. if (needsbyteswap)
  1615. byteswap(*magicp, *nmagicp);
  1616. return RET;
  1617. error:
  1618. if (fd != -1)
  1619. (void)close(fd);
  1620. if (mm) {
  1621. #ifdef QUICK
  1622. (void)munmap((void *)mm, (size_t)st.st_size);
  1623. #else
  1624. free(mm);
  1625. #endif
  1626. } else {
  1627. *magicp = NULL;
  1628. *nmagicp = 0;
  1629. }
  1630. return -1;
  1631. }
  1632. private const uint32_t ar[] = {
  1633. MAGICNO, VERSIONNO
  1634. };
  1635. /*
  1636. * handle an mmaped file.
  1637. */
  1638. private int
  1639. apprentice_compile(struct magic_set *ms, struct magic **magicp,
  1640. uint32_t *nmagicp, const char *fn)
  1641. {
  1642. int fd;
  1643. char buf[MAXPATHLEN];
  1644. char *dbname = mkdbname(fn, buf, sizeof(buf), 1);
  1645. if (dbname == NULL)
  1646. return -1;
  1647. if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0644)) == -1) {
  1648. file_error(ms, errno, "cannot open `%s'", dbname);
  1649. return -1;
  1650. }
  1651. if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) {
  1652. file_error(ms, errno, "error writing `%s'", dbname);
  1653. return -1;
  1654. }
  1655. if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET)
  1656. != sizeof(struct magic)) {
  1657. file_error(ms, errno, "error seeking `%s'", dbname);
  1658. return -1;
  1659. }
  1660. if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp))
  1661. != (ssize_t)(sizeof(struct magic) * *nmagicp)) {
  1662. file_error(ms, errno, "error writing `%s'", dbname);
  1663. return -1;
  1664. }
  1665. (void)close(fd);
  1666. return 0;
  1667. }
  1668. private const char ext[] = ".mgc";
  1669. /*
  1670. * make a dbname
  1671. */
  1672. private char *
  1673. mkdbname(const char *fn, char *buf, size_t bufsiz, int strip)
  1674. {
  1675. if (strip) {
  1676. const char *p;
  1677. if ((p = strrchr(fn, '/')) != NULL)
  1678. fn = ++p;
  1679. }
  1680. (void)snprintf(buf, bufsiz, "%s%s", fn, ext);
  1681. return buf;
  1682. }
  1683. /*
  1684. * Byteswap an mmap'ed file if needed
  1685. */
  1686. private void
  1687. byteswap(struct magic *magic, uint32_t nmagic)
  1688. {
  1689. uint32_t i;
  1690. for (i = 0; i < nmagic; i++)
  1691. bs1(&magic[i]);
  1692. }
  1693. /*
  1694. * swap a short
  1695. */
  1696. private uint16_t
  1697. swap2(uint16_t sv)
  1698. {
  1699. uint16_t rv;
  1700. uint8_t *s = (uint8_t *)(void *)&sv;
  1701. uint8_t *d = (uint8_t *)(void *)&rv;
  1702. d[0] = s[1];
  1703. d[1] = s[0];
  1704. return rv;
  1705. }
  1706. /*
  1707. * swap an int
  1708. */
  1709. private uint32_t
  1710. swap4(uint32_t sv)
  1711. {
  1712. uint32_t rv;
  1713. uint8_t *s = (uint8_t *)(void *)&sv;
  1714. uint8_t *d = (uint8_t *)(void *)&rv;
  1715. d[0] = s[3];
  1716. d[1] = s[2];
  1717. d[2] = s[1];
  1718. d[3] = s[0];
  1719. return rv;
  1720. }
  1721. /*
  1722. * swap a quad
  1723. */
  1724. private uint64_t
  1725. swap8(uint64_t sv)
  1726. {
  1727. uint32_t rv;
  1728. uint8_t *s = (uint8_t *)(void *)&sv;
  1729. uint8_t *d = (uint8_t *)(void *)&rv;
  1730. d[0] = s[3];
  1731. d[1] = s[2];
  1732. d[2] = s[1];
  1733. d[3] = s[0];
  1734. d[4] = s[7];
  1735. d[5] = s[6];
  1736. d[6] = s[5];
  1737. d[7] = s[4];
  1738. return rv;
  1739. }
  1740. /*
  1741. * byteswap a single magic entry
  1742. */
  1743. private void
  1744. bs1(struct magic *m)
  1745. {
  1746. m->cont_level = swap2(m->cont_level);
  1747. m->offset = swap4((uint32_t)m->offset);
  1748. m->in_offset = swap4((uint32_t)m->in_offset);
  1749. m->lineno = swap4((uint32_t)m->lineno);
  1750. if (IS_STRING(m->type)) {
  1751. m->str_count = swap4(m->str_count);
  1752. m->str_flags = swap4(m->str_flags);
  1753. }
  1754. else {
  1755. m->value.q = swap8(m->value.q);
  1756. m->num_mask = swap8(m->num_mask);
  1757. }
  1758. }