Rizin
unix-like reverse engineering framework and cli tools
magic.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2011-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 /* $OpenBSD: magic.c,v 1.8 2009/10/27 23:59:37 deraadt Exp $ */
4 
5 #include <rz_userconf.h>
6 #include <rz_magic.h>
7 
8 RZ_LIB_VERSION(rz_magic);
9 
10 #ifdef _MSC_VER
11 #include <io.h>
12 #include <sys\stat.h>
13 #define S_ISREG(m) (((m)&S_IFMT) == S_IFREG)
14 #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
15 #define S_IFIFO (-1)
16 #define S_ISFIFO(m) (((m)&S_IFIFO) == S_IFIFO)
17 #define MAXPATHLEN 255
18 #endif
19 
20 #if USE_LIB_MAGIC
21 
22 // we keep this code just to make debian happy, but we should use
23 // our own magic implementation for consistency reasons
24 #include <magic.h>
25 #undef RZ_API
26 #define RZ_API
27 
28 RZ_API RzMagic *rz_magic_new(int flags) {
29  return magic_open(flags);
30 }
31 RZ_API void rz_magic_free(RzMagic *m) {
32  if (m) {
33  magic_close(m);
34  }
35 }
36 RZ_API const char *rz_magic_file(RzMagic *m, const char *f) {
37  return magic_file(m, f);
38 }
39 RZ_API const char *rz_magic_descriptor(RzMagic *m, int fd) {
40  return magic_descriptor(m, fd);
41 }
42 RZ_API const char *rz_magic_buffer(RzMagic *m, const void *b, size_t s) {
43  return magic_buffer(m, b, s);
44 }
45 RZ_API const char *rz_magic_error(RzMagic *m) {
46  return magic_error(m);
47 }
48 RZ_API void rz_magic_setflags(RzMagic *m, int f) {
49  magic_setflags(m, f);
50 }
51 RZ_API bool rz_magic_load_buffer(RzMagic *m, const char *f) {
52  if (*f == '#') {
53  return magic_load(m, f) != -1;
54  } else {
55  eprintf("Magic buffers should start with #\n");
56  }
57  return false;
58 }
59 RZ_API bool rz_magic_load(RzMagic *m, const char *f) {
60  return magic_load(m, f) != -1;
61 }
62 RZ_API bool rz_magic_compile(RzMagic *m, const char *x) {
63  return magic_compile(m, x) != -1;
64 }
65 RZ_API bool rz_magic_check(RzMagic *m, const char *x) {
66  return magic_check(m, x) != -1;
67 }
68 RZ_API int rz_magic_errno(RzMagic *m) {
69  return magic_errno(m);
70 }
71 
72 #else
73 
74 /* use embedded magic library */
75 
76 #include "file.h"
77 
78 #ifndef PIPE_BUF
79 /* Get the PIPE_BUF from pathconf */
80 #ifdef _PC_PIPE_BUF
81 #define PIPE_BUF pathconf(".", _PC_PIPE_BUF)
82 #else
83 #define PIPE_BUF 512
84 #endif
85 #endif
86 
87 static void free_mlist(struct mlist *mlist) {
88  struct mlist *ml;
89  if (!mlist) {
90  return;
91  }
92  for (ml = mlist->next; ml != mlist;) {
93  struct mlist *next = ml->next;
94  struct rz_magic *mg = ml->magic;
95  file_delmagic(mg, ml->mapped, ml->nmagic);
96  free(ml);
97  ml = next;
98  }
99  free(ml);
100 }
101 
102 static int info_from_stat(RzMagic *ms, unsigned short md) {
103  /* We cannot open it, but we were able to stat it. */
104  if (md & 0222) {
105  if (file_printf(ms, "writable, ") == -1) {
106  return -1;
107  }
108  }
109  if (md & 0111) {
110  if (file_printf(ms, "executable, ") == -1) {
111  return -1;
112  }
113  }
114  if (S_ISREG(md)) {
115  if (file_printf(ms, "regular file, ") == -1) {
116  return -1;
117  }
118  }
119  if (file_printf(ms, "no read permission") == -1) {
120  return -1;
121  }
122  return 0;
123 }
124 
125 static void close_and_restore(const RzMagic *ms, const char *name, int fd, const struct stat *sb) {
126  if (fd >= 0) {
127  close(fd);
128  }
129 }
130 
131 static const char *file_or_fd(RzMagic *ms, const char *inname, int fd) {
132  bool ispipe = false;
133  int rv = -1;
134  unsigned char *buf;
135  struct stat sb;
136  int nbytes = 0; /* number of bytes read from a datafile */
137 
138  /*
139  * one extra for terminating '\0', and
140  * some overlapping space for matches near EOF
141  */
142 #define SLOP (1 + sizeof(union VALUETYPE))
143  if (!(buf = malloc(HOWMANY + SLOP))) {
144  return NULL;
145  }
146 
147  if (file_reset(ms) == -1) {
148  goto done;
149  }
150 
151  switch (file_fsmagic(ms, inname, &sb)) {
152  case -1: goto done; /* error */
153  case 0: break; /* nothing found */
154  default: rv = 0; goto done; /* matched it and printed type */
155  }
156 
157  if (!inname) {
158  if (fstat(fd, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
159  ispipe = true;
160  }
161  } else {
162  int flags = O_RDONLY | O_BINARY;
163 
164  if (stat(inname, &sb) == 0 && S_ISFIFO(sb.st_mode)) {
165 #if O_NONBLOCK
166  flags |= O_NONBLOCK;
167 #endif
168  ispipe = true;
169  }
170  errno = 0;
171  if ((fd = open(inname, flags)) < 0) {
172  eprintf("couldn't open file\n");
173  if (info_from_stat(ms, sb.st_mode) == -1) {
174  goto done;
175  }
176  rv = 0;
177  goto done;
178  }
179 #ifdef O_NONBLOCK
180  if ((flags = fcntl(fd, F_GETFL)) != -1) {
181  flags &= ~O_NONBLOCK;
182  (void)fcntl(fd, F_SETFL, flags);
183  }
184 #endif
185  }
186 
187  /*
188  * try looking at the first HOWMANY bytes
189  */
190 #ifdef O_NONBLOCK
191  if (ispipe) {
192  ssize_t r = 0;
193 
194  // while ((r = sread(fd, (void *)&buf[nbytes],
195  while ((r = read(fd, (void *)&buf[nbytes],
196  (size_t)(HOWMANY - nbytes))) > 0) {
197  nbytes += r;
198  if (r < PIPE_BUF) {
199  break;
200  }
201  }
202 
203  if (nbytes == 0) {
204  /* We can not read it, but we were able to stat it. */
205  if (info_from_stat(ms, sb.st_mode) == -1) {
206  goto done;
207  }
208  rv = 0;
209  goto done;
210  }
211  } else {
212 #endif
213  if ((nbytes = read(fd, (char *)buf, HOWMANY)) == -1) {
214  file_error(ms, errno, "cannot read `%s'", inname);
215  goto done;
216  }
217 #ifdef O_NONBLOCK
218  }
219 #endif
220 
221  (void)memset(buf + nbytes, 0, SLOP); /* NUL terminate */
222  if (file_buffer(ms, fd, inname, buf, (size_t)nbytes) == -1) {
223  goto done;
224  }
225  rv = 0;
226 done:
227  free(buf);
228  close_and_restore(ms, inname, fd, &sb);
229  return rv == 0 ? file_getbuffer(ms) : NULL;
230 }
231 
232 /* API */
233 
234 // TODO: reinitialize all the time
235 RZ_API RzMagic *rz_magic_new(int flags) {
236  RzMagic *ms = RZ_NEW0(RzMagic);
237  if (!ms) {
238  return NULL;
239  }
241  ms->o.buf = ms->o.pbuf = NULL;
242  ms->c.li = malloc((ms->c.len = 10) * sizeof(*ms->c.li));
243  if (!ms->c.li) {
244  free(ms);
245  return NULL;
246  }
247  file_reset(ms);
248  ms->mlist = NULL;
249  ms->file = "unknown";
250  ms->line = 0;
251  return ms;
252 }
253 
254 RZ_API void rz_magic_free(RzMagic *ms) {
255  if (ms) {
256  free_mlist(ms->mlist);
257  free(ms->o.pbuf);
258  free(ms->o.buf);
259  free(ms->c.li);
260  free(ms);
261  }
262 }
263 
264 RZ_API bool rz_magic_load_buffer(RzMagic *ms, const char *magicdata) {
265  if (*magicdata == '#') {
266  struct mlist *ml = file_apprentice(ms, magicdata, FILE_LOAD);
267  if (ml) {
268  free_mlist(ms->mlist);
269  ms->mlist = ml;
270  return true;
271  }
272  } else {
273  eprintf("Magic buffers should start with #\n");
274  }
275  return false;
276 }
277 
278 RZ_API bool rz_magic_load(RzMagic *ms, const char *magicfile) {
279  struct mlist *ml = file_apprentice(ms, magicfile, FILE_LOAD);
280  if (ml) {
281  free_mlist(ms->mlist);
282  ms->mlist = ml;
283  return true;
284  }
285  return false;
286 }
287 
288 RZ_API bool rz_magic_compile(RzMagic *ms, const char *magicfile) {
289  struct mlist *ml = file_apprentice(ms, magicfile, FILE_COMPILE);
290  free_mlist(ml);
291  return ml != NULL;
292 }
293 
294 RZ_API bool rz_magic_check(RzMagic *ms, const char *magicfile) {
295  struct mlist *ml = file_apprentice(ms, magicfile, FILE_CHECK);
296  free_mlist(ml);
297  return ml != NULL;
298 }
299 
300 RZ_API const char *rz_magic_descriptor(RzMagic *ms, int fd) {
301  return file_or_fd(ms, NULL, fd);
302 }
303 
304 RZ_API const char *rz_magic_file(RzMagic *ms, const char *inname) {
305  return file_or_fd(ms, inname, 0); // 0 = stdin
306 }
307 
308 RZ_API const char *rz_magic_buffer(RzMagic *ms, const void *buf, size_t nb) {
309  if (file_reset(ms) == -1) {
310  return NULL;
311  }
312  if (file_buffer(ms, -1, NULL, buf, nb) == -1) {
313  return NULL;
314  }
315  return file_getbuffer(ms);
316 }
317 
318 RZ_API const char *rz_magic_error(RzMagic *ms) {
319  if (ms && ms->haderr) {
320  return ms->o.buf;
321  }
322  return NULL;
323 }
324 
325 RZ_API int rz_magic_errno(RzMagic *ms) {
326  if (ms && ms->haderr) {
327  return ms->error;
328  }
329  return 0;
330 }
331 
332 RZ_API void rz_magic_setflags(RzMagic *ms, int flags) {
333  if (ms) {
334  ms->flags = flags;
335  }
336 }
337 #endif
struct mlist * file_apprentice(RzMagic *ms, const char *fn, int action)
Definition: apprentice.c:277
void file_delmagic(struct rz_magic *p, int type, size_t entries)
Definition: apprentice.c:255
static SblHeader sb
Definition: bin_mbn.c:26
#define S_ISREG(mode)
Definition: compat.h:191
#define O_BINARY
Definition: cpipe.c:13
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
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 nbytes
Definition: sflib.h:113
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 fcntl
Definition: sflib.h:79
struct tab * done
Definition: enough.c:233
int file_reset(struct rz_magic_set *)
const char * file_getbuffer(struct rz_magic_set *)
void file_error(struct rz_magic_set *, int, const char *,...)
int file_buffer(struct rz_magic_set *, int, const char *, const void *, size_t)
int file_fsmagic(struct rz_magic_set *, const char *, struct stat *)
Definition: fsmagic.c:76
int file_printf(struct rz_magic_set *, const char *,...)
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
return memset(p, 0, total)
void * malloc(size_t size)
Definition: malloc.c:123
static stat
Definition: sflib.h:131
static void free_mlist(struct mlist *mlist)
Definition: magic.c:87
RZ_API const char * rz_magic_descriptor(RzMagic *ms, int fd)
Definition: magic.c:300
RZ_API int rz_magic_errno(RzMagic *ms)
Definition: magic.c:325
RZ_LIB_VERSION(rz_magic)
static int info_from_stat(RzMagic *ms, unsigned short md)
Definition: magic.c:102
static const char * file_or_fd(RzMagic *ms, const char *inname, int fd)
Definition: magic.c:131
static void close_and_restore(const RzMagic *ms, const char *name, int fd, const struct stat *sb)
Definition: magic.c:125
RZ_API const char * rz_magic_buffer(RzMagic *ms, const void *buf, size_t nb)
Definition: magic.c:308
#define SLOP
RZ_API const char * rz_magic_file(RzMagic *ms, const char *inname)
Definition: magic.c:304
RZ_API bool rz_magic_check(RzMagic *ms, const char *magicfile)
Definition: magic.c:294
RZ_API RzMagic * rz_magic_new(int flags)
Definition: magic.c:235
RZ_API bool rz_magic_compile(RzMagic *ms, const char *magicfile)
Definition: magic.c:288
RZ_API bool rz_magic_load_buffer(RzMagic *ms, const char *magicdata)
Definition: magic.c:264
RZ_API bool rz_magic_load(RzMagic *ms, const char *magicfile)
Definition: magic.c:278
RZ_API void rz_magic_setflags(RzMagic *ms, int flags)
Definition: magic.c:332
RZ_API const char * rz_magic_error(RzMagic *ms)
Definition: magic.c:318
#define PIPE_BUF
Definition: magic.c:83
RZ_API void rz_magic_free(RzMagic *ms)
Definition: magic.c:254
int x
Definition: mipsasm.c:20
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define RZ_NEW0(x)
Definition: rz_types.h:284
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define F_GETFL
Definition: sftypes.h:506
#define O_NONBLOCK
Definition: sftypes.h:494
#define O_RDONLY
Definition: sftypes.h:486
#define F_SETFL
Definition: sftypes.h:507
int ssize_t
Definition: sftypes.h:39
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
Definition: z80asm.h:102
Definition: sftypes.h:80
static const z80_opcode fd[]
Definition: z80_tab.h:997
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115