1284194Sdelphij/* 2284194Sdelphij * Copyright (c) Christos Zoulas 2003. 3284194Sdelphij * All Rights Reserved. 4284194Sdelphij * 5284194Sdelphij * Redistribution and use in source and binary forms, with or without 6284194Sdelphij * modification, are permitted provided that the following conditions 7284194Sdelphij * are met: 8284194Sdelphij * 1. Redistributions of source code must retain the above copyright 9284194Sdelphij * notice immediately at the beginning of the file, without modification, 10284194Sdelphij * this list of conditions, and the following disclaimer. 11284194Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12284194Sdelphij * notice, this list of conditions and the following disclaimer in the 13284194Sdelphij * documentation and/or other materials provided with the distribution. 14284194Sdelphij * 15284194Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16284194Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17284194Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18284194Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19284194Sdelphij * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20284194Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21284194Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22284194Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23284194Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24284194Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25284194Sdelphij * SUCH DAMAGE. 26284194Sdelphij */ 27284194Sdelphij#include "file.h" 28284194Sdelphij 29284194Sdelphij#ifndef lint 30284194SdelphijFILE_RCSID("@(#)$File: funcs.c,v 1.79 2014/12/16 20:52:49 christos Exp $") 31284194Sdelphij#endif /* lint */ 32284194Sdelphij 33284194Sdelphij#include "magic.h" 34284194Sdelphij#include <assert.h> 35284194Sdelphij#include <stdarg.h> 36284194Sdelphij#include <stdlib.h> 37284194Sdelphij#include <string.h> 38284194Sdelphij#include <ctype.h> 39284194Sdelphij#if defined(HAVE_WCHAR_H) 40284194Sdelphij#include <wchar.h> 41284194Sdelphij#endif 42284194Sdelphij#if defined(HAVE_WCTYPE_H) 43284194Sdelphij#include <wctype.h> 44284194Sdelphij#endif 45284194Sdelphij#if defined(HAVE_LIMITS_H) 46284194Sdelphij#include <limits.h> 47284194Sdelphij#endif 48284194Sdelphij 49284194Sdelphij#ifndef SIZE_MAX 50284194Sdelphij#define SIZE_MAX ((size_t)~0) 51284194Sdelphij#endif 52284194Sdelphij 53284194Sdelphij/* 54284194Sdelphij * Like printf, only we append to a buffer. 55284194Sdelphij */ 56284194Sdelphijprotected int 57284194Sdelphijfile_vprintf(struct magic_set *ms, const char *fmt, va_list ap) 58284194Sdelphij{ 59284194Sdelphij int len; 60284194Sdelphij char *buf, *newstr; 61284194Sdelphij 62284194Sdelphij if (ms->event_flags & EVENT_HAD_ERR) 63284194Sdelphij return 0; 64284194Sdelphij len = vasprintf(&buf, fmt, ap); 65284194Sdelphij if (len < 0) 66284194Sdelphij goto out; 67284194Sdelphij 68284194Sdelphij if (ms->o.buf != NULL) { 69284194Sdelphij len = asprintf(&newstr, "%s%s", ms->o.buf, buf); 70284194Sdelphij free(buf); 71284194Sdelphij if (len < 0) 72284194Sdelphij goto out; 73284194Sdelphij free(ms->o.buf); 74284194Sdelphij buf = newstr; 75284194Sdelphij } 76284194Sdelphij ms->o.buf = buf; 77284194Sdelphij return 0; 78284194Sdelphijout: 79284194Sdelphij file_error(ms, errno, "vasprintf failed"); 80284194Sdelphij return -1; 81284194Sdelphij} 82284194Sdelphij 83284194Sdelphijprotected int 84284194Sdelphijfile_printf(struct magic_set *ms, const char *fmt, ...) 85284194Sdelphij{ 86284194Sdelphij int rv; 87284194Sdelphij va_list ap; 88284194Sdelphij 89284194Sdelphij va_start(ap, fmt); 90284194Sdelphij rv = file_vprintf(ms, fmt, ap); 91284194Sdelphij va_end(ap); 92284194Sdelphij return rv; 93284194Sdelphij} 94284194Sdelphij 95284194Sdelphij/* 96284194Sdelphij * error - print best error message possible 97284194Sdelphij */ 98284194Sdelphij/*VARARGS*/ 99284194Sdelphij__attribute__((__format__(__printf__, 3, 0))) 100284194Sdelphijprivate void 101284194Sdelphijfile_error_core(struct magic_set *ms, int error, const char *f, va_list va, 102284194Sdelphij size_t lineno) 103284194Sdelphij{ 104284194Sdelphij /* Only the first error is ok */ 105284194Sdelphij if (ms->event_flags & EVENT_HAD_ERR) 106284194Sdelphij return; 107284194Sdelphij if (lineno != 0) { 108284194Sdelphij free(ms->o.buf); 109284194Sdelphij ms->o.buf = NULL; 110284194Sdelphij file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno); 111284194Sdelphij } 112284194Sdelphij file_vprintf(ms, f, va); 113284194Sdelphij if (error > 0) 114284194Sdelphij file_printf(ms, " (%s)", strerror(error)); 115284194Sdelphij ms->event_flags |= EVENT_HAD_ERR; 116284194Sdelphij ms->error = error; 117284194Sdelphij} 118284194Sdelphij 119284194Sdelphij/*VARARGS*/ 120284194Sdelphijprotected void 121284194Sdelphijfile_error(struct magic_set *ms, int error, const char *f, ...) 122284194Sdelphij{ 123284194Sdelphij va_list va; 124284194Sdelphij va_start(va, f); 125284194Sdelphij file_error_core(ms, error, f, va, 0); 126284194Sdelphij va_end(va); 127284194Sdelphij} 128284194Sdelphij 129284194Sdelphij/* 130284194Sdelphij * Print an error with magic line number. 131284194Sdelphij */ 132284194Sdelphij/*VARARGS*/ 133284194Sdelphijprotected void 134284194Sdelphijfile_magerror(struct magic_set *ms, const char *f, ...) 135284194Sdelphij{ 136284194Sdelphij va_list va; 137284194Sdelphij va_start(va, f); 138284194Sdelphij file_error_core(ms, 0, f, va, ms->line); 139284194Sdelphij va_end(va); 140284194Sdelphij} 141284194Sdelphij 142284194Sdelphijprotected void 143284194Sdelphijfile_oomem(struct magic_set *ms, size_t len) 144284194Sdelphij{ 145284194Sdelphij file_error(ms, errno, "cannot allocate %" SIZE_T_FORMAT "u bytes", 146284194Sdelphij len); 147284194Sdelphij} 148284194Sdelphij 149284194Sdelphijprotected void 150284194Sdelphijfile_badseek(struct magic_set *ms) 151284194Sdelphij{ 152284194Sdelphij file_error(ms, errno, "error seeking"); 153284194Sdelphij} 154284194Sdelphij 155284194Sdelphijprotected void 156284194Sdelphijfile_badread(struct magic_set *ms) 157284194Sdelphij{ 158284194Sdelphij file_error(ms, errno, "error reading"); 159284194Sdelphij} 160284194Sdelphij 161284194Sdelphij#ifndef COMPILE_ONLY 162284194Sdelphijprotected int 163284194Sdelphijfile_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unused)), 164284194Sdelphij const void *buf, size_t nb) 165284194Sdelphij{ 166284194Sdelphij int m = 0, rv = 0, looks_text = 0; 167284194Sdelphij int mime = ms->flags & MAGIC_MIME; 168284194Sdelphij const unsigned char *ubuf = CAST(const unsigned char *, buf); 169284194Sdelphij unichar *u8buf = NULL; 170284194Sdelphij size_t ulen; 171284194Sdelphij const char *code = NULL; 172284194Sdelphij const char *code_mime = "binary"; 173284194Sdelphij const char *type = "application/octet-stream"; 174284194Sdelphij const char *def = "data"; 175284194Sdelphij const char *ftype = NULL; 176284194Sdelphij 177284194Sdelphij if (nb == 0) { 178284194Sdelphij def = "empty"; 179284194Sdelphij type = "application/x-empty"; 180284194Sdelphij goto simple; 181284194Sdelphij } else if (nb == 1) { 182284194Sdelphij def = "very short file (no magic)"; 183284194Sdelphij goto simple; 184284194Sdelphij } 185284194Sdelphij 186284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) { 187284194Sdelphij looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen, 188284194Sdelphij &code, &code_mime, &ftype); 189284194Sdelphij } 190284194Sdelphij 191284194Sdelphij#ifdef __EMX__ 192284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) { 193284194Sdelphij switch (file_os2_apptype(ms, inname, buf, nb)) { 194284194Sdelphij case -1: 195284194Sdelphij return -1; 196284194Sdelphij case 0: 197284194Sdelphij break; 198284194Sdelphij default: 199284194Sdelphij return 1; 200284194Sdelphij } 201284194Sdelphij } 202284194Sdelphij#endif 203284194Sdelphij#if HAVE_FORK 204284194Sdelphij /* try compression stuff */ 205284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) 206284194Sdelphij if ((m = file_zmagic(ms, fd, inname, ubuf, nb)) != 0) { 207284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 208284194Sdelphij (void)fprintf(stderr, "zmagic %d\n", m); 209284194Sdelphij goto done_encoding; 210284194Sdelphij } 211284194Sdelphij#endif 212284194Sdelphij /* Check if we have a tar file */ 213284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) 214284194Sdelphij if ((m = file_is_tar(ms, ubuf, nb)) != 0) { 215284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 216284194Sdelphij (void)fprintf(stderr, "tar %d\n", m); 217284194Sdelphij goto done; 218284194Sdelphij } 219284194Sdelphij 220284194Sdelphij /* Check if we have a CDF file */ 221284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) 222284194Sdelphij if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) { 223284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 224284194Sdelphij (void)fprintf(stderr, "cdf %d\n", m); 225284194Sdelphij goto done; 226284194Sdelphij } 227284194Sdelphij 228284194Sdelphij /* try soft magic tests */ 229284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) 230284194Sdelphij if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST, 231284194Sdelphij looks_text)) != 0) { 232284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 233284194Sdelphij (void)fprintf(stderr, "softmagic %d\n", m); 234284194Sdelphij#ifdef BUILTIN_ELF 235284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && 236284194Sdelphij nb > 5 && fd != -1) { 237284194Sdelphij /* 238284194Sdelphij * We matched something in the file, so this 239284194Sdelphij * *might* be an ELF file, and the file is at 240284194Sdelphij * least 5 bytes long, so if it's an ELF file 241284194Sdelphij * it has at least one byte past the ELF magic 242284194Sdelphij * number - try extracting information from the 243284194Sdelphij * ELF headers that cannot easily * be 244284194Sdelphij * extracted with rules in the magic file. 245284194Sdelphij */ 246284194Sdelphij if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0) 247284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 248284194Sdelphij (void)fprintf(stderr, 249284194Sdelphij "elf %d\n", m); 250284194Sdelphij } 251284194Sdelphij#endif 252284194Sdelphij goto done; 253284194Sdelphij } 254284194Sdelphij 255284194Sdelphij /* try text properties */ 256284194Sdelphij if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) { 257284194Sdelphij 258284194Sdelphij if ((m = file_ascmagic(ms, ubuf, nb, looks_text)) != 0) { 259284194Sdelphij if ((ms->flags & MAGIC_DEBUG) != 0) 260284194Sdelphij (void)fprintf(stderr, "ascmagic %d\n", m); 261284194Sdelphij goto done; 262284194Sdelphij } 263284194Sdelphij } 264284194Sdelphij 265284194Sdelphijsimple: 266284194Sdelphij /* give up */ 267284194Sdelphij m = 1; 268284194Sdelphij if ((!mime || (mime & MAGIC_MIME_TYPE)) && 269284194Sdelphij file_printf(ms, "%s", mime ? type : def) == -1) { 270284194Sdelphij rv = -1; 271284194Sdelphij } 272284194Sdelphij done: 273284194Sdelphij if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { 274284194Sdelphij if (ms->flags & MAGIC_MIME_TYPE) 275284194Sdelphij if (file_printf(ms, "; charset=") == -1) 276284194Sdelphij rv = -1; 277284194Sdelphij if (file_printf(ms, "%s", code_mime) == -1) 278284194Sdelphij rv = -1; 279284194Sdelphij } 280284194Sdelphij#if HAVE_FORK 281284194Sdelphij done_encoding: 282284194Sdelphij#endif 283284194Sdelphij free(u8buf); 284284194Sdelphij if (rv) 285284194Sdelphij return rv; 286284194Sdelphij 287284194Sdelphij return m; 288284194Sdelphij} 289284194Sdelphij#endif 290284194Sdelphij 291284194Sdelphijprotected int 292284194Sdelphijfile_reset(struct magic_set *ms) 293284194Sdelphij{ 294284194Sdelphij if (ms->mlist[0] == NULL) { 295284194Sdelphij file_error(ms, 0, "no magic files loaded"); 296284194Sdelphij return -1; 297284194Sdelphij } 298284194Sdelphij if (ms->o.buf) { 299284194Sdelphij free(ms->o.buf); 300284194Sdelphij ms->o.buf = NULL; 301284194Sdelphij } 302284194Sdelphij if (ms->o.pbuf) { 303284194Sdelphij free(ms->o.pbuf); 304284194Sdelphij ms->o.pbuf = NULL; 305284194Sdelphij } 306284194Sdelphij ms->event_flags &= ~EVENT_HAD_ERR; 307284194Sdelphij ms->error = -1; 308284194Sdelphij return 0; 309284194Sdelphij} 310284194Sdelphij 311284194Sdelphij#define OCTALIFY(n, o) \ 312284194Sdelphij /*LINTED*/ \ 313284194Sdelphij (void)(*(n)++ = '\\', \ 314284194Sdelphij *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ 315284194Sdelphij *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ 316284194Sdelphij *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ 317284194Sdelphij (o)++) 318284194Sdelphij 319284194Sdelphijprotected const char * 320284194Sdelphijfile_getbuffer(struct magic_set *ms) 321284194Sdelphij{ 322284194Sdelphij char *pbuf, *op, *np; 323284194Sdelphij size_t psize, len; 324284194Sdelphij 325284194Sdelphij if (ms->event_flags & EVENT_HAD_ERR) 326284194Sdelphij return NULL; 327284194Sdelphij 328284194Sdelphij if (ms->flags & MAGIC_RAW) 329284194Sdelphij return ms->o.buf; 330284194Sdelphij 331284194Sdelphij if (ms->o.buf == NULL) 332284194Sdelphij return NULL; 333284194Sdelphij 334284194Sdelphij /* * 4 is for octal representation, + 1 is for NUL */ 335284194Sdelphij len = strlen(ms->o.buf); 336284194Sdelphij if (len > (SIZE_MAX - 1) / 4) { 337284194Sdelphij file_oomem(ms, len); 338284194Sdelphij return NULL; 339284194Sdelphij } 340284194Sdelphij psize = len * 4 + 1; 341284194Sdelphij if ((pbuf = CAST(char *, realloc(ms->o.pbuf, psize))) == NULL) { 342284194Sdelphij file_oomem(ms, psize); 343284194Sdelphij return NULL; 344284194Sdelphij } 345284194Sdelphij ms->o.pbuf = pbuf; 346284194Sdelphij 347284194Sdelphij#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) 348284194Sdelphij { 349284194Sdelphij mbstate_t state; 350284194Sdelphij wchar_t nextchar; 351284194Sdelphij int mb_conv = 1; 352284194Sdelphij size_t bytesconsumed; 353284194Sdelphij char *eop; 354284194Sdelphij (void)memset(&state, 0, sizeof(mbstate_t)); 355284194Sdelphij 356284194Sdelphij np = ms->o.pbuf; 357284194Sdelphij op = ms->o.buf; 358284194Sdelphij eop = op + len; 359284194Sdelphij 360284194Sdelphij while (op < eop) { 361284194Sdelphij bytesconsumed = mbrtowc(&nextchar, op, 362284194Sdelphij (size_t)(eop - op), &state); 363284194Sdelphij if (bytesconsumed == (size_t)(-1) || 364284194Sdelphij bytesconsumed == (size_t)(-2)) { 365284194Sdelphij mb_conv = 0; 366284194Sdelphij break; 367284194Sdelphij } 368284194Sdelphij 369284194Sdelphij if (iswprint(nextchar)) { 370284194Sdelphij (void)memcpy(np, op, bytesconsumed); 371284194Sdelphij op += bytesconsumed; 372284194Sdelphij np += bytesconsumed; 373284194Sdelphij } else { 374284194Sdelphij while (bytesconsumed-- > 0) 375284194Sdelphij OCTALIFY(np, op); 376284194Sdelphij } 377284194Sdelphij } 378284194Sdelphij *np = '\0'; 379284194Sdelphij 380284194Sdelphij /* Parsing succeeded as a multi-byte sequence */ 381284194Sdelphij if (mb_conv != 0) 382284194Sdelphij return ms->o.pbuf; 383284194Sdelphij } 384284194Sdelphij#endif 385284194Sdelphij 386284194Sdelphij for (np = ms->o.pbuf, op = ms->o.buf; *op;) { 387284194Sdelphij if (isprint((unsigned char)*op)) { 388284194Sdelphij *np++ = *op++; 389284194Sdelphij } else { 390284194Sdelphij OCTALIFY(np, op); 391284194Sdelphij } 392284194Sdelphij } 393284194Sdelphij *np = '\0'; 394284194Sdelphij return ms->o.pbuf; 395284194Sdelphij} 396284194Sdelphij 397284194Sdelphijprotected int 398284194Sdelphijfile_check_mem(struct magic_set *ms, unsigned int level) 399284194Sdelphij{ 400284194Sdelphij size_t len; 401284194Sdelphij 402284194Sdelphij if (level >= ms->c.len) { 403284194Sdelphij len = (ms->c.len += 20) * sizeof(*ms->c.li); 404284194Sdelphij ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? 405284194Sdelphij malloc(len) : 406284194Sdelphij realloc(ms->c.li, len)); 407284194Sdelphij if (ms->c.li == NULL) { 408284194Sdelphij file_oomem(ms, len); 409284194Sdelphij return -1; 410284194Sdelphij } 411284194Sdelphij } 412284194Sdelphij ms->c.li[level].got_match = 0; 413284194Sdelphij#ifdef ENABLE_CONDITIONALS 414284194Sdelphij ms->c.li[level].last_match = 0; 415284194Sdelphij ms->c.li[level].last_cond = COND_NONE; 416284194Sdelphij#endif /* ENABLE_CONDITIONALS */ 417284194Sdelphij return 0; 418284194Sdelphij} 419284194Sdelphij 420284194Sdelphijprotected size_t 421284194Sdelphijfile_printedlen(const struct magic_set *ms) 422284194Sdelphij{ 423284194Sdelphij return ms->o.buf == NULL ? 0 : strlen(ms->o.buf); 424284194Sdelphij} 425284194Sdelphij 426284194Sdelphijprotected int 427284194Sdelphijfile_replace(struct magic_set *ms, const char *pat, const char *rep) 428284194Sdelphij{ 429284194Sdelphij file_regex_t rx; 430284194Sdelphij int rc, rv = -1; 431284194Sdelphij 432284194Sdelphij rc = file_regcomp(&rx, pat, REG_EXTENDED); 433284194Sdelphij if (rc) { 434284194Sdelphij file_regerror(&rx, rc, ms); 435284194Sdelphij } else { 436284194Sdelphij regmatch_t rm; 437284194Sdelphij int nm = 0; 438284194Sdelphij while (file_regexec(&rx, ms->o.buf, 1, &rm, 0) == 0) { 439284194Sdelphij ms->o.buf[rm.rm_so] = '\0'; 440284194Sdelphij if (file_printf(ms, "%s%s", rep, 441284194Sdelphij rm.rm_eo != 0 ? ms->o.buf + rm.rm_eo : "") == -1) 442284194Sdelphij goto out; 443284194Sdelphij nm++; 444284194Sdelphij } 445284194Sdelphij rv = nm; 446284194Sdelphij } 447284194Sdelphijout: 448284194Sdelphij file_regfree(&rx); 449284194Sdelphij return rv; 450284194Sdelphij} 451284194Sdelphij 452284194Sdelphijprotected int 453284194Sdelphijfile_regcomp(file_regex_t *rx, const char *pat, int flags) 454284194Sdelphij{ 455284194Sdelphij#ifdef USE_C_LOCALE 456284194Sdelphij rx->c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 457284194Sdelphij assert(rx->c_lc_ctype != NULL); 458284194Sdelphij rx->old_lc_ctype = uselocale(rx->c_lc_ctype); 459284194Sdelphij assert(rx->old_lc_ctype != NULL); 460284194Sdelphij#endif 461284194Sdelphij rx->pat = pat; 462284194Sdelphij 463284194Sdelphij return rx->rc = regcomp(&rx->rx, pat, flags); 464284194Sdelphij} 465284194Sdelphij 466284194Sdelphijprotected int 467284194Sdelphijfile_regexec(file_regex_t *rx, const char *str, size_t nmatch, 468284194Sdelphij regmatch_t* pmatch, int eflags) 469284194Sdelphij{ 470284194Sdelphij assert(rx->rc == 0); 471284194Sdelphij return regexec(&rx->rx, str, nmatch, pmatch, eflags); 472284194Sdelphij} 473284194Sdelphij 474284194Sdelphijprotected void 475284194Sdelphijfile_regfree(file_regex_t *rx) 476284194Sdelphij{ 477284194Sdelphij if (rx->rc == 0) 478284194Sdelphij regfree(&rx->rx); 479284194Sdelphij#ifdef USE_C_LOCALE 480284194Sdelphij (void)uselocale(rx->old_lc_ctype); 481284194Sdelphij freelocale(rx->c_lc_ctype); 482284194Sdelphij#endif 483284194Sdelphij} 484284194Sdelphij 485284194Sdelphijprotected void 486284194Sdelphijfile_regerror(file_regex_t *rx, int rc, struct magic_set *ms) 487284194Sdelphij{ 488284194Sdelphij char errmsg[512]; 489284194Sdelphij 490284194Sdelphij (void)regerror(rc, &rx->rx, errmsg, sizeof(errmsg)); 491284194Sdelphij file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat, 492284194Sdelphij errmsg); 493284194Sdelphij} 494284194Sdelphij 495284194Sdelphijprotected file_pushbuf_t * 496284194Sdelphijfile_push_buffer(struct magic_set *ms) 497284194Sdelphij{ 498284194Sdelphij file_pushbuf_t *pb; 499284194Sdelphij 500284194Sdelphij if (ms->event_flags & EVENT_HAD_ERR) 501284194Sdelphij return NULL; 502284194Sdelphij 503284194Sdelphij if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) 504284194Sdelphij return NULL; 505284194Sdelphij 506284194Sdelphij pb->buf = ms->o.buf; 507284194Sdelphij pb->offset = ms->offset; 508284194Sdelphij 509284194Sdelphij ms->o.buf = NULL; 510284194Sdelphij ms->offset = 0; 511284194Sdelphij 512284194Sdelphij return pb; 513284194Sdelphij} 514284194Sdelphij 515284194Sdelphijprotected char * 516284194Sdelphijfile_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) 517284194Sdelphij{ 518284194Sdelphij char *rbuf; 519284194Sdelphij 520284194Sdelphij if (ms->event_flags & EVENT_HAD_ERR) { 521284194Sdelphij free(pb->buf); 522284194Sdelphij free(pb); 523284194Sdelphij return NULL; 524284194Sdelphij } 525284194Sdelphij 526284194Sdelphij rbuf = ms->o.buf; 527284194Sdelphij 528284194Sdelphij ms->o.buf = pb->buf; 529284194Sdelphij ms->offset = pb->offset; 530284194Sdelphij 531284194Sdelphij free(pb); 532284194Sdelphij return rbuf; 533284194Sdelphij} 534284194Sdelphij 535284194Sdelphij/* 536284194Sdelphij * convert string to ascii printable format. 537284194Sdelphij */ 538284194Sdelphijprotected char * 539284194Sdelphijfile_printable(char *buf, size_t bufsiz, const char *str) 540284194Sdelphij{ 541284194Sdelphij char *ptr, *eptr; 542284194Sdelphij const unsigned char *s = (const unsigned char *)str; 543284194Sdelphij 544284194Sdelphij for (ptr = buf, eptr = ptr + bufsiz - 1; ptr < eptr && *s; s++) { 545284194Sdelphij if (isprint(*s)) { 546284194Sdelphij *ptr++ = *s; 547284194Sdelphij continue; 548284194Sdelphij } 549284194Sdelphij if (ptr >= eptr - 3) 550284194Sdelphij break; 551284194Sdelphij *ptr++ = '\\'; 552284194Sdelphij *ptr++ = ((*s >> 6) & 7) + '0'; 553284194Sdelphij *ptr++ = ((*s >> 3) & 7) + '0'; 554284194Sdelphij *ptr++ = ((*s >> 0) & 7) + '0'; 555284194Sdelphij } 556284194Sdelphij *ptr = '\0'; 557284194Sdelphij return buf; 558284194Sdelphij} 559