cudcv@warwick.ac.uk (Rob McMahon) (09/02/89)
Ian Darwin's PD file command which came over the net supported a very limited form of the `&' operator, which apparenty Sun added to the file command. The file as distributed allowed: >2 byte &0200 but there was no way to do >2 byte&0177 =2 Here are some diffs to give it the full functionality. Also one small fix for ANSI pre-processors which demand matching quotes even within comments, one not to print a space if the description string from the magic file is empty (useful when everything is going to be printed by continuation lines), and a bug fix for strtol which meant that the pointer was incremented one to many characters. After the diffs are my modified versions of magdir/{sun,compress}. Note, though, that I have to do >0 byte&0200 0200 ... rather than >0 byte&0200 >0 ... is it right that these comparisons should be signed ? When I think of a byte I think 0--255, not -128--127 ... Anyway, do with these patches what you will. Any improvements gratefully received. Have fun. =================================================================== RCS file: apprentice.c,v retrieving revision 1.1 diff -c -r1.1 apprentice.c *** /tmp/,RCSt1026546 Fri Sep 1 21:50:12 1989 --- apprentice.c Fri Sep 1 21:29:41 1989 *************** *** 67,73 **** /* parse it */ if (check) /* print silly verbose header for USG compat. */ ! (void) printf("cont\toffset\ttype\topcode\tvalue\tdesc\n"); while (fgets(line, MAXSTR, f) != NULL) { if (line[0]=='#') /* comment, do not parse */ --- 67,73 ---- /* parse it */ if (check) /* print silly verbose header for USG compat. */ ! (void) printf("cont\toffset\ttype\topcode\tmask\tvalue\tdesc\n"); while (fgets(line, MAXSTR, f) != NULL) { if (line[0]=='#') /* comment, do not parse */ *************** *** 92,98 **** int *ndx, check; { int i = 0, nd = *ndx; - int slen; static int warned = 0; struct magic *m; extern int errno; --- 92,97 ---- *************** *** 152,161 **** --- 151,205 ---- m->reln = '='; EATAB; + if (getvalue(m, &l)) + return -1; /* * TODO finish this macro and start using it! * #define offsetcheck {if (offset > HOWMANY-1) warning("offset too big"); } */ + /* + * if the relation was ``&'', + * change it to a MASK op relation. + */ + EATAB; + if (m->reln == '&') { + if (*l == '>' || *l == '<' || *l == '=') { + m->reln = *l | MASK; + ++l; + } else + m->reln = '=' | MASK; + m->mask = m->value.l; + EATAB; + if (getvalue(m, &l)) + return -1; + } + + /* + * now get last part - the description + */ + EATAB; + while ((m->desc[i++] = *l++) != '\0' && i<MAXDESC) + /* NULLBODY */; + + if (check) { + mdump(m); + } + ++(*ndx); /* make room for next */ + return 0; + } + + /* + * Read a numeric value from a pointer, into the value union of a magic + * pointer, according to the magic type. Update the string pointer to point + * just after the number read. Return 0 for success, non-zero for failure. + */ + int + getvalue(m, p) + struct magic *m; + char **p; + { + int slen; + switch(m->type) { /* * Do not remove the casts below. They are vital. *************** *** 163,178 **** * have happened. */ case BYTE: ! m->value.l = (char) strtol(l,&l,0); break; case SHORT: ! m->value.l = (short) strtol(l,&l,0); break; case LONG: ! m->value.l = (long) strtol(l,&l,0); break; case STRING: ! l = getstr(l, m->value.s, sizeof(m->value.s), &slen); m->vallen = slen; break; default: --- 207,222 ---- * have happened. */ case BYTE: ! m->value.l = (char) strtol(*p,p,0); break; case SHORT: ! m->value.l = (short) strtol(*p,p,0); break; case LONG: ! m->value.l = (long) strtol(*p,p,0); break; case STRING: ! *p = getstr(*p, m->value.s, sizeof(m->value.s), &slen); m->vallen = slen; break; default: *************** *** 179,196 **** warning("can't happen: m->type=%d\n", m->type); return -1; } - - /* - * now get last part - the description - */ - EATAB; - while ((m->desc[i++] = *l++) != '\0' && i<MAXDESC) - /* NULLBODY */; - - if (check) { - mdump(m); - } - ++(*ndx); /* make room for next */ return 0; } --- 223,228 ---- =================================================================== RCS file: file.1,v retrieving revision 1.1 diff -c -r1.1 file.1 *** /tmp/,RCSt1026546 Fri Sep 1 21:50:16 1989 --- file.1 Fri Sep 1 21:49:56 1989 *************** *** 149,165 **** The Sun Microsystems implementation of System V compatibility includes a file(1) command that has some extentions. My version differs from Sun's only in minor ways. ! The significant one is the `&' operator, which Sun's program expects as, for example, ..br >16 long&0x7fffffff >0 not stripped - ..br - would be entered in my version as - ..br - >16 long &0x7fffffff not stripped - ..br - which is a little less general; it simply tests (location 16)&0x7ffffff - and returns its truth value as a C expression. ..SH MAGIC DIRECTORY The magic file entries have been collected from various sources, mainly USENET, and contributed by various authors. --- 149,158 ---- The Sun Microsystems implementation of System V compatibility includes a file(1) command that has some extentions. My version differs from Sun's only in minor ways. ! It includes the extension of the `&' operator, used as, for example, ..br >16 long&0x7fffffff >0 not stripped ..SH MAGIC DIRECTORY The magic file entries have been collected from various sources, mainly USENET, and contributed by various authors. *************** *** 199,204 **** --- 192,200 ---- Written by Ian F. Darwin, UUCP address {utzoo | ihnp4}!darwin!ian, Internet address ian@sq.com, postal address: P.O. Box 603, Station F, Toronto, Ontario, CANADA M4Y 2L8. + ..PP + Altered by Rob McMahon, cudcv@warwick.ac.uk, 1989, to extend the `&' operator + from simple `x&y != 0' to `x&y op z'. ..PP ..I Strtok.c and =================================================================== RCS file: file.h,v retrieving revision 1.1 diff -c -r1.1 file.h *** /tmp/,RCSt1026546 Fri Sep 1 21:50:23 1989 --- file.h Fri Sep 1 21:29:44 1989 *************** *** 35,41 **** struct magic { short contflag; /* 1 if '>0' appears */ long offset; /* offset to magic number */ ! char reln; /* relation (0=eq, '>'=gt, etc) */ char type; /* int, short, long or string. */ char vallen; /* length of string value, if any */ #define BYTE 1 --- 35,42 ---- struct magic { short contflag; /* 1 if '>0' appears */ long offset; /* offset to magic number */ ! #define MASK 0200 /* this is a masked op, like & v1 = v2 */ ! unsigned char reln; /* relation (0=eq, '>'=gt, etc) */ char type; /* int, short, long or string. */ char vallen; /* length of string value, if any */ #define BYTE 1 *************** *** 48,53 **** --- 49,55 ---- long l; char s[MAXstring]; } value; /* either number or string */ + long mask; /* mask before comparison with value */ char desc[MAXDESC]; /* description */ }; =================================================================== RCS file: fsmagic.c,v retrieving revision 1.1 diff -c -r1.1 fsmagic.c *** /tmp/,RCSt1026546 Fri Sep 1 21:50:29 1989 --- fsmagic.c Fri Sep 1 21:29:47 1989 *************** *** 35,41 **** /* On most systems cpp will discard it automatically */ Congratulations, you have found a portability bug. Please grep /usr/include/sys and edit the above #include ! to point at the file that defines the `major' macro. #endif /*major*/ #include <sys/stat.h> #include "file.h" --- 35,41 ---- /* On most systems cpp will discard it automatically */ Congratulations, you have found a portability bug. Please grep /usr/include/sys and edit the above #include ! to point at the file that defines the ``major'' macro. #endif /*major*/ #include <sys/stat.h> #include "file.h" =================================================================== RCS file: magic.4,v retrieving revision 1.1 diff -c -r1.1 magic.4 *** /tmp/,RCSt1026546 Fri Sep 1 21:50:33 1989 --- magic.4 Fri Sep 1 21:50:00 1989 *************** *** 35,40 **** --- 35,45 ---- ..IP string A string of bytes. ..RE + The numeric types may optionally be followed by + ..B & + and a numeric value, + to specify that the value is to be AND'ed with the + numeric value before any comparisons are done. ..IP test The value to be compared with the value from the file. If the type is numeric, this value *************** *** 49,61 **** ..BR < , to specify that the value from the file must be less than the specified value, ..BR > , to specify that the value from the file must be greater than the specified ! value, or - ..BR & , - to specify that the value is to be AND'ed with the - numeric value before any comparisons are done. Numeric values are specified in C form; e.g. ..B 13 is decimal, --- 54,64 ---- ..BR < , to specify that the value from the file must be less than the specified value, + or ..BR > , to specify that the value from the file must be greater than the specified ! value. or Numeric values are specified in C form; e.g. ..B 13 is decimal, =================================================================== RCS file: print.c,v retrieving revision 1.1 diff -c -r1.1 print.c *** /tmp/,RCSt1026546 Fri Sep 1 21:50:36 1989 --- print.c Fri Sep 1 21:29:49 1989 *************** *** 44,55 **** mdump(m) struct magic *m; { ! (void) printf("%d\t%d\t%d\t%c\t", m->contflag, m->offset, m->type, ! m->reln, 0); if (m->type == STRING) showstr(m->value.s); else --- 44,59 ---- mdump(m) struct magic *m; { ! (void) printf("%d\t%d\t%d\t%s%c\t", m->contflag, m->offset, m->type, ! m->reln & MASK ? "&" : "", ! m->reln & ~MASK, 0); + if (m->reln & MASK) + (void) printf("%d",m->mask); + (void) putchar('\t'); if (m->type == STRING) showstr(m->value.s); else =================================================================== RCS file: softmagic.c,v retrieving revision 1.1 diff -c -r1.1 softmagic.c *** /tmp/,RCSt1026546 Fri Sep 1 21:50:41 1989 --- softmagic.c Fri Sep 1 21:29:52 1989 *************** *** 71,77 **** magindex < nmagic) { ++magindex; if (mcheck(s, &magic[magindex])){ ! (void) putchar(' '); mprint(&magic[magindex],s); } } --- 71,79 ---- magindex < nmagic) { ++magindex; if (mcheck(s, &magic[magindex])){ ! /* no space if nothing printed */ ! if (magic[magindex-1].desc[0]) ! (void) putchar(' '); mprint(&magic[magindex],s); } } *************** *** 98,110 **** switch (m->type) { case BYTE: ! (void) printf(m->desc, p->b); break; case SHORT: ! (void) printf(m->desc, p->h); break; case LONG: ! (void) printf(m->desc, p->l); break; case STRING: if ((pp=strchr(p->s, '\n')) != NULL) --- 100,115 ---- switch (m->type) { case BYTE: ! (void) printf(m->desc, ! (m->reln & MASK) ? p->b & m->mask : p->b); break; case SHORT: ! (void) printf(m->desc, ! (m->reln & MASK) ? p->h & m->mask : p->h); break; case LONG: ! (void) printf(m->desc, ! (m->reln & MASK) ? p->l & m->mask : p->l); break; case STRING: if ((pp=strchr(p->s, '\n')) != NULL) *************** *** 123,128 **** --- 128,134 ---- { register union VALUETYPE *p = (union VALUETYPE *)(s+m->offset); register long l = m->value.l; + register long mask = m->mask; register long v; if (debug) { *************** *** 167,172 **** --- 173,184 ---- return v < l; case '&': return v & l; + case MASK | '=': + return (v & mask) == l; + case MASK | '>': + return (v & mask) > l; + case MASK | '<': + return (v & mask) < l; default: warning("mcheck: can't happen: invalid relation %d", m->reln); return 0; =================================================================== RCS file: strtol.c,v retrieving revision 1.1 diff -c -r1.1 strtol.c *** /tmp/,RCSt1026546 Fri Sep 1 21:50:44 1989 --- strtol.c Fri Sep 1 21:29:54 1989 *************** *** 89,95 **** valid = 0; break; } ! ++s; } /* --- 89,96 ---- valid = 0; break; } ! if (valid) ! ++s; } /* ------------------------------------------------------------------------------ # Values for Sun binaries 0 long&0x7cfffff0 0x30100 sparc >2 short 0407 >2 short 0410 pure >2 short 0413 demand paged >0 byte&0200 0200 dynamically linked >16 long >0 executable not stripped >16 long =0 executable stripped 0 long&0x7cfffff0 0x20100 mc68020 >2 short 0407 >2 short 0410 pure >2 short 0413 demand paged >0 byte&0200 0200 dynamically linked >16 long >0 executable not stripped >16 long =0 executable stripped 0 long&0x7cfffff0 0x10100 mc68010 >2 short 0407 >2 short 0410 pure >2 short 0413 demand paged >0 byte&0200 0200 dynamically linked >16 long >0 executable not stripped >16 long =0 executable stripped 0 long&0x7cfffff0 0x100 #>2 short 0407 >2 short 0410 pure >2 short 0413 demand paged >0 byte&0200 0200 dynamically linked >16 long >0 executable not stripped >16 long =0 executable stripped 0 long 0x080456 core file >128 string >0 from '%s' # 0 short 05401 byte-swapped demand paged executable 0 short 010001 byte-swapped demand paged executable ------------------------------------------------------------------------------ 0 short 017037 packed data # CPL - added pack to /etc/magic 0 short 017436 packed data 0 short 0145405 huf output 0 string \037\235 compressed data >2 byte&0200 0200 block compressed # non block compressed >2 byte&0177 >0 - with %d bits ------------------------------------------------------------------------------ Rob-- UUCP: ...!mcvax!ukc!warwick!cudcv PHONE: +44 203 523037 JANET: cudcv@uk.ac.warwick ARPA: cudcv@warwick.ac.uk Rob McMahon, Computing Services, Warwick University, Coventry CV4 7AL, England