funcs.c revision 276415
160484Sobrien/* 2218822Sdim * Copyright (c) Christos Zoulas 2003. 3218822Sdim * All Rights Reserved. 460484Sobrien * 560484Sobrien * Redistribution and use in source and binary forms, with or without 660484Sobrien * modification, are permitted provided that the following conditions 760484Sobrien * are met: 860484Sobrien * 1. Redistributions of source code must retain the above copyright 960484Sobrien * notice immediately at the beginning of the file, without modification, 1060484Sobrien * this list of conditions, and the following disclaimer. 1160484Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1260484Sobrien * notice, this list of conditions and the following disclaimer in the 1360484Sobrien * documentation and/or other materials provided with the distribution. 1460484Sobrien * 1560484Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1660484Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1760484Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1860484Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 1960484Sobrien * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20218822Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2160484Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2260484Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2360484Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2460484Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2560484Sobrien * SUCH DAMAGE. 2660484Sobrien */ 2760484Sobrien#include "file.h" 2860484Sobrien 2960484Sobrien#ifndef lint 3060484SobrienFILE_RCSID("@(#)$File: funcs.c,v 1.77 2014/11/28 02:46:39 christos Exp $") 3160484Sobrien#endif /* lint */ 3260484Sobrien 3360484Sobrien#include "magic.h" 3460484Sobrien#include <assert.h> 35218822Sdim#include <stdarg.h> 3689857Sobrien#include <stdlib.h> 3760484Sobrien#include <string.h> 3860484Sobrien#include <ctype.h> 3960484Sobrien#if defined(HAVE_WCHAR_H) 4060484Sobrien#include <wchar.h> 4160484Sobrien#endif 4260484Sobrien#if defined(HAVE_WCTYPE_H) 4360484Sobrien#include <wctype.h> 4460484Sobrien#endif 4560484Sobrien#if defined(HAVE_LIMITS_H) 4660484Sobrien#include <limits.h> 4760484Sobrien#endif 4860484Sobrien 4960484Sobrien#ifndef SIZE_MAX 5060484Sobrien#define SIZE_MAX ((size_t)~0) 5160484Sobrien#endif 5260484Sobrien 5360484Sobrien/* 5460484Sobrien * Like printf, only we append to a buffer. 5560484Sobrien */ 5660484Sobrienprotected int 5760484Sobrienfile_vprintf(struct magic_set *ms, const char *fmt, va_list ap) 5860484Sobrien{ 5960484Sobrien int len; 6060484Sobrien char *buf, *newstr; 6160484Sobrien 6260484Sobrien if (ms->event_flags & EVENT_HAD_ERR) 6360484Sobrien return 0; 6460484Sobrien len = vasprintf(&buf, fmt, ap); 6560484Sobrien if (len < 0) 6660484Sobrien goto out; 6761843Sobrien 6861843Sobrien if (ms->o.buf != NULL) { 6961843Sobrien len = asprintf(&newstr, "%s%s", ms->o.buf, buf); 7061843Sobrien free(buf); 7161843Sobrien if (len < 0) 7260484Sobrien goto out; 7360484Sobrien free(ms->o.buf); 7460484Sobrien buf = newstr; 7560484Sobrien } 7660484Sobrien ms->o.buf = buf; 7760484Sobrien return 0; 7860484Sobrienout: 7960484Sobrien file_error(ms, errno, "vasprintf failed"); 8060484Sobrien return -1; 8160484Sobrien} 8260484Sobrien 8360484Sobrienprotected int 8460484Sobrienfile_printf(struct magic_set *ms, const char *fmt, ...) 8560484Sobrien{ 8660484Sobrien int rv; 8760484Sobrien va_list ap; 8860484Sobrien 8960484Sobrien va_start(ap, fmt); 90130561Sobrien rv = file_vprintf(ms, fmt, ap); 9160484Sobrien va_end(ap); 92130561Sobrien return rv; 9360484Sobrien} 94130561Sobrien 9560484Sobrien/* 9660484Sobrien * error - print best error message possible 9760484Sobrien */ 98130561Sobrien/*VARARGS*/ 9960484Sobrien__attribute__((__format__(__printf__, 3, 0))) 100130561Sobrienprivate void 101130561Sobrienfile_error_core(struct magic_set *ms, int error, const char *f, va_list va, 102130561Sobrien size_t lineno) 10360484Sobrien{ 10460484Sobrien /* Only the first error is ok */ 10560484Sobrien if (ms->event_flags & EVENT_HAD_ERR) 10660484Sobrien return; 10760484Sobrien if (lineno != 0) { 10860484Sobrien free(ms->o.buf); 109130561Sobrien ms->o.buf = NULL; 11060484Sobrien file_printf(ms, "line %" SIZE_T_FORMAT "u: ", lineno); 11160484Sobrien } 11260484Sobrien file_vprintf(ms, f, va); 11360484Sobrien if (error > 0) 11489857Sobrien file_printf(ms, " (%s)", strerror(error)); 11589857Sobrien ms->event_flags |= EVENT_HAD_ERR; 11689857Sobrien ms->error = error; 11789857Sobrien} 11860484Sobrien 119130561Sobrien/*VARARGS*/ 12060484Sobrienprotected void 12160484Sobrienfile_error(struct magic_set *ms, int error, const char *f, ...) 12260484Sobrien{ 12360484Sobrien va_list va; 124130561Sobrien va_start(va, f); 12560484Sobrien file_error_core(ms, error, f, va, 0); 12660484Sobrien va_end(va); 12760484Sobrien} 12860484Sobrien 12960484Sobrien/* 13060484Sobrien * Print an error with magic line number. 13160484Sobrien */ 13260484Sobrien/*VARARGS*/ 13360484Sobrienprotected void 134130561Sobrienfile_magerror(struct magic_set *ms, const char *f, ...) 13560484Sobrien{ 13660484Sobrien va_list va; 13760484Sobrien va_start(va, f); 13860484Sobrien file_error_core(ms, 0, f, va, ms->line); 13960484Sobrien va_end(va); 14060484Sobrien} 14160484Sobrien 14260484Sobrienprotected void 14360484Sobrienfile_oomem(struct magic_set *ms, size_t len) 14460484Sobrien{ 14560484Sobrien file_error(ms, errno, "cannot allocate %" SIZE_T_FORMAT "u bytes", 14660484Sobrien len); 14760484Sobrien} 14860484Sobrien 14960484Sobrienprotected void 15060484Sobrienfile_badseek(struct magic_set *ms) 15160484Sobrien{ 15260484Sobrien file_error(ms, errno, "error seeking"); 153218822Sdim} 15460484Sobrien 15560484Sobrienprotected void 15660484Sobrienfile_badread(struct magic_set *ms) 15760484Sobrien{ 15860484Sobrien file_error(ms, errno, "error reading"); 15960484Sobrien} 16060484Sobrien 16160484Sobrien#ifndef COMPILE_ONLY 16260484Sobrienprotected int 16360484Sobrienfile_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unused)), 16460484Sobrien const void *buf, size_t nb) 16560484Sobrien{ 16660484Sobrien int m = 0, rv = 0, looks_text = 0; 16760484Sobrien int mime = ms->flags & MAGIC_MIME; 16860484Sobrien const unsigned char *ubuf = CAST(const unsigned char *, buf); 16960484Sobrien unichar *u8buf = NULL; 17060484Sobrien size_t ulen; 17160484Sobrien const char *code = NULL; 17260484Sobrien const char *code_mime = "binary"; 17360484Sobrien const char *type = "application/octet-stream"; 17460484Sobrien const char *def = "data"; 17560484Sobrien const char *ftype = NULL; 17689857Sobrien 17789857Sobrien if (nb == 0) { 17860484Sobrien def = "empty"; 17960484Sobrien type = "application/x-empty"; 18060484Sobrien goto simple; 18160484Sobrien } else if (nb == 1) { 18260484Sobrien def = "very short file (no magic)"; 18360484Sobrien goto simple; 18460484Sobrien } 18560484Sobrien 18660484Sobrien if ((ms->flags & MAGIC_NO_CHECK_ENCODING) == 0) { 18760484Sobrien looks_text = file_encoding(ms, ubuf, nb, &u8buf, &ulen, 18860484Sobrien &code, &code_mime, &ftype); 18960484Sobrien } 19060484Sobrien 19160484Sobrien#ifdef __EMX__ 19260484Sobrien if ((ms->flags & MAGIC_NO_CHECK_APPTYPE) == 0 && inname) { 19360484Sobrien switch (file_os2_apptype(ms, inname, buf, nb)) { 19460484Sobrien case -1: 19560484Sobrien return -1; 19660484Sobrien case 0: 19760484Sobrien break; 19860484Sobrien default: 19960484Sobrien return 1; 20060484Sobrien } 20160484Sobrien } 20260484Sobrien#endif 20360484Sobrien#if HAVE_FORK 20460484Sobrien /* try compression stuff */ 20560484Sobrien if ((ms->flags & MAGIC_NO_CHECK_COMPRESS) == 0) 20660484Sobrien if ((m = file_zmagic(ms, fd, inname, ubuf, nb)) != 0) { 20760484Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 208218822Sdim (void)fprintf(stderr, "zmagic %d\n", m); 209218822Sdim goto done_encoding; 21060484Sobrien } 21160484Sobrien#endif 21260484Sobrien /* Check if we have a tar file */ 213218822Sdim if ((ms->flags & MAGIC_NO_CHECK_TAR) == 0) 21460484Sobrien if ((m = file_is_tar(ms, ubuf, nb)) != 0) { 21560484Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 21660484Sobrien (void)fprintf(stderr, "tar %d\n", m); 21760484Sobrien goto done; 21860484Sobrien } 21960484Sobrien 22060484Sobrien /* Check if we have a CDF file */ 22189857Sobrien if ((ms->flags & MAGIC_NO_CHECK_CDF) == 0) 22260484Sobrien if ((m = file_trycdf(ms, fd, ubuf, nb)) != 0) { 22360484Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 22460484Sobrien (void)fprintf(stderr, "cdf %d\n", m); 22560484Sobrien goto done; 22660484Sobrien } 22760484Sobrien 22860484Sobrien /* try soft magic tests */ 22960484Sobrien if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) 23060484Sobrien if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST, 23160484Sobrien looks_text)) != 0) { 232130561Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 23360484Sobrien (void)fprintf(stderr, "softmagic %d\n", m); 23460484Sobrien#ifdef BUILTIN_ELF 23560484Sobrien if ((ms->flags & MAGIC_NO_CHECK_ELF) == 0 && m == 1 && 23660484Sobrien nb > 5 && fd != -1) { 23760484Sobrien /* 23860484Sobrien * We matched something in the file, so this 23960484Sobrien * *might* be an ELF file, and the file is at 24089857Sobrien * least 5 bytes long, so if it's an ELF file 24189857Sobrien * it has at least one byte past the ELF magic 242130561Sobrien * number - try extracting information from the 243130561Sobrien * ELF headers that cannot easily * be 24460484Sobrien * extracted with rules in the magic file. 24560484Sobrien */ 24660484Sobrien if ((m = file_tryelf(ms, fd, ubuf, nb)) != 0) 24760484Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 24860484Sobrien (void)fprintf(stderr, 24960484Sobrien "elf %d\n", m); 25060484Sobrien } 25160484Sobrien#endif 25260484Sobrien goto done; 25360484Sobrien } 25460484Sobrien 25560484Sobrien /* try text properties */ 25660484Sobrien if ((ms->flags & MAGIC_NO_CHECK_TEXT) == 0) { 25760484Sobrien 25860484Sobrien if ((m = file_ascmagic(ms, ubuf, nb, looks_text)) != 0) { 25960484Sobrien if ((ms->flags & MAGIC_DEBUG) != 0) 26060484Sobrien (void)fprintf(stderr, "ascmagic %d\n", m); 26160484Sobrien goto done; 26260484Sobrien } 26360484Sobrien } 26489857Sobrien 26560484Sobriensimple: 26660484Sobrien /* give up */ 26760484Sobrien m = 1; 26860484Sobrien if ((!mime || (mime & MAGIC_MIME_TYPE)) && 26960484Sobrien file_printf(ms, "%s", mime ? type : def) == -1) { 27060484Sobrien rv = -1; 27160484Sobrien } 27260484Sobrien done: 27360484Sobrien if ((ms->flags & MAGIC_MIME_ENCODING) != 0) { 27460484Sobrien if (ms->flags & MAGIC_MIME_TYPE) 27560484Sobrien if (file_printf(ms, "; charset=") == -1) 27660484Sobrien rv = -1; 27760484Sobrien if (file_printf(ms, "%s", code_mime) == -1) 27860484Sobrien rv = -1; 27960484Sobrien } 28089857Sobrien#if HAVE_FORK 28160484Sobrien done_encoding: 28260484Sobrien#endif 28360484Sobrien free(u8buf); 28460484Sobrien if (rv) 28560484Sobrien return rv; 28660484Sobrien 28760484Sobrien return m; 28860484Sobrien} 28960484Sobrien#endif 290130561Sobrien 29160484Sobrienprotected int 29260484Sobrienfile_reset(struct magic_set *ms) 29360484Sobrien{ 29460484Sobrien if (ms->mlist[0] == NULL) { 29560484Sobrien file_error(ms, 0, "no magic files loaded"); 29660484Sobrien return -1; 29789857Sobrien } 29860484Sobrien if (ms->o.buf) { 29989857Sobrien free(ms->o.buf); 30060484Sobrien ms->o.buf = NULL; 301130561Sobrien } 30260484Sobrien if (ms->o.pbuf) { 30360484Sobrien free(ms->o.pbuf); 30460484Sobrien ms->o.pbuf = NULL; 30560484Sobrien } 30660484Sobrien ms->event_flags &= ~EVENT_HAD_ERR; 30760484Sobrien ms->error = -1; 30860484Sobrien return 0; 30960484Sobrien} 31060484Sobrien 31160484Sobrien#define OCTALIFY(n, o) \ 31260484Sobrien /*LINTED*/ \ 31360484Sobrien (void)(*(n)++ = '\\', \ 314218822Sdim *(n)++ = (((uint32_t)*(o) >> 6) & 3) + '0', \ 31560484Sobrien *(n)++ = (((uint32_t)*(o) >> 3) & 7) + '0', \ 31660484Sobrien *(n)++ = (((uint32_t)*(o) >> 0) & 7) + '0', \ 31760484Sobrien (o)++) 31860484Sobrien 31960484Sobrienprotected const char * 32060484Sobrienfile_getbuffer(struct magic_set *ms) 32160484Sobrien{ 322218822Sdim char *pbuf, *op, *np; 32360484Sobrien size_t psize, len; 32460484Sobrien 32560484Sobrien if (ms->event_flags & EVENT_HAD_ERR) 32660484Sobrien return NULL; 32760484Sobrien 32860484Sobrien if (ms->flags & MAGIC_RAW) 32960484Sobrien return ms->o.buf; 33060484Sobrien 33160484Sobrien if (ms->o.buf == NULL) 33260484Sobrien return NULL; 33360484Sobrien 33489857Sobrien /* * 4 is for octal representation, + 1 is for NUL */ 33560484Sobrien len = strlen(ms->o.buf); 33660484Sobrien if (len > (SIZE_MAX - 1) / 4) { 33760484Sobrien file_oomem(ms, len); 33860484Sobrien return NULL; 33960484Sobrien } 34060484Sobrien psize = len * 4 + 1; 34160484Sobrien if ((pbuf = CAST(char *, realloc(ms->o.pbuf, psize))) == NULL) { 34260484Sobrien file_oomem(ms, psize); 34360484Sobrien return NULL; 34460484Sobrien } 34560484Sobrien ms->o.pbuf = pbuf; 34660484Sobrien 34760484Sobrien#if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) 348218822Sdim { 349218822Sdim mbstate_t state; 35060484Sobrien wchar_t nextchar; 35160484Sobrien int mb_conv = 1; 35260484Sobrien size_t bytesconsumed; 353218822Sdim char *eop; 35460484Sobrien (void)memset(&state, 0, sizeof(mbstate_t)); 35560484Sobrien 35660484Sobrien np = ms->o.pbuf; 35760484Sobrien op = ms->o.buf; 35860484Sobrien eop = op + len; 35960484Sobrien 360130561Sobrien while (op < eop) { 36160484Sobrien bytesconsumed = mbrtowc(&nextchar, op, 36260484Sobrien (size_t)(eop - op), &state); 36360484Sobrien if (bytesconsumed == (size_t)(-1) || 364130561Sobrien bytesconsumed == (size_t)(-2)) { 36560484Sobrien mb_conv = 0; 36660484Sobrien break; 36760484Sobrien } 36860484Sobrien 36960484Sobrien if (iswprint(nextchar)) { 37060484Sobrien (void)memcpy(np, op, bytesconsumed); 37160484Sobrien op += bytesconsumed; 37260484Sobrien np += bytesconsumed; 37360484Sobrien } else { 37460484Sobrien while (bytesconsumed-- > 0) 37560484Sobrien OCTALIFY(np, op); 37660484Sobrien } 37760484Sobrien } 37860484Sobrien *np = '\0'; 37960484Sobrien 38060484Sobrien /* Parsing succeeded as a multi-byte sequence */ 38160484Sobrien if (mb_conv != 0) 38260484Sobrien return ms->o.pbuf; 38360484Sobrien } 384130561Sobrien#endif 38560484Sobrien 38660484Sobrien for (np = ms->o.pbuf, op = ms->o.buf; *op;) { 38760484Sobrien if (isprint((unsigned char)*op)) { 38860484Sobrien *np++ = *op++; 38960484Sobrien } else { 39060484Sobrien OCTALIFY(np, op); 39160484Sobrien } 392218822Sdim } 393218822Sdim *np = '\0'; 39460484Sobrien return ms->o.pbuf; 39560484Sobrien} 39660484Sobrien 39760484Sobrienprotected int 39860484Sobrienfile_check_mem(struct magic_set *ms, unsigned int level) 39960484Sobrien{ 40060484Sobrien size_t len; 401130561Sobrien 40260484Sobrien if (level >= ms->c.len) { 40360484Sobrien len = (ms->c.len += 20) * sizeof(*ms->c.li); 40460484Sobrien ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? 40560484Sobrien malloc(len) : 40660484Sobrien realloc(ms->c.li, len)); 40760484Sobrien if (ms->c.li == NULL) { 40860484Sobrien file_oomem(ms, len); 40960484Sobrien return -1; 41060484Sobrien } 41160484Sobrien } 41260484Sobrien ms->c.li[level].got_match = 0; 41360484Sobrien#ifdef ENABLE_CONDITIONALS 41460484Sobrien ms->c.li[level].last_match = 0; 41560484Sobrien ms->c.li[level].last_cond = COND_NONE; 41660484Sobrien#endif /* ENABLE_CONDITIONALS */ 41760484Sobrien return 0; 41860484Sobrien} 41960484Sobrien 42060484Sobrienprotected size_t 42160484Sobrienfile_printedlen(const struct magic_set *ms) 42260484Sobrien{ 42360484Sobrien return ms->o.buf == NULL ? 0 : strlen(ms->o.buf); 42460484Sobrien} 42560484Sobrien 42660484Sobrienprotected int 42760484Sobrienfile_replace(struct magic_set *ms, const char *pat, const char *rep) 42860484Sobrien{ 42960484Sobrien file_regex_t rx; 43060484Sobrien int rc, rv = -1; 43160484Sobrien 43260484Sobrien rc = file_regcomp(&rx, pat, REG_EXTENDED); 43360484Sobrien if (rc) { 43460484Sobrien file_regerror(&rx, rc, ms); 43560484Sobrien } else { 43660484Sobrien regmatch_t rm; 43760484Sobrien int nm = 0; 43860484Sobrien while (file_regexec(&rx, ms->o.buf, 1, &rm, 0) == 0) { 43960484Sobrien ms->o.buf[rm.rm_so] = '\0'; 44060484Sobrien if (file_printf(ms, "%s%s", rep, 44160484Sobrien rm.rm_eo != 0 ? ms->o.buf + rm.rm_eo : "") == -1) 44260484Sobrien goto out; 44360484Sobrien nm++; 44460484Sobrien } 44560484Sobrien rv = nm; 44660484Sobrien } 44760484Sobrienout: 44860484Sobrien file_regfree(&rx); 44960484Sobrien return rv; 45060484Sobrien} 45160484Sobrien 45260484Sobrienprotected int 45360484Sobrienfile_regcomp(file_regex_t *rx, const char *pat, int flags) 45460484Sobrien{ 45560484Sobrien#ifdef USE_C_LOCALE 45660484Sobrien rx->c_lc_ctype = newlocale(LC_CTYPE_MASK, "C", 0); 45760484Sobrien assert(rx->c_lc_ctype != NULL); 45860484Sobrien rx->old_lc_ctype = uselocale(rx->c_lc_ctype); 459130561Sobrien assert(rx->old_lc_ctype != NULL); 46060484Sobrien#endif 46160484Sobrien rx->pat = pat; 46260484Sobrien 46360484Sobrien return rx->rc = regcomp(&rx->rx, pat, flags); 46460484Sobrien} 46560484Sobrien 46660484Sobrienprotected int 46789857Sobrienfile_regexec(file_regex_t *rx, const char *str, size_t nmatch, 468218822Sdim regmatch_t* pmatch, int eflags) 469104834Sobrien{ 470218822Sdim assert(rx->rc == 0); 471218822Sdim return regexec(&rx->rx, str, nmatch, pmatch, eflags); 47260484Sobrien} 473104834Sobrien 47460484Sobrienprotected void 475104834Sobrienfile_regfree(file_regex_t *rx) 47660484Sobrien{ 47760484Sobrien if (rx->rc == 0) 47860484Sobrien regfree(&rx->rx); 47960484Sobrien#ifdef USE_C_LOCALE 48060484Sobrien (void)uselocale(rx->old_lc_ctype); 48160484Sobrien freelocale(rx->c_lc_ctype); 48260484Sobrien#endif 48360484Sobrien} 48460484Sobrien 485218822Sdimprotected void 48660484Sobrienfile_regerror(file_regex_t *rx, int rc, struct magic_set *ms) 48760484Sobrien{ 48860484Sobrien char errmsg[512]; 48960484Sobrien 49060484Sobrien (void)regerror(rc, &rx->rx, errmsg, sizeof(errmsg)); 49160484Sobrien file_magerror(ms, "regex error %d for `%s', (%s)", rc, rx->pat, 49260484Sobrien errmsg); 49360484Sobrien} 49460484Sobrien 49560484Sobrienprotected file_pushbuf_t * 49660484Sobrienfile_push_buffer(struct magic_set *ms) 49760484Sobrien{ 49860484Sobrien file_pushbuf_t *pb; 49960484Sobrien 50060484Sobrien if (ms->event_flags & EVENT_HAD_ERR) 50160484Sobrien return NULL; 50260484Sobrien 50360484Sobrien if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) 50460484Sobrien return NULL; 50560484Sobrien 50660484Sobrien pb->buf = ms->o.buf; 50760484Sobrien pb->offset = ms->offset; 50860484Sobrien 50960484Sobrien ms->o.buf = NULL; 51060484Sobrien ms->offset = 0; 51160484Sobrien 51260484Sobrien return pb; 51360484Sobrien} 51460484Sobrien 51560484Sobrienprotected char * 51660484Sobrienfile_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) 51760484Sobrien{ 51860484Sobrien char *rbuf; 51960484Sobrien 52060484Sobrien if (ms->event_flags & EVENT_HAD_ERR) { 52160484Sobrien free(pb->buf); 52260484Sobrien free(pb); 52360484Sobrien return NULL; 52460484Sobrien } 52560484Sobrien 52660484Sobrien rbuf = ms->o.buf; 52760484Sobrien 52860484Sobrien ms->o.buf = pb->buf; 52960484Sobrien ms->offset = pb->offset; 53060484Sobrien 531218822Sdim free(pb); 53260484Sobrien return rbuf; 53360484Sobrien} 53460484Sobrien