[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

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: }