home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff345.lzh / Du / du.c < prev    next >
C/C++ Source or Header  |  1990-04-16  |  10KB  |  478 lines

  1. /*
  2.  * du.c
  3.  * (C) 1986 Software Solution, all rights reserved
  4.  *----------------------------------------------------------------------------
  5.  *
  6.  *    Original taken from Fish Disk #48
  7.  *
  8.  *   - modified on May 89, emitted Mar 90 (since no original enhancements) by:-
  9.  *
  10.  *         Gary Duncan
  11.  *        24 Inkster St
  12.  *        Kambah ACT 2902
  13.  *        Australia
  14.  *              ~~~~~~~~~
  15.  *
  16.  *
  17.  *    reasons as follows :-
  18.  *
  19.  *    1.   print all files in dir at once ( original algorithm printed
  20.  *         files and sub-dirs in given,  unordered way ).
  21.  *         - this is the major functional  change.
  22.  *
  23.  *    2.   allow ^C abort - every text-cruncher should have it.
  24.  *
  25.  *      3.   print dirs in a redpen if not deselected ( looks much better )
  26.  *
  27.  *      4.   changed code to be compiled under AZTEC 16-bit ints 
  28.  *         ( it would be helpful if  people flagged their code with 
  29.  *           the compilation environment - hint  ).
  30.  *
  31.  *    Limitations ( the excession of will cause a GURU most likely )
  32.  *
  33.  *    a.   50 levels of dir nesting ( unreasonable ???!!!! )
  34.  *      b.   file name path length < 200 (   "         "     )
  35.  *
  36.  *
  37.  *----------------------------------------------------------------------------
  38.  *
  39.  * du is patterned after the Unix(tm) du command. Its default action is to
  40.  * give the total number of disk blocks used by a directory and recursively,
  41.  * its subdirectories. 
  42.  *
  43.  * options:
  44.  *
  45.  *       -a  ;  prints blocks use by  files and Directories
  46.  *
  47.  *       -s  ; sum of all blocks used by a directory and its subdirectories.
  48.  *
  49.  *     -n  ; no redpen for dir'd        --GMD--
  50.  *
  51.  * Bug reports or suggestions should be sent to: <<< original >>>
  52.  *    The Software Solution
  53.  *    16850 S.W. Timberland Dr.
  54.  *    Aloha, Oregon 97007
  55.  */
  56.  
  57.  
  58. #include <stdio.h>
  59. #include "libraries/dos.h"
  60. #include "libraries/dosextens.h"
  61. #include "exec/memory.h"
  62. #include "gd_functions.h"    
  63.  
  64. extern char *indent() ;
  65. extern long Recursive_Sum () ;
  66. extern char *MakeDate[] ;
  67.  
  68. char *version = "V1.1" ; /* every PD program should have one */
  69. /*               Vers1.0 is the presumed version GMD modified  */
  70.  
  71.  
  72. char banner[100] ;
  73.  
  74. int t_flag = 0;   /* summary only flag */
  75. int a_flag = 0;   /* list disk usage for both files and directories */
  76.  
  77. struct FileLock  *flockstt = NULL  ;
  78.  
  79. char *mostbug = "\n\n" ;     /* extra \n for 'most' - see intro     */
  80.  
  81. char *myname;     /* name by which this command has been called i.e."du" */
  82.  
  83. char *redpen  =  "    \x1b[33m";      /* red pen     */
  84. char *witepen =  "\x1b[0m ";      /* white  pen  */
  85.  
  86. #define    NEST_LVL    50        /* arbitrary dir nesting level */
  87. char *dirs[NEST_LVL] = NULL ;
  88. int level = 0 ;
  89. int Xblksz  ;
  90.  
  91.  
  92. main(argc, argv)
  93.  
  94. int argc;
  95. char **argv;
  96.  
  97. {
  98. int j  , ch ;
  99. char *cur_dir , *ptr ,*rtp ; 
  100. long total = 0 ;
  101.  
  102.    ptr = MakeDate[0] ;
  103.   /* 
  104.    * fiddle around to extract only the ddmmyy from date string
  105.    */
  106.  
  107.    while ( *ptr++ != ' ') ;    
  108.    rtp=ptr;while(*rtp++!=' ');*--rtp='\0'; /* hackers practise, avoid */
  109.  
  110.    sprintf ( banner ,  
  111. "DU : %s ; (original by Joe Mueller) , (v1.1 by Gary Duncan)\n" , 
  112.             ptr , version ) ;
  113.  
  114.    printf ( "%s" , banner ) ;    /* announce program    */
  115.  
  116.    myname = *argv++;
  117.  
  118.    for ( j=0 ; j < 50 ; ++j )    /* clear array        */
  119.     dirs[j] = NULL ;
  120.  
  121.   while ( --argc )
  122.    {
  123.    if ( *(ptr = *argv ) == '-' )
  124.      {               /* handle options ( - ) */
  125.     ++argv ;
  126.           ch = *++ptr ;
  127.     ++ptr ;
  128.         switch ( ch ) 
  129.           {
  130.             case 'n':        /* no redpen for dirs */
  131.             case 'N':
  132.         redpen = " <d>" ;
  133.         witepen = "" ;
  134.                 break;
  135.  
  136.             case 't':
  137.             case 'T':
  138.                if (a_flag)
  139.                    usage();
  140.  
  141.                t_flag++;   /* sum only */
  142.                break;
  143.  
  144.             case 's':        /* block size filter    */
  145.             case 'S':
  146.            if ( *ptr )    /* check for block size filter    */
  147.          {
  148.           if ( sscanf (ptr , "%d" , &Xblksz ) != 1 )
  149.             usage () ;
  150.          }            
  151.            else
  152.             usage() ;
  153.  
  154.                break;
  155.  
  156.             case 'a':
  157.             case 'A':
  158.                if (t_flag)
  159.                    usage();
  160.  
  161.                a_flag++;   /* all files reported */
  162.                break;
  163.  
  164.             default:    
  165.                usage();
  166.           }
  167.      }
  168.    }
  169.  
  170.    if (*argv) 
  171.      {
  172.       while (cur_dir = *argv++) 
  173.     {
  174.       total = Recursive_Sum(cur_dir)  ;
  175.           printf("%5ld %s%s%s%s", 
  176.             total, redpen, dirs[0] ,witepen , mostbug  );
  177.     }
  178.      }
  179.    else 
  180.      {
  181.       total = Recursive_Sum(argv);
  182.       printf("%5ld %s%s%s%s", 
  183.          total , redpen , dirs[0] , witepen , mostbug  );
  184.      }
  185.  
  186.    exit (0);
  187. }
  188.  
  189. /*************************************************************************** 
  190.  
  191.  
  192.   Name :          Recursive_Sum
  193.  
  194.   Purpose:
  195.  
  196.  
  197.   Entry    :           
  198.  
  199.  
  200.   Returns  :           
  201.                                
  202.  
  203.  
  204. ****************************************************************************/ 
  205.  
  206.  
  207. long Recursive_Sum (fn)
  208.  
  209. char *fn;  /* directory file name */
  210. {
  211.     long total = 0 ;
  212.     int  val;
  213.     long temp ;
  214.     struct FileLock *flock, *flockold ;
  215.     struct FileInfoBlock *fib ;
  216.     struct FileInfoBlock *fiblast;
  217.     char  *gfib ;
  218.     int foxy = 0 ;
  219.  
  220.       
  221.    level++ ;        /* dir indentation level */
  222.  
  223.    fib = AllocMem((long)sizeof(*fib), MEMF_CLEAR);
  224.    if (fib == NULL) 
  225.    {
  226.       fprintf(stderr,"%s: unable to allocate space for fileinfo block\n",
  227.     myname);
  228.       return 0;
  229.    }
  230.    if ( (flock = Lock(fn, ACCESS_READ)) == NULL )
  231.    {
  232.       fprintf(stderr,"%s: unable to lock %s\n", myname, fn);
  233.       FreeMem(fib, (long)sizeof(*fib));
  234.       return 0;
  235.    }
  236.    flockold = NULL;
  237.  
  238.   if (Examine(flock,fib))     /* process all under this dir */
  239.    {                 
  240.       if (fib->fib_DirEntryType > 0) 
  241.     {                   /* it's a directory */
  242.          flockold = CurrentDir(flock);
  243.          if ( flockstt == NULL )
  244.         flockstt = flockold ;    /* hold initial dir ptr for a ^C */
  245.  
  246.       gfib =  fib->fib_FileName ;        /* last is current */
  247.  
  248.          temp = strlen(gfib) + 1 ;        /* 1 for \0   */
  249.  
  250.          dirs[level-1] = AllocMem( temp , MEMF_CLEAR); /* mem for dir string */ 
  251.          if (dirs[level-1] == NULL) 
  252.           {
  253.              fprintf(stderr,"%s: unable to allocate space for dir ptr\n",
  254.         myname);
  255.              return 0;
  256.           }
  257.          strcpy ( dirs[level-1] , gfib ) ;  /* copy dir name */
  258.  
  259.         }
  260.       total += fib->fib_NumBlocks;
  261.  
  262.  
  263.      /* --- now scan for files --------------------*/
  264.  
  265.       val = 0 ;
  266.       Examine(flock,fib)  ;     /* now look for dirs */
  267.       while (ExNext(flock, fib))       
  268.        { 
  269.            if ( breakcheck() )
  270.         break ;
  271.           
  272.             if ( fib->fib_DirEntryType < 0 )  /* file ? */
  273.            {
  274.             ++foxy  ;
  275.                 val = fib->fib_NumBlocks;    /* yes    */
  276.             ++val ;        /* add 1 for info block -
  277.                        ?? correct        */
  278.                 if (a_flag && (val > Xblksz) )
  279.                        printf("%5d     %s%s\n", 
  280.                             val , indent(level), fib->fib_FileName );
  281.             total += val ;
  282.                 }
  283.        else
  284.         foxy = -1 ;
  285.        }
  286.      if ( (foxy < 0) && (a_flag) )
  287.     {
  288.           foxy = 147 ;        /* mysterious magic #     */
  289.         printf ( "\n" ) ;
  290.     }
  291.  
  292.       Examine(flock,fib)  ;     /* now look for dirs */
  293.       while (ExNext(flock, fib)) 
  294.     {
  295.            if ( breakcheck() )
  296.         break ;
  297.  
  298.          if ( fib->fib_DirEntryType > 0)   /* dir ? */
  299.           {                 /* found a subdirectory */
  300.                        val = Recursive_Sum(fib->fib_FileName); /* recursive call */
  301.             ++val ;        /* add 1 for info block -
  302.                        ?? correct        */
  303.                       if ( (t_flag==0)  && (val > Xblksz) )
  304.                       printf("%5d %s%s%s%s\n", val,redpen,indent(level),
  305.                               fib->fib_FileName, witepen );
  306.                total += val ;
  307.                } 
  308.      }
  309.  
  310.  
  311.    }    
  312.    FreeMem(fib, (long)sizeof(*fib));
  313.    if (flockold != NULL)
  314.          CurrentDir(flockold);   /* change directories back */
  315.  
  316.    UnLock(flock);
  317.  
  318.    FreeMem ( dirs[level] , (long)strlen(dirs[level]) ) ;
  319.    dirs[level--]  = NULL ;
  320.  
  321.    if ( breakcheck() )    /* ^C abort check    */
  322.     {
  323.           fprintf ( stderr , "\n^C\n" ) ;
  324.           hexit () ;
  325.     }
  326.    return total;
  327.  
  328. }
  329.  
  330. /*************************************************************************** 
  331.  
  332.  
  333.   Name :          indent
  334.  
  335.   Purpose:       generates a dir string , given level req'd.
  336.         - uses external list of ptrs to dir names.
  337.  
  338.   Entry    :           
  339.  
  340.  
  341.   Returns  :           
  342.                                
  343.  
  344.  
  345. ****************************************************************************/ 
  346.  
  347. char *indent ( no )
  348.  
  349. int no ;
  350. {
  351. static char citats[200]    ;     /* indentation space buffer - nom. size */
  352. int j ;
  353.  
  354.     citats[0] = 0 ;
  355.     for ( j=0  ; j < no  ; ++j )
  356.     {
  357.       strcat (citats , dirs[j]);
  358.       strcat (citats , "/" ) ;
  359.     }
  360.     
  361.     return ( citats ) ;
  362. }
  363.  
  364. /*************************************************************************** 
  365.  
  366.  
  367.   Name :          breakcheck
  368.  
  369.   Purpose:
  370.  
  371.  
  372.   Entry    :           
  373.  
  374.  
  375.   Returns  :           
  376.                                
  377.  
  378.  
  379. ****************************************************************************/ 
  380.  
  381.  
  382.  
  383.  
  384. breakcheck()
  385. {
  386.  
  387.    return ((SetSignal(0L,0L) & SIGBREAKF_CTRL_C) );
  388.  
  389. }
  390.  
  391. /*************************************************************************** 
  392.  
  393.  
  394.   Name :      hexit
  395.  
  396.   Purpose:
  397.  
  398.  
  399.   Entry    :           
  400.  
  401.  
  402.   Returns  :           
  403.                                
  404.  
  405.  
  406. ****************************************************************************/ 
  407.  
  408.  
  409.  
  410.  
  411. int hexit ()
  412.  
  413. {
  414.  int j ;
  415.  
  416.          fflush ( stdout ) ;
  417.          if (flockstt != NULL)
  418.              CurrentDir(flockstt);   /* change to orig dir    */
  419.  
  420.       while ( level ) 
  421.        {
  422.          FreeMem ( dirs[level] , (long)strlen(dirs[level]) ) ;
  423.             --level ;
  424.        }
  425.      exit (0) ;
  426.  
  427. }
  428.  
  429. Chk_Abort()
  430. {
  431. return(0);
  432. }
  433.  
  434. /*************************************************************************** 
  435.  
  436.  
  437.   Name :      usage 
  438.  
  439.   Purpose:
  440.  
  441.  
  442.   Entry    :           
  443.  
  444.  
  445.   Returns  :           
  446.                                
  447.  
  448.  
  449. ****************************************************************************/ 
  450.  
  451.  
  452.  
  453. int usage ()
  454.  
  455. {
  456.  
  457. static char *rats[] =  {
  458.  
  459. "Usage:  du   [-a] [-t] [-n] [-sNNN] [vol: / dir list]...\n" ,
  460. "                a = print # of blocks used in  all files and dirs \n" ,
  461. "                n = deselect pretty red-pen DIR hiliting\n",
  462. "                s = don't print those with lesser than NNN blocks\n",
  463. "                t = grand total of blocks only  \n"  ,
  464. "\n",
  465. "               no a,t options  = directories only\n",
  466. ""
  467.     } ;
  468.  
  469. int j = 0 ; 
  470. char *ptr ; 
  471.  
  472.  
  473.   while ( *(ptr = rats[j++])  ) 
  474.       fprintf ( stderr, ptr ) ;
  475.  
  476.   hexit () ;
  477. }
  478.