/* ** Find - AmigaDOS 2.04 commodities utility ** ** Copyright © 1991-1992 by Olaf `Olsen' Barthel ** All Rights Reserved */ #include "FindGlobal.h" /* A structure containing both a file name suffix and the * approriate file type. */ struct Suffix { UBYTE *Name; UBYTE Type; }; /* A table of valid ASCII characters (7 bits). */ STATIC BYTE ID_ValidTab[256] = { 0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0, 0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* A table of clearly invalid ASCII characters (8 bits). */ STATIC BYTE ID_InvalidTab[256] = { 1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1, 1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; /* Some file name suffixes for text files and the approriate * file types. */ STATIC struct Suffix TextSuffix[] = { ".C", TYPE_C, ".CPP", TYPE_C, ".CXX", TYPE_C, ".C++", TYPE_C, ".CC", TYPE_C, ".H", TYPE_H, ".ASM", TYPE_ASM, ".A", TYPE_ASM, ".S", TYPE_ASM, ".I", TYPE_I, ".BAS", TYPE_BASIC, ".GFA", TYPE_BASIC, ".REXX", TYPE_REXX, ".CED", TYPE_REXX, ".TTX", TYPE_REXX, ".VLT", TYPE_REXX, ".CPR", TYPE_REXX, ".TxEd", TYPE_REXX, ".ADPro", TYPE_REXX, ".TEX", TYPE_TEX, ".STY", TYPE_TEX, ".MF", TYPE_METAFONT, ".MOD", TYPE_MOD, ".DEF", TYPE_MOD, ".PS", TYPE_POSTSCRIPT, ".GUIDE", TYPE_AMIGAGUIDE }; /* Some more file name suffixes for executable files and the * approriate file types. */ STATIC struct Suffix ExecutableSuffix[] = { ".device", TYPE_DEVICE, ".library", TYPE_LIBRARY, "FileSystem", TYPE_FILESYS, "Handler", TYPE_HANDLER }; /* LongCompare(UBYTE *Buffer,ULONG Value): * * Compare space in memory with a longword value. */ STATIC BYTE __regargs LongCompare(UBYTE *Buffer,ULONG Value) { UBYTE *OtherBuffer = (UBYTE *)&Value,i; for(i = 0 ; i < 4 ; i++) { if(OtherBuffer[i] != Buffer[i]) return(FALSE); } return(TRUE); } /* Identify(UBYTE *Name): * * Simple routine to identify a file type by looking at * its first 400 bytes. If successful a comment is * attached to the file describing the file type. */ UBYTE __regargs Identify(UBYTE *Name) { ULONG *Buffer; UBYTE Type = TYPE_FILE; WORD i,Len = strlen(Name); UBYTE IFFType[5]; /* Allocate a buffer for the first 410 bytes of the * file. */ if(Buffer = (ULONG *)AllocVec(410,MEMF_PUBLIC)) { BPTR File,Size; /* Open the file. */ if(File = Open(Name,MODE_OLDFILE)) { /* Read the first 410 bytes. */ if((Size = Read(File,Buffer,410)) >= sizeof(ULONG)) { UBYTE *CharBuffer = (UBYTE *)Buffer; WORD Count = 0; /* See if it's an ASCII file. */ for(i = 0 ; i < Size ; i++) { if(ID_ValidTab[CharBuffer[i]]) Count++; else { if(ID_InvalidTab[CharBuffer[i]]) { Count = 0; break; } } } /* If more than 75% of the * characters in the first * 400 bytes are legal * ASCII characters this * file is supposed to be * a text file. */ if(Count > 3 * (Size / 4)) Type = TYPE_TEXT; /* Examine the first longword. */ if(Type == TYPE_FILE) { switch(Buffer[0]) { case 0x000003E7:Type = TYPE_OBJECT; break; case 0x000003F3:Type = TYPE_EXECUTABLE; break; case 0x000003FA:Type = TYPE_LIB; break; case 0xF7593647:Type = TYPE_TEXFONT; break; case 0xF7020183:Type = TYPE_TEXDVI; break; case 0xF7832020:Type = TYPE_GF; break; case 0x504B0304:Type = TYPE_ZIP; break; case 0x01030107:Type = TYPE_SPARCOBJECT; break; case 0x8103010B:Type = TYPE_SPARCEXECUTABLE; break; case 0x59A66A95:Type = TYPE_SUNRASTER; break; case 0x1F9D902A:Type = TYPE_COMPRESSED; break; case 0x30373037:Type = TYPE_CPIO; break; case 'FLIB': Type = TYPE_FLIB; break; case 'FORM': switch(Buffer[2]) { case 'ILBM': Type = TYPE_ILBM; break; case 'ANIM': Type = TYPE_ANIM; break; case '8SVX': Type = TYPE_8SVX; break; case 'SMUS': Type = TYPE_SMUS; break; case 'FTXT': Type = TYPE_FTXT; break; case 'PREF': Type = TYPE_PREFS; break; case 'TERM': Type = TYPE_TERM; break; case 'AVCF': Type = TYPE_AMIGAVISION; break; default: Type = TYPE_IFF; CopyMem(&Buffer[2],IFFType,4); IFFType[4] = 0; break; } break; case 'IMP!': Type = TYPE_IMPLODER; break; case 'PP20': Type = TYPE_POWERPACKER; break; case 'DMS!': Type = TYPE_DMS; break; case 'Warp': Type = TYPE_WARP; break; case 'ZOM5': case 'ZOOM': Type = TYPE_ZOOM; break; case 'ZOO ': Type = TYPE_ZOO; break; case 'GIF8': Type = TYPE_GIF; break; default: break; } } /* Now for oddly placed magic cookies... */ if(Type == TYPE_FILE) { /* Dumb check for PCX (awful header -- just * a single byte indicates that the file * is supposed to be a PCX file! Those * PC guys just don't have any * decent software culture!). */ if(CharBuffer[0] == 0x0A) Type = TYPE_PCX; /* Yet another awful file format... */ if(CharBuffer[0] == 'B' && CharBuffer[1] == 'M') Type = TYPE_BMP; /* Check for JFIF... */ if(LongCompare(&CharBuffer[6],'JFIF')) Type = TYPE_JFIF; } /* Check for Macintosh data (note: * this code assumes that the Mac * binary header is still present, * so if you are dealing with stripped * binary files, don't expect the * following code to work!). */ if(Type == TYPE_FILE) { UBYTE *ByteBuffer = &((UBYTE *)Buffer)[65]; /* Check for MacPaint... */ if(LongCompare(ByteBuffer,'PNTG')) Type = TYPE_MACPAINT; /* Check for SuperPaint... */ if(LongCompare(ByteBuffer,'SPTG')) Type = TYPE_SUPERPAINT; /* Check for PICT... */ if(LongCompare(ByteBuffer,'PICT')) Type = TYPE_PICT; /* Check for executable... */ if(LongCompare(ByteBuffer,'APPL') || LongCompare(ByteBuffer,'PRES') || LongCompare(ByteBuffer,'FDOC') || LongCompare(ByteBuffer,'cdev') || LongCompare(ByteBuffer,'INIT')) Type = TYPE_MACEXECUTABLE; /* Check for StuffIt archive... */ if(LongCompare(ByteBuffer,'SIT!') || LongCompare(ByteBuffer,'SIT2')) Type = TYPE_STUFFIT; /* Check for PackIt archive... */ if(LongCompare(ByteBuffer,'PIT ')) Type = TYPE_PACKIT; /* Check for self-extracting Compact archive. */ if(LongCompare(ByteBuffer,'APPL') && LongCompare(&ByteBuffer[4],'EXTR')) Type = TYPE_COMPACT; /* Check for MacCompress archive. */ if(LongCompare(ByteBuffer,'ZIVM')) Type = TYPE_MACCOMPRESS; /* Check for LhArc archive with MacBinary header. */ if(LongCompare(ByteBuffer,'LARC')) Type = TYPE_LHARC; /* Check for Compact archive. */ if(LongCompare(ByteBuffer,'PACT')) Type = TYPE_COMPACT; /* Check for Diamond archive. */ if(LongCompare(ByteBuffer,'Pack')) Type = TYPE_DIAMOND; } /* Still no match? Have another try... */ if(Type == TYPE_FILE) { if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00) { if(CharBuffer[5] == '5') Type = TYPE_LHA; else Type = TYPE_LHARC; } else { switch(Buffer[0] & 0xFFFF0000) { case 0x4D4D0000: case 0x49490000: Type = TYPE_TIFF; break; case 0x1A080000: Type = TYPE_ARC; break; case 0xEA600000: Type = TYPE_ARJ; break; case 0x434A0000: Type = TYPE_NEWMANX; break; case 0x414A0000: Type = TYPE_OLDMANX; break; case 0x636A0000: Type = TYPE_NEWMANXLIB; break; case 0x616A0000: Type = TYPE_OLDMANXLIB; break; case 0xF5000000: Type = TYPE_BASIC; break; case 0xE3100000: Type = TYPE_ICON; break; case 0x4D5A0000: Type = TYPE_MSDOSEXECUTABLE; break; case 0x601A0000: Type = TYPE_ATARIEXECUTABLE; break; case 0x80000000: Type = TYPE_DEGAS; break; default: break; } } } /* Take a look at the file name * suffixes. */ switch(Type) { case TYPE_TEXT: for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++) { Size = strlen(TextSuffix[i] . Name); if(Len >= Size) { if(!Stricmp(&Name[Len - Size],TextSuffix[i] . Name)) { Type = TextSuffix[i] . Type; break; } } } break; case TYPE_EXECUTABLE: for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++) { Size = strlen(ExecutableSuffix[i] . Name); if(Len >= Size) { if(!Stricmp(&Name[Len - Size],ExecutableSuffix[i] . Name)) { Type = ExecutableSuffix[i] . Type; break; } } } if(Type == TYPE_EXECUTABLE) { if(Buffer[10] == 'LSFX') Type = TYPE_LHPAK; } if(Type == TYPE_EXECUTABLE) { if(Buffer[11] == 'SFX!') Type = TYPE_LHASFX; } break; case TYPE_OBJECT: if(Len >= 4) { if(!Stricmp(&Name[Len - 4],".LIB")) Type = TYPE_LIB; } break; default: break; } } Close(File); } FreeVec(Buffer); } return(Type); }