file/src/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  *  
00016  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00019  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
00020  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00022  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00023  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00024  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00025  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00026  * SUCH DAMAGE.
00027  */
00028 /*
00029  * softmagic - interpret variable magic from MAGIC
00030  */
00031 
00032 #include "file.h"
00033 #include "magic.h"
00034 #include <string.h>
00035 #include <ctype.h>
00036 #include <stdlib.h>
00037 #include <time.h>
00038 
00039 
00040 #ifndef lint
00041 FILE_RCSID("@(#)$File: softmagic.c,v 1.99 2007/05/08 14:44:18 christos Exp $")
00042 #endif  /* lint */
00043 
00044 private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00045     const unsigned char *s, size_t nbytes)
00046         /*@globals fileSystem @*/
00047         /*@modifies ms, magic, fileSystem @*/;
00048 private int mget(struct magic_set *ms, const unsigned char *s,
00049     struct magic *m, size_t nbytes, unsigned int cont_level)
00050         /*@globals fileSystem @*/
00051         /*@modifies ms, m, fileSystem @*/;
00052 private int magiccheck(struct magic_set *ms, struct magic *m)
00053         /*@globals fileSystem @*/
00054         /*@modifies ms, fileSystem @*/;
00055 private int32_t mprint(struct magic_set *ms, struct magic *m)
00056         /*@globals fileSystem @*/
00057         /*@modifies ms, fileSystem @*/;
00058 private void mdebug(uint32_t offset, const char *str, size_t len)
00059         /*@globals fileSystem @*/
00060         /*@modifies ms, fileSystem @*/;
00061 private int mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00062     const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
00063         /*@modifies ms, p @*/;
00064 private int mconvert(struct magic_set *ms, struct magic *m)
00065         /*@modifies ms @*/;
00066 private int print_sep(struct magic_set *ms, int firstline)
00067         /*@modifies ms @*/;
00068 private void cvt_8(union VALUETYPE *p, const struct magic *m)
00069         /*@modifies p @*/;
00070 private void cvt_16(union VALUETYPE *p, const struct magic *m)
00071         /*@modifies p @*/;
00072 private void cvt_32(union VALUETYPE *p, const struct magic *m)
00073         /*@modifies p @*/;
00074 private void cvt_64(union VALUETYPE *p, const struct magic *m)
00075         /*@modifies p @*/;
00076 
00077 /*
00078  * softmagic - lookup one file in parsed, in-memory copy of database
00079  * Passed the name and FILE * of one file to be typed.
00080  */
00081 /*ARGSUSED1*/           /* nbytes passed for regularity, maybe need later */
00082 protected int
00083 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes)
00084 {
00085         struct mlist *ml;
00086         int rv;
00087         for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
00088                 if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0)
00089                         return rv;
00090 
00091         return 0;
00092 }
00093 
00094 /*
00095  * Go through the whole list, stopping if you find a match.  Process all
00096  * the continuations of that match before returning.
00097  *
00098  * We support multi-level continuations:
00099  *
00100  *      At any time when processing a successful top-level match, there is a
00101  *      current continuation level; it represents the level of the last
00102  *      successfully matched continuation.
00103  *
00104  *      Continuations above that level are skipped as, if we see one, it
00105  *      means that the continuation that controls them - i.e, the
00106  *      lower-level continuation preceding them - failed to match.
00107  *
00108  *      Continuations below that level are processed as, if we see one,
00109  *      it means we've finished processing or skipping higher-level
00110  *      continuations under the control of a successful or unsuccessful
00111  *      lower-level continuation, and are now seeing the next lower-level
00112  *      continuation and should process it.  The current continuation
00113  *      level reverts to the level of the one we're seeing.
00114  *
00115  *      Continuations at the current level are processed as, if we see
00116  *      one, there's no lower-level continuation that may have failed.
00117  *
00118  *      If a continuation matches, we bump the current continuation level
00119  *      so that higher-level continuations are processed.
00120  */
00121 private int
00122 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
00123     const unsigned char *s, size_t nbytes)
00124 {
00125         uint32_t magindex = 0;
00126         unsigned int cont_level = 0;
00127         int need_separator = 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         int printed_something = 0;
00131 
00132         if (file_check_mem(ms, cont_level) == -1)
00133                 return -1;
00134 
00135         for (magindex = 0; magindex < nmagic; magindex++) {
00136                 int flush;
00137 
00138                 ms->offset = magic[magindex].offset;
00139                 ms->line = magic[magindex].lineno;
00140 
00141                 /* if main entry matches, print it... */
00142                 flush = !mget(ms, s, &magic[magindex], nbytes, cont_level);
00143                 if (flush) {
00144                         if (magic[magindex].reln == '!')
00145                                 flush = 0;
00146                 } else {        
00147                         switch (magiccheck(ms, &magic[magindex])) {
00148                         case -1:
00149                                 return -1;
00150                         case 0:
00151                                 flush++;
00152                                 /*@switchbreak@*/ break;
00153                         default:
00154                                 /*@switchbreak@*/ break;
00155                         }
00156                 }
00157                 if (flush) {
00158                         /* 
00159                          * main entry didn't match,
00160                          * flush its continuations
00161                          */
00162                         while (magindex < nmagic - 1 &&
00163                                magic[magindex + 1].cont_level != 0)
00164                                magindex++;
00165                         continue;
00166                 }
00167 
00168                 /*
00169                  * If we are going to print something, we'll need to print
00170                  * a blank before we print something else.
00171                  */
00172                 if (magic[magindex].desc[0]) {
00173                         need_separator = 1;
00174                         printed_something = 1;
00175                         if (print_sep(ms, firstline) == -1)
00176                                 return -1;
00177                 }
00178 
00179                 if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex]))
00180                     == -1)
00181                         return -1;
00182 
00183                 /* and any continuations that match */
00184                 if (file_check_mem(ms, ++cont_level) == -1)
00185                         return -1;
00186 
00187                 while (magic[magindex+1].cont_level != 0 && 
00188                        ++magindex < nmagic) {
00189                         ms->line = magic[magindex].lineno; /* for messages */
00190 
00191                         if (cont_level < magic[magindex].cont_level)
00192                                 /*@innercontinue@*/ continue;
00193                         if (cont_level > magic[magindex].cont_level) {
00194                                 /*
00195                                  * We're at the end of the level
00196                                  * "cont_level" continuations.
00197                                  */
00198                                 cont_level = magic[magindex].cont_level;
00199                         }
00200                         ms->offset = magic[magindex].offset;
00201                         if (magic[magindex].flag & OFFADD) {
00202                                 ms->offset +=
00203                                     ms->c.li[cont_level - 1].off;
00204                         }
00205 
00206 #ifdef ENABLE_CONDITIONALS
00207                         if (magic[magindex].cond == COND_ELSE ||
00208                             magic[magindex].cond == COND_ELIF) {
00209                                 if (ms->c.li[cont_level].last_match == 1)
00210                                         /*@innercontinue@*/ continue;
00211                         }
00212 #endif
00213                         flush = !mget(ms, s, &magic[magindex], nbytes,
00214                             cont_level);
00215                         if (flush && magic[magindex].reln != '!')
00216                                 /*@innercontinue@*/ continue;
00217                                 
00218                         switch (flush ? 1 : magiccheck(ms, &magic[magindex])) {
00219                         case -1:
00220                                 return -1;
00221                         case 0:
00222 #ifdef ENABLE_CONDITIONALS
00223                                 ms->c.li[cont_level].last_match = 0;
00224 #endif
00225                                 /*@switchbreak@*/ break;
00226                         default:
00227 #ifdef ENABLE_CONDITIONALS
00228                                 ms->c.li[cont_level].last_match = 1;
00229 #endif
00230                                 if (magic[magindex].type != FILE_DEFAULT)
00231                                         ms->c.li[cont_level].got_match = 1;
00232                                 else if (ms->c.li[cont_level].got_match) {
00233                                         ms->c.li[cont_level].got_match = 0;
00234                                         /*@switchbreak@*/ break;
00235                                 }
00236                                 /*
00237                                  * If we are going to print something,
00238                                  * make sure that we have a separator first.
00239                                  */
00240                                 if (magic[magindex].desc[0]) {
00241                                         printed_something = 1;
00242                                         if (print_sep(ms, firstline) == -1)
00243                                                 return -1;
00244                                 }
00245                                 /*
00246                                  * This continuation matched.  Print
00247                                  * its message, with a blank before it
00248                                  * if the previous item printed and
00249                                  * this item isn't empty.
00250                                  */
00251                                 /* space if previous printed */
00252                                 if (need_separator
00253                                     && (magic[magindex].nospflag == 0)
00254                                    && (magic[magindex].desc[0] != '\0')) {
00255                                         if (file_printf(ms, " ") == -1)
00256                                                 return -1;
00257                                         need_separator = 0;
00258                                 }
00259                                 if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1)
00260                                         return -1;
00261                                 if (magic[magindex].desc[0])
00262                                         need_separator = 1;
00263 
00264                                 /*
00265                                  * If we see any continuations
00266                                  * at a higher level,
00267                                  * process them.
00268                                  */
00269                                 if (file_check_mem(ms, ++cont_level) == -1)
00270                                         return -1;
00271                                 /*@switchbreak@*/ break;
00272                         }
00273                 }
00274                 firstline = 0;
00275                 if (printed_something)
00276                 returnval = 1;
00277                 if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) {
00278                         return 1; /* don't keep searching */
00279                 }                       
00280         }
00281         return returnval;  /* This is hit if -k is set or there is no match */
00282 }
00283 
00284 private int
00285 check_fmt(struct magic_set *ms, struct magic *m)
00286         /*@modifies ms @*/
00287 {
00288         regex_t rx;
00289         int rc;
00290 
00291         if (strchr(m->desc, '%') == NULL)
00292                 return 0;
00293 
00294         rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB);
00295         if (rc) {
00296                 char errmsg[512];
00297                 (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
00298                 file_magerror(ms, "regex error %d, (%s)", rc, errmsg);
00299         return -1;
00300         } else {
00301                 rc = regexec(&rx, m->desc, 0, 0, 0);
00302 /*@i@*/         regfree(&rx);
00303                 return !rc;
00304         }
00305 }
00306 
00307 #ifndef HAVE_STRNDUP
00308 char * strndup(const char *, size_t);
00309 
00310 char *
00311 strndup(const char *str, size_t n)
00312 {
00313         size_t len;
00314         char *copy;
00315 
00316         len = strlen(str);
00317         if (len > n)
00318                 len = n;
00319         if (!(copy = malloc(len + 1)))
00320                 return (NULL);
00321         (void) memcpy(copy, str, len + 1);
00322         copy[len] = '\0';
00323         return (copy);
00324 }
00325 #endif /* HAVE_STRNDUP */
00326 
00327 private int32_t
00328 mprint(struct magic_set *ms, struct magic *m)
00329 {
00330         uint64_t v;
00331         int64_t t = 0;
00332         char buf[512];
00333         union VALUETYPE *p = &ms->ms_value;
00334 
00335         switch (m->type) {
00336         case FILE_BYTE:
00337                 v = file_signextend(ms, m, (uint64_t)p->b);
00338                 switch (check_fmt(ms, m)) {
00339                 case -1:
00340                         return -1;
00341                 case 1:
00342                         if (snprintf(buf, sizeof(buf), "%c",
00343                             (unsigned char)v) < 0)
00344                                 return -1;
00345                         if (file_printf(ms, m->desc, buf) == -1)
00346                                 return -1;
00347                         /*@innerbreak@*/ break;
00348                 default:
00349                 if (file_printf(ms, m->desc, (unsigned char) v) == -1)
00350                         return -1;
00351                         /*@innerbreak@*/ break;
00352                 }
00353                 t = ms->offset + sizeof(char);
00354                 break;
00355 
00356         case FILE_SHORT:
00357         case FILE_BESHORT:
00358         case FILE_LESHORT:
00359                 v = file_signextend(ms, m, (uint64_t)p->h);
00360                 switch (check_fmt(ms, m)) {
00361                 case -1:
00362                         return -1;
00363                 case 1:
00364                         if (snprintf(buf, sizeof(buf), "%hu",
00365                             (unsigned short)v) < 0)
00366                                 return -1;
00367                         if (file_printf(ms, m->desc, buf) == -1)
00368                                 return -1;
00369                         /*@innerbreak@*/ break;
00370                 default:
00371                 if (file_printf(ms, m->desc, (unsigned short) v) == -1)
00372                         return -1;
00373                         /*@innerbreak@*/ break;
00374                 }
00375                 t = ms->offset + sizeof(short);
00376                 break;
00377 
00378         case FILE_LONG:
00379         case FILE_BELONG:
00380         case FILE_LELONG:
00381         case FILE_MELONG:
00382                 v = file_signextend(ms, m, (uint64_t)p->l);
00383                 switch (check_fmt(ms, m)) {
00384                 case -1:
00385                         return -1;
00386                 case 1:
00387                         if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0)
00388                                 return -1;
00389                         if (file_printf(ms, m->desc, buf) == -1)
00390                                 return -1;
00391                         /*@innerbreak@*/ break;
00392                 default:
00393                 if (file_printf(ms, m->desc, (uint32_t) v) == -1)
00394                         return -1;
00395                         /*@innerbreak@*/ break;
00396                 }
00397                 t = ms->offset + sizeof(int32_t);
00398                 break;
00399 
00400         case FILE_QUAD:
00401         case FILE_BEQUAD:
00402         case FILE_LEQUAD:
00403                 v = file_signextend(ms, m, p->q);
00404                 if (file_printf(ms, m->desc, (uint64_t) v) == -1)
00405                         return -1;
00406                 t = ms->offset + sizeof(int64_t);
00407                 break;
00408 
00409         case FILE_STRING:
00410         case FILE_PSTRING:
00411         case FILE_BESTRING16:
00412         case FILE_LESTRING16:
00413                 if (m->reln == '=' || m->reln == '!') {
00414                         if (file_printf(ms, m->desc, m->value.s) == -1)
00415                                 return -1;
00416                         t = ms->offset + m->vallen;
00417                 }
00418                 else {
00419                         if (*m->value.s == '\0') {
00420                                 char *cp = strchr(p->s,'\n');
00421                                 if (cp)
00422                                         *cp = '\0';
00423                         }
00424                         if (file_printf(ms, m->desc, p->s) == -1)
00425                                 return -1;
00426                         t = ms->offset + strlen(p->s);
00427                 }
00428                 break;
00429 
00430         case FILE_DATE:
00431         case FILE_BEDATE:
00432         case FILE_LEDATE:
00433         case FILE_MEDATE:
00434                 if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1)
00435                         return -1;
00436                 t = ms->offset + sizeof(time_t);
00437                 break;
00438 
00439         case FILE_LDATE:
00440         case FILE_BELDATE:
00441         case FILE_LELDATE:
00442         case FILE_MELDATE:
00443                 if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1)
00444                         return -1;
00445                 t = ms->offset + sizeof(time_t);
00446                 break;
00447 
00448         case FILE_QDATE:
00449         case FILE_BEQDATE:
00450         case FILE_LEQDATE:
00451                 if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1))
00452                     == -1)
00453                         return -1;
00454                 t = ms->offset + sizeof(uint64_t);
00455                 break;
00456 
00457         case FILE_QLDATE:
00458         case FILE_BEQLDATE:
00459         case FILE_LEQLDATE:
00460                 if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0))
00461                     == -1)
00462                         return -1;
00463                 t = ms->offset + sizeof(uint64_t);
00464                 break;
00465 
00466         case FILE_REGEX: {
00467                 char *cp;
00468                 int rval;
00469 
00470                 cp = strndup((const char *)ms->search.s, ms->search.rm_len);
00471                 if (cp == NULL) {
00472                         file_oomem(ms, ms->search.rm_len);
00473                         return -1;
00474                 }
00475                 rval = file_printf(ms, m->desc, cp);
00476                 free(cp);
00477 
00478                 if (rval == -1)
00479                         return -1;
00480 
00481                 if ((m->str_flags & REGEX_OFFSET_START))
00482                         t = ms->search.offset;
00483                 else
00484                         t = ms->search.offset + ms->search.rm_len;
00485                 break;
00486         }
00487 
00488         case FILE_SEARCH:
00489                 if (file_printf(ms, m->desc, m->value.s) == -1)
00490                         return -1;
00491                 if ((m->str_flags & REGEX_OFFSET_START))
00492                         t = ms->search.offset;
00493                 else
00494                         t = ms->search.offset + m->vallen;
00495                 break;
00496 
00497         case FILE_DEFAULT:
00498                 if (file_printf(ms, m->desc, m->value.s) == -1)
00499                         return -1;
00500                 t = ms->offset;
00501                 break;
00502 
00503         default:
00504                 file_magerror(ms, "invalid m->type (%d) in mprint()", m->type);
00505                 return -1;
00506         }
00507         return(t);
00508 }
00509 
00510 
00511 #define DO_CVT(fld, cast) \
00512         if (m->num_mask) \
00513                 switch (m->mask_op & FILE_OPS_MASK) { \
00514                 case FILE_OPAND: \
00515                         p->fld &= cast m->num_mask; \
00516                         break; \
00517                 case FILE_OPOR: \
00518                         p->fld |= cast m->num_mask; \
00519                         break; \
00520                 case FILE_OPXOR: \
00521                         p->fld ^= cast m->num_mask; \
00522                         break; \
00523                 case FILE_OPADD: \
00524                         p->fld += cast m->num_mask; \
00525                         break; \
00526                 case FILE_OPMINUS: \
00527                         p->fld -= cast m->num_mask; \
00528                         break; \
00529                 case FILE_OPMULTIPLY: \
00530                         p->fld *= cast m->num_mask; \
00531                         break; \
00532                 case FILE_OPDIVIDE: \
00533                         p->fld /= cast m->num_mask; \
00534                         break; \
00535                 case FILE_OPMODULO: \
00536                         p->fld %= cast m->num_mask; \
00537                         break; \
00538                 } \
00539         if (m->mask_op & FILE_OPINVERSE) \
00540                 p->fld = ~p->fld \
00541 
00542 private void
00543 cvt_8(union VALUETYPE *p, const struct magic *m)
00544 {
00545         DO_CVT(b, (uint8_t));
00546 }
00547 
00548 private void
00549 cvt_16(union VALUETYPE *p, const struct magic *m)
00550 {
00551         DO_CVT(h, (uint16_t));
00552 }
00553 
00554 private void
00555 cvt_32(union VALUETYPE *p, const struct magic *m)
00556 {
00557         DO_CVT(l, (uint32_t));
00558 }
00559 
00560 private void
00561 cvt_64(union VALUETYPE *p, const struct magic *m)
00562 {
00563         DO_CVT(q, (uint64_t));
00564 }
00565 
00566 /*
00567  * Convert the byte order of the data we are looking at
00568  * While we're here, let's apply the mask operation
00569  * (unless you have a better idea)
00570  */
00571 private int
00572 mconvert(struct magic_set *ms, struct magic *m)
00573 {
00574         union VALUETYPE *p = &ms->ms_value;
00575 
00576         switch (m->type) {
00577         case FILE_BYTE:
00578                 cvt_8(p, m);
00579                 return 1;
00580         case FILE_SHORT:
00581                 cvt_16(p, m);
00582                 return 1;
00583         case FILE_LONG:
00584         case FILE_DATE:
00585         case FILE_LDATE:
00586                 cvt_32(p, m);
00587                 return 1;
00588         case FILE_QUAD:
00589         case FILE_QDATE:
00590         case FILE_QLDATE:
00591                 cvt_64(p, m);
00592                 return 1;
00593         case FILE_STRING:
00594         case FILE_BESTRING16:
00595         case FILE_LESTRING16: {
00596                         size_t len;
00597 
00598                         /* Null terminate and eat *trailing* return */
00599                         p->s[sizeof(p->s) - 1] = '\0';
00600                         len = strlen(p->s);
00601                         if (len-- && p->s[len] == '\n')
00602                                 p->s[len] = '\0';
00603                         return 1;
00604                 }
00605         case FILE_PSTRING: {
00606                         char *ptr1 = p->s, *ptr2 = ptr1 + 1;
00607                         size_t len = *p->s;
00608                         if (len >= sizeof(p->s))
00609                                 len = sizeof(p->s) - 1;
00610                         while (len--)
00611                                 *ptr1++ = *ptr2++;
00612                         *ptr1 = '\0';
00613                         len = strlen(p->s);
00614                         if (len-- && p->s[len] == '\n')
00615                                 p->s[len] = '\0';
00616                         return 1;
00617                 }
00618         case FILE_BESHORT:
00619                 p->h = (short)((p->hs[0]<<8)|(p->hs[1]));
00620                 cvt_16(p, m);
00621                 return 1;
00622         case FILE_BELONG:
00623         case FILE_BEDATE:
00624         case FILE_BELDATE:
00625                 p->l = (int32_t)
00626                     ((p->hl[0]<<24)|(p->hl[1]<<16)|(p->hl[2]<<8)|(p->hl[3]));
00627                 cvt_32(p, m);
00628                 return 1;
00629         case FILE_BEQUAD:
00630         case FILE_BEQDATE:
00631         case FILE_BEQLDATE:
00632                 p->q = (int64_t)
00633                     (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)|
00634                      ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)|
00635                      (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7]));
00636                 cvt_64(p, m);
00637                 return 1;
00638         case FILE_LESHORT:
00639                 p->h = (short)((p->hs[1]<<8)|(p->hs[0]));
00640                 cvt_16(p, m);
00641                 return 1;
00642         case FILE_LELONG:
00643         case FILE_LEDATE:
00644         case FILE_LELDATE:
00645                 p->l = (int32_t)
00646                     ((p->hl[3]<<24)|(p->hl[2]<<16)|(p->hl[1]<<8)|(p->hl[0]));
00647                 cvt_32(p, m);
00648                 return 1;
00649         case FILE_LEQUAD:
00650         case FILE_LEQDATE:
00651         case FILE_LEQLDATE:
00652                 p->q = (int64_t)
00653                     (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)|
00654                      ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)|
00655                      (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0]));
00656                 cvt_64(p, m);
00657                 return 1;
00658         case FILE_MELONG:
00659         case FILE_MEDATE:
00660         case FILE_MELDATE:
00661                 p->l = (int32_t)
00662                     ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2]));
00663                 cvt_32(p, m);
00664                 return 1;
00665         case FILE_REGEX:
00666         case FILE_SEARCH:
00667         case FILE_DEFAULT:
00668                 return 1;
00669         default:
00670                 file_magerror(ms, "invalid type %d in mconvert()", m->type);
00671                 return 0;
00672         }
00673 }
00674 
00675 
00676 private void
00677 mdebug(uint32_t offset, const char *str, size_t len)
00678 {
00679         (void) fprintf(stderr, "mget @%d: ", offset);
00680         file_showstr(stderr, str, len);
00681         (void) fputc('\n', stderr);
00682         (void) fputc('\n', stderr);
00683 }
00684 
00685 private int
00686 mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
00687     const unsigned char *s, uint32_t offset, size_t nbytes, size_t linecnt)
00688 {
00689         /*
00690          * Note: FILE_SEARCH and FILE_REGEX do not actually copy
00691          * anything, but setup pointers into the source
00692          */
00693         if (indir == 0) {
00694                 switch (type) {
00695                 case FILE_SEARCH:
00696                         ms->search.s = (const char *)s + offset;
00697                         ms->search.s_len = nbytes - offset;
00698                         return 0;
00699 
00700                 case FILE_REGEX: {
00701                 /*
00702                  * offset is interpreted as last line to search,
00703                  * (starting at 1), not as bytes-from start-of-file
00704                  */
00705                         const char *b;
00706                         const char *c;
00707                         const char *last;       /* end of search region */
00708                         const char *buf;        /* start of search region */
00709                         size_t lines;
00710 
00711                         if (s == NULL) {
00712                                 ms->search.s_len = 0;
00713                                 ms->search.s = NULL;
00714                                 return 0;
00715                         }
00716                         buf = (const char *)s + offset;
00717                         last = (const char *)s + nbytes;
00718                         /* mget() guarantees buf <= last */
00719                         for (lines = linecnt, b = buf;
00720                              lines && ((b = strchr(c = b, '\n')) || (b = strchr(c, '\r')));
00721                              lines--, b++) {
00722                         last = b;
00723                                 if (b[0] == '\r' && b[1] == '\n')
00724                                         b++;
00725                 }
00726                         if (lines)
00727                                 last = (const char *)s + nbytes;
00728                         
00729                         ms->search.s = buf;
00730                         ms->search.s_len = last - buf;
00731                         ms->search.offset = offset;
00732                         ms->search.rm_len = 0;
00733                 return 0;
00734         }
00735                 case FILE_BESTRING16:
00736                 case FILE_LESTRING16: {
00737                 const unsigned char *src = s + offset;
00738                 const unsigned char *esrc = s + nbytes;
00739                         char *dst = p->s;
00740                         char *edst = &p->s[sizeof(p->s) - 1];
00741 
00742                 if (type == FILE_BESTRING16)
00743                         src++;
00744 
00745                         /* check for pointer overflow */
00746                         if (src < s) {
00747                                 file_magerror(ms, "invalid offset %zu in mcopy()",
00748                                     offset);
00749                                 return -1;
00750                         }
00751                         for (/*EMPTY*/; src < esrc; src++, dst++) {
00752                         if (dst < edst)
00753                                 *dst = *src++;
00754                         else
00755                                         /*@loopbreak@*/ break;
00756                         if (*dst == '\0')
00757                                 *dst = ' ';
00758                 }
00759                 *edst = '\0';
00760                 return 0;
00761         }
00762                 case FILE_STRING:       /* XXX - these two should not need */
00763                 case FILE_PSTRING:      /* to copy anything, but do anyway. */
00764                 default:
00765                         break;
00766                 }
00767         }
00768 
00769         if (offset >= nbytes) {
00770                 (void)memset(p, '\0', sizeof(*p));
00771                 return 0;
00772         }
00773         if (nbytes - offset < sizeof(*p))
00774                 nbytes = nbytes - offset;
00775         else
00776                 nbytes = sizeof(*p);
00777 
00778         (void)memcpy(p, s + offset, nbytes);
00779 
00780         /*
00781          * the usefulness of padding with zeroes eludes me, it
00782          * might even cause problems
00783          */
00784         if (nbytes < sizeof(*p))
00785                 (void)memset(((char *)(void *)p) + nbytes, '\0',
00786                     sizeof(*p) - nbytes);
00787         return 0;
00788 }
00789 
00790 private int
00791 mget(struct magic_set *ms, const unsigned char *s,
00792     struct magic *m, size_t nbytes, unsigned int cont_level)
00793 {
00794         uint32_t offset = ms->offset;
00795         uint32_t count = m->str_count;
00796         union VALUETYPE *p = &ms->ms_value;
00797 
00798         if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
00799                 return -1;
00800 
00801         if ((ms->flags & MAGIC_DEBUG) != 0) {
00802                 mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
00803                 file_mdump(m);
00804         }
00805 
00806         if (m->flag & INDIR) {
00807                 int off = m->in_offset;
00808                 if (m->in_op & FILE_OPINDIRECT) {
00809                         const union VALUETYPE *q =
00810                             ((const void *)(s + offset + off));
00811                         switch (m->in_type) {
00812                         case FILE_BYTE:
00813                                 off = q->b;
00814                                 break;
00815                         case FILE_SHORT:
00816                                 off = q->h;
00817                                 break;
00818                         case FILE_BESHORT:
00819                                 off = (short)((q->hs[0]<<8)|(q->hs[1]));
00820                                 break;
00821                         case FILE_LESHORT:
00822                                 off = (short)((q->hs[1]<<8)|(q->hs[0]));
00823                                 break;
00824                         case FILE_LONG:
00825                                 off = q->l;
00826                                 break;
00827                         case FILE_BELONG:
00828                                 off = (int32_t)((q->hl[0]<<24)|(q->hl[1]<<16)|
00829                                                  (q->hl[2]<<8)|(q->hl[3]));
00830                                 break;
00831                         case FILE_LELONG:
00832                                 off = (int32_t)((q->hl[3]<<24)|(q->hl[2]<<16)|
00833                                                  (q->hl[1]<<8)|(q->hl[0]));
00834                                 break;
00835                         case FILE_MELONG:
00836                                 off = (int32_t)((q->hl[1]<<24)|(q->hl[0]<<16)|
00837                                                  (q->hl[3]<<8)|(q->hl[2]));
00838                                 break;
00839                         }
00840                 }
00841                 switch (m->in_type) {
00842                 case FILE_BYTE:
00843                         if (nbytes < (offset + 1))
00844                                 return 0;
00845                         if (off) {
00846                                 switch (m->in_op & FILE_OPS_MASK) {
00847                                 case FILE_OPAND:
00848                                         offset = p->b & off;
00849                                         /*@innerbreak@*/ break;
00850                                 case FILE_OPOR:
00851                                         offset = p->b | off;
00852                                         /*@innerbreak@*/ break;
00853                                 case FILE_OPXOR:
00854                                         offset = p->b ^ off;
00855                                         /*@innerbreak@*/ break;
00856                                 case FILE_OPADD:
00857                                         offset = p->b + off;
00858                                         /*@innerbreak@*/ break;
00859                                 case FILE_OPMINUS:
00860                                         offset = p->b - off;
00861                                         /*@innerbreak@*/ break;
00862                                 case FILE_OPMULTIPLY:
00863                                         offset = p->b * off;
00864                                         /*@innerbreak@*/ break;
00865                                 case FILE_OPDIVIDE:
00866                                         offset = p->b / off;
00867                                         /*@innerbreak@*/ break;
00868                                 case FILE_OPMODULO:
00869                                         offset = p->b % off;
00870                                         /*@innerbreak@*/ break;
00871                                 }
00872                         } else
00873                                 offset = p->b;
00874                         if (m->in_op & FILE_OPINVERSE)
00875                                 offset = ~offset;
00876                         break;
00877                 case FILE_BESHORT:
00878                         if (nbytes < (offset + 2))
00879                                 return 0;
00880                         if (off) {
00881                                 switch (m->in_op & FILE_OPS_MASK) {
00882                                 case FILE_OPAND:
00883                                         offset = (short)((p->hs[0]<<8)|
00884                                                          (p->hs[1])) &
00885                                                  off;
00886                                         /*@innerbreak@*/ break;
00887                                 case FILE_OPOR:
00888                                         offset = (short)((p->hs[0]<<8)|
00889                                                          (p->hs[1])) |
00890                                                  off;
00891                                         /*@innerbreak@*/ break;
00892                                 case FILE_OPXOR:
00893                                         offset = (short)((p->hs[0]<<8)|
00894                                                          (p->hs[1])) ^
00895                                                  off;
00896                                         /*@innerbreak@*/ break;
00897                                 case FILE_OPADD:
00898                                         offset = (short)((p->hs[0]<<8)|
00899                                                          (p->hs[1])) +
00900                                                  off;
00901                                         /*@innerbreak@*/ break;
00902                                 case FILE_OPMINUS:
00903                                         offset = (short)((p->hs[0]<<8)|
00904                                                          (p->hs[1])) -
00905                                                  off;
00906                                         /*@innerbreak@*/ break;
00907                                 case FILE_OPMULTIPLY:
00908                                         offset = (short)((p->hs[0]<<8)|
00909                                                          (p->hs[1])) *
00910                                                  off;
00911                                         /*@innerbreak@*/ break;
00912                                 case FILE_OPDIVIDE:
00913                                         offset = (short)((p->hs[0]<<8)|
00914                                                          (p->hs[1])) /
00915                                                  off;
00916                                         /*@innerbreak@*/ break;
00917                                 case FILE_OPMODULO:
00918                                         offset = (short)((p->hs[0]<<8)|
00919                                                          (p->hs[1])) %
00920                                                  off;
00921                                         /*@innerbreak@*/ break;
00922                                 }
00923                         } else
00924                                 offset = (short)((p->hs[0]<<8)|
00925                                                  (p->hs[1]));
00926                         if (m->in_op & FILE_OPINVERSE)
00927                                 offset = ~offset;
00928                         break;
00929                 case FILE_LESHORT:
00930                         if (nbytes < (offset + 2))
00931                                 return 0;
00932                         if (off) {
00933                                 switch (m->in_op & FILE_OPS_MASK) {
00934                                 case FILE_OPAND:
00935                                         offset = (short)((p->hs[1]<<8)|
00936                                                          (p->hs[0])) &
00937                                                  off;
00938                                         /*@innerbreak@*/ break;
00939                                 case FILE_OPOR:
00940                                         offset = (short)((p->hs[1]<<8)|
00941                                                          (p->hs[0])) |
00942                                                  off;
00943                                         /*@innerbreak@*/ break;
00944                                 case FILE_OPXOR:
00945                                         offset = (short)((p->hs[1]<<8)|
00946                                                          (p->hs[0])) ^
00947                                                  off;
00948                                         /*@innerbreak@*/ break;
00949                                 case FILE_OPADD:
00950                                         offset = (short)((p->hs[1]<<8)|
00951                                                          (p->hs[0])) +
00952                                                  off;
00953                                         /*@innerbreak@*/ break;
00954                                 case FILE_OPMINUS:
00955                                         offset = (short)((p->hs[1]<<8)|
00956                                                          (p->hs[0])) -
00957                                                  off;
00958                                         /*@innerbreak@*/ break;
00959                                 case FILE_OPMULTIPLY:
00960                                         offset = (short)((p->hs[1]<<8)|
00961                                                          (p->hs[0])) *
00962                                                  off;
00963                                         /*@innerbreak@*/ break;
00964                                 case FILE_OPDIVIDE:
00965                                         offset = (short)((p->hs[1]<<8)|
00966                                                          (p->hs[0])) /
00967                                                  off;
00968                                         /*@innerbreak@*/ break;
00969                                 case FILE_OPMODULO:
00970                                         offset = (short)((p->hs[1]<<8)|
00971                                                          (p->hs[0])) %
00972                                                  off;
00973                                         /*@innerbreak@*/ break;
00974                                 }
00975                         } else
00976                                 offset = (short)((p->hs[1]<<8)|
00977                                                  (p->hs[0]));
00978                         if (m->in_op & FILE_OPINVERSE)
00979                                 offset = ~offset;
00980                         break;
00981                 case FILE_SHORT:
00982                         if (nbytes < (offset + 2))
00983                                 return 0;
00984                         if (off) {
00985                                 switch (m->in_op & FILE_OPS_MASK) {
00986                                 case FILE_OPAND:
00987                                         offset = p->h & off;
00988                                         /*@innerbreak@*/ break;
00989                                 case FILE_OPOR:
00990                                         offset = p->h | off;
00991                                         /*@innerbreak@*/ break;
00992                                 case FILE_OPXOR:
00993                                         offset = p->h ^ off;
00994                                         /*@innerbreak@*/ break;
00995                                 case FILE_OPADD:
00996                                         offset = p->h + off;
00997                                         /*@innerbreak@*/ break;
00998                                 case FILE_OPMINUS:
00999                                         offset = p->h - off;
01000                                         /*@innerbreak@*/ break;
01001                                 case FILE_OPMULTIPLY:
01002                                         offset = p->h * off;
01003                                         /*@innerbreak@*/ break;
01004                                 case FILE_OPDIVIDE:
01005                                         offset = p->h / off;
01006                                         /*@innerbreak@*/ break;
01007                                 case FILE_OPMODULO:
01008                                         offset = p->h % off;
01009                                         /*@innerbreak@*/ break;
01010                                 }
01011                         }
01012                         else
01013                                 offset = p->h;
01014                         if (m->in_op & FILE_OPINVERSE)
01015                                 offset = ~offset;
01016                         break;
01017                 case FILE_BELONG:
01018                         if (nbytes < (offset + 4))
01019                                 return 0;
01020                         if (off) {
01021                                 switch (m->in_op & FILE_OPS_MASK) {
01022                                 case FILE_OPAND:
01023                                         offset = (int32_t)((p->hl[0]<<24)|
01024                                                          (p->hl[1]<<16)|
01025                                                          (p->hl[2]<<8)|
01026                                                          (p->hl[3])) &
01027                                                  off;
01028                                         /*@innerbreak@*/ break;
01029                                 case FILE_OPOR:
01030                                         offset = (int32_t)((p->hl[0]<<24)|
01031                                                          (p->hl[1]<<16)|
01032                                                          (p->hl[2]<<8)|
01033                                                          (p->hl[3])) |
01034                                                  off;
01035                                         /*@innerbreak@*/ break;
01036                                 case FILE_OPXOR:
01037                                         offset = (int32_t)((p->hl[0]<<24)|
01038                                                          (p->hl[1]<<16)|
01039                                                          (p->hl[2]<<8)|
01040                                                          (p->hl[3])) ^
01041                                                  off;
01042                                         /*@innerbreak@*/ break;
01043                                 case FILE_OPADD:
01044                                         offset = (int32_t)((p->hl[0]<<24)|
01045                                                          (p->hl[1]<<16)|
01046                                                          (p->hl[2]<<8)|
01047                                                          (p->hl[3])) +
01048                                                  off;
01049                                         /*@innerbreak@*/ break;
01050                                 case FILE_OPMINUS:
01051                                         offset = (int32_t)((p->hl[0]<<24)|
01052                                                          (p->hl[1]<<16)|
01053                                                          (p->hl[2]<<8)|
01054                                                          (p->hl[3])) -
01055                                                  off;
01056                                         /*@innerbreak@*/ break;
01057                                 case FILE_OPMULTIPLY:
01058                                         offset = (int32_t)((p->hl[0]<<24)|
01059                                                          (p->hl[1]<<16)|
01060                                                          (p->hl[2]<<8)|
01061                                                          (p->hl[3])) *
01062                                                  off;
01063                                         /*@innerbreak@*/ break;
01064                                 case FILE_OPDIVIDE:
01065                                         offset = (int32_t)((p->hl[0]<<24)|
01066                                                          (p->hl[1]<<16)|
01067                                                          (p->hl[2]<<8)|
01068                                                          (p->hl[3])) /
01069                                                  off;
01070                                         /*@innerbreak@*/ break;
01071                                 case FILE_OPMODULO:
01072                                         offset = (int32_t)((p->hl[0]<<24)|
01073                                                          (p->hl[1]<<16)|
01074                                                          (p->hl[2]<<8)|
01075                                                          (p->hl[3])) %
01076                                                  off;
01077                                         /*@innerbreak@*/ break;
01078                                 }
01079                         } else
01080                                 offset = (int32_t)((p->hl[0]<<24)|
01081                                                  (p->hl[1]<<16)|
01082                                                  (p->hl[2]<<8)|
01083                                                  (p->hl[3]));
01084                         if (m->in_op & FILE_OPINVERSE)
01085                                 offset = ~offset;
01086                         break;
01087                 case FILE_LELONG:
01088                         if (nbytes < (offset + 4))
01089                                 return 0;
01090                         if (off) {
01091                                 switch (m->in_op & FILE_OPS_MASK) {
01092                                 case FILE_OPAND:
01093                                         offset = (int32_t)((p->hl[3]<<24)|
01094                                                          (p->hl[2]<<16)|
01095                                                          (p->hl[1]<<8)|
01096                                                          (p->hl[0])) &
01097                                                  off;
01098                                         /*@innerbreak@*/ break;
01099                                 case FILE_OPOR:
01100                                         offset = (int32_t)((p->hl[3]<<24)|
01101                                                          (p->hl[2]<<16)|
01102                                                          (p->hl[1]<<8)|
01103                                                          (p->hl[0])) |
01104                                                  off;
01105                                         /*@innerbreak@*/ break;
01106                                 case FILE_OPXOR:
01107                                         offset = (int32_t)((p->hl[3]<<24)|
01108                                                          (p->hl[2]<<16)|
01109                                                          (p->hl[1]<<8)|
01110                                                          (p->hl[0])) ^
01111                                                  off;
01112                                         /*@innerbreak@*/ break;
01113                                 case FILE_OPADD:
01114                                         offset = (int32_t)((p->hl[3]<<24)|
01115                                                          (p->hl[2]<<16)|
01116                                                          (p->hl[1]<<8)|
01117                                                          (p->hl[0])) +
01118                                                  off;
01119                                         /*@innerbreak@*/ break;
01120                                 case FILE_OPMINUS:
01121                                         offset = (int32_t)((p->hl[3]<<24)|
01122                                                          (p->hl[2]<<16)|
01123                                                          (p->hl[1]<<8)|
01124                                                          (p->hl[0])) -
01125                                                  off;
01126                                         /*@innerbreak@*/ break;
01127                                 case FILE_OPMULTIPLY:
01128                                         offset = (int32_t)((p->hl[3]<<24)|
01129                                                          (p->hl[2]<<16)|
01130                                                          (p->hl[1]<<8)|
01131                                                          (p->hl[0])) *
01132                                                  off;
01133                                         /*@innerbreak@*/ break;
01134                                 case FILE_OPDIVIDE:
01135                                         offset = (int32_t)((p->hl[3]<<24)|
01136                                                          (p->hl[2]<<16)|
01137                                                          (p->hl[1]<<8)|
01138                                                          (p->hl[0])) /
01139                                                  off;
01140                                         /*@innerbreak@*/ break;
01141                                 case FILE_OPMODULO:
01142                                         offset = (int32_t)((p->hl[3]<<24)|
01143                                                          (p->hl[2]<<16)|
01144                                                          (p->hl[1]<<8)|
01145                                                          (p->hl[0])) %
01146                                                  off;
01147                                         /*@innerbreak@*/ break;
01148                                 }
01149                         } else
01150                                 offset = (int32_t)((p->hl[3]<<24)|
01151                                                  (p->hl[2]<<16)|
01152                                                  (p->hl[1]<<8)|
01153                                                  (p->hl[0]));
01154                         if (m->in_op & FILE_OPINVERSE)
01155                                 offset = ~offset;
01156                         break;
01157                 case FILE_MELONG:
01158                         if (nbytes < (offset + 4))
01159                                 return 0;
01160                         if (off) {
01161                                 switch (m->in_op & FILE_OPS_MASK) {
01162                                 case FILE_OPAND:
01163                                         offset = (int32_t)((p->hl[1]<<24)|
01164                                                          (p->hl[0]<<16)|
01165                                                          (p->hl[3]<<8)|
01166                                                          (p->hl[2])) &
01167                                                  off;
01168                                         /*@innerbreak@*/ break;
01169                                 case FILE_OPOR:
01170                                         offset = (int32_t)((p->hl[1]<<24)|
01171                                                          (p->hl[0]<<16)|
01172                                                          (p->hl[3]<<8)|
01173                                                          (p->hl[2])) |
01174                                                  off;
01175                                         /*@innerbreak@*/ break;
01176                                 case FILE_OPXOR:
01177                                         offset = (int32_t)((p->hl[1]<<24)|
01178                                                          (p->hl[0]<<16)|
01179                                                          (p->hl[3]<<8)|
01180                                                          (p->hl[2])) ^
01181                                                  off;
01182                                         /*@innerbreak@*/ break;
01183                                 case FILE_OPADD:
01184                                         offset = (int32_t)((p->hl[1]<<24)|
01185                                                          (p->hl[0]<<16)|
01186                                                          (p->hl[3]<<8)|
01187                                                          (p->hl[2])) +
01188                                                  off;
01189                                         /*@innerbreak@*/ break;
01190                                 case FILE_OPMINUS:
01191                                         offset = (int32_t)((p->hl[1]<<24)|
01192                                                          (p->hl[0]<<16)|
01193                                                          (p->hl[3]<<8)|
01194                                                          (p->hl[2])) -
01195                                                  off;
01196                                         /*@innerbreak@*/ break;
01197                                 case FILE_OPMULTIPLY:
01198                                         offset = (int32_t)((p->hl[1]<<24)|
01199                                                          (p->hl[0]<<16)|
01200                                                          (p->hl[3]<<8)|
01201                                                          (p->hl[2])) *
01202                                                  off;
01203                                         /*@innerbreak@*/ break;
01204                                 case FILE_OPDIVIDE:
01205                                         offset = (int32_t)((p->hl[1]<<24)|
01206                                                          (p->hl[0]<<16)|
01207                                                          (p->hl[3]<<8)|
01208                                                          (p->hl[2])) /
01209                                                  off;
01210                                         /*@innerbreak@*/ break;
01211                                 case FILE_OPMODULO:
01212                                         offset = (int32_t)((p->hl[1]<<24)|
01213                                                          (p->hl[0]<<16)|
01214                                                          (p->hl[3]<<8)|
01215                                                          (p->hl[2])) %
01216                                                  off;
01217                                         /*@innerbreak@*/ break;
01218                                 }
01219                         } else
01220                                 offset = (int32_t)((p->hl[1]<<24)|
01221                                                  (p->hl[0]<<16)|
01222                                                  (p->hl[3]<<8)|
01223                                                  (p->hl[2]));
01224                         if (m->in_op & FILE_OPINVERSE)
01225                                 offset = ~offset;
01226                         break;
01227                 case FILE_LONG:
01228                         if (nbytes < (offset + 4))
01229                                 return 0;
01230                         if (off) {
01231                                 switch (m->in_op & FILE_OPS_MASK) {
01232                                 case FILE_OPAND:
01233                                         offset = p->l & off;
01234                                         /*@innerbreak@*/ break;
01235                                 case FILE_OPOR:
01236                                         offset = p->l | off;
01237                                         /*@innerbreak@*/ break;
01238                                 case FILE_OPXOR:
01239                                         offset = p->l ^ off;
01240                                         /*@innerbreak@*/ break;
01241                                 case FILE_OPADD:
01242                                         offset = p->l + off;
01243                                         /*@innerbreak@*/ break;
01244                                 case FILE_OPMINUS:
01245                                         offset = p->l - off;
01246                                         /*@innerbreak@*/ break;
01247                                 case FILE_OPMULTIPLY:
01248                                         offset = p->l * off;
01249                                         /*@innerbreak@*/ break;
01250                                 case FILE_OPDIVIDE:
01251                                         offset = p->l / off;
01252                                         /*@innerbreak@*/ break;
01253                                 case FILE_OPMODULO:
01254                                         offset = p->l % off;
01255                                         /*@innerbreak@*/ break;
01256                         /*      case TOOMANYSWITCHBLOCKS:
01257                          *              ugh = p->eye % m->strain;
01258                          *              rub;
01259                          *      case BEER:
01260                          *              off = p->tab & m->in_gest;
01261                          *              sleep;
01262                          */
01263                                 }
01264                         } else
01265                                 offset = p->l;
01266                         if (m->in_op & FILE_OPINVERSE)
01267                                 offset = ~offset;
01268                         break;
01269                 }
01270 
01271                 if (m->flag & INDIROFFADD)
01272                         offset += ms->c.li[cont_level-1].off;
01273                 if (mcopy(ms, p, m->type, 0, s, offset, nbytes, count) == -1)
01274                         return -1;
01275                 ms->offset = offset;
01276 
01277                 if ((ms->flags & MAGIC_DEBUG) != 0) {
01278                         mdebug(offset, (char *)(void *)p,
01279                             sizeof(union VALUETYPE));
01280                         file_mdump(m);
01281                 }
01282         }
01283 
01284         /* Verify we have enough data to match magic type */
01285         switch (m->type) {
01286                 case FILE_BYTE:
01287                         if (nbytes < (offset + 1)) /* should alway be true */
01288                                 return 0;
01289                         break;
01290 
01291                 case FILE_SHORT:
01292                 case FILE_BESHORT:
01293                 case FILE_LESHORT:
01294                         if (nbytes < (offset + 2))
01295                                 return 0;
01296                         break;
01297 
01298                 case FILE_LONG:
01299                 case FILE_BELONG:
01300                 case FILE_LELONG:
01301         case FILE_MELONG:
01302                 case FILE_DATE:
01303                 case FILE_BEDATE:
01304                 case FILE_LEDATE:
01305         case FILE_MEDATE:
01306                 case FILE_LDATE:
01307                 case FILE_BELDATE:
01308                 case FILE_LELDATE:
01309         case FILE_MELDATE:
01310                         if (nbytes < (offset + 4))
01311                                 return 0;
01312                         break;
01313 
01314                 case FILE_STRING:
01315                 case FILE_PSTRING:
01316                 case FILE_SEARCH:
01317                         if (nbytes < (offset + m->vallen))
01318                                 return 0;
01319                         break;
01320 
01321         case FILE_REGEX:
01322                 if (nbytes < offset)
01323                         return 0;
01324                 break;
01325 
01326         case FILE_DEFAULT:      /* nothing to check */
01327         default:
01328                 break;
01329                 }
01330         if (!mconvert(ms, m))
01331                 return 0;
01332         return 1;
01333 }
01334 
01335 private uint64_t
01336 file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags)
01337         /*@*/
01338 {
01339         /*
01340          * Convert the source args to unsigned here so that (1) the
01341          * compare will be unsigned as it is in strncmp() and (2) so
01342          * the ctype functions will work correctly without extra
01343          * casting.
01344          */
01345         const unsigned char *a = (const unsigned char *)s1;
01346         const unsigned char *b = (const unsigned char *)s2;
01347         uint64_t v;
01348 
01349         /*
01350          * What we want here is:
01351          * v = strncmp(m->value.s, p->s, m->vallen);
01352          * but ignoring any nulls.  bcmp doesn't give -/+/0
01353          * and isn't universally available anyway.
01354          */
01355         v = 0;
01356         if (0L == flags) { /* normal string: do it fast */
01357                 while (len-- > 0)
01358                         if ((v = *b++ - *a++) != '\0')
01359                                 break; 
01360         }
01361         else { /* combine the others */
01362                 while (len-- > 0) {
01363                         if ((flags & STRING_IGNORE_LOWERCASE) &&
01364                             islower(*a)) {
01365                                 if ((v = tolower(*b++) - *a++) != '\0')
01366                                         break;
01367                         }
01368                         else if ((flags & STRING_IGNORE_UPPERCASE) &&
01369                             isupper(*a)) {
01370                                 if ((v = toupper(*b++) - *a++) != '\0')
01371                                         break;
01372                         }
01373                         else if ((flags & STRING_COMPACT_BLANK) && 
01374                             isspace(*a)) { 
01375                                 a++;
01376                                 if (isspace(*b++)) {
01377                                         while (isspace(*b))
01378                                                 b++;
01379                                 }
01380                                 else {
01381                                         v = 1;
01382                                         break;
01383                                 }
01384                         }
01385                         else if ((flags & STRING_COMPACT_OPTIONAL_BLANK) &&
01386                             isspace(*a)) {
01387                                 a++;
01388                                 while (isspace(*b))
01389                                         b++;
01390                         }
01391                         else {
01392                                 if ((v = *b++ - *a++) != '\0')
01393                                         break;
01394                         }
01395                 }
01396         }
01397         return v;
01398         }
01399 
01400 private uint64_t
01401 file_strncmp16(const char *a, const char *b, size_t len, uint32_t flags)
01402         /*@*/
01403 {
01404         /*
01405          * XXX - The 16-bit string compare probably needs to be done
01406          * differently, especially if the flags are to be supported.
01407          * At the moment, I am unsure.
01408          */
01409         flags = 0;
01410         return file_strncmp(a, b, len, flags);
01411 }
01412 
01413 private int
01414 magiccheck(struct magic_set *ms, struct magic *m)
01415 {
01416         uint64_t l = m->value.q;
01417         uint64_t v;
01418         int matched;
01419         union VALUETYPE *p = &ms->ms_value;
01420 
01421         switch (m->type) {
01422         case FILE_BYTE:
01423                 v = p->b;
01424                 break;
01425 
01426         case FILE_SHORT:
01427         case FILE_BESHORT:
01428         case FILE_LESHORT:
01429                 v = p->h;
01430                 break;
01431 
01432         case FILE_LONG:
01433         case FILE_BELONG:
01434         case FILE_LELONG:
01435         case FILE_MELONG:
01436         case FILE_DATE:
01437         case FILE_BEDATE:
01438         case FILE_LEDATE:
01439         case FILE_MEDATE:
01440         case FILE_LDATE:
01441         case FILE_BELDATE:
01442         case FILE_LELDATE:
01443         case FILE_MELDATE:
01444                 v = p->l;
01445                 break;
01446 
01447         case FILE_QUAD:
01448         case FILE_LEQUAD:
01449         case FILE_BEQUAD:
01450         case FILE_QDATE:
01451         case FILE_BEQDATE:
01452         case FILE_LEQDATE:
01453         case FILE_QLDATE:
01454         case FILE_BEQLDATE:
01455         case FILE_LEQLDATE:
01456                 v = p->q;
01457                 break;
01458 
01459         case FILE_DEFAULT:
01460                 l = 0;
01461                 v = 0;
01462                 break;
01463 
01464         case FILE_STRING:
01465         case FILE_PSTRING:
01466                 l = 0;
01467                 v = file_strncmp(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
01468                 break;
01469 
01470         case FILE_BESTRING16:
01471         case FILE_LESTRING16:
01472                 l = 0;
01473                 v = file_strncmp16(m->value.s, p->s, (size_t)m->vallen, m->str_flags);
01474                 break;
01475 
01476         case FILE_SEARCH: { /* search ms->search.s for the string m->value.s */
01477                 size_t slen;
01478                 size_t idx;
01479 
01480                 if (ms->search.s == NULL)
01481                         return 0;
01482 
01483                 slen = MIN(m->vallen, sizeof(m->value.s));
01484                 l = 0;
01485                 v = 0;
01486                 ms->search.offset = m->offset;
01487 
01488                 for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) {
01489                         if (slen + idx > ms->search.s_len)
01490                                                 /*@loopbreak@*/ break;
01491 
01492                         v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags);
01493                         if (v == 0) {   /* found match */
01494                                 ms->search.offset = m->offset + idx;
01495                                                 /*@loopbreak@*/ break;
01496                                 }
01497                         }
01498                 break;
01499         }
01500         case FILE_REGEX: {
01501                 int rc;
01502                 regex_t rx;
01503                 char errmsg[512];
01504 
01505                 if (ms->search.s == NULL)
01506                         return 0;
01507 
01508                 l = 0;
01509                 rc = regcomp(&rx, m->value.s,
01510                     REG_EXTENDED|REG_NEWLINE|
01511                     ((m->str_flags & STRING_IGNORE_CASE) ? REG_ICASE : 0));
01512                 if (rc) {
01513                         (void) regerror(rc, &rx, errmsg, sizeof(errmsg));
01514                         file_magerror(ms, "regex error %d, (%s)",
01515                             rc, errmsg);
01516                         v = (uint64_t)-1;
01517         }
01518                 else {
01519                         regmatch_t pmatch[1];
01520 #ifndef REG_STARTEND
01521 #define REG_STARTEND    0
01522                         size_t l = ms->search.s_len - 1;
01523                         char c = ms->search.s[l];
01524                         ((char *)(intptr_t)ms->search.s)[l] = '\0';
01525 #else
01526                         pmatch[0].rm_so = 0;
01527                         pmatch[0].rm_eo = ms->search.s_len;
01528 #endif
01529                         rc = regexec(&rx, (const char *)ms->search.s,
01530                             1, pmatch, REG_STARTEND);
01531 #if REG_STARTEND == 0
01532                         ((char *)(intptr_t)ms->search.s)[l] = c;
01533 #endif
01534                         switch (rc) {
01535                         case 0:
01536                                 ms->search.s += (int)pmatch[0].rm_so;
01537                                 ms->search.offset += (size_t)pmatch[0].rm_so;
01538                                 ms->search.rm_len =
01539                                     (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so);
01540                 v = 0;
01541                                 /*@innerbreak@*/ break;
01542 
01543                         case REG_NOMATCH:
01544                                 v = 1;
01545                                 /*@innerbreak@*/ break;
01546 
01547                         default:
01548                                 (void)regerror(rc, &rx, errmsg, sizeof(errmsg));
01549                                 file_magerror(ms, "regexec error %d, (%s)",
01550                                     rc, errmsg);
01551                                 v = (uint64_t)-1;
01552                                 /*@innerbreak@*/ break;
01553                         }
01554 /*@i@*/                 regfree(&rx);
01555                 }
01556                 if (v == (uint64_t)-1)
01557                         return -1;
01558                 break;
01559         }
01560         default:
01561                 file_magerror(ms, "invalid type %d in magiccheck()", m->type);
01562                 return -1;
01563         }
01564 
01565                 v = file_signextend(ms, m, v);
01566 
01567         switch (m->reln) {
01568         case 'x':
01569                 if ((ms->flags & MAGIC_DEBUG) != 0)
01570                         (void) fprintf(stderr, "%llu == *any* = 1\n",
01571                             (unsigned long long)v);
01572                 matched = 1;
01573                 break;
01574 
01575         case '!':
01576                 matched = v != l;
01577                 if ((ms->flags & MAGIC_DEBUG) != 0)
01578                         (void) fprintf(stderr, "%llu != %llu = %d\n",
01579                             (unsigned long long)v, (unsigned long long)l,
01580                             matched);
01581                 break;
01582 
01583         case '=':
01584                 matched = v == l;
01585                 if ((ms->flags & MAGIC_DEBUG) != 0)
01586                         (void) fprintf(stderr, "%llu == %llu = %d\n",
01587                             (unsigned long long)v, (unsigned long long)l,
01588                             matched);
01589                 break;
01590 
01591         case '>':
01592                 if (m->flag & UNSIGNED) {
01593                         matched = v > l;
01594                         if ((ms->flags & MAGIC_DEBUG) != 0)
01595                                 (void) fprintf(stderr, "%llu > %llu = %d\n",
01596                                     (unsigned long long)v,
01597                                     (unsigned long long)l, matched);
01598                 }
01599                 else {
01600                         matched = (int64_t) v > (int64_t) l;
01601                         if ((ms->flags & MAGIC_DEBUG) != 0)
01602                                 (void) fprintf(stderr, "%lld > %lld = %d\n",
01603                                     (long long)v, (long long)l, matched);
01604                 }
01605                 break;
01606 
01607         case '<':
01608                 if (m->flag & UNSIGNED) {
01609                         matched = v < l;
01610                         if ((ms->flags & MAGIC_DEBUG) != 0)
01611                                 (void) fprintf(stderr, "%llu < %llu = %d\n",
01612                                     (unsigned long long)v,
01613                                     (unsigned long long)l, matched);
01614                 }
01615                 else {
01616                         matched = (int64_t) v < (int64_t) l;
01617                         if ((ms->flags & MAGIC_DEBUG) != 0)
01618                                 (void) fprintf(stderr, "%lld < %lld = %d\n",
01619                                        (long long)v, (long long)l, matched);
01620                 }
01621                 break;
01622 
01623         case '&':
01624                 matched = (v & l) == l;
01625                 if ((ms->flags & MAGIC_DEBUG) != 0)
01626                         (void) fprintf(stderr, "((%llx & %llx) == %llx) = %d\n",
01627                             (unsigned long long)v, (unsigned long long)l,
01628                             (unsigned long long)l, matched);
01629                 break;
01630 
01631         case '^':
01632                 matched = (v & l) != l;
01633                 if ((ms->flags & MAGIC_DEBUG) != 0)
01634                         (void) fprintf(stderr, "((%llx & %llx) != %llx) = %d\n",
01635                             (unsigned long long)v, (unsigned long long)l,
01636                             (unsigned long long)l, matched);
01637                 break;
01638 
01639         default:
01640                 matched = 0;
01641                 file_magerror(ms, "cannot happen: invalid relation `%c'",
01642                     m->reln);
01643                 return -1;
01644         }
01645 
01646         return matched;
01647 }
01648 
01649 private int
01650 print_sep(struct magic_set *ms, int firstline)
01651 {
01652         if (firstline)
01653                 return 0;
01654         /*
01655          * we found another match 
01656          * put a newline and '-' to do some simple formatting
01657          */
01658         return file_printf(ms, "\n- ");
01659 }

Generated on Tue Sep 4 14:26:58 2007 for rpm by  doxygen 1.4.6