Rizin
unix-like reverse engineering framework and cli tools
fsmagic.c
Go to the documentation of this file.
1 /* $OpenBSD: fsmagic.c,v 1.14 2009/10/27 23:59:37 deraadt 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  * fsmagic - magic based on filesystem info - directory, special files, etc.
31  */
32 
33 #include <rz_userconf.h>
34 
35 #if !USE_LIB_MAGIC
36 
37 #include <rz_magic.h>
38 #include "file.h"
39 #include <string.h>
40 #include <stdlib.h>
41 #include <sys/stat.h>
42 /* Since major is a function on SVR4, we cannot use `ifndef major'. */
43 #ifdef MAJOR_IN_MKDEV
44 #include <sys/mkdev.h>
45 #define HAVE_MAJOR
46 #endif
47 #ifdef MAJOR_IN_SYSMACROS
48 #include <sys/sysmacros.h>
49 #define HAVE_MAJOR
50 #endif
51 #ifdef major /* Might be defined in sys/types.h. */
52 #define HAVE_MAJOR
53 #endif
54 
55 #ifndef HAVE_MAJOR
56 #define major(dev) (((dev) >> 8) & 0xff)
57 #define minor(dev) ((dev)&0xff)
58 #endif
59 #undef HAVE_MAJOR
60 
61 static int bad_link(RzMagic *ms, int err, char *buf) {
62 #ifdef ELOOP
63  const char *errfmt = (err == ELOOP) ? "symbolic link in a loop" : "broken symbolic link to `%s'";
64 #else
65  const char *errfmt = "broken symbolic link to `%s'";
66 #endif
67  if (ms->flags & RZ_MAGIC_ERROR) {
68  file_error(ms, err, errfmt, buf);
69  return -1;
70  }
71  if (file_printf(ms, errfmt, buf) == -1)
72  return -1;
73  return 1;
74 }
75 
76 int file_fsmagic(struct rz_magic_set *ms, const char *fn, struct stat *sb) {
77  int ret = 0;
78  int mime = ms->flags & RZ_MAGIC_MIME;
79 #ifdef S_IFLNK
80  char buf[BUFSIZ + 4];
81  int nch;
82  struct stat tstatbuf;
83 #endif
84  if (!fn)
85  return 0;
86  /*
87  * Fstat is cheaper but fails for files you don't have read perms on.
88  * On 4.2BSD and similar systems, use lstat() to identify symlinks.
89  */
90 #ifdef S_IFLNK
91  if ((ms->flags & RZ_MAGIC_SYMLINK) == 0)
92  ret = lstat(fn, sb);
93  else
94 #endif
95  ret = stat(fn, sb); /* don't merge into if; see "ret =" above */
96 
97  if (ret) {
98  if (ms->flags & RZ_MAGIC_ERROR) {
99  file_error(ms, errno, "cannot stat `%s'", fn);
100  return -1;
101  }
102  if (file_printf(ms, "cannot open `%s' (%s)",
103  fn, strerror(errno)) == -1)
104  return -1;
105  return 1;
106  }
107 
108  if (mime) {
109  if ((sb->st_mode & S_IFMT) != S_IFREG) {
110  if ((mime & RZ_MAGIC_MIME_TYPE) &&
111  file_printf(ms, "application/x-not-regular-file") == -1)
112  return -1;
113  return 1;
114  }
115  } else {
116 #ifdef S_ISUID
117  if (sb->st_mode & S_ISUID)
118  if (file_printf(ms, "setuid ") == -1)
119  return -1;
120 #endif
121 #ifdef S_ISGID
122  if (sb->st_mode & S_ISGID)
123  if (file_printf(ms, "setgid ") == -1)
124  return -1;
125 #endif
126 #ifdef S_ISVTX
127  if (sb->st_mode & S_ISVTX)
128  if (file_printf(ms, "sticky ") == -1)
129  return -1;
130 #endif
131  }
132 
133  switch (sb->st_mode & S_IFMT) {
134  case S_IFDIR:
135  if (file_printf(ms, "directory") == -1)
136  return -1;
137  return 1;
138 #ifdef S_IFCHR
139  case S_IFCHR:
140  /*
141  * If -s has been specified, treat character special files
142  * like ordinary files. Otherwise, just report that they
143  * are block special files and go on to the next file.
144  */
145  if ((ms->flags & RZ_MAGIC_DEVICES) != 0)
146  break;
147 #ifdef HAVE_STAT_ST_RDEV
148 #ifdef dv_unit
149  if (file_printf(ms, "character special (%d/%d/%d)",
150  major(sb->st_rdev), dv_unit(sb->st_rdev),
151  dv_subunit(sb->st_rdev)) == -1)
152  return -1;
153 #else
154  if (file_printf(ms, "character special (%ld/%ld)",
155  (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
156  return -1;
157 #endif
158 #else
159  if (file_printf(ms, "character special") == -1)
160  return -1;
161 #endif
162  return 1;
163 #endif
164 #ifdef S_IFBLK
165  case S_IFBLK:
166  /*
167  * If -s has been specified, treat block special files
168  * like ordinary files. Otherwise, just report that they
169  * are block special files and go on to the next file.
170  */
171  if ((ms->flags & RZ_MAGIC_DEVICES) != 0)
172  break;
173 #ifdef HAVE_STAT_ST_RDEV
174 #ifdef dv_unit
175  if (file_printf(ms, "block special (%d/%d/%d)",
176  major(sb->st_rdev), dv_unit(sb->st_rdev),
177  dv_subunit(sb->st_rdev)) == -1)
178  return -1;
179 #else
180  if (file_printf(ms, "block special (%ld/%ld)",
181  (long)major(sb->st_rdev), (long)minor(sb->st_rdev)) == -1)
182  return -1;
183 #endif
184 #else
185  if (file_printf(ms, "block special") == -1)
186  return -1;
187 #endif
188  return 1;
189 #endif
190  /* TODO add code to handle V7 MUX and Blit MUX files */
191 #ifdef S_IFIFO
192  case S_IFIFO:
193  if ((ms->flags & RZ_MAGIC_DEVICES) != 0)
194  break;
195  if (file_printf(ms, "fifo (named pipe)") == -1)
196  return -1;
197  return 1;
198 #endif
199 #ifdef S_IFDOOR
200  case S_IFDOOR:
201  return (file_printf(ms, "door") == -1) ? -1 : 1;
202 #endif
203 #ifdef S_IFLNK
204  case S_IFLNK:
205  if ((nch = readlink(fn, buf, BUFSIZ - 1)) <= 0) {
206  if (ms->flags & RZ_MAGIC_ERROR) {
207  file_error(ms, errno, "unreadable symlink `%s'", fn);
208  return -1;
209  }
210  if (file_printf(ms,
211  "unreadable symlink `%s' (%s)", fn,
212  strerror(errno)) == -1)
213  return -1;
214  return 1;
215  }
216  buf[nch] = '\0'; /* readlink(2) does not do this */
217 
218  /* If broken symlink, say so and quit early. */
219  if (*buf == '/') {
220  if (stat(buf, &tstatbuf) < 0)
221  return bad_link(ms, errno, buf);
222  } else {
223  char *tmp;
224  char buf2[BUFSIZ + BUFSIZ + 4];
225 
226  if (!(tmp = strrchr(fn, '/'))) {
227  tmp = buf; /* in current directory anyway */
228  } else {
229  if (tmp - fn + 1 > BUFSIZ) {
230  if (ms->flags & RZ_MAGIC_ERROR) {
231  file_error(ms, 0, "path too long: `%s'", buf);
232  return -1;
233  }
234  if (file_printf(ms, "path too long: `%s'", fn) == -1)
235  return -1;
236  return 1;
237  }
238  snprintf(buf2, sizeof(buf2), "%s%s", fn, buf);
239  tmp = buf2;
240  }
241  if (stat(tmp, &tstatbuf) < 0)
242  return bad_link(ms, errno, buf);
243  }
244 
245  /* Otherwise, handle it. */
246  if ((ms->flags & RZ_MAGIC_SYMLINK) != 0) {
247  const char *p;
248  ms->flags &= RZ_MAGIC_SYMLINK;
249  p = rz_magic_file(ms, buf);
250  ms->flags |= RZ_MAGIC_SYMLINK;
251  return p != NULL ? 1 : -1;
252  } else { /* just print what it points to */
253  if (file_printf(ms, "symbolic link to `%s'", buf) == -1)
254  return -1;
255  }
256  return 1;
257 #endif
258 #ifdef S_IFSOCK
259  case S_IFSOCK:
260  if (file_printf(ms, "socket") == -1)
261  return -1;
262  return 1;
263 #endif
264  case S_IFREG:
265  break;
266  default:
267  file_error(ms, 0, "invalid mode 0%o", sb->st_mode);
268  return -1;
269  /*NOTREACHED*/
270  }
271  /*
272  * regular file, check next possibility
273  *
274  * If stat() tells us the file has zero length, report here that
275  * the file is empty, so we can skip all the work of opening and
276  * reading the file.
277  * But if the -s option has been given, we skip this optimization,
278  * since on some systems, stat() reports zero size for raw disk
279  * partitions. (If the block special device really has zero length,
280  * the fact that it is empty will be detected and reported correctly
281  * when we read the file.)
282  */
283  if ((ms->flags & RZ_MAGIC_DEVICES) == 0 && sb->st_size == 0) {
284  if ((!mime || (mime & RZ_MAGIC_MIME_TYPE)) &&
285  file_printf(ms, mime ? "application/x-empty" : "empty") == -1)
286  return -1;
287  return 1;
288  }
289  return 0;
290 }
291 #endif
static bool err
Definition: armass.c:435
static SblHeader sb
Definition: bin_mbn.c:26
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len readlink
Definition: sflib.h:65
void file_error(struct rz_magic_set *, int, const char *,...)
int file_printf(struct rz_magic_set *, const char *,...)
checking print the parsed form of the magic use in n conjunction with m to debug a new magic file n before installing it n mime
Definition: file_opts.h:30
int file_fsmagic(struct rz_magic_set *ms, const char *fn, struct stat *sb)
Definition: fsmagic.c:76
#define minor(dev)
Definition: fsmagic.c:57
static int bad_link(RzMagic *ms, int err, char *buf)
Definition: fsmagic.c:61
#define major(dev)
Definition: fsmagic.c:56
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
void * p
Definition: libc.cpp:67
static stat
Definition: sflib.h:131
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
RZ_API const char * rz_magic_file(RzMagic *ms, const char *inname)
Definition: magic.c:304
static uint32_t const uint8_t * buf2
Definition: memcmplen.h:43
static int nch(struct parse *, cset *)
Definition: regcomp.c:1375
Definition: sftypes.h:80
#define S_IFLNK
Definition: win.h:68