[BACK]Return to magic-test.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / file

Annotation of src/usr.bin/file/magic-test.c, Revision 1.18

1.18    ! nicm        1: /* $OpenBSD: magic-test.c,v 1.17 2016/04/30 21:10:28 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2015 Nicholas Marriott <nicm@openbsd.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
                     21: #include <ctype.h>
                     22: #include <errno.h>
                     23: #include <fcntl.h>
                     24: #include <limits.h>
                     25: #include <stdarg.h>
                     26: #include <stdio.h>
                     27: #include <stdint.h>
                     28: #include <stdlib.h>
                     29: #include <string.h>
                     30: #include <unistd.h>
                     31: #include <vis.h>
                     32:
                     33: #include "magic.h"
                     34: #include "xmalloc.h"
                     35:
                     36: static int
                     37: magic_one_eq(char a, char b, int cflag)
                     38: {
                     39:        if (a == b)
                     40:                return (1);
1.4       nicm       41:        if (cflag && islower((u_char)b) && tolower((u_char)a) == (u_char)b)
1.1       nicm       42:                return (1);
                     43:        return (0);
                     44: }
                     45:
                     46: static int
                     47: magic_test_eq(const char *ap, size_t asize, const char *bp, size_t bsize,
                     48:     int cflag, int bflag, int Bflag)
                     49: {
                     50:        size_t  aoff, boff, aspaces, bspaces;
                     51:
                     52:        aoff = boff = 0;
                     53:        while (aoff != asize && boff != bsize) {
                     54:                if (Bflag && isspace((u_char)ap[aoff])) {
                     55:                        aspaces = 0;
                     56:                        while (aoff != asize && isspace((u_char)ap[aoff])) {
                     57:                                aspaces++;
                     58:                                aoff++;
                     59:                        }
                     60:                        bspaces = 0;
                     61:                        while (boff != bsize && isspace((u_char)bp[boff])) {
                     62:                                bspaces++;
                     63:                                boff++;
                     64:                        }
                     65:                        if (bspaces >= aspaces)
                     66:                                continue;
                     67:                        return (1);
                     68:                }
                     69:                if (magic_one_eq(ap[aoff], bp[boff], cflag)) {
                     70:                        aoff++;
                     71:                        boff++;
                     72:                        continue;
                     73:                }
                     74:                if (bflag && isspace((u_char)bp[boff])) {
                     75:                        boff++;
                     76:                        continue;
                     77:                }
                     78:                if (ap[aoff] < bp[boff])
                     79:                        return (-1);
                     80:                return (1);
                     81:        }
                     82:        return (0);
                     83: }
                     84:
                     85: static int
                     86: magic_copy_from(struct magic_state *ms, ssize_t offset, void *dst, size_t size)
                     87: {
                     88:        if (offset < 0)
                     89:                offset = ms->offset;
                     90:        if (offset + size > ms->size)
                     91:                return (-1);
                     92:        memcpy(dst, ms->base + offset, size);
                     93:        return (0);
                     94: }
                     95:
                     96: static void
                     97: magic_add_result(struct magic_state *ms, struct magic_line *ml,
                     98:     const char *fmt, ...)
                     99: {
                    100:        va_list  ap;
                    101:        int      separate;
                    102:        char    *s, *tmp, *add;
                    103:
                    104:        va_start(ap, fmt);
                    105:        if (ml->stringify) {
                    106:                if (vasprintf(&s, fmt, ap) == -1) {
                    107:                        va_end(ap);
                    108:                        return;
                    109:                }
                    110:                va_end(ap);
                    111:                if (asprintf(&tmp, ml->result, s) == -1) {
                    112:                        free(s);
                    113:                        return;
                    114:                }
                    115:                free(s);
                    116:        } else {
                    117:                if (vasprintf(&tmp, ml->result, ap) == -1) {
                    118:                        va_end(ap);
                    119:                        return;
                    120:                }
                    121:                va_end(ap);
                    122:        }
                    123:
                    124:        separate = 1;
                    125:        if (tmp[0] == '\\' && tmp[1] == 'b') {
                    126:                separate = 0;
                    127:                add = tmp + 2;
                    128:        } else
                    129:                add = tmp;
                    130:
                    131:        if (separate && *ms->out != '\0')
                    132:                strlcat(ms->out, " ", sizeof ms->out);
                    133:        strlcat(ms->out, add, sizeof ms->out);
                    134:
                    135:        free(tmp);
                    136: }
                    137:
                    138: static void
                    139: magic_add_string(struct magic_state *ms, struct magic_line *ml,
1.2       deraadt   140:     const char *s, size_t slen)
1.1       nicm      141: {
                    142:        char    *out;
                    143:        size_t   outlen, offset;
                    144:
                    145:        outlen = MAGIC_STRING_SIZE;
                    146:        if (outlen > slen)
                    147:                outlen = slen;
                    148:        for (offset = 0; offset < outlen; offset++) {
                    149:                if (s[offset] == '\0' || !isprint((u_char)s[offset])) {
                    150:                        outlen = offset;
                    151:                        break;
                    152:                }
                    153:        }
                    154:        out = xreallocarray(NULL, 4, outlen + 1);
                    155:        strvisx(out, s, outlen, VIS_TAB|VIS_NL|VIS_CSTYLE|VIS_OCTAL);
                    156:        magic_add_result(ms, ml, "%s", out);
                    157:        free(out);
                    158: }
                    159:
                    160: static int
                    161: magic_test_signed(struct magic_line *ml, int64_t value, int64_t wanted)
                    162: {
                    163:        switch (ml->test_operator) {
                    164:        case 'x':
                    165:                return (1);
                    166:        case '<':
                    167:                return (value < wanted);
                    168:        case '[':
                    169:                return (value <= wanted);
                    170:        case '>':
                    171:                return (value > wanted);
                    172:        case ']':
                    173:                return (value >= wanted);
                    174:        case '=':
                    175:                return (value == wanted);
                    176:        case '&':
                    177:                return ((value & wanted) == wanted);
                    178:        case '^':
                    179:                return ((~value & wanted) == wanted);
                    180:        }
                    181:        return (-1);
                    182: }
                    183:
                    184: static int
                    185: magic_test_unsigned(struct magic_line *ml, uint64_t value, uint64_t wanted)
                    186: {
                    187:        switch (ml->test_operator) {
                    188:        case 'x':
                    189:                return (1);
                    190:        case '<':
                    191:                return (value < wanted);
                    192:        case '[':
                    193:                return (value <= wanted);
                    194:        case '>':
                    195:                return (value > wanted);
                    196:        case ']':
                    197:                return (value >= wanted);
                    198:        case '=':
                    199:                return (value == wanted);
                    200:        case '&':
                    201:                return ((value & wanted) == wanted);
                    202:        case '^':
                    203:                return ((~value & wanted) == wanted);
                    204:        }
                    205:        return (-1);
                    206: }
                    207:
                    208: static int
1.7       nicm      209: magic_test_double(struct magic_line *ml, double value, double wanted)
                    210: {
                    211:        switch (ml->test_operator) {
                    212:        case 'x':
                    213:                return (1);
                    214:        case '=':
                    215:                return (value == wanted);
                    216:        }
                    217:        return (-1);
                    218: }
                    219:
                    220: static int
1.1       nicm      221: magic_test_type_none(__unused struct magic_line *ml,
                    222:     __unused struct magic_state *ms)
                    223: {
                    224:        return (0);
                    225: }
                    226:
                    227: static int
                    228: magic_test_type_byte(struct magic_line *ml, struct magic_state *ms)
                    229: {
                    230:        int8_t  value;
                    231:        int     result;
                    232:
                    233:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    234:                return (0);
                    235:
                    236:        if (ml->type_operator == '&')
                    237:                value &= (int8_t)ml->type_operand;
1.8       nicm      238:        else if (ml->type_operator == '-')
                    239:                value -= (int8_t)ml->type_operand;
                    240:        else if (ml->type_operator == '+')
                    241:                value += (int8_t)ml->type_operand;
                    242:        else if (ml->type_operator == '/')
                    243:                value /= (int8_t)ml->type_operand;
                    244:        else if (ml->type_operator == '%')
                    245:                value %= (int8_t)ml->type_operand;
                    246:        else if (ml->type_operator == '*')
                    247:                value *= (int8_t)ml->type_operand;
1.1       nicm      248:        else if (ml->type_operator != ' ')
                    249:                return (-1);
                    250:
                    251:        result = magic_test_signed(ml, value, (int8_t)ml->test_signed);
                    252:        if (result == !ml->test_not && ml->result != NULL) {
                    253:                magic_add_result(ms, ml, "%c", (int)value);
                    254:                ms->offset += sizeof value;
                    255:        }
                    256:        return (result);
                    257: }
                    258:
                    259: static int
                    260: magic_test_type_short(struct magic_line *ml, struct magic_state *ms)
                    261: {
                    262:        int16_t value;
                    263:        int     result;
                    264:
                    265:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    266:                return (0);
                    267:        if (ml->type == MAGIC_TYPE_BESHORT)
1.3       brynet    268:                value = be16toh(value);
1.1       nicm      269:        if (ml->type == MAGIC_TYPE_LESHORT)
1.3       brynet    270:                value = le16toh(value);
1.1       nicm      271:
                    272:        if (ml->type_operator == '&')
                    273:                value &= (int16_t)ml->type_operand;
1.8       nicm      274:        else if (ml->type_operator == '-')
                    275:                value -= (int16_t)ml->type_operand;
                    276:        else if (ml->type_operator == '+')
                    277:                value += (int16_t)ml->type_operand;
                    278:        else if (ml->type_operator == '/')
                    279:                value /= (int16_t)ml->type_operand;
                    280:        else if (ml->type_operator == '%')
                    281:                value %= (int16_t)ml->type_operand;
                    282:        else if (ml->type_operator == '*')
                    283:                value *= (int16_t)ml->type_operand;
1.1       nicm      284:        else if (ml->type_operator != ' ')
                    285:                return (-1);
                    286:
                    287:        result = magic_test_signed(ml, value, (int16_t)ml->test_signed);
                    288:        if (result == !ml->test_not && ml->result != NULL) {
                    289:                magic_add_result(ms, ml, "%hd", (int)value);
                    290:                ms->offset += sizeof value;
                    291:        }
                    292:        return (result);
                    293: }
                    294:
                    295: static int
                    296: magic_test_type_long(struct magic_line *ml, struct magic_state *ms)
                    297: {
                    298:        int32_t value;
                    299:        int     result;
                    300:
                    301:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    302:                return (0);
                    303:        if (ml->type == MAGIC_TYPE_BELONG)
1.3       brynet    304:                value = be32toh(value);
1.1       nicm      305:        if (ml->type == MAGIC_TYPE_LELONG)
1.3       brynet    306:                value = le32toh(value);
1.1       nicm      307:
                    308:        if (ml->type_operator == '&')
                    309:                value &= (int32_t)ml->type_operand;
1.8       nicm      310:        else if (ml->type_operator == '-')
                    311:                value -= (int32_t)ml->type_operand;
                    312:        else if (ml->type_operator == '+')
                    313:                value += (int32_t)ml->type_operand;
                    314:        else if (ml->type_operator == '/')
                    315:                value /= (int32_t)ml->type_operand;
                    316:        else if (ml->type_operator == '%')
                    317:                value %= (int32_t)ml->type_operand;
                    318:        else if (ml->type_operator == '*')
                    319:                value *= (int32_t)ml->type_operand;
1.1       nicm      320:        else if (ml->type_operator != ' ')
                    321:                return (-1);
                    322:
                    323:        result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
                    324:        if (result == !ml->test_not && ml->result != NULL) {
                    325:                magic_add_result(ms, ml, "%d", (int)value);
                    326:                ms->offset += sizeof value;
                    327:        }
                    328:        return (result);
                    329: }
                    330:
                    331: static int
                    332: magic_test_type_quad(struct magic_line *ml, struct magic_state *ms)
                    333: {
                    334:        int64_t value;
                    335:        int     result;
                    336:
                    337:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    338:                return (0);
                    339:        if (ml->type == MAGIC_TYPE_BEQUAD)
1.3       brynet    340:                value = be64toh(value);
1.1       nicm      341:        if (ml->type == MAGIC_TYPE_LEQUAD)
1.3       brynet    342:                value = le64toh(value);
1.1       nicm      343:
                    344:        if (ml->type_operator == '&')
                    345:                value &= (int64_t)ml->type_operand;
1.8       nicm      346:        else if (ml->type_operator == '-')
                    347:                value -= (int64_t)ml->type_operand;
                    348:        else if (ml->type_operator == '+')
                    349:                value += (int64_t)ml->type_operand;
                    350:        else if (ml->type_operator == '/')
                    351:                value /= (int64_t)ml->type_operand;
                    352:        else if (ml->type_operator == '%')
                    353:                value %= (int64_t)ml->type_operand;
                    354:        else if (ml->type_operator == '*')
                    355:                value *= (int64_t)ml->type_operand;
1.1       nicm      356:        else if (ml->type_operator != ' ')
                    357:                return (-1);
                    358:
                    359:        result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
                    360:        if (result == !ml->test_not && ml->result != NULL) {
                    361:                magic_add_result(ms, ml, "%lld", (long long)value);
                    362:                ms->offset += sizeof value;
                    363:        }
                    364:        return (result);
                    365: }
                    366:
                    367: static int
                    368: magic_test_type_ubyte(struct magic_line *ml, struct magic_state *ms)
                    369: {
                    370:        uint8_t value;
                    371:        int     result;
                    372:
                    373:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    374:                return (0);
                    375:
                    376:        if (ml->type_operator == '&')
                    377:                value &= (uint8_t)ml->type_operand;
1.8       nicm      378:        else if (ml->type_operator == '-')
                    379:                value -= (uint8_t)ml->type_operand;
                    380:        else if (ml->type_operator == '+')
                    381:                value += (uint8_t)ml->type_operand;
                    382:        else if (ml->type_operator == '/')
                    383:                value /= (uint8_t)ml->type_operand;
                    384:        else if (ml->type_operator == '%')
                    385:                value %= (uint8_t)ml->type_operand;
                    386:        else if (ml->type_operator == '*')
                    387:                value *= (uint8_t)ml->type_operand;
1.1       nicm      388:        else if (ml->type_operator != ' ')
                    389:                return (-1);
                    390:
                    391:        result = magic_test_unsigned(ml, value, (uint8_t)ml->test_unsigned);
                    392:        if (result == !ml->test_not && ml->result != NULL) {
                    393:                magic_add_result(ms, ml, "%c", (unsigned int)value);
                    394:                ms->offset += sizeof value;
                    395:        }
                    396:        return (result);
                    397: }
                    398:
                    399: static int
                    400: magic_test_type_ushort(struct magic_line *ml, struct magic_state *ms)
                    401: {
                    402:        uint16_t        value;
                    403:        int             result;
                    404:
                    405:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    406:                return (0);
                    407:        if (ml->type == MAGIC_TYPE_UBESHORT)
1.3       brynet    408:                value = be16toh(value);
1.1       nicm      409:        if (ml->type == MAGIC_TYPE_ULESHORT)
1.3       brynet    410:                value = le16toh(value);
1.1       nicm      411:
                    412:        if (ml->type_operator == '&')
                    413:                value &= (uint16_t)ml->type_operand;
1.8       nicm      414:        else if (ml->type_operator == '-')
                    415:                value -= (uint16_t)ml->type_operand;
                    416:        else if (ml->type_operator == '+')
                    417:                value += (uint16_t)ml->type_operand;
                    418:        else if (ml->type_operator == '/')
                    419:                value /= (uint16_t)ml->type_operand;
                    420:        else if (ml->type_operator == '%')
                    421:                value %= (uint16_t)ml->type_operand;
                    422:        else if (ml->type_operator == '*')
                    423:                value *= (uint16_t)ml->type_operand;
1.1       nicm      424:        else if (ml->type_operator != ' ')
                    425:                return (-1);
                    426:
                    427:        result = magic_test_unsigned(ml, value, (uint16_t)ml->test_unsigned);
                    428:        if (result == !ml->test_not && ml->result != NULL) {
                    429:                magic_add_result(ms, ml, "%hu", (unsigned int)value);
                    430:                ms->offset += sizeof value;
                    431:        }
                    432:        return (result);
                    433: }
                    434:
                    435: static int
                    436: magic_test_type_ulong(struct magic_line *ml, struct magic_state *ms)
                    437: {
                    438:        uint32_t        value;
                    439:        int             result;
                    440:
                    441:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    442:                return (0);
                    443:        if (ml->type == MAGIC_TYPE_UBELONG)
1.3       brynet    444:                value = be32toh(value);
1.1       nicm      445:        if (ml->type == MAGIC_TYPE_ULELONG)
1.3       brynet    446:                value = le32toh(value);
1.1       nicm      447:
                    448:        if (ml->type_operator == '&')
                    449:                value &= (uint32_t)ml->type_operand;
1.8       nicm      450:        else if (ml->type_operator == '-')
                    451:                value -= (uint32_t)ml->type_operand;
                    452:        else if (ml->type_operator == '+')
                    453:                value += (uint32_t)ml->type_operand;
                    454:        else if (ml->type_operator == '/')
                    455:                value /= (uint32_t)ml->type_operand;
                    456:        else if (ml->type_operator == '%')
                    457:                value %= (uint32_t)ml->type_operand;
                    458:        else if (ml->type_operator == '*')
                    459:                value *= (uint32_t)ml->type_operand;
1.1       nicm      460:        else if (ml->type_operator != ' ')
                    461:                return (-1);
                    462:
                    463:        result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
                    464:        if (result == !ml->test_not && ml->result != NULL) {
                    465:                magic_add_result(ms, ml, "%u", (unsigned int)value);
                    466:                ms->offset += sizeof value;
                    467:        }
                    468:        return (result);
                    469: }
                    470:
                    471: static int
                    472: magic_test_type_uquad(struct magic_line *ml, struct magic_state *ms)
                    473: {
                    474:        uint64_t        value;
                    475:        int             result;
                    476:
                    477:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    478:                return (0);
                    479:        if (ml->type == MAGIC_TYPE_UBEQUAD)
1.3       brynet    480:                value = be64toh(value);
1.1       nicm      481:        if (ml->type == MAGIC_TYPE_ULEQUAD)
1.3       brynet    482:                value = le64toh(value);
1.1       nicm      483:
                    484:        if (ml->type_operator == '&')
                    485:                value &= (uint64_t)ml->type_operand;
1.8       nicm      486:        else if (ml->type_operator == '-')
                    487:                value -= (uint64_t)ml->type_operand;
                    488:        else if (ml->type_operator == '+')
                    489:                value += (uint64_t)ml->type_operand;
                    490:        else if (ml->type_operator == '/')
                    491:                value /= (uint64_t)ml->type_operand;
                    492:        else if (ml->type_operator == '%')
                    493:                value %= (uint64_t)ml->type_operand;
                    494:        else if (ml->type_operator == '*')
                    495:                value *= (uint64_t)ml->type_operand;
1.1       nicm      496:        else if (ml->type_operator != ' ')
                    497:                return (-1);
                    498:
                    499:        result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
                    500:        if (result == !ml->test_not && ml->result != NULL) {
                    501:                magic_add_result(ms, ml, "%llu", (unsigned long long)value);
                    502:                ms->offset += sizeof value;
                    503:        }
                    504:        return (result);
                    505: }
                    506:
                    507: static int
                    508: magic_test_type_float(struct magic_line *ml, struct magic_state *ms)
                    509: {
                    510:        uint32_t        value0;
1.16      nicm      511:        float           value;
1.7       nicm      512:        int             result;
1.1       nicm      513:
                    514:        if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
                    515:                return (0);
                    516:        if (ml->type == MAGIC_TYPE_BEFLOAT)
1.3       brynet    517:                value0 = be32toh(value0);
1.1       nicm      518:        if (ml->type == MAGIC_TYPE_LEFLOAT)
1.3       brynet    519:                value0 = le32toh(value0);
1.1       nicm      520:        memcpy(&value, &value0, sizeof value);
                    521:
                    522:        if (ml->type_operator != ' ')
                    523:                return (-1);
                    524:
1.7       nicm      525:        result = magic_test_double(ml, value, (float)ml->test_double);
                    526:        if (result == !ml->test_not && ml->result != NULL) {
                    527:                magic_add_result(ms, ml, "%g", value);
                    528:                ms->offset += sizeof value0;
                    529:        }
1.1       nicm      530:        return (1);
                    531: }
                    532:
                    533: static int
                    534: magic_test_type_double(struct magic_line *ml, struct magic_state *ms)
                    535: {
                    536:        uint64_t        value0;
                    537:        double          value;
1.7       nicm      538:        int             result;
1.1       nicm      539:
                    540:        if (magic_copy_from(ms, -1, &value0, sizeof value0) != 0)
                    541:                return (0);
                    542:        if (ml->type == MAGIC_TYPE_BEDOUBLE)
1.3       brynet    543:                value0 = be64toh(value0);
1.1       nicm      544:        if (ml->type == MAGIC_TYPE_LEDOUBLE)
1.3       brynet    545:                value0 = le64toh(value0);
1.1       nicm      546:        memcpy(&value, &value0, sizeof value);
                    547:
                    548:        if (ml->type_operator != ' ')
                    549:                return (-1);
                    550:
1.7       nicm      551:        result = magic_test_double(ml, value, (double)ml->test_double);
                    552:        if (result == !ml->test_not && ml->result != NULL) {
                    553:                magic_add_result(ms, ml, "%g", value);
                    554:                ms->offset += sizeof value0;
                    555:        }
1.1       nicm      556:        return (1);
                    557: }
                    558:
                    559: static int
                    560: magic_test_type_string(struct magic_line *ml, struct magic_state *ms)
                    561: {
                    562:        const char      *s, *cp;
                    563:        size_t           slen;
                    564:        int              result, cflag = 0, bflag = 0, Bflag = 0;
                    565:
                    566:        cp = &ml->type_string[(sizeof "string") - 1];
                    567:        if (*cp != '\0') {
                    568:                if (*cp != '/')
                    569:                        return (-1);
                    570:                cp++;
                    571:                for (; *cp != '\0'; cp++) {
                    572:                        switch (*cp) {
                    573:                        case 'B':
1.11      nicm      574:                        case 'W':
1.1       nicm      575:                                Bflag = 1;
                    576:                                break;
                    577:                        case 'b':
1.11      nicm      578:                        case 'w':
1.1       nicm      579:                                bflag = 1;
                    580:                                break;
                    581:                        case 'c':
                    582:                                cflag = 1;
                    583:                                break;
1.11      nicm      584:                        case 't':
                    585:                                break;
1.1       nicm      586:                        default:
                    587:                                return (-1);
                    588:                        }
                    589:                }
                    590:        }
                    591:
                    592:        s = ms->base + ms->offset;
                    593:        slen = ms->size - ms->offset;
                    594:        if (slen < ml->test_string_size)
                    595:                return (0);
                    596:
                    597:        result = magic_test_eq(s, slen, ml->test_string, ml->test_string_size,
                    598:            cflag, bflag, Bflag);
                    599:        switch (ml->test_operator) {
                    600:        case 'x':
                    601:                result = 1;
                    602:                break;
                    603:        case '<':
                    604:                result = result < 0;
                    605:                break;
                    606:        case '>':
                    607:                result = result > 0;
                    608:                break;
                    609:        case '=':
1.10      nicm      610:                slen = ml->test_string_size; /* only print what was found */
1.1       nicm      611:                result = result == 0;
                    612:                break;
                    613:        default:
                    614:                result = -1;
                    615:                break;
                    616:        }
                    617:        if (result == !ml->test_not) {
                    618:                if (ml->result != NULL)
                    619:                        magic_add_string(ms, ml, s, slen);
                    620:                if (result && ml->test_operator == '=')
                    621:                        ms->offset = s - ms->base + ml->test_string_size;
                    622:        }
                    623:        return (result);
                    624: }
                    625:
                    626: static int
                    627: magic_test_type_pstring(struct magic_line *ml, struct magic_state *ms)
                    628: {
1.9       nicm      629:        const char      *s, *cp;
1.1       nicm      630:        size_t           slen;
                    631:        int              result;
1.9       nicm      632:
                    633:        cp = &ml->type_string[(sizeof "pstring") - 1];
                    634:        if (*cp != '\0') {
                    635:                if (*cp != '/')
                    636:                        return (-1);
                    637:                cp++;
                    638:                for (; *cp != '\0'; cp++) {
                    639:                        switch (*cp) {
                    640:                        default:
                    641:                                return (-1);
                    642:                        }
                    643:                }
                    644:        }
1.1       nicm      645:
                    646:        s = ms->base + ms->offset;
                    647:        if (ms->size - ms->offset < 1)
                    648:                return (-1);
                    649:        slen = *(u_char *)s;
                    650:        if (slen > ms->size - ms->offset)
                    651:                return (-1);
                    652:        s++;
                    653:
                    654:        if (slen < ml->test_string_size)
                    655:                result = -1;
                    656:        else if (slen > ml->test_string_size)
                    657:                result = 1;
                    658:        else
                    659:                result = memcmp(s, ml->test_string, ml->test_string_size);
                    660:        switch (ml->test_operator) {
                    661:        case 'x':
                    662:                result = 1;
                    663:                break;
                    664:        case '<':
                    665:                result = result < 0;
                    666:                break;
                    667:        case '>':
                    668:                result = result > 0;
                    669:                break;
                    670:        case '=':
                    671:                result = result == 0;
                    672:                break;
                    673:        default:
                    674:                result = -1;
                    675:                break;
                    676:        }
                    677:        if (result == !ml->test_not) {
                    678:                if (ml->result != NULL)
                    679:                        magic_add_string(ms, ml, s, slen);
1.12      nicm      680:                if (result && ml->test_operator == '=')
1.1       nicm      681:                        ms->offset += slen + 1;
                    682:        }
                    683:        return (result);
                    684: }
                    685:
                    686: static int
                    687: magic_test_type_date(struct magic_line *ml, struct magic_state *ms)
                    688: {
                    689:        int32_t value;
                    690:        int     result;
                    691:        time_t  t;
                    692:        char    s[64];
                    693:
                    694:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    695:                return (0);
                    696:        if (ml->type == MAGIC_TYPE_BEDATE ||
                    697:            ml->type == MAGIC_TYPE_BELDATE)
1.3       brynet    698:                value = be32toh(value);
1.1       nicm      699:        if (ml->type == MAGIC_TYPE_LEDATE ||
                    700:            ml->type == MAGIC_TYPE_LELDATE)
1.3       brynet    701:                value = le32toh(value);
1.1       nicm      702:
                    703:        if (ml->type_operator == '&')
                    704:                value &= (int32_t)ml->type_operand;
1.13      nicm      705:        else if (ml->type_operator == '-')
                    706:                value -= (int32_t)ml->type_operand;
                    707:        else if (ml->type_operator == '+')
                    708:                value += (int32_t)ml->type_operand;
1.1       nicm      709:        else if (ml->type_operator != ' ')
                    710:                return (-1);
                    711:
                    712:        result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
                    713:        if (result == !ml->test_not && ml->result != NULL) {
                    714:                t = value;
                    715:                switch (ml->type) {
                    716:                case MAGIC_TYPE_LDATE:
                    717:                case MAGIC_TYPE_LELDATE:
                    718:                case MAGIC_TYPE_BELDATE:
                    719:                        ctime_r(&t, s);
                    720:                        break;
                    721:                default:
1.6       nicm      722:                        asctime_r(gmtime(&t), s);
1.1       nicm      723:                        break;
                    724:                }
                    725:                s[strcspn(s, "\n")] = '\0';
                    726:                magic_add_result(ms, ml, "%s", s);
                    727:                ms->offset += sizeof value;
                    728:        }
                    729:        return (result);
                    730: }
                    731:
                    732: static int
                    733: magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms)
                    734: {
                    735:        int64_t value;
                    736:        int     result;
                    737:        time_t  t;
                    738:        char    s[64];
                    739:
                    740:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    741:                return (0);
                    742:        if (ml->type == MAGIC_TYPE_BEQDATE ||
                    743:            ml->type == MAGIC_TYPE_BEQLDATE)
1.3       brynet    744:                value = be64toh(value);
1.1       nicm      745:        if (ml->type == MAGIC_TYPE_LEQDATE ||
                    746:            ml->type == MAGIC_TYPE_LEQLDATE)
1.3       brynet    747:                value = le64toh(value);
1.1       nicm      748:
                    749:        if (ml->type_operator == '&')
                    750:                value &= (int64_t)ml->type_operand;
1.13      nicm      751:        else if (ml->type_operator == '-')
                    752:                value -= (int64_t)ml->type_operand;
                    753:        else if (ml->type_operator == '+')
                    754:                value += (int64_t)ml->type_operand;
1.1       nicm      755:        else if (ml->type_operator != ' ')
                    756:                return (-1);
                    757:
                    758:        result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
                    759:        if (result == !ml->test_not && ml->result != NULL) {
                    760:                t = value;
                    761:                switch (ml->type) {
                    762:                case MAGIC_TYPE_QLDATE:
                    763:                case MAGIC_TYPE_LEQLDATE:
                    764:                case MAGIC_TYPE_BEQLDATE:
                    765:                        ctime_r(&t, s);
                    766:                        break;
                    767:                default:
1.6       nicm      768:                        asctime_r(gmtime(&t), s);
1.1       nicm      769:                        break;
                    770:                }
                    771:                s[strcspn(s, "\n")] = '\0';
                    772:                magic_add_result(ms, ml, "%s", s);
                    773:                ms->offset += sizeof value;
                    774:        }
                    775:        return (result);
                    776: }
                    777:
                    778: static int
                    779: magic_test_type_udate(struct magic_line *ml, struct magic_state *ms)
                    780: {
                    781:        uint32_t        value;
                    782:        int             result;
                    783:        time_t          t;
                    784:        char            s[64];
                    785:
                    786:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    787:                return (0);
                    788:        if (ml->type == MAGIC_TYPE_BEDATE ||
                    789:            ml->type == MAGIC_TYPE_BELDATE)
1.3       brynet    790:                value = be32toh(value);
1.1       nicm      791:        if (ml->type == MAGIC_TYPE_LEDATE ||
                    792:            ml->type == MAGIC_TYPE_LELDATE)
1.3       brynet    793:                value = le32toh(value);
1.1       nicm      794:
                    795:        if (ml->type_operator == '&')
                    796:                value &= (uint32_t)ml->type_operand;
1.13      nicm      797:        else if (ml->type_operator == '-')
                    798:                value -= (uint32_t)ml->type_operand;
                    799:        else if (ml->type_operator == '+')
                    800:                value += (uint32_t)ml->type_operand;
1.1       nicm      801:        else if (ml->type_operator != ' ')
                    802:                return (-1);
                    803:
                    804:        result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
                    805:        if (result == !ml->test_not && ml->result != NULL) {
                    806:                t = value;
                    807:                switch (ml->type) {
                    808:                case MAGIC_TYPE_LDATE:
                    809:                case MAGIC_TYPE_LELDATE:
                    810:                case MAGIC_TYPE_BELDATE:
                    811:                        ctime_r(&t, s);
                    812:                        break;
                    813:                default:
                    814:                        asctime_r(gmtime(&t), s);
                    815:                        break;
                    816:                }
                    817:                s[strcspn(s, "\n")] = '\0';
                    818:                magic_add_result(ms, ml, "%s", s);
                    819:                ms->offset += sizeof value;
                    820:        }
                    821:        return (result);
                    822: }
                    823:
                    824: static int
                    825: magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms)
                    826: {
                    827:        uint64_t        value;
                    828:        int             result;
                    829:        time_t          t;
                    830:        char            s[64];
                    831:
                    832:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    833:                return (0);
                    834:        if (ml->type == MAGIC_TYPE_UBEQDATE ||
                    835:            ml->type == MAGIC_TYPE_UBEQLDATE)
1.3       brynet    836:                value = be64toh(value);
1.1       nicm      837:        if (ml->type == MAGIC_TYPE_ULEQDATE ||
                    838:            ml->type == MAGIC_TYPE_ULEQLDATE)
1.3       brynet    839:                value = le64toh(value);
1.1       nicm      840:
                    841:        if (ml->type_operator == '&')
                    842:                value &= (uint64_t)ml->type_operand;
1.13      nicm      843:        else if (ml->type_operator == '-')
                    844:                value -= (uint64_t)ml->type_operand;
                    845:        else if (ml->type_operator == '+')
                    846:                value += (uint64_t)ml->type_operand;
1.1       nicm      847:        else if (ml->type_operator != ' ')
                    848:                return (-1);
                    849:
                    850:        result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
                    851:        if (result == !ml->test_not && ml->result != NULL) {
                    852:                t = value;
                    853:                switch (ml->type) {
                    854:                case MAGIC_TYPE_UQLDATE:
                    855:                case MAGIC_TYPE_ULEQLDATE:
                    856:                case MAGIC_TYPE_UBEQLDATE:
                    857:                        ctime_r(&t, s);
                    858:                        break;
                    859:                default:
                    860:                        asctime_r(gmtime(&t), s);
                    861:                        break;
                    862:                }
                    863:                s[strcspn(s, "\n")] = '\0';
                    864:                magic_add_result(ms, ml, "%s", s);
                    865:                ms->offset += sizeof value;
                    866:        }
                    867:        return (result);
                    868: }
                    869:
                    870: static int
                    871: magic_test_type_bestring16(__unused struct magic_line *ml,
                    872:     __unused struct magic_state *ms)
                    873: {
                    874:        return (-2);
                    875: }
                    876:
                    877: static int
                    878: magic_test_type_lestring16(__unused struct magic_line *ml,
                    879:     __unused struct magic_state *ms)
                    880: {
                    881:        return (-2);
                    882: }
                    883:
                    884: static int
                    885: magic_test_type_melong(__unused struct magic_line *ml,
                    886:     __unused struct magic_state *ms)
                    887: {
                    888:        return (-2);
                    889: }
                    890:
                    891: static int
                    892: magic_test_type_medate(__unused struct magic_line *ml,
                    893:     __unused struct magic_state *ms)
                    894: {
                    895:        return (-2);
                    896: }
                    897:
                    898: static int
                    899: magic_test_type_meldate(__unused struct magic_line *ml,
                    900:     __unused struct magic_state *ms)
                    901: {
                    902:        return (-2);
                    903: }
                    904:
                    905: static int
                    906: magic_test_type_regex(struct magic_line *ml, struct magic_state *ms)
                    907: {
                    908:        const char      *cp;
                    909:        regex_t          re;
                    910:        regmatch_t       m;
                    911:        int              result, flags = 0, sflag = 0;
                    912:
                    913:        cp = &ml->type_string[(sizeof "regex") - 1];
                    914:        if (*cp != '\0') {
                    915:                if (*cp != '/')
                    916:                        return (-1);
                    917:                cp++;
                    918:                for (; *cp != '\0'; cp++) {
                    919:                        switch (*cp) {
                    920:                        case 's':
                    921:                                sflag = 1;
                    922:                                break;
                    923:                        case 'c':
                    924:                                flags |= REG_ICASE;
                    925:                                break;
                    926:                        default:
                    927:                                return (-1);
                    928:                        }
                    929:                }
                    930:        }
                    931:
                    932:        if (regcomp(&re, ml->test_string, REG_EXTENDED) != 0)
                    933:                return (-1);
                    934:        m.rm_so = ms->offset;
                    935:        m.rm_eo = ms->size;
                    936:
                    937:        result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0);
1.12      nicm      938:        if (result == !ml->test_not) {
1.17      nicm      939:                if (ml->result != NULL) {
                    940:                        magic_add_string(ms, ml, ms->base + m.rm_so,
                    941:                            m.rm_eo - m.rm_so);
                    942:                }
1.1       nicm      943:                if (result) {
                    944:                        if (sflag)
                    945:                                ms->offset = m.rm_so;
                    946:                        else
                    947:                                ms->offset = m.rm_eo;
                    948:                }
                    949:        }
                    950:        regfree(&re);
                    951:        return (result);
                    952: }
                    953:
                    954: static int
                    955: magic_test_type_search(struct magic_line *ml, struct magic_state *ms)
                    956: {
                    957:        const char      *cp, *endptr, *start, *found;
                    958:        size_t           size, end, i;
                    959:        uint64_t         range;
                    960:        int              result, n, cflag = 0, bflag = 0, Bflag = 0;
                    961:
                    962:        cp = &ml->type_string[(sizeof "search") - 1];
                    963:        if (*cp != '\0') {
                    964:                if (*cp != '/')
                    965:                        return (-1);
                    966:                cp++;
                    967:
                    968:                endptr = magic_strtoull(cp, &range);
                    969:                if (endptr == NULL || (*endptr != '/' && *endptr != '\0'))
                    970:                        return (-1);
                    971:
                    972:                if (*endptr == '/') {
                    973:                        for (cp = endptr + 1; *cp != '\0'; cp++) {
                    974:                                switch (*cp) {
                    975:                                case 'B':
1.11      nicm      976:                                case 'W':
1.1       nicm      977:                                        Bflag = 1;
                    978:                                        break;
                    979:                                case 'b':
1.11      nicm      980:                                case 'w':
1.1       nicm      981:                                        bflag = 1;
                    982:                                        break;
                    983:                                case 'c':
                    984:                                        cflag = 1;
1.11      nicm      985:                                        break;
                    986:                                case 't':
1.1       nicm      987:                                        break;
                    988:                                default:
                    989:                                        return (-1);
                    990:                                }
                    991:                        }
                    992:                }
                    993:        } else
                    994:                range = UINT64_MAX;
                    995:        if (range > (uint64_t)ms->size - ms->offset)
                    996:                range = ms->size - ms->offset;
                    997:        size = ml->test_string_size;
                    998:
                    999:        /* Want to search every starting position from up to range + size. */
                   1000:        end = range + size;
                   1001:        if (end > ms->size - ms->offset) {
                   1002:                if (size > ms->size - ms->offset)
                   1003:                        end = 0;
                   1004:                else
                   1005:                        end = ms->size - ms->offset - size;
                   1006:        }
                   1007:
                   1008:        /*
                   1009:         * < and > and the flags are only in /etc/magic with search/1 so don't
                   1010:         * support them with anything else.
                   1011:         */
                   1012:        start = ms->base + ms->offset;
                   1013:        if (end == 0)
                   1014:                found = NULL;
                   1015:        else if (ml->test_operator == 'x')
                   1016:                found = start;
                   1017:        else if (range == 1) {
                   1018:                n = magic_test_eq(start, ms->size - ms->offset, ml->test_string,
                   1019:                    size, cflag, bflag, Bflag);
                   1020:                if (n == -1 && ml->test_operator == '<')
                   1021:                        found = start;
                   1022:                else if (n == 1 && ml->test_operator == '>')
                   1023:                        found = start;
                   1024:                else if (n == 0 && ml->test_operator == '=')
                   1025:                        found = start;
                   1026:                else
                   1027:                        found = NULL;
                   1028:        } else {
                   1029:                if (ml->test_operator != '=')
                   1030:                        return (-2);
                   1031:                for (i = 0; i < end; i++) {
                   1032:                        n = magic_test_eq(start + i, ms->size - ms->offset - i,
                   1033:                            ml->test_string, size, cflag, bflag, Bflag);
                   1034:                        if (n == 0) {
                   1035:                                found = start + i;
                   1036:                                break;
                   1037:                        }
                   1038:                }
                   1039:                if (i == end)
                   1040:                        found = NULL;
                   1041:        }
                   1042:        result = (found != NULL);
                   1043:
1.12      nicm     1044:        if (result == !ml->test_not) {
                   1045:                if (ml->result != NULL)
                   1046:                        magic_add_string(ms, ml, found, ms->size - ms->offset);
                   1047:                if (result && found != NULL && ml->test_operator == '=')
                   1048:                        ms->offset = (found + size) - ms->base;
1.1       nicm     1049:        }
                   1050:        return (result);
                   1051: }
                   1052:
                   1053: static int
                   1054: magic_test_type_default(__unused struct magic_line *ml,
                   1055:     __unused struct magic_state *ms)
                   1056: {
1.18    ! nicm     1057:        return (!ms->matched);
1.1       nicm     1058: }
                   1059:
                   1060: static int (*magic_test_functions[])(struct magic_line *,
                   1061:     struct magic_state *) = {
                   1062:        magic_test_type_none,
                   1063:        magic_test_type_byte,
                   1064:        magic_test_type_short,
                   1065:        magic_test_type_long,
                   1066:        magic_test_type_quad,
                   1067:        magic_test_type_ubyte,
                   1068:        magic_test_type_ushort,
                   1069:        magic_test_type_ulong,
                   1070:        magic_test_type_uquad,
                   1071:        magic_test_type_float,
                   1072:        magic_test_type_double,
                   1073:        magic_test_type_string,
                   1074:        magic_test_type_pstring,
                   1075:        magic_test_type_date,
                   1076:        magic_test_type_qdate,
                   1077:        magic_test_type_date,
                   1078:        magic_test_type_qdate,
                   1079:        magic_test_type_udate,
                   1080:        magic_test_type_uqdate,
                   1081:        magic_test_type_udate,
                   1082:        magic_test_type_qdate,
                   1083:        magic_test_type_short,
                   1084:        magic_test_type_long,
                   1085:        magic_test_type_quad,
                   1086:        magic_test_type_ushort,
                   1087:        magic_test_type_ulong,
                   1088:        magic_test_type_uquad,
                   1089:        magic_test_type_float,
                   1090:        magic_test_type_double,
                   1091:        magic_test_type_date,
                   1092:        magic_test_type_qdate,
                   1093:        magic_test_type_date,
                   1094:        magic_test_type_qdate,
                   1095:        magic_test_type_udate,
                   1096:        magic_test_type_uqdate,
                   1097:        magic_test_type_udate,
                   1098:        magic_test_type_uqdate,
                   1099:        magic_test_type_bestring16,
                   1100:        magic_test_type_short,
                   1101:        magic_test_type_long,
                   1102:        magic_test_type_quad,
                   1103:        magic_test_type_ushort,
                   1104:        magic_test_type_ulong,
                   1105:        magic_test_type_uquad,
                   1106:        magic_test_type_float,
                   1107:        magic_test_type_double,
                   1108:        magic_test_type_date,
                   1109:        magic_test_type_qdate,
                   1110:        magic_test_type_date,
                   1111:        magic_test_type_qdate,
                   1112:        magic_test_type_udate,
                   1113:        magic_test_type_uqdate,
                   1114:        magic_test_type_udate,
                   1115:        magic_test_type_uqdate,
                   1116:        magic_test_type_lestring16,
                   1117:        magic_test_type_melong,
                   1118:        magic_test_type_medate,
                   1119:        magic_test_type_meldate,
                   1120:        magic_test_type_regex,
                   1121:        magic_test_type_search,
                   1122:        magic_test_type_default,
                   1123: };
                   1124:
                   1125: static int
                   1126: magic_test_line(struct magic_line *ml, struct magic_state *ms)
                   1127: {
                   1128:        struct magic_line       *child;
                   1129:        int64_t                  offset, wanted, next;
                   1130:        int                      result;
                   1131:        uint8_t                  b;
                   1132:        uint16_t                 s;
                   1133:        uint32_t                 l;
                   1134:
                   1135:        if (ml->indirect_type == ' ')
                   1136:                wanted = ml->offset;
                   1137:        else {
                   1138:                wanted = ml->indirect_offset;
                   1139:                if (ml->indirect_relative) {
1.14      nicm     1140:                        if (wanted < 0 && (size_t)-wanted > ms->offset)
1.1       nicm     1141:                                return (0);
                   1142:                        if (wanted > 0 && ms->offset + wanted > ms->size)
                   1143:                                return (0);
                   1144:                        next = ms->offset + ml->indirect_offset;
                   1145:                } else
                   1146:                        next = wanted;
                   1147:
                   1148:                switch (ml->indirect_type) {
                   1149:                case 'b':
                   1150:                case 'B':
                   1151:                        if (magic_copy_from(ms, next, &b, sizeof b) != 0)
                   1152:                                return (0);
                   1153:                        wanted = b;
                   1154:                        break;
                   1155:                case 's':
                   1156:                        if (magic_copy_from(ms, next, &s, sizeof s) != 0)
                   1157:                                return (0);
1.3       brynet   1158:                        wanted = le16toh(s);
1.1       nicm     1159:                        break;
                   1160:                case 'S':
                   1161:                        if (magic_copy_from(ms, next, &s, sizeof s) != 0)
                   1162:                                return (0);
1.3       brynet   1163:                        wanted = be16toh(s);
1.1       nicm     1164:                        break;
                   1165:                case 'l':
                   1166:                        if (magic_copy_from(ms, next, &l, sizeof l) != 0)
                   1167:                                return (0);
1.3       brynet   1168:                        wanted = le16toh(l);
1.1       nicm     1169:                        break;
                   1170:                case 'L':
                   1171:                        if (magic_copy_from(ms, next, &l, sizeof l) != 0)
                   1172:                                return (0);
1.3       brynet   1173:                        wanted = be16toh(l);
1.1       nicm     1174:                        break;
                   1175:                }
                   1176:
                   1177:                switch (ml->indirect_operator) {
                   1178:                case '+':
                   1179:                        wanted += ml->indirect_operand;
                   1180:                        break;
                   1181:                case '-':
                   1182:                        wanted -= ml->indirect_operand;
                   1183:                        break;
                   1184:                case '*':
                   1185:                        wanted *= ml->indirect_operand;
                   1186:                        break;
                   1187:                }
                   1188:        }
                   1189:
                   1190:        if (ml->offset_relative) {
1.14      nicm     1191:                if (wanted < 0 && (size_t)-wanted > ms->offset)
1.1       nicm     1192:                        return (0);
                   1193:                if (wanted > 0 && ms->offset + wanted > ms->size)
                   1194:                        return (0);
                   1195:                offset = ms->offset + wanted;
                   1196:        } else
                   1197:                offset = wanted;
1.14      nicm     1198:        if (offset < 0 || (size_t)offset > ms->size)
1.1       nicm     1199:                return (0);
                   1200:        ms->offset = offset;
                   1201:
                   1202:        result = magic_test_functions[ml->type](ml, ms);
                   1203:        if (result == -1) {
                   1204:                magic_warn(ml, "test %s/%c failed", ml->type_string,
                   1205:                    ml->test_operator);
                   1206:                return (0);
                   1207:        }
                   1208:        if (result == -2) {
                   1209:                magic_warn(ml, "test %s/%c not implemented", ml->type_string,
                   1210:                    ml->test_operator);
                   1211:                return (0);
                   1212:        }
                   1213:        if (result == ml->test_not)
                   1214:                return (0);
                   1215:        if (ml->mimetype != NULL)
                   1216:                ms->mimetype = ml->mimetype;
                   1217:
1.15      nicm     1218:        magic_warn(ml, "test %s/%c matched at offset %lld (now %zu): '%s'",
                   1219:            ml->type_string, ml->test_operator, offset, ms->offset,
1.1       nicm     1220:            ml->result == NULL ? "" : ml->result);
                   1221:
1.18    ! nicm     1222:        ms->matched = 0;
1.1       nicm     1223:        offset = ms->offset;
                   1224:        TAILQ_FOREACH(child, &ml->children, entry) {
                   1225:                ms->offset = offset;
                   1226:                magic_test_line(child, ms);
                   1227:        }
1.18    ! nicm     1228:
        !          1229:        ms->matched = 1;
1.5       nicm     1230:        return (ml->result != NULL);
1.1       nicm     1231: }
                   1232:
                   1233: const char *
                   1234: magic_test(struct magic *m, const void *base, size_t size, int flags)
                   1235: {
                   1236:        struct magic_line               *ml;
                   1237:        static struct magic_state        ms;
                   1238:
                   1239:        memset(&ms, 0, sizeof ms);
                   1240:
                   1241:        ms.base = base;
                   1242:        ms.size = size;
                   1243:
                   1244:        ms.text = !!(flags & MAGIC_TEST_TEXT);
                   1245:
                   1246:        RB_FOREACH(ml, magic_tree, &m->tree) {
                   1247:                ms.offset = 0;
                   1248:                if (ml->text == ms.text && magic_test_line(ml, &ms))
                   1249:                        break;
                   1250:        }
                   1251:
                   1252:        if (*ms.out != '\0') {
                   1253:                if (flags & MAGIC_TEST_MIME) {
                   1254:                        if (ms.mimetype)
                   1255:                                return (xstrdup(ms.mimetype));
                   1256:                        return (NULL);
                   1257:                }
                   1258:                return (xstrdup(ms.out));
                   1259:        }
                   1260:        return (NULL);
                   1261: }