home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 31 / CDASC_31_1996_juillet_aout.iso / vrac_os2 / drchk031.zip / DRIVECHK.CMD next >
OS/2 REXX Batch file  |  1996-05-01  |  53KB  |  1,535 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /*  DriveCheck v0.03                                                  */
  4. /*                                                                    */
  5. /*  Written by Mike Ruskai <mruskai@microfone.net>                    */
  6. /*                                                                    */
  7. /*  Distribute and modify freely, but it'd be nice if you give me     */
  8. /*  credit if you distribute a modified form.                         */
  9. /*                                                                    */
  10. /*  Usage:  DRIVECHK.CMD [/T] [<drive letter>: [/S] [/O:<filename>]]  */
  11. /*                                                                    */
  12. /*  Parameters are optional.  <drive letter>: is self explanatory.    */
  13. /*  The /S switch tells the program skip extended attributes, and     */
  14. /*  can only be used when the drive letter is passed.  The /O switch  */
  15. /*  tells the program to write the report to <filename>.  If no       */
  16. /*  options are chosen, the program will prompt for the input of the  */
  17. /*  drive to scan, whether or not to check extended attributes, and   */
  18. /*  the method of report output.                                      */
  19. /*                                                                    */
  20. /*  The new /T parameter tells DriveCheck to operate in text-only     */
  21. /*  mode.                                                             */
  22. /*                                                                    */
  23. /*  This REXX script will scan an entire drive to determine how much  */
  24. /*  space would be wasted for your specific files with the HPFS and   */
  25. /*  FAT file systems.  The display of this information depends on     */
  26. /*  which file system is actually being used.                         */
  27. /*                                                                    */
  28. /*  I've tried to include as much information as I know how.  In      */
  29. /*  addition to the normal file system usage for a file and a         */
  30. /*  directory, the extended attributes are also added up and used     */
  31. /*  in space and slack space determinations.  For files that do not   */
  32. /*  have any extended attributes, the size of the Fnode (512 bytes)   */
  33. /*  for the HPFS scenario is added to the slack space for the file,   */
  34. /*  since it would not exist in the FAT scenario.  That also goes     */
  35. /*  for zero-byte files, which take up 512 bytes on HPFS drives, but  */
  36. /*  zero bytes on FAT drives.                                         */
  37. /*                                                                    */
  38. /*  What's *not* included is the space consumed by the system areas   */
  39. /*  specific to the file system.  The reason for this exclusion is    */
  40. /*  that I don't know how to measure this size for HPFS volumes       */
  41. /*  without capturing the output of CHKDSK (time-consuming), since I  */
  42. /*  see no correlation between system area size and total disk size.  */
  43. /*  My own HPFS drives have system areas ranging from 2MB to 6.5MB,   */
  44. /*  with smaller drives sometimes having bigger system areas than     */
  45. /*  some larger drives.                                               */
  46. /*                                                                    */
  47. /*  As stated, extended attributes are included, but the process by   */
  48. /*  which they are is quite slow.  The only way via REXX to find the  */
  49. /*  size of a file's extended attributes was to use the output of     */
  50. /*  CMD.EXE or 4OS2.EXE's DIR command (using the /N parameter on FAT  */
  51. /*  volumes).  Piping the output to RXQUEUE was very slow, and        */
  52. /*  redirecting the output to a file, then reading from the file was  */
  53. /*  much faster, but still slow.  4OS2.EXE tends to be about 60%      */
  54. /*  slower than CMD.EXE in loading itself into memory (more features  */
  55. /*  to load).  This would normally prompt you to type CMD before      */
  56. /*  running this, given the frequency with which the interpreter is   */
  57. /*  called (if you knew this about CMD and 4OS2, that is), but here,  */
  58. /*  you needn't bother.  Because of some extra work necessitated by   */
  59. /*  the output of CMD, the speed balances out - both CMD and 4OS2     */
  60. /*  are equally snail-like in this process.  Because of the horrible  */
  61. /*  speed, you might want to skip EA checking altogether.  The        */
  62. /*  significance of EA's in space determinations vary from drive to   */
  63. /*  drive, though.  If you know that your files have quite a lot of   */
  64. /*  extended attributes, you should just suffer to get results which  */
  65. /*  more accurately represent reality.                                */
  66. /*                                                                    */
  67. /*  New in this version, I've implemented Visual REXX, which is an    */
  68. /*  IBM Employee Written Software gem that I recently rediscovered.   */
  69. /*  The first time I looked at it, I was not familiar enough with     */
  70. /*  REXX to use it.  You must have VREXX installed on your system in  */
  71. /*  order for the graphical component to work.  If you don't then     */
  72. /*  you will simply get text-mode operation.                          */
  73. /*                                                                    */
  74. /*  In addition to directing the normal output to graphical windows   */
  75. /*  on the desktop, I've also used the drawing functions of Visual    */
  76. /*  REXX to create bar graphs (originally, I tried to use VArc to     */
  77. /*  make pie graphs, but there was no consistent fill ability as the  */
  78. /*  documentation implied) that represent the different usage and     */
  79. /*  waste situations for the drive tested.  I've also implemented     */
  80. /*  this comparison for text-mode operation, using simple character   */
  81. /*  bar graphs.                                                       */
  82. /*                                                                    */
  83. /**********************************************************************/
  84.  
  85. call RxFuncAdd 'SysLoadFuncs','RexxUtil','SysLoadFuncs'
  86. call SysLoadFuncs
  87.  
  88. /* Sets digits to allow for large numbers, so that those of you with  */
  89. /* the big drives don't get a mess in the reported number.  Using 12  */
  90. /* digits guarantees that even if HPFS's theoretical limit of 512GB   */
  91. /* is implemented, the number will look alright (provided something   */
  92. /* odd doesn't happen to turn it into a fractional number, should it  */
  93. /* be larger than 4,294,967,296 - unless REXX can somehow use more    */
  94. /* than a 32-bit unsigned integer).                                   */
  95.  
  96. numeric digits 12
  97.  
  98. /* To prevent VREXX from remaining after a crash of some sort, all    */
  99. /* errors will result in it being deinitialized before exiting the    */
  100. /* program.                                                           */
  101.  
  102. signal on halt
  103. signal on error
  104. signal on syntax
  105. signal on failure
  106.  
  107. /* Checks whether or not to skip using Visual REXX, and independently */
  108. /* whether other parameters were given.  If only /T is passed, the    */
  109. /* program will run interactively in text-mode.  With no parameters,  */
  110. /* it will run interactively with graphical dialogs using Visual REXX */
  111. /* if it is present on the system.                                    */
  112.  
  113. DCVer='0.03'
  114. CurrDir=directory()
  115. arg par1 par2 par3 par4
  116.  
  117. if par1='?'|par1='/?'|translate(par1)='/H' then signal Usage
  118.  
  119. if translate(par1)='/T' then do
  120.     TestDrive=par2
  121.     SkipSwitch=par3
  122.     OutFile=par4
  123.     Visual=0
  124. end
  125. else do
  126.     TestDrive=par1
  127.     SkipSwitch=par2
  128.     OutFile=par3
  129.     TestVis=1
  130. end
  131.  
  132. if TestDrive\='' then do
  133.     if directory(TestDrive||'\')\=TestDrive||'\' then do
  134.         say 'Invalid drive, '||'"'TestDrive'"'||'.'
  135.         say ''
  136.         say 'Type DRIVECHK /? for usage.'
  137.         exit
  138.     end
  139.     else call directory CurrDir
  140.     if translate(SkipSwitch)='/S' then SkipEA=1
  141.         else if translate(substr(SkipSwitch,1,3))='/O:' then do
  142.             OutFile=SkipSwitch
  143.             SkipEA=0
  144.         end
  145.         else do
  146.             say 'Invalid skip switch or outfile option.'
  147.             say ''
  148.             say 'Type DRIVECHK /? for usage.'
  149.             exit
  150.         end
  151.     if OutFile\='' then do
  152.         if translate(substr(OutFile,1,3))\='/O:' then do
  153.             say 'Invalid outfile option.'
  154.             say ''
  155.             say 'Type DRIVECHK /? for usage.'
  156.             exit
  157.         end
  158.         else do
  159.             OutFile=substr(OutFile,4)
  160.             if substr(OutFile,2,1)\=':' then do
  161.                 if pos('\',OutFile)=0 then 
  162.                     OutFile=CurrDir||'\'||OutFile
  163.                 else if pos('\',OutFile)=1 then
  164.                     OutFile=left(CurrDir,2)||OutFile
  165.                     else OutFile=CurrDir||'\'||OutFile
  166.             end
  167.             check=lineout(OutFile,'1')
  168.             if check\=0 then do
  169.                 say 'Invalid outfile option, '||OutFile
  170.                 say ''
  171.                 say 'Type DRIVECHK /? for usage.'
  172.                 exit
  173.             end
  174.             else do
  175.                 call stream OutFile,'c','close'
  176.                 call SysFileDelete OutFile
  177.             end
  178.         end
  179.     end
  180.     else OutFile='CON'
  181. end
  182.  
  183. if TestVis=1 then do
  184.     call RxFuncAdd 'VInit','VRexx','VInit'
  185.     success=VInit()
  186.     if success='ERROR' then Visual=0
  187.         else Visual=1
  188. end
  189.  
  190. /* Finds the INI file, if it exists, and digs out the colors to use   */
  191. /* for the graphs.  If the file is "corrupt", it will use default     */
  192. /* colors.                                                            */
  193.  
  194. if Visual=1 then do
  195.  
  196.     parse source SourceString
  197.     SourceFile=word(SourceString,3)
  198.     SourceDrive=filespec('drive',SourceFile)
  199.     SourcePath=filespec('path',SourceFile)
  200.     SourceDir=SourceDrive||SourcePath
  201.     call directory SourceDir
  202.     INIfile='drivechk.ini'
  203.     check=stream(INIfile,'c','query exists')
  204.     if check='' then defaults=1
  205.     else do
  206.     
  207.         cc=translate(linein(INIfile))
  208.         ccheck=ColorCheck(cc)
  209.         if ccheck=1 then MainColor=cc
  210.         else MainColor='WHITE'
  211.         cc=translate(linein(INIfile))
  212.         ccheck=ColorCheck(cc)
  213.         if ccheck=1 then MainTextColor=cc
  214.         else MainTextColor='BLACK'
  215.  
  216.         cc=translate(linein(INIfile))
  217.         ccheck=ColorCheck(cc)
  218.         if ccheck=1 then DirColor=cc
  219.         else DirColor='CYAN'
  220.         cc=translate(linein(INIfile))
  221.         ccheck=ColorCheck(cc)
  222.         if ccheck=1 then DirTextColor=cc
  223.         else DirTextColor='BLACK'
  224.   
  225.         cc=translate(linein(INIfile))
  226.         ccheck=ColorCheck(cc)
  227.         if ccheck=1 then FileColor=cc
  228.         else FileColor='CYAN'
  229.         cc=translate(linein(INIfile))
  230.         ccheck=ColorCheck(cc)
  231.         if ccheck=1 then FileTextColor=cc
  232.         else FileTextColor='BLACK'
  233.  
  234.         cc=translate(linein(INIfile))
  235.         ccheck=ColorCheck(cc)
  236.         if ccheck=1 then GraphColor=cc
  237.         else GraphColor='BLACK'
  238.         cc=translate(linein(INIfile))
  239.         ccheck=ColorCheck(cc)
  240.         if ccheck=1 then GraphTextColor=cc
  241.         else GraphTextColor='WHITE'
  242.  
  243.         cc=translate(linein(INIfile))
  244.         ccheck=ColorCheck(cc)
  245.         if ccheck=1 then FreeColor=cc
  246.         else FreeColor='WHITE'
  247.         cc=translate(linein(INIfile))
  248.         ccheck=ColorCheck(cc)
  249.         if ccheck=1 then UsedColor=cc
  250.         else UsedColor='GREEN'
  251.         cc=translate(linein(INIfile))
  252.         ccheck=ColorCheck(cc)
  253.         if ccheck=1 then WasteColor=cc
  254.         else WasteColor='RED'
  255.         
  256.         res=translate(linein(INIfile))
  257.         rcheck=ResCheck(res)
  258.         if rcheck=1 then ScrRes=res
  259.         else ScrRes='640X480'
  260.     end
  261.     if defaults=1 then do
  262.         MainColor='WHITE'
  263.         MainTextColor='BLACK'
  264.         DirColor='CYAN'
  265.         DirTextColor='BLACK'
  266.         FileColor='CYAN'
  267.         FileTextColor='BLACK'
  268.         GraphColor='BLACK'
  269.         GraphTextColor='WHITE'
  270.         FreeColor='WHITE'
  271.         UsedColor='GREEN'
  272.         WasteColor='RED'
  273.         ScrRes='640X480'
  274.     end   
  275.  
  276.     if ScrRes='640X480' then do
  277.         FileDiagWidth=30
  278.         FontSize=16
  279.         TopText=960
  280.         TextSpace=38
  281.         DirListEnd=365
  282.         StatsHalfTwo=515
  283.         TopKey=890
  284.         BottomKey=825
  285.         KeyName=845
  286.         GraphLeft=12
  287.         GraphBottom=30
  288.         GraphRight=65
  289.         GraphTop=85
  290.         GTopText=930
  291.         GraphTopOne=760
  292.         GraphTopTwo=350
  293.         GraphTextOne=480
  294.         GraphTextTwo=50
  295.     end
  296.  
  297.     if ScrRes='800X600' then do
  298.         FileDiagWidth=28
  299.         FontSize=14
  300.         TopText=965
  301.         TextSpace=38
  302.         DirListEnd=320
  303.         StatsHalfTwo=450
  304.         TopKey=905
  305.         BottomKey=845
  306.         KeyName=860
  307.         GraphLeft=15
  308.         GraphBottom=40
  309.         GraphRight=60
  310.         GraphTop=80
  311.         GTopText=940
  312.         GraphTopOne=775
  313.         GraphTopTwo=360
  314.         GraphTextOne=485
  315.         GraphTextTwo=50
  316.     end
  317.  
  318.     if ScrRes='1024X768' then do
  319.         FileDiagWidth=25
  320.         FontSize=14
  321.         TopText=970
  322.         TextSpace=35
  323.         DirListEnd=325
  324.         StatsHalfTwo=460
  325.         TopKey=905
  326.         BottomKey=850
  327.         KeyName=860
  328.         GraphLeft=15
  329.         GraphBottom=40
  330.         GraphRight=60
  331.         GraphTop=80
  332.         GTopText=940
  333.         GraphTopOne=775
  334.         GraphTopTwo=360
  335.         GraphTextOne=485
  336.         GraphTextTwo=50
  337.     end
  338.  
  339.     if ScrRes='1280X1024' then do
  340.         FileDiagWidth=25
  341.         FontSize=14
  342.         TopText=970
  343.         TextSpace=33
  344.         DirListEnd=325
  345.         StatsHalfTwo=470
  346.         TopKey=900
  347.         BottomKey=855
  348.         KeyName=860
  349.         GraphLeft=15
  350.         GraphBottom=40
  351.         GraphRight=60
  352.         GraphTop=80
  353.         GTopText=945
  354.         GraphTopOne=765
  355.         GraphTopTwo=350
  356.         GraphTextOne=480
  357.         GraphTextTwo=50
  358.     end
  359.  
  360.     if ScrRes='1600X1200' then do
  361.         FileDiagWidth=24
  362.         FontSize=16
  363.         TopText=970
  364.         TextSpace=32
  365.         DirListEnd=305
  366.         StatsHalfTwo=435
  367.         TopKey=905
  368.         BottomKey=860
  369.         KeyName=865
  370.         GraphLeft=15
  371.         GraphBottom=40
  372.         GraphRight=60
  373.         GraphTop=80
  374.         GTopText=940
  375.         GraphTopOne=775
  376.         GraphTopTwo=360
  377.         GraphTextOne=485
  378.         GraphTextTwo=50
  379.     end
  380.  
  381. end
  382.  
  383. /* If using Visual REXX, the main window is now drawn with some info  */
  384. /* written into it.                                                   */
  385.  
  386. if Visual=1 then do
  387.     title='DriveCheck v'||DCVer
  388.     mpos.left=20
  389.     mpos.bottom=10
  390.     mpos.right=80
  391.     mpos.top=90
  392.     MainID=VOpenWindow(title,MainColor,mpos)
  393.     call VForeColor MainID,MainTextColor
  394.     call VSetFont MainID,'TIME',FontSize
  395.     iline.1="DriveCheck v"||DCVer||" is a program written in REXX that"
  396.     iline.2="scans each file on the drive you specify to determine how"
  397.     iline.3="much slack space it is wasting.  Slackspace is the difference"
  398.     iline.4="between the size of the file and how much space is allocated"
  399.     iline.5="to it on the hard drive."
  400.     iline.6=""
  401.     iline.7="FAT formatted drives have more slack space per file than HPFS"
  402.     iline.8="formatted drives because of the way each file system"
  403.     iline.9="allocates space.  The difference in slack space between the"
  404.     iline.10="two file systems increases with each doubling of the drive"
  405.     iline.11="size, starting from 16MB (below 16MB, FAT changes so that"
  406.     iline.12="the per-file waste is equivalent to that of a drive between"
  407.     iline.13="128MB and 256MB in size).  This program will show you"
  408.     iline.14="exactly what the different file systems would waste on the"
  409.     iline.15="drive you specify, with the current mix of files."
  410.     iline.16=""
  411.     iline.17="DriveCheck may be modified and distributed freely, but it"
  412.     iline.18="would be nice if you gave credit where credit is due if"
  413.     iline.19="you make any changes to it and distribute that modified"
  414.     iline.20="form (though I can't forsee a reason for this)."
  415.     iline.21=""
  416.     iline.22="I'd appreciate any comments about the program, which you"
  417.     iline.23="can direct to:"
  418.     iline.24=""
  419.     iline.25="mruskai@microfone.net"
  420.     iline.26="Mike Ruskai 1:107/634@fidonet"
  421.     PosY=TopText
  422.     do i=1 to 26
  423.         call VSay MainID,15,PosY,iline.i
  424.         PosY=PosY-TextSpace
  425.     end
  426.     call VDialogPos 50,50
  427. end
  428.  
  429.  
  430. /* If no drive was passed to the program, it prompts the user to      */
  431. /* input one, repeating if an invalid drive is given.                 */
  432.  
  433. else do
  434.     if Visual=1 then do
  435.         drives=SysDriveMap('C','USED')
  436.         numdrv=words(drives)
  437.         dnum=0
  438.         do i=1 to numdrv
  439.             chkdrv=word(drives,i)
  440.             chkwrt=lineout(chkdrv||'\test.txt','Testing')
  441.             if chkwrt=0 then do
  442.                 dnum=dnum+1
  443.                 dlabel=subword(SysDriveInfo(chkdrv),4)
  444.                 if dlabel='' then label=''
  445.                 else label='<'||dlabel||'>'
  446.                 drive.dnum=chkdrv||'    '||label
  447.                 call stream chkdrv||'\test.txt','c',close
  448.                 call SysFileDelete chkdrv||'\test.txt'
  449.             end
  450.         end
  451.         drive.0=dnum
  452.         if dnum>10 then height=10
  453.         else if dnum<4 then height=dnum
  454.         else if dnum<7 then height=dnum-1
  455.         else height=dnum-2
  456.         call VListBox 'Drive Selection',drive,FileDiagWidth,height,1
  457.         TestDrive=substr(drive.vstring,1,2)
  458.     end
  459.     else do until ans=1
  460.         call SysCls
  461.         if ans=0 then do
  462.             call SysCurPos 8,0
  463.             say '"'TestDrive'"'||', is an invalid drive.'
  464.         end
  465.         call SysCurPos 10,0
  466.         say 'Which drive do you wish to check (e.g. C)?'
  467.         call charout ,': '
  468.         TDrive=translate(SysGetKey('echo'))
  469.         TestDrive=TDrive||':'        
  470.         if directory(TestDrive||'\')\=TestDrive||'\' then ans=0
  471.             else ans=1
  472.     end
  473.     ans=2
  474.     if Visual=1 then do
  475.         msg.0=1
  476.         msg.1='  Do you wish to skip EA checking?'
  477.         ans=VMsgBox('EA Skipping',msg,6)
  478.         if ans='YES' then SkipEA=1
  479.         else SkipEA=0
  480.     end
  481.     else do until ans=1
  482.         call SysCls
  483.         if ans=0 then do
  484.             call SysCurPos 8,0
  485.             say "Please answer only with 'Y' or 'N'."
  486.         end
  487.         call SysCurPos 10,0
  488.         say 'Do you wish to skip EA checking? (Y/N)'
  489.         call charout ,': '
  490.         res=translate(SysGetKey('echo'))
  491.         if res\='Y' & res\='N' then ans=0
  492.             else do
  493.                 ans=1
  494.                 if res='Y' then SkipEA=1
  495.                 else SkipEA=0
  496.             end
  497.     end
  498.     ans=2
  499.     if Visual=1 then do until confirm=1
  500.         msg.0=1
  501.         msg.1='Do you wish to save the results to a file?'
  502.         filech=VMsgBox('Output Choice',msg,6)
  503.         if filech='YES' then do 
  504.             click=VFileBox('File to save results to','',log)
  505.             if click='CANCEL' then confirm=0
  506.             else do
  507.                 logfile=log.vstring
  508.                 check=lineout(logfile,'check')
  509.                 if check=1 then do
  510.                     msg.0=1
  511.                     msg.1='Invalid filename chosen.'
  512.                     call VMsgBox 'Invalid Filename',msg,1
  513.                     confirm=0
  514.                 end
  515.                 else do
  516.                     call stream logfile,'c','close'
  517.                     call SysFileDelete logfile
  518.                     msg.0=1
  519.                     msg.1='Save results to '||logfile||'?'
  520.                     ans=VMsgBox('Confirmation',msg,3)
  521.                     if ans='OK' then do
  522.                         OutFile=logfile
  523.                         confirm=1
  524.                     end
  525.                 end
  526.             end
  527.         end
  528.         else do
  529.             OutFile='CON'
  530.             confirm=1
  531.         end
  532.     end       
  533.     else do until ans=1
  534.         call SysCls
  535.         if ans=0 then do
  536.             call SysCurPos 8,0
  537.             say "Please answer only with 'Y' or 'N'."
  538.         end
  539.         call SysCurPos 10,0
  540.         say 'Do you wish to direct output to a file? (Y/N)'
  541.         call charout ,': '
  542.         res=translate(SysGetKey('echo'))
  543.         if res\='Y' & res\='N' then ans=0
  544.             else do
  545.                 ans=1
  546.                 if res='Y' then GetOF=1
  547.                 else OutFile='CON'
  548.             end
  549.     end
  550.     if GetOF=1 then do
  551.         ans=2
  552.         do until ans=1
  553.             call SysCls
  554.             if ans=0 then do
  555.                 call SysCurPos 8,0
  556.                 say '"'OFName'"'||' is not a valid filename.'
  557.             end
  558.             call SysCurPos 10,0
  559.             say 'Enter the name for the output file.'
  560.             call charout ,': '
  561.             parse pull OFName
  562.             if substr(OFName,2,1)\=':' then do
  563.                 if pos('\',OutFile)=0 then 
  564.                     OFName=CurrDir||'\'||OFName
  565.                 else if pos('\',OFName)=1 then
  566.                     OFName=left(CurrDir,2)||OFName
  567.                     else OFName=CurrDir||'\'||OFName
  568.             end
  569.             check=lineout(OFName,'1')
  570.             if check\=0 then ans=0
  571.                 else do
  572.                     OutFile=OFName
  573.                     call stream OFName,'c','close'
  574.                     call SysFileDelete OFName
  575.                     do until ans2=1
  576.                         call SysCls
  577.                         if ans2=0 then do
  578.                             call SysCurPos 8,0
  579.                             say "Please answer only with 'Y' or 'N'."
  580.                         end
  581.                         call SysCurPos 10,0
  582.                         say 'Use '||'"'OutFile'"'||' for output? (Y/N)'
  583.                         call charout ,': '
  584.                         res=translate(SysGetKey('echo'))
  585.                         if res\='Y' & res\='N' then ans2=0
  586.                             else do
  587.                                 ans2=1
  588.                                 if res='Y' then ans=1
  589.                                 else ans=2
  590.                             end
  591.                     end
  592.                 end
  593.         end
  594.     end
  595. end
  596.  
  597. call directory TestDrive||'\'
  598.  
  599. /* Uses the total drive space as reported by SysDriveInfo to deter-   */
  600. /* mine the cluster size that FAT would use on the drive.  It then    */
  601. /* attempts to write a file with a long name to determine if the      */
  602. /* drive being scanned is HPFS or FAT, and orders the allocation unit */
  603. /* variables accordingly (affects report at program conclusion).      */
  604.  
  605. DriveSize=word(SysDriveInfo(TestDrive),3)
  606. if DriveSize<16777216 then ClustSize=4096
  607. else do
  608.     if DriveSize>=16777216 & DriveSize<134217728 then ClustSize=2048
  609.     else do
  610.         RawClusterSize=format((DriveSize/65536),,0)
  611.         BinClust=x2b(d2x(RawClusterSize))
  612.         ValidPartStart=pos('1',BinClust)
  613.         DigitValue=length(substr(BinClust,ValidPartStart))
  614.         ClustSize=2**DigitValue
  615.     end
  616. end
  617. tfile='Testing For HPFS File System'
  618. rc=lineout(tfile,'test')
  619. if rc=1 then do
  620.     FileSystem.1='FAT'
  621.     FileSystem.2='HPFS'
  622.     AUnit.1=ClustSize
  623.     AUnit.2=512
  624.     Fnode.1=0
  625.     Fnode.2=512
  626. end
  627. else do
  628.     FileSystem.1='HPFS'
  629.     FileSystem.2='FAT'
  630.     call stream tfile,'c','close'
  631.     call SysFileDelete tfile
  632.     AUnit.1=512
  633.     AUnit.2=ClustSize
  634.     Fnode.1=512
  635.     Fnode.2=0
  636. end
  637.  
  638. /* Quick check to see if CMD.EXE or 4OS2.EXE is being used.  It has   */
  639. /* an effect on how EA size checking is done, since the display for   */
  640. /* each command processor is slightly different.                      */
  641. /* Note also that if you are using CMD.EXE, you will have to switch   */
  642. /* to the desktop manually to interact with the VREXX components.     */
  643. /* I do not know the source of the problem.                           */
  644.  
  645. p1=right(d2x(random(65535)),4,'0')
  646. p2=right(d2x(random(65535)),4,'0')
  647. TShChk='\'||p1||p2||'.TMP'
  648. '@ver>'||TShChk
  649. call SysFileSearch '4OS2',TShChk,'ShCheck.'
  650. call stream TShChk,'c','close'
  651. call SysFileDelete TShChk
  652. if ShCheck.0=0 then UShell='CMD'
  653.     else UShell='4OS2'
  654.  
  655. /* Initializes the variables used for the main procedure.             */
  656.  
  657. crlf='0a0d'x
  658. TotFiles=0
  659. TotSize=0
  660. TotDirs=0
  661. TotWaste.1=0
  662. TotWaste.2=0
  663. TotDirSize.1=0
  664. TotDirSize.2=0
  665.  
  666. /* Uses CMD.EXE or 4OS2.EXE to get a quick list of all subdirectories */
  667. /* on the drive for the computation of their space consumption, and   */
  668. /* that of the files they contain.  If Visual REXX is in use, the     */
  669. /* directory window and file window are drawn, and the scanning       */
  670. /* begins.                                                            */
  671.  
  672. if Visual=1 then do
  673.     title='DriveCheck v'||DCVer||' scanning drive '||TestDrive
  674.     call VSetTitle MainID,title
  675.     title='Current scan directory'
  676.     dpos.left=15
  677.     dpos.bottom=57
  678.     dpos.right=50
  679.     dpos.top=63
  680.     DirID=VOpenWindow(title,DirColor,dpos)
  681.     call VForeColor DirID,DirTextColor
  682.     call VSetFont DirID,'TIME',FontSize
  683.     title='Current scan file'
  684.     fpos.left=15
  685.     fpos.bottom=37
  686.     fpos.right=50
  687.     fpos.top=43
  688.     FileID=VOpenWindow(title,FileColor,fpos)
  689.     call VForeColor FileID,FileTextColor
  690.     call VSetFont FileID,'TIME',FontSize
  691.     call VSay DirID,5,500,TestDrive||'\'
  692. end
  693. else do
  694.     call SysCls
  695.     ClrStr="                                  "
  696.     ClrStr=ClrStr||ClrStr||' '
  697.     call SysCurPos 12,0
  698.     call charout ,'Scanning : '||TestDrive||'\'
  699. end
  700. Data=ProcDir(TestDrive||'\')
  701. TotSize=TotSize+word(Data,3)
  702. do i=1 to 2
  703.     TotWaste.i=TotWaste.i+word(Data,i)
  704.     TotDirSize.i=TotDirSize.i+AUnit.i
  705. end
  706. TotFiles=TotFiles+word(Data,4)
  707. p1=right(d2x(random(65535)),4,'0')
  708. p2=right(d2x(random(65535)),4,'0')
  709. TDList='\'||p1||p2||'.TMP'
  710. if Visual=1 then do
  711.     str='Getting list of directories... '
  712.     call VForeColor MainID,MainTextColor
  713.     call VClearWindow MainID
  714.     call VSay MainID,5,TopText,str
  715. end
  716. else do
  717.     call SysCurPos 10,0
  718.     call SysCurState 'off'
  719.     call charout ,"Getting list of directories... "
  720. end
  721. if UShell='4OS2' then do
  722.     signal off error
  723.     '*@dir/b/ad/s > '||TDList
  724.     signal on error
  725. end
  726. else '@dir/f/ad/s >'||TDList
  727. if Visual=1 then do
  728.     str='Done'
  729.     call VSay MainID,DirListEnd,TopText,str
  730. end
  731. else call charout ,"Done"
  732. check=lines(TDList)
  733. if Visual\=1 then do    
  734.     call SysCurPos 12,0
  735.     call charout ,'Scanning : '
  736. end
  737. do while check=1
  738.     WDir=linein(TDList)
  739.     if length(WDir)>68 then 
  740.         DDir=left(WDir,68)||'>'
  741.     else
  742.         DDir=WDir
  743.     if Visual=1 then do
  744.         call VClearWindow DirID
  745.         str=WDir
  746.         call VSay DirID,5,500,str
  747.     end
  748.     else do
  749.         call SysCurPos 12,11
  750.         call charout ,ClrStr
  751.         call SysCurPos 12,11
  752.         call charout ,DDir
  753.     end
  754.     TotDirs=TotDirs+1
  755.     Data=ProcDir(WDir)
  756.     TotSize=TotSize+word(Data,3)
  757.     do i=1 to 2
  758.         TotWaste.i=TotWaste.i+word(Data,i)
  759.         TotDirSize.i=TotDirSize.i+AUnit.i
  760.     end
  761.     TotFiles=TotFiles+word(Data,4)
  762.     DEAData=TallyDirEA(WDir)
  763.     do i=1 to 2
  764.         TotDirSize.i=TotDirSize.i+word(DEAData,i)
  765.     end
  766.     check=lines(TDList)
  767. end
  768. call stream TDList,'c','close'
  769. call SysFileDelete TDList
  770.  
  771. do i=1 to 2
  772.     TotFree.i=DriveSize-(TotSize+TotDirSize.i+TotWaste.i)
  773. end
  774. AllWaste=TotWaste.1-TotWaste.2
  775. AllDir=TotDirSize.1-TotDirSize.2
  776. AllTot=AllWaste+AllDir
  777. if AllTot>=0 then 
  778.     if AllTot=0 then
  779.         TotalDiff=0
  780. else do
  781.     Modifier='*LOST*'
  782.     TotalDiff=abs(AllTot)
  783. end
  784. else do
  785.     Modifier='*SAVED*'
  786.     TotalDiff=abs(AllTot)
  787. end
  788.  
  789. if Visual\=1 then do
  790.     if OutFile='CON' then do
  791.         call SysCurPos 16,0
  792.         call lineout ,'Press any key for statistics...'
  793.         scrap=SysGetKey('noecho')
  794.     end
  795. end
  796.  
  797. /* Reports the data in a formatted manner.  Each of the numerical     */
  798. /* variables is deliminated with via the CoDel procedure.  Then the   */
  799. /* screen is cleared, data presented, and conclusion stated.          */
  800.  
  801. FormDriveSize=CoDel(DriveSize)
  802. FormTotalDiff=CoDel(TotalDiff)
  803. do i=1 to 2
  804.     FormDirSpace.i=CoDel(TotDirSize.i)
  805.     FormWasteSpace.i=CoDel(TotWaste.i)
  806.     FormUnitSize.i=CoDel(AUnit.i)
  807.     FormTotFree.i=CoDel(TotFree.i)
  808. end
  809. FormTotSize=CoDel(TotSize)
  810. FormTotFiles=CoDel(TotFiles)
  811. FormTotDirs=CoDel(TotDirs)
  812.  
  813. do i=1 to 2
  814.     PercentFree.i=(TotFree.i/DriveSize)*100
  815.     PercentUsed.i=((TotDirSize.i+TotSize)/DriveSize)*100
  816.     PercentWaste.i=(TotWaste.i/DriveSize)*100
  817.     fPercentFree.i=format(PercentFree.i,,2)
  818.     fPercentUsed.i=format(PercentUsed.i,,2)
  819.     fPercentWaste.i=format(PercentWaste.i,,2)
  820.     IntPFree.i=format(PercentFree.i,,0)
  821.     IntPUsed.i=format(PercentUsed.i,,0)
  822.     IntPWaste.i=format(PercentWaste.i,,0)
  823. end
  824.  
  825. if Visual\=1 then do
  826.     call SysCls
  827.     call SysCurPos 5,0
  828. end
  829.  
  830. if SkipEA=1 then
  831.     infochecked="        "
  832. else 
  833.     infochecked="and EA's"
  834.  
  835. rline.1.1="Drive "||TestDrive||" "||FormDriveSize||" bytes"
  836. rline.1.2=""
  837. rline.2.1=""
  838. rline.2.2=""
  839. rline.3.1="Total files                           "
  840. rline.3.2=": "||FormTotFiles 
  841. rline.4.1="Total size of files "||infochecked||"          "
  842. rline.4.2=": "||FormTotSize||" bytes" 
  843. rline.5.1=""
  844. rline.5.2=""
  845. rline.6.1="Current statistics using "||FileSystem.1||" :"
  846. rline.6.2=""
  847. rline.7.1=""
  848. rline.7.2=""
  849. rline.8.1="Allocation unit size                  "
  850. rline.8.2=": "||FormUnitSize.1||" bytes" 
  851. rline.9.1="Total space consumed by directories   "
  852. rline.9.2=": "||FormDirSpace.1||" bytes" 
  853. rline.10.1="Total wasted space for files "||infochecked||" "
  854. rline.10.2=": "||FormWasteSpace.1||" bytes" 
  855. rline.11.1=""
  856. rline.11.2=""
  857. rline.12.1="If it was being used with "||FileSystem.2||" :"
  858. rline.12.2=""
  859. rline.13.1=""
  860. rline.13.2=""
  861. rline.14.1="Allocation unit size                  "
  862. rline.14.2=": "||FormUnitSize.2||" bytes" 
  863. rline.15.1="Total space consumed by directories   "
  864. rline.15.2=": "||FormDirSpace.2||" bytes" 
  865. rline.16.1="Total wasted space for files "||infochecked||" "
  866. rline.16.2=": "||FormWasteSpace.2||" bytes" 
  867. rline.17=""
  868. if TotalDiff=0 then do
  869.     rline.18="Oddly enough, by using "||FileSystem.1||" instead of "||FileSystem.2||","
  870.     rline.19="you've neither saved nor lost any disk space on drive "||TestDrive||"."
  871. end
  872. else do
  873.     rline.18="By using "||FileSystem.1||" instead of "||FileSystem.2||", you've"
  874.     rline.19=Modifier||" "||FormTotalDiff||" bytes on drive "||TestDrive||"."
  875. end
  876.  
  877. if Visual\=1 | (Visual=1 & Outfile\='CON') then do
  878.     do i=1 to 16
  879.         rline.i=rline.i.1||rline.i.2
  880.     end
  881.     do i=1 to 19
  882.         call lineout OutFile,rline.i
  883.     end
  884.     if Visual\=1 & OutFile='CON' then do
  885.         say ""
  886.         say "Press any key to see the graph..."
  887.         junk=SysGetKey('noecho')
  888.         call SysCls
  889.         UseChar=d2c(219)
  890.         WasteChar=d2c(177)
  891.         FreeChar=d2c(176)
  892.         do i=1 to 2
  893.             NumUse.i=format(((PercentUsed.i/100)*50),,0)
  894.             NumWaste.i=format(((PercentWaste.i/100)*50),,0)
  895.             NumFree.i=format(((PercentFree.i/100)*50),,0)
  896.         end
  897.         Graph.1=''
  898.         Graph.2=''
  899.         do i=1 to 2
  900.             do j=1 to NumUse.i
  901.                 Graph.i=Graph.i||UseChar
  902.             end
  903.         end
  904.         do i=1 to 2
  905.             do j=1 to NumWaste.i
  906.                 Graph.i=Graph.i||WasteChar
  907.             end
  908.         end
  909.         do i=1 to 2
  910.             do j=1 to NumFree.i
  911.                 Graph.i=Graph.i||FreeChar
  912.             end
  913.         end
  914.         GraphString.1='               '||Graph.1||crlf||'               '||,
  915.             Graph.1||crlf
  916.         GraphString.2='               '||Graph.2||crlf||'               '||,
  917.             Graph.2||crlf
  918.         tstring='Drive '||TestDrive||'    '||FormDriveSize||' bytes'
  919.         tspos=format(((80-(length(tstring)))/2),,0)
  920.         kstring=d2c(219)||' = used    '||d2c(177)||' = wasted    '||,
  921.             d2c(176)||' = free'
  922.         kspos=format(((80-(length(kstring)))/2),,0)
  923.         do i=1 to 2
  924.             pstring.i='With '||FileSystem.i||', '||fPercentUsed.i||'%'||' used, '||,
  925.                 fPercentWaste.i||'%'||' wasted, '||fPercentFree.i||'%'||' free.'
  926.             pspos.i=format(((80-(length(pstring.i)))/2),,0)
  927.         end
  928.         call SysCurPos 4,tspos
  929.         call charout ,tstring
  930.         call SysCurPos 6,kspos
  931.         call charout ,kstring
  932.         call SysCurPos 9,0
  933.         call charout ,GraphString.1
  934.         call SysCurPos 12,pspos.1
  935.         call charout ,pstring.1
  936.         call SysCurPos 15,0
  937.         call charout ,GraphString.2
  938.         call SysCurPos 18,pspos.2
  939.         call charout ,pstring.2
  940.         call charout ,crlf
  941.     end 
  942.     if Visual=1 then do
  943.         msg.0=1
  944.         msg.1='Results saved to '||OutFile||'.'
  945.         call VMsgBox 'Info',msg,1
  946.     end
  947. end
  948. else do
  949.     if Visual=1 then do
  950.         call VCloseWindow FileID
  951.         call VCloseWindow DirID
  952.         call VClearWindow MainID
  953.         PosY=TopText
  954.         do i=1 to 16
  955.             call VSay MainID,5,PosY,rline.i.1
  956.             call VSay MainID,StatsHalfTwo,PosY,rline.i.2
  957.             PosY=PosY-TextSpace
  958.         end
  959.         do i=17 to 19
  960.             call VSay MainID,5,PosY,rline.i
  961.             PosY=PosY-TextSpace
  962.         end
  963.         title='Comparison graphs'
  964.         gpos.left=GraphLeft
  965.         gpos.bottom=GraphBottom
  966.         gpos.right=GraphRight
  967.         gpos.top=GraphTop
  968.         GraphID=VOpenWindow(title,GraphColor,gpos)
  969.         call VForeColor GraphID,GraphTextColor
  970.         call VSetFont GraphID,'TIME',FontSize
  971.         hstring='Drive '||TestDrive||'    '||FormDriveSize||' bytes.'
  972.         call VSay GraphID,10,GTopText,hstring
  973.         ypos.1=TopKey
  974.         ypos.2=BottomKey
  975.         call VForeColor GraphID,UsedColor
  976.         call VDrawParms GraphID,0,0,5
  977.         ux.1=120
  978.         ux.2=160
  979.         ux.3=160
  980.         ux.4=120
  981.         ux.5=ux.1
  982.         uy.1=ypos.1
  983.         uy.2=ypos.1
  984.         uy.3=ypos.2
  985.         uy.4=ypos.2
  986.         uy.5=uy.1
  987.         call VDraw GraphID,'POLYGON',ux,uy,4
  988.         call VForeColor GraphID,WasteColor
  989.         call VDrawParms GraphID,0,0,1
  990.         wx.1=400
  991.         wx.2=440
  992.         wx.3=440
  993.         wx.4=400
  994.         wx.5=wx.1
  995.         wy.1=ypos.1
  996.         wy.2=ypos.1
  997.         wy.3=ypos.2
  998.         wy.4=ypos.2
  999.         wy.5=wy.1
  1000.         call VDraw GraphID,'POLYGON',wx,wy,4
  1001.         call VForeColor GraphID,FreeColor
  1002.         call VDrawParms GraphID,0,0,2
  1003.         fx.1=680
  1004.         fx.2=720
  1005.         fx.3=720
  1006.         fx.4=680
  1007.         fx.5=fx.1
  1008.         fy.1=ypos.1
  1009.         fy.2=ypos.1
  1010.         fy.3=ypos.2
  1011.         fy.4=ypos.2
  1012.         fy.5=fy.1
  1013.         call VDraw GraphID,'POLYGON',fx,fy,4
  1014.         call VForeColor GraphID,GraphTextColor
  1015.         call VDraw GraphID,'LINE',ux,uy,5
  1016.         call VDraw GraphID,'LINE',wx,wy,5
  1017.         call VDraw GraphID,'LINE',fx,fy,5
  1018.         
  1019.         ustring='= Used'
  1020.         wstring='= Wasted'
  1021.         fstring='= Free'
  1022.         call VSay GraphID,170,KeyName,ustring
  1023.         call VSay GraphID,450,KeyName,wstring
  1024.         call VSay GraphID,730,KeyName,fstring
  1025.         ypos.1=GraphTopOne
  1026.         ypos.2=GraphTopTwo
  1027.         do i=1 to 2
  1028.             UsedLength.i=format(((PercentUsed.i/100)*700),,0)
  1029.             WasteLength.i=format(((PercentWaste.i/100)*700),,0)
  1030.             FreeLength.i=format(((PercentFree.i/100)*700),,0)
  1031.         end
  1032.  
  1033.         ux1.1=150
  1034.         ux1.2=150+UsedLength.1
  1035.         ux1.3=ux1.2
  1036.         ux1.4=150
  1037.         uy1.1=ypos.1
  1038.         uy1.2=ypos.1
  1039.         uy1.3=ypos.1-150
  1040.         uy1.4=ypos.1-150
  1041.         wx1.1=ux1.2+1
  1042.         wx1.2=wx1.1+WasteLength.1
  1043.         wx1.3=wx1.2
  1044.         wx1.4=wx1.1
  1045.         wy1.1=ypos.1
  1046.         wy1.2=ypos.1
  1047.         wy1.3=ypos.1-150
  1048.         wy1.4=ypos.1-150
  1049.         fx1.1=wx1.2+1
  1050.         fx1.2=fx1.1+FreeLength.1
  1051.         fx1.3=fx1.2
  1052.         fx1.4=fx1.1
  1053.         fy1.1=ypos.1
  1054.         fy1.2=ypos.1
  1055.         fy1.3=ypos.1-150
  1056.         fy1.4=ypos.1-150
  1057.  
  1058.         ux2.1=150
  1059.         ux2.2=150+UsedLength.2
  1060.         ux2.3=ux2.2
  1061.         ux2.4=150
  1062.         uy2.1=ypos.2
  1063.         uy2.2=ypos.2
  1064.         uy2.3=ypos.2-150
  1065.         uy2.4=ypos.2-150
  1066.         wx2.1=ux2.2+1
  1067.         wx2.2=wx2.1+WasteLength.2
  1068.         wx2.3=wx2.2
  1069.         wx2.4=wx2.1
  1070.         wy2.1=ypos.2
  1071.         wy2.2=ypos.2
  1072.         wy2.3=ypos.2-150
  1073.         wy2.4=ypos.2-150
  1074.         fx2.1=wx2.2+1
  1075.         fx2.2=fx2.1+FreeLength.2
  1076.         fx2.3=fx2.2
  1077.         fx2.4=fx2.1
  1078.         fy2.1=ypos.2
  1079.         fy2.2=ypos.2
  1080.         fy2.3=ypos.2-150
  1081.         fy2.4=ypos.2-150
  1082.  
  1083.         call VForeColor GraphID,UsedColor
  1084.         call VDrawParms GraphID,0,0,5
  1085.         call VDraw GraphID,'POLYGON',ux1,uy1,4
  1086.         call VDraw GraphID,'POLYGON',ux2,uy2,4
  1087.         call VForeColor GraphID,WasteColor
  1088.         call VDrawParms GraphID,0,0,1
  1089.         call VDraw GraphID,'POLYGON',wx1,wy1,4
  1090.         call VDraw GraphID,'POLYGON',wx2,wy2,4
  1091.         call VForeColor GraphID,FreeColor
  1092.         call VDrawParms GraphID,0,0,2
  1093.         call VDraw GraphID,'POLYGON',fx1,fy1,4
  1094.         call VDraw GraphID,'POLYGON',fx2,fy2,4
  1095.     
  1096.         bx1.1=149
  1097.         bx1.2=852
  1098.         bx1.3=bx1.2
  1099.         bx1.4=bx1.1
  1100.         bx1.5=bx1.1
  1101.         by1.1=ypos.1+1
  1102.         by1.2=ypos.1+1
  1103.         by1.3=ypos.1-151
  1104.         by1.4=ypos.1-151
  1105.         by1.5=by1.1
  1106.         bx2.1=149
  1107.         bx2.2=852
  1108.         bx2.3=bx2.2
  1109.         bx2.4=bx2.1
  1110.         bx2.5=bx2.1
  1111.         by2.1=ypos.2+1
  1112.         by2.2=ypos.2+1
  1113.         by2.3=ypos.2-151
  1114.         by2.4=ypos.2-151
  1115.         by2.5=by2.1
  1116.  
  1117.         call VForeColor GraphID,GraphTextColor
  1118.         call VDrawParms GraphID,0,0,0
  1119.         call VDraw GraphID,'LINE',bx1,by1,5
  1120.         call VDraw GraphID,'LINE',bx2,by2,5
  1121.  
  1122.         do i=1 to 2
  1123.             pstring.i='With '||FileSystem.i||', '||fPercentUsed.i||'%'||,
  1124.                 ' used, '||fPercentWaste.i||'%'||' wasted, '||fPercentFree.i||,
  1125.             '% free.'
  1126.         end
  1127.         call VForeColor GraphID,GraphTextColor
  1128.         call VSay GraphID,100,GraphTextOne,pstring.1
  1129.         call VSay GraphID,100,GraphTextTwo,pstring.2
  1130.         call VDialogPos 80,50
  1131.         do until confirm=1
  1132.             ExitChoice.0=2
  1133.             ExitChoice.1='Exit DriveCheck'
  1134.             ExitChoice.2='Log results to file, then exit DriveCheck'
  1135.             ExitChoice.vstring=ExitChoice.1
  1136.             call VRadioBox 'Exiting DriveCheck',ExitChoice,1
  1137.             choice=ExitChoice.vstring
  1138.             if choice=ExitChoice.1 then confirm=1
  1139.             else do 
  1140.                 click=VFileBox('File to save results to','',log)
  1141.                 if click='CANCEL' then confirm=0 
  1142.                 else do
  1143.                     logfile=log.vstring
  1144.                     check=lineout(logfile,'check')
  1145.                     if check=1 then do
  1146.                         msg.0=1
  1147.                         msg.1='Invalid filename chosen.'
  1148.                         call VMsgBox 'Invalid Filename',msg,1
  1149.                         confirm=0
  1150.                     end
  1151.                     else do    
  1152.                         call stream logfile,'c','close'
  1153.                         call SysFileDelete logfile
  1154.                         msg.0=1
  1155.                         msg.1='Save results to '||logfile||'?'
  1156.                         ans=VMsgBox('Confirmation',msg,3)
  1157.                         if ans='OK' then do
  1158.                             confirm=1
  1159.                             do i=1 to 16
  1160.                                 rline.i=rline.i.1||rline.i.2
  1161.                             end
  1162.                             do i=1 to 19
  1163.                                 call lineout logfile,rline.i
  1164.                             end
  1165.                         end
  1166.                         else confirm=0
  1167.                     end
  1168.                 end
  1169.             end    
  1170.         end    
  1171.     end
  1172. end
  1173. call directory CurrDir
  1174. if Visual\=1 & OutFile\='CON' then say 'Results saved to '||Outfile||'.'
  1175. if Visual=1 then call VExit
  1176. exit
  1177.  
  1178. SYNTAX:
  1179. prob='SYNTAX'
  1180. proba=1
  1181. ERROR:
  1182. if proba\=1 then do
  1183.     prob='ERROR'
  1184.     proba=1
  1185. end
  1186. FAILURE:
  1187. if proba\=1 then do
  1188.     prob='FAILURE'
  1189.     proba=1
  1190. end
  1191. HALT:
  1192. if proba\=1 then prob='HALT'
  1193.  
  1194. say ''
  1195. say ''
  1196. say 'Problem of type '||prob||' while program was on line '||sigl||'.'
  1197. say '"'Sourceline(sigl)'"'
  1198. call directory CurrDir
  1199. if Visual=1 then call VExit
  1200. exit
  1201.  
  1202. Usage:
  1203. call SysCls
  1204. call SysCurPos 5,0
  1205. say "DriveCheck v"||DCVer||" REXX disk space waste scanner, written by:"
  1206. say ""
  1207. say "Mike Ruskai <mruskai@microfone.net>"
  1208. say ""
  1209. say "Usage: DRIVECHK.CMD [/T] [<drive letter>: [/S] [/O:<filename>]]"
  1210. say ""
  1211. say "/T               - Run in text mode (no graphical interface)"
  1212. say "<drive letter>:  - Drive to scan"
  1213. say "/S               - Skip extended attributes checking"
  1214. say "/O:<filename>    - Write output to <filename>"
  1215. say ""
  1216. say "Example:"
  1217. say ""
  1218. say "DRIVECHK C: /S /O:scan.log"
  1219. say ""
  1220. say " - Scans drive C:, skips EA's, writes output to 'scan.log'"
  1221. say ""
  1222. say "Run DRIVECHK.CMD with no parameters to be prompted for input."
  1223. say "Use of the /T parameter alone results in text-only prompting."
  1224. say ""
  1225. exit
  1226. /******************** Begin TallyFiles Procedure **********************/
  1227. /* Procedure to determine total size and waste of all files in a      */
  1228. /* given directory, for both FAT and HPFS file systems.  The list of  */
  1229. /* files is obtained using SysFileTree.  For each file, it's total    */
  1230. /* size and the size of its EA's (unless skipped) are tallied for the */
  1231. /* file size total, and the waste of the file and it's EA's is added  */
  1232. /* to the waste total.  Calculations are performed by the SlackSpace  */
  1233. /* procedure, for both FAT and HPFS file systems.                     */
  1234.  
  1235. TallyFiles: Procedure expose Fnode.1 Fnode.2 SkipEA UShell AUnit.1 AUnit.2 Visual FileID
  1236.  
  1237. ClrStr='                               '
  1238. ClrStr=ClrStr||ClrStr||' '
  1239. TotSize=0
  1240. TotWaste.1=0
  1241. TotWaste.2=0
  1242. TotAlloc.1=0
  1243. TotAlloc.2=0
  1244. arg Dir
  1245. call directory Dir
  1246. call SysFileTree '*','files.','F'
  1247. if Visual\=1 then do
  1248.     call SysCurPos 14,0
  1249.     call charout ,'Working on file: '
  1250. end
  1251. do i=1 to files.0
  1252.     if SkipEA=1 then do
  1253.         CurFile=filespec('name',(substr(files.i,38)))
  1254.         if length(CurFile)>63 then
  1255.             dCurFile=substr(CurFile,1,62)||'>'
  1256.         else dCurFile=CurFile
  1257.         if Visual=1 then do
  1258.             call VClearWindow FileID
  1259.             str=CurFile
  1260.             call VSay FileID,5,500,str
  1261.         end
  1262.         else do
  1263.             call SysCurPos 14,17
  1264.             say ClrStr
  1265.             call SysCurPos 14,17
  1266.             call charout ,dCurFile        
  1267.         end
  1268.         FSize=word(files.i,3)
  1269.         TotSize=TotSize+FSize
  1270.         Waste=SlackSpace(Fsize)
  1271.         TotWaste.1=TotWaste.1+word(Waste,1)+Fnode.1
  1272.         TotWaste.2=TotWaste.2+word(Waste,2)+Fnode.2
  1273.     end
  1274.     else do
  1275.         file=substr(files.i,38)
  1276.         p1=right(d2x(random(65535)),4,'0')
  1277.         p2=right(d2x(random(65535)),4,'0')
  1278.         tfile='\'||p1||p2||'.TMP'
  1279.         if UShell='4OS2' then do
  1280.             signal off error
  1281.             '*@dir/a/knm '||'"'file'"'||'>'||tfile
  1282.             signal on error
  1283.             CurFile=filespec('name',file)
  1284.             if length(CurFile)>63 then
  1285.                 dCurFile=substr(CurFile,1,62)||'>'
  1286.             else dCurFile=CurFile
  1287.             if Visual=1 then do
  1288.                 call VClearWindow FileID
  1289.                 str=CurFile
  1290.                 call VSay FileID,5,5,str
  1291.             end
  1292.             else do 
  1293.                 call SysCurPos 14,17
  1294.                 say ClrStr
  1295.                 call SysCurPos 14,17
  1296.                 call charout ,dCurFile        
  1297.             end
  1298.             filestring=linein(tfile)
  1299.             UFEASize=word(filestring,4)
  1300.             UFFSize=word(filestring,3)
  1301.             EACommaPos=pos(',',UFEASize)
  1302.             if EACommaPos\=0 then
  1303.                 EASize=delstr(UFEASize,EACommaPos,1)
  1304.             else EASize=UFEASize
  1305.             FCommaPos=pos(',',UFFSize)
  1306.             if FCommaPos\=0 then do until FCommaPos=0
  1307.                 UFFSize=delstr(UFFSize,FCommaPos,1)
  1308.                 FCommaPos=pos(',',UFFSize)
  1309.             end 
  1310.             FSize=UFFSize
  1311.         end
  1312.         else do
  1313.             '@dir/a/n '||'"'file'"'||'>'||tfile
  1314.             CurFile=filespec('name',file)
  1315.             if length(CurFile)>63 then
  1316.                 dCurFile=substr(CurFile,1,62)||'>'
  1317.             else dCurFile=CurFile
  1318.             if Visual=1 then do
  1319.                 call VClearWindows FileID
  1320.                 str=CurFile
  1321.                 call VSay FileID,5,5,str
  1322.             end
  1323.             else do
  1324.                 call SysCurPos 14,17
  1325.                 say ClrStr
  1326.                 call SysCurPos 14,17
  1327.                 call charout ,dCurFile        
  1328.             end
  1329.             do 5
  1330.                 scrap=linein(tfile)
  1331.             end
  1332.             filestring=linein(tfile)
  1333.         EASize=word(filestring,4)
  1334.         FSize=word(filestring,3)
  1335.         end
  1336.         TotSize=TotSize+FSize+EASize
  1337.         FWaste=SlackSpace(FSize)
  1338.         FWaste.1=word(FWaste,1)
  1339.         FWaste.2=word(FWaste,2)
  1340.         if EASize=0 then do
  1341.             TotWaste.1=TotWaste.1+FWaste.1+Fnode.1
  1342.             TotWaste.2=TotWaste.2+FWaste.2+Fnode.2
  1343.         end
  1344.         else do
  1345.             EAWaste=SlackSpace(EASize)
  1346.             EAWaste.1=word(EAWaste,1)
  1347.             EAWaste.2=word(EAWaste,2)
  1348.             TotWaste.1=TotWaste.1+FWaste.1+EAWaste.1
  1349.             TotWaste.2=TotWaste.2+FWaste.2+EAWaste.2
  1350.         end
  1351.         call stream tfile,'c','close'
  1352.         call SysFileDelete tfile
  1353.     end
  1354. end
  1355. return TotSize TotWaste.1 TotWaste.2 files.0
  1356. /******************** End TallyFiles Procedure ************************/
  1357.  
  1358. /******************** Begin SlackSpace Procddure **********************/
  1359. /* Procedure to determine the wasted space of the given file size.    */
  1360. /* This procedure receives the file size and allocation unit size     */
  1361. /* from the main program.  It divides the file size by the size of    */
  1362. /* the allocation unit, then multiplies the integer portion the       */
  1363. /* result to obtain the space occupied only by completely used        */
  1364. /* allocation units.  The difference between this and the size of the */
  1365. /* file is then subtracted from the size of the allocation unit which */
  1366. /* results in the amount of wasted space, in bytes.  Of course, if    */
  1367. /* there is no partial allocation unit usage, there is no wasted      */
  1368. /* space, and 0 is returned in such a case.                           */
  1369.  
  1370. SlackSpace: Procedure expose AUnit.1 AUnit.2 
  1371.  
  1372. arg FileSize
  1373. do i=1 to 2
  1374.     IntUnit.i=FileSize%AUnit.i
  1375.     FullUnits.i=IntUnit.i*AUnit.i
  1376.     Diff.i=FileSize-FullUnits.i
  1377.     if Diff.i=0 then do
  1378.         Waste.i=0
  1379.         AllocUnits.i=IntUnit.i
  1380.     end
  1381.     else do
  1382.         Waste.i=AUnit.i-Diff.i
  1383.         AllocUnits.i=IntUnit.i+1
  1384.     end
  1385.     TotAlloc.i=AllocUnits.i*AUnit.i
  1386. end
  1387. return Waste.1 Waste.2
  1388. /******************** End SlackSpace Procedure ************************/
  1389.  
  1390. /******************** Begin ProcDir Procedure *************************/
  1391. /* Procedure to get all information about a specific directory, which */
  1392. /* includes total file and EA size and wasted space (for both FAT and */
  1393. /* HPFS).                                                             */
  1394.  
  1395. ProcDir: Procedure expose FNode.1 FNode.2 AUnit.1 AUnit.2 UShell SkipEA Visual FileID
  1396.  
  1397. arg DirName
  1398. TSize=TallyFiles(DirName)
  1399. FSize=word(TSize,1)
  1400. Waste.1=word(TSize,2)
  1401. Waste.2=word(TSize,3)
  1402. NumFiles=word(TSize,4)
  1403. return Waste.1 Waste.2 FSize NumFiles
  1404. /******************** End ProcDir Procedure ***************************/
  1405.  
  1406. /******************** Begin TallyDirEA Procedure **********************/
  1407. /* Procedure to tally the extended attributes of a given directory,   */
  1408. /* which is done regardless of the SkipEA status, since it doesn't    */
  1409. /* really take that long.  The parent of the given directory is       */
  1410. /* changed to, so we can do a DIR listing of all directories, and     */
  1411. /* parse the information about the specific one we want from the list */
  1412. /* returned.  There seems to be no way to list only a specific        */
  1413. /* directory in either CMD.EXE or 4OS2.EXE.  Once the EA size for the */
  1414. /* directory is found, the total actual space taken up for each       */
  1415. /* allocation unit is calculated, and returned.                       */
  1416.  
  1417. TallyDirEA: Procedure expose AUnit.1 AUnit.2 UShell
  1418.  
  1419. arg DirName
  1420. tDirName=reverse(DirName)
  1421. BSPos=pos('\',tDirName)
  1422. BDName=translate(reverse(substr(tDirName,1,(BSPos-1))))
  1423. call directory DirName||'\..'
  1424. p1=right(d2x(random(65535)),4,'0')
  1425. p2=right(d2x(random(65535)),4,'0')
  1426. tfile='\'||p1||p2||'.TMP'
  1427. if UShell='4OS2' then do
  1428.     signal off error
  1429.     '@*dir/n/m/k/h/ad > '||tfile
  1430.     signal on error
  1431.     do until found=1
  1432.         dirstring=linein(tfile)
  1433.         if translate(subword(dirstring,5))=BDName then do
  1434.             UFEASize=word(dirstring,4)           
  1435.             EACommaPos=pos(',',UFEASize)
  1436.             if EACommaPos\=0 then
  1437.                 EASize=delstr(UFEASize,EACommaPos,1)
  1438.             else EASize=UFEASize
  1439.             found=1
  1440.         end
  1441.         else found=0
  1442.     end
  1443. end
  1444. else do
  1445.     '@dir/n/ad > '||tfile
  1446.     do 5
  1447.         scrap=linein(tfile)
  1448.     end
  1449.     do until found=1
  1450.         dirstring=linein(tfile)
  1451.         if translate(subword(dirstring,5))=BDName then do
  1452.             EASize=word(dirstring,4)
  1453.             found=1
  1454.         end
  1455.         else found=0
  1456.     end
  1457. end
  1458. call stream tfile,'c','close'
  1459. call SysFileDelete tfile
  1460. DSData=SlackSpace(EASize)
  1461. DirEATot.1=EASize+word(DSData,1)
  1462. DirEATot.2=EASize+word(DSData,2)
  1463. return DirEATot.1 DirEATot.2
  1464. /******************** End TallyDirEA Procedure ************************/
  1465.  
  1466. /******************** Begin CoDel Procedure ***************************/
  1467. /* Procedure to take a long decimal number, and deliminate it with a  */
  1468. /* comma for each group of three digits, starting from the end of the */
  1469. /* number.  First you reverse the string.  Then you take the first    */
  1470. /* three characters of the reversed string (i.e. last three           */
  1471. /* characters of the original string), writing the remaining          */
  1472. /* characters back to the variable.  The three characters are         */
  1473. /* appended to the final string with a comma at the end, and the      */
  1474. /* process is repeated until there are three or less characters left  */
  1475. /* in the reversed string variable.  The final write of the formatted */
  1476. /* string appends the remaining digits.  The string is then reversed  */
  1477. /* again (putting it back to normal), which results in a readable     */
  1478. /* number:                                                            */
  1479. /*                                                                    */
  1480. /*  2484693813       - Original string                                */
  1481. /*  3183964842       - Reversed                                       */
  1482. /*  318,             - Three chars and comma appended to final string */
  1483. /*  318,396,         - Next three and a comma                         */
  1484. /*  318,396,484,     - Next three and a comma                         */
  1485. /*  318,396,484,2    - Last char(s), three or less, no comma          */
  1486. /*  2,484,693,813    - Reversed back to normal                        */
  1487.  
  1488. CoDel: Procedure
  1489.  
  1490. arg RNum
  1491. rRNum=reverse(RNum)
  1492. FNum=''
  1493. do while length(rRNum)>3
  1494.     parse var rRNum TriDig +3 rRNum
  1495.     FNum=FNum||TriDig||','
  1496. end
  1497. FNum=reverse(FNum||rRNum)
  1498. return FNum
  1499. /******************** End CoDel Procedure *****************************/
  1500.  
  1501. /******************** Begin ColorCheck Procedure **********************/
  1502. /* This procedure simply verifies that the colors read in from the    */
  1503. /* INI file (if present) are valid or not.                            */
  1504.  
  1505. ColorCheck: Procedure
  1506.  
  1507. arg color
  1508. if color='BLACK' then rv=1
  1509. else if color='WHITE' then rv=1
  1510. else if color='RED' then rv=1
  1511. else if color='GREEN' then rv=1
  1512. else if color='BLUE' then rv=1
  1513. else if color='CYAN' then rv=1
  1514. else if color='YELLOW' then rv=1
  1515. else if color='PINK' then rv=1
  1516. else rv=0
  1517. return rv
  1518. /******************** End ColorCheck Procedure ************************/
  1519.  
  1520. /******************** Begin ResCheck Procedure ************************/
  1521. /* Simply checks to see if a resolution given in the INI file is one  */
  1522. /* which we know how to handle.                                       */
  1523.  
  1524. ResCheck: Procedure
  1525.  
  1526. arg res
  1527. if res='640X480' then rv=1
  1528. else if res='800X600' then rv=1
  1529. else if res='1024X768' then rv=1
  1530. else if res='1280X1024' then rv=1
  1531. else if res='1600X1200' then rv=1
  1532. else rv=0
  1533. return rv
  1534. /******************** End ResCheck Procedure **************************/
  1535.