home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d8xx / d832 / term.lha / Term / term-3.1-Source.lha / termIdentify.c < prev    next >
C/C++ Source or Header  |  1993-02-18  |  14KB  |  740 lines

  1. /*
  2. **    termIdentify.c
  3. **
  4. **    Heuristic file type identification routines (big words!).
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* The file types we know. */
  13.  
  14. enum    {    TYPE_DIR,TYPE_FILE,
  15.         TYPE_ICON,
  16.         TYPE_TEXT,
  17.         TYPE_C,TYPE_H,
  18.         TYPE_ASM,TYPE_I,
  19.         TYPE_MOD,
  20.         TYPE_REXX,
  21.         TYPE_BASIC,
  22.         TYPE_AMIGAGUIDE,
  23.         TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
  24.         TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
  25.         TYPE_OBJECT,TYPE_LIB,
  26.         TYPE_EXECUTABLE,
  27.         TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
  28.         TYPE_GIF,TYPE_DEGAS,TYPE_MACPAINT,TYPE_SUPERPAINT,TYPE_PICT,TYPE_SUNRASTER,TYPE_POSTSCRIPT,TYPE_PCX,TYPE_TIFF,TYPE_BMP,TYPE_JFIF,TYPE_ILBM,
  29.         TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,TYPE_AMIGAVISION,TYPE_IFF,
  30.         TYPE_IMPLODER,TYPE_POWERPACKER,TYPE_LHPAK,TYPE_LHASFX,
  31.         TYPE_ARC,TYPE_ARJ,TYPE_COMPRESSED,TYPE_CPIO,TYPE_UUENCODED,TYPE_FREEZE,TYPE_MACCOMPRESS,TYPE_COMPACT,TYPE_DIAMOND,TYPE_LHARC,TYPE_LHA,TYPE_ZOO,TYPE_ZIP,TYPE_STUFFIT,TYPE_PACKIT,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
  32.         TYPE_SPARCOBJECT,TYPE_SPARCEXECUTABLE,
  33.         TYPE_MSDOSEXECUTABLE,
  34.         TYPE_ATARIEXECUTABLE,
  35.         TYPE_MACEXECUTABLE,
  36.         TYPE_CDAF,TYPE_XPK
  37.     };
  38.  
  39.     /* A structure containing both a file name suffix and the
  40.      * approriate file type.
  41.      */
  42.  
  43. struct Suffix
  44. {
  45.     UBYTE    *Name;
  46.     UBYTE     Type;
  47. };
  48.  
  49.     /* A table of valid ASCII characters (7 bits). */
  50.  
  51. STATIC BYTE ID_ValidTab[256] =
  52. {
  53.     0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
  54.     0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
  55.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  56.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  57.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  58.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  59.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  60.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  61.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  62.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  63.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  64.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  65.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  66.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  67.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  68.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  69. };
  70.  
  71.     /* A table of clearly invalid ASCII characters (8 bits). */
  72.  
  73. STATIC BYTE ID_InvalidTab[256] =
  74. {
  75.     1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
  76.     1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
  77.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  78.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  79.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  80.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  81.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  82.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  83.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  84.     1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
  85.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  86.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  87.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  88.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  89.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  90.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  91. };
  92.  
  93.     /* Some file name suffixes for text files and the approriate
  94.      * file types.
  95.      */
  96.  
  97. STATIC struct Suffix TextSuffix[] =
  98. {
  99.     ".C",        TYPE_C,
  100.     ".CPP",        TYPE_C,
  101.     ".CXX",        TYPE_C,
  102.     ".C++",        TYPE_C,
  103.     ".CC",        TYPE_C,
  104.     ".H",        TYPE_H,
  105.     ".ASM",        TYPE_ASM,
  106.     ".A",        TYPE_ASM,
  107.     ".S",        TYPE_ASM,
  108.     ".I",        TYPE_I,
  109.     ".BAS",        TYPE_BASIC,
  110.     ".GFA",        TYPE_BASIC,
  111.     ".REXX",    TYPE_REXX,
  112.     ".CED",        TYPE_REXX,
  113.     ".TTX",        TYPE_REXX,
  114.     ".VLT",        TYPE_REXX,
  115.     ".CPR",        TYPE_REXX,
  116.     ".TxEd",    TYPE_REXX,
  117.     ".ADPro",    TYPE_REXX,
  118.     ".TEX",        TYPE_TEX,
  119.     ".STY",        TYPE_TEX,
  120.     ".MF",        TYPE_METAFONT,
  121.     ".MOD",        TYPE_MOD,
  122.     ".DEF",        TYPE_MOD,
  123.     ".PS",        TYPE_POSTSCRIPT,
  124.     ".GUIDE",    TYPE_AMIGAGUIDE,
  125.     ".UUE",        TYPE_UUENCODED
  126. };
  127.  
  128.     /* Some more file name suffixes for executable files and the
  129.      * approriate file types.
  130.      */
  131.  
  132. STATIC struct Suffix ExecutableSuffix[] =
  133. {
  134.     ".device",    TYPE_DEVICE,
  135.     ".library",    TYPE_LIBRARY,
  136.     "FileSystem",    TYPE_FILESYS,
  137.     "Handler",    TYPE_HANDLER
  138. };
  139.  
  140.     /* Miscellaneous magic cookies. */
  141.  
  142. STATIC STRPTR MagicCookies[] =
  143. {
  144.     "P1",
  145.     "P2",
  146.     "P3",
  147.     "P4",
  148.     "P5",
  149.     "P6",
  150.     "begin",
  151.     "xbtoa"
  152. };
  153.  
  154.     /* LongCompare(UBYTE *Buffer,ULONG Value):
  155.      *
  156.      *    Compare space in memory with a longword value.
  157.      */
  158.  
  159. STATIC BYTE __regargs
  160. LongCompare(UBYTE *Buffer,ULONG Value)
  161. {
  162.     UBYTE *OtherBuffer = (UBYTE *)&Value,i;
  163.  
  164.     for(i = 0 ; i < 4 ; i++)
  165.     {
  166.         if(OtherBuffer[i] != Buffer[i])
  167.             return(FALSE);
  168.     }
  169.  
  170.     return(TRUE);
  171. }
  172.  
  173.     /* Identify(STRPTR Name):
  174.      *
  175.      *    Simple routine to identify a file type by looking at
  176.      *    its first 400 bytes. If successful a comment is
  177.      *    attached to the file describing the file type.
  178.      */
  179.  
  180. VOID
  181. Identify(STRPTR Name)
  182. {
  183.     ULONG    *Buffer;
  184.     UBYTE     Type        = TYPE_FILE,
  185.         *TypeName    = NULL;
  186.     WORD     i,
  187.          Len = strlen(Name);
  188.     UBYTE     IFFType[5];
  189.  
  190.         /* Allocate a buffer for the first 410 bytes of the
  191.          * file.
  192.          */
  193.  
  194.     if(Buffer = (ULONG *)AllocVec(410,MEMF_ANY | MEMF_CLEAR))
  195.     {
  196.         BPTR File,Size;
  197.  
  198.             /* Open the file. */
  199.  
  200.         if(File = Open(Name,MODE_OLDFILE))
  201.         {
  202.                 /* Read the first 410 bytes. */
  203.  
  204.             if((Size = Read(File,Buffer,410)) >= sizeof(ULONG))
  205.             {
  206.                 UBYTE    *CharBuffer = (UBYTE *)Buffer;
  207.                 WORD     Count = 0;
  208.  
  209.                     /* See if it's an ASCII file. */
  210.  
  211.                 for(i = 0 ; i < Size ; i++)
  212.                 {
  213.                     if(ID_ValidTab[CharBuffer[i]])
  214.                         Count++;
  215.                     else
  216.                     {
  217.                         if(ID_InvalidTab[CharBuffer[i]])
  218.                         {
  219.                             Count = 0;
  220.  
  221.                             break;
  222.                         }
  223.                     }
  224.                 }
  225.  
  226.                     /* If more than 75% of the
  227.                      * characters in the first
  228.                      * 400 bytes are legal
  229.                      * ASCII characters this
  230.                      * file is supposed to be
  231.                      * a text file.
  232.                      */
  233.  
  234.                 if(Count > 3 * (Size / 4))
  235.                     Type = TYPE_TEXT;
  236.  
  237.                     /* Examine the first longword. */
  238.  
  239.                 if(Type == TYPE_FILE)
  240.                 {
  241.                     switch(Buffer[0])
  242.                     {
  243.                         case 0x58504B46:
  244.  
  245.                             Type = TYPE_XPK;
  246.                             break;
  247.  
  248.                         case 0x000003E7:
  249.  
  250.                             Type = TYPE_OBJECT;
  251.                             break;
  252.  
  253.                         case 0x000003F3:
  254.  
  255.                             if(Buffer[10] == 'LSFX')
  256.                                 Type = TYPE_LHPAK;
  257.                             else
  258.                             {
  259.                                 if(Buffer[11] == 'SFX!')
  260.                                     Type = TYPE_LHASFX;
  261.                                 else
  262.                                     Type = TYPE_EXECUTABLE;
  263.                             }
  264.  
  265.                             break;
  266.  
  267.                         case 0x000003FA:
  268.  
  269.                             Type = TYPE_LIB;
  270.                             break;
  271.  
  272.                         case 0xF7593647:
  273.  
  274.                             Type = TYPE_TEXFONT;
  275.                             break;
  276.  
  277.                         case 0xF7020183:
  278.  
  279.                             Type = TYPE_TEXDVI;
  280.                             break;
  281.  
  282.                         case 0xF7832020:
  283.  
  284.                             Type = TYPE_GF;
  285.                             break;
  286.  
  287.                         case 0x504B0304:
  288.  
  289.                             Type = TYPE_ZIP;
  290.                             break;
  291.  
  292.                         case 0x01030107:
  293.  
  294.                             Type = TYPE_SPARCOBJECT;
  295.                             break;
  296.  
  297.                         case 0x8103010B:
  298.  
  299.                             Type = TYPE_SPARCEXECUTABLE;
  300.                             break;
  301.  
  302.                         case 0x59A66A95:
  303.  
  304.                             Type = TYPE_SUNRASTER;
  305.                             break;
  306.  
  307.                         case 0x1F9D902A:
  308.  
  309.                             Type = TYPE_COMPRESSED;
  310.                             break;
  311.  
  312.                         case 0x30373037:
  313.  
  314.                             Type = TYPE_CPIO;
  315.                             break;
  316.  
  317.                         case 'FLIB':
  318.  
  319.                             Type = TYPE_FLIB;
  320.                             break;
  321.  
  322.                         case 'FORM':
  323.  
  324.                             switch(Buffer[2])
  325.                             {
  326.                                 case 'ILBM':
  327.  
  328.                                     Type = TYPE_ILBM;
  329.                                     break;
  330.  
  331.                                 case 'ANIM':
  332.  
  333.                                     Type = TYPE_ANIM;
  334.                                     break;
  335.  
  336.                                 case '8SVX':
  337.  
  338.                                     Type = TYPE_8SVX;
  339.                                     break;
  340.  
  341.                                 case 'SMUS':
  342.  
  343.                                     Type = TYPE_SMUS;
  344.                                     break;
  345.  
  346.                                 case 'FTXT':
  347.  
  348.                                     Type = TYPE_FTXT;
  349.                                     break;
  350.  
  351.                                 case 'PREF':
  352.  
  353.                                     Type = TYPE_PREFS;
  354.                                     break;
  355.  
  356.                                 case 'TERM':
  357.  
  358.                                     Type = TYPE_TERM;
  359.                                     break;
  360.  
  361.                                 case 'AVCF':
  362.  
  363.                                     Type = TYPE_AMIGAVISION;
  364.                                     break;
  365.  
  366.                                 case 'CDAF':
  367.  
  368.                                     Type = TYPE_CDAF;
  369.                                     break;
  370.  
  371.                                 default:
  372.  
  373.                                     Type = TYPE_IFF;
  374.  
  375.                                     CopyMem(&Buffer[2],IFFType,4);
  376.  
  377.                                     IFFType[4] = 0;
  378.  
  379.                                     break;
  380.                             }
  381.  
  382.                             break;
  383.  
  384.                         case 'IMP!':
  385.  
  386.                             Type = TYPE_IMPLODER;
  387.                             break;
  388.  
  389.                         case 'PP20':
  390.  
  391.                             Type = TYPE_POWERPACKER;
  392.                             break;
  393.  
  394.                         case 'DMS!':
  395.  
  396.                             Type = TYPE_DMS;
  397.                             break;
  398.  
  399.                         case 'Warp':
  400.  
  401.                             Type = TYPE_WARP;
  402.                             break;
  403.  
  404.                         case 'ZOM5':
  405.                         case 'ZOOM':
  406.  
  407.                             Type = TYPE_ZOOM;
  408.                             break;
  409.  
  410.                         case 'ZOO ':
  411.  
  412.                             Type = TYPE_ZOO;
  413.                             break;
  414.  
  415.                         case 'GIF8':
  416.  
  417.                             Type = TYPE_GIF;
  418.                             break;
  419.                     }
  420.                 }
  421.  
  422.                     /* Now for oddly placed magic cookies... */
  423.  
  424.                 if(Type == TYPE_FILE)
  425.                 {
  426.                         /* Dumb check for PCX (awful header -- just
  427.                          * a single byte indicates that the file
  428.                          * is supposed to be a PCX file! Those
  429.                          * PC guys just don't have any
  430.                          * decent software culture!).
  431.                          */
  432.  
  433.                     if(CharBuffer[0] == 0x0A)
  434.                         Type = TYPE_PCX;
  435.  
  436.                         /* Yet another awful file format... */
  437.  
  438.                     if(CharBuffer[0] == 'B' && CharBuffer[1] == 'M')
  439.                         Type = TYPE_BMP;
  440.  
  441.                         /* Check for JFIF... */
  442.  
  443.                     if(LongCompare(&CharBuffer[6],'JFIF'))
  444.                         Type = TYPE_JFIF;
  445.  
  446.                         /* Check for `freeze' output file. */
  447.  
  448.                     if(CharBuffer[0] == (UBYTE)'\037' && CharBuffer[1] >= (UBYTE)'\236')
  449.                         Type = TYPE_FREEZE;
  450.                 }
  451.  
  452.                     /* Check for Macintosh data (note:
  453.                      * this code assumes that the Mac
  454.                      * binary header is still present,
  455.                      * so if you are dealing with stripped
  456.                      * binary files, don't expect the
  457.                      * following code to work!).
  458.                      */
  459.  
  460.                 if(Type == TYPE_FILE)
  461.                 {
  462.                     UBYTE *ByteBuffer = &((UBYTE *)Buffer)[65];
  463.  
  464.                         /* Check for MacPaint... */
  465.  
  466.                     if(LongCompare(ByteBuffer,'PNTG'))
  467.                         Type = TYPE_MACPAINT;
  468.  
  469.                         /* Check for SuperPaint... */
  470.  
  471.                     if(LongCompare(ByteBuffer,'SPTG'))
  472.                         Type = TYPE_SUPERPAINT;
  473.  
  474.                         /* Check for PICT... */
  475.  
  476.                     if(LongCompare(ByteBuffer,'PICT'))
  477.                         Type = TYPE_PICT;
  478.  
  479.                         /* Check for executable... */
  480.  
  481.                     if(LongCompare(ByteBuffer,'APPL') || LongCompare(ByteBuffer,'PRES') || LongCompare(ByteBuffer,'FDOC') || LongCompare(ByteBuffer,'cdev') || LongCompare(ByteBuffer,'INIT'))
  482.                         Type = TYPE_MACEXECUTABLE;
  483.  
  484.                         /* Check for StuffIt archive... */
  485.  
  486.                     if(LongCompare(ByteBuffer,'SIT!') || LongCompare(ByteBuffer,'SIT2'))
  487.                         Type = TYPE_STUFFIT;
  488.  
  489.                         /* Check for PackIt archive... */
  490.  
  491.                     if(LongCompare(ByteBuffer,'PIT '))
  492.                         Type = TYPE_PACKIT;
  493.  
  494.                         /* Check for self-extracting Compact archive. */
  495.  
  496.                     if(LongCompare(ByteBuffer,'APPL') && LongCompare(&ByteBuffer[4],'EXTR'))
  497.                         Type = TYPE_COMPACT;
  498.  
  499.                         /* Check for MacCompress archive. */
  500.  
  501.                     if(LongCompare(ByteBuffer,'ZIVM'))
  502.                         Type = TYPE_MACCOMPRESS;
  503.  
  504.                         /* Check for LhArc archive with MacBinary header. */
  505.  
  506.                     if(LongCompare(ByteBuffer,'LARC'))
  507.                         Type = TYPE_LHARC;
  508.  
  509.                         /* Check for Compact archive. */
  510.  
  511.                     if(LongCompare(ByteBuffer,'PACT'))
  512.                         Type = TYPE_COMPACT;
  513.  
  514.                         /* Check for Diamond archive. */
  515.  
  516.                     if(LongCompare(ByteBuffer,'Pack'))
  517.                         Type = TYPE_DIAMOND;
  518.                 }
  519.  
  520.                     /* Still no match? Have another try... */
  521.  
  522.                 if(Type == TYPE_FILE)
  523.                 {
  524.                     if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
  525.                     {
  526.                         if(CharBuffer[5] == '5')
  527.                             Type = TYPE_LHA;
  528.                         else
  529.                             Type = TYPE_LHARC;
  530.                     }
  531.                     else
  532.                     {
  533.                         switch(Buffer[0] & 0xFFFF0000)
  534.                         {
  535.                             case 0x4D4D0000:
  536.                             case 0x49490000:
  537.  
  538.                                 Type = TYPE_TIFF;
  539.                                 break;
  540.  
  541.                             case 0x1A080000:
  542.  
  543.                                 Type = TYPE_ARC;
  544.                                 break;
  545.  
  546.                             case 0x60EA0000:
  547.  
  548.                                 Type = TYPE_ARJ;
  549.                                 break;
  550.  
  551.                             case 0x434A0000:
  552.  
  553.                                 Type = TYPE_NEWMANX;
  554.                                 break;
  555.  
  556.                             case 0x414A0000:
  557.  
  558.                                 Type = TYPE_OLDMANX;
  559.                                 break;
  560.  
  561.                             case 0x636A0000:
  562.  
  563.                                 Type = TYPE_NEWMANXLIB;
  564.                                 break;
  565.  
  566.                             case 0x616A0000:
  567.  
  568.                                 Type = TYPE_OLDMANXLIB;
  569.                                 break;
  570.  
  571.                             case 0xF5000000:
  572.  
  573.                                 Type = TYPE_BASIC;
  574.                                 break;
  575.  
  576.                             case 0xE3100000:
  577.  
  578.                                 Type = TYPE_ICON;
  579.                                 break;
  580.  
  581.                             case 0x4D5A0000:
  582.  
  583.                                 Type = TYPE_MSDOSEXECUTABLE;
  584.                                 break;
  585.  
  586.                             case 0x601A0000:
  587.  
  588.                                 Type = TYPE_ATARIEXECUTABLE;
  589.                                 break;
  590.  
  591.                             case 0x80000000:
  592.  
  593.                                 Type = TYPE_DEGAS;
  594.                                 break;
  595.                         }
  596.                     }
  597.                 }
  598.  
  599.                     /* Take a look at the file name
  600.                      * suffixes.
  601.                      */
  602.  
  603.                 switch(Type)
  604.                 {
  605.                     case TYPE_TEXT:
  606.  
  607.                         for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
  608.                         {
  609.                             Size = strlen(TextSuffix[i] . Name);
  610.  
  611.                             if(Len >= Size)
  612.                             {
  613.                                 if(!Stricmp(&Name[Len - Size],TextSuffix[i] . Name))
  614.                                 {
  615.                                     Type = TextSuffix[i] . Type;
  616.                                     break;
  617.                                 }
  618.                             }
  619.                         }
  620.  
  621.                             /* Is it still a text file? */
  622.  
  623.                         if(Type == TYPE_TEXT)
  624.                         {
  625.                                 /* Check for magic cookies. */
  626.  
  627.                             for(i = 0 ; i < sizeof(MagicCookies) / sizeof(STRPTR) ; i++)
  628.                             {
  629.                                 if(!memcmp(CharBuffer,MagicCookies[i],strlen(MagicCookies[i])))
  630.                                 {
  631.                                     TypeName = LocaleString(MSG_IDENTIFY_COOKIE_0 + i);
  632.  
  633.                                     break;
  634.                                 }
  635.                             }
  636.                         }
  637.  
  638.                         break;
  639.  
  640.                     case TYPE_EXECUTABLE:
  641.  
  642.                         for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
  643.                         {
  644.                             Size = strlen(ExecutableSuffix[i] . Name);
  645.  
  646.                             if(Len >= Size)
  647.                             {
  648.                                 if(!Stricmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
  649.                                 {
  650.                                     Type = ExecutableSuffix[i] . Type;
  651.                                     break;
  652.                                 }
  653.                             }
  654.                         }
  655.  
  656.                         break;
  657.  
  658.                     case TYPE_OBJECT:
  659.  
  660.                         if(Len >= 4)
  661.                         {
  662.                             if(!Stricmp(&Name[Len - 4],".LIB"))
  663.                                 Type = TYPE_LIB;
  664.                         }
  665.  
  666.                         break;
  667.                 }
  668.             }
  669.  
  670.             Close(File);
  671.         }
  672.  
  673.         FreeVec(Buffer);
  674.     }
  675.  
  676.     if(Type > TYPE_FILE || TypeName)
  677.     {
  678.         if(Type == TYPE_IFF)
  679.         {
  680.             UBYTE NameBuffer[40];
  681.  
  682.             SPrintf(NameBuffer,LocaleString(MSG_IDENTIFY_IFF_FILE),IFFType);
  683.  
  684.             SetComment(Name,NameBuffer);
  685.         }
  686.         else
  687.         {
  688.             if(TypeName)
  689.                 SetComment(Name,TypeName);
  690.             else
  691.                 SetComment(Name,LocaleString(MSG_IDENTIFY_FILETYPE_0 + Type - TYPE_ICON));
  692.         }
  693.     }
  694.  
  695.         /* Is it an executable file? */
  696.  
  697.     if(Type != TYPE_EXECUTABLE && Type != TYPE_LHPAK && Type != TYPE_LHASFX)
  698.     {
  699.         BPTR FileLock;
  700.  
  701.             /* Get a lock on it. */
  702.  
  703.         if(FileLock = Lock(Name,ACCESS_WRITE))
  704.         {
  705.             struct FileInfoBlock *FileInfo;
  706.  
  707.                 /* Allocate fileinfo data. */
  708.  
  709.             if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
  710.             {
  711.                     /* Take a closer look at it... */
  712.  
  713.                 if(Examine(FileLock,FileInfo))
  714.                 {
  715.                         /* Release the lock. */
  716.  
  717.                     UnLock(FileLock);
  718.  
  719.                         /* Really drop it. */
  720.  
  721.                     FileLock = NULL;
  722.  
  723.                         /* Update protection bits. */
  724.  
  725.                     SetProtection(Name,FileInfo -> fib_Protection | FIBF_EXECUTE);
  726.                 }
  727.  
  728.                     /* Free fileinfo data. */
  729.  
  730.                 FreeDosObject(DOS_FIB,FileInfo);
  731.             }
  732.         }
  733.  
  734.             /* Release the lock if still allocated. */
  735.  
  736.         if(FileLock)
  737.             UnLock(FileLock);
  738.     }
  739. }
  740.