[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.11

1.11    ! nicm        1: /* $OpenBSD: magic-test.c,v 1.10 2015/08/11 23:03:26 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;
                    511:        double          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);
                    680:                if (result)
                    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;
                    705:        else if (ml->type_operator != ' ')
                    706:                return (-1);
                    707:
                    708:        result = magic_test_signed(ml, value, (int32_t)ml->test_signed);
                    709:        if (result == !ml->test_not && ml->result != NULL) {
                    710:                t = value;
                    711:                switch (ml->type) {
                    712:                case MAGIC_TYPE_LDATE:
                    713:                case MAGIC_TYPE_LELDATE:
                    714:                case MAGIC_TYPE_BELDATE:
                    715:                        ctime_r(&t, s);
                    716:                        break;
                    717:                default:
1.6       nicm      718:                        asctime_r(gmtime(&t), s);
1.1       nicm      719:                        break;
                    720:                }
                    721:                s[strcspn(s, "\n")] = '\0';
                    722:                magic_add_result(ms, ml, "%s", s);
                    723:                ms->offset += sizeof value;
                    724:        }
                    725:        return (result);
                    726: }
                    727:
                    728: static int
                    729: magic_test_type_qdate(struct magic_line *ml, struct magic_state *ms)
                    730: {
                    731:        int64_t value;
                    732:        int     result;
                    733:        time_t  t;
                    734:        char    s[64];
                    735:
                    736:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    737:                return (0);
                    738:        if (ml->type == MAGIC_TYPE_BEQDATE ||
                    739:            ml->type == MAGIC_TYPE_BEQLDATE)
1.3       brynet    740:                value = be64toh(value);
1.1       nicm      741:        if (ml->type == MAGIC_TYPE_LEQDATE ||
                    742:            ml->type == MAGIC_TYPE_LEQLDATE)
1.3       brynet    743:                value = le64toh(value);
1.1       nicm      744:
                    745:        if (ml->type_operator == '&')
                    746:                value &= (int64_t)ml->type_operand;
                    747:        else if (ml->type_operator != ' ')
                    748:                return (-1);
                    749:
                    750:        result = magic_test_signed(ml, value, (int64_t)ml->test_signed);
                    751:        if (result == !ml->test_not && ml->result != NULL) {
                    752:                t = value;
                    753:                switch (ml->type) {
                    754:                case MAGIC_TYPE_QLDATE:
                    755:                case MAGIC_TYPE_LEQLDATE:
                    756:                case MAGIC_TYPE_BEQLDATE:
                    757:                        ctime_r(&t, s);
                    758:                        break;
                    759:                default:
1.6       nicm      760:                        asctime_r(gmtime(&t), s);
1.1       nicm      761:                        break;
                    762:                }
                    763:                s[strcspn(s, "\n")] = '\0';
                    764:                magic_add_result(ms, ml, "%s", s);
                    765:                ms->offset += sizeof value;
                    766:        }
                    767:        return (result);
                    768: }
                    769:
                    770: static int
                    771: magic_test_type_udate(struct magic_line *ml, struct magic_state *ms)
                    772: {
                    773:        uint32_t        value;
                    774:        int             result;
                    775:        time_t          t;
                    776:        char            s[64];
                    777:
                    778:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    779:                return (0);
                    780:        if (ml->type == MAGIC_TYPE_BEDATE ||
                    781:            ml->type == MAGIC_TYPE_BELDATE)
1.3       brynet    782:                value = be32toh(value);
1.1       nicm      783:        if (ml->type == MAGIC_TYPE_LEDATE ||
                    784:            ml->type == MAGIC_TYPE_LELDATE)
1.3       brynet    785:                value = le32toh(value);
1.1       nicm      786:
                    787:        if (ml->type_operator == '&')
                    788:                value &= (uint32_t)ml->type_operand;
                    789:        else if (ml->type_operator != ' ')
                    790:                return (-1);
                    791:
                    792:        result = magic_test_unsigned(ml, value, (uint32_t)ml->test_unsigned);
                    793:        if (result == !ml->test_not && ml->result != NULL) {
                    794:                t = value;
                    795:                switch (ml->type) {
                    796:                case MAGIC_TYPE_LDATE:
                    797:                case MAGIC_TYPE_LELDATE:
                    798:                case MAGIC_TYPE_BELDATE:
                    799:                        ctime_r(&t, s);
                    800:                        break;
                    801:                default:
                    802:                        asctime_r(gmtime(&t), s);
                    803:                        break;
                    804:                }
                    805:                s[strcspn(s, "\n")] = '\0';
                    806:                magic_add_result(ms, ml, "%s", s);
                    807:                ms->offset += sizeof value;
                    808:        }
                    809:        return (result);
                    810: }
                    811:
                    812: static int
                    813: magic_test_type_uqdate(struct magic_line *ml, struct magic_state *ms)
                    814: {
                    815:        uint64_t        value;
                    816:        int             result;
                    817:        time_t          t;
                    818:        char            s[64];
                    819:
                    820:        if (magic_copy_from(ms, -1, &value, sizeof value) != 0)
                    821:                return (0);
                    822:        if (ml->type == MAGIC_TYPE_UBEQDATE ||
                    823:            ml->type == MAGIC_TYPE_UBEQLDATE)
1.3       brynet    824:                value = be64toh(value);
1.1       nicm      825:        if (ml->type == MAGIC_TYPE_ULEQDATE ||
                    826:            ml->type == MAGIC_TYPE_ULEQLDATE)
1.3       brynet    827:                value = le64toh(value);
1.1       nicm      828:
                    829:        if (ml->type_operator == '&')
                    830:                value &= (uint64_t)ml->type_operand;
                    831:        else if (ml->type_operator != ' ')
                    832:                return (-1);
                    833:
                    834:        result = magic_test_unsigned(ml, value, (uint64_t)ml->test_unsigned);
                    835:        if (result == !ml->test_not && ml->result != NULL) {
                    836:                t = value;
                    837:                switch (ml->type) {
                    838:                case MAGIC_TYPE_UQLDATE:
                    839:                case MAGIC_TYPE_ULEQLDATE:
                    840:                case MAGIC_TYPE_UBEQLDATE:
                    841:                        ctime_r(&t, s);
                    842:                        break;
                    843:                default:
                    844:                        asctime_r(gmtime(&t), s);
                    845:                        break;
                    846:                }
                    847:                s[strcspn(s, "\n")] = '\0';
                    848:                magic_add_result(ms, ml, "%s", s);
                    849:                ms->offset += sizeof value;
                    850:        }
                    851:        return (result);
                    852: }
                    853:
                    854: static int
                    855: magic_test_type_bestring16(__unused struct magic_line *ml,
                    856:     __unused struct magic_state *ms)
                    857: {
                    858:        return (-2);
                    859: }
                    860:
                    861: static int
                    862: magic_test_type_lestring16(__unused struct magic_line *ml,
                    863:     __unused struct magic_state *ms)
                    864: {
                    865:        return (-2);
                    866: }
                    867:
                    868: static int
                    869: magic_test_type_melong(__unused struct magic_line *ml,
                    870:     __unused struct magic_state *ms)
                    871: {
                    872:        return (-2);
                    873: }
                    874:
                    875: static int
                    876: magic_test_type_medate(__unused struct magic_line *ml,
                    877:     __unused struct magic_state *ms)
                    878: {
                    879:        return (-2);
                    880: }
                    881:
                    882: static int
                    883: magic_test_type_meldate(__unused struct magic_line *ml,
                    884:     __unused struct magic_state *ms)
                    885: {
                    886:        return (-2);
                    887: }
                    888:
                    889: static int
                    890: magic_test_type_regex(struct magic_line *ml, struct magic_state *ms)
                    891: {
                    892:        const char      *cp;
                    893:        regex_t          re;
                    894:        regmatch_t       m;
                    895:        int              result, flags = 0, sflag = 0;
                    896:
                    897:        cp = &ml->type_string[(sizeof "regex") - 1];
                    898:        if (*cp != '\0') {
                    899:                if (*cp != '/')
                    900:                        return (-1);
                    901:                cp++;
                    902:                for (; *cp != '\0'; cp++) {
                    903:                        switch (*cp) {
                    904:                        case 's':
                    905:                                sflag = 1;
                    906:                                break;
                    907:                        case 'c':
                    908:                                flags |= REG_ICASE;
                    909:                                break;
                    910:                        default:
                    911:                                return (-1);
                    912:                        }
                    913:                }
                    914:        }
                    915:
                    916:        if (regcomp(&re, ml->test_string, REG_EXTENDED) != 0)
                    917:                return (-1);
                    918:        m.rm_so = ms->offset;
                    919:        m.rm_eo = ms->size;
                    920:
                    921:        result = (regexec(&re, ms->base, 1, &m, REG_STARTEND) == 0);
                    922:        if (result == !ml->test_not && ml->result != NULL) {
                    923:                magic_add_result(ms, ml, "%s", "");
                    924:                if (result) {
                    925:                        if (sflag)
                    926:                                ms->offset = m.rm_so;
                    927:                        else
                    928:                                ms->offset = m.rm_eo;
                    929:                }
                    930:        }
                    931:        regfree(&re);
                    932:        return (result);
                    933: }
                    934:
                    935: static int
                    936: magic_test_type_search(struct magic_line *ml, struct magic_state *ms)
                    937: {
                    938:        const char      *cp, *endptr, *start, *found;
                    939:        size_t           size, end, i;
                    940:        uint64_t         range;
                    941:        int              result, n, cflag = 0, bflag = 0, Bflag = 0;
                    942:
                    943:        cp = &ml->type_string[(sizeof "search") - 1];
                    944:        if (*cp != '\0') {
                    945:                if (*cp != '/')
                    946:                        return (-1);
                    947:                cp++;
                    948:
                    949:                endptr = magic_strtoull(cp, &range);
                    950:                if (endptr == NULL || (*endptr != '/' && *endptr != '\0'))
                    951:                        return (-1);
                    952:
                    953:                if (*endptr == '/') {
                    954:                        for (cp = endptr + 1; *cp != '\0'; cp++) {
                    955:                                switch (*cp) {
                    956:                                case 'B':
1.11    ! nicm      957:                                case 'W':
1.1       nicm      958:                                        Bflag = 1;
                    959:                                        break;
                    960:                                case 'b':
1.11    ! nicm      961:                                case 'w':
1.1       nicm      962:                                        bflag = 1;
                    963:                                        break;
                    964:                                case 'c':
                    965:                                        cflag = 1;
1.11    ! nicm      966:                                        break;
        !           967:                                case 't':
1.1       nicm      968:                                        break;
                    969:                                default:
                    970:                                        return (-1);
                    971:                                }
                    972:                        }
                    973:                }
                    974:        } else
                    975:                range = UINT64_MAX;
                    976:        if (range > (uint64_t)ms->size - ms->offset)
                    977:                range = ms->size - ms->offset;
                    978:        size = ml->test_string_size;
                    979:
                    980:        /* Want to search every starting position from up to range + size. */
                    981:        end = range + size;
                    982:        if (end > ms->size - ms->offset) {
                    983:                if (size > ms->size - ms->offset)
                    984:                        end = 0;
                    985:                else
                    986:                        end = ms->size - ms->offset - size;
                    987:        }
                    988:
                    989:        /*
                    990:         * < and > and the flags are only in /etc/magic with search/1 so don't
                    991:         * support them with anything else.
                    992:         */
                    993:        start = ms->base + ms->offset;
                    994:        if (end == 0)
                    995:                found = NULL;
                    996:        else if (ml->test_operator == 'x')
                    997:                found = start;
                    998:        else if (range == 1) {
                    999:                n = magic_test_eq(start, ms->size - ms->offset, ml->test_string,
                   1000:                    size, cflag, bflag, Bflag);
                   1001:                if (n == -1 && ml->test_operator == '<')
                   1002:                        found = start;
                   1003:                else if (n == 1 && ml->test_operator == '>')
                   1004:                        found = start;
                   1005:                else if (n == 0 && ml->test_operator == '=')
                   1006:                        found = start;
                   1007:                else
                   1008:                        found = NULL;
                   1009:        } else {
                   1010:                if (ml->test_operator != '=')
                   1011:                        return (-2);
                   1012:                for (i = 0; i < end; i++) {
                   1013:                        n = magic_test_eq(start + i, ms->size - ms->offset - i,
                   1014:                            ml->test_string, size, cflag, bflag, Bflag);
                   1015:                        if (n == 0) {
                   1016:                                found = start + i;
                   1017:                                break;
                   1018:                        }
                   1019:                }
                   1020:                if (i == end)
                   1021:                        found = NULL;
                   1022:        }
                   1023:        result = (found != NULL);
                   1024:
                   1025:        if (result == !ml->test_not && ml->result != NULL && found != NULL) {
                   1026:                magic_add_string(ms, ml, found, ms->size - ms->offset);
                   1027:                ms->offset = found - start + size;
                   1028:        }
                   1029:        return (result);
                   1030: }
                   1031:
                   1032: static int
                   1033: magic_test_type_default(__unused struct magic_line *ml,
                   1034:     __unused struct magic_state *ms)
                   1035: {
                   1036:        return (1);
                   1037: }
                   1038:
                   1039: static int (*magic_test_functions[])(struct magic_line *,
                   1040:     struct magic_state *) = {
                   1041:        magic_test_type_none,
                   1042:        magic_test_type_byte,
                   1043:        magic_test_type_short,
                   1044:        magic_test_type_long,
                   1045:        magic_test_type_quad,
                   1046:        magic_test_type_ubyte,
                   1047:        magic_test_type_ushort,
                   1048:        magic_test_type_ulong,
                   1049:        magic_test_type_uquad,
                   1050:        magic_test_type_float,
                   1051:        magic_test_type_double,
                   1052:        magic_test_type_string,
                   1053:        magic_test_type_pstring,
                   1054:        magic_test_type_date,
                   1055:        magic_test_type_qdate,
                   1056:        magic_test_type_date,
                   1057:        magic_test_type_qdate,
                   1058:        magic_test_type_udate,
                   1059:        magic_test_type_uqdate,
                   1060:        magic_test_type_udate,
                   1061:        magic_test_type_qdate,
                   1062:        magic_test_type_short,
                   1063:        magic_test_type_long,
                   1064:        magic_test_type_quad,
                   1065:        magic_test_type_ushort,
                   1066:        magic_test_type_ulong,
                   1067:        magic_test_type_uquad,
                   1068:        magic_test_type_float,
                   1069:        magic_test_type_double,
                   1070:        magic_test_type_date,
                   1071:        magic_test_type_qdate,
                   1072:        magic_test_type_date,
                   1073:        magic_test_type_qdate,
                   1074:        magic_test_type_udate,
                   1075:        magic_test_type_uqdate,
                   1076:        magic_test_type_udate,
                   1077:        magic_test_type_uqdate,
                   1078:        magic_test_type_bestring16,
                   1079:        magic_test_type_short,
                   1080:        magic_test_type_long,
                   1081:        magic_test_type_quad,
                   1082:        magic_test_type_ushort,
                   1083:        magic_test_type_ulong,
                   1084:        magic_test_type_uquad,
                   1085:        magic_test_type_float,
                   1086:        magic_test_type_double,
                   1087:        magic_test_type_date,
                   1088:        magic_test_type_qdate,
                   1089:        magic_test_type_date,
                   1090:        magic_test_type_qdate,
                   1091:        magic_test_type_udate,
                   1092:        magic_test_type_uqdate,
                   1093:        magic_test_type_udate,
                   1094:        magic_test_type_uqdate,
                   1095:        magic_test_type_lestring16,
                   1096:        magic_test_type_melong,
                   1097:        magic_test_type_medate,
                   1098:        magic_test_type_meldate,
                   1099:        magic_test_type_regex,
                   1100:        magic_test_type_search,
                   1101:        magic_test_type_default,
                   1102: };
                   1103:
                   1104: static int
                   1105: magic_test_line(struct magic_line *ml, struct magic_state *ms)
                   1106: {
                   1107:        struct magic_line       *child;
                   1108:        int64_t                  offset, wanted, next;
                   1109:        int                      result;
                   1110:        uint8_t                  b;
                   1111:        uint16_t                 s;
                   1112:        uint32_t                 l;
                   1113:
                   1114:        if (ml->indirect_type == ' ')
                   1115:                wanted = ml->offset;
                   1116:        else {
                   1117:                wanted = ml->indirect_offset;
                   1118:                if (ml->indirect_relative) {
                   1119:                        if (wanted < 0 && -wanted > ms->offset)
                   1120:                                return (0);
                   1121:                        if (wanted > 0 && ms->offset + wanted > ms->size)
                   1122:                                return (0);
                   1123:                        next = ms->offset + ml->indirect_offset;
                   1124:                } else
                   1125:                        next = wanted;
                   1126:
                   1127:                switch (ml->indirect_type) {
                   1128:                case 'b':
                   1129:                case 'B':
                   1130:                        if (magic_copy_from(ms, next, &b, sizeof b) != 0)
                   1131:                                return (0);
                   1132:                        wanted = b;
                   1133:                        break;
                   1134:                case 's':
                   1135:                        if (magic_copy_from(ms, next, &s, sizeof s) != 0)
                   1136:                                return (0);
1.3       brynet   1137:                        wanted = le16toh(s);
1.1       nicm     1138:                        break;
                   1139:                case 'S':
                   1140:                        if (magic_copy_from(ms, next, &s, sizeof s) != 0)
                   1141:                                return (0);
1.3       brynet   1142:                        wanted = be16toh(s);
1.1       nicm     1143:                        break;
                   1144:                case 'l':
                   1145:                        if (magic_copy_from(ms, next, &l, sizeof l) != 0)
                   1146:                                return (0);
1.3       brynet   1147:                        wanted = le16toh(l);
1.1       nicm     1148:                        break;
                   1149:                case 'L':
                   1150:                        if (magic_copy_from(ms, next, &l, sizeof l) != 0)
                   1151:                                return (0);
1.3       brynet   1152:                        wanted = be16toh(l);
1.1       nicm     1153:                        break;
                   1154:                }
                   1155:
                   1156:                switch (ml->indirect_operator) {
                   1157:                case '+':
                   1158:                        wanted += ml->indirect_operand;
                   1159:                        break;
                   1160:                case '-':
                   1161:                        wanted -= ml->indirect_operand;
                   1162:                        break;
                   1163:                case '*':
                   1164:                        wanted *= ml->indirect_operand;
                   1165:                        break;
                   1166:                }
                   1167:        }
                   1168:
                   1169:        if (ml->offset_relative) {
                   1170:                if (wanted < 0 && -wanted > ms->offset)
                   1171:                        return (0);
                   1172:                if (wanted > 0 && ms->offset + wanted > ms->size)
                   1173:                        return (0);
                   1174:                offset = ms->offset + wanted;
                   1175:        } else
                   1176:                offset = wanted;
                   1177:        if (offset < 0 || offset > ms->size)
                   1178:                return (0);
                   1179:        ms->offset = offset;
                   1180:
                   1181:        result = magic_test_functions[ml->type](ml, ms);
                   1182:        if (result == -1) {
                   1183:                magic_warn(ml, "test %s/%c failed", ml->type_string,
                   1184:                    ml->test_operator);
                   1185:                return (0);
                   1186:        }
                   1187:        if (result == -2) {
                   1188:                magic_warn(ml, "test %s/%c not implemented", ml->type_string,
                   1189:                    ml->test_operator);
                   1190:                return (0);
                   1191:        }
                   1192:        if (result == ml->test_not)
                   1193:                return (0);
                   1194:        if (ml->mimetype != NULL)
                   1195:                ms->mimetype = ml->mimetype;
                   1196:
                   1197:        magic_warn(ml, "test %s/%c matched at offset %llu: '%s'",
                   1198:            ml->type_string, ml->test_operator, ms->offset,
                   1199:            ml->result == NULL ? "" : ml->result);
                   1200:
                   1201:        offset = ms->offset;
                   1202:        TAILQ_FOREACH(child, &ml->children, entry) {
                   1203:                ms->offset = offset;
                   1204:                magic_test_line(child, ms);
                   1205:        }
1.5       nicm     1206:        return (ml->result != NULL);
1.1       nicm     1207: }
                   1208:
                   1209: const char *
                   1210: magic_test(struct magic *m, const void *base, size_t size, int flags)
                   1211: {
                   1212:        struct magic_line               *ml;
                   1213:        static struct magic_state        ms;
                   1214:
                   1215:        memset(&ms, 0, sizeof ms);
                   1216:
                   1217:        ms.base = base;
                   1218:        ms.size = size;
                   1219:
                   1220:        ms.text = !!(flags & MAGIC_TEST_TEXT);
                   1221:
                   1222:        RB_FOREACH(ml, magic_tree, &m->tree) {
                   1223:                ms.offset = 0;
                   1224:                if (ml->text == ms.text && magic_test_line(ml, &ms))
                   1225:                        break;
                   1226:        }
                   1227:
                   1228:        if (*ms.out != '\0') {
                   1229:                if (flags & MAGIC_TEST_MIME) {
                   1230:                        if (ms.mimetype)
                   1231:                                return (xstrdup(ms.mimetype));
                   1232:                        return (NULL);
                   1233:                }
                   1234:                return (xstrdup(ms.out));
                   1235:        }
                   1236:        return (NULL);
                   1237: }