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

Annotation of src/usr.bin/file/softmagic.c, Revision 1.7

1.7     ! millert     1: /*     $OpenBSD: softmagic.c,v 1.6 2002/02/16 21:27:46 millert Exp $   */
1.3       millert     2:
1.1       deraadt     3: /*
                      4:  * softmagic - interpret variable magic from /etc/magic
                      5:  *
                      6:  * Copyright (c) Ian F. Darwin, 1987.
                      7:  * Written by Ian F. Darwin.
                      8:  *
                      9:  * This software is not subject to any license of the American Telephone
                     10:  * and Telegraph Company or of the Regents of the University of California.
                     11:  *
                     12:  * Permission is granted to anyone to use this software for any purpose on
                     13:  * any computer system, and to alter it and redistribute it freely, subject
                     14:  * to the following restrictions:
                     15:  *
                     16:  * 1. The author is not responsible for the consequences of use of this
                     17:  *    software, no matter how awful, even if they arise from flaws in it.
                     18:  *
                     19:  * 2. The origin of this software must not be misrepresented, either by
                     20:  *    explicit claim or by omission.  Since few users ever read sources,
                     21:  *    credits must appear in the documentation.
                     22:  *
                     23:  * 3. Altered versions must be plainly marked as such, and must not be
                     24:  *    misrepresented as being the original software.  Since few users
                     25:  *    ever read sources, credits must appear in the documentation.
                     26:  *
                     27:  * 4. This notice may not be removed or altered.
                     28:  */
                     29:
1.4       mickey     30: #include <sys/types.h>
1.1       deraadt    31: #include <stdio.h>
                     32: #include <string.h>
1.3       millert    33: #include <stdlib.h>
1.1       deraadt    34: #include <time.h>
1.4       mickey     35: #include <err.h>
1.1       deraadt    36:
                     37: #include "file.h"
                     38:
                     39: #ifndef        lint
1.7     ! millert    40: static char *moduleid = "$OpenBSD: softmagic.c,v 1.6 2002/02/16 21:27:46 millert Exp $";
1.1       deraadt    41: #endif /* lint */
                     42:
1.6       millert    43: static int match(unsigned char *, int);
1.7     ! millert    44: static int mget(union VALUETYPE *, unsigned char *, struct magic *, int);
1.6       millert    45: static int mcheck(union VALUETYPE *, struct magic *);
                     46: static int32 mprint(union VALUETYPE *, struct magic *);
                     47: static void mdebug(int32, char *, int);
                     48: static int mconvert(union VALUETYPE *, struct magic *);
1.1       deraadt    49:
                     50: /*
                     51:  * softmagic - lookup one file in database
                     52:  * (already read from /etc/magic by apprentice.c).
                     53:  * Passed the name and FILE * of one file to be typed.
                     54:  */
                     55: /*ARGSUSED1*/          /* nbytes passed for regularity, maybe need later */
                     56: int
                     57: softmagic(buf, nbytes)
                     58: unsigned char *buf;
                     59: int nbytes;
                     60: {
                     61:        if (match(buf, nbytes))
                     62:                return 1;
                     63:
                     64:        return 0;
                     65: }
                     66:
                     67: /*
                     68:  * Go through the whole list, stopping if you find a match.  Process all
                     69:  * the continuations of that match before returning.
                     70:  *
                     71:  * We support multi-level continuations:
                     72:  *
                     73:  *     At any time when processing a successful top-level match, there is a
                     74:  *     current continuation level; it represents the level of the last
                     75:  *     successfully matched continuation.
                     76:  *
                     77:  *     Continuations above that level are skipped as, if we see one, it
                     78:  *     means that the continuation that controls them - i.e, the
                     79:  *     lower-level continuation preceding them - failed to match.
                     80:  *
                     81:  *     Continuations below that level are processed as, if we see one,
                     82:  *     it means we've finished processing or skipping higher-level
                     83:  *     continuations under the control of a successful or unsuccessful
                     84:  *     lower-level continuation, and are now seeing the next lower-level
                     85:  *     continuation and should process it.  The current continuation
                     86:  *     level reverts to the level of the one we're seeing.
                     87:  *
                     88:  *     Continuations at the current level are processed as, if we see
                     89:  *     one, there's no lower-level continuation that may have failed.
                     90:  *
                     91:  *     If a continuation matches, we bump the current continuation level
                     92:  *     so that higher-level continuations are processed.
                     93:  */
                     94: static int
                     95: match(s, nbytes)
                     96: unsigned char  *s;
                     97: int nbytes;
                     98: {
                     99:        int magindex = 0;
                    100:        int cont_level = 0;
                    101:        int need_separator = 0;
                    102:        union VALUETYPE p;
1.3       millert   103:        static int32 *tmpoff = NULL;
                    104:        static size_t tmplen = 0;
                    105:        int32 oldoff = 0;
                    106:
                    107:        if (tmpoff == NULL)
                    108:                if ((tmpoff = (int32 *) malloc(tmplen = 20)) == NULL)
1.4       mickey    109:                        err(1, "malloc");
1.1       deraadt   110:
                    111:        for (magindex = 0; magindex < nmagic; magindex++) {
                    112:                /* if main entry matches, print it... */
                    113:                if (!mget(&p, s, &magic[magindex], nbytes) ||
                    114:                    !mcheck(&p, &magic[magindex])) {
                    115:                            /*
                    116:                             * main entry didn't match,
                    117:                             * flush its continuations
                    118:                             */
                    119:                            while (magindex < nmagic &&
                    120:                                   magic[magindex + 1].cont_level != 0)
                    121:                                   magindex++;
                    122:                            continue;
                    123:                }
                    124:
1.3       millert   125:                tmpoff[cont_level] = mprint(&p, &magic[magindex]);
1.1       deraadt   126:                /*
                    127:                 * If we printed something, we'll need to print
                    128:                 * a blank before we print something else.
                    129:                 */
                    130:                if (magic[magindex].desc[0])
                    131:                        need_separator = 1;
                    132:                /* and any continuations that match */
1.3       millert   133:                if (++cont_level >= tmplen)
                    134:                        if ((tmpoff = (int32 *) realloc(tmpoff,
                    135:                                                       tmplen += 20)) == NULL)
1.4       mickey    136:                                err(1, "malloc");
1.1       deraadt   137:                while (magic[magindex+1].cont_level != 0 &&
                    138:                       ++magindex < nmagic) {
                    139:                        if (cont_level >= magic[magindex].cont_level) {
                    140:                                if (cont_level > magic[magindex].cont_level) {
                    141:                                        /*
                    142:                                         * We're at the end of the level
                    143:                                         * "cont_level" continuations.
                    144:                                         */
                    145:                                        cont_level = magic[magindex].cont_level;
                    146:                                }
1.3       millert   147:                                if (magic[magindex].flag & ADD) {
                    148:                                        oldoff=magic[magindex].offset;
                    149:                                        magic[magindex].offset += tmpoff[cont_level-1];
                    150:                                }
1.1       deraadt   151:                                if (mget(&p, s, &magic[magindex], nbytes) &&
                    152:                                    mcheck(&p, &magic[magindex])) {
                    153:                                        /*
                    154:                                         * This continuation matched.
                    155:                                         * Print its message, with
                    156:                                         * a blank before it if
                    157:                                         * the previous item printed
                    158:                                         * and this item isn't empty.
                    159:                                         */
                    160:                                        /* space if previous printed */
                    161:                                        if (need_separator
                    162:                                           && (magic[magindex].nospflag == 0)
                    163:                                           && (magic[magindex].desc[0] != '\0')
                    164:                                           ) {
                    165:                                                (void) putchar(' ');
                    166:                                                need_separator = 0;
                    167:                                        }
1.3       millert   168:                                        tmpoff[cont_level] = mprint(&p, &magic[magindex]);
1.1       deraadt   169:                                        if (magic[magindex].desc[0])
                    170:                                                need_separator = 1;
                    171:
                    172:                                        /*
                    173:                                         * If we see any continuations
                    174:                                         * at a higher level,
                    175:                                         * process them.
                    176:                                         */
1.3       millert   177:                                        if (++cont_level >= tmplen)
                    178:                                                if ((tmpoff =
                    179:                                                    (int32 *) realloc(tmpoff,
                    180:                                                    tmplen += 20)) == NULL)
1.4       mickey    181:                                                        err(1, "malloc");
1.3       millert   182:                                }
                    183:                                if (magic[magindex].flag & ADD) {
                    184:                                         magic[magindex].offset = oldoff;
1.1       deraadt   185:                                }
                    186:                        }
                    187:                }
                    188:                return 1;               /* all through */
                    189:        }
                    190:        return 0;                       /* no match at all */
                    191: }
                    192:
1.3       millert   193: static int32
1.1       deraadt   194: mprint(p, m)
                    195: union VALUETYPE *p;
                    196: struct magic *m;
                    197: {
                    198:        char *pp, *rt;
1.3       millert   199:        uint32 v;
                    200:        int32 t=0 ;
1.1       deraadt   201:
                    202:
                    203:        switch (m->type) {
                    204:        case BYTE:
                    205:                v = p->b;
                    206:                v = signextend(m, v) & m->mask;
                    207:                (void) printf(m->desc, (unsigned char) v);
1.3       millert   208:                t = m->offset + sizeof(char);
1.1       deraadt   209:                break;
                    210:
                    211:        case SHORT:
                    212:        case BESHORT:
                    213:        case LESHORT:
                    214:                v = p->h;
                    215:                v = signextend(m, v) & m->mask;
                    216:                (void) printf(m->desc, (unsigned short) v);
1.3       millert   217:                t = m->offset + sizeof(short);
1.1       deraadt   218:                break;
                    219:
                    220:        case LONG:
                    221:        case BELONG:
                    222:        case LELONG:
                    223:                v = p->l;
                    224:                v = signextend(m, v) & m->mask;
1.3       millert   225:                (void) printf(m->desc, (uint32) v);
                    226:                t = m->offset + sizeof(int32);
1.1       deraadt   227:                break;
                    228:
                    229:        case STRING:
                    230:                if (m->reln == '=') {
                    231:                        (void) printf(m->desc, m->value.s);
1.3       millert   232:                        t = m->offset + strlen(m->value.s);
1.1       deraadt   233:                }
                    234:                else {
1.3       millert   235:                        if (*m->value.s == '\0') {
                    236:                                char *cp = strchr(p->s,'\n');
                    237:                                if (cp)
                    238:                                        *cp = '\0';
                    239:                        }
1.1       deraadt   240:                        (void) printf(m->desc, p->s);
1.3       millert   241:                        t = m->offset + strlen(p->s);
1.1       deraadt   242:                }
1.3       millert   243:                break;
1.1       deraadt   244:
                    245:        case DATE:
                    246:        case BEDATE:
                    247:        case LEDATE:
                    248:                pp = ctime((time_t*) &p->l);
                    249:                if ((rt = strchr(pp, '\n')) != NULL)
                    250:                        *rt = '\0';
                    251:                (void) printf(m->desc, pp);
1.3       millert   252:                t = m->offset + sizeof(time_t);
                    253:                break;
                    254:
1.1       deraadt   255:        default:
1.4       mickey    256:                errx(1, "invalid m->type (%d) in mprint().", m->type);
1.1       deraadt   257:                /*NOTREACHED*/
                    258:        }
1.3       millert   259:        return(t);
1.1       deraadt   260: }
                    261:
                    262: /*
                    263:  * Convert the byte order of the data we are looking at
                    264:  */
                    265: static int
                    266: mconvert(p, m)
                    267: union VALUETYPE *p;
                    268: struct magic *m;
                    269: {
                    270:        switch (m->type) {
                    271:        case BYTE:
                    272:        case SHORT:
                    273:        case LONG:
                    274:        case DATE:
                    275:                return 1;
                    276:        case STRING:
1.3       millert   277:                {
                    278:                        char *ptr;
                    279:
                    280:                        /* Null terminate and eat the return */
                    281:                        p->s[sizeof(p->s) - 1] = '\0';
                    282:                        if ((ptr = strchr(p->s, '\n')) != NULL)
                    283:                                *ptr = '\0';
                    284:                        return 1;
                    285:                }
1.1       deraadt   286:        case BESHORT:
                    287:                p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
                    288:                return 1;
                    289:        case BELONG:
                    290:        case BEDATE:
1.3       millert   291:                p->l = (int32)
1.1       deraadt   292:                    ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
                    293:                return 1;
                    294:        case LESHORT:
                    295:                p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
                    296:                return 1;
                    297:        case LELONG:
                    298:        case LEDATE:
1.3       millert   299:                p->l = (int32)
1.1       deraadt   300:                    ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
                    301:                return 1;
                    302:        default:
1.4       mickey    303:                errx(1, "invalid type %d in mconvert().", m->type);
1.1       deraadt   304:                return 0;
                    305:        }
                    306: }
                    307:
                    308:
                    309: static void
                    310: mdebug(offset, str, len)
1.3       millert   311: int32 offset;
1.1       deraadt   312: char *str;
                    313: int len;
                    314: {
1.3       millert   315:        (void) fprintf(stderr, "mget @%d: ", offset);
1.1       deraadt   316:        showstr(stderr, (char *) str, len);
                    317:        (void) fputc('\n', stderr);
                    318:        (void) fputc('\n', stderr);
                    319: }
                    320:
                    321: static int
                    322: mget(p, s, m, nbytes)
                    323: union VALUETYPE* p;
                    324: unsigned char  *s;
                    325: struct magic *m;
                    326: int nbytes;
                    327: {
1.3       millert   328:        int32 offset = m->offset;
1.1       deraadt   329:
                    330:        if (offset + sizeof(union VALUETYPE) <= nbytes)
                    331:                memcpy(p, s + offset, sizeof(union VALUETYPE));
                    332:        else {
                    333:                /*
                    334:                 * the usefulness of padding with zeroes eludes me, it
                    335:                 * might even cause problems
                    336:                 */
1.3       millert   337:                int32 have = nbytes - offset;
1.1       deraadt   338:                memset(p, 0, sizeof(union VALUETYPE));
                    339:                if (have > 0)
                    340:                        memcpy(p, s + offset, have);
                    341:        }
                    342:
                    343:
                    344:        if (debug) {
                    345:                mdebug(offset, (char *) p, sizeof(union VALUETYPE));
                    346:                mdump(m);
                    347:        }
                    348:
                    349:        if (!mconvert(p, m))
                    350:                return 0;
                    351:
                    352:        if (m->flag & INDIR) {
                    353:
                    354:                switch (m->in.type) {
                    355:                case BYTE:
                    356:                        offset = p->b + m->in.offset;
                    357:                        break;
                    358:                case SHORT:
                    359:                        offset = p->h + m->in.offset;
                    360:                        break;
                    361:                case LONG:
                    362:                        offset = p->l + m->in.offset;
                    363:                        break;
                    364:                }
                    365:
                    366:                if (offset + sizeof(union VALUETYPE) > nbytes)
                    367:                        return 0;
                    368:
                    369:                memcpy(p, s + offset, sizeof(union VALUETYPE));
                    370:
                    371:                if (debug) {
                    372:                        mdebug(offset, (char *) p, sizeof(union VALUETYPE));
                    373:                        mdump(m);
                    374:                }
                    375:
                    376:                if (!mconvert(p, m))
                    377:                        return 0;
                    378:        }
                    379:        return 1;
                    380: }
                    381:
                    382: static int
                    383: mcheck(p, m)
                    384: union VALUETYPE* p;
                    385: struct magic *m;
                    386: {
1.5       mpech     387:        uint32 l = m->value.l;
                    388:        uint32 v;
1.1       deraadt   389:        int matched;
                    390:
                    391:        if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
                    392:                fprintf(stderr, "BOINK");
                    393:                return 1;
                    394:        }
                    395:
                    396:
                    397:        switch (m->type) {
                    398:        case BYTE:
                    399:                v = p->b;
                    400:                break;
                    401:
                    402:        case SHORT:
                    403:        case BESHORT:
                    404:        case LESHORT:
                    405:                v = p->h;
                    406:                break;
                    407:
                    408:        case LONG:
                    409:        case BELONG:
                    410:        case LELONG:
                    411:        case DATE:
                    412:        case BEDATE:
                    413:        case LEDATE:
                    414:                v = p->l;
                    415:                break;
                    416:
                    417:        case STRING:
                    418:                l = 0;
                    419:                /* What we want here is:
                    420:                 * v = strncmp(m->value.s, p->s, m->vallen);
                    421:                 * but ignoring any nulls.  bcmp doesn't give -/+/0
                    422:                 * and isn't universally available anyway.
                    423:                 */
                    424:                v = 0;
                    425:                {
1.5       mpech     426:                        unsigned char *a = (unsigned char*)m->value.s;
                    427:                        unsigned char *b = (unsigned char*)p->s;
                    428:                        int len = m->vallen;
1.1       deraadt   429:
                    430:                        while (--len >= 0)
1.3       millert   431:                                if ((v = *b++ - *a++) != '\0')
1.1       deraadt   432:                                        break;
                    433:                }
                    434:                break;
                    435:        default:
1.4       mickey    436:                errx(1, "invalid type %d in mcheck().", m->type);
1.1       deraadt   437:                return 0;/*NOTREACHED*/
                    438:        }
                    439:
                    440:        v = signextend(m, v) & m->mask;
                    441:
                    442:        switch (m->reln) {
                    443:        case 'x':
                    444:                if (debug)
1.3       millert   445:                        (void) fprintf(stderr, "%u == *any* = 1\n", v);
1.1       deraadt   446:                matched = 1;
                    447:                break;
                    448:
                    449:        case '!':
                    450:                matched = v != l;
                    451:                if (debug)
1.3       millert   452:                        (void) fprintf(stderr, "%u != %u = %d\n",
1.1       deraadt   453:                                       v, l, matched);
                    454:                break;
                    455:
                    456:        case '=':
                    457:                matched = v == l;
                    458:                if (debug)
1.3       millert   459:                        (void) fprintf(stderr, "%u == %u = %d\n",
1.1       deraadt   460:                                       v, l, matched);
                    461:                break;
                    462:
                    463:        case '>':
                    464:                if (m->flag & UNSIGNED) {
                    465:                        matched = v > l;
                    466:                        if (debug)
1.3       millert   467:                                (void) fprintf(stderr, "%u > %u = %d\n",
1.1       deraadt   468:                                               v, l, matched);
                    469:                }
                    470:                else {
1.3       millert   471:                        matched = (int32) v > (int32) l;
1.1       deraadt   472:                        if (debug)
1.3       millert   473:                                (void) fprintf(stderr, "%d > %d = %d\n",
1.1       deraadt   474:                                               v, l, matched);
                    475:                }
                    476:                break;
                    477:
                    478:        case '<':
                    479:                if (m->flag & UNSIGNED) {
                    480:                        matched = v < l;
                    481:                        if (debug)
1.3       millert   482:                                (void) fprintf(stderr, "%u < %u = %d\n",
1.1       deraadt   483:                                               v, l, matched);
                    484:                }
                    485:                else {
1.3       millert   486:                        matched = (int32) v < (int32) l;
1.1       deraadt   487:                        if (debug)
1.3       millert   488:                                (void) fprintf(stderr, "%d < %d = %d\n",
1.1       deraadt   489:                                               v, l, matched);
                    490:                }
                    491:                break;
                    492:
                    493:        case '&':
                    494:                matched = (v & l) == l;
                    495:                if (debug)
1.3       millert   496:                        (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
1.1       deraadt   497:                                       v, l, l, matched);
                    498:                break;
                    499:
                    500:        case '^':
                    501:                matched = (v & l) != l;
                    502:                if (debug)
1.3       millert   503:                        (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
1.1       deraadt   504:                                       v, l, l, matched);
                    505:                break;
                    506:
                    507:        default:
                    508:                matched = 0;
1.4       mickey    509:                errx(1, "mcheck: can't happen: invalid relation %d.", m->reln);
1.1       deraadt   510:                break;/*NOTREACHED*/
                    511:        }
                    512:
                    513:        return matched;
                    514: }