2 * Copyright (c) Christos Zoulas 2003.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice immediately at the beginning of the file, without modification,
10 * this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/types.h>
36 #include <sys/param.h> /* for MAXPATHLEN */
41 #include <limits.h> /* for PIPE_BUF */
43 #if defined(HAVE_UTIMES)
44 # include <sys/time.h>
45 #elif defined(HAVE_UTIME)
46 # if defined(HAVE_SYS_UTIME_H)
47 # include <sys/utime.h>
48 # elif defined(HAVE_UTIME_H)
54 #include <unistd.h> /* for read() */
61 #include <netinet/in.h> /* for byte swapping */
63 #include "patchlevel.h"
66 FILE_RCSID("@(#)$File: magic.c,v 1.45 2007/12/27 16:35:59 christos Exp $")
70 private char *apptypeName
= NULL
;
71 protected int file_os2_apptype(struct magic_set
*ms
, const char *fn
,
72 const void *buf
, size_t nb
);
75 private void free_mlist(struct mlist
*);
76 private void close_and_restore(const struct magic_set
*, const char *, int,
78 private int info_from_stat(struct magic_set
*, mode_t
);
80 private const char *file_or_fd(struct magic_set
*, const char *, int);
84 #define STDIN_FILENO 0
87 public struct magic_set
*
92 if ((ms
= calloc((size_t)1, sizeof(struct magic_set
))) == NULL
)
95 if (magic_setflags(ms
, flags
) == -1) {
100 ms
->o
.ptr
= ms
->o
.buf
= malloc(ms
->o
.left
= ms
->o
.size
= 1024);
101 if (ms
->o
.buf
== NULL
)
104 ms
->o
.pbuf
= malloc(ms
->o
.psize
= 1024);
105 if (ms
->o
.pbuf
== NULL
)
108 ms
->c
.li
= malloc((ms
->c
.len
= 10) * sizeof(*ms
->c
.li
));
109 if (ms
->c
.li
== NULL
)
115 ms
->file
= "unknown";
128 free_mlist(struct mlist
*mlist
)
135 for (ml
= mlist
->next
; ml
!= mlist
;) {
136 struct mlist
*next
= ml
->next
;
137 struct magic
*mg
= ml
->magic
;
138 file_delmagic(mg
, ml
->mapped
, ml
->nmagic
);
146 info_from_stat(struct magic_set
*ms
, mode_t md
)
148 /* We cannot open it, but we were able to stat it. */
150 if (file_printf(ms
, "writable, ") == -1)
153 if (file_printf(ms
, "executable, ") == -1)
156 if (file_printf(ms
, "regular file, ") == -1)
158 if (file_printf(ms
, "no read permission") == -1)
164 magic_close(struct magic_set
*ms
)
166 free_mlist(ms
->mlist
);
177 magic_load(struct magic_set
*ms
, const char *magicfile
)
179 struct mlist
*ml
= file_apprentice(ms
, magicfile
, FILE_LOAD
);
181 free_mlist(ms
->mlist
);
189 magic_compile(struct magic_set
*ms
, const char *magicfile
)
191 struct mlist
*ml
= file_apprentice(ms
, magicfile
, FILE_COMPILE
);
197 magic_check(struct magic_set
*ms
, const char *magicfile
)
199 struct mlist
*ml
= file_apprentice(ms
, magicfile
, FILE_CHECK
);
205 close_and_restore(const struct magic_set
*ms
, const char *name
, int fd
,
206 const struct stat
*sb
)
208 if (fd
== STDIN_FILENO
)
212 if ((ms
->flags
& MAGIC_PRESERVE_ATIME
) != 0) {
214 * Try to restore access, modification times if read it.
215 * This is really *bad* because it will modify the status
216 * time of the file... And of course this will affect
220 struct timeval utsbuf
[2];
221 utsbuf
[0].tv_sec
= sb
->st_atime
;
222 utsbuf
[1].tv_sec
= sb
->st_mtime
;
224 (void) utimes(name
, utsbuf
); /* don't care if loses */
225 #elif defined(HAVE_UTIME_H) || defined(HAVE_SYS_UTIME_H)
226 struct utimbuf utbuf
;
228 utbuf
.actime
= sb
->st_atime
;
229 utbuf
.modtime
= sb
->st_mtime
;
230 (void) utime(name
, &utbuf
); /* don't care if loses */
238 * find type of descriptor
241 magic_descriptor(struct magic_set
*ms
, int fd
)
243 return file_or_fd(ms
, NULL
, fd
);
247 * find type of named file
250 magic_file(struct magic_set
*ms
, const char *inname
)
252 return file_or_fd(ms
, inname
, STDIN_FILENO
);
256 file_or_fd(struct magic_set
*ms
, const char *inname
, int fd
)
261 ssize_t nbytes
= 0; /* number of bytes read from a datafile */
265 * one extra for terminating '\0', and
266 * some overlapping space for matches near EOF
268 #define SLOP (1 + sizeof(union VALUETYPE))
269 if ((buf
= malloc(HOWMANY
+ SLOP
)) == NULL
)
272 if (file_reset(ms
) == -1)
275 switch (file_fsmagic(ms
, inname
, &sb
)) {
278 case 0: /* nothing found */
280 default: /* matched it and printed type */
285 if (inname
== NULL
) {
286 if (fstat(fd
, &sb
) == 0 && S_ISFIFO(sb
.st_mode
))
289 int flags
= O_RDONLY
|O_BINARY
;
291 if (stat(inname
, &sb
) == 0 && S_ISFIFO(sb
.st_mode
)) {
297 if ((fd
= open(inname
, flags
)) < 0) {
299 char *tmp
= alloca(strlen(inname
) + 5);
300 (void)strcat(strcpy(tmp
, inname
), ".exe");
301 if ((fd
= open(tmp
, flags
)) < 0) {
303 if (info_from_stat(ms
, sb
.st_mode
) == -1)
312 if ((flags
= fcntl(fd
, F_GETFL
)) != -1) {
313 flags
&= ~O_NONBLOCK
;
314 (void)fcntl(fd
, F_SETFL
, flags
);
320 * try looking at the first HOWMANY bytes
325 while ((r
= sread(fd
, (void *)&buf
[nbytes
],
326 (size_t)(HOWMANY
- nbytes
), 1)) > 0) {
328 if (r
< PIPE_BUF
) break;
332 /* We can not read it, but we were able to stat it. */
333 if (info_from_stat(ms
, sb
.st_mode
) == -1)
340 if ((nbytes
= read(fd
, (char *)buf
, HOWMANY
)) == -1) {
341 file_error(ms
, errno
, "cannot read `%s'", inname
);
346 (void)memset(buf
+ nbytes
, 0, SLOP
); /* NUL terminate */
347 if (file_buffer(ms
, fd
, inname
, buf
, (size_t)nbytes
) == -1)
352 close_and_restore(ms
, inname
, fd
, &sb
);
353 return rv
== 0 ? file_getbuffer(ms
) : NULL
;
358 magic_buffer(struct magic_set
*ms
, const void *buf
, size_t nb
)
360 if (file_reset(ms
) == -1)
363 * The main work is done here!
364 * We have the file name and/or the data buffer to be identified.
366 if (file_buffer(ms
, -1, NULL
, buf
, nb
) == -1) {
369 return file_getbuffer(ms
);
374 magic_error(struct magic_set
*ms
)
376 return ms
->haderr
? ms
->o
.buf
: NULL
;
380 magic_errno(struct magic_set
*ms
)
382 return ms
->haderr
? ms
->error
: 0;
386 magic_setflags(struct magic_set
*ms
, int flags
)
388 #if !defined(HAVE_UTIME) && !defined(HAVE_UTIMES)
389 if (flags
& MAGIC_PRESERVE_ATIME
)