Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

file/softmagic.c

Go to the documentation of this file.
00001 /*
00002  * softmagic - interpret variable magic from MAGIC
00003  *
00004  * Copyright (c) Ian F. Darwin, 1987.
00005  * Written by Ian F. Darwin.
00006  *
00007  * This software is not subject to any license of the American Telephone
00008  * and Telegraph Company or of the Regents of the University of California.
00009  *
00010  * Permission is granted to anyone to use this software for any purpose on
00011  * any computer system, and to alter it and redistribute it freely, subject
00012  * to the following restrictions:
00013  *
00014  * 1. The author is not responsible for the consequences of use of this
00015  *    software, no matter how awful, even if they arise from flaws in it.
00016  *
00017  * 2. The origin of this software must not be misrepresented, either by
00018  *    explicit claim or by omission.  Since few users ever read sources,
00019  *    credits must appear in the documentation.
00020  *
00021  * 3. Altered versions must be plainly marked as such, and must not be
00022  *    misrepresented as being the original software.  Since few users
00023  *    ever read sources, credits must appear in the documentation.
00024  *
00025  * 4. This notice may not be removed or altered.
00026  */
00027 
00028 #include "system.h"
00029 #include "file.h"
00030 #include "debug.h"
00031 
00032 FILE_RCSID("@(#)Id: softmagic.c,v 1.51 2002/07/03 18:26:38 christos Exp ")
00033 
00034 /*@access fmagic @*/
00035 
00036 /*@-bounds@*/
00037 static int32_t
00038 fmagicSPrint(const fmagic fm, struct magic *m)
00039         /*@globals fileSystem @*/
00040         /*@modifies fm, fileSystem @*/
00041 {
00042     union VALUETYPE * p = &fm->val;
00043     uint32_t v;
00044     int32_t t = 0;
00045 
00046     switch (m->type) {
00047     case BYTE:
00048         v = signextend(m, p->b);
00049         fmagicPrintf(fm, m->desc, (unsigned char) v);
00050 /*@-sizeoftype@*/
00051         t = m->offset + sizeof(char);
00052 /*@=sizeoftype@*/
00053         break;
00054 
00055     case SHORT:
00056     case BESHORT:
00057     case LESHORT:
00058         v = signextend(m, p->h);
00059         fmagicPrintf(fm, m->desc, (unsigned short) v);
00060 /*@-sizeoftype@*/
00061         t = m->offset + sizeof(short);
00062 /*@=sizeoftype@*/
00063         break;
00064 
00065     case LONG:
00066     case BELONG:
00067     case LELONG:
00068         v = signextend(m, p->l);
00069         fmagicPrintf(fm, m->desc, (uint32_t) v);
00070 /*@-sizeoftype@*/
00071         t = m->offset + sizeof(int32_t);
00072 /*@=sizeoftype@*/
00073         break;
00074 
00075     case STRING:
00076     case PSTRING:
00077         if (m->reln == '=') {
00078             fmagicPrintf(fm, m->desc, m->value.s);
00079             t = m->offset + strlen(m->value.s);
00080         } else {
00081             if (*m->value.s == '\0') {
00082                 char *cp = strchr(p->s,'\n');
00083                 if (cp != NULL)
00084                     *cp = '\0';
00085             }
00086             fmagicPrintf(fm, m->desc, p->s);
00087             t = m->offset + strlen(p->s);
00088         }
00089         break;
00090 
00091     case DATE:
00092     case BEDATE:
00093     case LEDATE:
00094         fmagicPrintf(fm, m->desc, fmttime(p->l, 1));
00095 /*@-sizeoftype@*/
00096         t = m->offset + sizeof(time_t);
00097 /*@=sizeoftype@*/
00098         break;
00099 
00100     case LDATE:
00101     case BELDATE:
00102     case LELDATE:
00103         fmagicPrintf(fm, m->desc, fmttime(p->l, 0));
00104 /*@-sizeoftype@*/
00105         t = m->offset + sizeof(time_t);
00106 /*@=sizeoftype@*/
00107         break;
00108 
00109     case REGEX:
00110         fmagicPrintf(fm, m->desc, p->s);
00111         t = m->offset + strlen(p->s);
00112         break;
00113 
00114     default:
00115         error(EXIT_FAILURE, 0, "invalid m->type (%d) in fmagicSPrint().\n", m->type);
00116         /*@notreached@*/ break;
00117     }
00118     return(t);
00119 }
00120 /*@=bounds@*/
00121 
00122 /*
00123  * Convert the byte order of the data we are looking at
00124  * While we're here, let's apply the mask operation
00125  * (unless you have a better idea)
00126  */
00127 /*@-bounds@*/
00128 static int
00129 fmagicSConvert(fmagic fm, struct magic *m)
00130         /*@globals fileSystem @*/
00131         /*@modifies fm, fileSystem @*/
00132 {
00133     union VALUETYPE * p = &fm->val;
00134 
00135     switch (m->type) {
00136     case BYTE:
00137         if (m->mask)
00138             switch (m->mask_op&0x7F) {
00139             case OPAND:
00140                 p->b &= m->mask;
00141                 /*@innerbreak@*/ break;
00142             case OPOR:
00143                 p->b |= m->mask;
00144                 /*@innerbreak@*/ break;
00145             case OPXOR:
00146                 p->b ^= m->mask;
00147                 /*@innerbreak@*/ break;
00148             case OPADD:
00149                 p->b += m->mask;
00150                 /*@innerbreak@*/ break;
00151             case OPMINUS:
00152                 p->b -= m->mask;
00153                 /*@innerbreak@*/ break;
00154             case OPMULTIPLY:
00155                 p->b *= m->mask;
00156                 /*@innerbreak@*/ break;
00157             case OPDIVIDE:
00158                 p->b /= m->mask;
00159                 /*@innerbreak@*/ break;
00160             case OPMODULO:
00161                 p->b %= m->mask;
00162                 /*@innerbreak@*/ break;
00163             }
00164         if (m->mask_op & OPINVERSE)
00165             p->b = ~p->b;
00166         return 1;
00167     case SHORT:
00168         if (m->mask)
00169             switch (m->mask_op&0x7F) {
00170             case OPAND:
00171                 p->h &= m->mask;
00172                 /*@innerbreak@*/ break;
00173             case OPOR:
00174                 p->h |= m->mask;
00175                 /*@innerbreak@*/ break;
00176             case OPXOR:
00177                 p->h ^= m->mask;
00178                 /*@innerbreak@*/ break;
00179             case OPADD:
00180                 p->h += m->mask;
00181                 /*@innerbreak@*/ break;
00182             case OPMINUS:
00183                 p->h -= m->mask;
00184                 /*@innerbreak@*/ break;
00185             case OPMULTIPLY:
00186                 p->h *= m->mask;
00187                 /*@innerbreak@*/ break;
00188             case OPDIVIDE:
00189                 p->h /= m->mask;
00190                 /*@innerbreak@*/ break;
00191             case OPMODULO:
00192                 p->h %= m->mask;
00193                 /*@innerbreak@*/ break;
00194             }
00195         if (m->mask_op & OPINVERSE)
00196             p->h = ~p->h;
00197         return 1;
00198     case LONG:
00199     case DATE:
00200     case LDATE:
00201         if (m->mask)
00202             switch (m->mask_op&0x7F) {
00203             case OPAND:
00204                 p->l &= m->mask;
00205                 /*@innerbreak@*/ break;
00206             case OPOR:
00207                 p->l |= m->mask;
00208                 /*@innerbreak@*/ break;
00209             case OPXOR:
00210                 p->l ^= m->mask;
00211                 /*@innerbreak@*/ break;
00212             case OPADD:
00213                 p->l += m->mask;
00214                 /*@innerbreak@*/ break;
00215             case OPMINUS:
00216                 p->l -= m->mask;
00217                 /*@innerbreak@*/ break;
00218             case OPMULTIPLY:
00219                 p->l *= m->mask;
00220                 /*@innerbreak@*/ break;
00221             case OPDIVIDE:
00222                 p->l /= m->mask;
00223                 /*@innerbreak@*/ break;
00224             case OPMODULO:
00225                 p->l %= m->mask;
00226                 /*@innerbreak@*/ break;
00227             }
00228         if (m->mask_op & OPINVERSE)
00229             p->l = ~p->l;
00230         return 1;
00231     case STRING:
00232         {
00233             int n;
00234 
00235             /* Null terminate and eat *trailing* return */
00236             p->s[sizeof(p->s) - 1] = '\0';
00237             n = strlen(p->s) - 1;
00238             if (p->s[n] == '\n')
00239                 p->s[n] = '\0';
00240             return 1;
00241         }
00242     case PSTRING:
00243         {
00244             char *ptr1 = p->s, *ptr2 = ptr1 + 1;
00245             int n = *p->s;
00246             if (n >= sizeof(p->s))
00247                 n = sizeof(p->s) - 1;
00248             while (n--)
00249                 *ptr1++ = *ptr2++;
00250             *ptr1 = '\0';
00251             n = strlen(p->s) - 1;
00252             if (p->s[n] == '\n')
00253                 p->s[n] = '\0';
00254             return 1;
00255         }
00256     case BESHORT:
00257         p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
00258         if (m->mask)
00259             switch (m->mask_op&0x7F) {
00260             case OPAND:
00261                 p->h &= m->mask;
00262                 /*@innerbreak@*/ break;
00263             case OPOR:
00264                 p->h |= m->mask;
00265                 /*@innerbreak@*/ break;
00266             case OPXOR:
00267                 p->h ^= m->mask;
00268                 /*@innerbreak@*/ break;
00269             case OPADD:
00270                 p->h += m->mask;
00271                 /*@innerbreak@*/ break;
00272             case OPMINUS:
00273                 p->h -= m->mask;
00274                 /*@innerbreak@*/ break;
00275             case OPMULTIPLY:
00276                 p->h *= m->mask;
00277                 /*@innerbreak@*/ break;
00278             case OPDIVIDE:
00279                 p->h /= m->mask;
00280                 /*@innerbreak@*/ break;
00281             case OPMODULO:
00282                 p->h %= m->mask;
00283                 /*@innerbreak@*/ break;
00284             }
00285         if (m->mask_op & OPINVERSE)
00286             p->h = ~p->h;
00287         return 1;
00288     case BELONG:
00289     case BEDATE:
00290     case BELDATE:
00291         p->l = (int32_t)
00292             ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
00293         if (m->mask)
00294             switch (m->mask_op&0x7F) {
00295             case OPAND:
00296                 p->l &= m->mask;
00297                 /*@innerbreak@*/ break;
00298             case OPOR:
00299                 p->l |= m->mask;
00300                 /*@innerbreak@*/ break;
00301             case OPXOR:
00302                 p->l ^= m->mask;
00303                 /*@innerbreak@*/ break;
00304             case OPADD:
00305                 p->l += m->mask;
00306                 /*@innerbreak@*/ break;
00307             case OPMINUS:
00308                 p->l -= m->mask;
00309                 /*@innerbreak@*/ break;
00310             case OPMULTIPLY:
00311                 p->l *= m->mask;
00312                 /*@innerbreak@*/ break;
00313             case OPDIVIDE:
00314                 p->l /= m->mask;
00315                 /*@innerbreak@*/ break;
00316             case OPMODULO:
00317                 p->l %= m->mask;
00318                 /*@innerbreak@*/ break;
00319             }
00320         if (m->mask_op & OPINVERSE)
00321             p->l = ~p->l;
00322         return 1;
00323     case LESHORT:
00324         p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
00325         if (m->mask)
00326             switch (m->mask_op&0x7F) {
00327             case OPAND:
00328                 p->h &= m->mask;
00329                 /*@innerbreak@*/ break;
00330             case OPOR:
00331                 p->h |= m->mask;
00332                 /*@innerbreak@*/ break;
00333             case OPXOR:
00334                 p->h ^= m->mask;
00335                 /*@innerbreak@*/ break;
00336             case OPADD:
00337                 p->h += m->mask;
00338                 /*@innerbreak@*/ break;
00339             case OPMINUS:
00340                 p->h -= m->mask;
00341                 /*@innerbreak@*/ break;
00342             case OPMULTIPLY:
00343                 p->h *= m->mask;
00344                 /*@innerbreak@*/ break;
00345             case OPDIVIDE:
00346                 p->h /= m->mask;
00347                 /*@innerbreak@*/ break;
00348             case OPMODULO:
00349                 p->h %= m->mask;
00350                 /*@innerbreak@*/ break;
00351             }
00352         if (m->mask_op & OPINVERSE)
00353             p->h = ~p->h;
00354         return 1;
00355     case LELONG:
00356     case LEDATE:
00357     case LELDATE:
00358         p->l = (int32_t)
00359             ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
00360         if (m->mask)
00361             switch (m->mask_op&0x7F) {
00362             case OPAND:
00363                 p->l &= m->mask;
00364                 /*@innerbreak@*/ break;
00365             case OPOR:
00366                 p->l |= m->mask;
00367                 /*@innerbreak@*/ break;
00368             case OPXOR:
00369                 p->l ^= m->mask;
00370                 /*@innerbreak@*/ break;
00371             case OPADD:
00372                 p->l += m->mask;
00373                 /*@innerbreak@*/ break;
00374             case OPMINUS:
00375                 p->l -= m->mask;
00376                 /*@innerbreak@*/ break;
00377             case OPMULTIPLY:
00378                 p->l *= m->mask;
00379                 /*@innerbreak@*/ break;
00380             case OPDIVIDE:
00381                 p->l /= m->mask;
00382                 /*@innerbreak@*/ break;
00383             case OPMODULO:
00384                 p->l %= m->mask;
00385                 /*@innerbreak@*/ break;
00386             }
00387         if (m->mask_op & OPINVERSE)
00388             p->l = ~p->l;
00389         return 1;
00390     case REGEX:
00391         return 1;
00392     default:
00393         error(EXIT_FAILURE, 0, "invalid type %d in fmagicSConvert().\n", m->type);
00394         /*@notreached@*/
00395         return 0;
00396     }
00397 }
00398 /*@=bounds@*/
00399 
00400 
00401 static void
00402 fmagicSDebug(int32_t offset, char *str, int len)
00403         /*@globals fileSystem @*/
00404         /*@modifies fileSystem @*/
00405 {
00406     (void) fprintf(stderr, "fmagicSGet @%d: ", offset);
00407     showstr(stderr, (char *) str, len);
00408     (void) fputc('\n', stderr);
00409     (void) fputc('\n', stderr);
00410 }
00411 
00412 /*@-bounds@*/
00413 static int
00414 fmagicSGet(fmagic fm, struct magic *m)
00415         /*@globals fileSystem @*/
00416         /*@modifies fm, fileSystem @*/
00417 {
00418     unsigned char * buf = fm->buf;
00419     int nb = fm->nb;
00420     union VALUETYPE * p = &fm->val;
00421     int32_t offset = m->offset;
00422 
00423 /*@-branchstate@*/
00424     if (m->type == REGEX) {
00425         /*
00426         * offset is interpreted as last line to search,
00427         * (starting at 1), not as bytes-from start-of-file
00428         */
00429         char *last = NULL;
00430 /*@-temptrans@*/
00431         p->buf = buf;
00432 /*@=temptrans@*/
00433         for (; offset && (buf = strchr(buf, '\n')) != NULL; offset--, buf++)
00434             last = buf;
00435         if (last != NULL)
00436             *last = '\0';
00437     } else if (offset + sizeof(*p) <= nb)
00438         memcpy(p, buf + offset, sizeof(*p));
00439     else {
00440         /*
00441          * the usefulness of padding with zeroes eludes me, it
00442          * might even cause problems
00443          */
00444         int32_t have = nb - offset;
00445         memset(p, 0, sizeof(*p));
00446         if (have > 0)
00447             memcpy(p, buf + offset, have);
00448     }
00449 /*@=branchstate@*/
00450 
00451     if (fm->flags & FMAGIC_FLAGS_DEBUG) {
00452         fmagicSDebug(offset, (char *) p, sizeof(*p));
00453         mdump(m);
00454     }
00455 
00456     if (m->flag & INDIR) {
00457         switch (m->in_type) {
00458         case BYTE:
00459             if (m->in_offset)
00460                 switch (m->in_op&0x7F) {
00461                 case OPAND:
00462                     offset = p->b & m->in_offset;
00463                     /*@innerbreak@*/ break;
00464                 case OPOR:
00465                     offset = p->b | m->in_offset;
00466                     /*@innerbreak@*/ break;
00467                 case OPXOR:
00468                     offset = p->b ^ m->in_offset;
00469                     /*@innerbreak@*/ break;
00470                 case OPADD:
00471                     offset = p->b + m->in_offset;
00472                     /*@innerbreak@*/ break;
00473                 case OPMINUS:
00474                     offset = p->b - m->in_offset;
00475                     /*@innerbreak@*/ break;
00476                 case OPMULTIPLY:
00477                     offset = p->b * m->in_offset;
00478                     /*@innerbreak@*/ break;
00479                 case OPDIVIDE:
00480                     offset = p->b / m->in_offset;
00481                     /*@innerbreak@*/ break;
00482                 case OPMODULO:
00483                     offset = p->b % m->in_offset;
00484                     /*@innerbreak@*/ break;
00485                 }
00486             if (m->in_op & OPINVERSE)
00487                 offset = ~offset;
00488             break;
00489         case BESHORT:
00490             if (m->in_offset)
00491                 switch (m->in_op&0x7F) {
00492                 case OPAND:
00493                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) &
00494                                  m->in_offset;
00495                     /*@innerbreak@*/ break;
00496                 case OPOR:
00497                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) |
00498                                  m->in_offset;
00499                     /*@innerbreak@*/ break;
00500                 case OPXOR:
00501                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) ^
00502                                  m->in_offset;
00503                     /*@innerbreak@*/ break;
00504                 case OPADD:
00505                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) +
00506                                  m->in_offset;
00507                     /*@innerbreak@*/ break;
00508                 case OPMINUS:
00509                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) -
00510                                  m->in_offset;
00511                     /*@innerbreak@*/ break;
00512                 case OPMULTIPLY:
00513                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) *
00514                                  m->in_offset;
00515                     /*@innerbreak@*/ break;
00516                 case OPDIVIDE:
00517                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) /
00518                                  m->in_offset;
00519                     /*@innerbreak@*/ break;
00520                 case OPMODULO:
00521                     offset = (short)((p->hs[0]<<8) | (p->hs[1])) %
00522                                  m->in_offset;
00523                     /*@innerbreak@*/ break;
00524                 }
00525             if (m->in_op & OPINVERSE)
00526                 offset = ~offset;
00527             break;
00528         case LESHORT:
00529             if (m->in_offset)
00530                 switch (m->in_op&0x7F) {
00531                 case OPAND:
00532                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) &
00533                                  m->in_offset;
00534                     /*@innerbreak@*/ break;
00535                 case OPOR:
00536                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) |
00537                                  m->in_offset;
00538                     /*@innerbreak@*/ break;
00539                 case OPXOR:
00540                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) ^
00541                                  m->in_offset;
00542                     /*@innerbreak@*/ break;
00543                 case OPADD:
00544                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) +
00545                                  m->in_offset;
00546                     /*@innerbreak@*/ break;
00547                 case OPMINUS:
00548                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) -
00549                                  m->in_offset;
00550                     /*@innerbreak@*/ break;
00551                 case OPMULTIPLY:
00552                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) *
00553                                  m->in_offset;
00554                     /*@innerbreak@*/ break;
00555                 case OPDIVIDE:
00556                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) /
00557                                  m->in_offset;
00558                     /*@innerbreak@*/ break;
00559                 case OPMODULO:
00560                     offset = (short)((p->hs[1]<<8) | (p->hs[0])) %
00561                                  m->in_offset;
00562                     /*@innerbreak@*/ break;
00563                 }
00564             if (m->in_op & OPINVERSE)
00565                 offset = ~offset;
00566             break;
00567         case SHORT:
00568             if (m->in_offset)
00569                 switch (m->in_op&0x7F) {
00570                 case OPAND:
00571                     offset = p->h & m->in_offset;
00572                     /*@innerbreak@*/ break;
00573                 case OPOR:
00574                     offset = p->h | m->in_offset;
00575                     /*@innerbreak@*/ break;
00576                 case OPXOR:
00577                     offset = p->h ^ m->in_offset;
00578                     /*@innerbreak@*/ break;
00579                 case OPADD:
00580                     offset = p->h + m->in_offset;
00581                     /*@innerbreak@*/ break;
00582                 case OPMINUS:
00583                     offset = p->h - m->in_offset;
00584                     /*@innerbreak@*/ break;
00585                 case OPMULTIPLY:
00586                     offset = p->h * m->in_offset;
00587                     /*@innerbreak@*/ break;
00588                 case OPDIVIDE:
00589                     offset = p->h / m->in_offset;
00590                     /*@innerbreak@*/ break;
00591                 case OPMODULO:
00592                     offset = p->h % m->in_offset;
00593                     /*@innerbreak@*/ break;
00594                 }
00595             if (m->in_op & OPINVERSE)
00596                 offset = ~offset;
00597             break;
00598         case BELONG:
00599             if (m->in_offset)
00600                 switch (m->in_op&0x7F) {
00601                 case OPAND:
00602                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00603                                         (p->hl[2]<< 8) | (p->hl[3])) &
00604                                  m->in_offset;
00605                     /*@innerbreak@*/ break;
00606                 case OPOR:
00607                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00608                                         (p->hl[2]<< 8) | (p->hl[3])) |
00609                                  m->in_offset;
00610                     /*@innerbreak@*/ break;
00611                 case OPXOR:
00612                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00613                                         (p->hl[2]<< 8) | (p->hl[3])) ^
00614                                  m->in_offset;
00615                     /*@innerbreak@*/ break;
00616                 case OPADD:
00617                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00618                                         (p->hl[2]<< 8) | (p->hl[3])) +
00619                                  m->in_offset;
00620                     /*@innerbreak@*/ break;
00621                 case OPMINUS:
00622                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00623                                         (p->hl[2]<< 8) | (p->hl[3])) -
00624                                  m->in_offset;
00625                     /*@innerbreak@*/ break;
00626                 case OPMULTIPLY:
00627                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00628                                         (p->hl[2]<< 8) | (p->hl[3])) *
00629                                  m->in_offset;
00630                     /*@innerbreak@*/ break;
00631                 case OPDIVIDE:
00632                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00633                                         (p->hl[2]<< 8) | (p->hl[3])) /
00634                                  m->in_offset;
00635                     /*@innerbreak@*/ break;
00636                 case OPMODULO:
00637                     offset = (int32_t)( (p->hl[0]<<24) | (p->hl[1]<<16) |
00638                                         (p->hl[2]<< 8) | (p->hl[3])) %
00639                                  m->in_offset;
00640                     /*@innerbreak@*/ break;
00641                 }
00642             if (m->in_op & OPINVERSE)
00643                 offset = ~offset;
00644             break;
00645         case LELONG:
00646             if (m->in_offset)
00647                 switch (m->in_op&0x7F) {
00648                 case OPAND:
00649                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00650                                         (p->hl[1]<< 8) | (p->hl[0])) &
00651                                  m->in_offset;
00652                     /*@innerbreak@*/ break;
00653                 case OPOR:
00654                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00655                                         (p->hl[1]<< 8) | (p->hl[0])) |
00656                                  m->in_offset;
00657                     /*@innerbreak@*/ break;
00658                 case OPXOR:
00659                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00660                                         (p->hl[1]<< 8) | (p->hl[0])) ^
00661                                  m->in_offset;
00662                     /*@innerbreak@*/ break;
00663                 case OPADD:
00664                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00665                                         (p->hl[1]<< 8) | (p->hl[0])) +
00666                                  m->in_offset;
00667                     /*@innerbreak@*/ break;
00668                 case OPMINUS:
00669                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00670                                         (p->hl[1]<< 8) | (p->hl[0])) -
00671                                  m->in_offset;
00672                     /*@innerbreak@*/ break;
00673                 case OPMULTIPLY:
00674                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00675                                         (p->hl[1]<< 8) | (p->hl[0])) *
00676                                  m->in_offset;
00677                     /*@innerbreak@*/ break;
00678                 case OPDIVIDE:
00679                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00680                                          (p->hl[1]<< 8) | (p->hl[0])) /
00681                                  m->in_offset;
00682                     /*@innerbreak@*/ break;
00683                 case OPMODULO:
00684                     offset = (int32_t)( (p->hl[3]<<24) | (p->hl[2]<<16) |
00685                                         (p->hl[1]<< 8) | (p->hl[0])) %
00686                                  m->in_offset;
00687                     /*@innerbreak@*/ break;
00688                 }
00689             if (m->in_op & OPINVERSE)
00690                 offset = ~offset;
00691             break;
00692         case LONG:
00693             if (m->in_offset)
00694                 switch (m->in_op&0x7F) {
00695                 case OPAND:
00696                     offset = p->l & m->in_offset;
00697                     /*@innerbreak@*/ break;
00698                 case OPOR:
00699                     offset = p->l | m->in_offset;
00700                     /*@innerbreak@*/ break;
00701                 case OPXOR:
00702                     offset = p->l ^ m->in_offset;
00703                     /*@innerbreak@*/ break;
00704                 case OPADD:
00705                     offset = p->l + m->in_offset;
00706                     /*@innerbreak@*/ break;
00707                 case OPMINUS:
00708                     offset = p->l - m->in_offset;
00709                     /*@innerbreak@*/ break;
00710                 case OPMULTIPLY:
00711                     offset = p->l * m->in_offset;
00712                     /*@innerbreak@*/ break;
00713                 case OPDIVIDE:
00714                     offset = p->l / m->in_offset;
00715                     /*@innerbreak@*/ break;
00716                 case OPMODULO:
00717                     offset = p->l % m->in_offset;
00718                     /*@innerbreak@*/ break;
00719             /*  case TOOMANYSWITCHBLOCKS:
00720              *      ugh = p->eye % m->strain;
00721              *      rub;
00722              *  case BEER:
00723              *      off = p->tab & m->in_gest;
00724              *      sleep;
00725              */
00726                 }
00727             if (m->in_op & OPINVERSE)
00728                 offset = ~offset;
00729             break;
00730         }
00731 
00732 /*@-compmempass@*/
00733         if (buf == NULL || offset + sizeof(*p) > nb)
00734             return 0;
00735 /*@=compmempass@*/
00736 
00737         memcpy(p, buf + offset, sizeof(*p));
00738 
00739         if (fm->flags & FMAGIC_FLAGS_DEBUG) {
00740             fmagicSDebug(offset, (char *) p, sizeof(*p));
00741             mdump(m);
00742         }
00743     }
00744 /*@-compmempass@*/
00745     if (!fmagicSConvert(fm, m))
00746         return 0;
00747     return 1;
00748 /*@=compmempass@*/
00749 }
00750 /*@=bounds@*/
00751 
00752 /*@-bounds@*/
00753 static int
00754 fmagicSCheck(const fmagic fm, struct magic *m)
00755         /*@globals fileSystem @*/
00756         /*@modifies fileSystem @*/
00757 {
00758     union VALUETYPE * p = &fm->val;
00759     uint32_t l = m->value.l;
00760     uint32_t v = 0;
00761     int matched;
00762 
00763     if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
00764         fprintf(stderr, "BOINK");
00765         return 1;
00766     }
00767 
00768     switch (m->type) {
00769     case BYTE:
00770         v = p->b;
00771         break;
00772 
00773     case SHORT:
00774     case BESHORT:
00775     case LESHORT:
00776         v = p->h;
00777         break;
00778 
00779     case LONG:
00780     case BELONG:
00781     case LELONG:
00782     case DATE:
00783     case BEDATE:
00784     case LEDATE:
00785     case LDATE:
00786     case BELDATE:
00787     case LELDATE:
00788         v = p->l;
00789         break;
00790 
00791     case STRING:
00792     case PSTRING:
00793     {
00794         /*
00795          * What we want here is:
00796          * v = strncmp(m->value.s, p->s, m->vallen);
00797          * but ignoring any nulls.  bcmp doesn't give -/+/0
00798          * and isn't universally available anyway.
00799          */
00800         unsigned char *a = (unsigned char*)m->value.s;
00801         unsigned char *b = (unsigned char*)p->s;
00802         int len = m->vallen;
00803         l = 0;
00804         v = 0;
00805         if (0L == m->mask) { /* normal string: do it fast */
00806             while (--len >= 0)
00807                 if ((v = *b++ - *a++) != '\0')
00808                     /*@loopbreak@*/ break; 
00809         } else { /* combine the others */
00810             while (--len >= 0) {
00811                 if ((m->mask & STRING_IGNORE_LOWERCASE) && islower(*a)) {
00812                     if ((v = tolower(*b++) - *a++) != '\0')
00813                         /*@loopbreak@*/ break;
00814                 } else
00815                 if ((m->mask & STRING_COMPACT_BLANK) && isspace(*a)) { 
00816                     a++;
00817                     if (isspace(*b++)) {
00818                         while (isspace(*b))
00819                             b++;
00820                     } else {
00821                         v = 1;
00822                         /*@loopbreak@*/ break;
00823                     }
00824                 } else
00825                 if (isspace(*a) && (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
00826                     a++;
00827                     while (isspace(*b))
00828                         b++;
00829                 } else {
00830                     if ((v = *b++ - *a++) != '\0')
00831                         /*@loopbreak@*/ break;
00832                 }
00833             }
00834         }
00835         break;
00836     }
00837     case REGEX:
00838     {
00839         int rc;
00840         regex_t rx;
00841         char errmsg[512];
00842 
00843         rc = regcomp(&rx, m->value.s, REG_EXTENDED|REG_NOSUB);
00844         if (rc) {
00845             (void) regerror(rc, &rx, errmsg, sizeof(errmsg));
00846             error(EXIT_FAILURE, 0, "regex error %d, (%s)\n", rc, errmsg);
00847             /*@notreached@*/
00848         } else {
00849             rc = regexec(&rx, p->buf, 0, NULL, 0);
00850             return !rc;
00851         }
00852     }
00853         /*@notreached@*/ break;
00854     default:
00855         error(EXIT_FAILURE, 0, "invalid type %d in fmagicSCheck().\n", m->type);
00856         /*@notreached@*/
00857         return 0;
00858     }
00859 
00860     if(m->type != STRING && m->type != PSTRING)
00861         v = signextend(m, v);
00862 
00863     switch (m->reln) {
00864     case 'x':
00865         if (fm->flags & FMAGIC_FLAGS_DEBUG)
00866             (void) fprintf(stderr, "%u == *any* = 1\n", v);
00867         matched = 1;
00868         break;
00869 
00870     case '!':
00871         matched = v != l;
00872         if (fm->flags & FMAGIC_FLAGS_DEBUG)
00873             (void) fprintf(stderr, "%u != %u = %d\n",
00874                                v, l, matched);
00875         break;
00876 
00877     case '=':
00878         matched = v == l;
00879         if (fm->flags & FMAGIC_FLAGS_DEBUG)
00880             (void) fprintf(stderr, "%u == %u = %d\n",
00881                                v, l, matched);
00882         break;
00883 
00884     case '>':
00885         if (m->flag & UNSIGNED) {
00886             matched = v > l;
00887             if (fm->flags & FMAGIC_FLAGS_DEBUG)
00888                 (void) fprintf(stderr, "%u > %u = %d\n", v, l, matched);
00889         }
00890         else {
00891             matched = (int32_t) v > (int32_t) l;
00892             if (fm->flags & FMAGIC_FLAGS_DEBUG)
00893                 (void) fprintf(stderr, "%d > %d = %d\n", v, l, matched);
00894         }
00895         break;
00896 
00897     case '<':
00898         if (m->flag & UNSIGNED) {
00899             matched = v < l;
00900             if (fm->flags & FMAGIC_FLAGS_DEBUG)
00901                 (void) fprintf(stderr, "%u < %u = %d\n", v, l, matched);
00902         }
00903         else {
00904             matched = (int32_t) v < (int32_t) l;
00905             if (fm->flags & FMAGIC_FLAGS_DEBUG)
00906                 (void) fprintf(stderr, "%d < %d = %d\n", v, l, matched);
00907         }
00908         break;
00909 
00910     case '&':
00911         matched = (v & l) == l;
00912         if (fm->flags & FMAGIC_FLAGS_DEBUG)
00913             (void) fprintf(stderr, "((%x & %x) == %x) = %d\n", v, l, l, matched);
00914         break;
00915 
00916     case '^':
00917         matched = (v & l) != l;
00918         if (fm->flags & FMAGIC_FLAGS_DEBUG)
00919             (void) fprintf(stderr, "((%x & %x) != %x) = %d\n", v, l, l, matched);
00920         break;
00921 
00922     default:
00923         matched = 0;
00924         error(EXIT_FAILURE, 0, "fmagicSCheck: can't happen: invalid relation %d.\n", m->reln);
00925         /*@notreached@*/ break;
00926     }
00927 
00928     return matched;
00929 }
00930 /*@=bounds@*/
00931 
00932 /*
00933  * Go through the whole list, stopping if you find a match.  Process all
00934  * the continuations of that match before returning.
00935  *
00936  * We support multi-level continuations:
00937  *
00938  *      At any time when processing a successful top-level match, there is a
00939  *      current continuation level; it represents the level of the last
00940  *      successfully matched continuation.
00941  *
00942  *      Continuations above that level are skipped as, if we see one, it
00943  *      means that the continuation that controls them - i.e, the
00944  *      lower-level continuation preceding them - failed to match.
00945  *
00946  *      Continuations below that level are processed as, if we see one,
00947  *      it means we've finished processing or skipping higher-level
00948  *      continuations under the control of a successful or unsuccessful
00949  *      lower-level continuation, and are now seeing the next lower-level
00950  *      continuation and should process it.  The current continuation
00951  *      level reverts to the level of the one we're seeing.
00952  *
00953  *      Continuations at the current level are processed as, if we see
00954  *      one, there's no lower-level continuation that may have failed.
00955  *
00956  *      If a continuation matches, we bump the current continuation level
00957  *      so that higher-level continuations are processed.
00958  */
00959 /*@-bounds@*/
00960 static int
00961 fmagicSMatch(const fmagic fm)
00962         /*@globals fileSystem @*/
00963         /*@modifies fm, fileSystem @*/
00964 {
00965     struct magic * m;
00966     uint32_t nmagic = fm->ml->nmagic;
00967     int cont_level = 0;
00968     int need_separator = 0;
00969     /*@only@*/
00970     static int32_t * tmpoff = NULL;
00971     static int tmpdelta = 64;
00972     static size_t tmplen = 0;
00973     int32_t oldoff = 0;
00974     int firstline = 1; /* a flag to print X\n  X\n- X */
00975     int ret = 0; /* if a match is found it is set to 1*/
00976     int i;
00977 
00978     for (i = 0; i < nmagic; i++) {
00979         m = &fm->ml->magic[i];
00980         /* if main entry matches, print it... */
00981         if (!fmagicSGet(fm, m) || !fmagicSCheck(fm, m)) {
00982             /* main entry didn't match, flush its continuations */
00983             while ((m+1)->cont_level != 0 && ++i < nmagic)
00984                 m++;
00985             continue;
00986         }
00987 
00988         if (! firstline) { /* we found another match */
00989             /* put a newline and '-' to do some simple formatting */
00990             fmagicPrintf(fm, "\n- ");
00991         }
00992 
00993         if ((cont_level+1) >= tmplen) {
00994             tmplen += tmpdelta;
00995             tmpoff = xrealloc(tmpoff, tmplen * sizeof(*tmpoff));
00996         }
00997         tmpoff[cont_level] = fmagicSPrint(fm, m);
00998         cont_level++;
00999 
01000         /*
01001          * If we printed something, we'll need to print
01002          * a blank before we print something else.
01003          */
01004         if (m->desc[0])
01005             need_separator = 1;
01006 
01007         /* and any continuations that match */
01008         while ((m+1)->cont_level != 0 && ++i < nmagic) {
01009             m++;
01010             if (cont_level < m->cont_level)
01011                 /*@innercontinue@*/ continue;
01012             if (cont_level > m->cont_level) {
01013                 /* We're at the end of the level "cont_level" continuations. */
01014                 cont_level = m->cont_level;
01015             }
01016             if (m->flag & OFFADD) {
01017                 oldoff = m->offset;
01018                 m->offset += tmpoff[cont_level-1];
01019             }
01020             if (fmagicSGet(fm, m) && fmagicSCheck(fm, m)) {
01021                 /*
01022                  * This continuation matched.
01023                  * Print its message, with a blank before it if the previous
01024                  * item printed and this item isn't empty.
01025                  */
01026                 /* space if previous printed */
01027                 if (need_separator
01028                    && (m->nospflag == 0) && (m->desc[0] != '\0'))
01029                 {
01030                     fmagicPrintf(fm, " ");
01031                     need_separator = 0;
01032                 }
01033                 if ((cont_level+1) >= tmplen) {
01034                     tmplen += tmpdelta;
01035                     tmpoff = xrealloc(tmpoff, tmplen * sizeof(*tmpoff));
01036                 }
01037                 tmpoff[cont_level] = fmagicSPrint(fm, m);
01038                 cont_level++;
01039                 if (m->desc[0])
01040                     need_separator = 1;
01041             }
01042             if (m->flag & OFFADD)
01043                 m->offset = oldoff;
01044         }
01045         firstline = 0;
01046         ret = 1;
01047         if (!(fm->flags & FMAGIC_FLAGS_CONTINUE)) /* don't keep searching */
01048             return 1;
01049     }
01050     return ret; /* This is hit if -k is set or there is no match */
01051 }
01052 /*@=bounds@*/
01053 
01054 /*
01055  * fmagicS - lookup one file in database 
01056  * (already read from MAGIC by apprentice.c).
01057  * Passed the name and FILE * of one file to be typed.
01058  */
01059 int
01060 fmagicS(fmagic fm)
01061 {
01062 /*@-branchstate@*/
01063     if (fm->mlist != NULL)
01064     for (fm->ml = fm->mlist->next; fm->ml != fm->mlist; fm->ml = fm->ml->next) {
01065 /*@-compmempass@*/
01066         if (fmagicSMatch(fm))
01067             return 1;
01068 /*@=compmempass@*/
01069     }
01070 /*@=branchstate@*/
01071 
01072 /*@-compmempass@*/
01073     return 0;
01074 /*@=compmempass@*/
01075 }

Generated on Sun Oct 26 13:01:58 2003 for rpm by doxygen1.2.18