1/* 2 * Copyright (c) Ian F. Darwin 1986-1995. 3 * Software written by Ian F. Darwin and others; 4 * maintained 1995-present by Christos Zoulas and others. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice immediately at the beginning of the file, without modification, 11 * this list of conditions, and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution.
| 1/* 2 * Copyright (c) Ian F. Darwin 1986-1995. 3 * Software written by Ian F. Darwin and others; 4 * maintained 1995-present by Christos Zoulas and others. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice immediately at the beginning of the file, without modification, 11 * this list of conditions, and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution.
|
15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Ian F. Darwin and others. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission.
| |
20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33/* 34 * apprentice - make one pass through /etc/magic, learning its secrets. 35 */ 36 37#include "file.h" 38#include "magic.h" 39#include <stdlib.h> 40#ifdef HAVE_UNISTD_H 41#include <unistd.h> 42#endif 43#include <string.h> 44#include <ctype.h> 45#include <fcntl.h> 46#include <sys/stat.h> 47#include <sys/param.h> 48#ifdef QUICK 49#include <sys/mman.h> 50#endif 51 52#ifndef lint
| 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28/* 29 * apprentice - make one pass through /etc/magic, learning its secrets. 30 */ 31 32#include "file.h" 33#include "magic.h" 34#include <stdlib.h> 35#ifdef HAVE_UNISTD_H 36#include <unistd.h> 37#endif 38#include <string.h> 39#include <ctype.h> 40#include <fcntl.h> 41#include <sys/stat.h> 42#include <sys/param.h> 43#ifdef QUICK 44#include <sys/mman.h> 45#endif 46 47#ifndef lint
|
53FILE_RCSID("@(#)$Id: apprentice.c,v 1.78 2004/07/24 20:38:56 christos Exp $")
| 48FILE_RCSID("@(#)$Id: apprentice.c,v 1.82 2004/11/24 18:56:04 christos Exp $")
|
54#endif /* lint */ 55 56#define EATAB {while (isascii((unsigned char) *l) && \ 57 isspace((unsigned char) *l)) ++l;} 58#define LOWCASE(l) (isupper((unsigned char) (l)) ? \ 59 tolower((unsigned char) (l)) : (l)) 60/* 61 * Work around a bug in headers on Digital Unix. 62 * At least confirmed for: OSF1 V4.0 878 63 */ 64#if defined(__osf__) && defined(__DECC) 65#ifdef MAP_FAILED 66#undef MAP_FAILED 67#endif 68#endif 69 70#ifndef MAP_FAILED 71#define MAP_FAILED (void *) -1 72#endif 73 74#ifndef MAP_FILE 75#define MAP_FILE 0 76#endif 77 78#ifndef MAXPATHLEN 79#define MAXPATHLEN 1024 80#endif 81
| 49#endif /* lint */ 50 51#define EATAB {while (isascii((unsigned char) *l) && \ 52 isspace((unsigned char) *l)) ++l;} 53#define LOWCASE(l) (isupper((unsigned char) (l)) ? \ 54 tolower((unsigned char) (l)) : (l)) 55/* 56 * Work around a bug in headers on Digital Unix. 57 * At least confirmed for: OSF1 V4.0 878 58 */ 59#if defined(__osf__) && defined(__DECC) 60#ifdef MAP_FAILED 61#undef MAP_FAILED 62#endif 63#endif 64 65#ifndef MAP_FAILED 66#define MAP_FAILED (void *) -1 67#endif 68 69#ifndef MAP_FILE 70#define MAP_FILE 0 71#endif 72 73#ifndef MAXPATHLEN 74#define MAXPATHLEN 1024 75#endif 76
|
| 77#define IS_STRING(t) ((t) == FILE_STRING || (t) == FILE_PSTRING || \ 78 (t) == FILE_BESTRING16 || (t) == FILE_LESTRING16) 79
|
82private int getvalue(struct magic_set *ms, struct magic *, char **); 83private int hextoint(int); 84private char *getstr(struct magic_set *, char *, char *, int, int *); 85private int parse(struct magic_set *, struct magic **, uint32_t *, char *, int); 86private void eatsize(char **); 87private int apprentice_1(struct magic_set *, const char *, int, struct mlist *); 88private int apprentice_file(struct magic_set *, struct magic **, uint32_t *, 89 const char *, int); 90private void byteswap(struct magic *, uint32_t); 91private void bs1(struct magic *); 92private uint16_t swap2(uint16_t); 93private uint32_t swap4(uint32_t);
| 80private int getvalue(struct magic_set *ms, struct magic *, char **); 81private int hextoint(int); 82private char *getstr(struct magic_set *, char *, char *, int, int *); 83private int parse(struct magic_set *, struct magic **, uint32_t *, char *, int); 84private void eatsize(char **); 85private int apprentice_1(struct magic_set *, const char *, int, struct mlist *); 86private int apprentice_file(struct magic_set *, struct magic **, uint32_t *, 87 const char *, int); 88private void byteswap(struct magic *, uint32_t); 89private void bs1(struct magic *); 90private uint16_t swap2(uint16_t); 91private uint32_t swap4(uint32_t);
|
94private char *mkdbname(const char *, char *, size_t);
| 92private char *mkdbname(const char *, char *, size_t, int);
|
95private int apprentice_map(struct magic_set *, struct magic **, uint32_t *, 96 const char *); 97private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *, 98 const char *);
| 93private int apprentice_map(struct magic_set *, struct magic **, uint32_t *, 94 const char *); 95private int apprentice_compile(struct magic_set *, struct magic **, uint32_t *, 96 const char *);
|
99private int check_format(struct magic *);
| 97private int check_format(struct magic_set *, struct magic *);
|
100 101private size_t maxmagic = 0; 102private size_t magicsize = sizeof(struct magic); 103 104#ifdef COMPILE_ONLY 105 106int main(int, char *[]); 107 108int 109main(int argc, char *argv[]) 110{ 111 int ret; 112 struct magic_set *ms; 113 char *progname; 114 115 if ((progname = strrchr(argv[0], '/')) != NULL) 116 progname++; 117 else 118 progname = argv[0]; 119 120 if (argc != 2) { 121 (void)fprintf(stderr, "Usage: %s file\n", progname); 122 return 1; 123 } 124 125 if ((ms = magic_open(MAGIC_CHECK)) == NULL) { 126 (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno)); 127 return 1; 128 } 129 ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0; 130 if (ret == 1) 131 (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms)); 132 magic_close(ms); 133 return ret; 134} 135#endif /* COMPILE_ONLY */ 136 137 138/* 139 * Handle one file. 140 */ 141private int 142apprentice_1(struct magic_set *ms, const char *fn, int action, 143 struct mlist *mlist) 144{ 145 struct magic *magic = NULL; 146 uint32_t nmagic = 0; 147 struct mlist *ml; 148 int rv = -1; 149 int mapped; 150 151 if (magicsize != FILE_MAGICSIZE) { 152 file_error(ms, 0, "magic element size %lu != %lu", 153 (unsigned long)sizeof(*magic), 154 (unsigned long)FILE_MAGICSIZE); 155 return -1; 156 } 157 158 if (action == FILE_COMPILE) { 159 rv = apprentice_file(ms, &magic, &nmagic, fn, action); 160 if (rv != 0) 161 return -1; 162 rv = apprentice_compile(ms, &magic, &nmagic, fn); 163 free(magic); 164 return rv; 165 } 166#ifndef COMPILE_ONLY 167 if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) { 168 if (ms->flags & MAGIC_CHECK)
| 98 99private size_t maxmagic = 0; 100private size_t magicsize = sizeof(struct magic); 101 102#ifdef COMPILE_ONLY 103 104int main(int, char *[]); 105 106int 107main(int argc, char *argv[]) 108{ 109 int ret; 110 struct magic_set *ms; 111 char *progname; 112 113 if ((progname = strrchr(argv[0], '/')) != NULL) 114 progname++; 115 else 116 progname = argv[0]; 117 118 if (argc != 2) { 119 (void)fprintf(stderr, "Usage: %s file\n", progname); 120 return 1; 121 } 122 123 if ((ms = magic_open(MAGIC_CHECK)) == NULL) { 124 (void)fprintf(stderr, "%s: %s\n", progname, strerror(errno)); 125 return 1; 126 } 127 ret = magic_compile(ms, argv[1]) == -1 ? 1 : 0; 128 if (ret == 1) 129 (void)fprintf(stderr, "%s: %s\n", progname, magic_error(ms)); 130 magic_close(ms); 131 return ret; 132} 133#endif /* COMPILE_ONLY */ 134 135 136/* 137 * Handle one file. 138 */ 139private int 140apprentice_1(struct magic_set *ms, const char *fn, int action, 141 struct mlist *mlist) 142{ 143 struct magic *magic = NULL; 144 uint32_t nmagic = 0; 145 struct mlist *ml; 146 int rv = -1; 147 int mapped; 148 149 if (magicsize != FILE_MAGICSIZE) { 150 file_error(ms, 0, "magic element size %lu != %lu", 151 (unsigned long)sizeof(*magic), 152 (unsigned long)FILE_MAGICSIZE); 153 return -1; 154 } 155 156 if (action == FILE_COMPILE) { 157 rv = apprentice_file(ms, &magic, &nmagic, fn, action); 158 if (rv != 0) 159 return -1; 160 rv = apprentice_compile(ms, &magic, &nmagic, fn); 161 free(magic); 162 return rv; 163 } 164#ifndef COMPILE_ONLY 165 if ((rv = apprentice_map(ms, &magic, &nmagic, fn)) == -1) { 166 if (ms->flags & MAGIC_CHECK)
|
169 file_magwarn("using regular magic file `%s'", fn);
| 167 file_magwarn(ms, "using regular magic file `%s'", fn);
|
170 rv = apprentice_file(ms, &magic, &nmagic, fn, action); 171 if (rv != 0) 172 return -1; 173 mapped = 0; 174 } 175 176 if (rv == -1) 177 return rv; 178 mapped = rv; 179 180 if (magic == NULL || nmagic == 0) { 181 file_delmagic(magic, mapped, nmagic); 182 return -1; 183 } 184 185 if ((ml = malloc(sizeof(*ml))) == NULL) { 186 file_delmagic(magic, mapped, nmagic); 187 file_oomem(ms); 188 return -1; 189 } 190 191 ml->magic = magic; 192 ml->nmagic = nmagic; 193 ml->mapped = mapped; 194 195 mlist->prev->next = ml; 196 ml->prev = mlist->prev; 197 ml->next = mlist; 198 mlist->prev = ml; 199 200 return 0; 201#endif /* COMPILE_ONLY */ 202} 203 204protected void 205file_delmagic(struct magic *p, int type, size_t entries) 206{ 207 if (p == NULL) 208 return; 209 switch (type) { 210 case 2: 211 p--; 212 (void)munmap((void *)p, sizeof(*p) * (entries + 1)); 213 break; 214 case 1: 215 p--; 216 /*FALLTHROUGH*/ 217 case 0: 218 free(p); 219 break; 220 default: 221 abort(); 222 } 223} 224 225 226/* const char *fn: list of magic files */ 227protected struct mlist * 228file_apprentice(struct magic_set *ms, const char *fn, int action) 229{ 230 char *p, *mfn, *afn = NULL; 231 int file_err, errs = -1; 232 struct mlist *mlist; 233 234 if (fn == NULL) 235 fn = getenv("MAGIC"); 236 if (fn == NULL) 237 fn = MAGIC; 238 239 if ((fn = mfn = strdup(fn)) == NULL) { 240 file_oomem(ms); 241 return NULL; 242 } 243 244 if ((mlist = malloc(sizeof(*mlist))) == NULL) { 245 free(mfn); 246 file_oomem(ms); 247 return NULL; 248 } 249 mlist->next = mlist->prev = mlist; 250 251 while (fn) { 252 p = strchr(fn, PATHSEP); 253 if (p) 254 *p++ = '\0'; 255 if (*fn == '\0') 256 break; 257 if (ms->flags & MAGIC_MIME) { 258 if ((afn = malloc(strlen(fn) + 5 + 1)) == NULL) { 259 free(mfn); 260 free(mlist); 261 file_oomem(ms); 262 return NULL; 263 } 264 (void)strcpy(afn, fn); 265 (void)strcat(afn, ".mime"); 266 fn = afn; 267 } 268 file_err = apprentice_1(ms, fn, action, mlist); 269 if (file_err > errs) 270 errs = file_err; 271 if (afn) { 272 free(afn); 273 afn = NULL; 274 } 275 fn = p; 276 } 277 if (errs == -1) { 278 free(mfn); 279 free(mlist); 280 mlist = NULL; 281 file_error(ms, 0, "could not find any magic files!"); 282 return NULL; 283 } 284 free(mfn); 285 return mlist; 286} 287 288/* 289 * parse from a file 290 * const char *fn: name of magic file 291 */ 292private int 293apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, 294 const char *fn, int action) 295{ 296 private const char hdr[] = 297 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc"; 298 FILE *f; 299 char line[BUFSIZ+1];
| 168 rv = apprentice_file(ms, &magic, &nmagic, fn, action); 169 if (rv != 0) 170 return -1; 171 mapped = 0; 172 } 173 174 if (rv == -1) 175 return rv; 176 mapped = rv; 177 178 if (magic == NULL || nmagic == 0) { 179 file_delmagic(magic, mapped, nmagic); 180 return -1; 181 } 182 183 if ((ml = malloc(sizeof(*ml))) == NULL) { 184 file_delmagic(magic, mapped, nmagic); 185 file_oomem(ms); 186 return -1; 187 } 188 189 ml->magic = magic; 190 ml->nmagic = nmagic; 191 ml->mapped = mapped; 192 193 mlist->prev->next = ml; 194 ml->prev = mlist->prev; 195 ml->next = mlist; 196 mlist->prev = ml; 197 198 return 0; 199#endif /* COMPILE_ONLY */ 200} 201 202protected void 203file_delmagic(struct magic *p, int type, size_t entries) 204{ 205 if (p == NULL) 206 return; 207 switch (type) { 208 case 2: 209 p--; 210 (void)munmap((void *)p, sizeof(*p) * (entries + 1)); 211 break; 212 case 1: 213 p--; 214 /*FALLTHROUGH*/ 215 case 0: 216 free(p); 217 break; 218 default: 219 abort(); 220 } 221} 222 223 224/* const char *fn: list of magic files */ 225protected struct mlist * 226file_apprentice(struct magic_set *ms, const char *fn, int action) 227{ 228 char *p, *mfn, *afn = NULL; 229 int file_err, errs = -1; 230 struct mlist *mlist; 231 232 if (fn == NULL) 233 fn = getenv("MAGIC"); 234 if (fn == NULL) 235 fn = MAGIC; 236 237 if ((fn = mfn = strdup(fn)) == NULL) { 238 file_oomem(ms); 239 return NULL; 240 } 241 242 if ((mlist = malloc(sizeof(*mlist))) == NULL) { 243 free(mfn); 244 file_oomem(ms); 245 return NULL; 246 } 247 mlist->next = mlist->prev = mlist; 248 249 while (fn) { 250 p = strchr(fn, PATHSEP); 251 if (p) 252 *p++ = '\0'; 253 if (*fn == '\0') 254 break; 255 if (ms->flags & MAGIC_MIME) { 256 if ((afn = malloc(strlen(fn) + 5 + 1)) == NULL) { 257 free(mfn); 258 free(mlist); 259 file_oomem(ms); 260 return NULL; 261 } 262 (void)strcpy(afn, fn); 263 (void)strcat(afn, ".mime"); 264 fn = afn; 265 } 266 file_err = apprentice_1(ms, fn, action, mlist); 267 if (file_err > errs) 268 errs = file_err; 269 if (afn) { 270 free(afn); 271 afn = NULL; 272 } 273 fn = p; 274 } 275 if (errs == -1) { 276 free(mfn); 277 free(mlist); 278 mlist = NULL; 279 file_error(ms, 0, "could not find any magic files!"); 280 return NULL; 281 } 282 free(mfn); 283 return mlist; 284} 285 286/* 287 * parse from a file 288 * const char *fn: name of magic file 289 */ 290private int 291apprentice_file(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, 292 const char *fn, int action) 293{ 294 private const char hdr[] = 295 "cont\toffset\ttype\topcode\tmask\tvalue\tdesc"; 296 FILE *f; 297 char line[BUFSIZ+1];
|
300 int lineno;
| |
301 int errs = 0; 302
| 298 int errs = 0; 299
|
303 f = fopen(fn, "r");
| 300 f = fopen(ms->file = fn, "r");
|
304 if (f == NULL) { 305 if (errno != ENOENT) 306 file_error(ms, errno, "cannot read magic file `%s'", 307 fn); 308 return -1; 309 } 310 311 maxmagic = MAXMAGIS; 312 *magicp = (struct magic *) calloc(maxmagic, sizeof(struct magic)); 313 if (*magicp == NULL) { 314 (void)fclose(f); 315 file_oomem(ms); 316 return -1; 317 } 318 319 /* print silly verbose header for USG compat. */ 320 if (action == FILE_CHECK) 321 (void)fprintf(stderr, "%s\n", hdr); 322 323 /* parse it */
| 301 if (f == NULL) { 302 if (errno != ENOENT) 303 file_error(ms, errno, "cannot read magic file `%s'", 304 fn); 305 return -1; 306 } 307 308 maxmagic = MAXMAGIS; 309 *magicp = (struct magic *) calloc(maxmagic, sizeof(struct magic)); 310 if (*magicp == NULL) { 311 (void)fclose(f); 312 file_oomem(ms); 313 return -1; 314 } 315 316 /* print silly verbose header for USG compat. */ 317 if (action == FILE_CHECK) 318 (void)fprintf(stderr, "%s\n", hdr); 319 320 /* parse it */
|
324 for (lineno = 1; fgets(line, BUFSIZ, f) != NULL; lineno++) {
| 321 for (ms->line = 1; fgets(line, BUFSIZ, f) != NULL; ms->line++) { 322 size_t len;
|
325 if (line[0]=='#') /* comment, do not parse */ 326 continue;
| 323 if (line[0]=='#') /* comment, do not parse */ 324 continue;
|
327 if (strlen(line) <= (unsigned)1) /* null line, garbage, etc */
| 325 len = strlen(line); 326 if (len < 2) /* null line, garbage, etc */
|
328 continue;
| 327 continue;
|
329 line[strlen(line)-1] = '\0'; /* delete newline */
| 328 line[len - 1] = '\0'; /* delete newline */
|
330 if (parse(ms, magicp, nmagicp, line, action) != 0) 331 errs = 1; 332 } 333 334 (void)fclose(f); 335 if (errs) { 336 free(*magicp); 337 *magicp = NULL; 338 *nmagicp = 0; 339 } 340 return errs; 341} 342 343/* 344 * extend the sign bit if the comparison is to be signed 345 */ 346protected uint32_t 347file_signextend(struct magic_set *ms, struct magic *m, uint32_t v) 348{ 349 if (!(m->flag & UNSIGNED)) 350 switch(m->type) { 351 /* 352 * Do not remove the casts below. They are 353 * vital. When later compared with the data, 354 * the sign extension must have happened. 355 */ 356 case FILE_BYTE: 357 v = (char) v; 358 break; 359 case FILE_SHORT: 360 case FILE_BESHORT: 361 case FILE_LESHORT: 362 v = (short) v; 363 break; 364 case FILE_DATE: 365 case FILE_BEDATE: 366 case FILE_LEDATE: 367 case FILE_LDATE: 368 case FILE_BELDATE: 369 case FILE_LELDATE: 370 case FILE_LONG: 371 case FILE_BELONG: 372 case FILE_LELONG: 373 v = (int32_t) v; 374 break; 375 case FILE_STRING: 376 case FILE_PSTRING:
| 329 if (parse(ms, magicp, nmagicp, line, action) != 0) 330 errs = 1; 331 } 332 333 (void)fclose(f); 334 if (errs) { 335 free(*magicp); 336 *magicp = NULL; 337 *nmagicp = 0; 338 } 339 return errs; 340} 341 342/* 343 * extend the sign bit if the comparison is to be signed 344 */ 345protected uint32_t 346file_signextend(struct magic_set *ms, struct magic *m, uint32_t v) 347{ 348 if (!(m->flag & UNSIGNED)) 349 switch(m->type) { 350 /* 351 * Do not remove the casts below. They are 352 * vital. When later compared with the data, 353 * the sign extension must have happened. 354 */ 355 case FILE_BYTE: 356 v = (char) v; 357 break; 358 case FILE_SHORT: 359 case FILE_BESHORT: 360 case FILE_LESHORT: 361 v = (short) v; 362 break; 363 case FILE_DATE: 364 case FILE_BEDATE: 365 case FILE_LEDATE: 366 case FILE_LDATE: 367 case FILE_BELDATE: 368 case FILE_LELDATE: 369 case FILE_LONG: 370 case FILE_BELONG: 371 case FILE_LELONG: 372 v = (int32_t) v; 373 break; 374 case FILE_STRING: 375 case FILE_PSTRING:
|
| 376 case FILE_BESTRING16: 377 case FILE_LESTRING16:
|
377 break; 378 case FILE_REGEX: 379 break; 380 default: 381 if (ms->flags & MAGIC_CHECK)
| 378 break; 379 case FILE_REGEX: 380 break; 381 default: 382 if (ms->flags & MAGIC_CHECK)
|
382 file_magwarn("cannot happen: m->type=%d\n",
| 383 file_magwarn(ms, "cannot happen: m->type=%d\n",
|
383 m->type); 384 return ~0U; 385 } 386 return v; 387} 388 389/* 390 * parse one line from magic file, put into magic[index++] if valid 391 */ 392private int 393parse(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, char *l, 394 int action) 395{ 396 int i = 0; 397 struct magic *m; 398 char *t; 399 private const char *fops = FILE_OPS; 400 uint32_t val; 401 402#define ALLOC_INCR 200 403 if (*nmagicp + 1 >= maxmagic){ 404 maxmagic += ALLOC_INCR; 405 if ((m = (struct magic *) realloc(*magicp, 406 sizeof(struct magic) * maxmagic)) == NULL) { 407 file_oomem(ms); 408 if (*magicp) 409 free(*magicp); 410 return -1; 411 } 412 *magicp = m; 413 memset(&(*magicp)[*nmagicp], 0, sizeof(struct magic) 414 * ALLOC_INCR); 415 } 416 m = &(*magicp)[*nmagicp]; 417 m->flag = 0; 418 m->cont_level = 0; 419 420 while (*l == '>') { 421 ++l; /* step over */ 422 m->cont_level++; 423 } 424 425 if (m->cont_level != 0 && *l == '(') { 426 ++l; /* step over */ 427 m->flag |= INDIR; 428 } 429 if (m->cont_level != 0 && *l == '&') { 430 ++l; /* step over */ 431 m->flag |= OFFADD; 432 } 433 434 /* get offset, then skip over it */ 435 m->offset = (uint32_t)strtoul(l, &t, 0); 436 if (l == t) 437 if (ms->flags & MAGIC_CHECK)
| 384 m->type); 385 return ~0U; 386 } 387 return v; 388} 389 390/* 391 * parse one line from magic file, put into magic[index++] if valid 392 */ 393private int 394parse(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, char *l, 395 int action) 396{ 397 int i = 0; 398 struct magic *m; 399 char *t; 400 private const char *fops = FILE_OPS; 401 uint32_t val; 402 403#define ALLOC_INCR 200 404 if (*nmagicp + 1 >= maxmagic){ 405 maxmagic += ALLOC_INCR; 406 if ((m = (struct magic *) realloc(*magicp, 407 sizeof(struct magic) * maxmagic)) == NULL) { 408 file_oomem(ms); 409 if (*magicp) 410 free(*magicp); 411 return -1; 412 } 413 *magicp = m; 414 memset(&(*magicp)[*nmagicp], 0, sizeof(struct magic) 415 * ALLOC_INCR); 416 } 417 m = &(*magicp)[*nmagicp]; 418 m->flag = 0; 419 m->cont_level = 0; 420 421 while (*l == '>') { 422 ++l; /* step over */ 423 m->cont_level++; 424 } 425 426 if (m->cont_level != 0 && *l == '(') { 427 ++l; /* step over */ 428 m->flag |= INDIR; 429 } 430 if (m->cont_level != 0 && *l == '&') { 431 ++l; /* step over */ 432 m->flag |= OFFADD; 433 } 434 435 /* get offset, then skip over it */ 436 m->offset = (uint32_t)strtoul(l, &t, 0); 437 if (l == t) 438 if (ms->flags & MAGIC_CHECK)
|
438 file_magwarn("offset %s invalid", l);
| 439 file_magwarn(ms, "offset `%s' invalid", l);
|
439 l = t; 440 441 if (m->flag & INDIR) { 442 m->in_type = FILE_LONG; 443 m->in_offset = 0; 444 /* 445 * read [.lbs][+-]nnnnn) 446 */ 447 if (*l == '.') { 448 l++; 449 switch (*l) { 450 case 'l': 451 m->in_type = FILE_LELONG; 452 break; 453 case 'L': 454 m->in_type = FILE_BELONG; 455 break; 456 case 'h': 457 case 's': 458 m->in_type = FILE_LESHORT; 459 break; 460 case 'H': 461 case 'S': 462 m->in_type = FILE_BESHORT; 463 break; 464 case 'c': 465 case 'b': 466 case 'C': 467 case 'B': 468 m->in_type = FILE_BYTE; 469 break; 470 default: 471 if (ms->flags & MAGIC_CHECK)
| 440 l = t; 441 442 if (m->flag & INDIR) { 443 m->in_type = FILE_LONG; 444 m->in_offset = 0; 445 /* 446 * read [.lbs][+-]nnnnn) 447 */ 448 if (*l == '.') { 449 l++; 450 switch (*l) { 451 case 'l': 452 m->in_type = FILE_LELONG; 453 break; 454 case 'L': 455 m->in_type = FILE_BELONG; 456 break; 457 case 'h': 458 case 's': 459 m->in_type = FILE_LESHORT; 460 break; 461 case 'H': 462 case 'S': 463 m->in_type = FILE_BESHORT; 464 break; 465 case 'c': 466 case 'b': 467 case 'C': 468 case 'B': 469 m->in_type = FILE_BYTE; 470 break; 471 default: 472 if (ms->flags & MAGIC_CHECK)
|
472 file_magwarn( 473 "indirect offset type %c invalid",
| 473 file_magwarn(ms, 474 "indirect offset type `%c' invalid",
|
474 *l); 475 break; 476 } 477 l++; 478 } 479 if (*l == '~') { 480 m->in_op = FILE_OPINVERSE; 481 l++; 482 } 483 switch (*l) { 484 case '&': 485 m->in_op |= FILE_OPAND; 486 l++; 487 break; 488 case '|': 489 m->in_op |= FILE_OPOR; 490 l++; 491 break; 492 case '^': 493 m->in_op |= FILE_OPXOR; 494 l++; 495 break; 496 case '+': 497 m->in_op |= FILE_OPADD; 498 l++; 499 break; 500 case '-': 501 m->in_op |= FILE_OPMINUS; 502 l++; 503 break; 504 case '*': 505 m->in_op |= FILE_OPMULTIPLY; 506 l++; 507 break; 508 case '/': 509 m->in_op |= FILE_OPDIVIDE; 510 l++; 511 break; 512 case '%': 513 m->in_op |= FILE_OPMODULO; 514 l++; 515 break; 516 } 517 if (isdigit((unsigned char)*l)) 518 m->in_offset = (uint32_t)strtoul(l, &t, 0); 519 else 520 t = l; 521 if (*t++ != ')') 522 if (ms->flags & MAGIC_CHECK)
| 475 *l); 476 break; 477 } 478 l++; 479 } 480 if (*l == '~') { 481 m->in_op = FILE_OPINVERSE; 482 l++; 483 } 484 switch (*l) { 485 case '&': 486 m->in_op |= FILE_OPAND; 487 l++; 488 break; 489 case '|': 490 m->in_op |= FILE_OPOR; 491 l++; 492 break; 493 case '^': 494 m->in_op |= FILE_OPXOR; 495 l++; 496 break; 497 case '+': 498 m->in_op |= FILE_OPADD; 499 l++; 500 break; 501 case '-': 502 m->in_op |= FILE_OPMINUS; 503 l++; 504 break; 505 case '*': 506 m->in_op |= FILE_OPMULTIPLY; 507 l++; 508 break; 509 case '/': 510 m->in_op |= FILE_OPDIVIDE; 511 l++; 512 break; 513 case '%': 514 m->in_op |= FILE_OPMODULO; 515 l++; 516 break; 517 } 518 if (isdigit((unsigned char)*l)) 519 m->in_offset = (uint32_t)strtoul(l, &t, 0); 520 else 521 t = l; 522 if (*t++ != ')') 523 if (ms->flags & MAGIC_CHECK)
|
523 file_magwarn("missing ')' in indirect offset");
| 524 file_magwarn(ms, 525 "missing ')' in indirect offset");
|
524 l = t; 525 } 526 527 528 while (isascii((unsigned char)*l) && isdigit((unsigned char)*l)) 529 ++l; 530 EATAB; 531 532#define NBYTE 4 533#define NSHORT 5 534#define NLONG 4 535#define NSTRING 6 536#define NDATE 4 537#define NBESHORT 7 538#define NBELONG 6 539#define NBEDATE 6 540#define NLESHORT 7 541#define NLELONG 6 542#define NLEDATE 6 543#define NPSTRING 7 544#define NLDATE 5 545#define NBELDATE 7 546#define NLELDATE 7 547#define NREGEX 5
| 526 l = t; 527 } 528 529 530 while (isascii((unsigned char)*l) && isdigit((unsigned char)*l)) 531 ++l; 532 EATAB; 533 534#define NBYTE 4 535#define NSHORT 5 536#define NLONG 4 537#define NSTRING 6 538#define NDATE 4 539#define NBESHORT 7 540#define NBELONG 6 541#define NBEDATE 6 542#define NLESHORT 7 543#define NLELONG 6 544#define NLEDATE 6 545#define NPSTRING 7 546#define NLDATE 5 547#define NBELDATE 7 548#define NLELDATE 7 549#define NREGEX 5
|
| 550#define NBESTRING16 10 551#define NLESTRING16 10
|
548 549 if (*l == 'u') { 550 ++l; 551 m->flag |= UNSIGNED; 552 } 553 554 /* get type, skip it */ 555 if (strncmp(l, "char", NBYTE)==0) { /* HP/UX compat */ 556 m->type = FILE_BYTE; 557 l += NBYTE; 558 } else if (strncmp(l, "byte", NBYTE)==0) { 559 m->type = FILE_BYTE; 560 l += NBYTE; 561 } else if (strncmp(l, "short", NSHORT)==0) { 562 m->type = FILE_SHORT; 563 l += NSHORT; 564 } else if (strncmp(l, "long", NLONG)==0) { 565 m->type = FILE_LONG; 566 l += NLONG; 567 } else if (strncmp(l, "string", NSTRING)==0) { 568 m->type = FILE_STRING; 569 l += NSTRING; 570 } else if (strncmp(l, "date", NDATE)==0) { 571 m->type = FILE_DATE; 572 l += NDATE; 573 } else if (strncmp(l, "beshort", NBESHORT)==0) { 574 m->type = FILE_BESHORT; 575 l += NBESHORT; 576 } else if (strncmp(l, "belong", NBELONG)==0) { 577 m->type = FILE_BELONG; 578 l += NBELONG; 579 } else if (strncmp(l, "bedate", NBEDATE)==0) { 580 m->type = FILE_BEDATE; 581 l += NBEDATE; 582 } else if (strncmp(l, "leshort", NLESHORT)==0) { 583 m->type = FILE_LESHORT; 584 l += NLESHORT; 585 } else if (strncmp(l, "lelong", NLELONG)==0) { 586 m->type = FILE_LELONG; 587 l += NLELONG; 588 } else if (strncmp(l, "ledate", NLEDATE)==0) { 589 m->type = FILE_LEDATE; 590 l += NLEDATE; 591 } else if (strncmp(l, "pstring", NPSTRING)==0) { 592 m->type = FILE_PSTRING; 593 l += NPSTRING; 594 } else if (strncmp(l, "ldate", NLDATE)==0) { 595 m->type = FILE_LDATE; 596 l += NLDATE; 597 } else if (strncmp(l, "beldate", NBELDATE)==0) { 598 m->type = FILE_BELDATE; 599 l += NBELDATE; 600 } else if (strncmp(l, "leldate", NLELDATE)==0) { 601 m->type = FILE_LELDATE; 602 l += NLELDATE; 603 } else if (strncmp(l, "regex", NREGEX)==0) { 604 m->type = FILE_REGEX;
| 552 553 if (*l == 'u') { 554 ++l; 555 m->flag |= UNSIGNED; 556 } 557 558 /* get type, skip it */ 559 if (strncmp(l, "char", NBYTE)==0) { /* HP/UX compat */ 560 m->type = FILE_BYTE; 561 l += NBYTE; 562 } else if (strncmp(l, "byte", NBYTE)==0) { 563 m->type = FILE_BYTE; 564 l += NBYTE; 565 } else if (strncmp(l, "short", NSHORT)==0) { 566 m->type = FILE_SHORT; 567 l += NSHORT; 568 } else if (strncmp(l, "long", NLONG)==0) { 569 m->type = FILE_LONG; 570 l += NLONG; 571 } else if (strncmp(l, "string", NSTRING)==0) { 572 m->type = FILE_STRING; 573 l += NSTRING; 574 } else if (strncmp(l, "date", NDATE)==0) { 575 m->type = FILE_DATE; 576 l += NDATE; 577 } else if (strncmp(l, "beshort", NBESHORT)==0) { 578 m->type = FILE_BESHORT; 579 l += NBESHORT; 580 } else if (strncmp(l, "belong", NBELONG)==0) { 581 m->type = FILE_BELONG; 582 l += NBELONG; 583 } else if (strncmp(l, "bedate", NBEDATE)==0) { 584 m->type = FILE_BEDATE; 585 l += NBEDATE; 586 } else if (strncmp(l, "leshort", NLESHORT)==0) { 587 m->type = FILE_LESHORT; 588 l += NLESHORT; 589 } else if (strncmp(l, "lelong", NLELONG)==0) { 590 m->type = FILE_LELONG; 591 l += NLELONG; 592 } else if (strncmp(l, "ledate", NLEDATE)==0) { 593 m->type = FILE_LEDATE; 594 l += NLEDATE; 595 } else if (strncmp(l, "pstring", NPSTRING)==0) { 596 m->type = FILE_PSTRING; 597 l += NPSTRING; 598 } else if (strncmp(l, "ldate", NLDATE)==0) { 599 m->type = FILE_LDATE; 600 l += NLDATE; 601 } else if (strncmp(l, "beldate", NBELDATE)==0) { 602 m->type = FILE_BELDATE; 603 l += NBELDATE; 604 } else if (strncmp(l, "leldate", NLELDATE)==0) { 605 m->type = FILE_LELDATE; 606 l += NLELDATE; 607 } else if (strncmp(l, "regex", NREGEX)==0) { 608 m->type = FILE_REGEX;
|
605 l += sizeof("regex");
| 609 l += NREGEX; 610 } else if (strncmp(l, "bestring16", NBESTRING16)==0) { 611 m->type = FILE_BESTRING16; 612 l += NBESTRING16; 613 } else if (strncmp(l, "lestring16", NLESTRING16)==0) { 614 m->type = FILE_LESTRING16; 615 l += NLESTRING16;
|
606 } else { 607 if (ms->flags & MAGIC_CHECK)
| 616 } else { 617 if (ms->flags & MAGIC_CHECK)
|
608 file_magwarn("type %s invalid", l);
| 618 file_magwarn(ms, "type `%s' invalid", l);
|
609 return -1; 610 } 611 /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ 612 /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */ 613 if (*l == '~') {
| 619 return -1; 620 } 621 /* New-style anding: "0 byte&0x80 =0x80 dynamically linked" */ 622 /* New and improved: ~ & | ^ + - * / % -- exciting, isn't it? */ 623 if (*l == '~') {
|
614 if (FILE_STRING != m->type && FILE_PSTRING != m->type)
| 624 if (!IS_STRING(m->type))
|
615 m->mask_op = FILE_OPINVERSE; 616 ++l; 617 } 618 if ((t = strchr(fops, *l)) != NULL) { 619 uint32_t op = (uint32_t)(t - fops);
| 625 m->mask_op = FILE_OPINVERSE; 626 ++l; 627 } 628 if ((t = strchr(fops, *l)) != NULL) { 629 uint32_t op = (uint32_t)(t - fops);
|
620 if (op != FILE_OPDIVIDE || 621 (FILE_STRING != m->type && FILE_PSTRING != m->type)) {
| 630 if (op != FILE_OPDIVIDE || !IS_STRING(m->type)) {
|
622 ++l; 623 m->mask_op |= op; 624 val = (uint32_t)strtoul(l, &l, 0); 625 m->mask = file_signextend(ms, m, val); 626 eatsize(&l); 627 } else { 628 m->mask = 0L; 629 while (!isspace((unsigned char)*++l)) { 630 switch (*l) { 631 case CHAR_IGNORE_LOWERCASE: 632 m->mask |= STRING_IGNORE_LOWERCASE; 633 break; 634 case CHAR_COMPACT_BLANK: 635 m->mask |= STRING_COMPACT_BLANK; 636 break; 637 case CHAR_COMPACT_OPTIONAL_BLANK: 638 m->mask |= 639 STRING_COMPACT_OPTIONAL_BLANK; 640 break; 641 default: 642 if (ms->flags & MAGIC_CHECK)
| 631 ++l; 632 m->mask_op |= op; 633 val = (uint32_t)strtoul(l, &l, 0); 634 m->mask = file_signextend(ms, m, val); 635 eatsize(&l); 636 } else { 637 m->mask = 0L; 638 while (!isspace((unsigned char)*++l)) { 639 switch (*l) { 640 case CHAR_IGNORE_LOWERCASE: 641 m->mask |= STRING_IGNORE_LOWERCASE; 642 break; 643 case CHAR_COMPACT_BLANK: 644 m->mask |= STRING_COMPACT_BLANK; 645 break; 646 case CHAR_COMPACT_OPTIONAL_BLANK: 647 m->mask |= 648 STRING_COMPACT_OPTIONAL_BLANK; 649 break; 650 default: 651 if (ms->flags & MAGIC_CHECK)
|
643 file_magwarn( 644 "string extension %c invalid",
| 652 file_magwarn(ms, 653 "string extension `%c' invalid",
|
645 *l); 646 return -1; 647 } 648 } 649 } 650 } 651 /* 652 * We used to set mask to all 1's here, instead let's just not do 653 * anything if mask = 0 (unless you have a better idea) 654 */ 655 EATAB; 656 657 switch (*l) { 658 case '>': 659 case '<': 660 /* Old-style anding: "0 byte &0x80 dynamically linked" */ 661 case '&': 662 case '^': 663 case '=': 664 m->reln = *l; 665 ++l; 666 if (*l == '=') { 667 /* HP compat: ignore &= etc. */ 668 ++l; 669 } 670 break; 671 case '!':
| 654 *l); 655 return -1; 656 } 657 } 658 } 659 } 660 /* 661 * We used to set mask to all 1's here, instead let's just not do 662 * anything if mask = 0 (unless you have a better idea) 663 */ 664 EATAB; 665 666 switch (*l) { 667 case '>': 668 case '<': 669 /* Old-style anding: "0 byte &0x80 dynamically linked" */ 670 case '&': 671 case '^': 672 case '=': 673 m->reln = *l; 674 ++l; 675 if (*l == '=') { 676 /* HP compat: ignore &= etc. */ 677 ++l; 678 } 679 break; 680 case '!':
|
672 if (m->type != FILE_STRING && m->type != FILE_PSTRING) {
| 681 if (!IS_STRING(m->type)) {
|
673 m->reln = *l; 674 ++l; 675 break; 676 } 677 /*FALLTHROUGH*/ 678 default: 679 if (*l == 'x' && isascii((unsigned char)l[1]) && 680 isspace((unsigned char)l[1])) { 681 m->reln = *l; 682 ++l; 683 goto GetDesc; /* Bill The Cat */ 684 } 685 m->reln = '='; 686 break; 687 } 688 EATAB; 689 690 if (getvalue(ms, m, &l)) 691 return -1; 692 /* 693 * TODO finish this macro and start using it! 694 * #define offsetcheck {if (offset > HOWMANY-1) 695 * magwarn("offset too big"); } 696 */ 697 698 /* 699 * now get last part - the description 700 */ 701GetDesc: 702 EATAB; 703 if (l[0] == '\b') { 704 ++l; 705 m->nospflag = 1; 706 } else if ((l[0] == '\\') && (l[1] == 'b')) { 707 ++l; 708 ++l; 709 m->nospflag = 1; 710 } else 711 m->nospflag = 0; 712 while ((m->desc[i++] = *l++) != '\0' && i < MAXDESC) 713 /* NULLBODY */; 714 715 if (ms->flags & MAGIC_CHECK) {
| 682 m->reln = *l; 683 ++l; 684 break; 685 } 686 /*FALLTHROUGH*/ 687 default: 688 if (*l == 'x' && isascii((unsigned char)l[1]) && 689 isspace((unsigned char)l[1])) { 690 m->reln = *l; 691 ++l; 692 goto GetDesc; /* Bill The Cat */ 693 } 694 m->reln = '='; 695 break; 696 } 697 EATAB; 698 699 if (getvalue(ms, m, &l)) 700 return -1; 701 /* 702 * TODO finish this macro and start using it! 703 * #define offsetcheck {if (offset > HOWMANY-1) 704 * magwarn("offset too big"); } 705 */ 706 707 /* 708 * now get last part - the description 709 */ 710GetDesc: 711 EATAB; 712 if (l[0] == '\b') { 713 ++l; 714 m->nospflag = 1; 715 } else if ((l[0] == '\\') && (l[1] == 'b')) { 716 ++l; 717 ++l; 718 m->nospflag = 1; 719 } else 720 m->nospflag = 0; 721 while ((m->desc[i++] = *l++) != '\0' && i < MAXDESC) 722 /* NULLBODY */; 723 724 if (ms->flags & MAGIC_CHECK) {
|
716 if (!check_format(m))
| 725 if (!check_format(ms, m))
|
717 return -1; 718 } 719#ifndef COMPILE_ONLY 720 if (action == FILE_CHECK) { 721 file_mdump(m); 722 } 723#endif 724 ++(*nmagicp); /* make room for next */ 725 return 0; 726} 727 728/* 729 * Check that the optional printf format in description matches 730 * the type of the magic. 731 */ 732private int
| 726 return -1; 727 } 728#ifndef COMPILE_ONLY 729 if (action == FILE_CHECK) { 730 file_mdump(m); 731 } 732#endif 733 ++(*nmagicp); /* make room for next */ 734 return 0; 735} 736 737/* 738 * Check that the optional printf format in description matches 739 * the type of the magic. 740 */ 741private int
|
733check_format(struct magic *m)
| 742check_format(struct magic_set *ms, struct magic *m)
|
734{ 735 static const char *formats[] = { FILE_FORMAT_STRING }; 736 static const char *names[] = { FILE_FORMAT_NAME }; 737 char *ptr; 738 739 for (ptr = m->desc; *ptr; ptr++) 740 if (*ptr == '%') 741 break; 742 if (*ptr == '\0') { 743 /* No format string; ok */ 744 return 1; 745 } 746 if (m->type >= sizeof(formats)/sizeof(formats[0])) {
| 743{ 744 static const char *formats[] = { FILE_FORMAT_STRING }; 745 static const char *names[] = { FILE_FORMAT_NAME }; 746 char *ptr; 747 748 for (ptr = m->desc; *ptr; ptr++) 749 if (*ptr == '%') 750 break; 751 if (*ptr == '\0') { 752 /* No format string; ok */ 753 return 1; 754 } 755 if (m->type >= sizeof(formats)/sizeof(formats[0])) {
|
747 file_magwarn("Internal error inconsistency between m->type"
| 756 file_magwarn(ms, "Internal error inconsistency between m->type"
|
748 " and format strings"); 749 return 0; 750 } 751 if (formats[m->type] == NULL) {
| 757 " and format strings"); 758 return 0; 759 } 760 if (formats[m->type] == NULL) {
|
752 file_magwarn("No format string for `%s' with description `%s'", 753 m->desc, names[m->type]);
| 761 file_magwarn(ms, "No format string for `%s' with description " 762 "`%s'", m->desc, names[m->type]);
|
754 return 0; 755 } 756 for (; *ptr; ptr++) { 757 if (*ptr == 'l' || *ptr == 'h') { 758 /* XXX: we should really fix this one day */ 759 continue; 760 } 761 if (islower((unsigned char)*ptr) || *ptr == 'X') 762 break; 763 } 764 if (*ptr == '\0') { 765 /* Missing format string; bad */
| 763 return 0; 764 } 765 for (; *ptr; ptr++) { 766 if (*ptr == 'l' || *ptr == 'h') { 767 /* XXX: we should really fix this one day */ 768 continue; 769 } 770 if (islower((unsigned char)*ptr) || *ptr == 'X') 771 break; 772 } 773 if (*ptr == '\0') { 774 /* Missing format string; bad */
|
766 file_magwarn("Invalid format `%s' for type `%s'",
| 775 file_magwarn(ms, "Invalid format `%s' for type `%s'",
|
767 m->desc, names[m->type]); 768 return 0; 769 } 770 if (strchr(formats[m->type], *ptr) == NULL) {
| 776 m->desc, names[m->type]); 777 return 0; 778 } 779 if (strchr(formats[m->type], *ptr) == NULL) {
|
771 file_magwarn("Printf format `%c' is not valid for type `%s'"
| 780 file_magwarn(ms, "Printf format `%c' is not valid for type `%s'"
|
772 " in description `%s'", 773 *ptr, names[m->type], m->desc); 774 return 0; 775 } 776 return 1; 777} 778 779/* 780 * Read a numeric value from a pointer, into the value union of a magic 781 * pointer, according to the magic type. Update the string pointer to point 782 * just after the number read. Return 0 for success, non-zero for failure. 783 */ 784private int 785getvalue(struct magic_set *ms, struct magic *m, char **p) 786{ 787 int slen; 788 789 switch (m->type) {
| 781 " in description `%s'", 782 *ptr, names[m->type], m->desc); 783 return 0; 784 } 785 return 1; 786} 787 788/* 789 * Read a numeric value from a pointer, into the value union of a magic 790 * pointer, according to the magic type. Update the string pointer to point 791 * just after the number read. Return 0 for success, non-zero for failure. 792 */ 793private int 794getvalue(struct magic_set *ms, struct magic *m, char **p) 795{ 796 int slen; 797 798 switch (m->type) {
|
| 799 case FILE_BESTRING16: 800 case FILE_LESTRING16:
|
790 case FILE_STRING: 791 case FILE_PSTRING: 792 case FILE_REGEX: 793 *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen); 794 if (*p == NULL) { 795 if (ms->flags & MAGIC_CHECK)
| 801 case FILE_STRING: 802 case FILE_PSTRING: 803 case FILE_REGEX: 804 *p = getstr(ms, *p, m->value.s, sizeof(m->value.s), &slen); 805 if (*p == NULL) { 806 if (ms->flags & MAGIC_CHECK)
|
796 file_magwarn("cannot get string from `%s'",
| 807 file_magwarn(ms, "cannot get string from `%s'",
|
797 m->value.s); 798 return -1; 799 } 800 m->vallen = slen; 801 return 0; 802 default: 803 if (m->reln != 'x') { 804 m->value.l = file_signextend(ms, m, 805 (uint32_t)strtoul(*p, p, 0)); 806 eatsize(p); 807 } 808 return 0; 809 } 810} 811 812/* 813 * Convert a string containing C character escapes. Stop at an unescaped 814 * space or tab. 815 * Copy the converted version to "p", returning its length in *slen. 816 * Return updated scan pointer as function result. 817 */ 818private char * 819getstr(struct magic_set *ms, char *s, char *p, int plen, int *slen) 820{ 821 char *origs = s, *origp = p; 822 char *pmax = p + plen - 1; 823 int c; 824 int val; 825 826 while ((c = *s++) != '\0') { 827 if (isspace((unsigned char) c)) 828 break; 829 if (p >= pmax) { 830 file_error(ms, 0, "string too long: `%s'", origs); 831 return NULL; 832 } 833 if(c == '\\') { 834 switch(c = *s++) { 835 836 case '\0': 837 goto out; 838 839 default: 840 *p++ = (char) c; 841 break; 842 843 case 'n': 844 *p++ = '\n'; 845 break; 846 847 case 'r': 848 *p++ = '\r'; 849 break; 850 851 case 'b': 852 *p++ = '\b'; 853 break; 854 855 case 't': 856 *p++ = '\t'; 857 break; 858 859 case 'f': 860 *p++ = '\f'; 861 break; 862 863 case 'v': 864 *p++ = '\v'; 865 break; 866 867 /* \ and up to 3 octal digits */ 868 case '0': 869 case '1': 870 case '2': 871 case '3': 872 case '4': 873 case '5': 874 case '6': 875 case '7': 876 val = c - '0'; 877 c = *s++; /* try for 2 */ 878 if(c >= '0' && c <= '7') { 879 val = (val<<3) | (c - '0'); 880 c = *s++; /* try for 3 */ 881 if(c >= '0' && c <= '7') 882 val = (val<<3) | (c-'0'); 883 else 884 --s; 885 } 886 else 887 --s; 888 *p++ = (char)val; 889 break; 890 891 /* \x and up to 2 hex digits */ 892 case 'x': 893 val = 'x'; /* Default if no digits */ 894 c = hextoint(*s++); /* Get next char */ 895 if (c >= 0) { 896 val = c; 897 c = hextoint(*s++); 898 if (c >= 0) 899 val = (val << 4) + c; 900 else 901 --s; 902 } else 903 --s; 904 *p++ = (char)val; 905 break; 906 } 907 } else 908 *p++ = (char)c; 909 } 910out: 911 *p = '\0'; 912 *slen = p - origp; 913 return s; 914} 915 916 917/* Single hex char to int; -1 if not a hex char. */ 918private int 919hextoint(int c) 920{ 921 if (!isascii((unsigned char) c)) 922 return -1; 923 if (isdigit((unsigned char) c)) 924 return c - '0'; 925 if ((c >= 'a')&&(c <= 'f')) 926 return c + 10 - 'a'; 927 if (( c>= 'A')&&(c <= 'F')) 928 return c + 10 - 'A'; 929 return -1; 930} 931 932 933/* 934 * Print a string containing C character escapes. 935 */ 936protected void 937file_showstr(FILE *fp, const char *s, size_t len) 938{ 939 char c; 940 941 for (;;) { 942 c = *s++; 943 if (len == ~0U) { 944 if (c == '\0') 945 break; 946 } 947 else { 948 if (len-- == 0) 949 break; 950 } 951 if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */ 952 (void) fputc(c, fp); 953 else { 954 (void) fputc('\\', fp); 955 switch (c) { 956 957 case '\n': 958 (void) fputc('n', fp); 959 break; 960 961 case '\r': 962 (void) fputc('r', fp); 963 break; 964 965 case '\b': 966 (void) fputc('b', fp); 967 break; 968 969 case '\t': 970 (void) fputc('t', fp); 971 break; 972 973 case '\f': 974 (void) fputc('f', fp); 975 break; 976 977 case '\v': 978 (void) fputc('v', fp); 979 break; 980 981 default: 982 (void) fprintf(fp, "%.3o", c & 0377); 983 break; 984 } 985 } 986 } 987} 988 989/* 990 * eatsize(): Eat the size spec from a number [eg. 10UL] 991 */ 992private void 993eatsize(char **p) 994{ 995 char *l = *p; 996 997 if (LOWCASE(*l) == 'u') 998 l++; 999 1000 switch (LOWCASE(*l)) { 1001 case 'l': /* long */ 1002 case 's': /* short */ 1003 case 'h': /* short */ 1004 case 'b': /* char/byte */ 1005 case 'c': /* char/byte */ 1006 l++; 1007 /*FALLTHROUGH*/ 1008 default: 1009 break; 1010 } 1011 1012 *p = l; 1013} 1014 1015/* 1016 * handle a compiled file. 1017 */ 1018private int 1019apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, 1020 const char *fn) 1021{ 1022 int fd; 1023 struct stat st; 1024 uint32_t *ptr; 1025 uint32_t version; 1026 int needsbyteswap; 1027 char buf[MAXPATHLEN];
| 808 m->value.s); 809 return -1; 810 } 811 m->vallen = slen; 812 return 0; 813 default: 814 if (m->reln != 'x') { 815 m->value.l = file_signextend(ms, m, 816 (uint32_t)strtoul(*p, p, 0)); 817 eatsize(p); 818 } 819 return 0; 820 } 821} 822 823/* 824 * Convert a string containing C character escapes. Stop at an unescaped 825 * space or tab. 826 * Copy the converted version to "p", returning its length in *slen. 827 * Return updated scan pointer as function result. 828 */ 829private char * 830getstr(struct magic_set *ms, char *s, char *p, int plen, int *slen) 831{ 832 char *origs = s, *origp = p; 833 char *pmax = p + plen - 1; 834 int c; 835 int val; 836 837 while ((c = *s++) != '\0') { 838 if (isspace((unsigned char) c)) 839 break; 840 if (p >= pmax) { 841 file_error(ms, 0, "string too long: `%s'", origs); 842 return NULL; 843 } 844 if(c == '\\') { 845 switch(c = *s++) { 846 847 case '\0': 848 goto out; 849 850 default: 851 *p++ = (char) c; 852 break; 853 854 case 'n': 855 *p++ = '\n'; 856 break; 857 858 case 'r': 859 *p++ = '\r'; 860 break; 861 862 case 'b': 863 *p++ = '\b'; 864 break; 865 866 case 't': 867 *p++ = '\t'; 868 break; 869 870 case 'f': 871 *p++ = '\f'; 872 break; 873 874 case 'v': 875 *p++ = '\v'; 876 break; 877 878 /* \ and up to 3 octal digits */ 879 case '0': 880 case '1': 881 case '2': 882 case '3': 883 case '4': 884 case '5': 885 case '6': 886 case '7': 887 val = c - '0'; 888 c = *s++; /* try for 2 */ 889 if(c >= '0' && c <= '7') { 890 val = (val<<3) | (c - '0'); 891 c = *s++; /* try for 3 */ 892 if(c >= '0' && c <= '7') 893 val = (val<<3) | (c-'0'); 894 else 895 --s; 896 } 897 else 898 --s; 899 *p++ = (char)val; 900 break; 901 902 /* \x and up to 2 hex digits */ 903 case 'x': 904 val = 'x'; /* Default if no digits */ 905 c = hextoint(*s++); /* Get next char */ 906 if (c >= 0) { 907 val = c; 908 c = hextoint(*s++); 909 if (c >= 0) 910 val = (val << 4) + c; 911 else 912 --s; 913 } else 914 --s; 915 *p++ = (char)val; 916 break; 917 } 918 } else 919 *p++ = (char)c; 920 } 921out: 922 *p = '\0'; 923 *slen = p - origp; 924 return s; 925} 926 927 928/* Single hex char to int; -1 if not a hex char. */ 929private int 930hextoint(int c) 931{ 932 if (!isascii((unsigned char) c)) 933 return -1; 934 if (isdigit((unsigned char) c)) 935 return c - '0'; 936 if ((c >= 'a')&&(c <= 'f')) 937 return c + 10 - 'a'; 938 if (( c>= 'A')&&(c <= 'F')) 939 return c + 10 - 'A'; 940 return -1; 941} 942 943 944/* 945 * Print a string containing C character escapes. 946 */ 947protected void 948file_showstr(FILE *fp, const char *s, size_t len) 949{ 950 char c; 951 952 for (;;) { 953 c = *s++; 954 if (len == ~0U) { 955 if (c == '\0') 956 break; 957 } 958 else { 959 if (len-- == 0) 960 break; 961 } 962 if(c >= 040 && c <= 0176) /* TODO isprint && !iscntrl */ 963 (void) fputc(c, fp); 964 else { 965 (void) fputc('\\', fp); 966 switch (c) { 967 968 case '\n': 969 (void) fputc('n', fp); 970 break; 971 972 case '\r': 973 (void) fputc('r', fp); 974 break; 975 976 case '\b': 977 (void) fputc('b', fp); 978 break; 979 980 case '\t': 981 (void) fputc('t', fp); 982 break; 983 984 case '\f': 985 (void) fputc('f', fp); 986 break; 987 988 case '\v': 989 (void) fputc('v', fp); 990 break; 991 992 default: 993 (void) fprintf(fp, "%.3o", c & 0377); 994 break; 995 } 996 } 997 } 998} 999 1000/* 1001 * eatsize(): Eat the size spec from a number [eg. 10UL] 1002 */ 1003private void 1004eatsize(char **p) 1005{ 1006 char *l = *p; 1007 1008 if (LOWCASE(*l) == 'u') 1009 l++; 1010 1011 switch (LOWCASE(*l)) { 1012 case 'l': /* long */ 1013 case 's': /* short */ 1014 case 'h': /* short */ 1015 case 'b': /* char/byte */ 1016 case 'c': /* char/byte */ 1017 l++; 1018 /*FALLTHROUGH*/ 1019 default: 1020 break; 1021 } 1022 1023 *p = l; 1024} 1025 1026/* 1027 * handle a compiled file. 1028 */ 1029private int 1030apprentice_map(struct magic_set *ms, struct magic **magicp, uint32_t *nmagicp, 1031 const char *fn) 1032{ 1033 int fd; 1034 struct stat st; 1035 uint32_t *ptr; 1036 uint32_t version; 1037 int needsbyteswap; 1038 char buf[MAXPATHLEN];
|
1028 char *dbname = mkdbname(fn, buf, sizeof(buf));
| 1039 char *dbname = mkdbname(fn, buf, sizeof(buf), 0);
|
1029 void *mm = NULL; 1030 1031 if (dbname == NULL) 1032 return -1; 1033 1034 if ((fd = open(dbname, O_RDONLY)) == -1) 1035 return -1; 1036 1037 if (fstat(fd, &st) == -1) { 1038 file_error(ms, errno, "cannot stat `%s'", dbname); 1039 goto error; 1040 } 1041 if (st.st_size < 16) { 1042 file_error(ms, 0, "file `%s' is too small", dbname); 1043 goto error; 1044 } 1045 1046#ifdef QUICK 1047 if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE, 1048 MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) { 1049 file_error(ms, errno, "cannot map `%s'", dbname); 1050 goto error; 1051 } 1052#define RET 2 1053#else 1054 if ((mm = malloc((size_t)st.st_size)) == NULL) { 1055 file_oomem(ms); 1056 goto error; 1057 } 1058 if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) { 1059 file_badread(ms); 1060 goto error; 1061 } 1062#define RET 1 1063#endif 1064 *magicp = mm; 1065 (void)close(fd); 1066 fd = -1; 1067 ptr = (uint32_t *)(void *)*magicp; 1068 if (*ptr != MAGICNO) { 1069 if (swap4(*ptr) != MAGICNO) { 1070 file_error(ms, 0, "bad magic in `%s'"); 1071 goto error; 1072 } 1073 needsbyteswap = 1; 1074 } else 1075 needsbyteswap = 0; 1076 if (needsbyteswap) 1077 version = swap4(ptr[1]); 1078 else 1079 version = ptr[1]; 1080 if (version != VERSIONNO) { 1081 file_error(ms, 0, "version mismatch (%d != %d) in `%s'", 1082 version, VERSIONNO, dbname); 1083 goto error; 1084 } 1085 *nmagicp = (uint32_t)(st.st_size / sizeof(struct magic)) - 1; 1086 (*magicp)++; 1087 if (needsbyteswap) 1088 byteswap(*magicp, *nmagicp); 1089 return RET; 1090 1091error: 1092 if (fd != -1) 1093 (void)close(fd); 1094 if (mm) { 1095#ifdef QUICK 1096 (void)munmap((void *)mm, (size_t)st.st_size); 1097#else 1098 free(mm); 1099#endif 1100 } else { 1101 *magicp = NULL; 1102 *nmagicp = 0; 1103 } 1104 return -1; 1105} 1106 1107private const uint32_t ar[] = { 1108 MAGICNO, VERSIONNO 1109}; 1110/* 1111 * handle an mmaped file. 1112 */ 1113private int 1114apprentice_compile(struct magic_set *ms, struct magic **magicp, 1115 uint32_t *nmagicp, const char *fn) 1116{ 1117 int fd; 1118 char buf[MAXPATHLEN];
| 1040 void *mm = NULL; 1041 1042 if (dbname == NULL) 1043 return -1; 1044 1045 if ((fd = open(dbname, O_RDONLY)) == -1) 1046 return -1; 1047 1048 if (fstat(fd, &st) == -1) { 1049 file_error(ms, errno, "cannot stat `%s'", dbname); 1050 goto error; 1051 } 1052 if (st.st_size < 16) { 1053 file_error(ms, 0, "file `%s' is too small", dbname); 1054 goto error; 1055 } 1056 1057#ifdef QUICK 1058 if ((mm = mmap(0, (size_t)st.st_size, PROT_READ|PROT_WRITE, 1059 MAP_PRIVATE|MAP_FILE, fd, (off_t)0)) == MAP_FAILED) { 1060 file_error(ms, errno, "cannot map `%s'", dbname); 1061 goto error; 1062 } 1063#define RET 2 1064#else 1065 if ((mm = malloc((size_t)st.st_size)) == NULL) { 1066 file_oomem(ms); 1067 goto error; 1068 } 1069 if (read(fd, mm, (size_t)st.st_size) != (size_t)st.st_size) { 1070 file_badread(ms); 1071 goto error; 1072 } 1073#define RET 1 1074#endif 1075 *magicp = mm; 1076 (void)close(fd); 1077 fd = -1; 1078 ptr = (uint32_t *)(void *)*magicp; 1079 if (*ptr != MAGICNO) { 1080 if (swap4(*ptr) != MAGICNO) { 1081 file_error(ms, 0, "bad magic in `%s'"); 1082 goto error; 1083 } 1084 needsbyteswap = 1; 1085 } else 1086 needsbyteswap = 0; 1087 if (needsbyteswap) 1088 version = swap4(ptr[1]); 1089 else 1090 version = ptr[1]; 1091 if (version != VERSIONNO) { 1092 file_error(ms, 0, "version mismatch (%d != %d) in `%s'", 1093 version, VERSIONNO, dbname); 1094 goto error; 1095 } 1096 *nmagicp = (uint32_t)(st.st_size / sizeof(struct magic)) - 1; 1097 (*magicp)++; 1098 if (needsbyteswap) 1099 byteswap(*magicp, *nmagicp); 1100 return RET; 1101 1102error: 1103 if (fd != -1) 1104 (void)close(fd); 1105 if (mm) { 1106#ifdef QUICK 1107 (void)munmap((void *)mm, (size_t)st.st_size); 1108#else 1109 free(mm); 1110#endif 1111 } else { 1112 *magicp = NULL; 1113 *nmagicp = 0; 1114 } 1115 return -1; 1116} 1117 1118private const uint32_t ar[] = { 1119 MAGICNO, VERSIONNO 1120}; 1121/* 1122 * handle an mmaped file. 1123 */ 1124private int 1125apprentice_compile(struct magic_set *ms, struct magic **magicp, 1126 uint32_t *nmagicp, const char *fn) 1127{ 1128 int fd; 1129 char buf[MAXPATHLEN];
|
1119 char *dbname = mkdbname(fn, buf, sizeof(buf));
| 1130 char *dbname = mkdbname(fn, buf, sizeof(buf), 1);
|
1120 1121 if (dbname == NULL) 1122 return -1; 1123 1124 if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { 1125 file_error(ms, errno, "cannot open `%s'", dbname); 1126 return -1; 1127 } 1128 1129 if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) { 1130 file_error(ms, errno, "error writing `%s'", dbname); 1131 return -1; 1132 } 1133 1134 if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET) 1135 != sizeof(struct magic)) { 1136 file_error(ms, errno, "error seeking `%s'", dbname); 1137 return -1; 1138 } 1139 1140 if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp)) 1141 != (ssize_t)(sizeof(struct magic) * *nmagicp)) { 1142 file_error(ms, errno, "error writing `%s'", dbname); 1143 return -1; 1144 } 1145 1146 (void)close(fd); 1147 return 0; 1148} 1149 1150private const char ext[] = ".mgc"; 1151/* 1152 * make a dbname 1153 */ 1154private char *
| 1131 1132 if (dbname == NULL) 1133 return -1; 1134 1135 if ((fd = open(dbname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) { 1136 file_error(ms, errno, "cannot open `%s'", dbname); 1137 return -1; 1138 } 1139 1140 if (write(fd, ar, sizeof(ar)) != (ssize_t)sizeof(ar)) { 1141 file_error(ms, errno, "error writing `%s'", dbname); 1142 return -1; 1143 } 1144 1145 if (lseek(fd, (off_t)sizeof(struct magic), SEEK_SET) 1146 != sizeof(struct magic)) { 1147 file_error(ms, errno, "error seeking `%s'", dbname); 1148 return -1; 1149 } 1150 1151 if (write(fd, *magicp, (sizeof(struct magic) * *nmagicp)) 1152 != (ssize_t)(sizeof(struct magic) * *nmagicp)) { 1153 file_error(ms, errno, "error writing `%s'", dbname); 1154 return -1; 1155 } 1156 1157 (void)close(fd); 1158 return 0; 1159} 1160 1161private const char ext[] = ".mgc"; 1162/* 1163 * make a dbname 1164 */ 1165private char *
|
1155mkdbname(const char *fn, char *buf, size_t bufsiz)
| 1166mkdbname(const char *fn, char *buf, size_t bufsiz, int strip)
|
1156{
| 1167{
|
1157#ifdef notdef 1158 const char *p; 1159 if ((p = strrchr(fn, '/')) != NULL) 1160 fn = ++p; 1161#endif
| 1168 if (strip) { 1169 const char *p; 1170 if ((p = strrchr(fn, '/')) != NULL) 1171 fn = ++p; 1172 } 1173
|
1162 (void)snprintf(buf, bufsiz, "%s%s", fn, ext); 1163 return buf; 1164} 1165 1166/* 1167 * Byteswap an mmap'ed file if needed 1168 */ 1169private void 1170byteswap(struct magic *magic, uint32_t nmagic) 1171{ 1172 uint32_t i; 1173 for (i = 0; i < nmagic; i++) 1174 bs1(&magic[i]); 1175} 1176 1177/* 1178 * swap a short 1179 */ 1180private uint16_t 1181swap2(uint16_t sv) 1182{ 1183 uint16_t rv; 1184 uint8_t *s = (uint8_t *)(void *)&sv; 1185 uint8_t *d = (uint8_t *)(void *)&rv; 1186 d[0] = s[1]; 1187 d[1] = s[0]; 1188 return rv; 1189} 1190 1191/* 1192 * swap an int 1193 */ 1194private uint32_t 1195swap4(uint32_t sv) 1196{ 1197 uint32_t rv; 1198 uint8_t *s = (uint8_t *)(void *)&sv; 1199 uint8_t *d = (uint8_t *)(void *)&rv; 1200 d[0] = s[3]; 1201 d[1] = s[2]; 1202 d[2] = s[1]; 1203 d[3] = s[0]; 1204 return rv; 1205} 1206 1207/* 1208 * byteswap a single magic entry 1209 */ 1210private void 1211bs1(struct magic *m) 1212{ 1213 m->cont_level = swap2(m->cont_level); 1214 m->offset = swap4((uint32_t)m->offset); 1215 m->in_offset = swap4((uint32_t)m->in_offset);
| 1174 (void)snprintf(buf, bufsiz, "%s%s", fn, ext); 1175 return buf; 1176} 1177 1178/* 1179 * Byteswap an mmap'ed file if needed 1180 */ 1181private void 1182byteswap(struct magic *magic, uint32_t nmagic) 1183{ 1184 uint32_t i; 1185 for (i = 0; i < nmagic; i++) 1186 bs1(&magic[i]); 1187} 1188 1189/* 1190 * swap a short 1191 */ 1192private uint16_t 1193swap2(uint16_t sv) 1194{ 1195 uint16_t rv; 1196 uint8_t *s = (uint8_t *)(void *)&sv; 1197 uint8_t *d = (uint8_t *)(void *)&rv; 1198 d[0] = s[1]; 1199 d[1] = s[0]; 1200 return rv; 1201} 1202 1203/* 1204 * swap an int 1205 */ 1206private uint32_t 1207swap4(uint32_t sv) 1208{ 1209 uint32_t rv; 1210 uint8_t *s = (uint8_t *)(void *)&sv; 1211 uint8_t *d = (uint8_t *)(void *)&rv; 1212 d[0] = s[3]; 1213 d[1] = s[2]; 1214 d[2] = s[1]; 1215 d[3] = s[0]; 1216 return rv; 1217} 1218 1219/* 1220 * byteswap a single magic entry 1221 */ 1222private void 1223bs1(struct magic *m) 1224{ 1225 m->cont_level = swap2(m->cont_level); 1226 m->offset = swap4((uint32_t)m->offset); 1227 m->in_offset = swap4((uint32_t)m->in_offset);
|
1216 if (m->type != FILE_STRING)
| 1228 if (IS_STRING(m->type))
|
1217 m->value.l = swap4(m->value.l); 1218 m->mask = swap4(m->mask); 1219}
| 1229 m->value.l = swap4(m->value.l); 1230 m->mask = swap4(m->mask); 1231}
|