00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "file.h"
00028 #include "magic.h"
00029 #include <assert.h>
00030 #include <stdarg.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <ctype.h>
00034 #if defined(HAVE_WCHAR_H)
00035 #include <wchar.h>
00036 #endif
00037 #if defined(HAVE_WCTYPE_H)
00038 #include <wctype.h>
00039 #endif
00040
00041 #ifndef lint
00042 FILE_RCSID("@(#)$File: funcs.c,v 1.28 2007/03/01 22:14:54 christos Exp $")
00043 #endif
00044
00045 #ifndef HAVE_VSNPRINTF
00046 int vsnprintf(char *, size_t, const char *, va_list)
00047 ;
00048 #endif
00049
00050
00051
00052
00053 protected int
00054 file_printf(struct magic_set *ms, const char *fmt, ...)
00055 {
00056 va_list ap;
00057 size_t len, size;
00058 char *buf;
00059
00060 va_start(ap, fmt);
00061
00062 if ((len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap)) >= ms->o.left) {
00063 long diff;
00064
00065 va_end(ap);
00066 size = (ms->o.size - ms->o.left) + len + 1024;
00067 if ((buf = realloc(ms->o.buf, size)) == NULL) {
00068 file_oomem(ms, size);
00069 return -1;
00070 }
00071 diff = ms->o.ptr - ms->o.buf;
00072 ms->o.ptr = buf + diff;
00073 ms->o.buf = buf;
00074 ms->o.left = size - diff;
00075 ms->o.size = size;
00076
00077 va_start(ap, fmt);
00078 len = vsnprintf(ms->o.ptr, ms->o.left, fmt, ap);
00079 }
00080 va_end(ap);
00081 ms->o.ptr += len;
00082 ms->o.left -= len;
00083 return 0;
00084 }
00085
00086
00087
00088
00089
00090 private void
00091 file_error_core(struct magic_set *ms, int error, const char *f, va_list va,
00092 uint32_t lineno)
00093
00094 {
00095 size_t len;
00096
00097 if (ms->haderr)
00098 return;
00099 len = 0;
00100 if (lineno != 0) {
00101 (void)snprintf(ms->o.buf, ms->o.size, "line %u: ", lineno);
00102 len = strlen(ms->o.buf);
00103 }
00104 (void)vsnprintf(ms->o.buf + len, ms->o.size - len, f, va);
00105 if (error > 0) {
00106 len = strlen(ms->o.buf);
00107 (void)snprintf(ms->o.buf + len, ms->o.size - len, " (%s)",
00108 strerror(error));
00109 }
00110 ms->haderr++;
00111 ms->error = error;
00112 }
00113
00114
00115 protected void
00116 file_error(struct magic_set *ms, int error, const char *f, ...)
00117 {
00118 va_list va;
00119 va_start(va, f);
00120 file_error_core(ms, error, f, va, 0);
00121 va_end(va);
00122 }
00123
00124
00125
00126
00127
00128 protected void
00129 file_magerror(struct magic_set *ms, const char *f, ...)
00130 {
00131 va_list va;
00132 va_start(va, f);
00133 file_error_core(ms, 0, f, va, ms->line);
00134 va_end(va);
00135 }
00136
00137 protected void
00138 file_oomem(struct magic_set *ms, size_t len)
00139 {
00140 file_error(ms, errno, "cannot allocate %zu bytes", len);
00141 }
00142
00143 protected void
00144 file_badseek(struct magic_set *ms)
00145 {
00146 file_error(ms, errno, "error seeking");
00147 }
00148
00149 protected void
00150 file_badread(struct magic_set *ms)
00151 {
00152 file_error(ms, errno, "error reading");
00153 }
00154
00155 #ifndef COMPILE_ONLY
00156 protected int
00157 file_buffer(struct magic_set *ms, int fd, const char *inname, const void *buf,
00158 size_t nb)
00159 {
00160 int m;
00161
00162 #ifdef __EMX__
00163 if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) {
00164 switch (file_os2_apptype(ms, inname, buf, nb)) {
00165 case -1:
00166 return -1;
00167 case 0:
00168 break;
00169 default:
00170 return 1;
00171 }
00172 }
00173 #endif
00174
00175
00176 if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) != 0 ||
00177 (m = file_zmagic(ms, fd, inname, buf, nb)) == 0) {
00178
00179 if ((ms->flags & MAGIC_NO_CHECK_TAR) != 0 ||
00180 (m = file_is_tar(ms, buf, nb)) == 0) {
00181
00182 if ((ms->flags & MAGIC_NO_CHECK_SOFT) != 0 ||
00183 (m = file_softmagic(ms, buf, nb)) == 0) {
00184
00185 if ((ms->flags & MAGIC_NO_CHECK_ASCII) != 0 ||
00186 (m = file_ascmagic(ms, buf, nb)) == 0) {
00187
00188 if (file_printf(ms, ms->flags & MAGIC_MIME ?
00189 (nb ? "application/octet-stream" :
00190 "application/empty") :
00191 (nb ? "data" :
00192 "empty")) == -1)
00193 return -1;
00194 m = 1;
00195 }
00196 }
00197 }
00198 }
00199 #ifdef BUILTIN_ELF
00200 if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && nb > 5 && fd != -1) {
00201
00202
00203
00204
00205
00206
00207
00208
00209 (void)file_tryelf(ms, fd, buf, nb);
00210 }
00211 #endif
00212 return m;
00213 }
00214 #endif
00215
00216 protected int
00217 file_reset(struct magic_set *ms)
00218 {
00219 if (ms->mlist == NULL) {
00220 file_error(ms, 0, "no magic files loaded");
00221 return -1;
00222 }
00223 ms->o.ptr = ms->o.buf;
00224 ms->haderr = 0;
00225 ms->error = -1;
00226 return 0;
00227 }
00228
00229 #define OCTALIFY(n, o) \
00230 \
00231 (void)(*(n)++ = '\\', \
00232 *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \
00233 *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \
00234 *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \
00235 (o)++)
00236
00237 protected const char *
00238 file_getbuffer(struct magic_set *ms)
00239 {
00240 char *pbuf, *op, *np;
00241 size_t psize, len;
00242
00243 if (ms->haderr)
00244 return NULL;
00245
00246 if (ms->flags & MAGIC_RAW)
00247 return ms->o.buf;
00248
00249 len = ms->o.size - ms->o.left;
00250
00251 psize = len * 4 + 1;
00252 assert(psize > len);
00253 if (ms->o.psize < psize) {
00254 if ((pbuf = realloc(ms->o.pbuf, psize)) == NULL) {
00255 file_oomem(ms, psize);
00256 return NULL;
00257 }
00258 ms->o.psize = psize;
00259 ms->o.pbuf = pbuf;
00260 }
00261
00262 #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH)
00263 {
00264 mbstate_t state;
00265 wchar_t nextchar;
00266 int mb_conv = 1;
00267 size_t bytesconsumed;
00268 char *eop;
00269 (void)memset(&state, 0, sizeof(mbstate_t));
00270
00271 np = ms->o.pbuf;
00272 op = ms->o.buf;
00273 eop = op + strlen(ms->o.buf);
00274
00275 while (op < eop) {
00276 bytesconsumed = mbrtowc(&nextchar, op,
00277 (size_t)(eop - op), &state);
00278 if (bytesconsumed == (size_t)(-1) ||
00279 bytesconsumed == (size_t)(-2)) {
00280 mb_conv = 0;
00281 break;
00282 }
00283
00284 if (iswprint(nextchar)) {
00285 (void)memcpy(np, op, bytesconsumed);
00286 op += bytesconsumed;
00287 np += bytesconsumed;
00288 } else {
00289 while (bytesconsumed-- > 0)
00290 OCTALIFY(np, op);
00291 }
00292 }
00293 *np = '\0';
00294
00295
00296 if (mb_conv != 0)
00297 return ms->o.pbuf;
00298 }
00299 #endif
00300
00301 for (np = ms->o.pbuf, op = ms->o.buf; *op; op++) {
00302 if (isprint((unsigned char)*op)) {
00303 *np++ = *op;
00304 } else {
00305 OCTALIFY(np, op);
00306 }
00307 }
00308 *np = '\0';
00309 return ms->o.pbuf;
00310 }
00311
00312
00313
00314
00315
00316 #ifndef HAVE_VSNPRINTF
00317 int
00318 vsnprintf(char *buf, size_t len, const char *fmt, va_list ap)
00319 {
00320 return vsprintf(buf, fmt, ap);
00321 }
00322 #endif
00323
00324 #ifndef HAVE_SNPRINTF
00325
00326 int
00327 snprintf(char *buf, size_t len, const char *fmt, ...)
00328 {
00329 int rv;
00330 va_list ap;
00331 va_start(ap, fmt);
00332 rv = vsprintf(buf, fmt, ap);
00333 va_end(ap);
00334 return rv;
00335 }
00336 #endif