Rizin
unix-like reverse engineering framework and cli tools
apprentice.c
Go to the documentation of this file.
1 /* $OpenBSD: apprentice.c,v 1.29 2009/11/11 16:21:51 jsg Exp $ */
2 /*
3  * Copyright (c) Ian F. Darwin 1986-1995.
4  * Software written by Ian F. Darwin and others;
5  * maintained 1995-present by Christos Zoulas and others.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  * notice immediately at the beginning of the file, without modification,
12  * this list of conditions, and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 /*
30  * apprentice - make one pass through /etc/magic, learning its secrets.
31  */
32 #include <rz_userconf.h>
33 
34 #if !USE_LIB_MAGIC
35 
36 #include <rz_util.h>
37 #include <ctype.h>
38 #include "file.h"
39 #include "patchlevel.h"
40 
41 #if __UNIX__ && !defined(_MSC_VER)
42 #define QUICK 1
43 #include <sys/mman.h>
44 #include <sys/param.h>
45 #else
46 #define QUICK 0
47 #endif
48 
49 #ifdef _MSC_VER
50 #include <rz_windows.h>
51 #include <sys\stat.h>
52 #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
53 #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
54 #define MAXPATHLEN 255
55 #endif
56 
57 #define EATAB \
58  { \
59  while (isascii((ut8)*l) && isspace((ut8)*l)) { \
60  l++; \
61  } \
62  }
63 #define LOWCASE(l) (isupper((ut8)(l)) ? tolower((ut8)(l)) : (l))
64 
65 #ifndef MAP_FILE
66 #define MAP_FILE 0
67 #endif
68 
70  struct rz_magic *mp;
73 };
74 
75 static int magic_file_formats[FILE_NAMES_SIZE];
76 static const size_t file_nformats = FILE_NAMES_SIZE;
77 static const char *magic_file_names[FILE_NAMES_SIZE];
78 static const size_t file_nnames = FILE_NAMES_SIZE;
79 
80 static int getvalue(RzMagic *ms, struct rz_magic *, const char **, int);
81 static int hextoint(int);
82 static const char *getstr(RzMagic *, const char *, char *, int, int *, int);
83 static int parse(RzMagic *, struct rz_magic_entry **, ut32 *, const char *, size_t, int);
84 static int parse_mime(RzMagic *, struct rz_magic_entry **, ut32 *, const char *);
85 static void eatsize(const char **);
86 static int apprentice_1(RzMagic *, const char *, int, struct mlist *);
87 static size_t apprentice_r_magic_strength(const struct rz_magic *);
88 static int apprentice_sort(const void *, const void *);
89 static int apprentice_load(RzMagic *, struct rz_magic **, ut32 *, const char *, int);
90 static void byteswap(struct rz_magic *, ut32);
91 static void bs1(struct rz_magic *);
92 static ut16 swap2(ut16);
93 static ut32 swap4(ut32);
94 static ut64 swap8(ut64);
95 static char *mkdbname(const char *, int);
96 static int apprentice_map(RzMagic *, struct rz_magic **, ut32 *, const char *);
97 static int apprentice_compile(RzMagic *, struct rz_magic **, ut32 *, const char *);
98 static int check_format_type(const char *, int);
99 static int check_format(RzMagic *, struct rz_magic *);
100 static int get_op(char);
101 
102 static size_t maxmagic = 0;
103 static size_t magicsize = sizeof(struct rz_magic);
104 
105 static const char usg_hdr[] = "cont\toffset\ttype\topcode\tmask\tvalue\tdesc";
106 static const char mime_marker[] = "!:mime";
107 static const size_t mime_marker_len = sizeof(mime_marker) - 1;
108 
109 static const struct type_tbl_s {
110  const char name[16];
111  const size_t len;
112  const int type;
113  const int format;
114 } type_tbl[] = {
115 #define XX(s) s, (sizeof(s) - 1)
116 #define XX_NULL "", 0
117  { XX("byte"), FILE_BYTE, FILE_FMT_NUM },
118  { XX("short"), FILE_SHORT, FILE_FMT_NUM },
119  { XX("default"), FILE_DEFAULT, FILE_FMT_STR },
120  { XX("long"), FILE_LONG, FILE_FMT_NUM },
121  { XX("string"), FILE_STRING, FILE_FMT_STR },
122  { XX("date"), FILE_DATE, FILE_FMT_STR },
123  { XX("beshort"), FILE_BESHORT, FILE_FMT_NUM },
124  { XX("belong"), FILE_BELONG, FILE_FMT_NUM },
125  { XX("bedate"), FILE_BEDATE, FILE_FMT_STR },
126  { XX("leshort"), FILE_LESHORT, FILE_FMT_NUM },
127  { XX("lelong"), FILE_LELONG, FILE_FMT_NUM },
128  { XX("ledate"), FILE_LEDATE, FILE_FMT_STR },
129  { XX("pstring"), FILE_PSTRING, FILE_FMT_STR },
130  { XX("ldate"), FILE_LDATE, FILE_FMT_STR },
131  { XX("beldate"), FILE_BELDATE, FILE_FMT_STR },
132  { XX("leldate"), FILE_LELDATE, FILE_FMT_STR },
133  { XX("regex"), FILE_REGEX, FILE_FMT_STR },
134  { XX("bestring16"), FILE_BESTRING16, FILE_FMT_STR },
135  { XX("lestring16"), FILE_LESTRING16, FILE_FMT_STR },
136  { XX("search"), FILE_SEARCH, FILE_FMT_STR },
137  { XX("medate"), FILE_MEDATE, FILE_FMT_STR },
138  { XX("meldate"), FILE_MELDATE, FILE_FMT_STR },
139  { XX("melong"), FILE_MELONG, FILE_FMT_NUM },
140  { XX("quad"), FILE_QUAD, FILE_FMT_QUAD },
141  { XX("lequad"), FILE_LEQUAD, FILE_FMT_QUAD },
142  { XX("bequad"), FILE_BEQUAD, FILE_FMT_QUAD },
143  { XX("qdate"), FILE_QDATE, FILE_FMT_STR },
144  { XX("leqdate"), FILE_LEQDATE, FILE_FMT_STR },
145  { XX("beqdate"), FILE_BEQDATE, FILE_FMT_STR },
146  { XX("qldate"), FILE_QLDATE, FILE_FMT_STR },
147  { XX("leqldate"), FILE_LEQLDATE, FILE_FMT_STR },
148  { XX("beqldate"), FILE_BEQLDATE, FILE_FMT_STR },
149  { XX("float"), FILE_FLOAT, FILE_FMT_FLOAT },
150  { XX("befloat"), FILE_BEFLOAT, FILE_FMT_FLOAT },
151  { XX("lefloat"), FILE_LEFLOAT, FILE_FMT_FLOAT },
152  { XX("double"), FILE_DOUBLE, FILE_FMT_DOUBLE },
153  { XX("bedouble"), FILE_BEDOUBLE, FILE_FMT_DOUBLE },
154  { XX("ledouble"), FILE_LEDOUBLE, FILE_FMT_DOUBLE },
155  { XX_NULL, FILE_INVALID, FILE_FMT_NONE },
156 #undef XX
157 #undef XX_NULL
158 };
159 
160 static int get_type(const char *l, const char **t) {
161  const struct type_tbl_s *p;
162 
163  for (p = type_tbl; p->len; p++) {
164  if (strncmp(l, p->name, p->len) == 0) {
165  if (t) {
166  *t = l + p->len;
167  }
168  break;
169  }
170  }
171  return p->type;
172 }
173 
174 static void init_file_tables(void) {
175  static bool done = false;
176  const struct type_tbl_s *p;
177  if (done) {
178  return;
179  }
180  done = true;
181  for (p = type_tbl; p->len; p++) {
182  if (p->type >= FILE_NAMES_SIZE) {
183  continue;
184  }
185  magic_file_names[p->type] = p->name;
186  magic_file_formats[p->type] = p->format;
187  }
188 }
189 
190 /*
191  * Handle one file or directory.
192  */
193 static int apprentice_1(RzMagic *ms, const char *fn, int action, struct mlist *mlist) {
194  struct rz_magic *magic = NULL;
195  ut32 nmagic = 0;
196  struct mlist *ml;
197  int rv = -1;
198  int mapped;
199 
200  if (!ms) {
201  return -1;
202  }
203  ms->haderr = 0;
204  if (magicsize != FILE_MAGICSIZE) {
205  file_error(ms, 0, "magic element size %lu != %lu",
206  (unsigned long)(size_t)sizeof(*magic),
207  (unsigned long)FILE_MAGICSIZE);
208  return -1;
209  }
210 
211  ms->file = fn; // fix use of ms->file before being initialized
212  if (action == FILE_COMPILE) {
213  rv = apprentice_load(ms, &magic, &nmagic, fn, action);
214  if (rv != 0) {
215  return -1;
216  }
217  rv = apprentice_compile(ms, &magic, &nmagic, fn);
218  free(magic);
219  return rv;
220  }
221 
222  if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) {
223  // if (ms->flags & RZ_MAGIC_CHECK)
224  // file_magwarn(ms, "using regular magic file `%s'", fn);
225  rv = apprentice_load(ms, &magic, &nmagic, fn, action);
226  if (rv != 0) {
227  return -1;
228  }
229  }
230 
231  mapped = rv;
232 
233  if (!magic) {
234  file_delmagic(magic, mapped, nmagic);
235  return -1;
236  }
237 
238  if (!(ml = malloc(sizeof(*ml)))) {
239  file_delmagic(magic, mapped, nmagic);
240  file_oomem(ms, sizeof(*ml));
241  return -1;
242  }
243 
244  ml->magic = magic;
245  ml->nmagic = nmagic;
246  ml->mapped = mapped;
247 
248  mlist->prev->next = ml;
249  ml->prev = mlist->prev;
250  ml->next = mlist;
251  mlist->prev = ml;
252  return 0;
253 }
254 
255 void file_delmagic(struct rz_magic *p, int type, size_t entries) {
256  if (p) {
257  switch (type) {
258 #if QUICK
259  case 2:
260  p--;
261  (void)munmap((void *)p, sizeof(*p) * (entries + 1));
262  break;
263 #endif
264  case 1:
265  p--;
266  /*FALLTHROUGH*/
267  case 0:
268  RZ_FREE(p);
269  break;
270  default:
271  abort(); // do not abort, ever XXX this is a lib, so it shouldn just report an error
272  }
273  }
274 }
275 
276 /* const char *fn: list of magic files and directories */
277 struct mlist *file_apprentice(RzMagic *ms, const char *fn, int action) {
278  char *p, *mfn;
279  int file_err, errs = -1;
280  struct mlist *mlist;
281 
283  if (!fn) {
284  return NULL;
285  }
286 
287  if (!(mfn = strdup(fn))) {
288  file_oomem(ms, strlen(fn));
289  return NULL;
290  }
291  fn = mfn;
292 
293  if (!(mlist = malloc(sizeof(*mlist)))) {
294  free(mfn);
295  file_oomem(ms, sizeof(*mlist));
296  return NULL;
297  }
298  mlist->next = mlist->prev = mlist;
299 
300  while (fn) {
301  p = strchr(fn, PATHSEP);
302  if (p) {
303  *p++ = '\0';
304  }
305  if (*fn == '\0') {
306  break;
307  }
308  file_err = apprentice_1(ms, fn, action, mlist);
309  errs = RZ_MAX(errs, file_err);
310  fn = p;
311  }
312  if (errs == -1) {
313  free(mfn);
314  RZ_FREE(mlist);
315  file_error(ms, 0, "could not find any magic files!");
316  return NULL;
317  }
318  free(mfn);
319  return mlist;
320 }
321 
322 /*
323  * Get weight of this magic entry, for sorting purposes.
324  */
325 static size_t apprentice_r_magic_strength(const struct rz_magic *m) {
326 #define MULT 10
327  size_t val = 2 * MULT; /* baseline strength */
328 
329  switch (m->type) {
330  case FILE_DEFAULT: /* make sure this sorts last */
331  return 0;
332  case FILE_BYTE:
333  val += 1 * MULT;
334  break;
335  case FILE_SHORT:
336  case FILE_LESHORT:
337  case FILE_BESHORT:
338  val += 2 * MULT;
339  break;
340  case FILE_LONG:
341  case FILE_LELONG:
342  case FILE_BELONG:
343  case FILE_MELONG:
344  val += 4 * MULT;
345  break;
346  case FILE_PSTRING:
347  case FILE_STRING:
348  val += m->vallen * MULT;
349  break;
350  case FILE_BESTRING16:
351  case FILE_LESTRING16:
352  val += m->vallen * MULT / 2;
353  break;
354  case FILE_SEARCH:
355  case FILE_REGEX:
356  val += m->vallen * RZ_MAX(MULT / m->vallen, 1);
357  break;
358  case FILE_DATE:
359  case FILE_LEDATE:
360  case FILE_BEDATE:
361  case FILE_MEDATE:
362  case FILE_LDATE:
363  case FILE_LELDATE:
364  case FILE_BELDATE:
365  case FILE_MELDATE:
366  case FILE_FLOAT:
367  case FILE_BEFLOAT:
368  case FILE_LEFLOAT:
369  val += 4 * MULT;
370  break;
371  case FILE_QUAD:
372  case FILE_BEQUAD:
373  case FILE_LEQUAD:
374  case FILE_QDATE:
375  case FILE_LEQDATE:
376  case FILE_BEQDATE:
377  case FILE_QLDATE:
378  case FILE_LEQLDATE:
379  case FILE_BEQLDATE:
380  case FILE_DOUBLE:
381  case FILE_BEDOUBLE:
382  case FILE_LEDOUBLE:
383  val += 8 * MULT;
384  break;
385  default:
386  eprintf("Bad type %d\n", m->type);
387  abort();
388  }
389 
390  switch (m->reln) {
391  case 'x': /* matches anything penalize */
392  case '!': /* matches almost anything penalize */
393  val = 0;
394  break;
395  case '=': /* Exact match, prefer */
396  val += MULT;
397  break;
398  case '>':
399  case '<': /* comparison match reduce strength */
400  val -= 2 * MULT;
401  break;
402  case '^':
403  case '&': /* masking bits, we could count them too */
404  val -= MULT;
405  break;
406  default:
407  eprintf("Bad relation %c\n", m->reln);
408  abort();
409  }
410  return val ? val : 1; /* ensure we only return 0 for FILE_DEFAULT */
411 }
412 
413 /*
414  * Sort callback for sorting entries by "strength" (basically length)
415  */
416 static int apprentice_sort(const void *a, const void *b) {
417  const struct rz_magic_entry *ma = a;
418  const struct rz_magic_entry *mb = b;
419  size_t sa = apprentice_r_magic_strength(ma->mp);
420  size_t sb = apprentice_r_magic_strength(mb->mp);
421  if (sa == sb) {
422  return 0;
423  }
424  if (sa > sb) {
425  return -1;
426  }
427  return 1;
428 }
429 
430 static void set_test_type(struct rz_magic *mstart, struct rz_magic *m) {
431  switch (m->type) {
432  case FILE_BYTE:
433  case FILE_SHORT:
434  case FILE_LONG:
435  case FILE_DATE:
436  case FILE_BESHORT:
437  case FILE_BELONG:
438  case FILE_BEDATE:
439  case FILE_LESHORT:
440  case FILE_LELONG:
441  case FILE_LEDATE:
442  case FILE_LDATE:
443  case FILE_BELDATE:
444  case FILE_LELDATE:
445  case FILE_MEDATE:
446  case FILE_MELDATE:
447  case FILE_MELONG:
448  case FILE_QUAD:
449  case FILE_LEQUAD:
450  case FILE_BEQUAD:
451  case FILE_QDATE:
452  case FILE_LEQDATE:
453  case FILE_BEQDATE:
454  case FILE_QLDATE:
455  case FILE_LEQLDATE:
456  case FILE_BEQLDATE:
457  case FILE_FLOAT:
458  case FILE_BEFLOAT:
459  case FILE_LEFLOAT:
460  case FILE_DOUBLE:
461  case FILE_BEDOUBLE:
462  case FILE_LEDOUBLE:
463  case FILE_STRING:
464  case FILE_PSTRING:
465  case FILE_BESTRING16:
466  case FILE_LESTRING16:
467  /* binary test, set flag */
468  mstart->flag |= BINTEST;
469  break;
470  case FILE_REGEX:
471  case FILE_SEARCH:
472  /* binary test if pattern is not text */
473  if (file_looks_utf8((const ut8 *)m->value.s, m->vallen, NULL, NULL) == 0) {
474  mstart->flag |= BINTEST;
475  }
476  break;
477  case FILE_DEFAULT:
478  /* can't deduce anything; we shouldn't see this at the
479  top level anyway */
480  break;
481  case FILE_INVALID:
482  default:
483  /* invalid search type, but no need to complain here */
484  break;
485  }
486 }
487 
488 /*
489  * Load and parse from buffer.
490  */
491 static const char *bgets(char *line, size_t line_sz, const char *data) {
492  if (!*data) {
493  return NULL;
494  }
495  const char *nl = strchr(data, '\n');
496  const int nlsz = nl
497  ? nl - data + 1
498  : RZ_MIN(line_sz, strlen(data));
499  rz_str_ncpy(line, data, nlsz);
500  if (!data[nlsz]) {
501  return NULL;
502  }
503  return data + nlsz;
504 }
505 
506 static void load_b(RzMagic *ms, int action, const char *data, int *errs, struct rz_magic_entry **marray, ut32 *marraycount) {
507  char line[BUFSIZ];
508  size_t lineno = 0;
509  /* read and parse this file */
510  for (ms->line = 1; (data = bgets(line, sizeof(line), data)) != NULL; ms->line++) {
511  size_t len = strlen(line);
512  if (len == 0) { /* null line, garbage, etc */
513  continue;
514  }
515  if (line[len - 1] == '\n') {
516  lineno++;
517  line[len - 1] = '\0'; /* delete newline */
518  }
519  if (line[0] == '\0') { /* empty, do not parse */
520  continue;
521  }
522  if (line[0] == '#') { /* comment, do not parse */
523  continue;
524  }
525  if (len > mime_marker_len && !memcmp(line, mime_marker, mime_marker_len)) {
526  /* MIME type */
527  if (parse_mime(ms, marray, marraycount,
528  line + mime_marker_len) != 0) {
529  (*errs)++;
530  }
531  continue;
532  }
533  if (parse(ms, marray, marraycount, line, lineno, action) != 0) {
534  (*errs)++;
535  }
536  }
537 }
538 
539 /*
540  * Load and parse one file.
541  */
542 static void load_1(RzMagic *ms, int action, const char *file, int *errs, struct rz_magic_entry **marray, ut32 *marraycount) {
543  if (*file == '#') {
544  load_b(ms, action, file, errs, marray, marraycount);
545  return;
546  }
547  char line[BUFSIZ];
548  size_t lineno = 0;
549  FILE *f = rz_sys_fopen(ms->file = file, "r");
550  if (!f) {
551  if (errno != ENOENT) {
552  file_error(ms, errno, "cannot read magic file `%s'", file);
553  }
554  (*errs)++;
555  return;
556  }
557  /* read and parse this file */
558  for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; ms->line++) {
559  size_t len = strlen(line);
560  if (len == 0) { /* null line, garbage, etc */
561  continue;
562  }
563  if (line[len - 1] == '\n') {
564  lineno++;
565  line[len - 1] = '\0'; /* delete newline */
566  }
567  if (line[0] == '\0') { /* empty, do not parse */
568  continue;
569  }
570  if (line[0] == '#') { /* comment, do not parse */
571  continue;
572  }
573  if (len > mime_marker_len &&
574  memcmp(line, mime_marker, mime_marker_len) == 0) {
575  /* MIME type */
576  if (parse_mime(ms, marray, marraycount,
577  line + mime_marker_len) != 0) {
578  (*errs)++;
579  }
580  continue;
581  }
582  if (parse(ms, marray, marraycount, line, lineno, action) != 0) {
583  (*errs)++;
584  }
585  }
586  fclose(f);
587 }
588 
589 /*
590  * parse a file or directory of files
591  * const char *fn: name of magic file or directory
592  */
593 static int apprentice_load(RzMagic *ms, struct rz_magic **magicp, ut32 *nmagicp, const char *fn, int action) {
594  ut32 marraycount, i, mentrycount = 0, starttest;
595  struct rz_magic_entry *marray;
596  struct stat st;
597  int errs = 0;
598 #if __WINDOWS__
599  HANDLE hdir;
600  WIN32_FIND_DATAW entry;
601  wchar_t dir[MAX_PATH];
602  wchar_t *wcpath;
603  char *cfname;
604  char subfn[1024];
605 #else
606  DIR *dir;
607  struct dirent *d;
608  char subfn[MAXPATHLEN];
609 #endif
610  ms->flags |= RZ_MAGIC_CHECK; /* Enable checks for parsed files */
611 
612  maxmagic = MAXMAGIS;
613  if (!(marray = calloc(maxmagic, sizeof(*marray)))) {
614  file_oomem(ms, maxmagic * sizeof(*marray));
615  return -1;
616  }
617  marraycount = 0;
618 
619  /* print silly verbose header for USG compat. */
620  if (action == FILE_CHECK) {
621  eprintf("%s\n", usg_hdr);
622  }
623 
624  /* load directory or file */
625  if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) {
626 #if __WINDOWS__ && !defined(__CYGWIN__)
627  if ((wcpath = rz_utf8_to_utf16(fn))) {
628  swprintf(dir, _countof(dir), L"%ls\\*.*", wcpath);
629  hdir = FindFirstFileW(dir, &entry);
630  if (!(hdir == INVALID_HANDLE_VALUE)) {
631  do {
632  if (wcsncmp(entry.cFileName, L".", 1) == 0)
633  continue;
634  if ((cfname = rz_utf16_to_utf8(entry.cFileName))) {
635  snprintf(subfn, sizeof(subfn), "%s/%s", fn, cfname);
636  if (stat(subfn, &st) == 0 && S_ISREG(st.st_mode)) {
637  load_1(ms, action, subfn, &errs, &marray, &marraycount);
638  }
639  free(cfname);
640  }
641  } while (FindNextFileW(hdir, &entry));
642  FindClose(hdir);
643  }
644  free(wcpath);
645  } else {
646  errs++;
647  }
648 #else
649  dir = opendir(fn);
650  if (dir) {
651  while ((d = readdir(dir))) {
652  if (*d->d_name == '.') {
653  continue;
654  }
655  snprintf(subfn, sizeof(subfn), "%s/%s", fn, d->d_name);
656  if (stat(subfn, &st) == 0 && S_ISREG(st.st_mode)) {
657  load_1(ms, action, subfn, &errs, &marray, &marraycount);
658  }
659  // else perror (subfn);
660  }
661  closedir(dir);
662  } else {
663  errs++;
664  }
665 #endif
666  } else {
667  load_1(ms, action, fn, &errs, &marray, &marraycount);
668  }
669  if (errs) {
670  goto out;
671  }
672 
673  /* Set types of tests */
674  for (i = 0; i < marraycount;) {
675  if (marray[i].mp->cont_level != 0) {
676  i++;
677  continue;
678  }
679 
680  starttest = i;
681  do {
682  set_test_type(marray[starttest].mp, marray[i].mp);
683  if (ms->flags & RZ_MAGIC_DEBUG) {
684  (void)fprintf(stderr, "%s%s%s: %s\n",
685  marray[i].mp->mimetype,
686  marray[i].mp->mimetype[0] == '\0' ? "" : "; ",
687  marray[i].mp->desc[0] ? marray[i].mp->desc : "(no description)",
688  marray[i].mp->flag & BINTEST ? "binary" : "text");
689  if (marray[i].mp->flag & BINTEST) {
690 #define SYMLEN 4 /* strlen("text") */
691  char *p = strstr(marray[i].mp->desc, "text");
692  if (p && (p == marray[i].mp->desc || isspace((unsigned char)p[-1])) &&
693  (p + SYMLEN - marray[i].mp->desc == MAXstring ||
694  (p[SYMLEN] == '\0' || isspace((unsigned char)p[SYMLEN])))) {
695  (void)fprintf(stderr,
696  "*** Possible binary test for text type\n");
697  }
698  }
699  }
700  } while (++i < marraycount && marray[i].mp->cont_level != 0);
701  }
702 
703  qsort(marray, marraycount, sizeof(*marray), apprentice_sort);
704 
705  /*
706  * Make sure that any level 0 "default" line is last (if one exists).
707  */
708  for (i = 0; i < marraycount; i++) {
709  if (marray[i].mp->cont_level == 0 &&
710  marray[i].mp->type == FILE_DEFAULT) {
711  while (++i < marraycount) {
712  if (marray[i].mp->cont_level == 0) {
713  break;
714  }
715  }
716  if (i != marraycount) {
717  ms->line = marray[i].mp->lineno; /* XXX - Ugh! */
718  file_magwarn(ms, "level 0 \"default\" did not sort last");
719  }
720  break;
721  }
722  }
723 
724  for (i = 0; i < marraycount; i++) {
725  mentrycount += marray[i].cont_count;
726  }
727 
728  if (!(*magicp = malloc(1 + (sizeof(**magicp) * mentrycount)))) {
729  file_oomem(ms, sizeof(**magicp) * mentrycount);
730  errs++;
731  goto out;
732  }
733 
734  mentrycount = 0;
735  for (i = 0; i < marraycount; i++) {
736  (void)memcpy(*magicp + mentrycount, marray[i].mp,
737  marray[i].cont_count * sizeof(**magicp));
738  mentrycount += marray[i].cont_count;
739  }
740 out:
741  for (i = 0; i < marraycount; i++) {
742  free(marray[i].mp);
743  }
744  free(marray);
745  if (errs) {
746  *magicp = NULL;
747  *nmagicp = 0;
748  return errs;
749  }
750  *nmagicp = mentrycount;
751  return 0;
752 }
753 
754 /*
755  * extend the sign bit if the comparison is to be signed
756  */
757 ut64 file_signextend(RzMagic *ms, struct rz_magic *m, ut64 v) {
758  if (!(m->flag & UNSIGNED)) {
759  switch (m->type) {
760  /*
761  * Do not remove the casts below. They are
762  * vital. When later compared with the data,
763  * the sign extension must have happened.
764  */
765  case FILE_BYTE:
766  v = (char)v;
767  break;
768  case FILE_SHORT:
769  case FILE_BESHORT:
770  case FILE_LESHORT:
771  v = (short)v;
772  break;
773  case FILE_DATE:
774  case FILE_BEDATE:
775  case FILE_LEDATE:
776  case FILE_MEDATE:
777  case FILE_LDATE:
778  case FILE_BELDATE:
779  case FILE_LELDATE:
780  case FILE_MELDATE:
781  case FILE_LONG:
782  case FILE_BELONG:
783  case FILE_LELONG:
784  case FILE_MELONG:
785  case FILE_FLOAT:
786  case FILE_BEFLOAT:
787  case FILE_LEFLOAT:
788  v = (int32_t)v;
789  break;
790  case FILE_QUAD:
791  case FILE_BEQUAD:
792  case FILE_LEQUAD:
793  case FILE_QDATE:
794  case FILE_QLDATE:
795  case FILE_BEQDATE:
796  case FILE_BEQLDATE:
797  case FILE_LEQDATE:
798  case FILE_LEQLDATE:
799  case FILE_DOUBLE:
800  case FILE_BEDOUBLE:
801  case FILE_LEDOUBLE:
802  v = (int64_t)v;
803  break;
804  case FILE_STRING:
805  case FILE_PSTRING:
806  case FILE_BESTRING16:
807  case FILE_LESTRING16:
808  case FILE_REGEX:
809  case FILE_SEARCH:
810  case FILE_DEFAULT:
811  break;
812  default:
813  if (ms->flags & RZ_MAGIC_CHECK) {
814  file_magwarn(ms, "cannot happen: m->type=%d\n",
815  m->type);
816  }
817  return ~0U;
818  }
819  }
820  return v;
821 }
822 
823 static int string_modifier_check(RzMagic *ms, struct rz_magic *m) {
824  if ((ms->flags & RZ_MAGIC_CHECK) == 0) {
825  return 0;
826  }
827 
828  switch (m->type) {
829  case FILE_BESTRING16:
830  case FILE_LESTRING16:
831  if (m->str_flags != 0) {
832  file_magwarn(ms,
833  "no modifiers allowed for 16-bit strings\n");
834  return -1;
835  }
836  break;
837  case FILE_STRING:
838  case FILE_PSTRING:
839  if ((m->str_flags & REGEX_OFFSET_START) != 0) {
840  file_magwarn(ms,
841  "'/%c' only allowed on regex and search\n",
842  CHAR_REGEX_OFFSET_START);
843  return -1;
844  }
845  break;
846  case FILE_SEARCH:
847  if (m->str_range == 0) {
848  file_magwarn(ms,
849  "missing range; defaulting to %d\n",
850  STRING_DEFAULT_RANGE);
851  m->str_range = STRING_DEFAULT_RANGE;
852  return -1;
853  }
854  break;
855  case FILE_REGEX:
856  if ((m->str_flags & STRING_COMPACT_BLANK) != 0) {
857  file_magwarn(ms, "'/%c' not allowed on regex\n",
858  CHAR_COMPACT_BLANK);
859  return -1;
860  }
861  if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) {
862  file_magwarn(ms, "'/%c' not allowed on regex\n",
863  CHAR_COMPACT_OPTIONAL_BLANK);
864  return -1;
865  }
866  break;
867  default:
868  file_magwarn(ms, "coding error: m->type=%d\n",
869  m->type);
870  return -1;
871  }
872  return 0;
873 }
874 
875 static int get_op(char c) {
876  switch (c) {
877  case '&': return FILE_OPAND;
878  case '|': return FILE_OPOR;
879  case '^': return FILE_OPXOR;
880  case '+': return FILE_OPADD;
881  case '-': return FILE_OPMINUS;
882  case '*': return FILE_OPMULTIPLY;
883  case '/': return FILE_OPDIVIDE;
884  case '%': return FILE_OPMODULO;
885  default: return -1;
886  }
887 }
888 
889 static int get_cond(const char *l, const char **t) {
890  const struct cond_tbl_s *p;
891  static const struct cond_tbl_s {
892  char name[8];
893  size_t len;
894  int cond;
895  } cond_tbl[] = {
896  { "if", 2, COND_IF },
897  { "elif", 4, COND_ELIF },
898  { "else", 4, COND_ELSE },
899  { "", 0, COND_NONE },
900  };
901 
902  for (p = cond_tbl; p->len; p++) {
903  if (strncmp(l, p->name, p->len) == 0 &&
904  isspace((ut8)l[p->len])) {
905  if (t) {
906  *t = l + p->len;
907  }
908  break;
909  }
910  }
911  return p->cond;
912 }
913 
914 static int check_cond(RzMagic *ms, int cond, ut32 cont_level) {
915  int last_cond;
916  last_cond = ms->c.li[cont_level].last_cond;
917 
918  switch (cond) {
919  case COND_IF:
920  if (last_cond != COND_NONE && last_cond != COND_ELIF) {
921  if (ms->flags & RZ_MAGIC_CHECK) {
922  file_magwarn(ms, "syntax error: `if'");
923  }
924  return -1;
925  }
926  last_cond = COND_IF;
927  break;
928  case COND_ELIF:
929  if (last_cond != COND_IF && last_cond != COND_ELIF) {
930  if (ms->flags & RZ_MAGIC_CHECK) {
931  file_magwarn(ms, "syntax error: `elif'");
932  }
933  return -1;
934  }
935  last_cond = COND_ELIF;
936  break;
937  case COND_ELSE:
938  if (last_cond != COND_IF && last_cond != COND_ELIF) {
939  if (ms->flags & RZ_MAGIC_CHECK) {
940  file_magwarn(ms, "syntax error: `else'");
941  }
942  return -1;
943  }
944  last_cond = COND_NONE;
945  break;
946  case COND_NONE:
947  last_cond = COND_NONE;
948  break;
949  }
950 
951  ms->c.li[cont_level].last_cond = last_cond;
952  return 0;
953 }
954 
955 /*
956  * parse one line from magic file, put into magic[index++] if valid
957  */
958 static int parse(RzMagic *ms, struct rz_magic_entry **mentryp, ut32 *nmentryp, const char *line, size_t lineno, int action) {
959  static ut32 last_cont_level = 0;
960  size_t i;
961  struct rz_magic_entry *me;
962  struct rz_magic *m;
963  const char *l = line;
964  char *t;
965  int op;
966  ut32 cont_level = 0;
967 
968  for (; *l == '>'; l++, cont_level++) {
969  ;
970  }
971  if (cont_level == 0 || cont_level > last_cont_level) {
972  if (file_check_mem(ms, cont_level) == -1) {
973  return -1;
974  }
975  }
976  last_cont_level = cont_level;
977 #define ALLOC_CHUNK (size_t)10
978 #define ALLOC_INCR (size_t)200
979  if (cont_level != 0) {
980  if (*nmentryp == 0) {
981  file_error(ms, 0, "No current entry for continuation");
982  return -1;
983  }
984  me = &(*mentryp)[*nmentryp - 1];
985  if (me->cont_count == me->max_count) {
986  struct rz_magic *nm;
987  size_t cnt = me->max_count + ALLOC_CHUNK;
988  if (!(nm = realloc(me->mp, sizeof(*nm) * cnt))) {
989  file_oomem(ms, sizeof(*nm) * cnt);
990  return -1;
991  }
992  me->mp = nm;
993  me->max_count = cnt;
994  }
995  m = &me->mp[me->cont_count++];
996  (void)memset(m, 0, sizeof(*m));
997  m->cont_level = cont_level;
998  } else {
999  if (*nmentryp == maxmagic) {
1000  struct rz_magic_entry *mp;
1001 
1002  maxmagic += ALLOC_INCR;
1003  if (!(mp = realloc(*mentryp, sizeof(*mp) * maxmagic))) {
1004  file_oomem(ms, sizeof(*mp) * maxmagic);
1005  return -1;
1006  }
1007  (void)memset(&mp[*nmentryp], 0, sizeof(*mp) * ALLOC_INCR);
1008  *mentryp = mp;
1009  }
1010  me = &(*mentryp)[*nmentryp];
1011  if (!me->mp) {
1012  if (!(m = malloc(sizeof(*m) * ALLOC_CHUNK))) {
1013  file_oomem(ms, sizeof(*m) * ALLOC_CHUNK);
1014  return -1;
1015  }
1016  me->mp = m;
1017  me->max_count = ALLOC_CHUNK;
1018  } else {
1019  m = me->mp;
1020  }
1021  (void)memset(m, 0, sizeof(*m));
1022  m->cont_level = 0;
1023  me->cont_count = 1;
1024  }
1025  m->lineno = lineno;
1026 
1027  if (*l == '&') { /* m->cont_level == 0 checked below. */
1028  ++l; /* step over */
1029  m->flag |= OFFADD;
1030  }
1031  if (*l == '(') {
1032  ++l; /* step over */
1033  m->flag |= INDIR;
1034  if (m->flag & OFFADD) {
1035  m->flag = (m->flag & ~OFFADD) | INDIROFFADD;
1036  }
1037 
1038  if (*l == '&') { /* m->cont_level == 0 checked below */
1039  ++l; /* step over */
1040  m->flag |= OFFADD;
1041  }
1042  }
1043  /* Indirect offsets are not valid at level 0. */
1044  if (m->cont_level == 0 && (m->flag & (OFFADD | INDIROFFADD))) {
1045  if (ms->flags & RZ_MAGIC_CHECK) {
1046  file_magwarn(ms, "relative offset at level 0");
1047  }
1048  }
1049 
1050  /* get offset, then skip over it */
1051  m->offset = (ut32)strtoul(l, &t, 0);
1052  if ((l == t) && (ms->flags & RZ_MAGIC_CHECK)) {
1053  file_magwarn(ms, "offset `%s' invalid", l);
1054  }
1055  l = t;
1056 
1057  if (m->flag & INDIR) {
1058  m->in_type = FILE_LONG;
1059  m->in_offset = 0;
1060  /*
1061  * read [.lbs][+-]nnnnn)
1062  */
1063  if (*l == '.') {
1064  l++;
1065  switch (*l) {
1066  case 'l':
1067  m->in_type = FILE_LELONG;
1068  break;
1069  case 'L':
1070  m->in_type = FILE_BELONG;
1071  break;
1072  case 'm':
1073  m->in_type = FILE_MELONG;
1074  break;
1075  case 'h':
1076  case 's':
1077  m->in_type = FILE_LESHORT;
1078  break;
1079  case 'H':
1080  case 'S':
1081  m->in_type = FILE_BESHORT;
1082  break;
1083  case 'c':
1084  case 'b':
1085  case 'C':
1086  case 'B':
1087  m->in_type = FILE_BYTE;
1088  break;
1089  case 'e':
1090  case 'f':
1091  case 'g':
1092  m->in_type = FILE_LEDOUBLE;
1093  break;
1094  case 'E':
1095  case 'F':
1096  case 'G':
1097  m->in_type = FILE_BEDOUBLE;
1098  break;
1099  default:
1100  if (ms->flags & RZ_MAGIC_CHECK) {
1101  file_magwarn(ms,
1102  "indirect offset type `%c' invalid",
1103  *l);
1104  }
1105  break;
1106  }
1107  l++;
1108  }
1109 
1110  m->in_op = 0;
1111  if (*l == '~') {
1112  m->in_op |= FILE_OPINVERSE;
1113  l++;
1114  }
1115  if ((op = get_op(*l)) != -1) {
1116  m->in_op |= op;
1117  l++;
1118  }
1119  if (*l == '(') {
1120  m->in_op |= FILE_OPINDIRECT;
1121  l++;
1122  }
1123  if (isdigit((ut8)*l) || *l == '-') {
1124  m->in_offset = (int32_t)strtol(l, &t, 0);
1125  if (l == t) {
1126  if (ms->flags & RZ_MAGIC_CHECK) {
1127  file_magwarn(ms,
1128  "in_offset `%s' invalid", l);
1129  }
1130  }
1131  l = t;
1132  }
1133  if (*l++ != ')' ||
1134  ((m->in_op & FILE_OPINDIRECT) && *l++ != ')')) {
1135  if (ms->flags & RZ_MAGIC_CHECK) {
1136  file_magwarn(ms,
1137  "missing ')' in indirect offset");
1138  }
1139  }
1140  }
1141  EATAB;
1142 
1143  m->cond = get_cond(l, &l);
1144  if (check_cond(ms, m->cond, cont_level) == -1) {
1145  return -1;
1146  }
1147  EATAB;
1148 
1149  if (*l == 'u') {
1150  ++l;
1151  m->flag |= UNSIGNED;
1152  }
1153 
1154  m->type = get_type(l, &l);
1155  if (m->type == FILE_INVALID) {
1156  if (ms->flags & RZ_MAGIC_CHECK) {
1157  file_magwarn(ms, "type `%s' invalid", l);
1158  }
1159  return -1;
1160  }
1161 
1162  /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */
1163  /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */
1164 
1165  m->mask_op = 0;
1166  if (*l == '~') {
1167  if (!MAGIC_IS_STRING(m->type)) {
1168  m->mask_op |= FILE_OPINVERSE;
1169  } else if (ms->flags & RZ_MAGIC_CHECK) {
1170  file_magwarn(ms, "'~' invalid for string types");
1171  }
1172  ++l;
1173  }
1174  m->str_range = 0;
1175  m->str_flags = 0;
1176  m->num_mask = 0;
1177  if ((op = get_op(*l)) != -1) {
1178  if (!MAGIC_IS_STRING(m->type)) {
1179  ut64 val;
1180  ++l;
1181  m->mask_op |= op;
1182  val = (ut64)strtoull(l, &t, 0);
1183  l = t;
1184  m->num_mask = file_signextend(ms, m, val);
1185  eatsize(&l);
1186  } else if (op == FILE_OPDIVIDE) {
1187  int have_range = 0;
1188  while (!isspace((ut8) * ++l)) {
1189  switch (*l) {
1190  case '0':
1191  case '1':
1192  case '2':
1193  case '3':
1194  case '4':
1195  case '5':
1196  case '6':
1197  case '7':
1198  case '8':
1199  case '9':
1200  if (have_range &&
1201  (ms->flags & RZ_MAGIC_CHECK)) {
1202  file_magwarn(ms,
1203  "multiple ranges");
1204  }
1205  have_range = 1;
1206  m->str_range = strtoul(l, &t, 0);
1207  if (m->str_range == 0) {
1208  file_magwarn(ms,
1209  "zero range");
1210  }
1211  l = t - 1;
1212  break;
1213  case CHAR_COMPACT_BLANK:
1214  m->str_flags |= STRING_COMPACT_BLANK;
1215  break;
1216  case CHAR_COMPACT_OPTIONAL_BLANK:
1217  m->str_flags |=
1218  STRING_COMPACT_OPTIONAL_BLANK;
1219  break;
1220  case CHAR_IGNORE_LOWERCASE:
1221  m->str_flags |= STRING_IGNORE_LOWERCASE;
1222  break;
1223  case CHAR_IGNORE_UPPERCASE:
1224  m->str_flags |= STRING_IGNORE_UPPERCASE;
1225  break;
1226  case CHAR_REGEX_OFFSET_START:
1227  m->str_flags |= REGEX_OFFSET_START;
1228  break;
1229  default:
1230  if (ms->flags & RZ_MAGIC_CHECK) {
1231  file_magwarn(ms,
1232  "string extension `%c' invalid",
1233  *l);
1234  }
1235  return -1;
1236  }
1237  /* allow multiple '/' for readability */
1238  if (l[1] == '/' && !isspace((ut8)l[2])) {
1239  l++;
1240  }
1241  }
1242  if (string_modifier_check(ms, m) == -1) {
1243  return -1;
1244  }
1245  } else {
1246  if (ms->flags & RZ_MAGIC_CHECK) {
1247  file_magwarn(ms, "invalid string op: %c", *t);
1248  }
1249  return -1;
1250  }
1251  }
1252  /*
1253  * We used to set mask to all 1's here, instead let's just not do
1254  * anything if mask = 0 (unless you have a better idea)
1255  */
1256  EATAB;
1257 
1258  switch (*l) {
1259  case '>':
1260  case '<':
1261  /* Old-style anding: "0 byte &0x80 dynamically linked" */
1262  case '&':
1263  case '^':
1264  case '=':
1265  m->reln = *l;
1266  ++l;
1267  if (*l == '=') {
1268  /* HP compat: ignore &= etc. */
1269  ++l;
1270  }
1271  break;
1272  case '!':
1273  m->reln = *l;
1274  ++l;
1275  break;
1276  default:
1277  m->reln = '='; /* the default relation */
1278  if (*l == 'x' && ((isascii((ut8)l[1]) && isspace((ut8)l[1])) || !l[1])) {
1279  m->reln = *l;
1280  ++l;
1281  }
1282  break;
1283  }
1284  /*
1285  * Grab the value part, except for an 'x' reln.
1286  */
1287  if (m->reln != 'x' && getvalue(ms, m, &l, action)) {
1288  return -1;
1289  }
1290 
1291  /*
1292  * TODO finish this macro and start using it!
1293  * #define offsetcheck {if (offset > HOWMANY-1)
1294  * magwarn("offset too big"); }
1295  */
1296 
1297  /*
1298  * Now get last part - the description
1299  */
1300  EATAB;
1301  if (l[0] == '\b') {
1302  ++l;
1303  m->flag |= NOSPACE;
1304  } else if ((l[0] == '\\') && (l[1] == 'b')) {
1305  ++l;
1306  ++l;
1307  m->flag |= NOSPACE;
1308  }
1309  for (i = 0; (m->desc[i++] = *l++) != '\0' && i < sizeof(m->desc);) {
1310  }
1311  if (i == sizeof(m->desc)) {
1312  m->desc[sizeof(m->desc) - 1] = '\0';
1313  if (ms->flags & RZ_MAGIC_CHECK) {
1314  file_magwarn(ms, "description `%s' truncated", m->desc);
1315  }
1316  }
1317 
1318  /*
1319  * We only do this check while compiling, or if any of the magic
1320  * files were not compiled.
1321  */
1322  if (ms->flags & RZ_MAGIC_CHECK) {
1323  if (check_format(ms, m) == -1) {
1324  return -1;
1325  }
1326  }
1327  if (action == FILE_CHECK) {
1328  file_mdump(m);
1329  }
1330  m->mimetype[0] = '\0'; /* initialise MIME type to none */
1331  if (m->cont_level == 0) {
1332  ++(*nmentryp); /* make room for next */
1333  }
1334  return 0;
1335 }
1336 
1337 /*
1338  * parse a MIME annotation line from magic file, put into magic[index - 1]
1339  * if valid
1340  */
1341 static int parse_mime(RzMagic *ms, struct rz_magic_entry **mentryp, ut32 *nmentryp, const char *line) {
1342  size_t i;
1343  const char *l = line;
1344  struct rz_magic *m;
1345  struct rz_magic_entry *me;
1346 
1347  if (*nmentryp == 0) {
1348  file_error(ms, 0, "No current entry for MIME type");
1349  return -1;
1350  }
1351 
1352  me = &(*mentryp)[*nmentryp - 1];
1353  m = &me->mp[me->cont_count == 0 ? 0 : me->cont_count - 1];
1354 
1355  if (m->mimetype[0] != '\0') {
1356  file_error(ms, 0, "Current entry already has a MIME type: %s\n"
1357  "Description: %s\nNew type: %s",
1358  m->mimetype, m->desc, l);
1359  return -1;
1360  }
1361 
1362  EATAB;
1363  for (i = 0;
1364  *l && ((isascii((ut8)*l) && isalnum((ut8)*l)) || strchr("-+/.", *l)) && i < sizeof(m->mimetype);
1365  m->mimetype[i++] = *l++) {
1366  }
1367  if (i == sizeof(m->mimetype)) {
1368  m->desc[sizeof(m->mimetype) - 1] = '\0';
1369  if (ms->flags & RZ_MAGIC_CHECK) {
1370  file_magwarn(ms, "MIME type `%s' truncated %zu",
1371  m->mimetype, i);
1372  }
1373  } else {
1374  m->mimetype[i] = '\0';
1375  }
1376 
1377  return (i > 0) ? 0 : -1;
1378 }
1379 
1380 static int check_format_type(const char *ptr, int type) {
1381  int quad = 0;
1382  if (*ptr == '\0') {
1383  /* Missing format string; bad */
1384  return -1;
1385  }
1386 
1387  switch (type) {
1388  case FILE_FMT_QUAD:
1389  quad = 1;
1390  /*FALLTHROUGH*/
1391  case FILE_FMT_NUM:
1392  if (*ptr == '-') {
1393  ptr++;
1394  }
1395  if (*ptr == '.') {
1396  ptr++;
1397  }
1398  while (isdigit((ut8)*ptr)) {
1399  ptr++;
1400  }
1401  if (*ptr == '.') {
1402  ptr++;
1403  }
1404  while (isdigit((ut8)*ptr)) {
1405  ptr++;
1406  }
1407  if (quad) {
1408  if (*ptr++ != 'l') {
1409  return -1;
1410  }
1411  if (*ptr++ != 'l') {
1412  return -1;
1413  }
1414  }
1415  switch (*ptr++) {
1416  case 'l':
1417  switch (*ptr++) {
1418  case 'i':
1419  case 'd':
1420  case 'u':
1421  case 'x':
1422  case 'X':
1423  return 0;
1424  default:
1425  return -1;
1426  }
1427  case 'h':
1428  switch (*ptr++) {
1429  case 'h':
1430  switch (*ptr++) {
1431  case 'i':
1432  case 'd':
1433  case 'u':
1434  case 'x':
1435  case 'X':
1436  return 0;
1437  default:
1438  return -1;
1439  }
1440  case 'd':
1441  return 0;
1442  default:
1443  return -1;
1444  }
1445  case 'i':
1446  case 'c':
1447  case 'd':
1448  case 'u':
1449  case 'x':
1450  case 'X':
1451  return 0;
1452  default:
1453  return -1;
1454  }
1455  case FILE_FMT_FLOAT:
1456  case FILE_FMT_DOUBLE:
1457  if (*ptr == '-') {
1458  ptr++;
1459  }
1460  if (*ptr == '.') {
1461  ptr++;
1462  }
1463  while (isdigit((ut8)*ptr)) {
1464  ptr++;
1465  }
1466  if (*ptr == '.') {
1467  ptr++;
1468  }
1469  while (isdigit((ut8)*ptr)) {
1470  ptr++;
1471  }
1472 
1473  switch (*ptr++) {
1474  case 'e':
1475  case 'E':
1476  case 'f':
1477  case 'F':
1478  case 'g':
1479  case 'G':
1480  return 0;
1481 
1482  default:
1483  return -1;
1484  }
1485  case FILE_FMT_STR:
1486  if (*ptr == '-') {
1487  ptr++;
1488  }
1489  while (isdigit((ut8)*ptr)) {
1490  ptr++;
1491  }
1492  if (*ptr == '.') {
1493  ptr++;
1494  while (isdigit((ut8)*ptr)) {
1495  ptr++;
1496  }
1497  }
1498 
1499  if (*ptr++ == 's') {
1500  return 0;
1501  }
1502  return -1;
1503  default:
1504  /* internal error */
1505  abort();
1506  }
1507  /*NOTREACHED*/
1508  return -1;
1509 }
1510 
1511 /*
1512  * Check that the optional printf format in description matches
1513  * the type of the magic.
1514  */
1515 static int check_format(RzMagic *ms, struct rz_magic *m) {
1516  char *ptr;
1517 
1518  for (ptr = m->desc; *ptr; ptr++) {
1519  if (*ptr == '%') {
1520  break;
1521  }
1522  }
1523  if (*ptr == '\0') {
1524  /* No format string; ok */
1525  return 1;
1526  }
1527 
1528  if (file_nformats != file_nnames) {
1529  return -1;
1530  }
1531 
1532  if (m->type >= file_nformats) {
1533  file_magwarn(ms, "Internal error inconsistency between "
1534  "m->type and format strings");
1535  return -1;
1536  }
1537  if (magic_file_formats[m->type] == FILE_FMT_NONE) {
1538  file_magwarn(ms, "No format string for `%s' with description "
1539  "`%s'",
1540  m->desc, magic_file_names[m->type]);
1541  return -1;
1542  }
1543 
1544  ptr++;
1545  if (ptr && check_format_type(ptr, magic_file_formats[m->type]) == -1) {
1546  /*
1547  * TODO: this error message is unhelpful if the format
1548  * string is not one character long
1549  */
1550  file_magwarn(ms, "Printf format `%c' is not valid for type "
1551  "`%s' in description `%s'",
1552  ptr && *ptr ? *ptr : '?',
1553  magic_file_names[m->type], m->desc);
1554  return -1;
1555  }
1556 
1557  for (; *ptr; ptr++) {
1558  if (*ptr == '%') {
1559  file_magwarn(ms,
1560  "Too many format strings (should have at most one) "
1561  "for `%s' with description `%s'",
1562  magic_file_names[m->type], m->desc);
1563  return -1;
1564  }
1565  }
1566  return 0;
1567 }
1568 
1569 /*
1570  * Read a numeric value from a pointer, into the value union of a magic
1571  * pointer, according to the magic type. Update the string pointer to point
1572  * just after the number read. Return 0 for success, non-zero for failure.
1573  */
1574 static int getvalue(RzMagic *ms, struct rz_magic *m, const char **p, int action) {
1575  int slen;
1576 
1577  switch (m->type) {
1578  case FILE_BESTRING16:
1579  case FILE_LESTRING16:
1580  case FILE_STRING:
1581  case FILE_PSTRING:
1582  case FILE_REGEX:
1583  case FILE_SEARCH:
1584  *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen, action);
1585  if (!*p) {
1586  if (ms->flags & RZ_MAGIC_CHECK) {
1587  file_magwarn(ms, "cannot get string from `%s'",
1588  m->value.s);
1589  }
1590  return -1;
1591  }
1592  m->vallen = slen;
1593  if (m->type == FILE_PSTRING) {
1594  m->vallen++;
1595  }
1596  return 0;
1597  case FILE_FLOAT:
1598  case FILE_BEFLOAT:
1599  case FILE_LEFLOAT:
1600  if (m->reln != 'x') {
1601  char *ep;
1602 #ifdef HAVE_STRTOF
1603  m->value.f = strtof(*p, &ep);
1604 #else
1605  m->value.f = (float)strtod(*p, &ep);
1606 #endif
1607  *p = ep;
1608  }
1609  return 0;
1610  case FILE_DOUBLE:
1611  case FILE_BEDOUBLE:
1612  case FILE_LEDOUBLE:
1613  if (m->reln != 'x') {
1614  char *ep;
1615  m->value.d = strtod(*p, &ep);
1616  *p = ep;
1617  }
1618  return 0;
1619  default:
1620  if (m->reln != 'x') {
1621  char *ep;
1622  m->value.q = file_signextend(ms, m,
1623  (ut64)strtoull(*p, &ep, 0));
1624  *p = ep;
1625  eatsize(p);
1626  }
1627  return 0;
1628  }
1629 }
1630 
1631 /*
1632  * Convert a string containing C character escapes. Stop at an unescaped
1633  * space or tab.
1634  * Copy the converted version to "p", returning its length in *slen.
1635  * Return updated scan pointer as function result.
1636  */
1637 static const char *getstr(RzMagic *ms, const char *s, char *p, int plen, int *slen, int action) {
1638  const char *origs = s;
1639  char *origp = p;
1640  char *pmax = p + plen - 1;
1641  int c, val;
1642 
1643  while ((c = *s++) != '\0') {
1644  if (isspace((ut8)c)) {
1645  break;
1646  }
1647  if (p >= pmax) {
1648  file_error(ms, 0, "string too long: `%s'", origs);
1649  return NULL;
1650  }
1651  if (c == '\\') {
1652  switch ((c = *s++)) {
1653  case '\0':
1654  if (action == FILE_COMPILE) {
1655  file_magwarn(ms, "incomplete escape");
1656  }
1657  goto out;
1658  case '\t':
1659  if (action == FILE_COMPILE) {
1660  file_magwarn(ms,
1661  "escaped tab found, use \\t instead");
1662  action++;
1663  }
1664  /*FALLTHROUGH*/
1665  default:
1666  if (action == FILE_COMPILE) {
1667  if (isprint((ut8)c)) {
1668  file_magwarn(ms,
1669  "no need to escape `%c'", c);
1670  } else {
1671  file_magwarn(ms,
1672  "unknown escape sequence: \\%03o", c);
1673  }
1674  }
1675  /*FALLTHROUGH*/
1676  /* space, perhaps force people to use \040? */
1677  case ' ':
1678 #if 0
1679  /*
1680  * Other things people escape, but shouldn't need to,
1681  * so we disallow them
1682  */
1683  case '\'':
1684  case '"':
1685  case '?':
1686 #endif
1687  /* Relations */
1688  case '>':
1689  case '<':
1690  case '&':
1691  case '^':
1692  case '=':
1693  case '!':
1694  /* and baskslash itself */
1695  case '\\':
1696  *p++ = (char)c;
1697  break;
1698  case 'a': *p++ = '\a'; break;
1699  case 'b': *p++ = '\b'; break;
1700  case 'f': *p++ = '\f'; break;
1701  case 'n': *p++ = '\n'; break;
1702  case 'r': *p++ = '\r'; break;
1703  case 't': *p++ = '\t'; break;
1704  case 'v': *p++ = '\v'; break;
1705  /* \ and up to 3 octal digits */
1706  case '0':
1707  case '1':
1708  case '2':
1709  case '3':
1710  case '4':
1711  case '5':
1712  case '6':
1713  case '7':
1714  val = c - '0';
1715  c = *s++; /* try for 2 */
1716  if (c >= '0' && c <= '7') {
1717  val = (val << 3) | (c - '0');
1718  c = *s++; /* try for 3 */
1719  if (c >= '0' && c <= '7') {
1720  val = (val << 3) | (c - '0');
1721  } else {
1722  --s;
1723  }
1724  } else {
1725  --s;
1726  }
1727  *p++ = (char)val;
1728  break;
1729 
1730  /* \x and up to 2 hex digits */
1731  case 'x':
1732  val = 'x'; /* Default if no digits */
1733  c = hextoint(*s++); /* Get next char */
1734  if (c >= 0) {
1735  val = c;
1736  c = hextoint(*s++);
1737  if (c >= 0) {
1738  val = (val << 4) + c;
1739  } else {
1740  --s;
1741  }
1742  } else {
1743  --s;
1744  }
1745  *p++ = (char)val;
1746  break;
1747  }
1748  } else {
1749  *p++ = (char)c;
1750  }
1751  }
1752 out:
1753  *p = '\0';
1754  *slen = p - origp;
1755  return s;
1756 }
1757 
1758 /* Single hex char to int; -1 if not a hex char. */
1759 static int hextoint(int c) {
1760  if (!isascii((ut8)c)) {
1761  return -1;
1762  }
1763  if (isdigit((ut8)c)) {
1764  return c - '0';
1765  }
1766  if ((c >= 'a') && (c <= 'f')) {
1767  return c + 10 - 'a';
1768  }
1769  if ((c >= 'A') && (c <= 'F')) {
1770  return c + 10 - 'A';
1771  }
1772  return -1;
1773 }
1774 
1775 /*
1776  * Print a string containing C character escapes.
1777  */
1778 void file_showstr(FILE *fp, const char *s, size_t len) {
1779  for (;;) {
1780  char c = *s++;
1781  if (len == ~0U) {
1782  if (c == '\0') {
1783  break;
1784  }
1785  } else {
1786  if (len-- == 0) {
1787  break;
1788  }
1789  }
1790  if (c >= 040 && c <= 0176) { /* TODO isprint && !iscntrl */
1791  fputc(c, fp);
1792  } else {
1793  fputc('\\', fp);
1794  switch (c) {
1795  case '\a': fputc('a', fp); break;
1796  case '\b': fputc('b', fp); break;
1797  case '\f': fputc('f', fp); break;
1798  case '\n': fputc('n', fp); break;
1799  case '\r': fputc('r', fp); break;
1800  case '\t': fputc('t', fp); break;
1801  case '\v': fputc('v', fp); break;
1802  default: fprintf(fp, "%.3o", c & 0377); break;
1803  }
1804  }
1805  }
1806 }
1807 
1808 /*
1809  * eatsize(): Eat the size spec from a number [eg. 10UL]
1810  */
1811 static void eatsize(const char **p) {
1812  const char *l = *p;
1813 
1814  if (LOWCASE(*l) == 'u') {
1815  l++;
1816  }
1817 
1818  switch (LOWCASE(*l)) {
1819  case 'l': /* long */
1820  case 's': /* short */
1821  case 'h': /* short */
1822  case 'b': /* char/byte */
1823  case 'c': /* char/byte */
1824  l++;
1825  /*FALLTHROUGH*/
1826  default:
1827  break;
1828  }
1829 
1830  *p = l;
1831 }
1832 
1833 /*
1834  * handle a compiled file.
1835  */
1836 static int apprentice_map(RzMagic *ms, struct rz_magic **magicp, ut32 *nmagicp, const char *fn) {
1837  int fd;
1838  struct stat st;
1839  ut32 *ptr;
1840  ut32 version;
1841  int needsbyteswap;
1842  char *dbname = NULL;
1843  void *mm = NULL;
1844 
1845  dbname = mkdbname(fn, 0);
1846  if (!dbname) {
1847  goto error2;
1848  }
1849 
1850  if ((fd = rz_sys_open(dbname, O_RDONLY | O_BINARY, 0)) == -1) {
1851  goto error2;
1852  }
1853 
1854  if (fstat(fd, &st) == -1) {
1855  file_error(ms, errno, "cannot stat `%s'", dbname);
1856  goto error1;
1857  }
1858  if (st.st_size < 8) {
1859  file_error(ms, 0, "file `%s' is too small", dbname);
1860  goto error1;
1861  }
1862 
1863 #if QUICK
1864  if ((mm = mmap(0, (size_t)st.st_size, PROT_READ, // OPENBSDBUG |PROT_WRITE,
1865  MAP_PRIVATE | MAP_FILE, fd, (off_t)0)) == MAP_FAILED) {
1866  file_error(ms, errno, "cannot map `%s'", dbname);
1867  goto error1;
1868  }
1869 #define RET 2
1870 #else
1871  if (!(mm = malloc((size_t)st.st_size))) {
1872  file_oomem(ms, (size_t)st.st_size);
1873  goto error1;
1874  }
1875  if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) {
1876  file_badread(ms);
1877  goto error1;
1878  }
1879 #define RET 1
1880 #endif
1881  *magicp = mm;
1882  (void)close(fd);
1883  fd = -1;
1884  ptr = (ut32 *)(void *)*magicp;
1885 
1886  if (*ptr != MAGICNO) {
1887  if (swap4(*ptr) != MAGICNO) {
1888  // OPENBSDBUG file_error(ms, 0, "bad magic in `%s'");
1889  file_error(ms, 0, "bad magic in `%s'", dbname);
1890  goto error1;
1891  }
1892  needsbyteswap = 1;
1893  } else {
1894  needsbyteswap = 0;
1895  }
1896 
1897  version = needsbyteswap ? swap4(ptr[1]) : ptr[1];
1898  if (version != VERSIONNO) {
1899  file_error(ms, 0, "File %d.%d supports only %d version magic "
1900  "files. `%s' is version %d",
1902  VERSIONNO, dbname, version);
1903  goto error1;
1904  }
1905  *nmagicp = (ut32)(st.st_size / sizeof(struct rz_magic));
1906  if (*nmagicp > 0) {
1907  (*nmagicp)--;
1908  }
1909  (*magicp)++;
1910  if (needsbyteswap) {
1911  byteswap(*magicp, *nmagicp);
1912  }
1913  free(dbname);
1914  return RET;
1915 
1916 error1:
1917  if (fd != -1) {
1918  (void)close(fd);
1919  }
1920  if (mm) {
1921 #if QUICK
1922  (void)munmap((void *)mm, (size_t)st.st_size);
1923 #else
1924  free(mm);
1925 #endif
1926  } else {
1927  *magicp = NULL;
1928  *nmagicp = 0;
1929  }
1930 error2:
1931  free(dbname);
1932  return -1;
1933 }
1934 
1935 static const ut32 ar[] = {
1936  MAGICNO, VERSIONNO
1937 };
1938 
1939 /*
1940  * handle an mmaped file.
1941  */
1942 static int apprentice_compile(RzMagic *ms, struct rz_magic **magicp, ut32 *nmagicp, const char *fn) {
1943  int fd;
1944  char *dbname;
1945  int rv = -1;
1946 
1947  dbname = mkdbname(fn, 1);
1948 
1949  if (!dbname) {
1950  goto out;
1951  }
1952 
1953  if ((fd = rz_sys_open(dbname, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644)) == -1) {
1954  file_error(ms, errno, "cannot open `%s'", dbname);
1955  goto out;
1956  }
1957 
1958  if (write(fd, ar, sizeof(ar)) != (int)sizeof(ar)) {
1959  file_error(ms, errno, "error writing `%s'", dbname);
1960  goto beach;
1961  }
1962 
1963  if (lseek(fd, (off_t)sizeof(struct rz_magic), SEEK_SET) != sizeof(struct rz_magic)) {
1964  file_error(ms, errno, "error seeking `%s'", dbname);
1965  goto beach;
1966  }
1967 
1968  if (write(fd, *magicp, (sizeof(struct rz_magic) * *nmagicp)) != (int)(sizeof(struct rz_magic) * *nmagicp)) {
1969  file_error(ms, errno, "error writing `%s'", dbname);
1970  goto beach;
1971  }
1972 
1973  rv = 0;
1974 beach:
1975  (void)close(fd);
1976 out:
1977  free(dbname);
1978  return rv;
1979 }
1980 
1981 static const char ext[] = ".mgc";
1982 /*
1983  * make a dbname
1984  */
1985 static char *mkdbname(const char *fn, int strip) {
1986  char *buf = NULL;
1987  int fnlen, extlen;
1988  if (strip) {
1989  const char *p;
1990  if ((p = strrchr(fn, '/')) != NULL) {
1991  fn = ++p;
1992  }
1993  }
1994  fnlen = strlen(fn);
1995  extlen = strlen(ext);
1996  if (fnlen + extlen + 1 > MAXPATHLEN) {
1997  return NULL;
1998  }
1999  buf = malloc(fnlen + extlen + 1);
2000  if (buf) {
2001  memcpy(buf, fn, fnlen);
2002  memcpy(buf + fnlen, ext, extlen);
2003  buf[fnlen + extlen] = 0;
2004  }
2005  return buf;
2006 }
2007 
2008 /*
2009  * Byteswap an mmap'ed file if needed
2010  */
2011 static void byteswap(struct rz_magic *magic, ut32 nmagic) {
2012  ut32 i;
2013  for (i = 0; i < nmagic; i++) {
2014  bs1(&magic[i]);
2015  }
2016 }
2017 
2018 /*
2019  * swap a short
2020  */
2021 static ut16 swap2(ut16 sv) {
2022  ut16 rv;
2023  ut8 *s = (ut8 *)(void *)&sv;
2024  ut8 *d = (ut8 *)(void *)&rv;
2025  d[0] = s[1];
2026  d[1] = s[0];
2027  return rv;
2028 }
2029 
2030 /*
2031  * swap an int
2032  */
2033 static ut32 swap4(ut32 sv) {
2034  ut32 rv;
2035  ut8 *s = (ut8 *)(void *)&sv;
2036  ut8 *d = (ut8 *)(void *)&rv;
2037  d[0] = s[3];
2038  d[1] = s[2];
2039  d[2] = s[1];
2040  d[3] = s[0];
2041  return rv;
2042 }
2043 
2044 /*
2045  * swap a quad
2046  */
2047 static ut64 swap8(ut64 sv) {
2048  ut64 rv;
2049  ut8 *s = (ut8 *)(void *)&sv;
2050  ut8 *d = (ut8 *)(void *)&rv;
2051 #if 0
2052  d[0] = s[3];
2053  d[1] = s[2];
2054  d[2] = s[1];
2055  d[3] = s[0];
2056  d[4] = s[7];
2057  d[5] = s[6];
2058  d[6] = s[5];
2059  d[7] = s[4];
2060 #else
2061  d[0] = s[7];
2062  d[1] = s[6];
2063  d[2] = s[5];
2064  d[3] = s[4];
2065  d[4] = s[3];
2066  d[5] = s[2];
2067  d[6] = s[1];
2068  d[7] = s[0];
2069 #endif
2070  return rv;
2071 }
2072 
2073 /*
2074  * byteswap a single magic entry
2075  */
2076 static void bs1(struct rz_magic *m) {
2077  m->cont_level = swap2(m->cont_level);
2078  m->offset = swap4((ut32)m->offset);
2079  m->in_offset = swap4((ut32)m->in_offset);
2080  m->lineno = swap4((ut32)m->lineno);
2081  if (MAGIC_IS_STRING(m->type)) {
2082  m->str_range = swap4(m->str_range);
2083  m->str_flags = swap4(m->str_flags);
2084  } else {
2085  m->value.q = swap8(m->value.q);
2086  m->num_mask = swap8(m->num_mask);
2087  }
2088 }
2089 #endif
2090 
2091 #include "mdump.c"
size_t len
Definition: 6502dis.c:15
ut8 op
Definition: 6502dis.c:13
static char * version
Definition: acr.h:4
lzma_index ** i
Definition: index.h:629
static const size_t file_nnames
Definition: apprentice.c:78
static int check_format(RzMagic *, struct rz_magic *)
Definition: apprentice.c:1515
static int check_cond(RzMagic *ms, int cond, ut32 cont_level)
Definition: apprentice.c:914
void file_showstr(FILE *fp, const char *s, size_t len)
Definition: apprentice.c:1778
static int apprentice_sort(const void *, const void *)
Definition: apprentice.c:416
static const char ext[]
Definition: apprentice.c:1981
#define MAP_FILE
Definition: apprentice.c:66
static void load_1(RzMagic *ms, int action, const char *file, int *errs, struct rz_magic_entry **marray, ut32 *marraycount)
Definition: apprentice.c:542
ut64 file_signextend(RzMagic *ms, struct rz_magic *m, ut64 v)
Definition: apprentice.c:757
static const char mime_marker[]
Definition: apprentice.c:106
static const char usg_hdr[]
Definition: apprentice.c:105
static int apprentice_1(RzMagic *, const char *, int, struct mlist *)
Definition: apprentice.c:193
static void eatsize(const char **)
Definition: apprentice.c:1811
#define XX_NULL
#define EATAB
Definition: apprentice.c:57
static int hextoint(int)
Definition: apprentice.c:1759
static const size_t file_nformats
Definition: apprentice.c:76
static void set_test_type(struct rz_magic *mstart, struct rz_magic *m)
Definition: apprentice.c:430
static int apprentice_map(RzMagic *, struct rz_magic **, ut32 *, const char *)
Definition: apprentice.c:1836
#define ALLOC_INCR
static size_t magicsize
Definition: apprentice.c:103
static int get_cond(const char *l, const char **t)
Definition: apprentice.c:889
static int get_type(const char *l, const char **t)
Definition: apprentice.c:160
static int apprentice_compile(RzMagic *, struct rz_magic **, ut32 *, const char *)
Definition: apprentice.c:1942
static int getvalue(RzMagic *ms, struct rz_magic *, const char **, int)
Definition: apprentice.c:1574
static size_t maxmagic
Definition: apprentice.c:102
static int apprentice_load(RzMagic *, struct rz_magic **, ut32 *, const char *, int)
Definition: apprentice.c:593
static void byteswap(struct rz_magic *, ut32)
Definition: apprentice.c:2011
#define XX(s)
static ut32 swap4(ut32)
Definition: apprentice.c:2033
#define SYMLEN
static const char * getstr(RzMagic *, const char *, char *, int, int *, int)
Definition: apprentice.c:1637
static void load_b(RzMagic *ms, int action, const char *data, int *errs, struct rz_magic_entry **marray, ut32 *marraycount)
Definition: apprentice.c:506
static int magic_file_formats[FILE_NAMES_SIZE]
Definition: apprentice.c:75
#define LOWCASE(l)
Definition: apprentice.c:63
static void init_file_tables(void)
Definition: apprentice.c:174
static const char * magic_file_names[FILE_NAMES_SIZE]
Definition: apprentice.c:77
static const char * bgets(char *line, size_t line_sz, const char *data)
Definition: apprentice.c:491
static ut16 swap2(ut16)
Definition: apprentice.c:2021
static int parse(RzMagic *, struct rz_magic_entry **, ut32 *, const char *, size_t, int)
Definition: apprentice.c:958
struct mlist * file_apprentice(RzMagic *ms, const char *fn, int action)
Definition: apprentice.c:277
static size_t apprentice_r_magic_strength(const struct rz_magic *)
Definition: apprentice.c:325
static int string_modifier_check(RzMagic *ms, struct rz_magic *m)
Definition: apprentice.c:823
#define RET
#define MULT
void file_delmagic(struct rz_magic *p, int type, size_t entries)
Definition: apprentice.c:255
static int get_op(char)
Definition: apprentice.c:875
static ut64 swap8(ut64)
Definition: apprentice.c:2047
static const struct type_tbl_s type_tbl[]
static int parse_mime(RzMagic *, struct rz_magic_entry **, ut32 *, const char *)
Definition: apprentice.c:1341
static void bs1(struct rz_magic *)
Definition: apprentice.c:2076
#define ALLOC_CHUNK
static int check_format_type(const char *, int)
Definition: apprentice.c:1380
static const ut32 ar[]
Definition: apprentice.c:1935
static char * mkdbname(const char *, int)
Definition: apprentice.c:1985
static const size_t mime_marker_len
Definition: apprentice.c:107
ut16 val
Definition: armass64_const.h:6
int file_looks_utf8(const ut8 *, size_t, unichar *, size_t *)
Definition: ascmagic.c:605
static SblHeader sb
Definition: bin_mbn.c:26
RzList * entries(RzBinFile *bf)
Definition: bin_ne.c:98
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define S_ISDIR(mode)
Definition: compat.h:187
#define S_ISREG(mode)
Definition: compat.h:191
#define O_BINARY
Definition: cpipe.c:13
#define NULL
Definition: cris-opc.c:27
static static fork write
Definition: sflib.h:33
static static fork const void static count close
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset fstat
Definition: sflib.h:107
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep lseek
Definition: sflib.h:113
uint16_t ut16
uint32_t ut32
const char * v
Definition: dsignal.c:12
struct tab * done
Definition: enough.c:233
void file_badread(struct rz_magic_set *)
void file_oomem(struct rz_magic_set *, size_t)
void file_error(struct rz_magic_set *, int, const char *,...)
void file_mdump(struct rz_magic *)
Definition: mdump.c:47
void file_magwarn(struct rz_magic_set *, const char *,...)
Definition: mdump.c:172
int file_check_mem(struct rz_magic_set *, unsigned int)
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
#define INVALID_HANDLE_VALUE
Definition: iowin32.c:21
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static stat
Definition: sflib.h:131
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags mmap
Definition: sflib.h:115
static const char struct stat static buf struct stat static buf static idle const char static path static fd const char static len const void static prot const char struct module static image struct kernel_sym static table unsigned char static buf static fsuid unsigned struct dirent unsigned static count const struct iovec static count static pid const void static len static flags const struct sched_param static p static pid static policy struct timespec static tp static suid unsigned fn
Definition: sflib.h:186
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause const char static mode static sync const char const char static newpath const char static pathname unsigned long static filedes void static end_data_segment static handler static getegid char static len static pgid const char static path static newfd static getpgrp static euid const sigset_t static mask const char static len const gid_t static list const char const char static newpath const char static library readdir
Definition: sflib.h:120
static const void static count static fd struct stat static buf struct pollfd unsigned static timeout void static offset munmap
Definition: sflib.h:43
int type
Definition: mipsasm.c:17
string FILE
Definition: benchmark.py:21
line
Definition: setup.py:34
#define FILE_VERSION_MAJOR
Definition: patchlevel.h:3
#define patchlevel
Definition: patchlevel.h:4
void qsort(void *a, size_t n, size_t es, int(*cmp)(const void *, const void *))
Definition: qsort.h:130
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define UNSIGNED(n, x)
RZ_API size_t rz_str_ncpy(char *dst, const char *src, size_t n)
Secure string copy with null terminator.
Definition: str.c:923
RZ_API int rz_sys_open(const char *path, int perm, int mode)
Definition: sys.c:1740
RZ_API FILE * rz_sys_fopen(const char *path, const char *mode)
Definition: sys.c:1815
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
#define isspace(c)
Definition: safe-ctype.h:141
#define isdigit(c)
Definition: safe-ctype.h:131
#define isalnum(c)
Definition: safe-ctype.h:127
#define isprint(c)
Definition: safe-ctype.h:137
#define ENOENT
Definition: sftypes.h:112
#define O_WRONLY
Definition: sftypes.h:487
#define PROT_READ
Definition: sftypes.h:95
#define O_CREAT
Definition: sftypes.h:489
long int64_t
Definition: sftypes.h:32
int int32_t
Definition: sftypes.h:33
#define MAP_PRIVATE
Definition: sftypes.h:102
int size_t
Definition: sftypes.h:40
#define O_RDONLY
Definition: sftypes.h:486
int off_t
Definition: sftypes.h:41
#define O_TRUNC
Definition: sftypes.h:492
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
#define cond(bop, top, mask, flags)
Definition: sftypes.h:48
Definition: zipcmp.c:77
Definition: gzappend.c:170
Definition: z80asm.h:102
Definition: apprentice.c:69
ut32 cont_count
Definition: apprentice.c:71
struct rz_magic * mp
Definition: apprentice.c:70
ut32 max_count
Definition: apprentice.c:72
Definition: sftypes.h:80
const int type
Definition: apprentice.c:112
const int format
Definition: apprentice.c:113
const size_t len
Definition: apprentice.c:111
Definition: dis.c:32
DWORD * HANDLE
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static const z80_opcode fd[]
Definition: z80_tab.h:997
#define SEEK_SET
Definition: zip.c:88
#define L
Definition: zip_err_str.c:7
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115