Annotation of embedaddon/php/ext/fileinfo/libmagic/softmagic.c, revision 1.1.1.5

1.1       misho       1: /*
                      2:  * Copyright (c) Ian F. Darwin 1986-1995.
                      3:  * Software written by Ian F. Darwin and others;
                      4:  * maintained 1995-present by Christos Zoulas and others.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice immediately at the beginning of the file, without modification,
                     11:  *    this list of conditions, and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
                     20:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  */
                     28: /*
                     29:  * softmagic - interpret variable magic from MAGIC
                     30:  */
                     31: 
                     32: #include "file.h"
                     33: 
                     34: #ifndef        lint
1.1.1.3   misho      35: FILE_RCSID("@(#)$File: softmagic.c,v 1.165 2013/03/07 02:22:24 christos Exp $")
1.1       misho      36: #endif /* lint */
                     37: 
                     38: #include "magic.h"
                     39: #include <string.h>
                     40: #include <ctype.h>
                     41: #include <stdlib.h>
                     42: #include <time.h>
                     43: 
                     44: #ifndef PREG_OFFSET_CAPTURE
                     45: # define PREG_OFFSET_CAPTURE                 (1<<8)
                     46: #endif
                     47: 
                     48: 
                     49: 
                     50: private int match(struct magic_set *, struct magic *, uint32_t,
1.1.1.3   misho      51:     const unsigned char *, size_t, size_t, int, int, int, int, int *, int *,
                     52:     int *);
1.1       misho      53: private int mget(struct magic_set *, const unsigned char *,
1.1.1.3   misho      54:     struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *,
                     55:     int *, int *);
1.1       misho      56: private int magiccheck(struct magic_set *, struct magic *);
                     57: private int32_t mprint(struct magic_set *, struct magic *);
                     58: private int32_t moffset(struct magic_set *, struct magic *);
                     59: private void mdebug(uint32_t, const char *, size_t);
                     60: private int mcopy(struct magic_set *, union VALUETYPE *, int, int,
                     61:     const unsigned char *, uint32_t, size_t, size_t);
1.1.1.3   misho      62: private int mconvert(struct magic_set *, struct magic *, int);
1.1       misho      63: private int print_sep(struct magic_set *, int);
                     64: private int handle_annotation(struct magic_set *, struct magic *);
                     65: private void cvt_8(union VALUETYPE *, const struct magic *);
                     66: private void cvt_16(union VALUETYPE *, const struct magic *);
                     67: private void cvt_32(union VALUETYPE *, const struct magic *);
                     68: private void cvt_64(union VALUETYPE *, const struct magic *);
                     69: 
1.1.1.5 ! misho      70: #define OFFSET_OOB(n, o, i)    ((n) < (o) || (i) > ((n) - (o)))
        !            71: 
1.1       misho      72: /*
                     73:  * softmagic - lookup one file in parsed, in-memory copy of database
                     74:  * Passed the name and FILE * of one file to be typed.
                     75:  */
                     76: /*ARGSUSED1*/          /* nbytes passed for regularity, maybe need later */
                     77: protected int
1.1.1.2   misho      78: file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
1.1.1.5 ! misho      79:     size_t level, int mode, int text)
1.1       misho      80: {
                     81:        struct mlist *ml;
1.1.1.3   misho      82:        int rv, printed_something = 0, need_separator = 0;
                     83:        for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
                     84:                if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
1.1.1.5 ! misho      85:                    text, 0, level, &printed_something, &need_separator,
1.1.1.3   misho      86:                    NULL)) != 0)
1.1       misho      87:                        return rv;
                     88: 
                     89:        return 0;
                     90: }
                     91: 
                     92: /*
                     93:  * Go through the whole list, stopping if you find a match.  Process all
                     94:  * the continuations of that match before returning.
                     95:  *
                     96:  * We support multi-level continuations:
                     97:  *
                     98:  *     At any time when processing a successful top-level match, there is a
                     99:  *     current continuation level; it represents the level of the last
                    100:  *     successfully matched continuation.
                    101:  *
                    102:  *     Continuations above that level are skipped as, if we see one, it
                    103:  *     means that the continuation that controls them - i.e, the
                    104:  *     lower-level continuation preceding them - failed to match.
                    105:  *
                    106:  *     Continuations below that level are processed as, if we see one,
                    107:  *     it means we've finished processing or skipping higher-level
                    108:  *     continuations under the control of a successful or unsuccessful
                    109:  *     lower-level continuation, and are now seeing the next lower-level
                    110:  *     continuation and should process it.  The current continuation
                    111:  *     level reverts to the level of the one we're seeing.
                    112:  *
                    113:  *     Continuations at the current level are processed as, if we see
                    114:  *     one, there's no lower-level continuation that may have failed.
                    115:  *
                    116:  *     If a continuation matches, we bump the current continuation level
                    117:  *     so that higher-level continuations are processed.
                    118:  */
                    119: private int
                    120: match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
1.1.1.3   misho     121:     const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
                    122:     int flip, int recursion_level, int *printed_something, int *need_separator,
                    123:     int *returnval)
1.1       misho     124: {
                    125:        uint32_t magindex = 0;
                    126:        unsigned int cont_level = 0;
1.1.1.3   misho     127:        int returnvalv = 0, e; /* if a match is found it is set to 1*/
1.1       misho     128:        int firstline = 1; /* a flag to print X\n  X\n- X */
                    129:        int print = (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0;
                    130: 
1.1.1.3   misho     131:        if (returnval == NULL)
                    132:                returnval = &returnvalv;
                    133: 
1.1       misho     134:        if (file_check_mem(ms, cont_level) == -1)
                    135:                return -1;
                    136: 
                    137:        for (magindex = 0; magindex < nmagic; magindex++) {
                    138:                int flush = 0;
                    139:                struct magic *m = &magic[magindex];
                    140: 
1.1.1.3   misho     141:                if (m->type != FILE_NAME)
1.1.1.2   misho     142:                if ((IS_LIBMAGIC_STRING(m->type) &&
1.1.1.3   misho     143: #define FLT (STRING_BINTEST | STRING_TEXTTEST)
                    144:                     ((text && (m->str_flags & FLT) == STRING_BINTEST) ||
                    145:                      (!text && (m->str_flags & FLT) == STRING_TEXTTEST))) ||
1.1.1.2   misho     146:                    (m->flag & mode) != mode) {
1.1       misho     147:                        /* Skip sub-tests */
1.1.1.3   misho     148:                        while (magindex + 1 < nmagic &&
                    149:                                magic[magindex + 1].cont_level != 0 &&
                    150:                               ++magindex)
                    151:                                continue;
1.1       misho     152:                        continue; /* Skip to next top-level test*/
                    153:                }
                    154: 
                    155:                ms->offset = m->offset;
                    156:                ms->line = m->lineno;
                    157: 
                    158:                /* if main entry matches, print it... */
1.1.1.3   misho     159:                switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
                    160:                    flip, recursion_level + 1, printed_something,
                    161:                    need_separator, returnval)) {
1.1       misho     162:                case -1:
                    163:                        return -1;
                    164:                case 0:
                    165:                        flush = m->reln != '!';
                    166:                        break;
                    167:                default:
                    168:                        if (m->type == FILE_INDIRECT)
1.1.1.3   misho     169:                                *returnval = 1;
1.1.1.2   misho     170: 
1.1       misho     171:                        switch (magiccheck(ms, m)) {
                    172:                        case -1:
                    173:                                return -1;
                    174:                        case 0:
                    175:                                flush++;
                    176:                                break;
                    177:                        default:
                    178:                                flush = 0;
                    179:                                break;
                    180:                        }
                    181:                        break;
                    182:                }
                    183:                if (flush) {
                    184:                        /*
                    185:                         * main entry didn't match,
                    186:                         * flush its continuations
                    187:                         */
1.1.1.3   misho     188:                        while (magindex < nmagic - 1 &&
                    189:                            magic[magindex + 1].cont_level != 0)
1.1       misho     190:                                magindex++;
                    191:                        continue;
                    192:                }
                    193: 
1.1.1.3   misho     194:                if ((e = handle_annotation(ms, m)) != 0) {
                    195:                        *returnval = 1;
1.1.1.2   misho     196:                        return e;
1.1.1.3   misho     197:                }
1.1       misho     198:                /*
                    199:                 * If we are going to print something, we'll need to print
                    200:                 * a blank before we print something else.
                    201:                 */
                    202:                if (*m->desc) {
1.1.1.3   misho     203:                        *need_separator = 1;
                    204:                        *printed_something = 1;
1.1       misho     205:                        if (print_sep(ms, firstline) == -1)
                    206:                                return -1;
                    207:                }
                    208: 
                    209: 
                    210:                if (print && mprint(ms, m) == -1)
                    211:                        return -1;
                    212: 
                    213:                ms->c.li[cont_level].off = moffset(ms, m);
                    214: 
                    215:                /* and any continuations that match */
                    216:                if (file_check_mem(ms, ++cont_level) == -1)
                    217:                        return -1;
                    218: 
1.1.1.3   misho     219:                while (magindex + 1 < nmagic && magic[magindex+1].cont_level != 0 &&
                    220:                    ++magindex) {
1.1       misho     221:                        m = &magic[magindex];
                    222:                        ms->line = m->lineno; /* for messages */
                    223: 
                    224:                        if (cont_level < m->cont_level)
                    225:                                continue;
                    226:                        if (cont_level > m->cont_level) {
                    227:                                /*
                    228:                                 * We're at the end of the level
                    229:                                 * "cont_level" continuations.
                    230:                                 */
                    231:                                cont_level = m->cont_level;
                    232:                        }
                    233:                        ms->offset = m->offset;
                    234:                        if (m->flag & OFFADD) {
1.1.1.3   misho     235:                                ms->offset +=
                    236:                                    ms->c.li[cont_level - 1].off;
1.1       misho     237:                        }
                    238: 
                    239: #ifdef ENABLE_CONDITIONALS
                    240:                        if (m->cond == COND_ELSE ||
                    241:                            m->cond == COND_ELIF) {
                    242:                                if (ms->c.li[cont_level].last_match == 1)
                    243:                                        continue;
                    244:                        }
                    245: #endif
1.1.1.3   misho     246:                        switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
                    247:                            text, flip, recursion_level + 1, printed_something,
                    248:                            need_separator, returnval)) {
1.1       misho     249:                        case -1:
                    250:                                return -1;
                    251:                        case 0:
                    252:                                if (m->reln != '!')
                    253:                                        continue;
                    254:                                flush = 1;
                    255:                                break;
                    256:                        default:
                    257:                                if (m->type == FILE_INDIRECT)
1.1.1.3   misho     258:                                        *returnval = 1;
1.1       misho     259:                                flush = 0;
                    260:                                break;
                    261:                        }
                    262: 
                    263:                        switch (flush ? 1 : magiccheck(ms, m)) {
                    264:                        case -1:
                    265:                                return -1;
                    266:                        case 0:
                    267: #ifdef ENABLE_CONDITIONALS
                    268:                                ms->c.li[cont_level].last_match = 0;
                    269: #endif
                    270:                                break;
                    271:                        default:
                    272: #ifdef ENABLE_CONDITIONALS
                    273:                                ms->c.li[cont_level].last_match = 1;
                    274: #endif
                    275:                                if (m->type != FILE_DEFAULT)
                    276:                                        ms->c.li[cont_level].got_match = 1;
                    277:                                else if (ms->c.li[cont_level].got_match) {
                    278:                                        ms->c.li[cont_level].got_match = 0;
                    279:                                        break;
                    280:                                }
1.1.1.3   misho     281:                                if ((e = handle_annotation(ms, m)) != 0) {
                    282:                                        *returnval = 1;
1.1.1.2   misho     283:                                        return e;
1.1.1.3   misho     284:                                }
1.1       misho     285:                                /*
                    286:                                 * If we are going to print something,
                    287:                                 * make sure that we have a separator first.
                    288:                                 */
                    289:                                if (*m->desc) {
1.1.1.3   misho     290:                                        if (!*printed_something) {
                    291:                                                *printed_something = 1;
1.1       misho     292:                                                if (print_sep(ms, firstline)
                    293:                                                    == -1)
                    294:                                                        return -1;
                    295:                                        }
                    296:                                }
                    297:                                /*
                    298:                                 * This continuation matched.  Print
                    299:                                 * its message, with a blank before it
                    300:                                 * if the previous item printed and
                    301:                                 * this item isn't empty.
                    302:                                 */
                    303:                                /* space if previous printed */
1.1.1.3   misho     304:                                if (*need_separator
1.1       misho     305:                                    && ((m->flag & NOSPACE) == 0)
                    306:                                    && *m->desc) {
                    307:                                        if (print &&
                    308:                                            file_printf(ms, " ") == -1)
                    309:                                                return -1;
1.1.1.3   misho     310:                                        *need_separator = 0;
1.1       misho     311:                                }
                    312:                                if (print && mprint(ms, m) == -1)
                    313:                                        return -1;
                    314: 
                    315:                                ms->c.li[cont_level].off = moffset(ms, m);
                    316: 
                    317:                                if (*m->desc)
1.1.1.3   misho     318:                                        *need_separator = 1;
1.1       misho     319: 
                    320:                                /*
                    321:                                 * If we see any continuations
                    322:                                 * at a higher level,
                    323:                                 * process them.
                    324:                                 */
                    325:                                if (file_check_mem(ms, ++cont_level) == -1)
                    326:                                        return -1;
                    327:                                break;
                    328:                        }
                    329:                }
1.1.1.3   misho     330:                if (*printed_something) {
1.1       misho     331:                        firstline = 0;
                    332:                        if (print)
1.1.1.3   misho     333:                                *returnval = 1;
1.1       misho     334:                }
1.1.1.3   misho     335:                if ((ms->flags & MAGIC_CONTINUE) == 0 && *printed_something) {
                    336:                        return *returnval; /* don't keep searching */
1.1       misho     337:                }
                    338:        }
1.1.1.3   misho     339:        return *returnval;  /* This is hit if -k is set or there is no match */
1.1       misho     340: }
                    341: 
                    342: private int
                    343: check_fmt(struct magic_set *ms, struct magic *m)
                    344: {
                    345:        pcre *pce;
                    346:        int re_options;
                    347:        pcre_extra *re_extra;
                    348:        TSRMLS_FETCH();
                    349:        
                    350:        if (strchr(m->desc, '%') == NULL) {
                    351:                return 0;
                    352:        }
                    353:        
                    354:        if ((pce = pcre_get_compiled_regex("~%[-0-9.]*s~", &re_extra, &re_options TSRMLS_CC)) == NULL) {
                    355:                return -1;
                    356:        } else {
                    357:                return !pcre_exec(pce, re_extra, m->desc, strlen(m->desc), 0, re_options, NULL, 0);
                    358:        }
                    359: }
                    360: 
                    361: private int32_t
                    362: mprint(struct magic_set *ms, struct magic *m)
                    363: {
                    364:        uint64_t v;
                    365:        float vf;
                    366:        double vd;
                    367:        int64_t t = 0;
1.1.1.3   misho     368:        char buf[128], tbuf[26];
1.1       misho     369:        union VALUETYPE *p = &ms->ms_value;
                    370: 
                    371:        switch (m->type) {
                    372:        case FILE_BYTE:
                    373:                v = file_signextend(ms, m, (uint64_t)p->b);
                    374:                switch (check_fmt(ms, m)) {
                    375:                case -1:
                    376:                        return -1;
                    377:                case 1:
                    378:                        (void)snprintf(buf, sizeof(buf), "%c",
                    379:                            (unsigned char)v);
                    380:                        if (file_printf(ms, m->desc, buf) == -1)
                    381:                                return -1;
                    382:                        break;
                    383:                default:
                    384:                        if (file_printf(ms, m->desc, (unsigned char) v) == -1)
                    385:                                return -1;
                    386:                        break;
                    387:                }
                    388:                t = ms->offset + sizeof(char);
                    389:                break;
                    390: 
                    391:        case FILE_SHORT:
                    392:        case FILE_BESHORT:
                    393:        case FILE_LESHORT:
                    394:                v = file_signextend(ms, m, (uint64_t)p->h);
                    395:                switch (check_fmt(ms, m)) {
                    396:                case -1:
                    397:                        return -1;
                    398:                case 1:
                    399:                        (void)snprintf(buf, sizeof(buf), "%hu",
                    400:                            (unsigned short)v);
                    401:                        if (file_printf(ms, m->desc, buf) == -1)
                    402:                                return -1;
                    403:                        break;
                    404:                default:
                    405:                        if (
                    406:                            file_printf(ms, m->desc, (unsigned short) v) == -1)
                    407:                                return -1;
                    408:                        break;
                    409:                }
                    410:                t = ms->offset + sizeof(short);
                    411:                break;
                    412: 
                    413:        case FILE_LONG:
                    414:        case FILE_BELONG:
                    415:        case FILE_LELONG:
                    416:        case FILE_MELONG:
                    417:                v = file_signextend(ms, m, (uint64_t)p->l);
                    418:                switch (check_fmt(ms, m)) {
                    419:                case -1:
                    420:                        return -1;
                    421:                case 1:
                    422:                        (void)snprintf(buf, sizeof(buf), "%u", (uint32_t)v);
                    423:                        if (file_printf(ms, m->desc, buf) == -1)
                    424:                                return -1;
                    425:                        break;
                    426:                default:
                    427:                        if (file_printf(ms, m->desc, (uint32_t) v) == -1)
                    428:                                return -1;
                    429:                        break;
                    430:                }
                    431:                t = ms->offset + sizeof(int32_t);
                    432:                break;
                    433: 
                    434:        case FILE_QUAD:
                    435:        case FILE_BEQUAD:
                    436:        case FILE_LEQUAD:
                    437:                v = file_signextend(ms, m, p->q);
                    438:                if (file_printf(ms, m->desc, (uint64_t) v) == -1)
                    439:                        return -1;
                    440:                t = ms->offset + sizeof(int64_t);
                    441:                break;
                    442: 
                    443:        case FILE_STRING:
                    444:        case FILE_PSTRING:
                    445:        case FILE_BESTRING16:
                    446:        case FILE_LESTRING16:
                    447:                if (m->reln == '=' || m->reln == '!') {
                    448:                        if (file_printf(ms, m->desc, m->value.s) == -1)
                    449:                                return -1;
                    450:                        t = ms->offset + m->vallen;
                    451:                }
                    452:                else {
1.1.1.3   misho     453:                        char *str = p->s;
                    454: 
                    455:                        /* compute t before we mangle the string? */
                    456:                        t = ms->offset + strlen(str);
                    457: 
1.1       misho     458:                        if (*m->value.s == '\0')
1.1.1.3   misho     459:                                str[strcspn(str, "\n")] = '\0';
                    460: 
                    461:                        if (m->str_flags & STRING_TRIM) {
                    462:                                char *last;
                    463:                                while (isspace((unsigned char)*str))
                    464:                                        str++;
                    465:                                last = str;
                    466:                                while (*last)
                    467:                                        last++;
                    468:                                --last;
                    469:                                while (isspace((unsigned char)*last))
                    470:                                        last--;
                    471:                                *++last = '\0';
                    472:                        }
                    473: 
                    474:                        if (file_printf(ms, m->desc, str) == -1)
1.1       misho     475:                                return -1;
1.1.1.3   misho     476: 
1.1       misho     477:                        if (m->type == FILE_PSTRING)
1.1.1.2   misho     478:                                t += file_pstring_length_size(m);
1.1       misho     479:                }
                    480:                break;
                    481: 
                    482:        case FILE_DATE:
                    483:        case FILE_BEDATE:
                    484:        case FILE_LEDATE:
                    485:        case FILE_MEDATE:
1.1.1.3   misho     486:                if (file_printf(ms, m->desc, file_fmttime(p->l, FILE_T_LOCAL,
                    487:                    tbuf)) == -1)
1.1       misho     488:                        return -1;
1.1.1.3   misho     489:                t = ms->offset + sizeof(uint32_t);
1.1       misho     490:                break;
                    491: 
                    492:        case FILE_LDATE:
                    493:        case FILE_BELDATE:
                    494:        case FILE_LELDATE:
                    495:        case FILE_MELDATE:
1.1.1.3   misho     496:                if (file_printf(ms, m->desc, file_fmttime(p->l, 0, tbuf)) == -1)
1.1       misho     497:                        return -1;
1.1.1.3   misho     498:                t = ms->offset + sizeof(uint32_t);
1.1       misho     499:                break;
                    500: 
                    501:        case FILE_QDATE:
                    502:        case FILE_BEQDATE:
                    503:        case FILE_LEQDATE:
1.1.1.3   misho     504:                if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_LOCAL,
                    505:                    tbuf)) == -1)
1.1       misho     506:                        return -1;
                    507:                t = ms->offset + sizeof(uint64_t);
                    508:                break;
                    509: 
                    510:        case FILE_QLDATE:
                    511:        case FILE_BEQLDATE:
                    512:        case FILE_LEQLDATE:
1.1.1.3   misho     513:                if (file_printf(ms, m->desc, file_fmttime(p->q, 0, tbuf)) == -1)
                    514:                        return -1;
                    515:                t = ms->offset + sizeof(uint64_t);
                    516:                break;
                    517: 
                    518:        case FILE_QWDATE:
                    519:        case FILE_BEQWDATE:
                    520:        case FILE_LEQWDATE:
                    521:                if (file_printf(ms, m->desc, file_fmttime(p->q, FILE_T_WINDOWS,
                    522:                    tbuf)) == -1)
1.1       misho     523:                        return -1;
                    524:                t = ms->offset + sizeof(uint64_t);
                    525:                break;
                    526: 
                    527:        case FILE_FLOAT:
                    528:        case FILE_BEFLOAT:
                    529:        case FILE_LEFLOAT:
                    530:                vf = p->f;
                    531:                switch (check_fmt(ms, m)) {
                    532:                case -1:
                    533:                        return -1;
                    534:                case 1:
                    535:                        (void)snprintf(buf, sizeof(buf), "%g", vf);
                    536:                        if (file_printf(ms, m->desc, buf) == -1)
                    537:                                return -1;
                    538:                        break;
                    539:                default:
                    540:                        if (file_printf(ms, m->desc, vf) == -1)
                    541:                                return -1;
                    542:                        break;
                    543:                }
                    544:                t = ms->offset + sizeof(float);
                    545:                break;
                    546: 
                    547:        case FILE_DOUBLE:
                    548:        case FILE_BEDOUBLE:
                    549:        case FILE_LEDOUBLE:
                    550:                vd = p->d;
                    551:                switch (check_fmt(ms, m)) {
                    552:                case -1:
                    553:                        return -1;
                    554:                case 1:
                    555:                        (void)snprintf(buf, sizeof(buf), "%g", vd);
                    556:                        if (file_printf(ms, m->desc, buf) == -1)
                    557:                                return -1;
                    558:                        break;
                    559:                default:
                    560:                        if (file_printf(ms, m->desc, vd) == -1)
                    561:                                return -1;
                    562:                        break;
                    563:                }
                    564:                t = ms->offset + sizeof(double);
                    565:                break;
                    566: 
                    567:        case FILE_REGEX: {
                    568:                char *cp;
                    569:                int rval;
                    570: 
                    571:                cp = estrndup((const char *)ms->search.s, ms->search.rm_len);
1.1.1.3   misho     572:                if (cp == NULL) {
                    573:                        file_oomem(ms, ms->search.rm_len);
                    574:                        return -1;
                    575:                }
1.1       misho     576:                rval = file_printf(ms, m->desc, cp);
                    577:                efree(cp);
                    578: 
                    579:                if (rval == -1)
                    580:                        return -1;
                    581: 
                    582:                if ((m->str_flags & REGEX_OFFSET_START))
                    583:                        t = ms->search.offset;
                    584:                else
                    585:                        t = ms->search.offset + ms->search.rm_len;
                    586:                break;
                    587:        }
                    588: 
                    589:        case FILE_SEARCH:
                    590:                if (file_printf(ms, m->desc, m->value.s) == -1)
                    591:                        return -1;
                    592:                if ((m->str_flags & REGEX_OFFSET_START))
                    593:                        t = ms->search.offset;
                    594:                else
                    595:                        t = ms->search.offset + m->vallen;
                    596:                break;
                    597: 
                    598:        case FILE_DEFAULT:
                    599:                if (file_printf(ms, m->desc, m->value.s) == -1)
                    600:                        return -1;
                    601:                t = ms->offset;
                    602:                break;
                    603: 
                    604:        case FILE_INDIRECT:
1.1.1.3   misho     605:        case FILE_USE:
                    606:        case FILE_NAME:
1.1       misho     607:                t = ms->offset;
                    608:                break;
                    609: 
                    610:        default:
                    611:                file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
                    612:                return -1;
                    613:        }
                    614:        return (int32_t)t;
                    615: }
                    616: 
                    617: private int32_t
                    618: moffset(struct magic_set *ms, struct magic *m)
                    619: {
                    620:        switch (m->type) {
                    621:        case FILE_BYTE:
1.1.1.2   misho     622:                return CAST(int32_t, (ms->offset + sizeof(char)));
1.1       misho     623: 
                    624:        case FILE_SHORT:
                    625:        case FILE_BESHORT:
                    626:        case FILE_LESHORT:
1.1.1.2   misho     627:                return CAST(int32_t, (ms->offset + sizeof(short)));
1.1       misho     628: 
                    629:        case FILE_LONG:
                    630:        case FILE_BELONG:
                    631:        case FILE_LELONG:
                    632:        case FILE_MELONG:
1.1.1.2   misho     633:                return CAST(int32_t, (ms->offset + sizeof(int32_t)));
1.1       misho     634: 
                    635:        case FILE_QUAD:
                    636:        case FILE_BEQUAD:
                    637:        case FILE_LEQUAD:
1.1.1.2   misho     638:                return CAST(int32_t, (ms->offset + sizeof(int64_t)));
1.1       misho     639: 
                    640:        case FILE_STRING:
                    641:        case FILE_PSTRING:
                    642:        case FILE_BESTRING16:
                    643:        case FILE_LESTRING16:
                    644:                if (m->reln == '=' || m->reln == '!')
                    645:                        return ms->offset + m->vallen;
                    646:                else {
                    647:                        union VALUETYPE *p = &ms->ms_value;
                    648:                        uint32_t t;
                    649: 
                    650:                        if (*m->value.s == '\0')
                    651:                                p->s[strcspn(p->s, "\n")] = '\0';
1.1.1.2   misho     652:                        t = CAST(uint32_t, (ms->offset + strlen(p->s)));
1.1       misho     653:                        if (m->type == FILE_PSTRING)
1.1.1.3   misho     654:                                t += (uint32_t)file_pstring_length_size(m);
1.1       misho     655:                        return t;
                    656:                }
                    657: 
                    658:        case FILE_DATE:
                    659:        case FILE_BEDATE:
                    660:        case FILE_LEDATE:
                    661:        case FILE_MEDATE:
1.1.1.3   misho     662:                return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
1.1       misho     663: 
                    664:        case FILE_LDATE:
                    665:        case FILE_BELDATE:
                    666:        case FILE_LELDATE:
                    667:        case FILE_MELDATE:
1.1.1.3   misho     668:                return CAST(int32_t, (ms->offset + sizeof(uint32_t)));
1.1       misho     669: 
                    670:        case FILE_QDATE:
                    671:        case FILE_BEQDATE:
                    672:        case FILE_LEQDATE:
1.1.1.2   misho     673:                return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
1.1       misho     674: 
                    675:        case FILE_QLDATE:
                    676:        case FILE_BEQLDATE:
                    677:        case FILE_LEQLDATE:
1.1.1.2   misho     678:                return CAST(int32_t, (ms->offset + sizeof(uint64_t)));
1.1       misho     679: 
                    680:        case FILE_FLOAT:
                    681:        case FILE_BEFLOAT:
                    682:        case FILE_LEFLOAT:
1.1.1.2   misho     683:                return CAST(int32_t, (ms->offset + sizeof(float)));
1.1       misho     684: 
                    685:        case FILE_DOUBLE:
                    686:        case FILE_BEDOUBLE:
                    687:        case FILE_LEDOUBLE:
1.1.1.2   misho     688:                return CAST(int32_t, (ms->offset + sizeof(double)));
1.1       misho     689: 
                    690:        case FILE_REGEX:
                    691:                if ((m->str_flags & REGEX_OFFSET_START) != 0)
1.1.1.2   misho     692:                        return CAST(int32_t, ms->search.offset);
1.1       misho     693:                else
1.1.1.2   misho     694:                        return CAST(int32_t, (ms->search.offset +
                    695:                            ms->search.rm_len));
1.1       misho     696: 
                    697:        case FILE_SEARCH:
                    698:                if ((m->str_flags & REGEX_OFFSET_START) != 0)
1.1.1.2   misho     699:                        return CAST(int32_t, ms->search.offset);
1.1       misho     700:                else
1.1.1.2   misho     701:                        return CAST(int32_t, (ms->search.offset + m->vallen));
1.1       misho     702: 
                    703:        case FILE_DEFAULT:
                    704:                return ms->offset;
                    705: 
                    706:        case FILE_INDIRECT:
                    707:                return ms->offset;
                    708: 
                    709:        default:
                    710:                return 0;
                    711:        }
                    712: }
                    713: 
1.1.1.3   misho     714: private int
                    715: cvt_flip(int type, int flip)
                    716: {
                    717:        if (flip == 0)
                    718:                return type;
                    719:        switch (type) {
                    720:        case FILE_BESHORT:
                    721:                return FILE_LESHORT;
                    722:        case FILE_BELONG:
                    723:                return FILE_LELONG;
                    724:        case FILE_BEDATE:
                    725:                return FILE_LEDATE;
                    726:        case FILE_BELDATE:
                    727:                return FILE_LELDATE;
                    728:        case FILE_BEQUAD:
                    729:                return FILE_LEQUAD;
                    730:        case FILE_BEQDATE:
                    731:                return FILE_LEQDATE;
                    732:        case FILE_BEQLDATE:
                    733:                return FILE_LEQLDATE;
                    734:        case FILE_BEQWDATE:
                    735:                return FILE_LEQWDATE;
                    736:        case FILE_LESHORT:
                    737:                return FILE_BESHORT;
                    738:        case FILE_LELONG:
                    739:                return FILE_BELONG;
                    740:        case FILE_LEDATE:
                    741:                return FILE_BEDATE;
                    742:        case FILE_LELDATE:
                    743:                return FILE_BELDATE;
                    744:        case FILE_LEQUAD:
                    745:                return FILE_BEQUAD;
                    746:        case FILE_LEQDATE:
                    747:                return FILE_BEQDATE;
                    748:        case FILE_LEQLDATE:
                    749:                return FILE_BEQLDATE;
                    750:        case FILE_LEQWDATE:
                    751:                return FILE_BEQWDATE;
                    752:        case FILE_BEFLOAT:
                    753:                return FILE_LEFLOAT;
                    754:        case FILE_LEFLOAT:
                    755:                return FILE_BEFLOAT;
                    756:        case FILE_BEDOUBLE:
                    757:                return FILE_LEDOUBLE;
                    758:        case FILE_LEDOUBLE:
                    759:                return FILE_BEDOUBLE;
                    760:        default:
                    761:                return type;
                    762:        }
                    763: }
1.1       misho     764: #define DO_CVT(fld, cast) \
                    765:        if (m->num_mask) \
                    766:                switch (m->mask_op & FILE_OPS_MASK) { \
                    767:                case FILE_OPAND: \
                    768:                        p->fld &= cast m->num_mask; \
                    769:                        break; \
                    770:                case FILE_OPOR: \
                    771:                        p->fld |= cast m->num_mask; \
                    772:                        break; \
                    773:                case FILE_OPXOR: \
                    774:                        p->fld ^= cast m->num_mask; \
                    775:                        break; \
                    776:                case FILE_OPADD: \
                    777:                        p->fld += cast m->num_mask; \
                    778:                        break; \
                    779:                case FILE_OPMINUS: \
                    780:                        p->fld -= cast m->num_mask; \
                    781:                        break; \
                    782:                case FILE_OPMULTIPLY: \
                    783:                        p->fld *= cast m->num_mask; \
                    784:                        break; \
                    785:                case FILE_OPDIVIDE: \
                    786:                        p->fld /= cast m->num_mask; \
                    787:                        break; \
                    788:                case FILE_OPMODULO: \
                    789:                        p->fld %= cast m->num_mask; \
                    790:                        break; \
                    791:                } \
                    792:        if (m->mask_op & FILE_OPINVERSE) \
                    793:                p->fld = ~p->fld \
                    794: 
                    795: private void
                    796: cvt_8(union VALUETYPE *p, const struct magic *m)
                    797: {
                    798:        DO_CVT(b, (uint8_t));
                    799: }
                    800: 
                    801: private void
                    802: cvt_16(union VALUETYPE *p, const struct magic *m)
                    803: {
                    804:        DO_CVT(h, (uint16_t));
                    805: }
                    806: 
                    807: private void
                    808: cvt_32(union VALUETYPE *p, const struct magic *m)
                    809: {
                    810:        DO_CVT(l, (uint32_t));
                    811: }
                    812: 
                    813: private void
                    814: cvt_64(union VALUETYPE *p, const struct magic *m)
                    815: {
                    816:        DO_CVT(q, (uint64_t));
                    817: }
                    818: 
                    819: #define DO_CVT2(fld, cast) \
                    820:        if (m->num_mask) \
                    821:                switch (m->mask_op & FILE_OPS_MASK) { \
                    822:                case FILE_OPADD: \
                    823:                        p->fld += cast (int64_t)m->num_mask; \
                    824:                        break; \
                    825:                case FILE_OPMINUS: \
                    826:                        p->fld -= cast (int64_t)m->num_mask; \
                    827:                        break; \
                    828:                case FILE_OPMULTIPLY: \
                    829:                        p->fld *= cast (int64_t)m->num_mask; \
                    830:                        break; \
                    831:                case FILE_OPDIVIDE: \
                    832:                        p->fld /= cast (int64_t)m->num_mask; \
                    833:                        break; \
                    834:                } \
                    835: 
                    836: private void
                    837: cvt_float(union VALUETYPE *p, const struct magic *m)
                    838: {
                    839:        DO_CVT2(f, (float));
                    840: }
                    841: 
                    842: private void
                    843: cvt_double(union VALUETYPE *p, const struct magic *m)
                    844: {
                    845:        DO_CVT2(d, (double));
                    846: }
                    847: 
                    848: /*
                    849:  * Convert the byte order of the data we are looking at
                    850:  * While we're here, let's apply the mask operation
                    851:  * (unless you have a better idea)
                    852:  */
                    853: private int
1.1.1.3   misho     854: mconvert(struct magic_set *ms, struct magic *m, int flip)
1.1       misho     855: {
                    856:        union VALUETYPE *p = &ms->ms_value;
                    857: 
1.1.1.3   misho     858:        switch (cvt_flip(m->type, flip)) {
1.1       misho     859:        case FILE_BYTE:
                    860:                cvt_8(p, m);
                    861:                return 1;
                    862:        case FILE_SHORT:
                    863:                cvt_16(p, m);
                    864:                return 1;
                    865:        case FILE_LONG:
                    866:        case FILE_DATE:
                    867:        case FILE_LDATE:
                    868:                cvt_32(p, m);
                    869:                return 1;
                    870:        case FILE_QUAD:
                    871:        case FILE_QDATE:
                    872:        case FILE_QLDATE:
1.1.1.3   misho     873:        case FILE_QWDATE:
1.1       misho     874:                cvt_64(p, m);
                    875:                return 1;
                    876:        case FILE_STRING:
                    877:        case FILE_BESTRING16:
                    878:        case FILE_LESTRING16: {
                    879:                /* Null terminate and eat *trailing* return */
                    880:                p->s[sizeof(p->s) - 1] = '\0';
                    881:                return 1;
                    882:        }
                    883:        case FILE_PSTRING: {
1.1.1.2   misho     884:                char *ptr1 = p->s, *ptr2 = ptr1 + file_pstring_length_size(m);
                    885:                size_t len = file_pstring_get_length(m, ptr1);
1.1       misho     886:                if (len >= sizeof(p->s))
                    887:                        len = sizeof(p->s) - 1;
                    888:                while (len--)
                    889:                        *ptr1++ = *ptr2++;
                    890:                *ptr1 = '\0';
                    891:                return 1;
                    892:        }
                    893:        case FILE_BESHORT:
                    894:                p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
                    895:                cvt_16(p, m);
                    896:                return 1;
                    897:        case FILE_BELONG:
                    898:        case FILE_BEDATE:
                    899:        case FILE_BELDATE:
                    900:                p->l = (int32_t)
                    901:                    ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
                    902:                cvt_32(p, m);
                    903:                return 1;
                    904:        case FILE_BEQUAD:
                    905:        case FILE_BEQDATE:
                    906:        case FILE_BEQLDATE:
1.1.1.3   misho     907:        case FILE_BEQWDATE:
1.1       misho     908:                p->q = (uint64_t)
                    909:                    (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
                    910:                     ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
                    911:                     ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
                    912:                     ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7]));
                    913:                cvt_64(p, m);
                    914:                return 1;
                    915:        case FILE_LESHORT:
                    916:                p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
                    917:                cvt_16(p, m);
                    918:                return 1;
                    919:        case FILE_LELONG:
                    920:        case FILE_LEDATE:
                    921:        case FILE_LELDATE:
                    922:                p->l = (int32_t)
                    923:                    ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
                    924:                cvt_32(p, m);
                    925:                return 1;
                    926:        case FILE_LEQUAD:
                    927:        case FILE_LEQDATE:
                    928:        case FILE_LEQLDATE:
1.1.1.3   misho     929:        case FILE_LEQWDATE:
1.1       misho     930:                p->q = (uint64_t)
                    931:                    (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
                    932:                     ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
                    933:                     ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
                    934:                     ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0]));
                    935:                cvt_64(p, m);
                    936:                return 1;
                    937:        case FILE_MELONG:
                    938:        case FILE_MEDATE:
                    939:        case FILE_MELDATE:
                    940:                p->l = (int32_t)
                    941:                    ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
                    942:                cvt_32(p, m);
                    943:                return 1;
                    944:        case FILE_FLOAT:
                    945:                cvt_float(p, m);
                    946:                return 1;
                    947:        case FILE_BEFLOAT:
                    948:                p->l =  ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)|
                    949:                        ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]);
                    950:                cvt_float(p, m);
                    951:                return 1;
                    952:        case FILE_LEFLOAT:
                    953:                p->l =  ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)|
                    954:                        ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]);
                    955:                cvt_float(p, m);
                    956:                return 1;
                    957:        case FILE_DOUBLE:
                    958:                cvt_double(p, m);
                    959:                return 1;
                    960:        case FILE_BEDOUBLE:
                    961:                p->q =  ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)|
                    962:                        ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)|
                    963:                        ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)|
                    964:                        ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]);
                    965:                cvt_double(p, m);
                    966:                return 1;
                    967:        case FILE_LEDOUBLE:
                    968:                p->q =  ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)|
                    969:                        ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)|
                    970:                        ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)|
                    971:                        ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]);
                    972:                cvt_double(p, m);
                    973:                return 1;
                    974:        case FILE_REGEX:
                    975:        case FILE_SEARCH:
                    976:        case FILE_DEFAULT:
1.1.1.3   misho     977:        case FILE_NAME:
                    978:        case FILE_USE:
1.1       misho     979:                return 1;
                    980:        default:
                    981:                file_magerror(ms, "invalid type %d in mconvert()", m->type);
                    982:                return 0;
                    983:        }
                    984: }
                    985: 
                    986: 
                    987: private void
                    988: mdebug(uint32_t offset, const char *str, size_t len)
                    989: {
1.1.1.3   misho     990:        (void) fprintf(stderr, "mget/%zu @%d: ", len, offset);
1.1       misho     991:        file_showstr(stderr, str, len);
                    992:        (void) fputc('\n', stderr);
                    993:        (void) fputc('\n', stderr);
                    994: }
                    995: 
                    996: private int
                    997: mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
                    998:     const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
                    999: {
                   1000:        /*
                   1001:         * Note: FILE_SEARCH and FILE_REGEX do not actually copy
                   1002:         * anything, but setup pointers into the source
                   1003:         */
                   1004:        if (indir == 0) {
                   1005:                switch (type) {
                   1006:                case FILE_SEARCH:
1.1.1.2   misho    1007:                        ms->search.s = RCAST(const char *, s) + offset;
1.1       misho    1008:                        ms->search.s_len = nbytes - offset;
                   1009:                        ms->search.offset = offset;
                   1010:                        return 0;
                   1011: 
                   1012:                case FILE_REGEX: {
                   1013:                        const char *b;
                   1014:                        const char *c;
                   1015:                        const char *last;       /* end of search region */
                   1016:                        const char *buf;        /* start of search region */
                   1017:                        const char *end;
                   1018:                        size_t lines;
                   1019: 
                   1020:                        if (s == NULL) {
                   1021:                                ms->search.s_len = 0;
                   1022:                                ms->search.s = NULL;
                   1023:                                return 0;
                   1024:                        }
1.1.1.2   misho    1025:                        buf = RCAST(const char *, s) + offset;
                   1026:                        end = last = RCAST(const char *, s) + nbytes;
1.1       misho    1027:                        /* mget() guarantees buf <= last */
1.1.1.2   misho    1028:                        for (lines = linecnt, b = buf; lines && b < end &&
                   1029:                             ((b = CAST(const char *,
                   1030:                                 memchr(c = b, '\n', CAST(size_t, (end - b)))))
                   1031:                             || (b = CAST(const char *,
                   1032:                                 memchr(c, '\r', CAST(size_t, (end - c))))));
1.1       misho    1033:                             lines--, b++) {
                   1034:                                last = b;
                   1035:                                if (b[0] == '\r' && b[1] == '\n')
                   1036:                                        b++;
                   1037:                        }
                   1038:                        if (lines)
1.1.1.2   misho    1039:                                last = RCAST(const char *, s) + nbytes;
1.1       misho    1040: 
                   1041:                        ms->search.s = buf;
                   1042:                        ms->search.s_len = last - buf;
                   1043:                        ms->search.offset = offset;
                   1044:                        ms->search.rm_len = 0;
                   1045:                        return 0;
                   1046:                }
                   1047:                case FILE_BESTRING16:
                   1048:                case FILE_LESTRING16: {
                   1049:                        const unsigned char *src = s + offset;
                   1050:                        const unsigned char *esrc = s + nbytes;
                   1051:                        char *dst = p->s;
                   1052:                        char *edst = &p->s[sizeof(p->s) - 1];
                   1053: 
                   1054:                        if (type == FILE_BESTRING16)
                   1055:                                src++;
                   1056: 
1.1.1.3   misho    1057:                        /* check that offset is within range */
                   1058:                        if (offset >= nbytes) {
1.1       misho    1059:                                file_magerror(ms, "invalid offset %u in mcopy()",
                   1060:                                    offset);
                   1061:                                return -1;
                   1062:                        }
                   1063:                        for (/*EMPTY*/; src < esrc; src += 2, dst++) {
                   1064:                                if (dst < edst)
                   1065:                                        *dst = *src;
                   1066:                                else
                   1067:                                        break;
                   1068:                                if (*dst == '\0') {
                   1069:                                        if (type == FILE_BESTRING16 ?
                   1070:                                            *(src - 1) != '\0' :
                   1071:                                            *(src + 1) != '\0')
                   1072:                                                *dst = ' ';
                   1073:                                }
                   1074:                        }
                   1075:                        *edst = '\0';
                   1076:                        return 0;
                   1077:                }
                   1078:                case FILE_STRING:       /* XXX - these two should not need */
                   1079:                case FILE_PSTRING:      /* to copy anything, but do anyway. */
                   1080:                default:
                   1081:                        break;
                   1082:                }
                   1083:        }
                   1084: 
                   1085:        if (offset >= nbytes) {
                   1086:                (void)memset(p, '\0', sizeof(*p));
                   1087:                return 0;
                   1088:        }
                   1089:        if (nbytes - offset < sizeof(*p))
                   1090:                nbytes = nbytes - offset;
                   1091:        else
                   1092:                nbytes = sizeof(*p);
                   1093: 
                   1094:        (void)memcpy(p, s + offset, nbytes);
                   1095: 
                   1096:        /*
                   1097:         * the usefulness of padding with zeroes eludes me, it
                   1098:         * might even cause problems
                   1099:         */
                   1100:        if (nbytes < sizeof(*p))
                   1101:                (void)memset(((char *)(void *)p) + nbytes, '\0',
                   1102:                    sizeof(*p) - nbytes);
                   1103:        return 0;
                   1104: }
                   1105: 
                   1106: private int
1.1.1.3   misho    1107: mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
                   1108:     size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
                   1109:     int flip, int recursion_level, int *printed_something,
                   1110:     int *need_separator, int *returnval)
1.1       misho    1111: {
1.1.1.3   misho    1112:        uint32_t soffset, offset = ms->offset;
1.1       misho    1113:        uint32_t count = m->str_range;
1.1.1.3   misho    1114:        int rv, oneed_separator;
                   1115:        char *sbuf, *rbuf;
1.1       misho    1116:        union VALUETYPE *p = &ms->ms_value;
1.1.1.3   misho    1117:        struct mlist ml;
1.1       misho    1118: 
1.1.1.3   misho    1119:        if (recursion_level >= 20) {
                   1120:                file_error(ms, 0, "recursion nesting exceeded");
                   1121:                return -1;
                   1122:        }
                   1123: 
                   1124:        if (mcopy(ms, p, m->type, m->flag & INDIR, s, (uint32_t)(offset + o),
                   1125:            (uint32_t)nbytes, count) == -1)
1.1       misho    1126:                return -1;
                   1127: 
                   1128:        if ((ms->flags & MAGIC_DEBUG) != 0) {
1.1.1.3   misho    1129:                fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
                   1130:                    "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
                   1131:                    nbytes, count);
1.1       misho    1132:                mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
                   1133:        }
                   1134: 
                   1135:        if (m->flag & INDIR) {
                   1136:                int off = m->in_offset;
                   1137:                if (m->in_op & FILE_OPINDIRECT) {
1.1.1.3   misho    1138:                        const union VALUETYPE *q = CAST(const union VALUETYPE *,
                   1139:                            ((const void *)(s + offset + off)));
                   1140:                        switch (cvt_flip(m->in_type, flip)) {
1.1       misho    1141:                        case FILE_BYTE:
                   1142:                                off = q->b;
                   1143:                                break;
                   1144:                        case FILE_SHORT:
                   1145:                                off = q->h;
                   1146:                                break;
                   1147:                        case FILE_BESHORT:
                   1148:                                off = (short)((q->hs[0]<<8)|(q->hs[1]));
                   1149:                                break;
                   1150:                        case FILE_LESHORT:
                   1151:                                off = (short)((q->hs[1]<<8)|(q->hs[0]));
                   1152:                                break;
                   1153:                        case FILE_LONG:
                   1154:                                off = q->l;
                   1155:                                break;
                   1156:                        case FILE_BELONG:
                   1157:                        case FILE_BEID3:
                   1158:                                off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
                   1159:                                                 (q->hl[2]<<8)|(q->hl[3]));
                   1160:                                break;
                   1161:                        case FILE_LEID3:
                   1162:                        case FILE_LELONG:
                   1163:                                off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
                   1164:                                                 (q->hl[1]<<8)|(q->hl[0]));
                   1165:                                break;
                   1166:                        case FILE_MELONG:
                   1167:                                off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
                   1168:                                                 (q->hl[3]<<8)|(q->hl[2]));
                   1169:                                break;
                   1170:                        }
1.1.1.3   misho    1171:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                   1172:                                fprintf(stderr, "indirect offs=%u\n", off);
1.1       misho    1173:                }
1.1.1.3   misho    1174:                switch (cvt_flip(m->in_type, flip)) {
1.1       misho    1175:                case FILE_BYTE:
1.1.1.5 ! misho    1176:                        if (OFFSET_OOB(nbytes, offset, 1))
1.1       misho    1177:                                return 0;
                   1178:                        if (off) {
                   1179:                                switch (m->in_op & FILE_OPS_MASK) {
                   1180:                                case FILE_OPAND:
                   1181:                                        offset = p->b & off;
                   1182:                                        break;
                   1183:                                case FILE_OPOR:
                   1184:                                        offset = p->b | off;
                   1185:                                        break;
                   1186:                                case FILE_OPXOR:
                   1187:                                        offset = p->b ^ off;
                   1188:                                        break;
                   1189:                                case FILE_OPADD:
                   1190:                                        offset = p->b + off;
                   1191:                                        break;
                   1192:                                case FILE_OPMINUS:
                   1193:                                        offset = p->b - off;
                   1194:                                        break;
                   1195:                                case FILE_OPMULTIPLY:
                   1196:                                        offset = p->b * off;
                   1197:                                        break;
                   1198:                                case FILE_OPDIVIDE:
                   1199:                                        offset = p->b / off;
                   1200:                                        break;
                   1201:                                case FILE_OPMODULO:
                   1202:                                        offset = p->b % off;
                   1203:                                        break;
                   1204:                                }
                   1205:                        } else
                   1206:                                offset = p->b;
                   1207:                        if (m->in_op & FILE_OPINVERSE)
                   1208:                                offset = ~offset;
                   1209:                        break;
                   1210:                case FILE_BESHORT:
1.1.1.5 ! misho    1211:                        if (OFFSET_OOB(nbytes, offset, 2))
1.1       misho    1212:                                return 0;
                   1213:                        if (off) {
                   1214:                                switch (m->in_op & FILE_OPS_MASK) {
                   1215:                                case FILE_OPAND:
                   1216:                                        offset = (short)((p->hs[0]<<8)|
                   1217:                                                         (p->hs[1])) &
                   1218:                                                 off;
                   1219:                                        break;
                   1220:                                case FILE_OPOR:
                   1221:                                        offset = (short)((p->hs[0]<<8)|
                   1222:                                                         (p->hs[1])) |
                   1223:                                                 off;
                   1224:                                        break;
                   1225:                                case FILE_OPXOR:
                   1226:                                        offset = (short)((p->hs[0]<<8)|
                   1227:                                                         (p->hs[1])) ^
                   1228:                                                 off;
                   1229:                                        break;
                   1230:                                case FILE_OPADD:
                   1231:                                        offset = (short)((p->hs[0]<<8)|
                   1232:                                                         (p->hs[1])) +
                   1233:                                                 off;
                   1234:                                        break;
                   1235:                                case FILE_OPMINUS:
                   1236:                                        offset = (short)((p->hs[0]<<8)|
                   1237:                                                         (p->hs[1])) -
                   1238:                                                 off;
                   1239:                                        break;
                   1240:                                case FILE_OPMULTIPLY:
                   1241:                                        offset = (short)((p->hs[0]<<8)|
                   1242:                                                         (p->hs[1])) *
                   1243:                                                 off;
                   1244:                                        break;
                   1245:                                case FILE_OPDIVIDE:
                   1246:                                        offset = (short)((p->hs[0]<<8)|
                   1247:                                                         (p->hs[1])) /
                   1248:                                                 off;
                   1249:                                        break;
                   1250:                                case FILE_OPMODULO:
                   1251:                                        offset = (short)((p->hs[0]<<8)|
                   1252:                                                         (p->hs[1])) %
                   1253:                                                 off;
                   1254:                                        break;
                   1255:                                }
                   1256:                        } else
                   1257:                                offset = (short)((p->hs[0]<<8)|
                   1258:                                                 (p->hs[1]));
                   1259:                        if (m->in_op & FILE_OPINVERSE)
                   1260:                                offset = ~offset;
                   1261:                        break;
                   1262:                case FILE_LESHORT:
1.1.1.5 ! misho    1263:                        if (OFFSET_OOB(nbytes, offset, 2))
1.1       misho    1264:                                return 0;
                   1265:                        if (off) {
                   1266:                                switch (m->in_op & FILE_OPS_MASK) {
                   1267:                                case FILE_OPAND:
                   1268:                                        offset = (short)((p->hs[1]<<8)|
                   1269:                                                         (p->hs[0])) &
                   1270:                                                 off;
                   1271:                                        break;
                   1272:                                case FILE_OPOR:
                   1273:                                        offset = (short)((p->hs[1]<<8)|
                   1274:                                                         (p->hs[0])) |
                   1275:                                                 off;
                   1276:                                        break;
                   1277:                                case FILE_OPXOR:
                   1278:                                        offset = (short)((p->hs[1]<<8)|
                   1279:                                                         (p->hs[0])) ^
                   1280:                                                 off;
                   1281:                                        break;
                   1282:                                case FILE_OPADD:
                   1283:                                        offset = (short)((p->hs[1]<<8)|
                   1284:                                                         (p->hs[0])) +
                   1285:                                                 off;
                   1286:                                        break;
                   1287:                                case FILE_OPMINUS:
                   1288:                                        offset = (short)((p->hs[1]<<8)|
                   1289:                                                         (p->hs[0])) -
                   1290:                                                 off;
                   1291:                                        break;
                   1292:                                case FILE_OPMULTIPLY:
                   1293:                                        offset = (short)((p->hs[1]<<8)|
                   1294:                                                         (p->hs[0])) *
                   1295:                                                 off;
                   1296:                                        break;
                   1297:                                case FILE_OPDIVIDE:
                   1298:                                        offset = (short)((p->hs[1]<<8)|
                   1299:                                                         (p->hs[0])) /
                   1300:                                                 off;
                   1301:                                        break;
                   1302:                                case FILE_OPMODULO:
                   1303:                                        offset = (short)((p->hs[1]<<8)|
                   1304:                                                         (p->hs[0])) %
                   1305:                                                 off;
                   1306:                                        break;
                   1307:                                }
                   1308:                        } else
                   1309:                                offset = (short)((p->hs[1]<<8)|
                   1310:                                                 (p->hs[0]));
                   1311:                        if (m->in_op & FILE_OPINVERSE)
                   1312:                                offset = ~offset;
                   1313:                        break;
                   1314:                case FILE_SHORT:
1.1.1.5 ! misho    1315:                        if (OFFSET_OOB(nbytes, offset, 2))
1.1       misho    1316:                                return 0;
                   1317:                        if (off) {
                   1318:                                switch (m->in_op & FILE_OPS_MASK) {
                   1319:                                case FILE_OPAND:
                   1320:                                        offset = p->h & off;
                   1321:                                        break;
                   1322:                                case FILE_OPOR:
                   1323:                                        offset = p->h | off;
                   1324:                                        break;
                   1325:                                case FILE_OPXOR:
                   1326:                                        offset = p->h ^ off;
                   1327:                                        break;
                   1328:                                case FILE_OPADD:
                   1329:                                        offset = p->h + off;
                   1330:                                        break;
                   1331:                                case FILE_OPMINUS:
                   1332:                                        offset = p->h - off;
                   1333:                                        break;
                   1334:                                case FILE_OPMULTIPLY:
                   1335:                                        offset = p->h * off;
                   1336:                                        break;
                   1337:                                case FILE_OPDIVIDE:
                   1338:                                        offset = p->h / off;
                   1339:                                        break;
                   1340:                                case FILE_OPMODULO:
                   1341:                                        offset = p->h % off;
                   1342:                                        break;
                   1343:                                }
                   1344:                        }
                   1345:                        else
                   1346:                                offset = p->h;
                   1347:                        if (m->in_op & FILE_OPINVERSE)
                   1348:                                offset = ~offset;
                   1349:                        break;
                   1350:                case FILE_BELONG:
                   1351:                case FILE_BEID3:
1.1.1.5 ! misho    1352:                        if (OFFSET_OOB(nbytes, offset, 4))
1.1       misho    1353:                                return 0;
                   1354:                        if (off) {
                   1355:                                switch (m->in_op & FILE_OPS_MASK) {
                   1356:                                case FILE_OPAND:
                   1357:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1358:                                                         (p->hl[1]<<16)|
                   1359:                                                         (p->hl[2]<<8)|
                   1360:                                                         (p->hl[3])) &
                   1361:                                                 off;
                   1362:                                        break;
                   1363:                                case FILE_OPOR:
                   1364:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1365:                                                         (p->hl[1]<<16)|
                   1366:                                                         (p->hl[2]<<8)|
                   1367:                                                         (p->hl[3])) |
                   1368:                                                 off;
                   1369:                                        break;
                   1370:                                case FILE_OPXOR:
                   1371:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1372:                                                         (p->hl[1]<<16)|
                   1373:                                                         (p->hl[2]<<8)|
                   1374:                                                         (p->hl[3])) ^
                   1375:                                                 off;
                   1376:                                        break;
                   1377:                                case FILE_OPADD:
                   1378:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1379:                                                         (p->hl[1]<<16)|
                   1380:                                                         (p->hl[2]<<8)|
                   1381:                                                         (p->hl[3])) +
                   1382:                                                 off;
                   1383:                                        break;
                   1384:                                case FILE_OPMINUS:
                   1385:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1386:                                                         (p->hl[1]<<16)|
                   1387:                                                         (p->hl[2]<<8)|
                   1388:                                                         (p->hl[3])) -
                   1389:                                                 off;
                   1390:                                        break;
                   1391:                                case FILE_OPMULTIPLY:
                   1392:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1393:                                                         (p->hl[1]<<16)|
                   1394:                                                         (p->hl[2]<<8)|
                   1395:                                                         (p->hl[3])) *
                   1396:                                                 off;
                   1397:                                        break;
                   1398:                                case FILE_OPDIVIDE:
                   1399:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1400:                                                         (p->hl[1]<<16)|
                   1401:                                                         (p->hl[2]<<8)|
                   1402:                                                         (p->hl[3])) /
                   1403:                                                 off;
                   1404:                                        break;
                   1405:                                case FILE_OPMODULO:
                   1406:                                        offset = (int32_t)((p->hl[0]<<24)|
                   1407:                                                         (p->hl[1]<<16)|
                   1408:                                                         (p->hl[2]<<8)|
                   1409:                                                         (p->hl[3])) %
                   1410:                                                 off;
                   1411:                                        break;
                   1412:                                }
                   1413:                        } else
                   1414:                                offset = (int32_t)((p->hl[0]<<24)|
                   1415:                                                 (p->hl[1]<<16)|
                   1416:                                                 (p->hl[2]<<8)|
                   1417:                                                 (p->hl[3]));
                   1418:                        if (m->in_op & FILE_OPINVERSE)
                   1419:                                offset = ~offset;
                   1420:                        break;
                   1421:                case FILE_LELONG:
                   1422:                case FILE_LEID3:
1.1.1.5 ! misho    1423:                        if (OFFSET_OOB(nbytes, offset, 4))
1.1       misho    1424:                                return 0;
                   1425:                        if (off) {
                   1426:                                switch (m->in_op & FILE_OPS_MASK) {
                   1427:                                case FILE_OPAND:
                   1428:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1429:                                                         (p->hl[2]<<16)|
                   1430:                                                         (p->hl[1]<<8)|
                   1431:                                                         (p->hl[0])) &
                   1432:                                                 off;
                   1433:                                        break;
                   1434:                                case FILE_OPOR:
                   1435:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1436:                                                         (p->hl[2]<<16)|
                   1437:                                                         (p->hl[1]<<8)|
                   1438:                                                         (p->hl[0])) |
                   1439:                                                 off;
                   1440:                                        break;
                   1441:                                case FILE_OPXOR:
                   1442:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1443:                                                         (p->hl[2]<<16)|
                   1444:                                                         (p->hl[1]<<8)|
                   1445:                                                         (p->hl[0])) ^
                   1446:                                                 off;
                   1447:                                        break;
                   1448:                                case FILE_OPADD:
                   1449:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1450:                                                         (p->hl[2]<<16)|
                   1451:                                                         (p->hl[1]<<8)|
                   1452:                                                         (p->hl[0])) +
                   1453:                                                 off;
                   1454:                                        break;
                   1455:                                case FILE_OPMINUS:
                   1456:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1457:                                                         (p->hl[2]<<16)|
                   1458:                                                         (p->hl[1]<<8)|
                   1459:                                                         (p->hl[0])) -
                   1460:                                                 off;
                   1461:                                        break;
                   1462:                                case FILE_OPMULTIPLY:
                   1463:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1464:                                                         (p->hl[2]<<16)|
                   1465:                                                         (p->hl[1]<<8)|
                   1466:                                                         (p->hl[0])) *
                   1467:                                                 off;
                   1468:                                        break;
                   1469:                                case FILE_OPDIVIDE:
                   1470:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1471:                                                         (p->hl[2]<<16)|
                   1472:                                                         (p->hl[1]<<8)|
                   1473:                                                         (p->hl[0])) /
                   1474:                                                 off;
                   1475:                                        break;
                   1476:                                case FILE_OPMODULO:
                   1477:                                        offset = (int32_t)((p->hl[3]<<24)|
                   1478:                                                         (p->hl[2]<<16)|
                   1479:                                                         (p->hl[1]<<8)|
                   1480:                                                         (p->hl[0])) %
                   1481:                                                 off;
                   1482:                                        break;
                   1483:                                }
                   1484:                        } else
                   1485:                                offset = (int32_t)((p->hl[3]<<24)|
                   1486:                                                 (p->hl[2]<<16)|
                   1487:                                                 (p->hl[1]<<8)|
                   1488:                                                 (p->hl[0]));
                   1489:                        if (m->in_op & FILE_OPINVERSE)
                   1490:                                offset = ~offset;
                   1491:                        break;
                   1492:                case FILE_MELONG:
1.1.1.5 ! misho    1493:                        if (OFFSET_OOB(nbytes, offset, 4))
1.1       misho    1494:                                return 0;
                   1495:                        if (off) {
                   1496:                                switch (m->in_op & FILE_OPS_MASK) {
                   1497:                                case FILE_OPAND:
                   1498:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1499:                                                         (p->hl[0]<<16)|
                   1500:                                                         (p->hl[3]<<8)|
                   1501:                                                         (p->hl[2])) &
                   1502:                                                 off;
                   1503:                                        break;
                   1504:                                case FILE_OPOR:
                   1505:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1506:                                                         (p->hl[0]<<16)|
                   1507:                                                         (p->hl[3]<<8)|
                   1508:                                                         (p->hl[2])) |
                   1509:                                                 off;
                   1510:                                        break;
                   1511:                                case FILE_OPXOR:
                   1512:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1513:                                                         (p->hl[0]<<16)|
                   1514:                                                         (p->hl[3]<<8)|
                   1515:                                                         (p->hl[2])) ^
                   1516:                                                 off;
                   1517:                                        break;
                   1518:                                case FILE_OPADD:
                   1519:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1520:                                                         (p->hl[0]<<16)|
                   1521:                                                         (p->hl[3]<<8)|
                   1522:                                                         (p->hl[2])) +
                   1523:                                                 off;
                   1524:                                        break;
                   1525:                                case FILE_OPMINUS:
                   1526:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1527:                                                         (p->hl[0]<<16)|
                   1528:                                                         (p->hl[3]<<8)|
                   1529:                                                         (p->hl[2])) -
                   1530:                                                 off;
                   1531:                                        break;
                   1532:                                case FILE_OPMULTIPLY:
                   1533:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1534:                                                         (p->hl[0]<<16)|
                   1535:                                                         (p->hl[3]<<8)|
                   1536:                                                         (p->hl[2])) *
                   1537:                                                 off;
                   1538:                                        break;
                   1539:                                case FILE_OPDIVIDE:
                   1540:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1541:                                                         (p->hl[0]<<16)|
                   1542:                                                         (p->hl[3]<<8)|
                   1543:                                                         (p->hl[2])) /
                   1544:                                                 off;
                   1545:                                        break;
                   1546:                                case FILE_OPMODULO:
                   1547:                                        offset = (int32_t)((p->hl[1]<<24)|
                   1548:                                                         (p->hl[0]<<16)|
                   1549:                                                         (p->hl[3]<<8)|
                   1550:                                                         (p->hl[2])) %
                   1551:                                                 off;
                   1552:                                        break;
                   1553:                                }
                   1554:                        } else
                   1555:                                offset = (int32_t)((p->hl[1]<<24)|
                   1556:                                                 (p->hl[0]<<16)|
                   1557:                                                 (p->hl[3]<<8)|
                   1558:                                                 (p->hl[2]));
                   1559:                        if (m->in_op & FILE_OPINVERSE)
                   1560:                                offset = ~offset;
                   1561:                        break;
                   1562:                case FILE_LONG:
1.1.1.5 ! misho    1563:                        if (OFFSET_OOB(nbytes, offset, 4))
1.1       misho    1564:                                return 0;
                   1565:                        if (off) {
                   1566:                                switch (m->in_op & FILE_OPS_MASK) {
                   1567:                                case FILE_OPAND:
                   1568:                                        offset = p->l & off;
                   1569:                                        break;
                   1570:                                case FILE_OPOR:
                   1571:                                        offset = p->l | off;
                   1572:                                        break;
                   1573:                                case FILE_OPXOR:
                   1574:                                        offset = p->l ^ off;
                   1575:                                        break;
                   1576:                                case FILE_OPADD:
                   1577:                                        offset = p->l + off;
                   1578:                                        break;
                   1579:                                case FILE_OPMINUS:
                   1580:                                        offset = p->l - off;
                   1581:                                        break;
                   1582:                                case FILE_OPMULTIPLY:
                   1583:                                        offset = p->l * off;
                   1584:                                        break;
                   1585:                                case FILE_OPDIVIDE:
                   1586:                                        offset = p->l / off;
                   1587:                                        break;
                   1588:                                case FILE_OPMODULO:
                   1589:                                        offset = p->l % off;
                   1590:                                        break;
                   1591:                                }
                   1592:                        } else
                   1593:                                offset = p->l;
                   1594:                        if (m->in_op & FILE_OPINVERSE)
                   1595:                                offset = ~offset;
                   1596:                        break;
                   1597:                }
                   1598: 
1.1.1.3   misho    1599:                switch (cvt_flip(m->in_type, flip)) {
1.1       misho    1600:                case FILE_LEID3:
                   1601:                case FILE_BEID3:
                   1602:                        offset = ((((offset >>  0) & 0x7f) <<  0) |
                   1603:                                 (((offset >>  8) & 0x7f) <<  7) |
                   1604:                                 (((offset >> 16) & 0x7f) << 14) |
                   1605:                                 (((offset >> 24) & 0x7f) << 21)) + 10;
                   1606:                        break;
                   1607:                default:
                   1608:                        break;
                   1609:                }
                   1610: 
                   1611:                if (m->flag & INDIROFFADD) {
                   1612:                        offset += ms->c.li[cont_level-1].off;
1.1.1.3   misho    1613:                        if (offset == 0) {
                   1614:                                if ((ms->flags & MAGIC_DEBUG) != 0)
                   1615:                                        fprintf(stderr,
                   1616:                                            "indirect *zero* offset\n");
                   1617:                                return 0;
                   1618:                        }
                   1619:                        if ((ms->flags & MAGIC_DEBUG) != 0)
                   1620:                                fprintf(stderr, "indirect +offs=%u\n", offset);
1.1       misho    1621:                }
                   1622:                if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
                   1623:                        return -1;
                   1624:                ms->offset = offset;
                   1625: 
                   1626:                if ((ms->flags & MAGIC_DEBUG) != 0) {
                   1627:                        mdebug(offset, (char *)(void *)p,
                   1628:                            sizeof(union VALUETYPE));
                   1629:                }
                   1630:        }
                   1631: 
                   1632:        /* Verify we have enough data to match magic type */
                   1633:        switch (m->type) {
                   1634:        case FILE_BYTE:
1.1.1.5 ! misho    1635:                if (OFFSET_OOB(nbytes, offset, 1))
1.1       misho    1636:                        return 0;
                   1637:                break;
                   1638: 
                   1639:        case FILE_SHORT:
                   1640:        case FILE_BESHORT:
                   1641:        case FILE_LESHORT:
1.1.1.5 ! misho    1642:                if (OFFSET_OOB(nbytes, offset, 2))
1.1       misho    1643:                        return 0;
                   1644:                break;
                   1645: 
                   1646:        case FILE_LONG:
                   1647:        case FILE_BELONG:
                   1648:        case FILE_LELONG:
                   1649:        case FILE_MELONG:
                   1650:        case FILE_DATE:
                   1651:        case FILE_BEDATE:
                   1652:        case FILE_LEDATE:
                   1653:        case FILE_MEDATE:
                   1654:        case FILE_LDATE:
                   1655:        case FILE_BELDATE:
                   1656:        case FILE_LELDATE:
                   1657:        case FILE_MELDATE:
                   1658:        case FILE_FLOAT:
                   1659:        case FILE_BEFLOAT:
                   1660:        case FILE_LEFLOAT:
1.1.1.5 ! misho    1661:                if (OFFSET_OOB(nbytes, offset, 4))
1.1       misho    1662:                        return 0;
                   1663:                break;
                   1664: 
                   1665:        case FILE_DOUBLE:
                   1666:        case FILE_BEDOUBLE:
                   1667:        case FILE_LEDOUBLE:
1.1.1.5 ! misho    1668:                if (OFFSET_OOB(nbytes, offset, 8))
1.1       misho    1669:                        return 0;
                   1670:                break;
                   1671: 
                   1672:        case FILE_STRING:
                   1673:        case FILE_PSTRING:
                   1674:        case FILE_SEARCH:
1.1.1.5 ! misho    1675:                if (OFFSET_OOB(nbytes, offset, m->vallen))
1.1       misho    1676:                        return 0;
                   1677:                break;
                   1678: 
                   1679:        case FILE_REGEX:
1.1.1.5 ! misho    1680:                if (OFFSET_OOB(nbytes, offset, 0))
1.1       misho    1681:                        return 0;
                   1682:                break;
                   1683: 
                   1684:        case FILE_INDIRECT:
1.1.1.5 ! misho    1685:                if (offset == 0)
        !          1686:                        return 0;
        !          1687:                if (OFFSET_OOB(nbytes, offset, 0))
1.1.1.3   misho    1688:                        return 0;
                   1689:                sbuf = ms->o.buf;
                   1690:                soffset = ms->offset;
                   1691:                ms->o.buf = NULL;
                   1692:                ms->offset = 0;
                   1693:                rv = file_softmagic(ms, s + offset, nbytes - offset,
1.1.1.5 ! misho    1694:                    recursion_level, BINTEST, text);
1.1.1.3   misho    1695:                if ((ms->flags & MAGIC_DEBUG) != 0)
                   1696:                        fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
                   1697:                rbuf = ms->o.buf;
                   1698:                ms->o.buf = sbuf;
                   1699:                ms->offset = soffset;
                   1700:                if (rv == 1) {
1.1.1.5 ! misho    1701:                        if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
        !          1702:                            file_printf(ms, m->desc, offset) == -1) {
        !          1703:                                if (rbuf) {
        !          1704:                                        efree(rbuf);
        !          1705:                                }
1.1.1.3   misho    1706:                                return -1;
1.1.1.5 ! misho    1707:                        }
        !          1708:                        if (file_printf(ms, "%s", rbuf) == -1) {
        !          1709:                                if (rbuf) {
        !          1710:                                        efree(rbuf);
        !          1711:                                }
        !          1712:                                return -1;
        !          1713:                        }
        !          1714:                }
        !          1715:                if (rbuf) {
1.1.1.3   misho    1716:                        efree(rbuf);
                   1717:                }
                   1718:                return rv;
                   1719: 
                   1720:        case FILE_USE:
1.1.1.5 ! misho    1721:                if (OFFSET_OOB(nbytes, offset, 0))
1.1       misho    1722:                        return 0;
1.1.1.3   misho    1723:                sbuf = m->value.s;
                   1724:                if (*sbuf == '^') {
                   1725:                        sbuf++;
                   1726:                        flip = !flip;
                   1727:                }
                   1728:                if (file_magicfind(ms, sbuf, &ml) == -1) {
                   1729:                        file_error(ms, 0, "cannot find entry `%s'", sbuf);
                   1730:                        return -1;
                   1731:                }
1.1       misho    1732: 
1.1.1.3   misho    1733:                oneed_separator = *need_separator;
                   1734:                if (m->flag & NOSPACE)
                   1735:                        *need_separator = 0;
                   1736:                rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
                   1737:                    mode, text, flip, recursion_level, printed_something,
                   1738:                    need_separator, returnval);
                   1739:                if (rv != 1)
                   1740:                    *need_separator = oneed_separator;
                   1741:                return rv;
                   1742: 
                   1743:        case FILE_NAME:
                   1744:                if (file_printf(ms, "%s", m->desc) == -1)
                   1745:                        return -1;
                   1746:                return 1;
1.1       misho    1747:        case FILE_DEFAULT:      /* nothing to check */
                   1748:        default:
                   1749:                break;
                   1750:        }
1.1.1.3   misho    1751:        if (!mconvert(ms, m, flip))
1.1       misho    1752:                return 0;
                   1753:        return 1;
                   1754: }
                   1755: 
                   1756: private uint64_t
                   1757: file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
                   1758: {
                   1759:        /*
                   1760:         * Convert the source args to unsigned here so that (1) the
                   1761:         * compare will be unsigned as it is in strncmp() and (2) so
                   1762:         * the ctype functions will work correctly without extra
                   1763:         * casting.
                   1764:         */
                   1765:        const unsigned char *a = (const unsigned char *)s1;
                   1766:        const unsigned char *b = (const unsigned char *)s2;
                   1767:        uint64_t v;
                   1768: 
                   1769:        /*
                   1770:         * What we want here is v = strncmp(s1, s2, len),
                   1771:         * but ignoring any nulls.
                   1772:         */
                   1773:        v = 0;
                   1774:        if (0L == flags) { /* normal string: do it fast */
                   1775:                while (len-- > 0)
                   1776:                        if ((v = *b++ - *a++) != '\0')
                   1777:                                break;
                   1778:        }
                   1779:        else { /* combine the others */
                   1780:                while (len-- > 0) {
                   1781:                        if ((flags & STRING_IGNORE_LOWERCASE) &&
                   1782:                            islower(*a)) {
                   1783:                                if ((v = tolower(*b++) - *a++) != '\0')
                   1784:                                        break;
                   1785:                        }
                   1786:                        else if ((flags & STRING_IGNORE_UPPERCASE) &&
                   1787:                            isupper(*a)) {
                   1788:                                if ((v = toupper(*b++) - *a++) != '\0')
                   1789:                                        break;
                   1790:                        }
1.1.1.2   misho    1791:                        else if ((flags & STRING_COMPACT_WHITESPACE) &&
1.1       misho    1792:                            isspace(*a)) {
                   1793:                                a++;
                   1794:                                if (isspace(*b++)) {
1.1.1.2   misho    1795:                                        if (!isspace(*a))
                   1796:                                                while (isspace(*b))
                   1797:                                                        b++;
1.1       misho    1798:                                }
                   1799:                                else {
                   1800:                                        v = 1;
                   1801:                                        break;
                   1802:                                }
                   1803:                        }
1.1.1.2   misho    1804:                        else if ((flags & STRING_COMPACT_OPTIONAL_WHITESPACE) &&
1.1       misho    1805:                            isspace(*a)) {
                   1806:                                a++;
                   1807:                                while (isspace(*b))
                   1808:                                        b++;
                   1809:                        }
                   1810:                        else {
                   1811:                                if ((v = *b++ - *a++) != '\0')
                   1812:                                        break;
                   1813:                        }
                   1814:                }
                   1815:        }
                   1816:        return v;
                   1817: }
                   1818: 
                   1819: private uint64_t
                   1820: file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
                   1821: {
                   1822:        /*
                   1823:         * XXX - The 16-bit string compare probably needs to be done
                   1824:         * differently, especially if the flags are to be supported.
                   1825:         * At the moment, I am unsure.
                   1826:         */
                   1827:        flags = 0;
                   1828:        return file_strncmp(a, b, len, flags);
                   1829: }
                   1830: 
1.1.1.2   misho    1831: public void
1.1       misho    1832: convert_libmagic_pattern(zval *pattern, int options)
                   1833: {
                   1834:                int i, j=0;
                   1835:                char *t;
                   1836: 
                   1837:                t = (char *) safe_emalloc(Z_STRLEN_P(pattern), 2, 5);
                   1838:                
                   1839:                t[j++] = '~';
                   1840:                
                   1841:                for (i=0; i<Z_STRLEN_P(pattern); i++, j++) {
                   1842:                        switch (Z_STRVAL_P(pattern)[i]) {
                   1843:                                case '~':
                   1844:                                        t[j++] = '\\';
                   1845:                                        t[j] = '~';
                   1846:                                        break;
                   1847:                                default:
                   1848:                                        t[j] = Z_STRVAL_P(pattern)[i];
                   1849:                                        break;
                   1850:                        }
                   1851:                }
                   1852:                t[j++] = '~';
                   1853:        
                   1854:                if (options & PCRE_CASELESS) 
1.1.1.2   misho    1855:                        t[j++] = 'i';
1.1       misho    1856:        
                   1857:                if (options & PCRE_MULTILINE)
1.1.1.2   misho    1858:                        t[j++] = 'm';
1.1       misho    1859: 
1.1.1.2   misho    1860:                t[j]='\0';
1.1       misho    1861:        
                   1862:                Z_STRVAL_P(pattern) = t;
                   1863:                Z_STRLEN_P(pattern) = j;
                   1864: 
                   1865: }
                   1866: 
                   1867: private int
                   1868: magiccheck(struct magic_set *ms, struct magic *m)
                   1869: {
                   1870:        uint64_t l = m->value.q;
                   1871:        uint64_t v;
                   1872:        float fl, fv;
                   1873:        double dl, dv;
                   1874:        int matched;
                   1875:        union VALUETYPE *p = &ms->ms_value;
                   1876: 
                   1877:        switch (m->type) {
                   1878:        case FILE_BYTE:
                   1879:                v = p->b;
                   1880:                break;
                   1881: 
                   1882:        case FILE_SHORT:
                   1883:        case FILE_BESHORT:
                   1884:        case FILE_LESHORT:
                   1885:                v = p->h;
                   1886:                break;
                   1887: 
                   1888:        case FILE_LONG:
                   1889:        case FILE_BELONG:
                   1890:        case FILE_LELONG:
                   1891:        case FILE_MELONG:
                   1892:        case FILE_DATE:
                   1893:        case FILE_BEDATE:
                   1894:        case FILE_LEDATE:
                   1895:        case FILE_MEDATE:
                   1896:        case FILE_LDATE:
                   1897:        case FILE_BELDATE:
                   1898:        case FILE_LELDATE:
                   1899:        case FILE_MELDATE:
                   1900:                v = p->l;
                   1901:                break;
                   1902: 
                   1903:        case FILE_QUAD:
                   1904:        case FILE_LEQUAD:
                   1905:        case FILE_BEQUAD:
                   1906:        case FILE_QDATE:
                   1907:        case FILE_BEQDATE:
                   1908:        case FILE_LEQDATE:
                   1909:        case FILE_QLDATE:
                   1910:        case FILE_BEQLDATE:
                   1911:        case FILE_LEQLDATE:
1.1.1.3   misho    1912:        case FILE_QWDATE:
                   1913:        case FILE_BEQWDATE:
                   1914:        case FILE_LEQWDATE:
1.1       misho    1915:                v = p->q;
                   1916:                break;
                   1917: 
                   1918:        case FILE_FLOAT:
                   1919:        case FILE_BEFLOAT:
                   1920:        case FILE_LEFLOAT:
                   1921:                fl = m->value.f;
                   1922:                fv = p->f;
                   1923:                switch (m->reln) {
                   1924:                case 'x':
                   1925:                        matched = 1;
                   1926:                        break;
                   1927: 
                   1928:                case '!':
                   1929:                        matched = fv != fl;
                   1930:                        break;
                   1931: 
                   1932:                case '=':
                   1933:                        matched = fv == fl;
                   1934:                        break;
                   1935: 
                   1936:                case '>':
                   1937:                        matched = fv > fl;
                   1938:                        break;
                   1939: 
                   1940:                case '<':
                   1941:                        matched = fv < fl;
                   1942:                        break;
                   1943: 
                   1944:                default:
                   1945:                        matched = 0;
                   1946:                        file_magerror(ms, "cannot happen with float: invalid relation `%c'",
                   1947:                            m->reln);
                   1948:                        return -1;
                   1949:                }
                   1950:                return matched;
                   1951: 
                   1952:        case FILE_DOUBLE:
                   1953:        case FILE_BEDOUBLE:
                   1954:        case FILE_LEDOUBLE:
                   1955:                dl = m->value.d;
                   1956:                dv = p->d;
                   1957:                switch (m->reln) {
                   1958:                case 'x':
                   1959:                        matched = 1;
                   1960:                        break;
                   1961: 
                   1962:                case '!':
                   1963:                        matched = dv != dl;
                   1964:                        break;
                   1965: 
                   1966:                case '=':
                   1967:                        matched = dv == dl;
                   1968:                        break;
                   1969: 
                   1970:                case '>':
                   1971:                        matched = dv > dl;
                   1972:                        break;
                   1973: 
                   1974:                case '<':
                   1975:                        matched = dv < dl;
                   1976:                        break;
                   1977: 
                   1978:                default:
                   1979:                        matched = 0;
                   1980:                        file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln);
                   1981:                        return -1;
                   1982:                }
                   1983:                return matched;
                   1984: 
                   1985:        case FILE_DEFAULT:
                   1986:                l = 0;
                   1987:                v = 0;
                   1988:                break;
                   1989: 
                   1990:        case FILE_STRING:
                   1991:        case FILE_PSTRING:
                   1992:                l = 0;
                   1993:                v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
                   1994:                break;
                   1995: 
                   1996:        case FILE_BESTRING16:
                   1997:        case FILE_LESTRING16:
                   1998:                l = 0;
                   1999:                v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
                   2000:                break;
                   2001: 
                   2002:        case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
                   2003:                size_t slen;
                   2004:                size_t idx;
                   2005: 
                   2006:                if (ms->search.s == NULL)
                   2007:                        return 0;
                   2008: 
                   2009:                slen = MIN(m->vallen, sizeof(m->value.s));
                   2010:                l = 0;
                   2011:                v = 0;
                   2012: 
                   2013:                for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) {
                   2014:                        if (slen + idx > ms->search.s_len)
                   2015:                                break;
                   2016: 
                   2017:                        v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
                   2018:                        if (v == 0) {   /* found match */
                   2019:                                ms->search.offset += idx;
                   2020:                                break;
                   2021:                        }
                   2022:                }
                   2023:                break;
                   2024:        }
                   2025:        case FILE_REGEX: {
                   2026:                zval *pattern;
                   2027:                int options = 0;
                   2028:                pcre_cache_entry *pce;
                   2029:                TSRMLS_FETCH();
                   2030:                
                   2031:                MAKE_STD_ZVAL(pattern);
                   2032:                ZVAL_STRINGL(pattern, (char *)m->value.s, m->vallen, 0);
                   2033:        
                   2034:                options |= PCRE_MULTILINE;
                   2035:                
                   2036:                if (m->str_flags & STRING_IGNORE_CASE) {
                   2037:                        options |= PCRE_CASELESS;
                   2038:                }
                   2039:                
                   2040:                convert_libmagic_pattern(pattern, options);
                   2041:                
1.1.1.3   misho    2042:                l = v = 0;
1.1       misho    2043:                if ((pce = pcre_get_compiled_regex_cache(Z_STRVAL_P(pattern), Z_STRLEN_P(pattern) TSRMLS_CC)) == NULL) {
                   2044:                        zval_dtor(pattern);
                   2045:                        FREE_ZVAL(pattern);
                   2046:                        return -1;
                   2047:                } else {
                   2048:                        /* pce now contains the compiled regex */
                   2049:                        zval *retval;
                   2050:                        zval *subpats;
                   2051:                        char *haystack;
                   2052:                        
                   2053:                        MAKE_STD_ZVAL(retval);
                   2054:                        ALLOC_INIT_ZVAL(subpats);
                   2055:                        
                   2056:                        /* Cut the search len from haystack, equals to REG_STARTEND */
                   2057:                        haystack = estrndup(ms->search.s, ms->search.s_len);
                   2058: 
                   2059:                        /* match v = 0, no match v = 1 */
                   2060:                        php_pcre_match_impl(pce, haystack, ms->search.s_len, retval, subpats, 1, 1, PREG_OFFSET_CAPTURE, 0 TSRMLS_CC);
                   2061:                        /* Free haystack */
                   2062:                        efree(haystack);
                   2063:                        
                   2064:                        if (Z_LVAL_P(retval) < 0) {
                   2065:                                zval_ptr_dtor(&subpats);
                   2066:                                FREE_ZVAL(retval);
                   2067:                                zval_dtor(pattern);
                   2068:                                FREE_ZVAL(pattern);
                   2069:                                return -1;
                   2070:                        } else if ((Z_LVAL_P(retval) > 0) && (Z_TYPE_P(subpats) == IS_ARRAY)) {
                   2071:                                
                   2072:                                /* Need to fetch global match which equals pmatch[0] */
                   2073:                                HashTable *ht = Z_ARRVAL_P(subpats);
                   2074:                                HashPosition outer_pos;
                   2075:                                zval *pattern_match = NULL, *pattern_offset = NULL;
                   2076:                                
                   2077:                                zend_hash_internal_pointer_reset_ex(ht, &outer_pos); 
                   2078:                                
                   2079:                                if (zend_hash_has_more_elements_ex(ht, &outer_pos) == SUCCESS &&
                   2080:                                        zend_hash_move_forward_ex(ht, &outer_pos)) {
                   2081:                                        
                   2082:                                        zval **ppzval;
                   2083:                                        
                   2084:                                        /* The first element (should be) is the global match 
                   2085:                                           Need to move to the inner array to get the global match */
                   2086:                                        
                   2087:                                        if (zend_hash_get_current_data_ex(ht, (void**)&ppzval, &outer_pos) != FAILURE) { 
                   2088:                                                
                   2089:                                                HashTable *inner_ht;
                   2090:                                                HashPosition inner_pos;
                   2091:                                                zval **match, **offset;
                   2092:                                                zval tmpcopy = **ppzval, matchcopy, offsetcopy;
                   2093:                                                
                   2094:                                                zval_copy_ctor(&tmpcopy); 
                   2095:                                                INIT_PZVAL(&tmpcopy);
                   2096:                                                
                   2097:                                                inner_ht = Z_ARRVAL(tmpcopy);
                   2098:                                                
                   2099:                                                /* If everything goes according to the master plan
                   2100:                                                   tmpcopy now contains two elements:
                   2101:                                                   0 = the match
                   2102:                                                   1 = starting position of the match */
                   2103:                                                zend_hash_internal_pointer_reset_ex(inner_ht, &inner_pos); 
                   2104:                                                
                   2105:                                                if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
                   2106:                                                        zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
                   2107:                                                
                   2108:                                                        if (zend_hash_get_current_data_ex(inner_ht, (void**)&match, &inner_pos) != FAILURE) { 
                   2109:                                                                        
                   2110:                                                                matchcopy = **match;
                   2111:                                                                zval_copy_ctor(&matchcopy);
                   2112:                                                                INIT_PZVAL(&matchcopy);
                   2113:                                                                convert_to_string(&matchcopy); 
                   2114:                                                                
                   2115:                                                                MAKE_STD_ZVAL(pattern_match);
                   2116:                                                                Z_STRVAL_P(pattern_match) = (char *)Z_STRVAL(matchcopy);
                   2117:                                                                Z_STRLEN_P(pattern_match) = Z_STRLEN(matchcopy);
                   2118:                                                                Z_TYPE_P(pattern_match) = IS_STRING; 
                   2119: 
                   2120:                                                                zval_dtor(&matchcopy);
                   2121:                                                        }
                   2122:                                                }
                   2123:                                                
                   2124:                                                if (zend_hash_has_more_elements_ex(inner_ht, &inner_pos) == SUCCESS &&
                   2125:                                                        zend_hash_move_forward_ex(inner_ht, &inner_pos)) {
                   2126:                                                        
                   2127:                                                        if (zend_hash_get_current_data_ex(inner_ht, (void**)&offset, &inner_pos) != FAILURE) { 
                   2128:                                                                
                   2129:                                                                offsetcopy = **offset;
                   2130:                                                                zval_copy_ctor(&offsetcopy);
                   2131:                                                                INIT_PZVAL(&offsetcopy);
                   2132:                                                                convert_to_long(&offsetcopy); 
                   2133:                                                                
                   2134:                                                                MAKE_STD_ZVAL(pattern_offset);
                   2135:                                                                Z_LVAL_P(pattern_offset) = Z_LVAL(offsetcopy);
                   2136:                                                                Z_TYPE_P(pattern_offset) = IS_LONG;
                   2137:                                                                
                   2138:                                                                zval_dtor(&offsetcopy);
                   2139:                                                        }
                   2140:                                                }
                   2141:                                                zval_dtor(&tmpcopy);    
                   2142:                                        }
                   2143:                                        
                   2144:                                        if ((pattern_match != NULL) && (pattern_offset != NULL)) {
                   2145:                                                ms->search.s += (int)Z_LVAL_P(pattern_offset); /* this is where the match starts */
                   2146:                                                ms->search.offset += (size_t)Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */
                   2147:                                                ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */;
                   2148:                                                v = 0;
                   2149:                                                
                   2150:                                                efree(pattern_match);
                   2151:                                                efree(pattern_offset);
                   2152:                                                
                   2153:                                        } else {
                   2154:                                                zval_ptr_dtor(&subpats);
                   2155:                                                FREE_ZVAL(retval);
                   2156:                                                zval_dtor(pattern);
                   2157:                                                FREE_ZVAL(pattern);
                   2158:                                                return -1;
                   2159:                                        }                                       
                   2160:                                }
                   2161: 
                   2162:                                
                   2163:                        } else {
                   2164:                                v = 1;
                   2165:                        }
                   2166:                        zval_ptr_dtor(&subpats);
                   2167:                        FREE_ZVAL(retval);
                   2168:                }
                   2169:                zval_dtor(pattern);
                   2170:                FREE_ZVAL(pattern);
                   2171:                break;  
                   2172:        }
                   2173:        case FILE_INDIRECT:
1.1.1.3   misho    2174:        case FILE_USE:
                   2175:        case FILE_NAME:
1.1       misho    2176:                return 1;        
                   2177:        default:
                   2178:                file_magerror(ms, "invalid type %d in magiccheck()", m->type);
                   2179:                return -1;
                   2180:        }
                   2181: 
                   2182:        v = file_signextend(ms, m, v);
                   2183: 
                   2184:        switch (m->reln) {
                   2185:        case 'x':
                   2186:                if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2187:                        (void) fprintf(stderr, "%" INT64_T_FORMAT
                   2188:                            "u == *any* = 1\n", (unsigned long long)v);
1.1       misho    2189:                matched = 1;
                   2190:                break;
                   2191: 
                   2192:        case '!':
                   2193:                matched = v != l;
                   2194:                if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2195:                        (void) fprintf(stderr, "%" INT64_T_FORMAT "u != %"
                   2196:                            INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
                   2197:                            (unsigned long long)l, matched);
1.1       misho    2198:                break;
                   2199: 
                   2200:        case '=':
                   2201:                matched = v == l;
                   2202:                if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2203:                        (void) fprintf(stderr, "%" INT64_T_FORMAT "u == %"
                   2204:                            INT64_T_FORMAT "u = %d\n", (unsigned long long)v,
                   2205:                            (unsigned long long)l, matched);
1.1       misho    2206:                break;
                   2207: 
                   2208:        case '>':
                   2209:                if (m->flag & UNSIGNED) {
                   2210:                        matched = v > l;
                   2211:                        if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2212:                                (void) fprintf(stderr, "%" INT64_T_FORMAT
                   2213:                                    "u > %" INT64_T_FORMAT "u = %d\n",
                   2214:                                    (unsigned long long)v,
                   2215:                                    (unsigned long long)l, matched);
1.1       misho    2216:                }
                   2217:                else {
                   2218:                        matched = (int64_t) v > (int64_t) l;
                   2219:                        if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2220:                                (void) fprintf(stderr, "%" INT64_T_FORMAT
                   2221:                                    "d > %" INT64_T_FORMAT "d = %d\n",
                   2222:                                    (long long)v, (long long)l, matched);
1.1       misho    2223:                }
                   2224:                break;
                   2225: 
                   2226:        case '<':
                   2227:                if (m->flag & UNSIGNED) {
                   2228:                        matched = v < l;
                   2229:                        if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2230:                                (void) fprintf(stderr, "%" INT64_T_FORMAT
                   2231:                                    "u < %" INT64_T_FORMAT "u = %d\n",
                   2232:                                    (unsigned long long)v,
                   2233:                                    (unsigned long long)l, matched);
1.1       misho    2234:                }
                   2235:                else {
                   2236:                        matched = (int64_t) v < (int64_t) l;
                   2237:                        if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2238:                                (void) fprintf(stderr, "%" INT64_T_FORMAT
                   2239:                                    "d < %" INT64_T_FORMAT "d = %d\n",
                   2240:                                     (long long)v, (long long)l, matched);
1.1       misho    2241:                }
                   2242:                break;
                   2243: 
                   2244:        case '&':
                   2245:                matched = (v & l) == l;
                   2246:                if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2247:                        (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
                   2248:                            INT64_T_FORMAT "x) == %" INT64_T_FORMAT
                   2249:                            "x) = %d\n", (unsigned long long)v,
                   2250:                            (unsigned long long)l, (unsigned long long)l,
                   2251:                            matched);
1.1       misho    2252:                break;
                   2253: 
                   2254:        case '^':
                   2255:                matched = (v & l) != l;
                   2256:                if ((ms->flags & MAGIC_DEBUG) != 0)
1.1.1.2   misho    2257:                        (void) fprintf(stderr, "((%" INT64_T_FORMAT "x & %"
                   2258:                            INT64_T_FORMAT "x) != %" INT64_T_FORMAT
                   2259:                            "x) = %d\n", (unsigned long long)v,
                   2260:                            (unsigned long long)l, (unsigned long long)l,
                   2261:                            matched);
1.1       misho    2262:                break;
                   2263: 
                   2264:        default:
                   2265:                matched = 0;
                   2266:                file_magerror(ms, "cannot happen: invalid relation `%c'",
                   2267:                    m->reln);
                   2268:                return -1;
                   2269:        }
                   2270: 
                   2271:        return matched;
                   2272: }
                   2273: 
                   2274: private int
                   2275: handle_annotation(struct magic_set *ms, struct magic *m)
                   2276: {
                   2277:        if (ms->flags & MAGIC_APPLE) {
                   2278:                if (file_printf(ms, "%.8s", m->apple) == -1)
                   2279:                        return -1;
                   2280:                return 1;
                   2281:        }
                   2282:        if ((ms->flags & MAGIC_MIME_TYPE) && m->mimetype[0]) {
                   2283:                if (file_printf(ms, "%s", m->mimetype) == -1)
                   2284:                        return -1;
                   2285:                return 1;
                   2286:        }
                   2287:        return 0;
                   2288: }
                   2289: 
                   2290: private int
                   2291: print_sep(struct magic_set *ms, int firstline)
                   2292: {
                   2293:        if (ms->flags & MAGIC_MIME)
                   2294:                return 0;
                   2295:        if (firstline)
                   2296:                return 0;
                   2297:        /*
                   2298:         * we found another match
                   2299:         * put a newline and '-' to do some simple formatting
                   2300:         */
                   2301:        return file_printf(ms, "\n- ");
                   2302: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>