file/src/softmagic.c

Go to the documentation of this file.
00001 /*@-compdef@*/
00002 /*@-evalorder@*/
00003 /*@-sizeoftype@*/
00004 /*@-uniondef@*/
00005 /*@-usereleased@*/
00006 /*
00007  * Copyright (c) Ian F. Darwin 1986-1995.
00008  * Software written by Ian F. Darwin and others;
00009  * maintained 1995-present by Christos Zoulas and others.
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions
00013  * are met:
00014  * 1. Redistributions of source code must retain the above copyright
00015  *    notice immediately at the beginning of the file, without modification,
00016  *    this list of conditions, and the following disclaimer.
00017  * 2. Redistributions in binary form must reproduce the above copyright
00018  *    notice, this list of conditions and the following disclaimer in the
00019  *    documentation and/or other materials provided with the distribution.
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 "file.h"
00038 #include "magic.h"
00039 #include <string.h>
00040 #include <ctype.h>
00041 #include <stdlib.h>
00042 #include <time.h>
00043 #include <regex.h>
00044 
00045 
00046 #ifndef lint
00047 FILE_RCSID("@(#)$Id: softmagic.c,v 1.76 2005/10/17 19:04:36 christos Exp $")
00048 #endif  /* lint */
00049 
00050 private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00051     const unsigned char *s, size_t nbytes)
00052         /*@globals fileSystem @*/
00053         /*@modifies ms, magic, fileSystem @*/;
00054 private int mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
00055     struct magic *m, size_t nbytes, unsigned int cont_level)
00056         /*@globals fileSystem @*/
00057         /*@modifies ms, p, m, fileSystem @*/;
00058 private int mymcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00059         /*@globals fileSystem @*/
00060         /*@modifies ms, p, m, fileSystem @*/;
00061 private int32_t mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)       
00062         /*@globals fileSystem @*/
00063         /*@modifies ms, p, fileSystem @*/;
00064 private void mdebug(uint32_t offset, const char *str, size_t len)
00065         /*@globals fileSystem @*/
00066         /*@modifies fileSystem @*/;
00067 private int mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00068     const unsigned char *s, size_t offset, size_t nbytes)
00069         /*@modifies ms, p @*/;
00070 private int mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00071         /*@modifies ms, p @*/;
00072 private int check_mem(struct magic_set *ms, unsigned int level)
00073         /*@modifies ms @*/;
00074 
00075 /*
00076  * softmagic - lookup one file in database 
00077  * (already read from MAGIC by apprentice.c).
00078  * Passed the name and FILE * of one file to be typed.
00079  */
00080 /*ARGSUSED1*/           /* nbytes passed for regularity, maybe need later */
00081 protected int
00082 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
00083 {
00084         struct mlist *ml;
00085         for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
00086                 if (match(ms, ml->magic, ml->nmagic, buf, nbytes))
00087                         return 1;
00088 
00089         return 0;
00090 }
00091 
00092 /*
00093  * Go through the whole list, stopping if you find a match.  Process all
00094  * the continuations of that match before returning.
00095  *
00096  * We support multi-level continuations:
00097  *
00098  *      At any time when processing a successful top-level match, there is a
00099  *      current continuation level; it represents the level of the last
00100  *      successfully matched continuation.
00101  *
00102  *      Continuations above that level are skipped as, if we see one, it
00103  *      means that the continuation that controls them - i.e, the
00104  *      lower-level continuation preceding them - failed to match.
00105  *
00106  *      Continuations below that level are processed as, if we see one,
00107  *      it means we've finished processing or skipping higher-level
00108  *      continuations under the control of a successful or unsuccessful
00109  *      lower-level continuation, and are now seeing the next lower-level
00110  *      continuation and should process it.  The current continuation
00111  *      level reverts to the level of the one we're seeing.
00112  *
00113  *      Continuations at the current level are processed as, if we see
00114  *      one, there's no lower-level continuation that may have failed.
00115  *
00116  *      If a continuation matches, we bump the current continuation level
00117  *      so that higher-level continuations are processed.
00118  */
00119 private int
00120 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00121     const unsigned char *s, size_t nbytes)
00122 {
00123         uint32_t magindex = 0;
00124         unsigned int cont_level = 0;
00125         int need_separator = 0;
00126         union VALUETYPE p;
00127         int32_t oldoff = 0;
00128         int returnval = 0; /* if a match is found it is set to 1*/
00129         int firstline = 1; /* a flag to print X\n  X\n- X */
00130 
00131         if (check_mem(ms, cont_level) == -1)
00132                 return -1;
00133 
00134         for (magindex = 0; magindex < nmagic; magindex++) {
00135                 /* if main entry matches, print it... */
00136                 int flush = !mget(ms, &p, s, &magic[magindex], nbytes,
00137                     cont_level);
00138                 if (flush) {
00139                         if (magic[magindex].reln == '!') flush = 0;
00140                 } else {        
00141                         switch (mymcheck(ms, &p, &magic[magindex])) {
00142                         case -1:
00143                                 return -1;
00144                         case 0:
00145                                 flush++;
00146                                 /*@switchbreak@*/ break;
00147                         default:
00148                                 /*@switchbreak@*/ break;
00149                         }
00150                 }
00151                 if (flush) {
00152                         /* 
00153                          * main entry didn't match,
00154                          * flush its continuations
00155                          */
00156                         while (magindex < nmagic - 1 &&
00157                                magic[magindex + 1].cont_level != 0)
00158                                magindex++;
00159                         continue;
00160                 }
00161 
00162                 if (!firstline) { /* we found another match */
00163                         /* put a newline and '-' to do some simple formatting*/
00164                         if (file_printf(ms, "\n- ") == -1)
00165                                 return -1;
00166                 }
00167 
00168                 if ((ms->c.off[cont_level] = mprint(ms, &p, &magic[magindex]))
00169                     == -1)
00170                         return -1;
00171                 /*
00172                  * If we printed something, we'll need to print
00173                  * a blank before we print something else.
00174                  */
00175                 if (magic[magindex].desc[0])
00176                         need_separator = 1;
00177                 /* and any continuations that match */
00178                 if (check_mem(ms, ++cont_level) == -1)
00179                         return -1;
00180 
00181                 while (magic[magindex+1].cont_level != 0 && 
00182                        ++magindex < nmagic) {
00183                         if (cont_level < magic[magindex].cont_level)
00184                                 /*@innercontinue@*/ continue;
00185                         if (cont_level > magic[magindex].cont_level) {
00186                                 /*
00187                                  * We're at the end of the level
00188                                  * "cont_level" continuations.
00189                                  */
00190                                 cont_level = magic[magindex].cont_level;
00191                         }
00192                         oldoff = magic[magindex].offset;
00193                         if (magic[magindex].flag & OFFADD) {
00194                                 magic[magindex].offset +=
00195                                     ms->c.off[cont_level - 1];
00196                         }
00197 
00198                         flush = !mget(ms, &p, s, &magic[magindex], nbytes,
00199                             cont_level);
00200                         if (flush && magic[magindex].reln != '!')
00201                                 goto done;
00202                                 
00203                         switch (flush ? 1 : mymcheck(ms, &p, &magic[magindex])) {
00204                         case -1:
00205                                 return -1;
00206                         case 0:
00207                                 /*@switchbreak@*/ break;
00208                         default:
00209                                 /*
00210                                  * This continuation matched.
00211                                  * Print its message, with
00212                                  * a blank before it if
00213                                  * the previous item printed
00214                                  * and this item isn't empty.
00215                                  */
00216                                 /* space if previous printed */
00217                                 if (need_separator
00218                                     && (magic[magindex].nospflag == 0)
00219                                    && (magic[magindex].desc[0] != '\0')) {
00220                                         if (file_printf(ms, " ") == -1)
00221                                                 return -1;
00222                                         need_separator = 0;
00223                                 }
00224                                 if ((ms->c.off[cont_level] = mprint(ms, &p,
00225                                     &magic[magindex])) == -1)
00226                                         return -1;
00227                                 if (magic[magindex].desc[0])
00228                                         need_separator = 1;
00229 
00230                                 /*
00231                                  * If we see any continuations
00232                                  * at a higher level,
00233                                  * process them.
00234                                  */
00235                                 if (check_mem(ms, ++cont_level) == -1)
00236                                         return -1;
00237                         }
00238 done:
00239                         magic[magindex].offset = oldoff;
00240                 }
00241                 firstline = 0;
00242                 returnval = 1;
00243                 if ((ms->flags & MAGIC_CONTINUE) == 0) {
00244                         return 1; /* don't keep searching */
00245                 }                       
00246         }
00247         return returnval;  /* This is hit if -k is set or there is no match */
00248 }
00249 
00250 private int
00251 check_mem(struct magic_set *ms, unsigned int level)
00252 {
00253         size_t len;
00254 
00255         if (level < ms->c.len)
00256                 return 0;
00257 
00258         len = (ms->c.len += 20) * sizeof(*ms->c.off);
00259         ms->c.off = (ms->c.off == NULL) ? malloc(len) : realloc(ms->c.off, len);
00260         if (ms->c.off != NULL)
00261                 return 0;
00262         file_oomem(ms);
00263         return -1;
00264 }
00265 
00266 private int32_t
00267 mprint(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00268 {
00269         uint32_t v;
00270         int32_t t=0 ;
00271 
00272 
00273         switch (m->type) {
00274         case FILE_BYTE:
00275                 v = file_signextend(ms, m, (size_t)p->b);
00276                 if (file_printf(ms, m->desc, (unsigned char) v) == -1)
00277                         return -1;
00278                 t = m->offset + sizeof(char);
00279                 break;
00280 
00281         case FILE_SHORT:
00282         case FILE_BESHORT:
00283         case FILE_LESHORT:
00284                 v = file_signextend(ms, m, (size_t)p->h);
00285                 if (file_printf(ms, m->desc, (unsigned short) v) == -1)
00286                         return -1;
00287                 t = m->offset + sizeof(short);
00288                 break;
00289 
00290         case FILE_LONG:
00291         case FILE_BELONG:
00292         case FILE_LELONG:
00293                 v = file_signextend(ms, m, p->l);
00294                 if (file_printf(ms, m->desc, (uint32_t) v) == -1)
00295                         return -1;
00296                 t = m->offset + sizeof(int32_t);
00297                 break;
00298 
00299         case FILE_STRING:
00300         case FILE_PSTRING:
00301         case FILE_BESTRING16:
00302         case FILE_LESTRING16:
00303                 if (m->reln == '=' || m->reln == '!') {
00304                         if (file_printf(ms, m->desc, m->value.s) == -1)
00305                                 return -1;
00306                         t = m->offset + m->vallen;
00307                 }
00308                 else {
00309                         if (*m->value.s == '\0') {
00310                                 char *cp = strchr(p->s,'\n');
00311                                 if (cp)
00312                                         *cp = '\0';
00313                         }
00314                         if (file_printf(ms, m->desc, p->s) == -1)
00315                                 return -1;
00316                         t = m->offset + strlen(p->s);
00317                 }
00318                 break;
00319 
00320         case FILE_DATE:
00321         case FILE_BEDATE:
00322         case FILE_LEDATE:
00323                 if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
00324                         return -1;
00325                 t = m->offset + sizeof(time_t);
00326                 break;
00327 
00328         case FILE_LDATE:
00329         case FILE_BELDATE:
00330         case FILE_LELDATE:
00331                 if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
00332                         return -1;
00333                 t = m->offset + sizeof(time_t);
00334                 break;
00335         case FILE_REGEX:
00336                 if (file_printf(ms, m->desc, p->s) == -1)
00337                         return -1;
00338                 t = m->offset + strlen(p->s);
00339                 break;
00340         case FILE_SEARCH:
00341                 if (file_printf(ms, m->desc, m->value.s) == -1)
00342                         return -1;
00343                 t = m->offset + m->vallen;
00344                 break;
00345 
00346         default:
00347                 file_error(ms, 0, "invalid m->type (%d) in mprint()", m->type);
00348                 return -1;
00349         }
00350         return(t);
00351 }
00352 
00353 /*
00354  * Convert the byte order of the data we are looking at
00355  * While we're here, let's apply the mask operation
00356  * (unless you have a better idea)
00357  */
00358 private int
00359 mconvert(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
00360 {
00361         switch (m->type) {
00362         case FILE_BYTE:
00363                 if (m->mask)
00364                         switch (m->mask_op & 0x7F) {
00365                         case FILE_OPAND:
00366                                 p->b &= m->mask;
00367                                 /*@innerbreak@*/ break;
00368                         case FILE_OPOR:
00369                                 p->b |= m->mask;
00370                                 /*@innerbreak@*/ break;
00371                         case FILE_OPXOR:
00372                                 p->b ^= m->mask;
00373                                 /*@innerbreak@*/ break;
00374                         case FILE_OPADD:
00375                                 p->b += m->mask;
00376                                 /*@innerbreak@*/ break;
00377                         case FILE_OPMINUS:
00378                                 p->b -= m->mask;
00379                                 /*@innerbreak@*/ break;
00380                         case FILE_OPMULTIPLY:
00381                                 p->b *= m->mask;
00382                                 /*@innerbreak@*/ break;
00383                         case FILE_OPDIVIDE:
00384                                 p->b /= m->mask;
00385                                 /*@innerbreak@*/ break;
00386                         case FILE_OPMODULO:
00387                                 p->b %= m->mask;
00388                                 /*@innerbreak@*/ break;
00389                         }
00390                 if (m->mask_op & FILE_OPINVERSE)
00391                         p->b = ~p->b;
00392                 return 1;
00393         case FILE_SHORT:
00394                 if (m->mask)
00395                         switch (m->mask_op & 0x7F) {
00396                         case FILE_OPAND:
00397                                 p->h &= m->mask;
00398                                 /*@innerbreak@*/ break;
00399                         case FILE_OPOR:
00400                                 p->h |= m->mask;
00401                                 /*@innerbreak@*/ break;
00402                         case FILE_OPXOR:
00403                                 p->h ^= m->mask;
00404                                 /*@innerbreak@*/ break;
00405                         case FILE_OPADD:
00406                                 p->h += m->mask;
00407                                 /*@innerbreak@*/ break;
00408                         case FILE_OPMINUS:
00409                                 p->h -= m->mask;
00410                                 /*@innerbreak@*/ break;
00411                         case FILE_OPMULTIPLY:
00412                                 p->h *= m->mask;
00413                                 /*@innerbreak@*/ break;
00414                         case FILE_OPDIVIDE:
00415                                 p->h /= m->mask;
00416                                 /*@innerbreak@*/ break;
00417                         case FILE_OPMODULO:
00418                                 p->h %= m->mask;
00419                                 /*@innerbreak@*/ break;
00420                         }
00421                 if (m->mask_op & FILE_OPINVERSE)
00422                         p->h = ~p->h;
00423                 return 1;
00424         case FILE_LONG:
00425         case FILE_DATE:
00426         case FILE_LDATE:
00427                 if (m->mask)
00428                         switch (m->mask_op & 0x7F) {
00429                         case FILE_OPAND:
00430                                 p->l &= m->mask;
00431                                 /*@innerbreak@*/ break;
00432                         case FILE_OPOR:
00433                                 p->l |= m->mask;
00434                                 /*@innerbreak@*/ break;
00435                         case FILE_OPXOR:
00436                                 p->l ^= m->mask;
00437                                 /*@innerbreak@*/ break;
00438                         case FILE_OPADD:
00439                                 p->l += m->mask;
00440                                 /*@innerbreak@*/ break;
00441                         case FILE_OPMINUS:
00442                                 p->l -= m->mask;
00443                                 /*@innerbreak@*/ break;
00444                         case FILE_OPMULTIPLY:
00445                                 p->l *= m->mask;
00446                                 /*@innerbreak@*/ break;
00447                         case FILE_OPDIVIDE:
00448                                 p->l /= m->mask;
00449                                 /*@innerbreak@*/ break;
00450                         case FILE_OPMODULO:
00451                                 p->l %= m->mask;
00452                                 /*@innerbreak@*/ break;
00453                         }
00454                 if (m->mask_op & FILE_OPINVERSE)
00455                         p->l = ~p->l;
00456                 return 1;
00457         case FILE_STRING:
00458         case FILE_BESTRING16:
00459         case FILE_LESTRING16:
00460                 {
00461                         size_t len;
00462 
00463                         /* Null terminate and eat *trailing* return */
00464                         p->s[sizeof(p->s) - 1] = '\0';
00465                         len = strlen(p->s);
00466                         if (len-- && p->s[len] == '\n')
00467                                 p->s[len] = '\0';
00468                         return 1;
00469                 }
00470         case FILE_PSTRING:
00471                 {
00472                         char *ptr1 = p->s, *ptr2 = ptr1 + 1;
00473                         size_t len = *p->s;
00474                         if (len >= sizeof(p->s))
00475                                 len = sizeof(p->s) - 1;
00476                         while (len--)
00477                                 *ptr1++ = *ptr2++;
00478                         *ptr1 = '\0';
00479                         len = strlen(p->s);
00480                         if (len-- && p->s[len] == '\n')
00481                                 p->s[len] = '\0';
00482                         return 1;
00483                 }
00484         case FILE_BESHORT:
00485                 p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
00486                 if (m->mask)
00487                         switch (m->mask_op&0x7F) {
00488                         case FILE_OPAND:
00489                                 p->h &= m->mask;
00490                                 /*@innerbreak@*/ break;
00491                         case FILE_OPOR:
00492                                 p->h |= m->mask;
00493                                 /*@innerbreak@*/ break;
00494                         case FILE_OPXOR:
00495                                 p->h ^= m->mask;
00496                                 /*@innerbreak@*/ break;
00497                         case FILE_OPADD:
00498                                 p->h += m->mask;
00499                                 /*@innerbreak@*/ break;
00500                         case FILE_OPMINUS:
00501                                 p->h -= m->mask;
00502                                 /*@innerbreak@*/ break;
00503                         case FILE_OPMULTIPLY:
00504                                 p->h *= m->mask;
00505                                 /*@innerbreak@*/ break;
00506                         case FILE_OPDIVIDE:
00507                                 p->h /= m->mask;
00508                                 /*@innerbreak@*/ break;
00509                         case FILE_OPMODULO:
00510                                 p->h %= m->mask;
00511                                 /*@innerbreak@*/ break;
00512                         }
00513                 if (m->mask_op & FILE_OPINVERSE)
00514                         p->h = ~p->h;
00515                 return 1;
00516         case FILE_BELONG:
00517         case FILE_BEDATE:
00518         case FILE_BELDATE:
00519                 p->l = (int32_t)
00520                     ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
00521                 if (m->mask)
00522                         switch (m->mask_op&0x7F) {
00523                         case FILE_OPAND:
00524                                 p->l &= m->mask;
00525                                 /*@innerbreak@*/ break;
00526                         case FILE_OPOR:
00527                                 p->l |= m->mask;
00528                                 /*@innerbreak@*/ break;
00529                         case FILE_OPXOR:
00530                                 p->l ^= m->mask;
00531                                 /*@innerbreak@*/ break;
00532                         case FILE_OPADD:
00533                                 p->l += m->mask;
00534                                 /*@innerbreak@*/ break;
00535                         case FILE_OPMINUS:
00536                                 p->l -= m->mask;
00537                                 /*@innerbreak@*/ break;
00538                         case FILE_OPMULTIPLY:
00539                                 p->l *= m->mask;
00540                                 /*@innerbreak@*/ break;
00541                         case FILE_OPDIVIDE:
00542                                 p->l /= m->mask;
00543                                 /*@innerbreak@*/ break;
00544                         case FILE_OPMODULO:
00545                                 p->l %= m->mask;
00546                                 /*@innerbreak@*/ break;
00547                         }
00548                 if (m->mask_op & FILE_OPINVERSE)
00549                         p->l = ~p->l;
00550                 return 1;
00551         case FILE_LESHORT:
00552                 p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
00553                 if (m->mask)
00554                         switch (m->mask_op&0x7F) {
00555                         case FILE_OPAND:
00556                                 p->h &= m->mask;
00557                                 /*@innerbreak@*/ break;
00558                         case FILE_OPOR:
00559                                 p->h |= m->mask;
00560                                 /*@innerbreak@*/ break;
00561                         case FILE_OPXOR:
00562                                 p->h ^= m->mask;
00563                                 /*@innerbreak@*/ break;
00564                         case FILE_OPADD:
00565                                 p->h += m->mask;
00566                                 /*@innerbreak@*/ break;
00567                         case FILE_OPMINUS:
00568                                 p->h -= m->mask;
00569                                 /*@innerbreak@*/ break;
00570                         case FILE_OPMULTIPLY:
00571                                 p->h *= m->mask;
00572                                 /*@innerbreak@*/ break;
00573                         case FILE_OPDIVIDE:
00574                                 p->h /= m->mask;
00575                                 /*@innerbreak@*/ break;
00576                         case FILE_OPMODULO:
00577                                 p->h %= m->mask;
00578                                 /*@innerbreak@*/ break;
00579                         }
00580                 if (m->mask_op & FILE_OPINVERSE)
00581                         p->h = ~p->h;
00582                 return 1;
00583         case FILE_LELONG:
00584         case FILE_LEDATE:
00585         case FILE_LELDATE:
00586                 p->l = (int32_t)
00587                     ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
00588                 if (m->mask)
00589                         switch (m->mask_op&0x7F) {
00590                         case FILE_OPAND:
00591                                 p->l &= m->mask;
00592                                 /*@innerbreak@*/ break;
00593                         case FILE_OPOR:
00594                                 p->l |= m->mask;
00595                                 /*@innerbreak@*/ break;
00596                         case FILE_OPXOR:
00597                                 p->l ^= m->mask;
00598                                 /*@innerbreak@*/ break;
00599                         case FILE_OPADD:
00600                                 p->l += m->mask;
00601                                 /*@innerbreak@*/ break;
00602                         case FILE_OPMINUS:
00603                                 p->l -= m->mask;
00604                                 /*@innerbreak@*/ break;
00605                         case FILE_OPMULTIPLY:
00606                                 p->l *= m->mask;
00607                                 /*@innerbreak@*/ break;
00608                         case FILE_OPDIVIDE:
00609                                 p->l /= m->mask;
00610                                 /*@innerbreak@*/ break;
00611                         case FILE_OPMODULO:
00612                                 p->l %= m->mask;
00613                                 /*@innerbreak@*/ break;
00614                         }
00615                 if (m->mask_op & FILE_OPINVERSE)
00616                         p->l = ~p->l;
00617                 return 1;
00618         case FILE_REGEX:
00619         case FILE_SEARCH:
00620                 return 1;
00621         default:
00622                 file_error(ms, 0, "invalid type %d in mconvert()", m->type);
00623                 return 0;
00624         }
00625 }
00626 
00627 
00628 private void
00629 mdebug(uint32_t offset, const char *str, size_t len)
00630 {
00631         (void) fprintf(stderr, "mget @%d: ", offset);
00632         file_showstr(stderr, str, len);
00633         (void) fputc('\n', stderr);
00634         (void) fputc('\n', stderr);
00635 }
00636 
00637 private int
00638 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00639     const unsigned char *s, size_t offset, size_t nbytes)
00640 {
00641         if (type == FILE_REGEX && indir == 0) {
00642                 /*
00643                  * offset is interpreted as last line to search,
00644                  * (starting at 1), not as bytes-from start-of-file
00645                  */
00646                 char *b, *c, *last = NULL;
00647                 if ((p->search.buf = strdup((const char *)s)) == NULL) {
00648                         file_oomem(ms);
00649                         return -1;
00650                 }
00651                 for (b = p->search.buf; offset && 
00652                     ((b = strchr(c = b, '\n')) != NULL || (b = strchr(c, '\r')) != NULL);
00653                     offset--, b++) {
00654                         last = b;
00655                         if (b[0] == '\r' && b[1] == '\n') b++;
00656                 }
00657                 if (last != NULL)
00658                         *last = '\0';
00659                 p->search.buflen = last - p->search.buf;
00660                 return 0;
00661         }
00662 
00663         if (indir == 0 && (type == FILE_BESTRING16 || type == FILE_LESTRING16))
00664         {
00665                 const unsigned char *src = s + offset;
00666                 const unsigned char *esrc = s + nbytes;
00667                 char *dst = p->s, *edst = &p->s[sizeof(p->s) - 1];
00668 
00669                 if (type == FILE_BESTRING16)
00670                         src++;
00671 
00672                 for (;src < esrc; src++, dst++) {
00673                         if (dst < edst)
00674                                 *dst = *src++;
00675                         else
00676                                 break;
00677                         if (*dst == '\0')
00678                                 *dst = ' ';
00679                 }
00680                 *edst = '\0';
00681                 return 0;
00682         }
00683 
00684         if (offset >= nbytes) {
00685                 (void)memset(p, '\0', sizeof(*p));
00686                 return 0;
00687         }
00688         if (nbytes - offset < sizeof(*p))
00689                 nbytes = nbytes - offset;
00690         else
00691                 nbytes = sizeof(*p);
00692 
00693         (void)memcpy(p, s + offset, nbytes);
00694 
00695         /*
00696          * the usefulness of padding with zeroes eludes me, it
00697          * might even cause problems
00698          */
00699         if (nbytes < sizeof(*p))
00700                 (void)memset(((char *)(void *)p) + nbytes, '\0',
00701                     sizeof(*p) - nbytes);
00702         return 0;
00703 }
00704 
00705 private int
00706 mget(struct magic_set *ms, union VALUETYPE *p, const unsigned char *s,
00707     struct magic *m, size_t nbytes, unsigned int cont_level)
00708 {
00709         uint32_t offset = m->offset;
00710 
00711         if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes) == -1)
00712                 return -1;
00713 
00714         if ((ms->flags & MAGIC_DEBUG) != 0) {
00715                 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
00716                 file_mdump(m);
00717         }
00718 
00719         if (m->flag & INDIR) {
00720                 int off = m->in_offset;
00721                 if (m->in_op & FILE_OPINDIRECT) {
00722                         const union VALUETYPE *q =
00723                             ((const void *)(s + offset + off));
00724                         switch (m->in_type) {
00725                         case FILE_BYTE:
00726                                 off = q->b;
00727                                 break;
00728                         case FILE_SHORT:
00729                                 off = q->h;
00730                                 break;
00731                         case FILE_BESHORT:
00732                                 off = (short)((q->hs[0]<<8)|(q->hs[1]));
00733                                 break;
00734                         case FILE_LESHORT:
00735                                 off = (short)((q->hs[1]<<8)|(q->hs[0]));
00736                                 break;
00737                         case FILE_LONG:
00738                                 off = q->l;
00739                                 break;
00740                         case FILE_BELONG:
00741                                 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
00742                                                  (q->hl[2]<<8)|(q->hl[3]));
00743                                 break;
00744                         case FILE_LELONG:
00745                                 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
00746                                                  (q->hl[1]<<8)|(q->hl[0]));
00747                                 break;
00748                         }
00749                 }
00750                 switch (m->in_type) {
00751                 case FILE_BYTE:
00752                         if (nbytes < (offset + 1)) return 0;
00753                         if (off) {
00754                                 switch (m->in_op & 0x3F) {
00755                                 case FILE_OPAND:
00756                                         offset = p->b & off;
00757                                         /*@innerbreak@*/ break;
00758                                 case FILE_OPOR:
00759                                         offset = p->b | off;
00760                                         /*@innerbreak@*/ break;
00761                                 case FILE_OPXOR:
00762                                         offset = p->b ^ off;
00763                                         /*@innerbreak@*/ break;
00764                                 case FILE_OPADD:
00765                                         offset = p->b + off;
00766                                         /*@innerbreak@*/ break;
00767                                 case FILE_OPMINUS:
00768                                         offset = p->b - off;
00769                                         /*@innerbreak@*/ break;
00770                                 case FILE_OPMULTIPLY:
00771                                         offset = p->b * off;
00772                                         /*@innerbreak@*/ break;
00773                                 case FILE_OPDIVIDE:
00774                                         offset = p->b / off;
00775                                         /*@innerbreak@*/ break;
00776                                 case FILE_OPMODULO:
00777                                         offset = p->b % off;
00778                                         /*@innerbreak@*/ break;
00779                                 }
00780                         } else
00781                                 offset = p->b;
00782                         if (m->in_op & FILE_OPINVERSE)
00783                                 offset = ~offset;
00784                         break;
00785                 case FILE_BESHORT:
00786                         if (nbytes < (offset + 2))
00787                                 return 0;
00788                         if (off) {
00789                                 switch (m->in_op & 0x7F) {
00790                                 case FILE_OPAND:
00791                                         offset = (short)((p->hs[0]<<8)|
00792                                                          (p->hs[1])) &
00793                                                  off;
00794                                         /*@innerbreak@*/ break;
00795                                 case FILE_OPOR:
00796                                         offset = (short)((p->hs[0]<<8)|
00797                                                          (p->hs[1])) |
00798                                                  off;
00799                                         /*@innerbreak@*/ break;
00800                                 case FILE_OPXOR:
00801                                         offset = (short)((p->hs[0]<<8)|
00802                                                          (p->hs[1])) ^
00803                                                  off;
00804                                         /*@innerbreak@*/ break;
00805                                 case FILE_OPADD:
00806                                         offset = (short)((p->hs[0]<<8)|
00807                                                          (p->hs[1])) +
00808                                                  off;
00809                                         /*@innerbreak@*/ break;
00810                                 case FILE_OPMINUS:
00811                                         offset = (short)((p->hs[0]<<8)|
00812                                                          (p->hs[1])) -
00813                                                  off;
00814                                         /*@innerbreak@*/ break;
00815                                 case FILE_OPMULTIPLY:
00816                                         offset = (short)((p->hs[0]<<8)|
00817                                                          (p->hs[1])) *
00818                                                  off;
00819                                         /*@innerbreak@*/ break;
00820                                 case FILE_OPDIVIDE:
00821                                         offset = (short)((p->hs[0]<<8)|
00822                                                          (p->hs[1])) /
00823                                                  off;
00824                                         /*@innerbreak@*/ break;
00825                                 case FILE_OPMODULO:
00826                                         offset = (short)((p->hs[0]<<8)|
00827                                                          (p->hs[1])) %
00828                                                  off;
00829                                         /*@innerbreak@*/ break;
00830                                 }
00831                         } else
00832                                 offset = (short)((p->hs[0]<<8)|
00833                                                  (p->hs[1]));
00834                         if (m->in_op & FILE_OPINVERSE)
00835                                 offset = ~offset;
00836                         break;
00837                 case FILE_LESHORT:
00838                         if (nbytes < (offset + 2))
00839                                 return 0;
00840                         if (off) {
00841                                 switch (m->in_op & 0x7F) {
00842                                 case FILE_OPAND:
00843                                         offset = (short)((p->hs[1]<<8)|
00844                                                          (p->hs[0])) &
00845                                                  off;
00846                                         /*@innerbreak@*/ break;
00847                                 case FILE_OPOR:
00848                                         offset = (short)((p->hs[1]<<8)|
00849                                                          (p->hs[0])) |
00850                                                  off;
00851                                         /*@innerbreak@*/ break;
00852                                 case FILE_OPXOR:
00853                                         offset = (short)((p->hs[1]<<8)|
00854                                                          (p->hs[0])) ^
00855                                                  off;
00856                                         /*@innerbreak@*/ break;
00857                                 case FILE_OPADD:
00858                                         offset = (short)((p->hs[1]<<8)|
00859                                                          (p->hs[0])) +
00860                                                  off;
00861                                         /*@innerbreak@*/ break;
00862                                 case FILE_OPMINUS:
00863                                         offset = (short)((p->hs[1]<<8)|
00864                                                          (p->hs[0])) -
00865                                                  off;
00866                                         /*@innerbreak@*/ break;
00867                                 case FILE_OPMULTIPLY:
00868                                         offset = (short)((p->hs[1]<<8)|
00869                                                          (p->hs[0])) *
00870                                                  off;
00871                                         /*@innerbreak@*/ break;
00872                                 case FILE_OPDIVIDE:
00873                                         offset = (short)((p->hs[1]<<8)|
00874                                                          (p->hs[0])) /
00875                                                  off;
00876                                         /*@innerbreak@*/ break;
00877                                 case FILE_OPMODULO:
00878                                         offset = (short)((p->hs[1]<<8)|
00879                                                          (p->hs[0])) %
00880                                                  off;
00881                                         /*@innerbreak@*/ break;
00882                                 }
00883                         } else
00884                                 offset = (short)((p->hs[1]<<8)|
00885                                                  (p->hs[0]));
00886                         if (m->in_op & FILE_OPINVERSE)
00887                                 offset = ~offset;
00888                         break;
00889                 case FILE_SHORT:
00890                         if (nbytes < (offset + 2))
00891                                 return 0;
00892                         if (off) {
00893                                 switch (m->in_op & 0x7F) {
00894                                 case FILE_OPAND:
00895                                         offset = p->h & off;
00896                                         /*@innerbreak@*/ break;
00897                                 case FILE_OPOR:
00898                                         offset = p->h | off;
00899                                         /*@innerbreak@*/ break;
00900                                 case FILE_OPXOR:
00901                                         offset = p->h ^ off;
00902                                         /*@innerbreak@*/ break;
00903                                 case FILE_OPADD:
00904                                         offset = p->h + off;
00905                                         /*@innerbreak@*/ break;
00906                                 case FILE_OPMINUS:
00907                                         offset = p->h - off;
00908                                         /*@innerbreak@*/ break;
00909                                 case FILE_OPMULTIPLY:
00910                                         offset = p->h * off;
00911                                         /*@innerbreak@*/ break;
00912                                 case FILE_OPDIVIDE:
00913                                         offset = p->h / off;
00914                                         /*@innerbreak@*/ break;
00915                                 case FILE_OPMODULO:
00916                                         offset = p->h % off;
00917                                         /*@innerbreak@*/ break;
00918                                 }
00919                         }
00920                         else
00921                                 offset = p->h;
00922                         if (m->in_op & FILE_OPINVERSE)
00923                                 offset = ~offset;
00924                         break;
00925                 case FILE_BELONG:
00926                         if (nbytes < (offset + 4))
00927                                 return 0;
00928                         if (off) {
00929                                 switch (m->in_op & 0x7F) {
00930                                 case FILE_OPAND:
00931                                         offset = (int32_t)((p->hl[0]<<24)|
00932                                                          (p->hl[1]<<16)|
00933                                                          (p->hl[2]<<8)|
00934                                                          (p->hl[3])) &
00935                                                  off;
00936                                         /*@innerbreak@*/ break;
00937                                 case FILE_OPOR:
00938                                         offset = (int32_t)((p->hl[0]<<24)|
00939                                                          (p->hl[1]<<16)|
00940                                                          (p->hl[2]<<8)|
00941                                                          (p->hl[3])) |
00942                                                  off;
00943                                         /*@innerbreak@*/ break;
00944                                 case FILE_OPXOR:
00945                                         offset = (int32_t)((p->hl[0]<<24)|
00946                                                          (p->hl[1]<<16)|
00947                                                          (p->hl[2]<<8)|
00948                                                          (p->hl[3])) ^
00949                                                  off;
00950                                         /*@innerbreak@*/ break;
00951                                 case FILE_OPADD:
00952                                         offset = (int32_t)((p->hl[0]<<24)|
00953                                                          (p->hl[1]<<16)|
00954                                                          (p->hl[2]<<8)|
00955                                                          (p->hl[3])) +
00956                                                  off;
00957                                         /*@innerbreak@*/ break;
00958                                 case FILE_OPMINUS:
00959                                         offset = (int32_t)((p->hl[0]<<24)|
00960                                                          (p->hl[1]<<16)|
00961                                                          (p->hl[2]<<8)|
00962                                                          (p->hl[3])) -
00963                                                  off;
00964                                         /*@innerbreak@*/ break;
00965                                 case FILE_OPMULTIPLY:
00966                                         offset = (int32_t)((p->hl[0]<<24)|
00967                                                          (p->hl[1]<<16)|
00968                                                          (p->hl[2]<<8)|
00969                                                          (p->hl[3])) *
00970                                                  off;
00971                                         /*@innerbreak@*/ break;
00972                                 case FILE_OPDIVIDE:
00973                                         offset = (int32_t)((p->hl[0]<<24)|
00974                                                          (p->hl[1]<<16)|
00975                                                          (p->hl[2]<<8)|
00976                                                          (p->hl[3])) /
00977                                                  off;
00978                                         /*@innerbreak@*/ break;
00979                                 case FILE_OPMODULO:
00980                                         offset = (int32_t)((p->hl[0]<<24)|
00981                                                          (p->hl[1]<<16)|
00982                                                          (p->hl[2]<<8)|
00983                                                          (p->hl[3])) %
00984                                                  off;
00985                                         /*@innerbreak@*/ break;
00986                                 }
00987                         } else
00988                                 offset = (int32_t)((p->hl[0]<<24)|
00989                                                  (p->hl[1]<<16)|
00990                                                  (p->hl[2]<<8)|
00991                                                  (p->hl[3]));
00992                         if (m->in_op & FILE_OPINVERSE)
00993                                 offset = ~offset;
00994                         break;
00995                 case FILE_LELONG:
00996                         if (nbytes < (offset + 4))
00997                                 return 0;
00998                         if (off) {
00999                                 switch (m->in_op & 0x7F) {
01000                                 case FILE_OPAND:
01001                                         offset = (int32_t)((p->hl[3]<<24)|
01002                                                          (p->hl[2]<<16)|
01003                                                          (p->hl[1]<<8)|
01004                                                          (p->hl[0])) &
01005                                                  off;
01006                                         /*@innerbreak@*/ break;
01007                                 case FILE_OPOR:
01008                                         offset = (int32_t)((p->hl[3]<<24)|
01009                                                          (p->hl[2]<<16)|
01010                                                          (p->hl[1]<<8)|
01011                                                          (p->hl[0])) |
01012                                                  off;
01013                                         /*@innerbreak@*/ break;
01014                                 case FILE_OPXOR:
01015                                         offset = (int32_t)((p->hl[3]<<24)|
01016                                                          (p->hl[2]<<16)|
01017                                                          (p->hl[1]<<8)|
01018                                                          (p->hl[0])) ^
01019                                                  off;
01020                                         /*@innerbreak@*/ break;
01021                                 case FILE_OPADD:
01022                                         offset = (int32_t)((p->hl[3]<<24)|
01023                                                          (p->hl[2]<<16)|
01024                                                          (p->hl[1]<<8)|
01025                                                          (p->hl[0])) +
01026                                                  off;
01027                                         /*@innerbreak@*/ break;
01028                                 case FILE_OPMINUS:
01029                                         offset = (int32_t)((p->hl[3]<<24)|
01030                                                          (p->hl[2]<<16)|
01031                                                          (p->hl[1]<<8)|
01032                                                          (p->hl[0])) -
01033                                                  off;
01034                                         /*@innerbreak@*/ break;
01035                                 case FILE_OPMULTIPLY:
01036                                         offset = (int32_t)((p->hl[3]<<24)|
01037                                                          (p->hl[2]<<16)|
01038                                                          (p->hl[1]<<8)|
01039                                                          (p->hl[0])) *
01040                                                  off;
01041                                         /*@innerbreak@*/ break;
01042                                 case FILE_OPDIVIDE:
01043                                         offset = (int32_t)((p->hl[3]<<24)|
01044                                                          (p->hl[2]<<16)|
01045                                                          (p->hl[1]<<8)|
01046                                                          (p->hl[0])) /
01047                                                  off;
01048                                         /*@innerbreak@*/ break;
01049                                 case FILE_OPMODULO:
01050                                         offset = (int32_t)((p->hl[3]<<24)|
01051                                                          (p->hl[2]<<16)|
01052                                                          (p->hl[1]<<8)|
01053                                                          (p->hl[0])) %
01054                                                  off;
01055                                         /*@innerbreak@*/ break;
01056                                 }
01057                         } else
01058                                 offset = (int32_t)((p->hl[3]<<24)|
01059                                                  (p->hl[2]<<16)|
01060                                                  (p->hl[1]<<8)|
01061                                                  (p->hl[0]));
01062                         if (m->in_op & FILE_OPINVERSE)
01063                                 offset = ~offset;
01064                         break;
01065                 case FILE_LONG:
01066                         if (nbytes < (offset + 4))
01067                                 return 0;
01068                         if (off) {
01069                                 switch (m->in_op & 0x7F) {
01070                                 case FILE_OPAND:
01071                                         offset = p->l & off;
01072                                         /*@innerbreak@*/ break;
01073                                 case FILE_OPOR:
01074                                         offset = p->l | off;
01075                                         /*@innerbreak@*/ break;
01076                                 case FILE_OPXOR:
01077                                         offset = p->l ^ off;
01078                                         /*@innerbreak@*/ break;
01079                                 case FILE_OPADD:
01080                                         offset = p->l + off;
01081                                         /*@innerbreak@*/ break;
01082                                 case FILE_OPMINUS:
01083                                         offset = p->l - off;
01084                                         /*@innerbreak@*/ break;
01085                                 case FILE_OPMULTIPLY:
01086                                         offset = p->l * off;
01087                                         /*@innerbreak@*/ break;
01088                                 case FILE_OPDIVIDE:
01089                                         offset = p->l / off;
01090                                         /*@innerbreak@*/ break;
01091                                 case FILE_OPMODULO:
01092                                         offset = p->l % off;
01093                                         /*@innerbreak@*/ break;
01094                         /*      case TOOMANYSWITCHBLOCKS:
01095                          *              ugh = p->eye % m->strain;
01096                          *              rub;
01097                          *      case BEER:
01098                          *              off = p->tab & m->in_gest;
01099                          *              sleep;
01100                          */
01101                                 }
01102                         } else
01103                                 offset = p->l;
01104                         if (m->in_op & FILE_OPINVERSE)
01105                                 offset = ~offset;
01106                         break;
01107                 }
01108 
01109                 if (m->flag & INDIROFFADD) offset += ms->c.off[cont_level-1];
01110                 if (mcopy(ms, p, m->type, 0, s, offset, nbytes) == -1)
01111                         return -1;
01112                 m->offset = offset;
01113 
01114                 if ((ms->flags & MAGIC_DEBUG) != 0) {
01115                         mdebug(offset, (char *)(void *)p,
01116                             sizeof(union VALUETYPE));
01117                         file_mdump(m);
01118                 }
01119         }
01120 
01121         /* Verify we have enough data to match magic type */
01122         switch (m->type) {
01123                 case FILE_BYTE:
01124                         if (nbytes < (offset + 1)) /* should alway be true */
01125                                 return 0;
01126                         break;
01127 
01128                 case FILE_SHORT:
01129                 case FILE_BESHORT:
01130                 case FILE_LESHORT:
01131                         if (nbytes < (offset + 2))
01132                                 return 0;
01133                         break;
01134 
01135                 case FILE_LONG:
01136                 case FILE_BELONG:
01137                 case FILE_LELONG:
01138                 case FILE_DATE:
01139                 case FILE_BEDATE:
01140                 case FILE_LEDATE:
01141                 case FILE_LDATE:
01142                 case FILE_BELDATE:
01143                 case FILE_LELDATE:
01144                         if (nbytes < (offset + 4))
01145                                 return 0;
01146                         break;
01147 
01148                 case FILE_STRING:
01149                 case FILE_PSTRING:
01150                 case FILE_SEARCH:
01151                         if (nbytes < (offset + m->vallen))
01152                                 return 0;
01153                         break;
01154                 default: break;
01155         }
01156 
01157         if (m->type == FILE_SEARCH) {
01158                 size_t mlen = m->mask + m->vallen;
01159                 size_t flen = nbytes - offset;
01160                 if (flen < mlen)
01161                         mlen = flen;
01162                 p->search.buflen = mlen;
01163                 p->search.buf = malloc(mlen + 1);
01164                 if (p->search.buf == NULL) {
01165                         file_error(ms, errno, "Cannot allocate search buffer");
01166                         return 0;
01167                 }
01168                 (void)memcpy(p->search.buf, s + offset, mlen);
01169                 p->search.buf[mlen] = '\0';
01170         }
01171         if (!mconvert(ms, p, m))
01172                 return 0;
01173         return 1;
01174 }
01175 
01176 private int
01177 mymcheck(struct magic_set *ms, union VALUETYPE *p, struct magic *m)
01178 {
01179         uint32_t l = m->value.l;
01180         uint32_t v;
01181         int matched;
01182 
01183         if ( (m->value.s[0] == 'x') && (m->value.s[1] == '\0') ) {
01184                 return 1;
01185         }
01186 
01187 
01188         switch (m->type) {
01189         case FILE_BYTE:
01190                 v = p->b;
01191                 break;
01192 
01193         case FILE_SHORT:
01194         case FILE_BESHORT:
01195         case FILE_LESHORT:
01196                 v = p->h;
01197                 break;
01198 
01199         case FILE_LONG:
01200         case FILE_BELONG:
01201         case FILE_LELONG:
01202         case FILE_DATE:
01203         case FILE_BEDATE:
01204         case FILE_LEDATE:
01205         case FILE_LDATE:
01206         case FILE_BELDATE:
01207         case FILE_LELDATE:
01208                 v = p->l;
01209                 break;
01210 
01211         case FILE_STRING:
01212         case FILE_BESTRING16:
01213         case FILE_LESTRING16:
01214         case FILE_PSTRING:
01215         {
01216                 /*
01217                  * What we want here is:
01218                  * v = strncmp(m->value.s, p->s, m->vallen);
01219                  * but ignoring any nulls.  bcmp doesn't give -/+/0
01220                  * and isn't universally available anyway.
01221                  */
01222                 unsigned char *a = (unsigned char*)m->value.s;
01223                 unsigned char *b = (unsigned char*)p->s;
01224                 int len = m->vallen;
01225                 l = 0;
01226                 v = 0;
01227                 if (0L == m->mask) { /* normal string: do it fast */
01228                         while (--len >= 0)
01229                                 if ((v = *b++ - *a++) != '\0')
01230                                         /*@loopbreak@*/ break; 
01231                 } else { /* combine the others */
01232                         while (--len >= 0) {
01233                                 if ((m->mask & STRING_IGNORE_LOWERCASE) &&
01234                                     islower(*a)) {
01235                                         if ((v = tolower(*b++) - *a++) != '\0')
01236                                                 /*@loopbreak@*/ break;
01237                                 } else if ((m->mask & STRING_COMPACT_BLANK) && 
01238                                     isspace(*a)) { 
01239                                         a++;
01240                                         if (isspace(*b++)) {
01241                                                 while (isspace(*b))
01242                                                         b++;
01243                                         } else {
01244                                                 v = 1;
01245                                                 /*@loopbreak@*/ break;
01246                                         }
01247                                 } else if (isspace(*a) &&
01248                                     (m->mask & STRING_COMPACT_OPTIONAL_BLANK)) {
01249                                         a++;
01250                                         while (isspace(*b))
01251                                                 b++;
01252                                 } else {
01253                                         if ((v = *b++ - *a++) != '\0')
01254                                                 /*@loopbreak@*/ break;
01255                                 }
01256                         }
01257                 }
01258                 break;
01259         }
01260         case FILE_REGEX:
01261         {
01262                 int rc;
01263                 regex_t rx;
01264                 char errmsg[512];
01265 
01266                 if (p->search.buf == NULL)
01267                         return 0;
01268 
01269                 rc = regcomp(&rx, m->value.s,
01270                     REG_EXTENDED|REG_NOSUB|REG_NEWLINE|
01271                     ((m->mask & STRING_IGNORE_LOWERCASE) ? REG_ICASE : 0));
01272                 if (rc) {
01273                         free(p->search.buf);
01274                         p->search.buf = NULL;
01275                         (void) regerror(rc, &rx, errmsg, sizeof(errmsg));
01276                         file_error(ms, 0, "regex error %d, (%s)", rc, errmsg);
01277                         return -1;
01278                 } else {
01279 /*@i@*/                 rc = regexec(&rx, p->search.buf, 0, 0, 0);
01280 /*@i@*/                 regfree(&rx);
01281                         free(p->search.buf);
01282                         p->search.buf = NULL;
01283                         return !rc;
01284                 }
01285         }
01286         case FILE_SEARCH:
01287         {
01288                 /*
01289                  * search for a string in a certain range
01290                  */
01291                 unsigned char *a = (unsigned char*)m->value.s;
01292                 unsigned char *b = (unsigned char*)p->search.buf;
01293                 size_t len, slen = m->vallen;
01294                 size_t range = 0;
01295                 if (slen > sizeof(m->value.s))
01296                         slen = sizeof(m->value.s);
01297                 l = 0;
01298                 v = 0;
01299                 if (b == NULL)
01300                         return 0;
01301                 len = slen;
01302                 while (++range <= m->mask) {
01303                         while (len-- > 0 && (v = *b++ - *a++) == 0)
01304                                 /*@innercontinue@*/ continue;
01305                         if (!v) {
01306                                 m->offset += range - 1;
01307                                 /*@loopbreak@*/ break;
01308                         }
01309                         if (range + slen >= p->search.buflen)
01310                                 /*@loopbreak@*/ break;
01311                         len = slen;
01312                         a = (unsigned char*)m->value.s;
01313                         b = (unsigned char*)p->search.buf + range;
01314                 }
01315                 free(p->search.buf);
01316                 p->search.buf = NULL;
01317                 break;
01318         }
01319         default:
01320                 file_error(ms, 0, "invalid type %d in mcheck()", m->type);
01321                 return -1;
01322         }
01323 
01324         if (m->type != FILE_STRING && m->type != FILE_PSTRING)
01325                 v = file_signextend(ms, m, v);
01326 
01327         switch (m->reln) {
01328         case 'x':
01329                 if ((ms->flags & MAGIC_DEBUG) != 0)
01330                         (void) fprintf(stderr, "%u == *any* = 1\n", v);
01331                 matched = 1;
01332                 break;
01333 
01334         case '!':
01335                 matched = v != l;
01336                 if ((ms->flags & MAGIC_DEBUG) != 0)
01337                         (void) fprintf(stderr, "%u != %u = %d\n",
01338                                        v, l, matched);
01339                 break;
01340 
01341         case '=':
01342                 matched = v == l;
01343                 if ((ms->flags & MAGIC_DEBUG) != 0)
01344                         (void) fprintf(stderr, "%u == %u = %d\n",
01345                                        v, l, matched);
01346                 break;
01347 
01348         case '>':
01349                 if (m->flag & UNSIGNED) {
01350                         matched = v > l;
01351                         if ((ms->flags & MAGIC_DEBUG) != 0)
01352                                 (void) fprintf(stderr, "%u > %u = %d\n",
01353                                                v, l, matched);
01354                 }
01355                 else {
01356                         matched = (int32_t) v > (int32_t) l;
01357                         if ((ms->flags & MAGIC_DEBUG) != 0)
01358                                 (void) fprintf(stderr, "%d > %d = %d\n",
01359                                                v, l, matched);
01360                 }
01361                 break;
01362 
01363         case '<':
01364                 if (m->flag & UNSIGNED) {
01365                         matched = v < l;
01366                         if ((ms->flags & MAGIC_DEBUG) != 0)
01367                                 (void) fprintf(stderr, "%u < %u = %d\n",
01368                                                v, l, matched);
01369                 }
01370                 else {
01371                         matched = (int32_t) v < (int32_t) l;
01372                         if ((ms->flags & MAGIC_DEBUG) != 0)
01373                                 (void) fprintf(stderr, "%d < %d = %d\n",
01374                                                v, l, matched);
01375                 }
01376                 break;
01377 
01378         case '&':
01379                 matched = (v & l) == l;
01380                 if ((ms->flags & MAGIC_DEBUG) != 0)
01381                         (void) fprintf(stderr, "((%x & %x) == %x) = %d\n",
01382                                        v, l, l, matched);
01383                 break;
01384 
01385         case '^':
01386                 matched = (v & l) != l;
01387                 if ((ms->flags & MAGIC_DEBUG) != 0)
01388                         (void) fprintf(stderr, "((%x & %x) != %x) = %d\n",
01389                                        v, l, l, matched);
01390                 break;
01391 
01392         default:
01393                 matched = 0;
01394                 file_error(ms, 0, "cannot happen: invalid relation `%c'",
01395                     m->reln);
01396                 return -1;
01397         }
01398 
01399         return matched;
01400 }
01401 /*@=usereleased@*/
01402 /*@=uniondef@*/
01403 /*@=sizeoftype@*/
01404 /*@=evalorder@*/
01405 /*@=compdef@*/ 

Generated on Fri Oct 12 08:44:53 2007 for rpm by  doxygen 1.5.2