home *** CD-ROM | disk | FTP | other *** search
/ Programming Win32 Under the API / ProgrammingWin32UnderTheApiPatVillani.iso / Chapter9 / cmd32 / Dir.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-14  |  8.6 KB  |  380 lines

  1. /****************************************************************/
  2. /*                                */
  3. /*                  dir.c                */
  4. /*                                */
  5. /*            Copyright (c) 2000            */
  6. /*            Pasquale J. Villani            */
  7. /*            All Rights Reserved            */
  8. /*                                */
  9. /* This file is part of CMD32.                    */
  10. /*                                */
  11. /* CMD32 is free software; you can redistribute it and/or    */
  12. /* modify it under the terms of the GNU General Public License    */
  13. /* as published by the Free Software Foundation; either version    */
  14. /* 2, or (at your option) any later version.            */
  15. /*                                */
  16. /* CMD32 is distributed in the hope that it will be useful, but    */
  17. /* WITHOUT ANY WARRANTY; without even the implied warranty of    */
  18. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See    */
  19. /* the GNU General Public License for more details.        */
  20. /*                                */
  21. /* You should have received a copy of the GNU General Public    */
  22. /* License along with CMD32; see the file COPYING.  If not,    */
  23. /* write to the Free Software Foundation, 675 Mass Ave,        */
  24. /* Cambridge, MA 02139, USA.                    */
  25. /****************************************************************/
  26.  
  27.  
  28. /* $Logfile$ */
  29.  
  30. /* $Log$ 
  31.  * $EndLog$ */
  32.  
  33. #include <windows.h>
  34. #include <string.h>
  35. #include <ctype.h>
  36. #include "globals.h"
  37. #include "proto.h"
  38.  
  39. #ifdef VERSION_STRINGS
  40. static BYTE *RcsId = "$Header$";
  41. #endif
  42.  
  43.  
  44. #define TM_HOUR(x)    (((x)&0xf800)>>11)
  45. #define TM_MIN(x)    (((x)&0x07e0)>>5)
  46. #define DT_DAY(x)    ((x)&0x001f)
  47. #define DT_MONTH(x)    (((x)&0x01e0)>>5)
  48. #define DT_YEAR(x)    (((x)&0xfe00)>>9)
  49.  
  50.         
  51. static INT chk_line(INT);
  52.  
  53.  
  54.  
  55. BOOL dir(INT argc, BYTE *argv[])
  56. {
  57.     WIN32_FIND_DATA  dmp;
  58.     HANDLE hDir;
  59.     WORD nFileCount = 0, nLineCount, nColumns = 0;
  60.     DWORD nTotal = 0l;
  61.     BYTE szVolumeID[MAX_CMDLINE], *ext;
  62.     BYTE cudir[MAX_CMDLINE];
  63.     DWORD nFreeClusters, nBytesPerSector, nSectorsPerCluster, nTotalClusters;
  64.     BOOL wflag, pflag, lflag, bflag;
  65.     BYTE szFilePattern[MAX_CMDLINE] = "", szFormatted[MAX_CMDLINE];
  66.     BYTE szPath[MAX_CMDLINE] = "";
  67.     BYTE szRoot[MAX_CMDLINE] = "";
  68.     BYTE szDrive[3] = "";
  69.     BYTE szPattern[MAX_PATH];
  70.     DWORD nMaximumComponentLength;
  71.     DWORD nFileSystemFlags;
  72.  
  73.     /* parse for options                        */
  74.     wflag = pflag = lflag = bflag = FALSE;
  75.     nFileCount = 0;
  76.  
  77.     switch(argc)
  78.     {
  79.     BYTE *argp;
  80.  
  81.     case 3:
  82.         argp = argv[2];
  83.         goto process;
  84.         /* fall into pattern processing */
  85.  
  86.     case 2:
  87.         argp = argv[1];
  88.  
  89.     process:
  90.         while(*argp && (argp[0] == '/'))
  91.         {
  92.             switch(argp[1])
  93.             {
  94.             case 'p':
  95.                 pflag = TRUE;
  96.                 break;
  97.  
  98.             case 'l':
  99.                 lflag = TRUE;
  100.                 break;
  101.  
  102.             case 'b':
  103.                 bflag = TRUE;
  104.                 break;
  105.  
  106.             case 'w':
  107.                 wflag = TRUE;
  108.                 break;
  109.             }
  110.             argp++;
  111.         }
  112.         if(argv[1][0] != '/')
  113.         {
  114.             scan_name(argv[1], szDrive, szPath, szFilePattern);
  115.         }
  116.         break;
  117.  
  118.     case 1:
  119.         strcpy(szFilePattern, "*.*");
  120.         break;
  121.  
  122.     default:
  123.         error_message(INV_NUM_PARAMS);
  124.         return FALSE;
  125.     }
  126.  
  127.     /* Set defaults for file name and path if not supplied.        */
  128.     if(*szDrive == '\0')
  129.     {
  130.         szDrive[0] = 'A' + default_drive;
  131.         szDrive[1] = '\0';
  132.     }
  133.     if(islower(*szDrive))
  134.     {
  135.         *szDrive = toupper(*szDrive);
  136.     }
  137.  
  138.     if(*szPath == '\0')
  139.     {
  140.         if(szDrive[0] != ('A' + default_drive))
  141.         {
  142.             strcpy(szPath, "\\");
  143.         }
  144.         else
  145.         {
  146.             GetCurrentDirectory(MAX_CMDLINE, szPath);
  147.             if(*szDrive == '\0')
  148.             {
  149.                 szDrive[0] = szPath[0];
  150.                 szDrive[1] = '\0';
  151.             }
  152.             memmove(szPath, &szPath[2], sizeof(szPath) - 2);
  153.         }
  154.     }
  155.     if(*szFilePattern == '\0')
  156.         strcpy(szFilePattern,"*.*");
  157.     strcpy(szRoot, szDrive);
  158.     strcat(szRoot, ":\\");
  159.  
  160.     /* Get the volume label                */
  161.     if(!GetVolumeInformation((LPCTSTR)szRoot, (LPTSTR)szVolumeID,
  162.         (DWORD)MAX_CMDLINE, NULL,
  163.         &nMaximumComponentLength, &nFileSystemFlags,
  164.         0, 0))
  165.     {
  166.         if(ERROR_NO_VOLUME_LABEL == GetLastError())
  167.             strcpy(szVolumeID, "has no label");
  168.         else
  169.         {
  170.             error_message(PATH_NOT_FOUND);
  171.             return FALSE;
  172.         }
  173.     }
  174.     if(*szVolumeID == '\0')
  175.         strcpy(szVolumeID, "has no label");
  176.  
  177.  
  178.     sprintf(szPattern, (szPath[0] == '\\' && !szPath[1]) ? "%s:%s%s" : "%s:%s\\%s",
  179.         szDrive, szPath, szFilePattern);
  180.     if((hDir = FindFirstFile((LPCTSTR)szPattern, (LPWIN32_FIND_DATA)&dmp))
  181.      == INVALID_HANDLE_VALUE)
  182.     {
  183.         error_message(FILE_NOT_FOUND);
  184.         return FALSE;
  185.     }
  186.     /* If the user specified a directory, he/she wants the contents of the */
  187.     /* directory.  Adjust everything to make this happen. */
  188.     if((dmp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (strcmp(szFilePattern, "*.*")))
  189.     {
  190.         if((szPath[0] == '\\' && szPath[1]) || (szPath[0] == '.'))
  191.         {
  192.             strcat(szPath, "\\");
  193.         }
  194.         strcat(szPath, szFilePattern);
  195.         strcpy(szFilePattern, "*.*");
  196.         CloseHandle(hDir);
  197.         sprintf(szPattern, (szPath[0] == '\\' && !szPath[1]) ? "%s:%s%s" : "%s:%s\\%s",
  198.             szDrive, szPath, szFilePattern);
  199.         if((hDir = FindFirstFile((LPCTSTR)szPattern, (LPWIN32_FIND_DATA)&dmp))
  200.          == INVALID_HANDLE_VALUE)
  201.         {
  202.             error_message(FILE_NOT_FOUND);
  203.             return FALSE;
  204.         }
  205.     }
  206.  
  207.     /* Display the header, if not turned off            */
  208.     if(bflag)
  209.         nLineCount = 0;
  210.     else
  211.         nLineCount = 4;
  212.     if(!bflag)
  213.     {
  214.         printf("\n Volume in drive %s %s\n", szDrive, szVolumeID);
  215.         printf(" Directory of %s:%s\n\n", szDrive, szPath);
  216.     }
  217.  
  218.     if(wflag)
  219.     {
  220.         BYTE szFileName[NAMEMAX+1];
  221.  
  222.         do
  223.         {
  224.             char *p;
  225.  
  226.             strcpy(szFileName,
  227.                 (*dmp.cAlternateFileName) ? dmp.cAlternateFileName : dmp.cFileName);
  228.  
  229.             if(dmp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  230.             {
  231.                 if(bflag && *szFileName == '.')
  232.                     continue;
  233.                 sprintf(szFormatted, "[%s]", szFileName);
  234.                 if(lflag)
  235.                     strlwr(szFormatted);
  236.                 printf("%-14s ", szFormatted);
  237.                 ++nColumns;
  238.                 if(nColumns == 5)
  239.                 {
  240.                     if(pflag)
  241.                         nLineCount = chk_line(nLineCount);
  242.                     printf("\n");
  243.                     nColumns = 0;
  244.                 }
  245.             }
  246.             else
  247.             {
  248.                 ext = "   ";
  249.                 sprintf(szFormatted, "%s", szFileName);
  250.                 if(lflag)
  251.                     strlwr(szFormatted);
  252.                 printf("%-15s",szFormatted);
  253.                 ++nColumns;
  254.                 if(nColumns == 5)
  255.                 {
  256.                     if(pflag)
  257.                         nLineCount = chk_line(nLineCount);
  258.                     printf("\n");
  259.                     nColumns = 0;
  260.                 }
  261.             }
  262.         ++nFileCount;
  263.         nTotal += dmp.nFileSizeLow;
  264.         }
  265.         while(FindNextFile((HANDLE)hDir, (LPWIN32_FIND_DATA)&dmp));
  266.     }
  267.     else
  268.     {
  269.         FILETIME LocalFileTime;
  270.         WORD nFatDate, nFatTime;
  271.         BYTE szFileName[NAMEMAX+1];
  272.  
  273.         do
  274.         {
  275.             WORD hour;
  276.  
  277.             strcpy(szFileName,
  278.                 (*dmp.cAlternateFileName) ? dmp.cAlternateFileName : dmp.cFileName);
  279.             FileTimeToLocalFileTime(&dmp.ftCreationTime,
  280.                 &LocalFileTime);
  281.             FileTimeToDosDateTime(&LocalFileTime,
  282.                 &nFatDate, &nFatTime);
  283.             hour = TM_HOUR(nFatTime);
  284.  
  285.             if(szFileName[0] == '.')
  286.                 ext = "";
  287.             else
  288.                 for(ext = szFileName; *ext != '\0'; ext++)
  289.                 {
  290.                     if(*ext == '.')
  291.                     {
  292.                         *ext++ = '\0';
  293.                         break;
  294.                     }
  295.                 }
  296.             if(lflag)
  297.             {
  298.                 strlwr(szFileName);
  299.                 strlwr(ext);
  300.             }
  301.             if(dmp.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  302.             {
  303.                 if(bflag && *szFileName == '.')
  304.                     continue;
  305.                 if(pflag)
  306.                     nLineCount = chk_line(nLineCount);
  307.                 printf(bflag ? "\n%s.%s" : "\n   %8s %3s  <DIR>      %2d-%02d-%02d  %2d:%02d%s   %s",
  308.                     szFileName, ext,
  309.                     DT_MONTH(nFatDate),
  310.                     DT_DAY(nFatDate),
  311.                     (DT_YEAR(nFatDate) + 1980) % 100,
  312.                     hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour,
  313.                     TM_MIN(nFatTime),
  314.                     hour >= 12 ? "p" : "a",
  315.                     dmp.cFileName);
  316.             }
  317.             else
  318.             {
  319.                 if(pflag)
  320.                     nLineCount = chk_line(nLineCount);
  321.                 printf(bflag ? "\n%s.%s" : "\n   %8s %3s %10ld  %2d-%02d-%02d  %2d:%02d%s   %s",
  322.                     szFileName, ext, dmp.nFileSizeLow,
  323.                     DT_MONTH(nFatDate),
  324.                     DT_DAY(nFatDate),
  325.                     (DT_YEAR(nFatDate) + 1980) % 100,
  326.                     hour > 12 ? hour - 12 : (hour == 0) ? 12 : hour,
  327.                     TM_MIN(nFatTime),
  328.                     hour >= 12 ? "p" : "a",
  329.                     dmp.cFileName);
  330.             }
  331.             ++nFileCount;
  332.             nTotal += dmp.nFileSizeLow;
  333.         }
  334.         while(FindNextFile((HANDLE)hDir, (LPWIN32_FIND_DATA)&dmp));
  335.     }
  336.  
  337.     /* /b does not print any statistics                */
  338.     if(bflag)
  339.     {
  340.         printf("\n\n");
  341.     }
  342.     else
  343.     /* Now print the available free bytes (It's really clusters    */
  344.     /* translated to bytes.                        */
  345.     {
  346.         GetDiskFreeSpace((LPCTSTR)szRoot,
  347.             (LPDWORD)&nSectorsPerCluster,
  348.             (LPDWORD)&nBytesPerSector,
  349.             (LPDWORD) &nFreeClusters,
  350.             (LPDWORD)&nTotalClusters);
  351.         printf("\n\n  %10d file(s)   %10ld bytes\n", nFileCount, nTotal);
  352.         printf(  "                       %10lu bytes free\n\n",
  353.             (DWORD)nFreeClusters
  354.             * (DWORD)nBytesPerSector
  355.             * (DWORD)nSectorsPerCluster);
  356.     }
  357.  
  358.     FindClose(hDir);
  359.     return TRUE;
  360. }
  361.  
  362. static INT chk_line(INT nLineCount)
  363. {
  364.     BYTE szLine[MAX_CMDLINE];
  365.  
  366.     if(nLineCount == 23)
  367.     {
  368.         DWORD nRead;
  369.  
  370.         printf("\nStrike a key when ready . . .");
  371.         ReadFile(hStdin, (LPVOID)szLine, (DWORD)1, &nRead, 0);
  372.         return 0;
  373.     }
  374.     return ++nLineCount;
  375. }
  376.  
  377.  
  378.  
  379.  
  380.