1*b6cee71dSXin LI /* 2*b6cee71dSXin LI * Copyright (c) Christos Zoulas 2003. 3*b6cee71dSXin LI * All Rights Reserved. 4*b6cee71dSXin LI * 5*b6cee71dSXin LI * Redistribution and use in source and binary forms, with or without 6*b6cee71dSXin LI * modification, are permitted provided that the following conditions 7*b6cee71dSXin LI * are met: 8*b6cee71dSXin LI * 1. Redistributions of source code must retain the above copyright 9*b6cee71dSXin LI * notice immediately at the beginning of the file, without modification, 10*b6cee71dSXin LI * this list of conditions, and the following disclaimer. 11*b6cee71dSXin LI * 2. Redistributions in binary form must reproduce the above copyright 12*b6cee71dSXin LI * notice, this list of conditions and the following disclaimer in the 13*b6cee71dSXin LI * documentation and/or other materials provided with the distribution. 14*b6cee71dSXin LI * 15*b6cee71dSXin LI * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*b6cee71dSXin LI * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*b6cee71dSXin LI * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*b6cee71dSXin LI * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19*b6cee71dSXin LI * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*b6cee71dSXin LI * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*b6cee71dSXin LI * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*b6cee71dSXin LI * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*b6cee71dSXin LI * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*b6cee71dSXin LI * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*b6cee71dSXin LI * SUCH DAMAGE. 26*b6cee71dSXin LI */ 27*b6cee71dSXin LI #include "file.h" 28*b6cee71dSXin LI 29*b6cee71dSXin LI #ifndef lint 30*b6cee71dSXin LI FILE_RCSID("@(#)$File: funcs.c,v 1.72 2014/05/14 23:15:42 christos Exp $") 31*b6cee71dSXin LI #endif /* lint */ 32*b6cee71dSXin LI 33*b6cee71dSXin LI #include "magic.h" 34*b6cee71dSXin LI #include <assert.h> 35*b6cee71dSXin LI #include <stdarg.h> 36*b6cee71dSXin LI #include <stdlib.h> 37*b6cee71dSXin LI #include <string.h> 38*b6cee71dSXin LI #include <ctype.h> 39*b6cee71dSXin LI #if defined(HAVE_WCHAR_H) 40*b6cee71dSXin LI #include <wchar.h> 41*b6cee71dSXin LI #endif 42*b6cee71dSXin LI #if defined(HAVE_WCTYPE_H) 43*b6cee71dSXin LI #include <wctype.h> 44*b6cee71dSXin LI #endif 45*b6cee71dSXin LI #if defined(HAVE_LIMITS_H) 46*b6cee71dSXin LI #include <limits.h> 47*b6cee71dSXin LI #endif 48*b6cee71dSXin LI #if defined(HAVE_LOCALE_H) 49*b6cee71dSXin LI #include <locale.h> 50*b6cee71dSXin LI #endif 51*b6cee71dSXin LI 52*b6cee71dSXin LI #ifndef SIZE_MAX 53*b6cee71dSXin LI #define SIZE_MAX ((size_t)~0) 54*b6cee71dSXin LI #endif 55*b6cee71dSXin LI 56*b6cee71dSXin LI /* 57*b6cee71dSXin LI * Like printf, only we append to a buffer. 58*b6cee71dSXin LI */ 59*b6cee71dSXin LI protected int 60*b6cee71dSXin LI file_vprintf(struct magic_set *ms, const char *fmt, va_list ap) 61*b6cee71dSXin LI { 62*b6cee71dSXin LI int len; 63*b6cee71dSXin LI char *buf, *newstr; 64*b6cee71dSXin LI 65*b6cee71dSXin LI if (ms->event_flags & EVENT_HAD_ERR) 66*b6cee71dSXin LI return 0; 67*b6cee71dSXin LI len = vasprintf(&buf, fmt, ap); 68*b6cee71dSXin LI if (len < 0) 69*b6cee71dSXin LI goto out; 70*b6cee71dSXin LI 71*b6cee71dSXin LI if (ms->o.buf != NULL) { 72*b6cee71dSXin LI len = asprintf(&newstr, "%s%s", ms->o.buf, buf); 73*b6cee71dSXin LI free(buf); 74*b6cee71dSXin LI if (len < 0) 75*b6cee71dSXin LI goto out; 76*b6cee71dSXin LI free(ms->o.buf); 77*b6cee71dSXin LI buf = newstr; 78*b6cee71dSXin LI } 79*b6cee71dSXin LI ms->o.buf = buf; 80*b6cee71dSXin LI return 0; 81*b6cee71dSXin LI out: 82*b6cee71dSXin LI file_error(ms, errno, "vasprintf failed"); 83*b6cee71dSXin LI return -1; 84*b6cee71dSXin LI } 85*b6cee71dSXin LI 86*b6cee71dSXin LI protected int 87*b6cee71dSXin LI file_printf(struct magic_set *ms, const char *fmt, ...) 88*b6cee71dSXin LI { 89*b6cee71dSXin LI int rv; 90*b6cee71dSXin LI va_list ap; 91*b6cee71dSXin LI 92*b6cee71dSXin LI va_start(ap, fmt); 93*b6cee71dSXin LI rv = file_vprintf(ms, fmt, ap); 94*b6cee71dSXin LI va_end(ap); 95*b6cee71dSXin LI return rv; 96*b6cee71dSXin LI } 97*b6cee71dSXin LI 98*b6cee71dSXin LI /* 99*b6cee71dSXin LI * error - print best error message possible 100*b6cee71dSXin LI */ 101*b6cee71dSXin LI /*VARARGS*/ 102*b6cee71dSXin LI __attribute__((__format__(__printf__, 3, 0))) 103*b6cee71dSXin LI private void 104*b6cee71dSXin LI file_error_core(struct magic_set *ms, int error, const char *f, va_list va, 105*b6cee71dSXin LI size_t lineno) 106*b6cee71dSXin LI { 107*b6cee71dSXin LI /* Only the first error is ok */ 108*b6cee71dSXin LI if (ms->event_flags & EVENT_HAD_ERR) 109*b6cee71dSXin LI return; 110*b6cee71dSXin LI if (lineno != 0) { 111*b6cee71dSXin LI free(ms->o.buf); 112*b6cee71dSXin LI ms->o.buf = NULL; 113*b6cee71dSXin LI file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno); 114*b6cee71dSXin LI } 115*b6cee71dSXin LI file_vprintf(ms, f, va); 116*b6cee71dSXin LI if (error > 0) 117*b6cee71dSXin LI file_printf(ms, " (%s)", strerror(error)); 118*b6cee71dSXin LI ms->event_flags |= EVENT_HAD_ERR; 119*b6cee71dSXin LI ms->error = error; 120*b6cee71dSXin LI } 121*b6cee71dSXin LI 122*b6cee71dSXin LI /*VARARGS*/ 123*b6cee71dSXin LI protected void 124*b6cee71dSXin LI file_error(struct magic_set *ms, int error, const char *f, ...) 125*b6cee71dSXin LI { 126*b6cee71dSXin LI va_list va; 127*b6cee71dSXin LI va_start(va, f); 128*b6cee71dSXin LI file_error_core(ms, error, f, va, 0); 129*b6cee71dSXin LI va_end(va); 130*b6cee71dSXin LI } 131*b6cee71dSXin LI 132*b6cee71dSXin LI /* 133*b6cee71dSXin LI * Print an error with magic line number. 134*b6cee71dSXin LI */ 135*b6cee71dSXin LI /*VARARGS*/ 136*b6cee71dSXin LI protected void 137*b6cee71dSXin LI file_magerror(struct magic_set *ms, const char *f, ...) 138*b6cee71dSXin LI { 139*b6cee71dSXin LI va_list va; 140*b6cee71dSXin LI va_start(va, f); 141*b6cee71dSXin LI file_error_core(ms, 0, f, va, ms->line); 142*b6cee71dSXin LI va_end(va); 143*b6cee71dSXin LI } 144*b6cee71dSXin LI 145*b6cee71dSXin LI protected void 146*b6cee71dSXin LI file_oomem(struct magic_set *ms, size_t len) 147*b6cee71dSXin LI { 148*b6cee71dSXin LI file_error(ms, errno, "cannot allocate %" SIZE_T_FORMAT "u bytes", 149*b6cee71dSXin LI len); 150*b6cee71dSXin LI } 151*b6cee71dSXin LI 152*b6cee71dSXin LI protected void 153*b6cee71dSXin LI file_badseek(struct magic_set *ms) 154*b6cee71dSXin LI { 155*b6cee71dSXin LI file_error(ms, errno, "error seeking"); 156*b6cee71dSXin LI } 157*b6cee71dSXin LI 158*b6cee71dSXin LI protected void 159*b6cee71dSXin LI file_badread(struct magic_set *ms) 160*b6cee71dSXin LI { 161*b6cee71dSXin LI file_error(ms, errno, "error reading"); 162*b6cee71dSXin LI } 163*b6cee71dSXin LI 164*b6cee71dSXin LI #ifndef COMPILE_ONLY 165*b6cee71dSXin LI protected int 166*b6cee71dSXin LI file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unused)), 167*b6cee71dSXin LI const void *buf, size_t nb) 168*b6cee71dSXin LI { 169*b6cee71dSXin LI int m = 0, rv = 0, looks_text = 0; 170*b6cee71dSXin LI int mime = ms->flags & MAGIC_MIME; 171*b6cee71dSXin LI const unsigned char *ubuf = CAST(const unsigned char *, buf); 172*b6cee71dSXin LI unichar *u8buf = NULL; 173*b6cee71dSXin LI size_t ulen; 174*b6cee71dSXin LI const char *code = NULL; 175*b6cee71dSXin LI const char *code_mime = "binary"; 176*b6cee71dSXin LI const char *type = "application/octet-stream"; 177*b6cee71dSXin LI const char *def = "data"; 178*b6cee71dSXin LI const char *ftype = NULL; 179*b6cee71dSXin LI 180*b6cee71dSXin LI if (nb == 0) { 181*b6cee71dSXin LI def = "empty"; 182*b6cee71dSXin LI type = "application/x-empty"; 183*b6cee71dSXin LI goto simple; 184*b6cee71dSXin LI } else if (nb == 1) { 185*b6cee71dSXin LI def = "very short file (no magic)"; 186*b6cee71dSXin LI goto simple; 187*b6cee71dSXin LI } 188*b6cee71dSXin LI 189*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) { 190*b6cee71dSXin LI looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen, 191*b6cee71dSXin LI &code, &code_mime, &ftype); 192*b6cee71dSXin LI } 193*b6cee71dSXin LI 194*b6cee71dSXin LI #ifdef __EMX__ 195*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) { 196*b6cee71dSXin LI switch (file_os2_apptype(ms, inname, buf, nb)) { 197*b6cee71dSXin LI case -1: 198*b6cee71dSXin LI return -1; 199*b6cee71dSXin LI case 0: 200*b6cee71dSXin LI break; 201*b6cee71dSXin LI default: 202*b6cee71dSXin LI return 1; 203*b6cee71dSXin LI } 204*b6cee71dSXin LI } 205*b6cee71dSXin LI #endif 206*b6cee71dSXin LI #if HAVE_FORK 207*b6cee71dSXin LI /* try compression stuff */ 208*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) 209*b6cee71dSXin LI if ((m = file_zmagic(ms, fd, inname, ubuf, nb)) != 0) { 210*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 211*b6cee71dSXin LI (void)fprintf(stderr, "zmagic %d\n", m); 212*b6cee71dSXin LI goto done_encoding; 213*b6cee71dSXin LI } 214*b6cee71dSXin LI #endif 215*b6cee71dSXin LI /* Check if we have a tar file */ 216*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) 217*b6cee71dSXin LI if ((m = file_is_tar(ms, ubuf, nb)) != 0) { 218*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 219*b6cee71dSXin LI (void)fprintf(stderr, "tar %d\n", m); 220*b6cee71dSXin LI goto done; 221*b6cee71dSXin LI } 222*b6cee71dSXin LI 223*b6cee71dSXin LI /* Check if we have a CDF file */ 224*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) 225*b6cee71dSXin LI if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) { 226*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 227*b6cee71dSXin LI (void)fprintf(stderr, "cdf %d\n", m); 228*b6cee71dSXin LI goto done; 229*b6cee71dSXin LI } 230*b6cee71dSXin LI 231*b6cee71dSXin LI /* try soft magic tests */ 232*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) 233*b6cee71dSXin LI if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST, 234*b6cee71dSXin LI looks_text)) != 0) { 235*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 236*b6cee71dSXin LI (void)fprintf(stderr, "softmagic %d\n", m); 237*b6cee71dSXin LI #ifdef BUILTIN_ELF 238*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && 239*b6cee71dSXin LI nb > 5 && fd != -1) { 240*b6cee71dSXin LI /* 241*b6cee71dSXin LI * We matched something in the file, so this 242*b6cee71dSXin LI * *might* be an ELF file, and the file is at 243*b6cee71dSXin LI * least 5 bytes long, so if it's an ELF file 244*b6cee71dSXin LI * it has at least one byte past the ELF magic 245*b6cee71dSXin LI * number - try extracting information from the 246*b6cee71dSXin LI * ELF headers that cannot easily * be 247*b6cee71dSXin LI * extracted with rules in the magic file. 248*b6cee71dSXin LI */ 249*b6cee71dSXin LI if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0) 250*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 251*b6cee71dSXin LI (void)fprintf(stderr, 252*b6cee71dSXin LI "elf %d\n", m); 253*b6cee71dSXin LI } 254*b6cee71dSXin LI #endif 255*b6cee71dSXin LI goto done; 256*b6cee71dSXin LI } 257*b6cee71dSXin LI 258*b6cee71dSXin LI /* try text properties */ 259*b6cee71dSXin LI if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) { 260*b6cee71dSXin LI 261*b6cee71dSXin LI if ((m = file_ascmagic(ms, ubuf, nb, looks_text)) != 0) { 262*b6cee71dSXin LI if ((ms->flags & MAGIC_DEBUG) != 0) 263*b6cee71dSXin LI (void)fprintf(stderr, "ascmagic %d\n", m); 264*b6cee71dSXin LI goto done; 265*b6cee71dSXin LI } 266*b6cee71dSXin LI } 267*b6cee71dSXin LI 268*b6cee71dSXin LI simple: 269*b6cee71dSXin LI /* give up */ 270*b6cee71dSXin LI m = 1; 271*b6cee71dSXin LI if ((!mime || (mime & MAGIC_MIME_TYPE)) && 272*b6cee71dSXin LI file_printf(ms, "%s", mime ? type : def) == -1) { 273*b6cee71dSXin LI rv = -1; 274*b6cee71dSXin LI } 275*b6cee71dSXin LI done: 276*b6cee71dSXin LI if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { 277*b6cee71dSXin LI if (ms->flags & MAGIC_MIME_TYPE) 278*b6cee71dSXin LI if (file_printf(ms, "; charset=") == -1) 279*b6cee71dSXin LI rv = -1; 280*b6cee71dSXin LI if (file_printf(ms, "%s", code_mime) == -1) 281*b6cee71dSXin LI rv = -1; 282*b6cee71dSXin LI } 283*b6cee71dSXin LI #if HAVE_FORK 284*b6cee71dSXin LI done_encoding: 285*b6cee71dSXin LI #endif 286*b6cee71dSXin LI free(u8buf); 287*b6cee71dSXin LI if (rv) 288*b6cee71dSXin LI return rv; 289*b6cee71dSXin LI 290*b6cee71dSXin LI return m; 291*b6cee71dSXin LI } 292*b6cee71dSXin LI #endif 293*b6cee71dSXin LI 294*b6cee71dSXin LI protected int 295*b6cee71dSXin LI file_reset(struct magic_set *ms) 296*b6cee71dSXin LI { 297*b6cee71dSXin LI if (ms->mlist[0] == NULL) { 298*b6cee71dSXin LI file_error(ms, 0, "no magic files loaded"); 299*b6cee71dSXin LI return -1; 300*b6cee71dSXin LI } 301*b6cee71dSXin LI if (ms->o.buf) { 302*b6cee71dSXin LI free(ms->o.buf); 303*b6cee71dSXin LI ms->o.buf = NULL; 304*b6cee71dSXin LI } 305*b6cee71dSXin LI if (ms->o.pbuf) { 306*b6cee71dSXin LI free(ms->o.pbuf); 307*b6cee71dSXin LI ms->o.pbuf = NULL; 308*b6cee71dSXin LI } 309*b6cee71dSXin LI ms->event_flags &= ~EVENT_HAD_ERR; 310*b6cee71dSXin LI ms->error = -1; 311*b6cee71dSXin LI return 0; 312*b6cee71dSXin LI } 313*b6cee71dSXin LI 314*b6cee71dSXin LI #define OCTALIFY(n, o) \ 315*b6cee71dSXin LI /*LINTED*/ \ 316*b6cee71dSXin LI (void)(*(n)++ = '\\', \ 317*b6cee71dSXin LI *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ 318*b6cee71dSXin LI *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ 319*b6cee71dSXin LI *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ 320*b6cee71dSXin LI (o)++) 321*b6cee71dSXin LI 322*b6cee71dSXin LI protected const char * 323*b6cee71dSXin LI file_getbuffer(struct magic_set *ms) 324*b6cee71dSXin LI { 325*b6cee71dSXin LI char *pbuf, *op, *np; 326*b6cee71dSXin LI size_t psize, len; 327*b6cee71dSXin LI 328*b6cee71dSXin LI if (ms->event_flags & EVENT_HAD_ERR) 329*b6cee71dSXin LI return NULL; 330*b6cee71dSXin LI 331*b6cee71dSXin LI if (ms->flags & MAGIC_RAW) 332*b6cee71dSXin LI return ms->o.buf; 333*b6cee71dSXin LI 334*b6cee71dSXin LI if (ms->o.buf == NULL) 335*b6cee71dSXin LI return NULL; 336*b6cee71dSXin LI 337*b6cee71dSXin LI /* * 4 is for octal representation, + 1 is for NUL */ 338*b6cee71dSXin LI len = strlen(ms->o.buf); 339*b6cee71dSXin LI if (len > (SIZE_MAX - 1) / 4) { 340*b6cee71dSXin LI file_oomem(ms, len); 341*b6cee71dSXin LI return NULL; 342*b6cee71dSXin LI } 343*b6cee71dSXin LI psize = len * 4 + 1; 344*b6cee71dSXin LI if ((pbuf = CAST(char *, realloc(ms->o.pbuf, psize))) == NULL) { 345*b6cee71dSXin LI file_oomem(ms, psize); 346*b6cee71dSXin LI return NULL; 347*b6cee71dSXin LI } 348*b6cee71dSXin LI ms->o.pbuf = pbuf; 349*b6cee71dSXin LI 350*b6cee71dSXin LI #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) 351*b6cee71dSXin LI { 352*b6cee71dSXin LI mbstate_t state; 353*b6cee71dSXin LI wchar_t nextchar; 354*b6cee71dSXin LI int mb_conv = 1; 355*b6cee71dSXin LI size_t bytesconsumed; 356*b6cee71dSXin LI char *eop; 357*b6cee71dSXin LI (void)memset(&state, 0, sizeof(mbstate_t)); 358*b6cee71dSXin LI 359*b6cee71dSXin LI np = ms->o.pbuf; 360*b6cee71dSXin LI op = ms->o.buf; 361*b6cee71dSXin LI eop = op + len; 362*b6cee71dSXin LI 363*b6cee71dSXin LI while (op < eop) { 364*b6cee71dSXin LI bytesconsumed = mbrtowc(&nextchar, op, 365*b6cee71dSXin LI (size_t)(eop - op), &state); 366*b6cee71dSXin LI if (bytesconsumed == (size_t)(-1) || 367*b6cee71dSXin LI bytesconsumed == (size_t)(-2)) { 368*b6cee71dSXin LI mb_conv = 0; 369*b6cee71dSXin LI break; 370*b6cee71dSXin LI } 371*b6cee71dSXin LI 372*b6cee71dSXin LI if (iswprint(nextchar)) { 373*b6cee71dSXin LI (void)memcpy(np, op, bytesconsumed); 374*b6cee71dSXin LI op += bytesconsumed; 375*b6cee71dSXin LI np += bytesconsumed; 376*b6cee71dSXin LI } else { 377*b6cee71dSXin LI while (bytesconsumed-- > 0) 378*b6cee71dSXin LI OCTALIFY(np, op); 379*b6cee71dSXin LI } 380*b6cee71dSXin LI } 381*b6cee71dSXin LI *np = '\0'; 382*b6cee71dSXin LI 383*b6cee71dSXin LI /* Parsing succeeded as a multi-byte sequence */ 384*b6cee71dSXin LI if (mb_conv != 0) 385*b6cee71dSXin LI return ms->o.pbuf; 386*b6cee71dSXin LI } 387*b6cee71dSXin LI #endif 388*b6cee71dSXin LI 389*b6cee71dSXin LI for (np = ms->o.pbuf, op = ms->o.buf; *op;) { 390*b6cee71dSXin LI if (isprint((unsigned char)*op)) { 391*b6cee71dSXin LI *np++ = *op++; 392*b6cee71dSXin LI } else { 393*b6cee71dSXin LI OCTALIFY(np, op); 394*b6cee71dSXin LI } 395*b6cee71dSXin LI } 396*b6cee71dSXin LI *np = '\0'; 397*b6cee71dSXin LI return ms->o.pbuf; 398*b6cee71dSXin LI } 399*b6cee71dSXin LI 400*b6cee71dSXin LI protected int 401*b6cee71dSXin LI file_check_mem(struct magic_set *ms, unsigned int level) 402*b6cee71dSXin LI { 403*b6cee71dSXin LI size_t len; 404*b6cee71dSXin LI 405*b6cee71dSXin LI if (level >= ms->c.len) { 406*b6cee71dSXin LI len = (ms->c.len += 20) * sizeof(*ms->c.li); 407*b6cee71dSXin LI ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? 408*b6cee71dSXin LI malloc(len) : 409*b6cee71dSXin LI realloc(ms->c.li, len)); 410*b6cee71dSXin LI if (ms->c.li == NULL) { 411*b6cee71dSXin LI file_oomem(ms, len); 412*b6cee71dSXin LI return -1; 413*b6cee71dSXin LI } 414*b6cee71dSXin LI } 415*b6cee71dSXin LI ms->c.li[level].got_match = 0; 416*b6cee71dSXin LI #ifdef ENABLE_CONDITIONALS 417*b6cee71dSXin LI ms->c.li[level].last_match = 0; 418*b6cee71dSXin LI ms->c.li[level].last_cond = COND_NONE; 419*b6cee71dSXin LI #endif /* ENABLE_CONDITIONALS */ 420*b6cee71dSXin LI return 0; 421*b6cee71dSXin LI } 422*b6cee71dSXin LI 423*b6cee71dSXin LI protected size_t 424*b6cee71dSXin LI file_printedlen(const struct magic_set *ms) 425*b6cee71dSXin LI { 426*b6cee71dSXin LI return ms->o.buf == NULL ? 0 : strlen(ms->o.buf); 427*b6cee71dSXin LI } 428*b6cee71dSXin LI 429*b6cee71dSXin LI protected int 430*b6cee71dSXin LI file_replace(struct magic_set *ms, const char *pat, const char *rep) 431*b6cee71dSXin LI { 432*b6cee71dSXin LI file_regex_t rx; 433*b6cee71dSXin LI int rc, rv = -1; 434*b6cee71dSXin LI 435*b6cee71dSXin LI rc = file_regcomp(&rx, pat, REG_EXTENDED); 436*b6cee71dSXin LI if (rc) { 437*b6cee71dSXin LI file_regerror(&rx, rc, ms); 438*b6cee71dSXin LI } else { 439*b6cee71dSXin LI regmatch_t rm; 440*b6cee71dSXin LI int nm = 0; 441*b6cee71dSXin LI while (file_regexec(&rx, ms->o.buf, 1, &rm, 0) == 0) { 442*b6cee71dSXin LI ms->o.buf[rm.rm_so] = '\0'; 443*b6cee71dSXin LI if (file_printf(ms, "%s%s", rep, 444*b6cee71dSXin LI rm.rm_eo != 0 ? ms->o.buf + rm.rm_eo : "") == -1) 445*b6cee71dSXin LI goto out; 446*b6cee71dSXin LI nm++; 447*b6cee71dSXin LI } 448*b6cee71dSXin LI rv = nm; 449*b6cee71dSXin LI } 450*b6cee71dSXin LI out: 451*b6cee71dSXin LI file_regfree(&rx); 452*b6cee71dSXin LI return rv; 453*b6cee71dSXin LI } 454*b6cee71dSXin LI 455*b6cee71dSXin LI protected int 456*b6cee71dSXin LI file_regcomp(file_regex_t *rx, const char *pat, int flags) 457*b6cee71dSXin LI { 458*b6cee71dSXin LI rx->old_lc_ctype = setlocale(LC_CTYPE, NULL); 459*b6cee71dSXin LI assert(rx->old_lc_ctype != NULL); 460*b6cee71dSXin LI rx->old_lc_ctype = strdup(rx->old_lc_ctype); 461*b6cee71dSXin LI assert(rx->old_lc_ctype != NULL); 462*b6cee71dSXin LI rx->pat = pat; 463*b6cee71dSXin LI 464*b6cee71dSXin LI (void)setlocale(LC_CTYPE, "C"); 465*b6cee71dSXin LI return rx->rc = regcomp(&rx->rx, pat, flags); 466*b6cee71dSXin LI } 467*b6cee71dSXin LI 468*b6cee71dSXin LI protected int 469*b6cee71dSXin LI file_regexec(file_regex_t *rx, const char *str, size_t nmatch, 470*b6cee71dSXin LI regmatch_t* pmatch, int eflags) 471*b6cee71dSXin LI { 472*b6cee71dSXin LI assert(rx->rc == 0); 473*b6cee71dSXin LI return regexec(&rx->rx, str, nmatch, pmatch, eflags); 474*b6cee71dSXin LI } 475*b6cee71dSXin LI 476*b6cee71dSXin LI protected void 477*b6cee71dSXin LI file_regfree(file_regex_t *rx) 478*b6cee71dSXin LI { 479*b6cee71dSXin LI if (rx->rc == 0) 480*b6cee71dSXin LI regfree(&rx->rx); 481*b6cee71dSXin LI (void)setlocale(LC_CTYPE, rx->old_lc_ctype); 482*b6cee71dSXin LI free(rx->old_lc_ctype); 483*b6cee71dSXin LI } 484*b6cee71dSXin LI 485*b6cee71dSXin LI protected void 486*b6cee71dSXin LI file_regerror(file_regex_t *rx, int rc, struct magic_set *ms) 487*b6cee71dSXin LI { 488*b6cee71dSXin LI char errmsg[512]; 489*b6cee71dSXin LI 490*b6cee71dSXin LI (void)regerror(rc, &rx->rx, errmsg, sizeof(errmsg)); 491*b6cee71dSXin LI file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat, 492*b6cee71dSXin LI errmsg); 493*b6cee71dSXin LI } 494