diff options
Diffstat (limited to 'usr.bin/file/softmagic.c')
-rw-r--r-- | usr.bin/file/softmagic.c | 367 |
1 files changed, 278 insertions, 89 deletions
diff --git a/usr.bin/file/softmagic.c b/usr.bin/file/softmagic.c index 701ebe41646..5290b613334 100644 --- a/usr.bin/file/softmagic.c +++ b/usr.bin/file/softmagic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softmagic.c,v 1.13 2008/05/08 01:40:56 chl Exp $ */ +/* $OpenBSD: softmagic.c,v 1.14 2009/04/24 18:54:34 chl Exp $ */ /* * Copyright (c) Ian F. Darwin 1986-1995. * Software written by Ian F. Darwin and others; @@ -39,11 +39,11 @@ #ifndef lint -FILE_RCSID("@(#)$Id: softmagic.c,v 1.13 2008/05/08 01:40:56 chl Exp $") +FILE_RCSID("@(#)$Id: softmagic.c,v 1.14 2009/04/24 18:54:34 chl Exp $") #endif /* lint */ private int match(struct magic_set *, struct magic *, uint32_t, - const unsigned char *, size_t); + const unsigned char *, size_t, int); private int mget(struct magic_set *, const unsigned char *, struct magic *, size_t, unsigned int); private int magiccheck(struct magic_set *, struct magic *); @@ -59,17 +59,23 @@ private void cvt_32(union VALUETYPE *, const struct magic *); private void cvt_64(union VALUETYPE *, const struct magic *); /* + * Macro to give description string according to whether we want plain + * text or MIME type + */ +#define MAGIC_DESC ((ms->flags & MAGIC_MIME) ? m->mimetype : m->desc) + +/* * softmagic - lookup one file in parsed, in-memory copy of database * Passed the name and FILE * of one file to be typed. */ /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ protected int -file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) +file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, int mode) { struct mlist *ml; int rv; for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next) - if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes)) != 0) + if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode)) != 0) return rv; return 0; @@ -104,7 +110,7 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes) */ private int match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, - const unsigned char *s, size_t nbytes) + const unsigned char *s, size_t nbytes, int mode) { uint32_t magindex = 0; unsigned int cont_level = 0; @@ -118,17 +124,26 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, for (magindex = 0; magindex < nmagic; magindex++) { int flush; + struct magic *m = &magic[magindex]; + + if ((m->flag & BINTEST) != mode) { + /* Skip sub-tests */ + while (magic[magindex + 1].cont_level != 0 && + ++magindex < nmagic) + continue; + continue; /* Skip to next top-level test*/ + } - ms->offset = magic[magindex].offset; - ms->line = magic[magindex].lineno; + ms->offset = m->offset; + ms->line = m->lineno; /* if main entry matches, print it... */ - flush = !mget(ms, s, &magic[magindex], nbytes, cont_level); + flush = !mget(ms, s, m, nbytes, cont_level); if (flush) { - if (magic[magindex].reln == '!') + if (m->reln == '!') flush = 0; } else { - switch (magiccheck(ms, &magic[magindex])) { + switch (magiccheck(ms, m)) { case -1: return -1; case 0: @@ -153,15 +168,14 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, * If we are going to print something, we'll need to print * a blank before we print something else. */ - if (magic[magindex].desc[0]) { + if (*MAGIC_DESC) { need_separator = 1; printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; } - if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) - == -1) + if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1) return -1; /* and any continuations that match */ @@ -170,36 +184,36 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, while (magic[magindex+1].cont_level != 0 && ++magindex < nmagic) { - ms->line = magic[magindex].lineno; /* for messages */ + m = &magic[magindex]; + ms->line = m->lineno; /* for messages */ - if (cont_level < magic[magindex].cont_level) + if (cont_level < m->cont_level) continue; - if (cont_level > magic[magindex].cont_level) { + if (cont_level > m->cont_level) { /* * We're at the end of the level * "cont_level" continuations. */ - cont_level = magic[magindex].cont_level; + cont_level = m->cont_level; } - ms->offset = magic[magindex].offset; - if (magic[magindex].flag & OFFADD) { + ms->offset = m->offset; + if (m->flag & OFFADD) { ms->offset += ms->c.li[cont_level - 1].off; } #ifdef ENABLE_CONDITIONALS - if (magic[magindex].cond == COND_ELSE || - magic[magindex].cond == COND_ELIF) { + if (m->cond == COND_ELSE || + m->cond == COND_ELIF) { if (ms->c.li[cont_level].last_match == 1) continue; } #endif - flush = !mget(ms, s, &magic[magindex], nbytes, - cont_level); - if (flush && magic[magindex].reln != '!') + flush = !mget(ms, s, m, nbytes, cont_level); + if (flush && m->reln != '!') continue; - switch (flush ? 1 : magiccheck(ms, &magic[magindex])) { + switch (flush ? 1 : magiccheck(ms, m)) { case -1: return -1; case 0: @@ -211,7 +225,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, #ifdef ENABLE_CONDITIONALS ms->c.li[cont_level].last_match = 1; #endif - if (magic[magindex].type != FILE_DEFAULT) + if (m->type != FILE_DEFAULT) ms->c.li[cont_level].got_match = 1; else if (ms->c.li[cont_level].got_match) { ms->c.li[cont_level].got_match = 0; @@ -221,7 +235,7 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, * If we are going to print something, * make sure that we have a separator first. */ - if (magic[magindex].desc[0]) { + if (*MAGIC_DESC) { printed_something = 1; if (print_sep(ms, firstline) == -1) return -1; @@ -234,15 +248,15 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, */ /* space if previous printed */ if (need_separator - && (magic[magindex].nospflag == 0) - && (magic[magindex].desc[0] != '\0')) { + && ((m->flag & NOSPACE) == 0) + && *MAGIC_DESC) { if (file_printf(ms, " ") == -1) return -1; need_separator = 0; } - if ((ms->c.li[cont_level].off = mprint(ms, &magic[magindex])) == -1) + if ((ms->c.li[cont_level].off = mprint(ms, m)) == -1) return -1; - if (magic[magindex].desc[0]) + if (*MAGIC_DESC) need_separator = 1; /* @@ -255,9 +269,10 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, break; } } - firstline = 0; - if (printed_something) + if (printed_something) { + firstline = 0; returnval = 1; + } if ((ms->flags & MAGIC_CONTINUE) == 0 && printed_something) { return 1; /* don't keep searching */ } @@ -271,7 +286,7 @@ check_fmt(struct magic_set *ms, struct magic *m) regex_t rx; int rc; - if (strchr(m->desc, '%') == NULL) + if (strchr(MAGIC_DESC, '%') == NULL) return 0; rc = regcomp(&rx, "%[-0-9\\.]*s", REG_EXTENDED|REG_NOSUB); @@ -281,7 +296,7 @@ check_fmt(struct magic_set *ms, struct magic *m) file_magerror(ms, "regex error %d, (%s)", rc, errmsg); return -1; } else { - rc = regexec(&rx, m->desc, 0, 0, 0); + rc = regexec(&rx, MAGIC_DESC, 0, 0, 0); regfree(&rx); return !rc; } @@ -311,8 +326,10 @@ private int32_t mprint(struct magic_set *ms, struct magic *m) { uint64_t v; + float vf; + double vd; int64_t t = 0; - char buf[512]; + char *buf; union VALUETYPE *p = &ms->ms_value; switch (m->type) { @@ -322,14 +339,13 @@ mprint(struct magic_set *ms, struct magic *m) case -1: return -1; case 1: - if (snprintf(buf, sizeof(buf), "%c", - (unsigned char)v) < 0) + if (asprintf(&buf, "%c", (unsigned char)v) < 0) return -1; - if (file_printf(ms, m->desc, buf) == -1) + if (file_printf(ms, MAGIC_DESC, buf) == -1) return -1; break; default: - if (file_printf(ms, m->desc, (unsigned char) v) == -1) + if (file_printf(ms, MAGIC_DESC, (unsigned char) v) == -1) return -1; break; } @@ -344,14 +360,13 @@ mprint(struct magic_set *ms, struct magic *m) case -1: return -1; case 1: - if (snprintf(buf, sizeof(buf), "%hu", - (unsigned short)v) < 0) + if (asprintf(&buf, "%hu", (unsigned short)v) < 0) return -1; - if (file_printf(ms, m->desc, buf) == -1) + if (file_printf(ms, MAGIC_DESC, buf) == -1) return -1; break; default: - if (file_printf(ms, m->desc, (unsigned short) v) == -1) + if (file_printf(ms, MAGIC_DESC, (unsigned short) v) == -1) return -1; break; } @@ -367,13 +382,13 @@ mprint(struct magic_set *ms, struct magic *m) case -1: return -1; case 1: - if (snprintf(buf, sizeof(buf), "%u", (uint32_t)v) < 0) + if (asprintf(&buf, "%u", (uint32_t)v) < 0) return -1; - if (file_printf(ms, m->desc, buf) == -1) + if (file_printf(ms, MAGIC_DESC, buf) == -1) return -1; break; default: - if (file_printf(ms, m->desc, (uint32_t) v) == -1) + if (file_printf(ms, MAGIC_DESC, (uint32_t) v) == -1) return -1; break; } @@ -384,7 +399,7 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BEQUAD: case FILE_LEQUAD: v = file_signextend(ms, m, p->q); - if (file_printf(ms, m->desc, (uint64_t) v) == -1) + if (file_printf(ms, MAGIC_DESC, (uint64_t) v) == -1) return -1; t = ms->offset + sizeof(int64_t); break; @@ -394,16 +409,18 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BESTRING16: case FILE_LESTRING16: if (m->reln == '=' || m->reln == '!') { - if (file_printf(ms, m->desc, m->value.s) == -1) + if (file_printf(ms, MAGIC_DESC, m->value.s) == -1) return -1; t = ms->offset + m->vallen; } else { if (*m->value.s == '\0') p->s[strcspn(p->s, "\n")] = '\0'; - if (file_printf(ms, m->desc, p->s) == -1) + if (file_printf(ms, MAGIC_DESC, p->s) == -1) return -1; t = ms->offset + strlen(p->s); + if (m->type == FILE_PSTRING) + t++; } break; @@ -411,7 +428,7 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BEDATE: case FILE_LEDATE: case FILE_MEDATE: - if (file_printf(ms, m->desc, file_fmttime(p->l, 1)) == -1) + if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 1)) == -1) return -1; t = ms->offset + sizeof(time_t); break; @@ -420,7 +437,7 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: - if (file_printf(ms, m->desc, file_fmttime(p->l, 0)) == -1) + if (file_printf(ms, MAGIC_DESC, file_fmttime(p->l, 0)) == -1) return -1; t = ms->offset + sizeof(time_t); break; @@ -428,7 +445,7 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_QDATE: case FILE_BEQDATE: case FILE_LEQDATE: - if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 1)) + if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 1)) == -1) return -1; t = ms->offset + sizeof(uint64_t); @@ -437,12 +454,54 @@ mprint(struct magic_set *ms, struct magic *m) case FILE_QLDATE: case FILE_BEQLDATE: case FILE_LEQLDATE: - if (file_printf(ms, m->desc, file_fmttime((uint32_t)p->q, 0)) + if (file_printf(ms, MAGIC_DESC, file_fmttime((uint32_t)p->q, 0)) == -1) return -1; t = ms->offset + sizeof(uint64_t); break; + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: + vf = p->f; + switch (check_fmt(ms, m)) { + case -1: + return -1; + case 1: + if (asprintf(&buf, "%g", vf) < 0) + return -1; + if (file_printf(ms, MAGIC_DESC, buf) == -1) + return -1; + break; + default: + if (file_printf(ms, MAGIC_DESC, vf) == -1) + return -1; + break; + } + t = ms->offset + sizeof(float); + break; + + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: + vd = p->d; + switch (check_fmt(ms, m)) { + case -1: + return -1; + case 1: + if (asprintf(&buf, "%g", vd) < 0) + return -1; + if (file_printf(ms, MAGIC_DESC, buf) == -1) + return -1; + break; + default: + if (file_printf(ms, MAGIC_DESC, vd) == -1) + return -1; + break; + } + t = ms->offset + sizeof(double); + break; + case FILE_REGEX: { char *cp; int rval; @@ -452,7 +511,7 @@ mprint(struct magic_set *ms, struct magic *m) file_oomem(ms, ms->search.rm_len); return -1; } - rval = file_printf(ms, m->desc, cp); + rval = file_printf(ms, MAGIC_DESC, cp); free(cp); if (rval == -1) @@ -466,7 +525,7 @@ mprint(struct magic_set *ms, struct magic *m) } case FILE_SEARCH: - if (file_printf(ms, m->desc, m->value.s) == -1) + if (file_printf(ms, MAGIC_DESC, m->value.s) == -1) return -1; if ((m->str_flags & REGEX_OFFSET_START)) t = ms->search.offset; @@ -475,7 +534,7 @@ mprint(struct magic_set *ms, struct magic *m) break; case FILE_DEFAULT: - if (file_printf(ms, m->desc, m->value.s) == -1) + if (file_printf(ms, MAGIC_DESC, m->value.s) == -1) return -1; t = ms->offset; break; @@ -543,6 +602,35 @@ cvt_64(union VALUETYPE *p, const struct magic *m) DO_CVT(q, (uint64_t)); } +#define DO_CVT2(fld, cast) \ + if (m->num_mask) \ + switch (m->mask_op & FILE_OPS_MASK) { \ + case FILE_OPADD: \ + p->fld += cast m->num_mask; \ + break; \ + case FILE_OPMINUS: \ + p->fld -= cast m->num_mask; \ + break; \ + case FILE_OPMULTIPLY: \ + p->fld *= cast m->num_mask; \ + break; \ + case FILE_OPDIVIDE: \ + p->fld /= cast m->num_mask; \ + break; \ + } \ + +private void +cvt_float(union VALUETYPE *p, const struct magic *m) +{ + DO_CVT2(f, (float)); +} + +private void +cvt_double(union VALUETYPE *p, const struct magic *m) +{ + DO_CVT2(d, (double)); +} + /* * Convert the byte order of the data we are looking at * While we're here, let's apply the mask operation @@ -609,10 +697,11 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_BEQUAD: case FILE_BEQDATE: case FILE_BEQLDATE: - p->q = (int64_t) - (((int64_t)p->hq[0]<<56)|((int64_t)p->hq[1]<<48)| - ((int64_t)p->hq[2]<<40)|((int64_t)p->hq[3]<<32)| - (p->hq[4]<<24)|(p->hq[5]<<16)|(p->hq[6]<<8)|(p->hq[7])); + p->q = (uint64_t) + (((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| + ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| + ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| + ((uint64_t)p->hq[6]<<8)|((uint64_t)p->hq[7])); cvt_64(p, m); return 1; case FILE_LESHORT: @@ -629,10 +718,11 @@ mconvert(struct magic_set *ms, struct magic *m) case FILE_LEQUAD: case FILE_LEQDATE: case FILE_LEQLDATE: - p->q = (int64_t) - (((int64_t)p->hq[7]<<56)|((int64_t)p->hq[6]<<48)| - ((int64_t)p->hq[5]<<40)|((int64_t)p->hq[4]<<32)| - (p->hq[3]<<24)|(p->hq[2]<<16)|(p->hq[1]<<8)|(p->hq[0])); + p->q = (uint64_t) + (((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| + ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| + ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| + ((uint64_t)p->hq[1]<<8)|((uint64_t)p->hq[0])); cvt_64(p, m); return 1; case FILE_MELONG: @@ -642,6 +732,36 @@ mconvert(struct magic_set *ms, struct magic *m) ((p->hl[1]<<24)|(p->hl[0]<<16)|(p->hl[3]<<8)|(p->hl[2])); cvt_32(p, m); return 1; + case FILE_FLOAT: + cvt_float(p, m); + return 1; + case FILE_BEFLOAT: + p->l = ((uint32_t)p->hl[0]<<24)|((uint32_t)p->hl[1]<<16)| + ((uint32_t)p->hl[2]<<8) |((uint32_t)p->hl[3]); + cvt_float(p, m); + return 1; + case FILE_LEFLOAT: + p->l = ((uint32_t)p->hl[3]<<24)|((uint32_t)p->hl[2]<<16)| + ((uint32_t)p->hl[1]<<8) |((uint32_t)p->hl[0]); + cvt_float(p, m); + return 1; + case FILE_DOUBLE: + cvt_double(p, m); + return 1; + case FILE_BEDOUBLE: + p->q = ((uint64_t)p->hq[0]<<56)|((uint64_t)p->hq[1]<<48)| + ((uint64_t)p->hq[2]<<40)|((uint64_t)p->hq[3]<<32)| + ((uint64_t)p->hq[4]<<24)|((uint64_t)p->hq[5]<<16)| + ((uint64_t)p->hq[6]<<8) |((uint64_t)p->hq[7]); + cvt_double(p, m); + return 1; + case FILE_LEDOUBLE: + p->q = ((uint64_t)p->hq[7]<<56)|((uint64_t)p->hq[6]<<48)| + ((uint64_t)p->hq[5]<<40)|((uint64_t)p->hq[4]<<32)| + ((uint64_t)p->hq[3]<<24)|((uint64_t)p->hq[2]<<16)| + ((uint64_t)p->hq[1]<<8) |((uint64_t)p->hq[0]); + cvt_double(p, m); + return 1; case FILE_REGEX: case FILE_SEARCH: case FILE_DEFAULT: @@ -675,13 +795,10 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, case FILE_SEARCH: ms->search.s = (const char *)s + offset; ms->search.s_len = nbytes - offset; + ms->search.offset = offset; return 0; case FILE_REGEX: { - /* - * offset is interpreted as last line to search, - * (starting at 1), not as bytes-from start-of-file - */ const char *b; const char *c; const char *last; /* end of search region */ @@ -728,13 +845,17 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, offset); return -1; } - for (/*EMPTY*/; src < esrc; src++, dst++) { + for (/*EMPTY*/; src < esrc; src += 2, dst++) { if (dst < edst) - *dst = *src++; + *dst = *src; else break; - if (*dst == '\0') - *dst = ' '; + if (*dst == '\0') { + if (type == FILE_BESTRING16 ? + *(src - 1) != '\0' : + *(src + 1) != '\0') + *dst = ' '; + } } *edst = '\0'; return 0; @@ -772,7 +893,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, size_t nbytes, unsigned int cont_level) { uint32_t offset = ms->offset; - uint32_t count = m->str_count; + uint32_t count = m->str_range; union VALUETYPE *p = &ms->ms_value; if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1) @@ -1233,13 +1354,6 @@ mget(struct magic_set *ms, const unsigned char *s, case FILE_OPMODULO: offset = p->l % off; break; - /* case TOOMANYSWITCHBLOCKS: - * ugh = p->eye % m->strain; - * rub; - * case BEER: - * off = p->tab & m->in_gest; - * sleep; - */ } } else offset = p->l; @@ -1287,10 +1401,20 @@ mget(struct magic_set *ms, const unsigned char *s, case FILE_BELDATE: case FILE_LELDATE: case FILE_MELDATE: + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: if (nbytes < (offset + 4)) return 0; break; + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: + if (nbytes < (offset + 8)) + return 0; + break; + case FILE_STRING: case FILE_PSTRING: case FILE_SEARCH: @@ -1326,10 +1450,8 @@ file_strncmp(const char *s1, const char *s2, size_t len, uint32_t flags) uint64_t v; /* - * What we want here is: - * v = strncmp(m->value.s, p->s, m->vallen); - * but ignoring any nulls. bcmp doesn't give -/+/0 - * and isn't universally available anyway. + * What we want here is v = strncmp(s1, s2, len), + * but ignoring any nulls. */ v = 0; if (0L == flags) { /* normal string: do it fast */ @@ -1393,6 +1515,8 @@ magiccheck(struct magic_set *ms, struct magic *m) { uint64_t l = m->value.q; uint64_t v; + float fl, fv; + double dl, dv; int matched; union VALUETYPE *p = &ms->ms_value; @@ -1434,6 +1558,72 @@ magiccheck(struct magic_set *ms, struct magic *m) v = p->q; break; + case FILE_FLOAT: + case FILE_BEFLOAT: + case FILE_LEFLOAT: + fl = m->value.f; + fv = p->f; + switch (m->reln) { + case 'x': + matched = 1; + break; + + case '!': + matched = fv != fl; + break; + + case '=': + matched = fv == fl; + break; + + case '>': + matched = fv > fl; + break; + + case '<': + matched = fv < fl; + break; + + default: + matched = 0; + file_magerror(ms, "cannot happen with float: invalid relation `%c'", m->reln); + return -1; + } + return matched; + + case FILE_DOUBLE: + case FILE_BEDOUBLE: + case FILE_LEDOUBLE: + dl = m->value.d; + dv = p->d; + switch (m->reln) { + case 'x': + matched = 1; + break; + + case '!': + matched = dv != dl; + break; + + case '=': + matched = dv == dl; + break; + + case '>': + matched = dv > dl; + break; + + case '<': + matched = dv < dl; + break; + + default: + matched = 0; + file_magerror(ms, "cannot happen with double: invalid relation `%c'", m->reln); + return -1; + } + return matched; + case FILE_DEFAULT: l = 0; v = 0; @@ -1461,15 +1651,14 @@ magiccheck(struct magic_set *ms, struct magic *m) slen = MIN(m->vallen, sizeof(m->value.s)); l = 0; v = 0; - ms->search.offset = m->offset; - for (idx = 0; m->str_count == 0 || idx < m->str_count; idx++) { + for (idx = 0; m->str_range == 0 || idx < m->str_range; idx++) { if (slen + idx > ms->search.s_len) break; v = file_strncmp(m->value.s, ms->search.s + idx, slen, m->str_flags); if (v == 0) { /* found match */ - ms->search.offset = m->offset + idx; + ms->search.offset += idx; break; } } |