#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#include <mach.h> /* * file - determine type of file */#define LENDIAN(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) uchar buf[6001];short cfreq[140];short wfreq[50];int nbuf;Dir* mbuf;int fd;char *fname;char *slash; enum{ Cword, Fword, Aword, Alword, Lword, I1, I2, I3, Clatin = 128, Cbinary, Cnull, Ceascii, Cutf,};struct{ char* word; int class;} dict[] ={ "PATH", Lword, "TEXT", Aword, "adt", Alword, "aggr", Alword, "alef", Alword, "array", Lword, "block", Fword, "char", Cword, "common", Fword, "con", Lword, "data", Fword, "dimension", Fword, "double", Cword, "extern", Cword, "bio", I2, "float", Cword, "fn", Lword, "function", Fword, "h", I3, "implement", Lword, "import", Lword, "include", I1, "int", Cword, "integer", Fword, "iota", Lword, "libc", I2, "long", Cword, "module", Lword, "real", Fword, "ref", Lword, "register", Cword, "self", Lword, "short", Cword, "static", Cword, "stdio", I2, "struct", Cword, "subroutine", Fword, "u", I2, "void", Cword,}; /* codes for 'mode' field in language structure */enum { Normal = 0, First, /* first entry for language spanning several ranges */ Multi, /* later entries " " " ... */ Shared, /* codes used in several languages */ }; struct{ int mode; /* see enum above */ int count; int low; int high; char *name; } language[] ={ Normal, 0, 0x0100, 0x01FF, "Extended Latin", Normal, 0, 0x0370, 0x03FF, "Greek", Normal, 0, 0x0400, 0x04FF, "Cyrillic", Normal, 0, 0x0530, 0x058F, "Armenian", Normal, 0, 0x0590, 0x05FF, "Hebrew", Normal, 0, 0x0600, 0x06FF, "Arabic", Normal, 0, 0x0900, 0x097F, "Devanagari", Normal, 0, 0x0980, 0x09FF, "Bengali", Normal, 0, 0x0A00, 0x0A7F, "Gurmukhi", Normal, 0, 0x0A80, 0x0AFF, "Gujarati", Normal, 0, 0x0B00, 0x0B7F, "Oriya", Normal, 0, 0x0B80, 0x0BFF, "Tamil", Normal, 0, 0x0C00, 0x0C7F, "Telugu", Normal, 0, 0x0C80, 0x0CFF, "Kannada", Normal, 0, 0x0D00, 0x0D7F, "Malayalam", Normal, 0, 0x0E00, 0x0E7F, "Thai", Normal, 0, 0x0E80, 0x0EFF, "Lao", Normal, 0, 0x1000, 0x105F, "Tibetan", Normal, 0, 0x10A0, 0x10FF, "Georgian", Normal, 0, 0x3040, 0x30FF, "Japanese", Normal, 0, 0x3100, 0x312F, "Chinese", First, 0, 0x3130, 0x318F, "Korean", Multi, 0, 0x3400, 0x3D2F, "Korean", Shared, 0, 0x4e00, 0x9fff, "CJK", Normal, 0, 0, 0, 0, /* terminal entry */}; enum{ Fascii, /* printable ascii */ Flatin, /* latin 1*/ Futf, /* UTF character set */ Fbinary, /* binary */ Feascii, /* ASCII with control chars */ Fnull, /* NULL in file */} guess; void bump_utf_count(Rune);int cistrncmp(char*, char*, int);void filetype(int);int getfontnum(uchar*, uchar**);int isas(void);int isc(void);int iscint(void);int isenglish(void);int ishp(void);int ishtml(void);int isrfc822(void);int ismbox(void);int islimbo(void);int istga(void);int ismp3(void);int ismp4(void);int isoggvorbis(void);int isoggopus(void);int ismung(void);int isp9bit(void);int isp9font(void);int isrtf(void);int ismsdos(void);int isicocur(void);int iself(void);int istring(void);int isoffstr(void);int iff(void);int long0(void);int longoff(void);int istar(void);int isface(void);int isexec(void);int isudiff(void);int isexecscript(void);int p9bitnum(char*, int*);int p9subfont(uchar*);void print_utf(void);void type(char*, int);int utf_count(void);void wordfreq(void); int (*call[])(void) ={ long0, /* recognizable by first 4 bytes */ istring, /* recognizable by first string */ iself, /* ELF (foreign) executable */ isexec, /* native executables */ isexecscript, /* executable scripts */ iff, /* interchange file format (strings) */ longoff, /* recognizable by 4 bytes at some offset */ isoffstr, /* recognizable by string at some offset */ isudiff, /* unified diff output */ isrfc822, /* email file */ ismbox, /* mail box */ istar, /* recognizable by tar checksum */ iscint, /* compiler/assembler intermediate */ ishtml, /* html keywords */ islimbo, /* limbo source */ isc, /* c & alef compiler key words */ isas, /* assembler key words */ isp9font, /* plan 9 font */ isp9bit, /* plan 9 image (as from /dev/window) */ isrtf, /* rich text format */ ismsdos, /* msdos exe (virus file attachement) */ isicocur, /* windows icon or cursor file */ isface, /* ascii face file */ istga, isoggvorbis, isoggopus, ismp4, ismp3, /* last resorts */ ismung, /* entropy compressed/encrypted */ isenglish, /* char frequency English */ 0}; int mime; char OCTET[] = "application/octet-stream";char PLAIN[] = "text/plain"; voidmain(int argc, char *argv[]){ int i, j, maxlen; char *cp; Rune r; ARGBEGIN{ case 'm': mime = 1; break; default: fprint(2, "usage: file [-m] [file...]\n"); exits("usage"); }ARGEND; maxlen = 0; if(mime == 0 || argc > 1){ for(i = 0; i < argc; i++) { for (j = 0, cp = argv[i]; *cp; j++, cp += chartorune(&r, cp)) ; if(j > maxlen) maxlen = j; } } if (argc <= 0) { if(!mime) print ("stdin: "); filetype(0); } else { for(i = 0; i < argc; i++) type(argv[i], maxlen); } exits(0);} voidtype(char *file, int nlen){ Rune r; int i; char *p; if(nlen > 0){ slash = 0; for (i = 0, p = file; *p; i++) { if (*p == '/') /* find rightmost slash */ slash = p; p += chartorune(&r, p); /* count runes */ } print("%s:%*s",file, nlen-i+1, ""); } fname = file; if ((fd = open(file, OREAD)) < 0) { fprint(2, "cannot open: %r\n"); return; } filetype(fd); close(fd);} voidutfconv(void){ Rune r; uchar *rb; char *p, *e; int i; if(nbuf < 4) return; if(memcmp(buf, "\x00\x00\xFE\xFF", 4) == 0){ if(!mime) print("utf-32be "); return; } else if(memcmp(buf, "\xFE\xFF\x00\x00", 4) == 0){ if(!mime) print("utf-32le "); return; } else if(memcmp(buf, "\xEF\xBB\xBF", 3) == 0){ memmove(buf, buf+3, nbuf-3); nbuf -= 3; return; } else if(memcmp(buf, "\xFE\xFF", 2) == 0){ if(!mime) print("utf-16be "); nbuf -= 2; rb = malloc(nbuf+1); memmove(rb, buf+2, nbuf); p = (char*)buf; e = p+sizeof(buf)-UTFmax-1; for(i=0; i<nbuf && p < e; i+=2){ r = rb[i+1] | rb[i]<<8; p += runetochar(p, &r); } *p = 0; free(rb); nbuf = p - (char*)buf; } else if(memcmp(buf, "\xFF\xFE", 2) == 0){ if(!mime) print("utf-16le "); nbuf -= 2; rb = malloc(nbuf+1); memmove(rb, buf+2, nbuf); p = (char*)buf; e = p+sizeof(buf)-UTFmax-1; for(i=0; i<nbuf && p < e; i+=2){ r = rb[i] | rb[i+1]<<8; p += runetochar(p, &r); } *p = 0; free(rb); nbuf = p - (char*)buf; }} voidfiletype(int fd){ Rune r; int i, f, n; char *p, *eob; free(mbuf); mbuf = dirfstat(fd); if(mbuf == nil){ fprint(2, "cannot stat: %r\n"); return; } if(mbuf->mode & DMDIR) { print("%s\n", mime ? OCTET : "directory"); return; } if(mbuf->type != 'M' && mbuf->type != '|') { if(mime) print("%s\n", OCTET); else print("special file #%C/%s\n", mbuf->type, mbuf->name); return; } /* may be reading a pipe on standard input */ nbuf = readn(fd, buf, sizeof(buf)-1); if(nbuf < 0) { fprint(2, "cannot read: %r\n"); return; } if(nbuf == 0) { print("%s\n", mime ? PLAIN : "empty file"); return; } buf[nbuf] = 0; utfconv(); /* * build histogram table */ memset(cfreq, 0, sizeof(cfreq)); for (i = 0; language[i].name; i++) language[i].count = 0; eob = (char *)buf+nbuf; for(n = 0, p = (char *)buf; p < eob; n++) { if (!fullrune(p, eob-p) && eob-p < UTFmax) break; p += chartorune(&r, p); if (r == 0) f = Cnull; else if (r <= 0x7f) { if (!isprint(r) && !isspace(r)) f = Ceascii; /* ASCII control char */ else f = r; } else if (r == 0x80) { bump_utf_count(r); f = Cutf; } else if (r < 0xA0) f = Cbinary; /* Invalid Runes */ else if (r <= 0xff) f = Clatin; /* Latin 1 */ else { bump_utf_count(r); f = Cutf; /* UTF extension */ } cfreq[f]++; /* ASCII chars peg directly */ } /* * gross classify */ if (cfreq[Cbinary]) guess = Fbinary; else if (cfreq[Cutf]) guess = Futf; else if (cfreq[Clatin]) guess = Flatin; else if (cfreq[Ceascii]) guess = Feascii; else if (cfreq[Cnull]) guess = Fbinary; else guess = Fascii; /* * lookup dictionary words */ memset(wfreq, 0, sizeof(wfreq)); if(guess == Fascii || guess == Flatin || guess == Futf) wordfreq(); /* * call individual classify routines */ for(i=0; call[i]; i++) if((*call[i])()) return; /* * if all else fails, * print out gross classification */ if (nbuf < 100 && !mime) print(mime ? PLAIN : "short "); if (guess == Fascii) print("%s\n", mime ? PLAIN : "Ascii"); else if (guess == Feascii) print("%s\n", mime ? PLAIN : "extended ascii"); else if (guess == Flatin) print("%s\n", mime ? PLAIN : "latin ascii"); else if (guess == Futf && utf_count() < 4) print_utf(); else print("%s\n", mime ? OCTET : "binary");} voidbump_utf_count(Rune r){ int low, high, mid; high = sizeof(language)/sizeof(language[0])-1; for (low = 0; low < high;) { mid = (low+high)/2; if (r >= language[mid].low) { if (r <= language[mid].high) { language[mid].count++; break; } else low = mid+1; } else high = mid; }} intutf_count(void){ int i, count; count = 0; for (i = 0; language[i].name; i++) if (language[i].count > 0) switch (language[i].mode) { case Normal: case First: count++; break; default: break; } return count;} intchkascii(void){ int i;Lines 1–500 of 1772. Load more
#include <u.h> #include <libc.h> #include <bio.h> #include <ctype.h> #include <mach.h> /* * file - determine type of file */ #define LENDIAN(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) uchar buf[6001]; short cfreq[140]; short wfreq[50]; int nbuf; Dir* mbuf; int fd; char *fname; char *slash; enum { Cword, Fword, Aword, Alword, Lword, I1, I2, I3, Clatin = 128, Cbinary, Cnull, Ceascii, Cutf, }; struct { char* word; int class; } dict[] = { "PATH", Lword, "TEXT", Aword, "adt", Alword, "aggr", Alword, "alef", Alword, "array", Lword, "block", Fword, "char", Cword, "common", Fword, "con", Lword, "data", Fword, "dimension", Fword, "double", Cword, "extern", Cword, "bio", I2, "float", Cword, "fn", Lword, "function", Fword, "h", I3, "implement", Lword, "import", Lword, "include", I1, "int", Cword, "integer", Fword, "iota", Lword, "libc", I2, "long", Cword, "module", Lword, "real", Fword, "ref", Lword, "register", Cword, "self", Lword, "short", Cword, "static", Cword, "stdio", I2, "struct", Cword, "subroutine", Fword, "u", I2, "void", Cword, }; /* codes for 'mode' field in language structure */ enum { Normal = 0, First, /* first entry for language spanning several ranges */ Multi, /* later entries " " " ... */ Shared, /* codes used in several languages */ }; struct { int mode; /* see enum above */ int count; int low; int high; char *name; } language[] = { Normal, 0, 0x0100, 0x01FF, "Extended Latin", Normal, 0, 0x0370, 0x03FF, "Greek", Normal, 0, 0x0400, 0x04FF, "Cyrillic", Normal, 0, 0x0530, 0x058F, "Armenian", Normal, 0, 0x0590, 0x05FF, "Hebrew", Normal, 0, 0x0600, 0x06FF, "Arabic", Normal, 0, 0x0900, 0x097F, "Devanagari", Normal, 0, 0x0980, 0x09FF, "Bengali", Normal, 0, 0x0A00, 0x0A7F, "Gurmukhi", Normal, 0, 0x0A80, 0x0AFF, "Gujarati", Normal, 0, 0x0B00, 0x0B7F, "Oriya", Normal, 0, 0x0B80, 0x0BFF, "Tamil", Normal, 0, 0x0C00, 0x0C7F, "Telugu", Normal, 0, 0x0C80, 0x0CFF, "Kannada", Normal, 0, 0x0D00, 0x0D7F, "Malayalam", Normal, 0, 0x0E00, 0x0E7F, "Thai", Normal, 0, 0x0E80, 0x0EFF, "Lao", Normal, 0, 0x1000, 0x105F, "Tibetan", Normal, 0, 0x10A0, 0x10FF, "Georgian", Normal, 0, 0x3040, 0x30FF, "Japanese", Normal, 0, 0x3100, 0x312F, "Chinese", First, 0, 0x3130, 0x318F, "Korean", Multi, 0, 0x3400, 0x3D2F, "Korean", Shared, 0, 0x4e00, 0x9fff, "CJK", Normal, 0, 0, 0, 0, /* terminal entry */ }; enum { Fascii, /* printable ascii */ Flatin, /* latin 1*/ Futf, /* UTF character set */ Fbinary, /* binary */ Feascii, /* ASCII with control chars */ Fnull, /* NULL in file */ } guess; void bump_utf_count(Rune); int cistrncmp(char*, char*, int); void filetype(int); int getfontnum(uchar*, uchar**); int isas(void); int isc(void); int iscint(void); int isenglish(void); int ishp(void); int ishtml(void); int isrfc822(void); int ismbox(void); int islimbo(void); int istga(void); int ismp3(void); int ismp4(void); int isoggvorbis(void); int isoggopus(void); int ismung(void); int isp9bit(void); int isp9font(void); int isrtf(void); int ismsdos(void); int isicocur(void); int iself(void); int istring(void); int isoffstr(void); int iff(void); int long0(void); int longoff(void); int istar(void); int isface(void); int isexec(void); int isudiff(void); int isexecscript(void); int p9bitnum(char*, int*); int p9subfont(uchar*); void print_utf(void); void type(char*, int); int utf_count(void); void wordfreq(void); int (*call[])(void) = { long0, /* recognizable by first 4 bytes */ istring, /* recognizable by first string */ iself, /* ELF (foreign) executable */ isexec, /* native executables */ isexecscript, /* executable scripts */ iff, /* interchange file format (strings) */ longoff, /* recognizable by 4 bytes at some offset */ isoffstr, /* recognizable by string at some offset */ isudiff, /* unified diff output */ isrfc822, /* email file */ ismbox, /* mail box */ istar, /* recognizable by tar checksum */ iscint, /* compiler/assembler intermediate */ ishtml, /* html keywords */ islimbo, /* limbo source */ isc, /* c & alef compiler key words */ isas, /* assembler key words */ isp9font, /* plan 9 font */ isp9bit, /* plan 9 image (as from /dev/window) */ isrtf, /* rich text format */ ismsdos, /* msdos exe (virus file attachement) */ isicocur, /* windows icon or cursor file */ isface, /* ascii face file */ istga, isoggvorbis, isoggopus, ismp4, ismp3, /* last resorts */ ismung, /* entropy compressed/encrypted */ isenglish, /* char frequency English */ 0 }; int mime; char OCTET[] = "application/octet-stream"; char PLAIN[] = "text/plain"; void main(int argc, char *argv[]) { int i, j, maxlen; char *cp; Rune r; ARGBEGIN{ case 'm': mime = 1; break; default: fprint(2, "usage: file [-m] [file...]\n"); exits("usage"); }ARGEND; maxlen = 0; if(mime == 0 || argc > 1){ for(i = 0; i < argc; i++) { for (j = 0, cp = argv[i]; *cp; j++, cp += chartorune(&r, cp)) ; if(j > maxlen) maxlen = j; } } if (argc <= 0) { if(!mime) print ("stdin: "); filetype(0); } else { for(i = 0; i < argc; i++) type(argv[i], maxlen); } exits(0); } void type(char *file, int nlen) { Rune r; int i; char *p; if(nlen > 0){ slash = 0; for (i = 0, p = file; *p; i++) { if (*p == '/') /* find rightmost slash */ slash = p; p += chartorune(&r, p); /* count runes */ } print("%s:%*s",file, nlen-i+1, ""); } fname = file; if ((fd = open(file, OREAD)) < 0) { fprint(2, "cannot open: %r\n"); return; } filetype(fd); close(fd); } void utfconv(void) { Rune r; uchar *rb; char *p, *e; int i; if(nbuf < 4) return; if(memcmp(buf, "\x00\x00\xFE\xFF", 4) == 0){ if(!mime) print("utf-32be "); return; } else if(memcmp(buf, "\xFE\xFF\x00\x00", 4) == 0){ if(!mime) print("utf-32le "); return; } else if(memcmp(buf, "\xEF\xBB\xBF", 3) == 0){ memmove(buf, buf+3, nbuf-3); nbuf -= 3; return; } else if(memcmp(buf, "\xFE\xFF", 2) == 0){ if(!mime) print("utf-16be "); nbuf -= 2; rb = malloc(nbuf+1); memmove(rb, buf+2, nbuf); p = (char*)buf; e = p+sizeof(buf)-UTFmax-1; for(i=0; i<nbuf && p < e; i+=2){ r = rb[i+1] | rb[i]<<8; p += runetochar(p, &r); } *p = 0; free(rb); nbuf = p - (char*)buf; } else if(memcmp(buf, "\xFF\xFE", 2) == 0){ if(!mime) print("utf-16le "); nbuf -= 2; rb = malloc(nbuf+1); memmove(rb, buf+2, nbuf); p = (char*)buf; e = p+sizeof(buf)-UTFmax-1; for(i=0; i<nbuf && p < e; i+=2){ r = rb[i] | rb[i+1]<<8; p += runetochar(p, &r); } *p = 0; free(rb); nbuf = p - (char*)buf; } } void filetype(int fd) { Rune r; int i, f, n; char *p, *eob; free(mbuf); mbuf = dirfstat(fd); if(mbuf == nil){ fprint(2, "cannot stat: %r\n"); return; } if(mbuf->mode & DMDIR) { print("%s\n", mime ? OCTET : "directory"); return; } if(mbuf->type != 'M' && mbuf->type != '|') { if(mime) print("%s\n", OCTET); else print("special file #%C/%s\n", mbuf->type, mbuf->name); return; } /* may be reading a pipe on standard input */ nbuf = readn(fd, buf, sizeof(buf)-1); if(nbuf < 0) { fprint(2, "cannot read: %r\n"); return; } if(nbuf == 0) { print("%s\n", mime ? PLAIN : "empty file"); return; } buf[nbuf] = 0; utfconv(); /* * build histogram table */ memset(cfreq, 0, sizeof(cfreq)); for (i = 0; language[i].name; i++) language[i].count = 0; eob = (char *)buf+nbuf; for(n = 0, p = (char *)buf; p < eob; n++) { if (!fullrune(p, eob-p) && eob-p < UTFmax) break; p += chartorune(&r, p); if (r == 0) f = Cnull; else if (r <= 0x7f) { if (!isprint(r) && !isspace(r)) f = Ceascii; /* ASCII control char */ else f = r; } else if (r == 0x80) { bump_utf_count(r); f = Cutf; } else if (r < 0xA0) f = Cbinary; /* Invalid Runes */ else if (r <= 0xff) f = Clatin; /* Latin 1 */ else { bump_utf_count(r); f = Cutf; /* UTF extension */ } cfreq[f]++; /* ASCII chars peg directly */ } /* * gross classify */ if (cfreq[Cbinary]) guess = Fbinary; else if (cfreq[Cutf]) guess = Futf; else if (cfreq[Clatin]) guess = Flatin; else if (cfreq[Ceascii]) guess = Feascii; else if (cfreq[Cnull]) guess = Fbinary; else guess = Fascii; /* * lookup dictionary words */ memset(wfreq, 0, sizeof(wfreq)); if(guess == Fascii || guess == Flatin || guess == Futf) wordfreq(); /* * call individual classify routines */ for(i=0; call[i]; i++) if((*call[i])()) return; /* * if all else fails, * print out gross classification */ if (nbuf < 100 && !mime) print(mime ? PLAIN : "short "); if (guess == Fascii) print("%s\n", mime ? PLAIN : "Ascii"); else if (guess == Feascii) print("%s\n", mime ? PLAIN : "extended ascii"); else if (guess == Flatin) print("%s\n", mime ? PLAIN : "latin ascii"); else if (guess == Futf && utf_count() < 4) print_utf(); else print("%s\n", mime ? OCTET : "binary"); } void bump_utf_count(Rune r) { int low, high, mid; high = sizeof(language)/sizeof(language[0])-1; for (low = 0; low < high;) { mid = (low+high)/2; if (r >= language[mid].low) { if (r <= language[mid].high) { language[mid].count++; break; } else low = mid+1; } else high = mid; } } int utf_count(void) { int i, count; count = 0; for (i = 0; language[i].name; i++) if (language[i].count > 0) switch (language[i].mode) { case Normal: case First: count++; break; default: break; } return count; } int chkascii(void) { int i;