Determining the Amount of Free Space on a Volume
You can determine how much space is free on a particular volume by calling the low-level functionPBHGetVInfo
. This function returns, in theioVFrBlk
field of the parameter block passed to it, the number of free allocation blocks on a volume. It also returns, in theioVAlBlkSiz
field, the number of bytes in the allocation blocks on that volume. By multiplying those two values, you can determine how many bytes are free on a particular volume.There is, however, one complication in this process. The
ioVFrBlk
field of the parameter block is actually an unsigned integer and can contain values from 0 to 65,535. However, because Pascal does not support unsigned integers, it interprets the values in theioVFrBlk
field as lying in the range -32,768 to 32,767. (Integers are stored as 16-bit quantities where the high-order bit indicates whether the value is true binary or a negated value in its two's complement positive form.) If, for example, a volume has 40,000 allocation blocks free and your application blindly returned the value in theioVFrBlk
field, it would erroneously report that the volume had -25,536 allocation blocks available.You can circumvent this problem by forcing Pascal to interpret the high-order bit as
part of the number of free blocks. For example, if you install the value returned in theioVFrBlk
field as the low-order word of a long integer, the high-order bit of that
word is no longer the high-order bit of that long integer and hence is not interpreted
as a sign indication. The data typeTwoIntsMakeALong
provides a convenient way
to accomplish this.
TYPE TwoIntsMakeALong = {two integers make a long integer} RECORD CASE Integer OF 1: (long: LongInt); 2: (ints: ARRAY[0..1] OF Integer); END;Listing 2-6 illustrates how to use this technique to determine the amount of free space on a volume (specified by its volume reference number).Listing 2-6 Determining the amount of free space on a volume
FUNCTION GetVolumeFreeSpace (myVol: Integer): LongInt; VAR myHPB: HParamBlockRec; {parameter block for PBHGetVInfo} myErr: OSErr; {result code from PBHGetVInfo} myRec: TwoIntsMakeALong; {easy way to get an unsigned int} BEGIN WITH myHPB DO BEGIN ioNamePtr := NIL; ioVRefNum := myVol; ioVolIndex := 0; END; myErr := PBHGetVInfo(@myHPB, FALSE); IF myErr = noErr THEN BEGIN myRec.ints[0] := 0; myRec.ints[1] := myHPB.ioVFrBlk; GetVolumeFreeSpace := myRec.long * myHPB.ioVAlBlkSiz; END ELSE GetVolumeFreeSpace := 0; END;If the value passed to GetVolumeFreeSpace is a valid volume reference number,
then this function reads the number of free allocation blocks on the volume, installs
that number as the low-order word of a long integer, and performs the necessary multiplication to determine how many bytes are free on the volume.
- Note
- You could avoid these complications with unsigned integers by calling
PBHGetVInfo
as illustrated and then passing the value returned in theioVDrvInfo
field to the high-level functionGetVInfo
. The technique using theTwoIntsMakeALong
data type to convert unsigned integers to long integers is illustrated here because it is useful when reading the fields of many other File Manager data structures from Pascal. For example, thevcbFreeBks
field of a volume control block contains an unsigned integer that you can interpret in this way.