'===========================================================================
' Subject: DIRECTORY SIZE II                  Date: 10-18-00 (11:29)       
'  Author: Randall L. Glass                   Code: PB                     
'  Origin: rlglass@yahoo.com                Packet: DOS.ABC
'===========================================================================
'----------------------------------------------------------------------------
'                                 DirSize II
'                             By Randall L Glass
'                               CopyRight 2000
'
'----------------------------------------------------------------------------
'
' This program is freeware. You may use it anyway you want as long as you
' give me credit in your program or documentation.
'
'----------------------------------------------------------------------------
'
' I was using this program to get rid of junk files on my hard drive.
' So I made a few improvements. Now the program shows the largest directories
' first. And a argument to show directories alphabeticaly.
' Also it shows the total size of files in the present directory.
'
'----------------------------------------------------------------------------
' This Program looks a directory and subdirectories and adds up the file
' sizes to give you the total amount of space that the directories in that
' directory that up.
'
' This is useful for finding junkfiles and wasted space on your hard drive.
' So you can delete the junk files and compress the files that waste a lot
' of disk space.
'
'--------------------------------------------------------------------------

$CPU 8086                 ' program works on any CPU
$COMPILE EXE              ' compile to an EXE

$ERROR ALL OFF            ' turn off error handling

$STACK  16384             ' use a 16k stack

$OPTION CNTLBREAK OFF     ' don't allow Ctrl-Break to exit program

DEFINT A-Z                ' default all variables to integers for maximum
                          ' speed and minimum size
DECLARE FUNCTION GetStrLoc(BYVAL AllocHandle%) AS LONG
DIM Directories$(1000)
SHARED TotalTreeSize&&, TotalFiles%, TotalDirectories%,Directories%,FileNumber%
SHARED SubDirTreeSize&&, SubFileNumber%, DirFileNumber%, SubDirectories%
SHARED AllocSubDirTreeSize&&,ClusterSize&&,Numberlines%,AllocatedTreeSize&&
SHARED Directories$()
Drive$ = LEFT$(CURDIR$, 1)                       'get the default drive

Cmd$ = COMMAND$
Arguments$ = TRIM$(UCASE$(Cmd$))

IF INSTR(Arguments$,"/?") OR INSTR(Arguments$,"/H") THEN
  PRINT
  PRINT "Usage: DirSize [Directory]  [/?,H] [/A]"
  PRINT "Finds total size of directories"
  PRINT
  PRINT "[Directory] shows size of directories in directory"
  PRINT "Default is root directory"
  PRINT
  PRINT "/A Show directories alphabetically"
  PRINT "Default is by size"
  PRINT
  PRINT  "/? OR /H shows help section"
  END 1
END IF

SortSize% = 1

IF INSTR(Arguments$,"/A") THEN
	SortSize% = 0
	Arguments$ = EXTRACT$(Arguments$,"/A")
END IF

REPLACE "/" WITH "\" IN TempDir$
Directory$ = Arguments$

FileSpec$  = "*.*"
TempDir$ = ENVIRON$("TEMP")+"\"
REPLACE "\\" WITH "\" IN TempDir$

DiskInfo Drive$,DiskSize&&,Diskfree&&,ClusterSize&&
PRINT
PRINT "Disk Waste Finder"
PRINT "By Randall Glass"
PRINT "Getting Total Size of Directories"
PRINT "Checking Directories for files \";

DirectorySize&& = DirSize&&(Directory$, FileSpec$)

OPEN TempDir$ + "Dskspace.use" FOR OUTPUT AS #1

'A$ = "SORT <" + TempDir$ + "Temp99.use>" + TempDir$ + "Dskspace.use"
'SHELL "SORT <" + TempDir$ + "Temp99.use>" + TempDir$ + "Dskspace.use"

IF SortSize% THEN
	ARRAY SORT Directories$(1) FOR Directories%+1,FROM 65 TO 76,DESCEND
ELSE
	ARRAY SORT Directories$(1) FOR Directories%+1
END IF


FOR ZZZ% = 1 TO Directories%
	IF (ZZZ% -1) MOD 19 = 0 THEN
		PRINT #1, STRING$(78,"-")
	        PRINT #1, "Directory  Number Files    AveragSize   % Wasted      Bytes   Allocated Bytes"
	        PRINT #1, STRING$(78,"-")
	END IF
	a$ = MID$(Directories$(zzz%),65)
	Alen% = LEN(Directories$(zzz%))
	PRINT #1,Directories$(zzz%)
NEXT ZZZ%

'OPEN TempDir$ + "Dskspace.use" FOR APPEND AS #1
Numberlines% = 22 - (Numberlilnes% MOD 22)
PRINT #1, STRING$(78,"-")
PRINT #1, LTRIM$(USING$("###,###,###",Directories%)); " Directories"
PRINT #1, STRING$(78,"-")
PRINT #1, "Total Directories% = "; LTRIM$(USING$("###,###,###",TotalDirectories%)); ": ";
PRINT #1, "Total Files = "; LTRIM$(USING$("###,###,###",TotalFiles%))
PRINT #1, "Total Size of Directory And SubDirectories = "; FormatSize$(TotalTreeSize&&)
PRINT #1, "Total Allocated Size of Directory And SubDirectories = "; FormatSize$(DiskSize&& -Diskfree&&)
Wasted&& = INT(.5 + 100 * (AllocatedTreeSize&& -TotalTreeSize&&)/TotalTreeSize&&)
PRINT #1,
PRINT #1, "Disk Size = "; FormatSize$(DiskSize&&)
PRINT #1, "Free Disk Space = "; FormatSize$(Diskfree&&)
PRINT #1, "Wasted Directory Space = "; LTRIM$(USING$("###%",Wasted&&))
PRINT #1, "Disk Cluster Size = "; LTRIM$(USING$("###,###,###",ClusterSize&&))

FOR I% = 1 TO NumberLines% -10
	PRINT #1,
NEXT I%
CLOSE
PRINT
A$ = "EDIT.COM " + TempDir$ + "Dskspace.use"
SHELL "EDIT.COM " + TempDir$ + "Dskspace.use"
END

FUNCTION DirSize&&(StartPath$, FileSpec$) PUBLIC
  DIM SPIN$(3)
  SPIN$(0) = "-"
  SPIN$(1) = "\"
  SPIN$(2) = "|"
  SPIN$(3) = "/"

  DriveNo% = ASCII(UCASE$(StartPath$))
  IF DriveNo% > 63 AND DriveNo% < 91 AND RIGHT$(StartPath$,1) = ":" THEN StartPath$ = StartPath$ + "."

  StartPath$ = TrueName$(StartPath$)

  StartPath$ = StartPath$ + "\"

  REPLACE "\\" WITH "\" IN StartPath$

  FileName$ = DIR$(StartPath$ + FileSpec$, 55)

  WHILE LEN(FileName$) > 0
      AllocatedFileSize??? = 0
      DirInfo DirAttrib?,FileSize???
      IF Bit(DirAttrib?,4) AND FileName$ <> "." AND FileName$ <> ".." THEN
		SubFileNumber% = 0
		SubDirectories% = 0
		SubDirTreeSize&& = 0
		AllocatedSubDirSize&& = 0
		AllocSubDirTreeSize&& = 0
		SubDirectorySize&& = SubDirSize&&(StartPath$ + FileName$ + "\", FileSpec$)
		TotalTreeSize&& = TotalTreeSize&& + SubDirectorySize&&
		AllocatedTreeSize&& = AllocatedTreeSize&& + AllocSubDirTreeSize&&
		TotalFiles% = TotalFiles% + SubFileNumber%
                TotalDirectories% = TotalDirectories% + SubDirectories% + 1
                INCR Directories%
                INCR Numberlines%
                INCR Spin3%
                Spin2% = Spin3% MOD 4
                'PRINT Spin3%
                QPRINT SPIN$(Spin2%)
		Directories$(Directories%) = USING$("\        \",FileName$) + _
                "  " + USING$("###,###",SubFileNumber%) + "  "
                IF SubFileNumber% > 0 THEN
                	AverageFileSize&& = SubDirectorySize&&\SubFileNumber%
                	Directories$(Directories%) = Directories$(Directories%) + USING$("###,###,###,###",AverageFileSize&&)
                ELSE
			Directories$(Directories%) = Directories$(Directories%) + " Not Applicable"
                END IF
		Directories$(Directories%) = Directories$(Directories%) + _
                USING$("      ###%",INT(.5 + 100 *(AllocSubDirTreeSize&& -SubDirectorySize&&)/AllocSubDirTreeSize&&)) + _
                USING$("###,###,###,###",SubDirectorySize&&) + _
                USING$("###,###,###,###",AllocSubDirTreeSize&&)

      ELSEIF ISFALSE Bit(DirAttrib?,3) THEN
                ClusterNumber??? = FileSize???\ClusterSize&&
      		ModSize??? = FileSize??? MOD ClusterSize&&
		IF ModSize??? <> 0 THEN
      			AllocatedFileSize??? = (ClusterNumber??? + 1) * ClusterSize&&
                ELSE
			AllocatedFileSize??? = FileSize???
      		END IF
                'IF FileSize??? = 0 THEN AllocatedFileSize??? = ClusterNumber???
		INCR FileNumber%
                INCR DirFileNumber%
		DirectorySize&& = DirectorySize&& + FileSize???
		AllocatedDirSize&& = AllocatedDirSize&& + AllocatedFileSize???
      END IF

      IF INKEY$ = CHR$(27) THEN END  'is escape is pressed
      FileName$ = DIR$
  WEND

DirSize&& = DirectorySize&&
TotalTreeSize&& = TotalTreeSize&& + DirectorySize&&
AllocatedTreeSize&& = AllocatedTreeSize&& + AllocatedDirSize&&
TotalFiles% = TotalFiles% + FileNumber%

INCR Directories%
DirName$ = "."
Directories$(Directories%) = USING$("\        \",DirName$) + _
  "  " + USING$("###,###",DirFileNumber%) + "  "
IF SubFileNumber% > 0 THEN
	AverageFileSize&& = DirectorySize&&\DirFileNumber%
	Directories$(Directories%) = Directories$(Directories%) + USING$("###,###,###,###",AverageFileSize&&)
ELSE
	Directories$(Directories%) = Directories$(Directories%) + " Not Applicable"
END IF
Directories$(Directories%) = Directories$(Directories%) + _
  USING$("      ###%",INT(.5 + 100 *(AllocatedDirSize&& -DirectorySize&&)/AllocatedDirSize&&)) + _
  USING$("###,###,###,###",DirectorySize&&) + _
  USING$("###,###,###,###",AllocatedDirSize&&)



END FUNCTION

FUNCTION SubDirSize&&(Path$, FileSpec$) PUBLIC

  GetDta DtaSeg??,DtaOfs??
  DEF SEG = DtaSeg??
    SubOldDtaBuffer$ = PEEK$(DtaOfs??, 44)    'save current DTA information
  DEF SEG

  FileName$ = DIR$(Path$ + FileSpec$, 55)

  WHILE LEN(FileName$) > 0
      DirInfo DirAttrib?,FileSize???
      IF Bit(DirAttrib?,4) AND FileName$ <> "." AND FileName$ <> ".." THEN
		AllocDirSize&& = 0
		SubDirSize&& Path$ + FileName$ + "\", FileSpec$
		INCR SubDirectories%
      ELSEIF ISFALSE Bit(DirAttrib?,3) THEN
                ClusterNumber??? = FileSize???\ClusterSize&&
      		ModSize??? = FileSize??? MOD ClusterSize&&
		IF ModSize??? <> 0 THEN
      			AllocatedFileSize??? = (ClusterNumber??? + 1) * ClusterSize&&
                ELSE
			AllocatedFileSize??? = FileSize???
      		END IF

                'IF FileSize??? = 0 THEN AllocatedFileSize??? = ClusterNumber???
		INCR SubFileNumber%
		DirectorySize&& = DirectorySize&& + FileSize???
		AllocatedDirSize&& = AllocatedDirSize&& + AllocatedFileSize???
      END IF

      IF INKEY$ = CHR$(27) THEN END  'escape is pressed
      FileName$ = DIR$
  WEND

  DEF SEG = DtaSeg??
    POKE$ DtaOfs??, SubOldDtaBuffer$   'restore saved DTA information
  DEF SEG

  SubDirTreeSize&& =  SubDirTreeSize&& + DirectorySize&&
  AllocSubDirTreeSize&& = AllocSubDirTreeSize&& + AllocatedDirSize&&
  SubDirSize&& = SubDirTreeSize&&

END FUNCTION

'===========================================================================
' Subject: PB DISKINFO V2.5                  Date: 06-21-98 (05:12)
'  Author: Marc van den Dikkenberg           Code: PB
'  Origin: excel@xs4all.nl                 Packet: DISK.ABC
'===========================================================================
DEFINT A-Z

SUB DiskInfo(drive$,DiskSize&&,Diskfree&&,ClusterSize&&) PUBLIC
   Dim Drivename AS String * 4
   Dim Filesysname AS String * 8

   LOCAL Rax??, Rbx??, Rcx??, Rdx??

   Drive$ = ucase$(left$(drive$,1))
   Drivename$ = left$(drive$,1) +":\"+CHR$(0)
   DiskSize&& = 0
   Diskfree&& = 0

   Seg1?? = varseg(drivename)
   Off1?? = varptr(drivename)
   Seg2?? = varseg(filesysname)
   Off2?? = varptr(filesysname)

	! MOV AX,&H71A0
        ! MOV DS,Seg1??
        ! MOV DX,Off1??
        ! MOV ES,Seg2??
        ! MOV DI,Off2??
	! MOV CX,&HFF
	! INT &H21
        ! MOV Rax??,AX
        ! MOV Rbx??,BX

        if Rax?? = &H7100 then
	   ' FAT32 not supported -- Using FAT16 Method instead.
           Driv% = asc(left$(drive$,1))-64
	   ! PUSH DS
	   ! MOV AX,&H3600
	   ! MOV DX,driv%    ; Disk-#  01=A:, 02=B:, etc.
	   ! XOR CX,CX
	   ! XOR BX,DX
	   ! INT &H21
           ! MOV Rax??,ax
           ! MOV Rbx??,bx
           ! MOV Rcx??,cx
           ! MOV Rdx??,dx
	   ! POP DS
           IF Rax?? <> &H0FFFF THEN
              DiskSize&& = Rax?? * Rcx?? * Rdx??
              Diskfree&& = Rax?? * Rbx?? * Rcx??
              ClusterSize&& = Rax?? * Rcx??
           ELSE
               'Disk not found
               Diskfree&& = -1
               Drive$ = chr$(255)
               END IF
        ELSE
	   Dim buffer as String*44
                Seg1?? = varseg(buffer)
                Off1?? = varptr(buffer)
                Seg2?? = varseg(drivename)
                Off2?? = varptr(drivename)

		! PUSH DS
		! MOV AX,&H7303
                ! MOV ds,Seg2??
                ! MOV dx,Off2??
                ! MOV es,Seg1??
                ! MOV di,Off1??
		! MOV CX,128
		! INT &H21
		! POP DS

		if cvwrd(left$(buffer,2))<>0 then
                        ' FAT32
			DiskSize&& = CVDWD(mid$(buffer,9,4)) * CVDWD(mid$(buffer,5,4)) * CVDWD(mid$(buffer,17,4))
                        Diskfree&& = CVDWD(mid$(buffer,9,4)) * CVDWD(mid$(buffer,5,4)) * CVDWD(mid$(buffer,13,4))
                        ClusterSize&& = CVDWD(mid$(buffer,9,4)) * CVDWD(mid$(buffer,5,4))
                else
                        ' Disk not found
                        drive$ = chr$(255)
                        Diskfree&& = -1
		end if
	end if
END SUB

SUB DirInfo(DirAttrib?,DirectorySize???) PUBLIC
  LOCAL DirDate??,DirTime??,DirAttr?,Dsize???
  ! mov  AX, &H2F00              ; function 2Fh, get DTA location
  ! int  &H21                    ; call DOS
  ! MOV  AX,ES:[BX +26]
  ! MOV  DSize???[0],AX
  ! MOV  AX,ES:[BX +28]
  ! MOV  DSize???[2],AX
  ! MOV  AL,ES:[BX +21]
  ! MOV  DirAttr?,AL
  DirectorySize??? = DSize???
  DirAttrib? = DirAttr?
END SUB

SUB GetDTA(DtaSeg??, DtaOfs??) PUBLIC
  ! push DS
  ! mov  AX, &H2F00              ; function 2Fh, get DTA location
  ! int  &H21                    ; call DOS
  ! lds  SI, DtaSeg??            ; point DS:SI at DtaSeg
  ! mov  DS:[SI], ES             ; put segment of DTA in variable
  ! lds  SI, DtaOfs??            ; point DS:SI at DtaOfs
  ! mov  DS:[SI], BX             ; put offset of DTA in variable
  ! pop  DS
END SUB

FUNCTION FormatSize$(Bytes&&)
IF Bytes&& > 3999999 THEN
        FormatSize$ = LTRIM$(USING$("###,###,###.##",Bytes&&/1000000))+" Megabytes"
ELSEIF Bytes&& > 999999 THEN
        FormatSize$ = LTRIM$(USING$("###,###,###,###,###.##",Bytes&&/1000))+" Kilobytes"
ELSE
        FormatSize$ = LTRIM$(USING$("###,###,###,###,###",Bytes&&))+" Bytes"
END IF
END FUNCTION

FUNCTION TrueName$(Directory$)
REPLACE "\\" WITH "\" IN Directory$
REPLACE "//" WITH "/" IN Directory$
DIM Canonicalized AS STRING * 128
DirName$ = TRIM$(Directory$) + CHR$(0)
DirNamePtr??? = STRPTR32(DirName$)
CanonicalizedPtr??? = VARPTR32(Canonicalized$)
DosError?? = 0

!PUSH DS
!LDS SI,DirNamePtr???
!LES DI,CanonicalizedPtr???
!MOV AH,&H60
!INT &H21
!POP DS

!JNC NoError
!MOV DosError??,AX
NoError:
IF LEFT$(Canonicalized$,2) = "\\" THEN
        Drive$ = MID$(Canonicalized$,3,1)+":"
        Path$ = EXTRACT$(MID$(Canonicalized$,8),CHR$(0))
        IF Path$ = "" THEN Path$ = "\"
	FUNCTION = EXTRACT$(Drive$ +Path$,CHR$(0))
ELSE
FUNCTION = EXTRACT$(Canonicalized$,CHR$(0))
END IF
END FUNCTION

SUB QPRINT(Txt$) PUBLIC
 ! LES     BX,Txt$
 ! MOV     AX,ES:[BX]
 ! PUSH    AX
 ! CALL    GetStrLoc
 ! JCXZ    Quit
 ! MOV     ES, DX
 ! MOV     SI, AX
 ! MOV     AH,&H0E
 ! MOV     BH,PbvScrnVpage
 ! MOV     BL,7
 Printit:
 ! MOV     AL,ES:[SI]
 ! INT     &H10
 ! INC     SI
 ! LOOP    Printit
Quit:
END SUB
