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

softmagic.c

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

Generated on Fri Aug 11 13:29:36 2006 for rpm by  doxygen 1.3.9.1