X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/blobdiff_plain/e2ba133e3d3e557b0605c261be0dfaf9aa2e9ee6..96d24db91c8454b549fb47466f22b706255e93a5:/contrib/file/src/apprentice.c diff --git a/contrib/file/src/apprentice.c b/contrib/file/src/apprentice.c index f3df21fa01..fdf4b2f584 100644 --- a/contrib/file/src/apprentice.c +++ b/contrib/file/src/apprentice.c @@ -32,7 +32,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: apprentice.c,v 1.151 2009/03/18 15:19:23 christos Exp $") +FILE_RCSID("@(#)$File: apprentice.c,v 1.158 2009/10/19 13:10:20 christos Exp $") #endif /* lint */ #include "magic.h" @@ -353,12 +353,10 @@ file_apprentice(struct magic_set *ms, const char *fn, int action) int file_err, errs = -1; struct mlist *mlist; - init_file_tables(); + if ((fn = magic_getpath(fn, action)) == NULL) + return NULL; - if (fn == NULL) - fn = getenv("MAGIC"); - if (fn == NULL) - fn = MAGIC; + init_file_tables(); if ((mfn = strdup(fn)) == NULL) { file_oomem(ms, strlen(fn)); @@ -595,10 +593,20 @@ set_test_type(struct magic *mstart, struct magic *m) case FILE_REGEX: case FILE_SEARCH: #ifndef COMPILE_ONLY + if (mstart->str_flags & STRING_BINTEST) + mstart->flag |= BINTEST; + if (mstart->str_flags & STRING_TEXTTEST) + mstart->flag |= TEXTTEST; + + if (mstart->flag & (TEXTTEST|BINTEST)) + break; + /* binary test if pattern is not text */ if (file_looks_utf8(m->value.us, (size_t)m->vallen, NULL, NULL) <= 0) mstart->flag |= BINTEST; + else + mstart->flag |= TEXTTEST; #endif break; case FILE_DEFAULT: @@ -629,7 +637,9 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, (*errs)++; } else { /* read and parse this file */ - for (ms->line = 1; fgets(line, sizeof(line), f) != NULL; ms->line++) { + for (ms->line = 1; + fgets(line, CAST(int, sizeof(line)), f) != NULL; + ms->line++) { size_t len; len = strlen(line); if (len == 0) /* null line, garbage, etc */ @@ -685,6 +695,12 @@ load_1(struct magic_set *ms, int action, const char *fn, int *errs, * parse a file or directory of files * const char *fn: name of magic file or directory */ +private int +cmpstrp(const void *p1, const void *p2) +{ + return strcmp(*(char *const *)p1, *(char *const *)p2); +} + private int apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, const char *fn, int action) @@ -692,8 +708,8 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, int errs = 0; struct magic_entry *marray; uint32_t marraycount, i, mentrycount = 0, starttest; - size_t slen; - char subfn[MAXPATHLEN]; + size_t slen, files = 0, maxfiles = 0; + char subfn[MAXPATHLEN], **filearr = NULL, *mfn; struct stat st; DIR *dir; struct dirent *d; @@ -713,23 +729,43 @@ apprentice_load(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, (void)fprintf(stderr, "%s\n", usg_hdr); /* load directory or file */ - /* FIXME: Read file names and sort them to prevent - non-determinism. See Debian bug #488562. */ if (stat(fn, &st) == 0 && S_ISDIR(st.st_mode)) { dir = opendir(fn); - if (dir) { - while ((d = readdir(dir)) != NULL) { - snprintf(subfn, sizeof(subfn), "%s/%s", - fn, d->d_name); - if (stat(subfn, &st) == 0 && - S_ISREG(st.st_mode)) { - load_1(ms, action, subfn, &errs, - &marray, &marraycount); + if (!dir) { + errs++; + goto out; + } + while ((d = readdir(dir)) != NULL) { + (void)snprintf(subfn, sizeof(subfn), "%s/%s", + fn, d->d_name); + if (stat(subfn, &st) == -1 || !S_ISREG(st.st_mode)) + continue; + if ((mfn = strdup(subfn)) == NULL) { + file_oomem(ms, strlen(subfn)); + errs++; + goto out; + } + if (files >= maxfiles) { + size_t mlen; + maxfiles = (maxfiles + 1) * 2; + mlen = maxfiles * sizeof(*filearr); + if ((filearr = CAST(char **, + realloc(filearr, mlen))) == NULL) { + file_oomem(ms, mlen); + errs++; + goto out; } } - closedir(dir); - } else - errs++; + filearr[files++] = mfn; + } + closedir(dir); + qsort(filearr, files, sizeof(*filearr), cmpstrp); + for (i = 0; i < files; i++) { + load_1(ms, action, filearr[i], &errs, &marray, + &marraycount); + free(filearr[i]); + } + free(filearr); } else load_1(ms, action, fn, &errs, &marray, &marraycount); if (errs) @@ -925,14 +961,14 @@ string_modifier_check(struct magic_set *ms, struct magic *m) } break; case FILE_REGEX: - if ((m->str_flags & STRING_COMPACT_BLANK) != 0) { + if ((m->str_flags & STRING_COMPACT_WHITESPACE) != 0) { file_magwarn(ms, "'/%c' not allowed on regex\n", - CHAR_COMPACT_BLANK); + CHAR_COMPACT_WHITESPACE); return -1; } - if ((m->str_flags & STRING_COMPACT_OPTIONAL_BLANK) != 0) { + if ((m->str_flags & STRING_COMPACT_OPTIONAL_WHITESPACE) != 0) { file_magwarn(ms, "'/%c' not allowed on regex\n", - CHAR_COMPACT_OPTIONAL_BLANK); + CHAR_COMPACT_OPTIONAL_WHITESPACE); return -1; } break; @@ -1089,7 +1125,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, return -1; } me->mp = m = nm; - me->max_count = cnt; + me->max_count = CAST(uint32_t, cnt); } m = &me->mp[me->cont_count++]; (void)memset(m, 0, sizeof(*m)); @@ -1125,7 +1161,7 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, m->cont_level = 0; me->cont_count = 1; } - m->lineno = lineno; + m->lineno = CAST(uint32_t, lineno); if (*l == '&') { /* m->cont_level == 0 checked below. */ ++l; /* step over */ @@ -1298,18 +1334,19 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, file_magwarn(ms, "multiple ranges"); have_range = 1; - m->str_range = strtoul(l, &t, 0); + m->str_range = CAST(uint32_t, + strtoul(l, &t, 0)); if (m->str_range == 0) file_magwarn(ms, "zero range"); l = t - 1; break; - case CHAR_COMPACT_BLANK: - m->str_flags |= STRING_COMPACT_BLANK; + case CHAR_COMPACT_WHITESPACE: + m->str_flags |= STRING_COMPACT_WHITESPACE; break; - case CHAR_COMPACT_OPTIONAL_BLANK: + case CHAR_COMPACT_OPTIONAL_WHITESPACE: m->str_flags |= - STRING_COMPACT_OPTIONAL_BLANK; + STRING_COMPACT_OPTIONAL_WHITESPACE; break; case CHAR_IGNORE_LOWERCASE: m->str_flags |= STRING_IGNORE_LOWERCASE; @@ -1320,6 +1357,12 @@ parse(struct magic_set *ms, struct magic_entry **mentryp, uint32_t *nmentryp, case CHAR_REGEX_OFFSET_START: m->str_flags |= REGEX_OFFSET_START; break; + case CHAR_BINTEST: + m->str_flags |= STRING_BINTEST; + break; + case CHAR_TEXTTEST: + m->str_flags |= STRING_TEXTTEST; + break; default: if (ms->flags & MAGIC_CHECK) file_magwarn(ms, @@ -1511,6 +1554,7 @@ parse_apple(struct magic_set *ms, struct magic_entry *me, const char *line) || strchr("-+/.", *l)) && i < sizeof(m->apple); m->apple[i++] = *l++) continue; if (i == sizeof(m->apple) && *l) { + /* We don't need to NUL terminate here, printing handles it */ if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "APPLE type `%s' truncated %zu", line, i); @@ -1544,7 +1588,7 @@ parse_mime(struct magic_set *ms, struct magic_entry *me, const char *line) || strchr("-+/.", *l)) && i < sizeof(m->mimetype); m->mimetype[i++] = *l++) continue; if (i == sizeof(m->mimetype)) { - m->desc[sizeof(m->mimetype) - 1] = '\0'; + m->mimetype[sizeof(m->mimetype) - 1] = '\0'; if (ms->flags & MAGIC_CHECK) file_magwarn(ms, "MIME type `%s' truncated %zu", m->mimetype, i); @@ -1945,7 +1989,7 @@ getstr(struct magic_set *ms, struct magic *m, const char *s, int warn) } out: *p = '\0'; - m->vallen = p - origp; + m->vallen = CAST(unsigned char, (p - origp)); if (m->type == FILE_PSTRING) m->vallen++; return s; @@ -1977,14 +2021,15 @@ file_showstr(FILE *fp, const char *s, size_t len) char c; for (;;) { - c = *s++; if (len == ~0U) { + c = *s++; if (c == '\0') break; } else { if (len-- == 0) break; + c = *s++; } if (c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */ (void) fputc(c, fp);