home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / sources / du.zoo / du.c < prev    next >
Text File  |  1992-04-13  |  11KB  |  413 lines

  1. /*
  2. **  source file      : #(@)du.c
  3. **  program desc     : DU for OS/2 2.0
  4. **  author           : John J. Allen
  5. **  last edited by   : John J. Allen
  6. **  date created     : Fri 10 April 1992
  7. **  version          : 1.00.00
  8. **  verdate          : Mon 13th Apr 1992
  9. **  comment          : A du for OS/2 2.0
  10. **
  11. ** (c) Copyright John J. Allen. 1990-1992. 
  12. ** 
  13. ** This program may be freely distributed and modified as long as the
  14. ** original copyright message remains intact. 
  15. ** 
  16. ** This program uses the regular expression parser distributed with the
  17. ** GNU Text Utilities.
  18. ** 
  19. ** This is a 32bit OS/2 2.0 program and requires the IBM C Set/2 compiler.
  20. ** It has been compiled & tested under the LA release and I hope to
  21. ** be able to test it under GA RSN.
  22. ** 
  23. ** All comments/suggestions for mod's etc... should be mailed to jja@wsl.ie
  24. ** 
  25. ** example usage.
  26. ** du \*.c
  27. ** du \
  28. ** du \*map*
  29. ** 
  30. */ 
  31.  
  32. #define INCL_FILEMGR
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <limits.h>
  36. #include <string.h>
  37. #include <os2.h>
  38. #include "regex.h"
  39.  
  40. char* copr="DU/2-Directory Usage, Release 1.00\n"
  41.            "(c) Copr. 1990-1992, John J. Allen\n";
  42.  
  43. unsigned long treeDepthToDisplay = 0xFFFFFFFF;
  44.  
  45. /* translate table for regexp functions */
  46. static char upcase[0400] =
  47.   { 000, 001, 002, 003, 004, 005, 006, 007,
  48.     010, 011, 012, 013, 014, 015, 016, 017,
  49.     020, 021, 022, 023, 024, 025, 026, 027,
  50.     030, 031, 032, 033, 034, 035, 036, 037,
  51.     040, 041, 042, 043, 044, 045, 046, 047,
  52.     050, 051, 052, 053, 054, 055, 056, 057,
  53.     060, 061, 062, 063, 064, 065, 066, 067,
  54.     070, 071, 072, 073, 074, 075, 076, 077,
  55.     0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
  56.     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
  57.     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
  58.     0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137,
  59.     0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107,
  60.     0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117,
  61.     0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127,
  62.     0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177,
  63.     0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207,
  64.     0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217,
  65.     0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227,
  66.     0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237,
  67.     0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247,
  68.     0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257,
  69.     0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267,
  70.     0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277,
  71.     0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307,
  72.     0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317,
  73.     0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327,
  74.     0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337,
  75.     0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347,
  76.     0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357,
  77.     0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367,
  78.     0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377
  79.   };
  80.  
  81. /*-----------------------------------oOo------------------------------------*/
  82.  
  83. void usage()
  84. {
  85.    printf("%s\n", copr);
  86.    printf("usage: du [switches] {directory[\\filespec]}\n\n");
  87.    printf("switches are:\n");
  88.    printf("/?  display this screen.\n");
  89.    printf("/Dn display tree to depth n.\n");
  90.    printf("/T  display totals only. (same as /D1)\n");
  91. }
  92.  
  93. /*-----------------------------------oOo------------------------------------*/
  94.  
  95. char* fileEx2RegEx(char* s)
  96. {
  97.    static char buf[2048];
  98.    char*       bp = buf;
  99.    char        lastchar = '\0';
  100.  
  101.    *bp++ = '^';
  102.  
  103.    while (*s) {
  104.       switch (*s) {
  105.          case '*': {
  106.             strcpy(bp, "[^\\/:]*");
  107.             bp = strchr(bp, 0);
  108.             }
  109.          break;
  110.  
  111.          case '?': {
  112.             *bp++ = '.';
  113.             }
  114.          break;
  115.  
  116.          case '.':
  117.          case '$': {
  118.             *bp++ = '\\';
  119.             *bp++ = *s;
  120.             }
  121.          break;
  122.  
  123.          case '+': {
  124.             if (lastchar == ']') {
  125.                if (isdigit(*(s+1))) {
  126.                   int min=1, max=1;
  127.  
  128.                   s++;
  129.  
  130.                   max = atoi(s);
  131.  
  132.                   while (*s && isdigit(*s))
  133.                      s++;
  134.  
  135.                   if (*s == ',') {
  136.                      s++;
  137.  
  138.                      min = atoi(s);
  139.  
  140.                      while (*s && isdigit(*s))
  141.                         s++;
  142.                      }
  143.  
  144.                   s--;
  145.  
  146.                   sprintf(bp, "\\{%d,%d\\}", min, max);
  147.                   bp = strchr(bp, 0);
  148.                   }
  149.                }
  150.             else {
  151.                *bp++ = *s;
  152.                }
  153.             }
  154.          break;
  155.  
  156.          default: {
  157.             *bp++ = *s;
  158.             }
  159.          }
  160.  
  161.       lastchar = *s++;
  162.       }
  163.  
  164.    *bp++ = '$';
  165.    *bp = '\0';
  166.  
  167.    return buf;
  168. }
  169.  
  170. /*-----------------------------------oOo------------------------------------*/
  171.  
  172. char* makePathSpec(char* dir, char* fileSpec)
  173. {
  174.    static char pathSpec[255];
  175.  
  176.    strcpy(pathSpec, dir);
  177.  
  178.    if (*pathSpec && pathSpec[strlen(pathSpec)-1] != '\\')
  179.       strcat(pathSpec, "\\");
  180.  
  181.    strcat(pathSpec, fileSpec);
  182.  
  183.    return pathSpec;
  184. }
  185.  
  186. /*-----------------------------------oOo------------------------------------*/
  187.  
  188. long duDir(char* directory, char* fileSpec)
  189. {
  190.    HDIR           hDir           = HDIR_CREATE;
  191.    ULONG          attribute      = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
  192.    FILEFINDBUF3   resultBuf;
  193.    ULONG          resultBufLen;
  194.    ULONG          searchCount    = 1;
  195.    ULONG          fileInfoLevel  = FIL_STANDARD;
  196.    ULONG          returnCode;
  197.    char           fullPathSpec[255];
  198.    long           bytesOccupied  = 0;
  199.    struct re_pattern_buffer buf;
  200.    char fastmap[(1 << CHAR_BIT)];
  201.  
  202.    static unsigned long treeDepthCount   = 0;
  203.  
  204.    if ((strlen(directory) + strlen(fileSpec) + 2) >= sizeof(fullPathSpec)) {
  205.       printf("du: directory + filespec too long\n");
  206.       return 0;
  207.       }
  208.  
  209.    strcpy(fullPathSpec, makePathSpec(directory, "*"));
  210.  
  211.    returnCode = DosFindFirst
  212.       (
  213.       fullPathSpec,
  214.       &hDir,
  215.       attribute,
  216.       &resultBuf,
  217.       sizeof(resultBuf),
  218.       &searchCount,
  219.       fileInfoLevel
  220.       );
  221.  
  222.    if (returnCode == 0) {
  223.       long  fileCount = 0;
  224.       long  dirCount = 0;
  225.       char* pattern = fileEx2RegEx(fileSpec);
  226.  
  227.       treeDepthCount++;
  228.  
  229.         buf.allocated = 10000;
  230.           buf.buffer = malloc(buf.allocated);
  231.           buf.fastmap = fastmap;
  232.           buf.translate = upcase;
  233.  
  234.       re_compile_pattern (pattern, strlen(pattern), &buf);
  235.       re_compile_fastmap (&buf);
  236.  
  237.       do {
  238.          if (resultBuf.attrFile & FILE_DIRECTORY) {
  239.             dirCount++;
  240.  
  241.             if (strcmp(resultBuf.achName, ".") != 0 && strcmp(resultBuf.achName, "..") != 0) {
  242.                char newDirectory[255];
  243.  
  244.                strcpy(newDirectory, makePathSpec(directory, resultBuf.achName));
  245.  
  246.                bytesOccupied += duDir(newDirectory, fileSpec);
  247.                }
  248.             }
  249.          else {
  250.             if (re_match(&buf, resultBuf.achName, strlen(resultBuf.achName), 0, 0) != -1) {
  251.                fileCount++;
  252.                bytesOccupied += resultBuf.cbFile;
  253.                }
  254.             }
  255.          }
  256.       while (DosFindNext(hDir, &resultBuf, sizeof(resultBuf), &searchCount) == 0);
  257.  
  258.       DosFindClose(hDir);
  259.  
  260.       treeDepthCount--;
  261.  
  262.       if (treeDepthCount < treeDepthToDisplay && fileCount > 0) {
  263.          printf("%10li %6li %6li %s\n", bytesOccupied, fileCount, dirCount, directory);
  264.          }
  265.  
  266.       free(buf.buffer);
  267.  
  268.       return bytesOccupied;
  269.       }
  270.  
  271.    return -1;
  272. }
  273.  
  274. /*-----------------------------------oOo------------------------------------*/
  275.  
  276. long du(char* directory)
  277. {
  278.    static char     dir[255];
  279.    long     bytesOccupied = 0;
  280.    ULONG    pathLen = sizeof(dir)-3;
  281.    ULONG    driveNumber, logicalDriveMap;
  282.  
  283.    DosQCurDisk(&driveNumber, &logicalDriveMap);
  284.    dir[0] = 'A' + (driveNumber-1);
  285.    dir[1] = ':';
  286.    dir[2] = '\\';
  287.    DosQCurDir(0, &dir[3], &pathLen);
  288.  
  289.    switch (*directory) {
  290.       case '\\': {
  291.          strcpy(&dir[2], directory);
  292.          }
  293.       break;
  294.  
  295.       case '\0': {
  296.          }
  297.       break;
  298.  
  299.       default: {
  300.          /* is a drive specified */
  301.          if (strlen(directory) > 1 && directory[1] == ':') {
  302.             /* is it not a full path */
  303.             if (strlen(directory) > 2 && directory[2] != '\\') {
  304.                dir[0] = directory[0];
  305.                dir[1] = directory[1];
  306.  
  307.                pathLen--;
  308.                DosQCurDir((toupper(dir[0]) - 'A')+1, &dir[2], &pathLen);
  309.  
  310.                strcat(dir, "\\");
  311.                strcat(dir, directory);
  312.                }
  313.             else {
  314.                strcpy(dir, directory);
  315.                dir[0] = toupper(dir[0]);
  316.                }
  317.             }
  318.          else {
  319.             strcat(dir, "\\");
  320.             strcat(dir, directory);
  321.             }
  322.          }
  323.       }
  324.                 
  325.    if ((bytesOccupied = duDir(dir, "*")) == -1) {
  326.       char* fileSpec = strrchr(dir, '\\');
  327.  
  328.       *fileSpec++ = '\0';
  329.  
  330.       bytesOccupied = duDir(dir, fileSpec);
  331.       }
  332.  
  333.    return bytesOccupied;
  334. }
  335.  
  336. /*-----------------------------------oOo------------------------------------*/
  337.  
  338. int main(int argc, char* argv[])
  339. {
  340.    int   i, dirsCounted = 0;
  341.    long  total = 0;
  342.  
  343.    for (i=1; i < argc && *argv[i] == '/'; i++) {
  344.       char* c = argv[i]+1;
  345.  
  346.       while (*c) {
  347.          switch (*c) {
  348.             case '?': {
  349.                usage();
  350.  
  351.                return 0;
  352.                }
  353.             break;
  354.  
  355.             case 't':
  356.             case 'T': {
  357.                treeDepthToDisplay = 1;
  358.                }
  359.             break;
  360.  
  361.             case 'd':
  362.             case 'D': {
  363.                treeDepthToDisplay = atol(c+1);
  364.  
  365.                /* skip to end of string */
  366.                while (*++c)
  367.                   ;
  368.  
  369.                c--;
  370.                }
  371.             break;
  372.  
  373.             default: {
  374.                usage();
  375.                printf("\nunknown switch character %c\n", *c);
  376.  
  377.                return 3;
  378.                }
  379.             } /* endswitch */
  380.  
  381.          c++;
  382.          } /* endwhile */
  383.       } /* endfor */
  384.  
  385.    if (i == argc) {
  386.       long dirSize = du("");
  387.  
  388.       if (dirSize != -1) {
  389.          total += dirSize;
  390.          dirsCounted++;
  391.          }
  392.       }
  393.  
  394.    for (; i < argc; i++) {
  395.       long dirSize = du(argv[i]);
  396.  
  397.       if (dirSize != -1) {
  398.          total += dirSize;
  399.          dirsCounted++;
  400.          }
  401.       } /* endfor */
  402.  
  403.    if (dirsCounted > 1) {
  404.       printf("%10li\n", total);
  405.       } 
  406.  
  407.    return 0;
  408. }
  409.  
  410. /*-----------------------------------oOo------------------------------------*/
  411. /* (c) Copyright John J. Allen. 1990-1992.                                   */
  412. /*-----------------------------------oOo------------------------------------*/
  413.