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

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

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