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

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