home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / FILEINFO.ZIP / FILE.C next >
Text File  |  1990-08-14  |  16KB  |  527 lines

  1. //
  2. //  file.c
  3. //
  4. //  Portions of this program are taken from a program by Ray Duncan
  5. //  published in PC Magazine called SHOWEA.  Those protions are:
  6. //
  7. //    Copyright (C) 1989 Ziff-Davis Communications
  8. //
  9. //  The original portions are:
  10. //
  11. //    Copyright (C) 1990, Brady Flowers
  12. //
  13. //  I compiled this with MSC 6.0 and the following compile command:
  14. //
  15. //    cl -AL -Zep -Oxaz -Grs -Lp -W3 file.c file.def
  16. //
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <memory.h>
  22. #include <malloc.h>
  23.  
  24. #define INCL_DOS
  25. #define INCL_DOSERRORS
  26. #include <os2.h>
  27.  
  28. // --------------------------------------------------------------------------
  29.  
  30. #define dim(x) (sizeof(x)/sizeof(x[0])) // number of elements in structure
  31.  
  32. #define EABUF_SIZE      16384           // size of EA buffer
  33. #define MAXPATHNAME     260             // maximum length of pathname
  34. #define MAXFILENAME     255             // maximum length of filename
  35.  
  36. #define FILE_ANY (FILE_READONLY|FILE_HIDDEN|FILE_SYSTEM|FILE_DIRECTORY|FILE_ARCHIVED)
  37.  
  38. // --------------------------------------------------------------------------
  39.  
  40. void GetCountryInfo(void);
  41. void ShowTimeStamp(PFDATE pD, PFTIME pT);
  42. void ShowAttributes(USHORT attr);
  43. void showapptype(char *filename);
  44. void showeas(char *filename);           // local function prototypes
  45. void showea(void);
  46. int  findtype(unsigned EAtype);
  47. void fmtUNKNOWN(void);
  48. void fmtBINARY(void);
  49. void fmtASCII(void);
  50. void fmtBITMAP(void);
  51. void fmtMETAFILE(void);
  52. void fmtICON(void);   
  53. void fmtEA(void);  
  54. void fmtMVMT(void);   
  55. void fmtMVST(void);   
  56. void fmtASN1(void);
  57. int  _cdecl main(int argc, char **argv);
  58.  
  59. // --------------------------------------------------------------------------
  60.  
  61. struct _EA                        // extended attribute header 
  62. {
  63.   unsigned char flags;            // critical flag etc.
  64.   unsigned char nsize;            // length of EA name (without null)
  65.   unsigned vsize;                 // total size of EA value
  66.   char name[1];                   // EA name and value begin here
  67. };
  68.  
  69. struct _EAvalue                   // extended attribute value 
  70. {
  71.   unsigned type;                  // EA value type
  72.   unsigned size;                  // length of EA variable data
  73.   char data[1];                   // actual data begins here
  74. };
  75.  
  76.  
  77. // --------------------------------------------------------------------------
  78.  
  79.  
  80. struct _EAtable                   // lookup table of EA types
  81. {
  82.   unsigned type;                  // binary type indicator
  83.   char *name;                     // descriptive text
  84.   void (*formatter)(void);        // formatting routine
  85. } EAtable[] = {
  86.                 0,              "unknown EA type",          fmtUNKNOWN,
  87.                 EAT_BINARY,     "length-preceeded binary",  fmtBINARY,
  88.                 EAT_ASCII,      "length-preceeded ASCII",   fmtASCII,
  89.                 EAT_BITMAP,     "length-preceeded bitmap",  fmtBITMAP,
  90.                 EAT_METAFILE,   "metafile",                 fmtMETAFILE,
  91.                 EAT_ICON,       "length-preceeded icon",    fmtICON,
  92.                 EAT_EA,         "associated EA data",       fmtEA,
  93.                 EAT_MVMT,       "multi-value multi-type",   fmtMVMT,
  94.                 EAT_MVST,       "multi-value single-type",  fmtMVST,
  95.                 EAT_ASN1,       "ASN.1",                    fmtASN1,
  96.               };
  97.  
  98.  
  99. char            *fname;                 // pointer to qualified pathname
  100. FEALIST         *FEAList;               // pointer to EA buffer
  101. struct _EA      *pEA;                   // pointer to individual EA header
  102. struct _EAvalue *pEAval;                // pointer to individual EA value
  103.  
  104. char            Argv[MAXPATHNAME];
  105. PSZ             pszDateSep;
  106. PSZ             pszTimeSep;
  107. USHORT          usDateFmt;
  108. USHORT          usTimeFmt;
  109. USHORT          usRecurLevel = 0;
  110.  
  111. // --------------------------------------------------------------------------
  112.  
  113.  
  114. void GetCountryInfo()
  115. {
  116.   COUNTRYCODE countryCode = { 0, 0 };
  117.   COUNTRYINFO countryInfo;
  118.   USHORT      rVal, usInfo;
  119.  
  120.   if (rVal = DosGetCtryInfo(sizeof(countryInfo), &countryCode, &countryInfo, &usInfo))
  121.   {
  122.     printf("ERROR 0x%04x: Getting country information.\n");
  123.     exit(1);
  124.   }
  125.  
  126.   pszDateSep = strdup(countryInfo.szDateSeparator);
  127.   pszTimeSep = strdup(countryInfo.szTimeSeparator);
  128.   usDateFmt  = countryInfo.fsDateFmt;
  129.   usTimeFmt  = countryInfo.fsTimeFmt;
  130. }
  131.  
  132.  
  133. // --------------------------------------------------------------------------
  134.  
  135.  
  136. void ShowTimeStamp(PFDATE pD, PFTIME pT)
  137. {
  138.   PSZ p;
  139.   USHORT usTmp, usPM = FALSE;
  140.  
  141.   p = pszDateSep;
  142.   switch (usDateFmt)
  143.   {
  144.     case DATEFMT_MM_DD_YY:
  145.       printf("%02d%s%02d%s%04d ", pD->month, p, pD->day, p, pD->year + 1980);
  146.       break;
  147.     case DATEFMT_DD_MM_YY:
  148.       printf("%02d%s%02d%s%04d ", pD->day, p, pD->month, p, pD->year + 1980);
  149.       break;
  150.     case DATEFMT_YY_MM_DD:
  151.       printf("%4d%s%02d%s%02d ", pD->year + 1980, p, pD->month, p, pD->day);
  152.       break;
  153.   }
  154.   p = pszTimeSep;
  155.   if (usTimeFmt)
  156.     printf("%02d%s%02d%s%0d", pT->hours, p, pT->minutes, p, pT->twosecs * 2);
  157.   else
  158.   {
  159.     if (pT->hours > 11) usPM = TRUE;
  160.     if (pT->hours > 12)
  161.       usTmp = pT->hours - 12;
  162.     else
  163.       usTmp = pT->hours;
  164.  
  165.     printf("%2d%s%02d%s%02d %s", usTmp, p, pT->minutes, p, pT->twosecs * 2, usPM ? "pm" : "am");
  166.   }
  167.   puts("");
  168. }
  169.  
  170.  
  171.  
  172. void ShowAttributes(USHORT attr)
  173. {
  174.  
  175.   if (attr)
  176.   {
  177.     printf("Attributes:");
  178.     if (attr & FILE_READONLY)  printf(" READONLY");
  179.     if (attr & FILE_HIDDEN)    printf(" HIDDEN");
  180.     if (attr & FILE_SYSTEM)    printf(" SYSTEM");
  181.     if (attr & FILE_DIRECTORY) printf(" DIRECTORY");
  182.     if (attr & FILE_ARCHIVED)  printf(" ARCHIVED");
  183.     puts("");
  184.   }
  185. }
  186.  
  187.  
  188.  
  189. // --------------------------------------------------------------------------
  190.  
  191.  
  192. void showapptype(char *filename)
  193. {
  194.   USHORT rVal, usAppType;
  195.  
  196.   if (rVal = DosQAppType(filename, &usAppType))
  197.   {
  198.     switch (rVal)
  199.     {
  200.       case ERROR_INVALID_EXE_SIGNATURE:
  201.       case ERROR_BAD_EXE_FORMAT:
  202.         // printf(" Not an Executable File\n");
  203.         break;
  204.       case ERROR_EXE_MARKED_INVALID:
  205.         printf("ERROR 0x%04x: Bad mark on Executable file\n", rVal);
  206.         break;
  207.       case ERROR_SHARING_VIOLATION:
  208.         printf("Cannot access file for Application Type\n");
  209.         break;
  210.       default:
  211.         printf("ERROR 0x%04x: execing DosQAppType.\n", rVal);
  212.         break;
  213.     }
  214.     return;
  215.   }
  216.  
  217.   printf("Application type:");
  218.   if (usAppType == NOTSPECIFIED)
  219.     printf(" NOTSPECIFIED");
  220.   else
  221.   {
  222.     if ((usAppType & WINDOWAPI) == WINDOWAPI)
  223.       printf(" WINDOWAPI");
  224.     else
  225.     {
  226.       if ((usAppType & NOTWINDOCOMPAT) == NOTWINDOCOMPAT) printf(" NOTWINDOWCOMPAT");
  227.       if ((usAppType & WINDOWCOMPAT)   == WINDOWCOMPAT)   printf(" WINDOWCOMPAT");
  228.     }
  229.     if ((usAppType & BOUND)          == BOUND)          printf(" BOUND");
  230.     if ((usAppType & DYNAMICLINK)    == DYNAMICLINK)    printf(" DYNAMICLINK");
  231.     if ((usAppType & DOSFORMAT)      == DOSFORMAT)      printf(" DOSFORMAT");
  232.   }
  233.   puts("");                           // extra blank line
  234. }
  235.  
  236.  
  237.  
  238. // --------------------------------------------------------------------------
  239.  
  240.  
  241. void showeas(char *filename)
  242. {
  243.   EAOP eaop;                          // holds pointers for DosQPathInfo
  244.   int  error;                         // error code from DosQPathInfo
  245.  
  246.   if (!FEAList)
  247.   {
  248.     FEAList   = malloc(EABUF_SIZE);     // allocate EA buffer and
  249.     fname     = malloc(MAXPATHNAME);    // qualified pathname buffer
  250.   }
  251.  
  252.   if ((FEAList == NULL) || (fname == NULL))
  253.   {
  254.     // ---- exit if not enough heap 
  255.     printf("ERROR 0x%04x: heap allocation error\n", ERROR_NOT_ENOUGH_MEMORY);
  256.     exit(2);
  257.   }
  258.  
  259.   eaop.fpGEAList = NULL;               // initialize EAOP components
  260.   eaop.fpFEAList = FEAList;            // and buffer to receive EAs
  261.   eaop.oError = 0L;
  262.   FEAList->cbList = EABUF_SIZE - sizeof(unsigned long);
  263.  
  264.   if (error = DosQPathInfo(filename,  // retrieve EAs using filename
  265.                   4,                  // info level 4 = get all EAs
  266.                   (PBYTE)&eaop,       // buffer to receieve EAs
  267.                   sizeof(eaop),       // size of buffer
  268.                   0L))                // reserved
  269.   {   
  270.     if (error == ERROR_BUFFER_OVERFLOW)
  271.     {
  272.       printf("ERROR 0x04x: EA buffer too small\n", error);
  273.       exit(3);
  274.     }
  275.     else if (error == ERROR_SHARING_VIOLATION)
  276.       printf("Cannot access file for Extended Attributes\n");
  277.     else
  278.       printf("ERROR 0x%04x: execing DosQPathInfo for: \'%s\'\n", error, filename);
  279.     return;
  280.   }
  281.  
  282.   // ---- display full pathname
  283.   DosQPathInfo(filename, 5, fname, MAXPATHNAME, 0L);
  284.  
  285.   if (FEAList->cbList == sizeof(unsigned long))
  286.   {
  287.     // printf(" None found.\n");
  288.     return;
  289.   }
  290.  
  291.   printf("Extended Attributes:\n");
  292.   printf("Name        Type                       Value");
  293.   
  294.   pEA = (struct _EA *) FEAList->list; // point to first EA
  295.  
  296.   while((char *)pEA < ((char *)(FEAList->list)+FEAList->cbList-sizeof(unsigned long)))
  297.   {                               
  298.     (char *) pEAval =               // point to EA value
  299.         pEA->name + pEA->nsize + 1;
  300.  
  301.     showea();                       // display this EA name & value
  302.  
  303.     (char *) pEA =                  // go to next EA
  304.         pEA->name + pEA->nsize + pEA->vsize + 1;
  305.   }
  306.   
  307.   puts("");                           // extra blank line
  308. }
  309.  
  310.  
  311. /*
  312.     SHOWEA: format and display current extended attribute.
  313. */
  314. void showea()
  315. {
  316.     int i;                              // scratch variable
  317.  
  318.     i = findtype(pEAval->type);         // look up the EA type
  319.  
  320.     printf("\n%-10.10s  %-25.25s  ",    // display EA name, value type
  321.            pEA->name, EAtable[i].name);
  322.  
  323.     (*(EAtable[i].formatter))();        // call type-specific routine
  324. }                                       // to display EA value
  325.  
  326. /*
  327.     FINDTYPE: look up extended attribute type in EAtable.
  328. */
  329. int findtype(unsigned EAtype)
  330. {
  331.     int i;                              // scratch variable
  332.  
  333.     for(i = 1; i < dim(EAtable); i++)   // skip dummy entry EAtable[0]
  334.     {
  335.         if(EAtable[i].type == EAtype)   // if we matched EA type
  336.             return(i);                  // return EAtable index
  337.     }
  338.  
  339.     return(0);                          // no match, return 0
  340. }
  341.  
  342. /*
  343.     The routines below perform formatting and output of the value
  344.     for each EA type.  In this version of the demo program only 
  345.     the length-preceded ASCII, length-preceded simple binary, and 
  346.     multi-type multi-value types are implemented.  
  347.     The remainder are dummy functions that do nothing.
  348. */
  349.  
  350. void fmtUNKNOWN()                       // unknown EA type
  351. {
  352.     fmtBINARY();
  353. }
  354.  
  355. void fmtBINARY()                        // length-preceded binary
  356. {
  357.     int i;                              // scratch variable
  358.  
  359.     for(i = 0; i < min(8, pEAval->size); i++)   // display binary data
  360.         printf("%02X ", pEAval->data[i]);   
  361.  
  362.     if(pEAval->size > 8) printf("..."); // indicate there is more
  363. }
  364.  
  365. void fmtASCII()                         // length-preceded ASCII string
  366. {
  367.     printf("%.*s", pEAval->size, pEAval->data);
  368. }
  369.  
  370. void fmtBITMAP()                        // length-preceded bitmap
  371. {
  372.     fmtBINARY();
  373. }
  374.  
  375. void fmtMETAFILE()                      // length-preceded metafile
  376. {
  377.     fmtBINARY();
  378. }
  379.  
  380. void fmtICON()                          // length-preceded icon
  381. {
  382.     fmtBINARY();
  383. }
  384.  
  385. void fmtEA()                            // ASCIIZ extended attribute
  386. {                                       // name of associated data
  387.     printf("%s", (char *) &pEAval->size);
  388. }
  389.  
  390. void fmtMVMT()                          // multi-value multi-type
  391. {
  392.     int i;                              // scratch variable
  393.     int fields;                         // number of value fields
  394.  
  395.     strcpy(pEA->name, "");              // erase EA name 
  396.     fields = *((int *)(pEAval->data));  // retrieve number of fields
  397.     (char *) pEAval =                   // point to first field
  398.         pEAval->data + sizeof(int);
  399.  
  400.     for(i = 0; i < fields; i++)         // loop across value fields
  401.     {
  402.         showea();                       // display this value field
  403.  
  404.         (char *) pEAval =               // point to next value
  405.             pEAval->data + pEAval->size; 
  406.     }
  407. }
  408.  
  409. void fmtMVST()                          // multi-value single-type
  410. {
  411.     return;
  412. }
  413.  
  414. void fmtASN1()                          // ASN.1 field
  415. {
  416.     return;
  417. }
  418.  
  419.  
  420. int _cdecl main(int argc, char **argv)
  421. {
  422.   static char buffer[2048];
  423.   HDIR hDir = HDIR_CREATE;
  424.   FILEFINDBUF2 ffbuf;
  425.   USHORT usSearchCt = 1;
  426.   BOOL fRecurse = FALSE;
  427.   BOOL fCanRecurse = TRUE;
  428.   char c, *cp, *cpTail;
  429.   char *acp[3];
  430.   int  i;
  431.  
  432.   if (argc == 1)                        // check command line
  433.   {
  434.     printf("\nusage: file [-s] filename|pathname [[-s] filename|pathname ...]\n");
  435.     printf("  '-s' toggles subdirectory recursion on and off for subsequent\n");
  436.     printf("       arguments.  Default is no recursion.\n");
  437.     exit(1);
  438.   }
  439.  
  440.   if (usRecurLevel == 0)
  441.     GetCountryInfo();
  442.  
  443.   for (i = 1; i < argc; i++)
  444.   {
  445.     if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "/s") == 0))
  446.     {
  447.       fRecurse = !fRecurse;
  448.       continue;
  449.     }
  450.  
  451.     while (cpTail = strchr(argv[i], '\\'))
  452.       *cpTail = '/';
  453.  
  454.     if (strchr(argv[i], '*') || strchr(argv[i], '?'))
  455.       fCanRecurse = TRUE;
  456.     else
  457.       fCanRecurse = FALSE;
  458.  
  459.     if (!(cpTail = strrchr(argv[i], '/')))
  460.       cpTail = strrchr(argv[i], ':');
  461.     if (cpTail)
  462.       ++cpTail;
  463.  
  464.     if (DosFindFirst2(argv[i], &hDir, FILE_ANY, &ffbuf, sizeof(ffbuf), &usSearchCt, FIL_QUERYEASIZE, 0L))
  465.       printf("No files matching \'%s\'\n\n", argv[i]);
  466.     else
  467.     {
  468.       do
  469.       {
  470.         if (cpTail)
  471.         {
  472.           c = *cpTail;
  473.           *cpTail = 0;
  474.           strcpy(buffer, argv[i]);
  475.           strcat(buffer, ffbuf.achName);
  476.           *cpTail = c;
  477.         }
  478.         else
  479.           strcpy(buffer, ffbuf.achName);
  480.         if (ffbuf.attrFile & FILE_DIRECTORY)
  481.           printf("Directory: %s\n", buffer);
  482.         else
  483.         {
  484.           printf("File: %s\n", buffer);
  485.           printf("Size: %ld bytes using %ld of disk space.\n", ffbuf.cbFile, ffbuf.cbFileAlloc);
  486.         }
  487.  
  488.         printf("Created:  ");
  489.         ShowTimeStamp(&(ffbuf.fdateCreation), &(ffbuf.ftimeCreation));
  490.         printf("Access:   ");
  491.         ShowTimeStamp(&(ffbuf.fdateLastAccess), &(ffbuf.ftimeLastAccess));
  492.         printf("Modified: ");
  493.         ShowTimeStamp(&(ffbuf.fdateLastWrite), &(ffbuf.ftimeLastWrite));
  494.  
  495.         ShowAttributes(ffbuf.attrFile);
  496.         if (!(ffbuf.attrFile & FILE_DIRECTORY) && ffbuf.cbFile)
  497.           showapptype(buffer);
  498.         showeas(buffer);
  499.         puts("");
  500.         if ((ffbuf.attrFile & FILE_DIRECTORY) && fRecurse && fCanRecurse)
  501.         {
  502.           if (strcmp(ffbuf.achName, ".") && strcmp(ffbuf.achName, ".."))
  503.           {
  504.             ++usRecurLevel;
  505.             acp[0] = argv[0];
  506.             acp[1] = cp = malloc(strlen(buffer) + strlen(cpTail) + 2);
  507.             acp[2] = NULL;
  508.             strcpy(cp, buffer);
  509.             strcat(cp, "/");
  510.             strcat(cp, cpTail);
  511.             main(2, acp);
  512.             free(cp);
  513.             --usRecurLevel;
  514.           }
  515.         }
  516.       }
  517.       while (!DosFindNext(hDir, (PFILEFINDBUF)&ffbuf, sizeof(ffbuf), &usSearchCt));
  518.     }
  519.     DosFindClose(hDir);
  520.   }
  521.  
  522.   return 0;
  523. }
  524.  
  525. 
  526.  
  527.