home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 1 / FREEWARE.BIN / ms_dos / gap / gap.c next >
Text File  |  1989-10-17  |  11KB  |  517 lines

  1. /*
  2.  *    gap.exe
  3.  *    display information of disk space use efficiency
  4.  *    1988 Sey
  5.  *    1988/10/13    1.0
  6.  *         10/14    1.1    simulation added
  7.  *         10/19    1.2    rank,extention and directory analysis added
  8.  *         10/24    1.2a    1 bug fixed
  9.  *    1989/ 2/22    1.2b    1 bug fixed
  10.  *          3/ 5    1.3    real number available for simulation cluster
  11.  *                size
  12.  */
  13. #define    VERSION    "1.3 "
  14.  
  15. #include    <stdio.h>
  16. #include    <dos.h>
  17. #include    <io.h>
  18. #include    <fcntl.h>
  19. #include    <dir.h>
  20. #include    <ctype.h>
  21.  
  22. long    clussize,clususe,filesize;
  23. long    simclussize = 0,simclususe = 0;
  24. int    rank_anal = 0,ext_anal = 0,dir_anal = 0;
  25. int    freq[10];
  26. long    rank[10];
  27.  
  28. void
  29. usage()
  30.     {
  31.     printf( "GAP - display cluster gap  ver.%s (C) 1988-9 Sey\n"
  32.         "usage : GAP <drive> [<options>]\n"
  33.         "        <options> : <num> - gap simulation for <num>K bytes"
  34.                     " cluster\n"
  35.         "                    R - file distribution for gap Rank\n"
  36.         "                    D - gap distribution for Directory\n"
  37.         "                    E - gap distribution for file Extention\n"
  38.         "GAP will help you to revive your hard disk."
  39.         " GOOD LUCK!\n"
  40.         ,VERSION);
  41.     exit(1);
  42.     }
  43. /* end usage */
  44.  
  45. void
  46. fatal(char *msg)
  47.     {
  48.     fprintf(stderr,"gap : %s\n",msg);
  49.     exit(1);
  50.     }
  51. /* end fatal */
  52.  
  53. void
  54. option_error(void)
  55.     {
  56.     fprintf(stderr,"gap : unknown option\n\n");
  57.     usage();
  58.     }
  59. /* end option_error */
  60.  
  61. /*
  62.  *    structures and operators for file EXTENSION analysis
  63.  */
  64.  
  65. struct    ext_list
  66.     {
  67.     char            ext[4];
  68.     int            count;
  69.     long            gap;
  70.     struct    ext_list    *next;
  71.     };
  72.  
  73. typedef    struct    ext_list    EXT_LIST;
  74.  
  75. EXT_LIST    ext_list0 = { "",0,0,NULL };
  76. EXT_LIST    *elp0 = &ext_list0;
  77. int        nel = 0;
  78.  
  79. char
  80. *ext(char *filename)
  81.     {
  82.     char    *p = filename;
  83.  
  84.     while( *p )
  85.         if( *p++ == '.' )
  86.             break;
  87.     return( p );
  88.     }
  89. /* end ext */
  90.  
  91. void
  92. add_ext_list(char *name,long gap)
  93.     {
  94.     int    found = 0;
  95.     EXT_LIST    *elp,*elp2;
  96.  
  97.     for( elp = elp0; elp->next != NULL; elp = elp->next )
  98.         if( strcmp(elp->ext,ext(name)) == 0 )
  99.             {
  100.             elp->count++;
  101.             elp->gap += gap;
  102.             found = 1;
  103.             break;
  104.             }
  105.     if( !found )
  106.         {
  107.         if( (elp2 = (EXT_LIST *)malloc(sizeof(EXT_LIST))) == NULL )
  108.             fatal("not enough memory");
  109.         strcpy(elp2->ext,ext(name));
  110.         elp2->count = 1;
  111.         elp2->gap = gap;
  112.         elp2->next = elp0;
  113.         elp0 = elp2;
  114.         nel++;
  115.         }
  116.     }
  117. /* end add_ext_list */
  118.  
  119. int
  120. extcmp(EXT_LIST **elpp1,EXT_LIST **elpp2)
  121.     {
  122.     long    gapdiff;
  123.  
  124.     gapdiff = (*elpp1)->gap - (*elpp2)->gap;
  125.     if( gapdiff > 0 )    return( -1 );
  126.     else if( gapdiff == 0 )    return(  0 );
  127.     else            return(  1 );
  128.     }
  129. /* end extcmp */
  130.  
  131. void
  132. sort_ext_list()
  133.     {
  134.     int        j;
  135.     EXT_LIST    *elp,**ela;
  136.  
  137.     if( (ela = (EXT_LIST **)malloc(nel * sizeof(EXT_LIST *))) == NULL )
  138.         fatal("not enough memory");
  139.     for( j = 0,elp = elp0; elp->next != NULL; j++,elp = elp->next )
  140.         ela[j] = elp;
  141.     qsort( ela,nel,sizeof(EXT_LIST *),extcmp );
  142.     for( j = 0; j < nel - 1; j++ )
  143.         ela[j]->next = ela[j+1];
  144.     elp0 = ela[0];
  145.     ela[nel - 1]->next = &ext_list0;
  146.     }
  147. /* end sort_ext_list */
  148.  
  149. /*
  150.  *    structures and operators for DIRECTORY analysis
  151.  */
  152.  
  153. struct    dir_list
  154.     {
  155.     char            dir[65];
  156.     int            count;
  157.     long            gap;
  158.     struct    dir_list    *next;
  159.     };
  160.  
  161. typedef    struct    dir_list    DIR_LIST;
  162.  
  163. DIR_LIST    dir_list0 = { "",0,0,NULL };
  164. DIR_LIST    *dlp0 = &dir_list0;
  165. int        ndl = 0;
  166.  
  167. void
  168. add_dir_list(char *name,long gap)
  169.     {
  170.     int    found = 0;
  171.     DIR_LIST    *dlp,*dlp2;
  172.  
  173.     for( dlp = dlp0; dlp->next != NULL; dlp = dlp->next )
  174.         if( strcmp(dlp->dir,name) == 0 )
  175.             {
  176.             dlp->count++;
  177.             dlp->gap += gap;
  178.             found = 1;
  179.             break;
  180.             }
  181.     if( !found )
  182.         {
  183.         if( (dlp2 = (DIR_LIST *)malloc(sizeof(DIR_LIST))) == NULL )
  184.             fatal("not enough memory");
  185.         strcpy(dlp2->dir,name);
  186.         dlp2->count = 1;
  187.         dlp2->gap = gap;
  188.         dlp2->next = dlp0;
  189.         dlp0 = dlp2;
  190.         ndl++;
  191.         }
  192.     }
  193. /* end add_dir_list */
  194.  
  195. int
  196. dircmp(DIR_LIST **dlpp1,DIR_LIST **dlpp2)
  197.     {
  198.     long    gapdiff;
  199.  
  200.     gapdiff = (*dlpp1)->gap - (*dlpp2)->gap;
  201.     if( gapdiff > 0 )    return( -1 );
  202.     else if( gapdiff == 0 )    return(  0 );
  203.     else            return(  1 );
  204.     }
  205. /* end dircmp */
  206.  
  207. void
  208. sort_dir_list()
  209.     {
  210.     int        j;
  211.     DIR_LIST    *dlp,**dla;
  212.  
  213.     if( (dla = (DIR_LIST **)malloc(ndl * sizeof(DIR_LIST *))) == NULL )
  214.         fatal("not enough memory");
  215.     for( j = 0,dlp = dlp0; dlp->next != NULL; j++,dlp = dlp->next )
  216.         dla[j] = dlp;
  217.     qsort( dla,ndl,sizeof(DIR_LIST *),dircmp );
  218.     for( j = 0; j < ndl - 1; j++ )
  219.         dla[j]->next = dla[j+1];
  220.     dlp0 = dla[0];
  221.     dla[ndl - 1]->next = &dir_list0;
  222.     }
  223. /* end sort_dir_list */
  224.  
  225. /* 
  226.  *    filesearch - search files and do indicated analysis
  227.  *    returns number of files in the directory 
  228.  */
  229. int
  230. filesearch(char *path)
  231.     {
  232.         struct    ffblk    ffblk;
  233.     int    done,files;
  234.     char    searchpath[MAXPATH];
  235.  
  236.     files = 0;
  237.     strcpy(searchpath,path);
  238.         strcat(searchpath,"\\*.*");
  239.     done = findfirst(searchpath,&ffblk,
  240.         FA_DIREC|FA_RDONLY|FA_HIDDEN|FA_SYSTEM);
  241.     while(!done)
  242.         {
  243.         files++;
  244.         if( !(ffblk.ff_attrib & FA_DIREC) )
  245.             {
  246.             filesize += ffblk.ff_fsize;
  247.             if( simclussize )
  248.                 simclususe +=
  249.                 ((ffblk.ff_fsize + simclussize - 1)
  250.                  / simclussize) * simclussize;
  251.             if( rank_anal && ffblk.ff_fsize )
  252.                 {
  253.                 int    j;
  254.  
  255.                 for( j = 9; j >= 0; j-- )
  256.                     if( rank[j] >= clussize -
  257.                         (ffblk.ff_fsize + clussize - 1) %
  258.                         clussize - 1 )
  259.                         {
  260.                         freq[j]++;
  261.                         break;
  262.                         }
  263.                 }
  264.             if( ext_anal )
  265.                 add_ext_list(ffblk.ff_name,
  266.                                   clussize - (ffblk.ff_fsize + clussize - 1) %
  267.                   clussize - 1 );
  268.             if( dir_anal )
  269.                 add_dir_list(path,
  270.                                   clussize - (ffblk.ff_fsize + clussize - 1) %
  271.                   clussize - 1 );
  272.             }
  273.         else if( strcmp(ffblk.ff_name,".")
  274.               && strcmp(ffblk.ff_name,"..") )
  275.             {
  276.             long    subfiles;
  277.  
  278.             strcpy(searchpath,path);
  279.             strcat(searchpath,"\\");
  280.             strcat(searchpath,ffblk.ff_name);
  281.             subfiles = filesearch(searchpath);
  282.             if( simclussize )
  283.                 simclususe +=
  284.                 ((subfiles * 32 + simclussize - 1)
  285.                  / simclussize) * simclussize;
  286.             if( rank_anal )
  287.                 freq[0]++;
  288.             if( ext_anal )
  289.                 add_ext_list(ffblk.ff_name,
  290.                 ((subfiles * 32 + clussize - 1)
  291.                  / clussize) * clussize );
  292.             if( dir_anal )
  293.                 add_dir_list(path,
  294.                 ((subfiles * 32 + clussize - 1)
  295.                  / clussize) * clussize );
  296.             }
  297.         done = findnext(&ffblk);
  298.         }
  299.     return( files );
  300.         }
  301. /* end filesearch */
  302.  
  303. /*
  304.  *    diskstat - display and set fundamental information of the drive
  305.  */
  306. void
  307. diskstat(char *drive)
  308.     {
  309.     struct    dfree    dfree;
  310.  
  311.     getdfree( toupper(*drive) - '@',&dfree );
  312.     clussize = dfree.df_bsec;
  313.     clussize *= dfree.df_sclus;
  314.     clususe = dfree.df_total - dfree.df_avail;
  315.     clususe *= clussize;
  316.     printf( "DRIVE             : %s\n"
  317.         "BYTES / SECTOR    : %10u\n"
  318.         "SECTORS / CLUSTER : %10u\n"
  319.         "CLUSTER SIZE      : %10ld bytes\n"
  320.         "TOTAL CLUSTERS    : %10u\n"
  321.         "FREE CLUSTERS     : %10u\n"
  322.         "USED CLUSTERS     : %10u\n"
  323.         ,drive,dfree.df_bsec,dfree.df_sclus,clussize,dfree.df_total
  324.         ,dfree.df_avail,dfree.df_total-dfree.df_avail);
  325.     }
  326. /* end diskstat */
  327.  
  328. /*
  329.  *    disp_... - display each infomation
  330.  */
  331. void
  332. disp_gap()
  333.     {
  334.     double        eff;
  335.  
  336.     eff = (double)filesize / (double)clususe;
  337.     printf(    "USED CLUSTERS SIZE: %10ld bytes\n"
  338.         "TOTAL FILE SIZE   : %10ld bytes\n"
  339.         "USE EFFICIENCY    : %10.2f %%\n"
  340.         "GAP               : %10ld bytes\n"
  341.         ,clususe,filesize,eff*100,clususe-filesize);
  342.     }
  343. /* end disp_gap */
  344.  
  345. void
  346. disp_simulation()
  347.     {
  348.     double    simeff;
  349.  
  350.     simeff = (double)filesize / (double)simclususe;
  351.     printf( "\n**** simulation ****\n"
  352.         "CLUSTER SIZE      : %10ld bytes\n"
  353.         "USED CLUSTERS SIZE: %10ld bytes\n"
  354.         "TOTAL FILE SIZE   : %10ld bytes\n"
  355.         "USE EFFICIENCY    : %10.2f %%\n"
  356.         "GAP               : %10ld bytes\n"
  357.         "ADVANTAGE         : %10ld bytes\n"
  358.         ,simclussize,simclususe,filesize,simeff*100
  359.         ,simclususe-filesize,clususe-simclususe);
  360.     }
  361. /* end disp_simulation */
  362.  
  363. void
  364. disp_rank_anal()
  365.     {
  366.     int    j;
  367.  
  368.     printf( "\n**** file distribution for gap rank ****\n"
  369.         "  gap rank : files          gap rank : files\n"
  370.         "-----------:-------       -----------:-------\n" );
  371.         for( j = 0; j < 5; j++ )
  372.         printf( "  - %6ld : %5d          - %6ld : %5d\n",
  373.             rank[j],freq[j],rank[j+5],freq[j+5] );
  374.     }
  375. /* end disp_rank_anal */
  376.  
  377. void
  378. disp_ext_anal()
  379.     {
  380.     EXT_LIST    *elp;
  381.     long    gapsum = 0;
  382.     int    countsum = 0;
  383.  
  384.     sort_ext_list();
  385.     printf( "\n**** gap distribution for file extension ****\n"
  386.         " ext : files        gap               average\n"
  387.         "-----:---------------------------------------\n" );
  388.     for( elp = elp0; elp->next != NULL; elp = elp->next )
  389.         {
  390.         printf( ".%-3s : %5d %10ld (%6.2f %%) %10ld\n",
  391.             elp->ext,elp->count,elp->gap,
  392.             (double)elp->gap / (clususe - filesize) * 100,
  393.             elp->gap / elp->count );
  394.         countsum += elp->count;
  395.         gapsum += elp->gap;
  396.         }
  397.     printf( "-----:---------------------------------------\n"
  398.         "total: %5d %10ld (%6.2f %%) %10ld\n",
  399.         countsum,gapsum,(double)gapsum / (clususe - filesize) * 100,
  400.         gapsum / countsum );
  401.     }
  402. /* end disp_ext_anal */
  403.  
  404. void
  405. disp_dir_anal()
  406.     {
  407.     DIR_LIST    *dlp;
  408.     long    gapsum = 0;
  409.     int    countsum = 0;
  410.  
  411.     sort_dir_list();
  412.     printf( "\n**** gap distribution for directory ****\n"
  413.         " directory\n"
  414.         "     : files        gap               average\n"
  415.         "-----:---------------------------------------\n" );
  416.     for( dlp = dlp0; dlp->next != NULL; dlp = dlp->next )
  417.         {
  418.         printf( " %s\n"
  419.             "     : %5d %10ld (%6.2f %%) %10ld\n",
  420.             dlp->dir,dlp->count,dlp->gap,
  421.             (double)dlp->gap / (clususe - filesize) * 100,
  422.             dlp->gap / dlp->count );
  423.         countsum += dlp->count;
  424.         gapsum += dlp->gap;
  425.         }
  426.     printf( "-----:---------------------------------------\n"
  427.         "total: %5d %10ld (%6.2f %%) %10ld\n",
  428.         countsum,gapsum,(double)gapsum / (clususe - filesize) * 100,
  429.         gapsum / countsum );
  430.     }
  431. /* end disp_dir_anal */
  432.  
  433. double
  434. strtof(char *str,char **endp)
  435.     {
  436.     double    x = 0.,y = 1.;
  437.     int    base = 10;
  438.     char    sign;
  439.     char    *p = str;
  440.  
  441.     if( *p == '+' || *p == '-' )
  442.         sign = *p++;
  443.     if( isdigit(*p) )
  444.         {
  445.         x = *p++ - '0';
  446.         while( isdigit(*p) )
  447.             x = base * x + *p++ - '0';
  448.         if( *p == '.' )
  449.                         {
  450.             p++;
  451.             while( isdigit(*p) )
  452.                 {
  453.                 y /= base;
  454.                 x += y * (*p++ - '0');
  455.                 }
  456.                         }
  457.         }
  458.     if( sign == '-' )
  459.         x = - x;
  460.     *endp = p;
  461.     return( x );
  462.     }
  463. /* end strtof */
  464.  
  465. /*
  466.  *    main routine
  467.  */
  468. main(int ac,char *av[])
  469.     {
  470.     int    j;
  471.     char    drive[3];
  472.  
  473.     if( ac != 2 && ac != 3 )
  474.         usage();
  475.     strcpy( drive,av[1] );
  476.     if( toupper(*drive) - '@' < 1 ||
  477.         toupper(*drive) - '@' > setdisk(0xff) )
  478.         fatal("not available drive");
  479.     if( ac == 3 )
  480.         {
  481.         char    *p;
  482.  
  483.         for( p = av[2]; *p; )
  484.             if( isdigit(*p) )
  485.                 simclussize = strtof(p,&p) * 1024;
  486.             else
  487.                 switch( toupper(*p++) )
  488.                     {
  489.                     case 'R':    rank_anal = 1; break;
  490.                     case 'E':       ext_anal = 1; break;
  491.                     case 'D':    dir_anal = 1; break;
  492.                     default:    option_error();
  493.                     }
  494.         }
  495.  
  496.     diskstat(drive);
  497.     if( rank_anal )
  498.         for( j = 0; j < 10; j++ )
  499.             {
  500.             freq[j] = 0;
  501.             rank[j] = clussize * (10 - j) / 10;
  502.             }
  503.     fprintf(stderr,"...working...\r");
  504.     filesearch(drive);
  505.     disp_gap();
  506.     if( simclussize )
  507.         disp_simulation();
  508.     if( rank_anal )
  509.         disp_rank_anal();
  510.     if( dir_anal )
  511.         disp_dir_anal();
  512.     if( ext_anal )
  513.         disp_ext_anal();
  514.     }
  515. /* end main */
  516. /* end gap.c */
  517.