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
33 #if defined(HAVE_WCHAR_H)
36 #if defined(HAVE_WCTYPE_H)
41 FILE_RCSID("@(#)$Id: funcs.c,v 1.23 2006/12/11 21:48:49 christos Exp $")
44 #ifndef HAVE_VSNPRINTF
45 int vsnprintf(char *, size_t, const char *, va_list);
49 * Like printf, only we print to a buffer and advance it.
52 file_printf(struct magic_set *ms, const char *fmt, ...)
60 if ((len = vsnprintf(ms->o.ptr, ms->o.len, fmt, ap)) >= ms->o.len) {
62 if ((buf = realloc(ms->o.buf, len + 1024)) == NULL) {
63 file_oomem(ms, len + 1024);
66 ms->o.ptr = buf + (ms->o.ptr - ms->o.buf);
68 ms->o.len = ms->o.size - (ms->o.ptr - ms->o.buf);
69 ms->o.size = len + 1024;
72 len = vsnprintf(ms->o.ptr, ms->o.len, fmt, ap);
81 * error - print best error message possible
85 file_error(struct magic_set *ms, int error, const char *f, ...)
88 /* Only the first error is ok */
92 (void)vsnprintf(ms->o.buf, ms->o.size, f, va);
95 size_t len = strlen(ms->o.buf);
96 (void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)",
105 file_oomem(struct magic_set *ms, size_t len)
107 file_error(ms, errno, "cannot allocate %zu bytes", len);
111 file_badseek(struct magic_set *ms)
113 file_error(ms, errno, "error seeking");
117 file_badread(struct magic_set *ms)
119 file_error(ms, errno, "error reading");
124 file_buffer(struct magic_set *ms, int fd, const void *buf, size_t nb)
127 /* try compression stuff */
128 if ((m = file_zmagic(ms, fd, buf, nb)) == 0) {
129 /* Check if we have a tar file */
130 if ((m = file_is_tar(ms, buf, nb)) == 0) {
131 /* try tests in /etc/magic (or surrogate magic file) */
132 if ((m = file_softmagic(ms, buf, nb)) == 0) {
133 /* try known keywords, check whether it is ASCII */
134 if ((m = file_ascmagic(ms, buf, nb)) == 0) {
135 /* abandon hope, all ye who remain here */
136 if (file_printf(ms, ms->flags & MAGIC_MIME ?
137 (nb ? "application/octet-stream" :
138 "application/empty") :
152 file_reset(struct magic_set *ms)
154 if (ms->mlist == NULL) {
155 file_error(ms, 0, "no magic files loaded");
158 ms->o.ptr = ms->o.buf;
164 #define OCTALIFY(n, o) \
166 (void)(*(n)++ = '\\', \
167 *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
168 *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
169 *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
172 protected const char *
173 file_getbuffer(struct magic_set *ms)
175 char *nbuf, *op, *np;
181 if (ms->flags & MAGIC_RAW)
184 nsize = ms->o.len * 4 + 1;
185 if (ms->o.psize < nsize) {
186 if ((nbuf = realloc(ms->o.pbuf, nsize)) == NULL) {
187 file_oomem(ms, nsize);
194 #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
199 size_t bytesconsumed;
201 (void)memset(&state, 0, sizeof(mbstate_t));
205 eop = op + strlen(ms->o.buf);
208 bytesconsumed = mbrtowc(&nextchar, op,
209 (size_t)(eop - op), &state);
210 if (bytesconsumed == (size_t)(-1) ||
211 bytesconsumed == (size_t)(-2)) {
216 if (iswprint(nextchar)) {
217 (void)memcpy(np, op, bytesconsumed);
221 while (bytesconsumed-- > 0)
227 /* Parsing succeeded as a multi-byte sequence */
233 for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
234 if (isprint((unsigned char)*op)) {
245 * Yes these wrappers suffer from buffer overflows, but if your OS does not have
246 * the real functions, maybe you should consider replacing your OS?
248 #ifndef HAVE_VSNPRINTF
250 vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
252 return vsprintf(buf, fmt, ap);
256 #ifndef HAVE_SNPRINTF
259 snprintf(char *buf, size_t len, const char *fmt, ...)
264 rv = vsprintf(buf, fmt, ap);