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

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

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