home *** CD-ROM | disk | FTP | other *** search
/ FreeWare Collection 2 / FreeSoftwareCollection2pd199x-jp.img / ms_dos / gap / gap.c next >
Text File  |  1990-06-14  |  14KB  |  641 lines

  1. /*
  2.  *    gap.exe
  3.  *    display information of disk space use efficiency
  4.  *    (C) 1988,9 Sey
  5.  *    on Turbo C / ver.1.4 or later on LSIC86
  6.  *    lcc gap.c -lmathlib
  7.  *    1988/10/13    1.0
  8.  *         10/14    1.1    simulation added
  9.  *         10/19    1.2    rank,extention and directory analysis added
  10.  *         10/24    1.2a    1 bug fixed
  11.  *    1989/ 2/22    1.2b    1 bug fixed
  12.  *          3/ 5    1.3    real number available for simulation cluster
  13.  *                    size
  14.  *          9/13    1.4    check JOINed directory
  15.  *                    any directory allowed for search object
  16.  *    1990/ 3/21    1.4a/T LSIC863.12B2->3.20B1 / test option
  17.  */
  18. #ifdef TEST
  19. #define    VERSION    "1.4T"
  20. #else
  21. #define    VERSION    "1.4a"
  22. #endif
  23.  
  24. #include    <stdio.h>
  25. #include    <stdlib.h>
  26. #include    <dos.h>
  27. #include    <string.h>
  28. #include    <ctype.h>
  29. #include    <jctype.h>
  30.  
  31. #define    MAXPATH    80
  32. #define    MAXDIR    64
  33.  
  34. long    clussize,clususe = 0,filesize = 0;
  35. long    simclussize = 0,simclususe = 0;
  36. int    rank_anal = 0,ext_anal = 0,dir_anal = 0;
  37. int    freq[10];
  38. long    rank[10];
  39.  
  40. #ifdef TEST
  41. int    test = 0;    /* for testing */
  42. #endif
  43.  
  44. void
  45. usage()
  46.     {
  47.     printf( "GAP - display cluster gap  ver.%s (C) 1988-9 Sey\n"
  48.         "usage : GAP <directory> [<options>]\n"
  49.         "        <options> : <num> - gap simulation for <num>K bytes"
  50.                     " cluster\n"
  51.         "                    R - file distribution for gap Rank\n"
  52.         "                    D - gap distribution for Directory\n"
  53.         "                    E - gap distribution for file Extention\n"
  54.         "GAP will help you to revive your hard disk."
  55.         " GOOD LUCK!\n"
  56.         ,VERSION);
  57.     exit(1);
  58.     }
  59. /* end usage */
  60.  
  61. void
  62. fatal(char *msg)
  63.     {
  64.     fprintf(stderr,"gap : %s\n",msg);
  65.     exit(1);
  66.     }
  67. /* end fatal */
  68.  
  69. void
  70. option_error(void)
  71.     {
  72.     fprintf(stderr,"gap : unknown option\n\n");
  73.     usage();
  74.     }
  75. /* end option_error */
  76.  
  77. /*
  78.  *    structures and operators for file EXTENSION analysis
  79.  */
  80.  
  81. struct    ext_list
  82.     {
  83.     char            ext[4];
  84.     int            count;
  85.     long            gap;
  86.     struct    ext_list    *next;
  87.     };
  88.  
  89. typedef    struct    ext_list    EXT_LIST;
  90.  
  91. EXT_LIST    ext_list0 = { "",0,0,NULL };
  92. EXT_LIST    *elp0 = &ext_list0;
  93. int        nel = 0;
  94.  
  95. char
  96. *ext(char *filename)
  97.     {
  98.     char    *p = filename;
  99.  
  100.     while( *p )
  101.         if( *p++ == '.' )
  102.             break;
  103.     return( p );
  104.     }
  105. /* end ext */
  106.  
  107. void
  108. add_ext_list(char *name,long gap)
  109.     {
  110.     int    found = 0;
  111.     EXT_LIST    *elp,*elp2;
  112.  
  113.     for( elp = elp0; elp->next != NULL; elp = elp->next )
  114.         if( strcmp(elp->ext,ext(name)) == 0 )
  115.             {
  116.             elp->count++;
  117.             elp->gap += gap;
  118.             found = 1;
  119.             break;
  120.             }
  121.     if( !found )
  122.         {
  123.         if( (elp2 = (EXT_LIST *)malloc(sizeof(EXT_LIST))) == NULL )
  124.             fatal("not enough memory");
  125.         strcpy(elp2->ext,ext(name));
  126.         elp2->count = 1;
  127.         elp2->gap = gap;
  128.         elp2->next = elp0;
  129.         elp0 = elp2;
  130.         nel++;
  131.         }
  132.     }
  133. /* end add_ext_list */
  134.  
  135. int
  136. extcmp(EXT_LIST **elpp1,EXT_LIST **elpp2)
  137.     {
  138.     long    gapdiff;
  139.  
  140.     gapdiff = (*elpp1)->gap - (*elpp2)->gap;
  141.     if( gapdiff > 0 )    return( -1 );
  142.     else if( gapdiff == 0 )    return(  0 );
  143.     else            return(  1 );
  144.     }
  145. /* end extcmp */
  146.  
  147. void
  148. sort_ext_list()
  149.     {
  150.     int        j;
  151.     EXT_LIST    *elp,**ela;
  152.  
  153.     if( (ela = (EXT_LIST **)malloc(nel * sizeof(EXT_LIST *))) == NULL )
  154.         fatal("not enough memory");
  155.     for( j = 0,elp = elp0; elp->next != NULL; j++,elp = elp->next )
  156.         ela[j] = elp;
  157.     qsort( ela,nel,sizeof(EXT_LIST *),extcmp );
  158.     for( j = 0; j < nel - 1; j++ )
  159.         ela[j]->next = ela[j+1];
  160.     elp0 = ela[0];
  161.     ela[nel - 1]->next = &ext_list0;
  162.     }
  163. /* end sort_ext_list */
  164.  
  165. /*
  166.  *    structures and operators for DIRECTORY analysis
  167.  */
  168.  
  169. struct    dir_list
  170.     {
  171.     char            dir[MAXDIR];
  172.     int            count;
  173.     long            gap;
  174.     struct    dir_list    *next;
  175.     };
  176.  
  177. typedef    struct    dir_list    DIR_LIST;
  178.  
  179. DIR_LIST    dir_list0 = { "",0,0,NULL };
  180. DIR_LIST    *dlp0 = &dir_list0;
  181. int        ndl = 0;
  182.  
  183. void
  184. add_dir_list(char *name,long gap)
  185.     {
  186.     int    found = 0;
  187.     DIR_LIST    *dlp,*dlp2;
  188.  
  189.     for( dlp = dlp0; dlp->next != NULL; dlp = dlp->next )
  190.         if( strcmp(dlp->dir,name) == 0 )
  191.             {
  192.             dlp->count++;
  193.             dlp->gap += gap;
  194.             found = 1;
  195.             break;
  196.             }
  197.     if( !found )
  198.         {
  199.         if( (dlp2 = (DIR_LIST *)malloc(sizeof(DIR_LIST))) == NULL )
  200.             fatal("not enough memory");
  201.         strcpy(dlp2->dir,name);
  202.         dlp2->count = 1;
  203.         dlp2->gap = gap;
  204.         dlp2->next = dlp0;
  205.         dlp0 = dlp2;
  206.         ndl++;
  207.         }
  208.     }
  209. /* end add_dir_list */
  210.  
  211. int
  212. dircmp(DIR_LIST **dlpp1,DIR_LIST **dlpp2)
  213.     {
  214.     long    gapdiff;
  215.  
  216.     gapdiff = (*dlpp1)->gap - (*dlpp2)->gap;
  217.     if( gapdiff > 0 )    return( -1 );
  218.     else if( gapdiff == 0 )    return(  0 );
  219.     else            return(  1 );
  220.     }
  221. /* end dircmp */
  222.  
  223. void
  224. sort_dir_list()
  225.     {
  226.     int        j;
  227.     DIR_LIST    *dlp,**dla;
  228.  
  229.     if( (dla = (DIR_LIST **)malloc(ndl * sizeof(DIR_LIST *))) == NULL )
  230.         fatal("not enough memory");
  231.     for( j = 0,dlp = dlp0; dlp->next != NULL; j++,dlp = dlp->next )
  232.         dla[j] = dlp;
  233.     qsort( dla,ndl,sizeof(DIR_LIST *),dircmp );
  234.     for( j = 0; j < ndl - 1; j++ )
  235.         dla[j]->next = dla[j+1];
  236.     dlp0 = dla[0];
  237.     dla[ndl - 1]->next = &dir_list0;
  238.     }
  239. /* end sort_dir_list */
  240.  
  241. /* 
  242.  *    physical - convert logical(JOIN,SUBST) to physical path name 
  243.  */
  244. char
  245. *physical(char *path)
  246.     {
  247.     static char    ret[MAXPATH];
  248.     union REGS    r;
  249.     
  250.     r.h.ah = 0x30;
  251.     intdos(&r,&r);
  252.     if( r.h.al < 3 )        /* if DOS 2.x */
  253.         {
  254.         strcpy(ret,path);
  255.         return(ret);
  256.         }
  257.     
  258.     r.h.ah = 0x60;
  259.     r.x.si = (unsigned)path;
  260.     r.x.di = (unsigned)ret;
  261.     intdos(&r,&r);
  262.     return(ret);
  263.     }
  264. /* end physical */
  265.     
  266. /* 
  267.  *    filesearch - search files and do indicated analysis
  268.  *    returns number of files in the directory 
  269.  */
  270. int
  271. filesearch(char *path)
  272.     {
  273.     struct    find_t    find_t;
  274.     int    done,files;
  275.     char    searchpath[MAXPATH];
  276.     char    *physpath;
  277.  
  278.     files = 0;
  279. #ifdef TEST
  280.     if( test )
  281.         printf("searching for %s\n",path);
  282. #endif
  283.     strcpy(searchpath,path);
  284.     physpath = physical(searchpath);
  285.     if( *physpath != *searchpath )    /* JOINed */
  286.         {
  287. #ifdef TEST
  288.         if( test )
  289.             printf("%s may be a JOINed directory --> skipped\n",searchpath);
  290. #endif
  291.         return(2);        /* . and .. (JOINed directory must to be empty) */
  292.         }
  293.     if( searchpath[strlen(searchpath) - 1] == '\\' )
  294.         strcat(searchpath,"*.*");
  295.     else
  296.         strcat(searchpath,"\\*.*");
  297.     done = _dos_findfirst(searchpath
  298.             ,_A_SUBDIR|_A_RDONLY|_A_HIDDEN|_A_SYSTEM,&find_t);
  299.     while(!done)
  300.         {
  301.         files++;
  302.         if( !(find_t.attrib & _A_SUBDIR) )
  303.             {
  304. #ifdef TEST
  305.             if( test )
  306.                 printf("  %s\n",find_t.name);
  307. #endif
  308.             filesize += find_t.size;
  309.             clususe += ((find_t.size + clussize - 1) / clussize) * clussize;
  310.             if( simclussize )
  311.                 simclususe +=
  312.                 ((find_t.size + simclussize - 1)
  313.                  / simclussize) * simclussize;
  314.             if( rank_anal && find_t.size )
  315.                 {
  316.                 int    j;
  317.  
  318.                 for( j = 9; j >= 0; j-- )
  319.                     if( rank[j] >= clussize -
  320.                         (find_t.size + clussize - 1) %
  321.                         clussize - 1 )
  322.                         {
  323.                         freq[j]++;
  324.                         break;
  325.                         }
  326.                 }
  327.             if( ext_anal )
  328.                 add_ext_list(find_t.name,
  329.                     clussize - (find_t.size + clussize - 1) %
  330.                     clussize - 1 );
  331.             if( dir_anal )
  332.                 add_dir_list(path,
  333.                     clussize - (find_t.size + clussize - 1) %
  334.                     clussize - 1 );
  335.             }
  336.         else if( strcmp(find_t.name,".")
  337.               && strcmp(find_t.name,"..") )
  338.             {
  339.             long    subfiles;
  340.  
  341.             strcpy(searchpath,path);
  342.             if( searchpath[strlen(searchpath) - 1] != '\\' )
  343.                 strcat(searchpath,"\\");
  344.             strcat(searchpath,find_t.name);
  345.             subfiles = filesearch(searchpath);
  346.             clususe += ((subfiles * 32 + clussize - 1) / clussize) * clussize;
  347.             if( simclussize )
  348.                 simclususe +=
  349.                 ((subfiles * 32 + simclussize - 1)
  350.                  / simclussize) * simclussize;
  351.             if( rank_anal )
  352.                 freq[0]++;
  353.             if( ext_anal )
  354.                 add_ext_list(find_t.name,
  355.                 ((subfiles * 32 + clussize - 1)
  356.                  / clussize) * clussize );
  357.             if( dir_anal )
  358.                 add_dir_list(path,
  359.                 ((subfiles * 32 + clussize - 1)
  360.                  / clussize) * clussize );
  361.             }
  362.         done = _dos_findnext(&find_t);    /* dialect of LSIC86 */
  363.         }
  364.     return( files );
  365.     }
  366. /* end filesearch */
  367.  
  368. /*
  369.  *    diskstat - display and set fundamental information of a drive
  370.  */
  371. void
  372. diskstat(char *drive)
  373.     {
  374.     struct    diskfree_t    diskfree_t;        /* dialect of LSIC86 */
  375.  
  376.     _dos_getdiskfree( toupper(*drive) - '@',&diskfree_t );    
  377.                                         /* dialect of LSIC86 */
  378.     clussize = diskfree_t.bytes_per_sector;
  379.     clussize *= diskfree_t.sectors_per_cluster;
  380.     printf( "DRIVE             : %s\n"
  381.             "BYTES / SECTOR    : %10u\n"
  382.             "SECTORS / CLUSTER : %10u\n"
  383.             "CLUSTER SIZE      : %10ld bytes\n"
  384.             "TOTAL CLUSTERS    : %10u\n"
  385.             "FREE CLUSTERS     : %10u\n"
  386.             "USED CLUSTERS     : %10u\n"
  387.             ,drive
  388.             ,diskfree_t.bytes_per_sector
  389.             ,diskfree_t.sectors_per_cluster
  390.             ,clussize
  391.             ,diskfree_t.total_clusters
  392.             ,diskfree_t.avail_clusters
  393.             ,diskfree_t.total_clusters - diskfree_t.avail_clusters);
  394.     }
  395. /* end diskstat */
  396.  
  397. /*
  398.  *    disp_... - display each infomation
  399.  */
  400. void
  401. disp_gap(char *path)
  402.     {
  403.     double        eff;
  404.  
  405.     eff = (double)filesize / (double)clususe;
  406.     printf(    "SEARCH PATH       : %s\n"
  407.             "USED CLUSTERS     : %10u\n"
  408.             "USED CLUSTERS SIZE: %10ld bytes\n"
  409.             "TOTAL FILE SIZE   : %10ld bytes\n"
  410.             "USE EFFICIENCY    : %10.2f %%\n"
  411.             "GAP               : %10ld bytes\n"
  412.             ,path,(unsigned)(clususe / clussize),clususe
  413.             ,filesize,eff*100,clususe-filesize);
  414.     }
  415. /* end disp_gap */
  416.  
  417. void
  418. disp_simulation()
  419.     {
  420.     double    simeff;
  421.  
  422.     simeff = (double)filesize / (double)simclususe;
  423.     printf( "\n**** simulation ****\n"
  424.             "CLUSTER SIZE      : %10ld bytes\n"
  425.             "USED CLUSTERS SIZE: %10ld bytes\n"
  426.             "TOTAL FILE SIZE   : %10ld bytes\n"
  427.             "USE EFFICIENCY    : %10.2f %%\n"
  428.             "GAP               : %10ld bytes\n"
  429.             "ADVANTAGE         : %10ld bytes\n"
  430.             ,simclussize,simclususe,filesize,simeff*100
  431.             ,simclususe-filesize,clususe-simclususe);
  432.     }
  433. /* end disp_simulation */
  434.  
  435. void
  436. disp_rank_anal()
  437.     {
  438.     int    j;
  439.  
  440.     printf( "\n**** file distribution for gap rank ****\n"
  441.             "  gap rank : files          gap rank : files\n"
  442.             "-----------:-------       -----------:-------\n" );
  443.     for( j = 0; j < 5; j++ )
  444.     printf( "  - %6ld : %5d          - %6ld : %5d\n",
  445.         rank[j],freq[j],rank[j+5],freq[j+5] );
  446.     }
  447. /* end disp_rank_anal */
  448.  
  449. void
  450. disp_ext_anal()
  451.     {
  452.     EXT_LIST    *elp;
  453.     long    gapsum = 0;
  454.     int    countsum = 0;
  455.  
  456.     sort_ext_list();
  457.     printf( "\n**** gap distribution for file extension ****\n"
  458.             " ext : files        gap               average\n"
  459.             "-----:---------------------------------------\n" );
  460.     for( elp = elp0; elp->next != NULL; elp = elp->next )
  461.         {
  462.         printf( ".%-3s : %5d %10ld (%6.2f %%) %10ld\n",
  463.             elp->ext,elp->count,elp->gap,
  464.             (double)elp->gap / (clususe - filesize) * 100,
  465.             elp->gap / elp->count );
  466.         countsum += elp->count;
  467.         gapsum += elp->gap;
  468.         }
  469.     printf( "-----:---------------------------------------\n"
  470.             "total: %5d %10ld (%6.2f %%) %10ld\n",
  471.             countsum,gapsum,(double)gapsum / (clususe - filesize) * 100,
  472.             gapsum / countsum );
  473.     }
  474. /* end disp_ext_anal */
  475.  
  476. void
  477. disp_dir_anal()
  478.     {
  479.     DIR_LIST    *dlp;
  480.     long    gapsum = 0;
  481.     int    countsum = 0;
  482.  
  483.     sort_dir_list();
  484.     printf( "\n**** gap distribution for directory ****\n"
  485.              " directory\n"
  486.              "     : files        gap               average\n"
  487.              "-----:---------------------------------------\n" );
  488.     for( dlp = dlp0; dlp->next != NULL; dlp = dlp->next )
  489.         {
  490.         printf( " %s\n"
  491.                 "     : %5d %10ld (%6.2f %%) %10ld\n",
  492.                 dlp->dir,dlp->count,dlp->gap,
  493.                 (double)dlp->gap / (clususe - filesize) * 100,
  494.                 dlp->gap / dlp->count );
  495.         countsum += dlp->count;
  496.         gapsum += dlp->gap;
  497.         }
  498.     printf( "-----:---------------------------------------\n"
  499.             "total: %5d %10ld (%6.2f %%) %10ld\n",
  500.             countsum,gapsum,(double)gapsum / (clususe - filesize) * 100,
  501.             gapsum / countsum );
  502.     }
  503. /* end disp_dir_anal */
  504.  
  505. double
  506. strtof(char *str,char **endp)
  507.     {
  508.     double    x = 0.,y = 1.;
  509.     int    base = 10;
  510.     char    sign;
  511.     char    *p = str;
  512.  
  513.     if( *p == '+' || *p == '-' )
  514.         sign = *p++;
  515.     if( isdigit(*p) )
  516.         {
  517.         x = *p++ - '0';
  518.         while( isdigit(*p) )
  519.             x = base * x + *p++ - '0';
  520.         if( *p == '.' )
  521.                         {
  522.             p++;
  523.             while( isdigit(*p) )
  524.                 {
  525.                 y /= base;
  526.                 x += y * (*p++ - '0');
  527.                 }
  528.                         }
  529.         }
  530.     if( sign == '-' )
  531.         x = - x;
  532.     *endp = p;
  533.     return( x );
  534.     }
  535. /* end strtof */
  536.  
  537. unsigned
  538. setdisk(unsigned driveno)
  539.     {
  540.     unsigned    drives;
  541.     
  542.     _dos_setdrive(driveno,&drives);        /* dialect of LSIC86 */
  543.     return( drives );
  544.     }
  545. /* end setdisk */
  546.  
  547. void
  548. splitdrive(char *path,char *drive)
  549.     {
  550.     unsigned    driveno;
  551.     
  552.     if( path[1] == ':' )
  553.         {
  554.         drive[0] = path[0];
  555.         }
  556.     else
  557.         {
  558.         _dos_getdrive(&driveno);
  559.         drive[0] = '@' + driveno;
  560.         }
  561.     drive[1] = ':';
  562.     drive[2] = '\0';
  563.     }
  564. /* end splitdrive */
  565.  
  566. char
  567. *strupr(char *str)
  568.     {
  569.     char    *p;
  570.     
  571.     for( p = str; *p; p++ )
  572.         {
  573.         if( iskanji(*p) && iskanji2(*(p + 1)) )
  574.             p++;
  575.         else
  576.             *p = toupper(*p);
  577.         }
  578.     return(str);
  579.     }
  580. /* end strupr */
  581.  
  582. /*
  583.  *    main routine
  584.  */
  585. main(int ac,char *av[])
  586.     {
  587.     int    j;
  588.     char    drive[3],path[MAXPATH];
  589.  
  590.     if( ac != 2 && ac != 3 )
  591.         usage();
  592.     strcpy(path,av[1]);
  593.     if( path[strlen(path) - 1] == ':' )
  594.         strcat(path,"\\");
  595.     strcpy(path,physical(path));
  596.     splitdrive(path,drive);
  597.     if( toupper(*drive) - '@' < 1 ||
  598.         toupper(*drive) - '@' > setdisk(0xff) )
  599.         fatal("not available drive");
  600.     if( ac == 3 )
  601.         {
  602.         char    *p;
  603.  
  604.         for( p = av[2]; *p; )
  605.             if( isdigit(*p) )
  606.                 simclussize = strtof(p,&p) * 1024;
  607.             else
  608.                 switch( toupper(*p++) )
  609.                     {
  610.                     case 'R':    rank_anal = 1; break;
  611.                     case 'E':    ext_anal = 1; break;
  612.                     case 'D':    dir_anal = 1; break;
  613. #ifdef TEST
  614.                     case 'T':    test = 1;    break;
  615. #endif
  616.                     default:    option_error();
  617.                     }
  618.         }
  619.  
  620.     diskstat(drive);
  621.     if( rank_anal )
  622.         for( j = 0; j < 10; j++ )
  623.             {
  624.             freq[j] = 0;
  625.             rank[j] = clussize * (10 - j) / 10;
  626.             }
  627.     fprintf(stderr,"...working...\r");
  628.     filesearch(path);
  629.     disp_gap(path);
  630.     if( simclussize )
  631.         disp_simulation();
  632.     if( rank_anal )
  633.         disp_rank_anal();
  634.     if( dir_anal )
  635.         disp_dir_anal();
  636.     if( ext_anal )
  637.         disp_ext_anal();
  638.     }
  639. /* end main */
  640. /* end gap.c */
  641.