[net.micro.cpm] Determining free disk space

ded@aplvax.UUCP (12/20/83)

One of these days I'll learn to state my question clearly.  I asked
for a way to determine how much free space is available on a disk
in a CP/M environment.  Several nice people resonded with STAT.COM,
XDIR.COM, etc.  Ah, they were right, but I had meant to ask something 
different.  

I want to determine free disk space from the confines of an application
program -- through a BDOS call, or some other portable method.  So
when my programs are going to write to disk, they can first check
if enough space if available.  One of the major flaws of CP/M is that
when things start to go wrong...you're done for.  I would like to avoid
that if all possible.  I could read every directory entry and determine
through some simple mathematics how much space is available, but I would
prefer something more elegant.
-- 

					Don Davis
					JHU/APL
				...decvax!harpo!seismo!umcp-cs!aplvax!ded
				...rlgvax!cvl!umcp-cs!aplvax!ded

mem@sii.UUCP (Mark Mallett) (12/22/83)

b
In response to the question of how to determine free space under
CP/M: CP/M keeps in memory an allocation bitmap for all LOGGED IN
drives.  The easiest way to determine freespace on a disc is to
make sure the drive is logged in, and then to look at the allocation
bitmap.  This is possible under CP/M 2.2 as you can find out where
this bitmap is kept.

What follows is an Aztec C routine `frespc' which determines the
free space on a given drive (assumed to be logged in).  This routine
is extracted from my program VDIR (a `dired'-like program for CP/M).
Preceding the routine is some definitions from VDIR.H which apply
to the routine.  I hope that this is useful. -mm

----------------------------------------------------------------------
typedef	char		BYTE;
typedef	int		BOOL;
typedef	int		WORD;
typedef	long		LONG;

#define	IND	static		/* For variables with no allocation
				    dependancies (don't have to be
				    on the stack) */


/* CP/M call codes */

#define	_MRICC	1		/* Input console character */
#define	_MROCC	2		/* Output console character */
#define	_MRPTR	3		/* Read paper tape */
#define	_MRPTP	4		/* Write paper tape */
#define	_MRLPT	5		/* Write LPT */
#define	_MRDCIO	6		/* Direct console I/O */
#define	_MRRIO	7		/* Read IO status */
#define	_MRSIO	8		/* Write IO status */
#define	_MRWCS	9		/* Write string to console */
#define	_MRRBC	10		/* Read buffer from console */
#define	_MRRCS	11		/* Read console status */
#define	_MRLFH	12		/* Lift head */
#define	_MRINI	13		/* Init BDOS */
#define	_MRSEL	14		/* Select and login a disk */
#define	_MROPN	15		/* Open a file */
#define	_MRCLS	16		/* Close a file */
#define	_MRSFL	17		/* Search for file */
#define	_MRSNF	18		/* Search for next file */
#define	_MRDEL	19		/* Delete a file */
#define	_MRREA	20		/* Read next record */
#define	_MRWRT	21		/* Write next record */
#define	_MRCRF	22		/* Create file */
#define	_MRREN	23		/* Rename file */
#define	_MRILV	24		/* Interrogate login vector */
#define	_MRIDN	25		/* Get drive number */
#define	_MRDMA	26		/* Set DMA address */
#define	_MRIAL	27		/* Get allocation vector */
#define	_MRWPD	28		/* Write-protect disc */
#define	_MRROV	29		/* Get R/O vector */
#define	_MRSFA	30		/* Set file attributes */
#define	_MRGDP	31		/* Get disc parms */
#define	_MRGUC	32		/* Get/set user code */
#define	_MRRRR	33		/* Read random record */
#define	_MRWRR	34		/* Write random record */
#define	_MRCFS	35		/* Compute file size */
#define	_MRSRR	36		/* Set random record */
#define	_MRWRZ	37		/* Write random record with zero fill */


/* Bios calls */

#define	_CBBOOT	0		/* Cold boot */
#define	_CBWBOOT 1		/* Warm boot */
#define	_CBCNST	2		/* Console status */
#define	_CBCNIN	3		/* Console input */
#define	_CBCNOUT 4		/* Console out */
#define	_CBLIST	5		/* Write to listing */
#define	_CBPUN	6		/* Write to punch */
#define	_CBRDR	7		/* Read from reader */
#define	_CBHOME	8		/* Home the disk */
#define	_CBSEL	9		/* Select disc */
#define	_CBSTRK	10		/* Set track */
#define	_CBSSEC	11		/* Set sector */
#define	_CBSDMA	12		/* Set DMA */
#define	_CBREAD	13		/* Read sector */
#define	_CBWRT	14		/* Write sector */
#define	_CBLSST	15		/* List status */
#define	_CBSTRN	16		/* Sector translate */


/* Structures used */




/* Disk parameter block */

typedef
  struct DPBs
    {
    WORD		DPB_SPT;		/* Sectors per track */
    BYTE		DPB_BSH;		/* Allocation shift factor */
    BYTE		DPB_BLM;		/* Allocation mask */
    BYTE		DPB_EXM;		/* Extent mask */
    WORD		DPB_DSM;		/* Storage mask */
    WORD		DPB_DRM;		/* Directory sizer */
    BYTE		DPB_AL0;
    BYTE		DPB_AL1;
    WORD		DPB_CKS;		/* Directory check vector */
    WORD		DPB_OFF;		/* Number of reserved tracks */
    }
  DPB;


/* Disc parameter header */

typedef
  struct DPHs
    {
    BYTE		*DPH_XLT;		/* Translate table */
    WORD		DPH_SCR[3];		/* Scratch */
    BYTE		*DPH_DIR;		/* Directory scratch */
    DPB			*DPH_DPB;		/* Pointer to DPB */
    BYTE		*DPH_CSV;		/* Checkpoint area */
    BYTE		*DPH_ALV;		/* Allocation area */
    }
  DPH;



/* frespc (drvnum)

	Find free space on drive drvnum

Accepts :

	drvnum		Drive number


Returns

	<value>		Number of K free on the drive.

*/

int frespc (drvnum)

int		drvnum;			/* Drive number */

{
IND	BYTE		*Bptr;		/* Allocation pointer */
IND	DPB		*DPBptr;
IND	DPH		*DPHptr;
IND	int		btotl;		/* Total blocks */
IND	int		blib;		/* Bits left-in-byte */
IND	int		i;		/* Scratch */
IND	WORD		albyte;		/* Allocation byte */

DPHptr = bioshl (_CBSEL, drvnum, 0);
DPBptr = bdoshl (_MRGDP, drvnum);

i = DPBptr -> DPB_DSM+1;		/* Number of blocks */
btotl = 0;				/* Total blocks */
blib = 0;				/* Bits-left-in-byte */
Bptr = DPHptr -> DPH_ALV;		/* Pointer to allocation byte */

while (i--)				/* DO all of them */
    {
    if (blib == 0)
	{
	albyte = *Bptr++;
	blib = 8;
	}

    if ((albyte & 0x80))
	btotl++;
    albyte = albyte << 1;
    blib--;
    }

btotl = DPBptr -> DPB_DSM + 1 - btotl;	/* Blocks left */
btotl = btotl * ((DPBptr -> DPB_BLM +1)/8);

return (btotl);

}

----------------------------------------------------------------------

Mark E. Mallett
decvax!sii!mem

rconn%brl@sri-unix.UUCP (12/29/83)

From:      Rick Conn <rconn@brl>

The DFREE routine in SYSLIB determines free disk space for a CP/M 2.2
system.  It is a simple subroutine in assembly language, and you can get
the source (make sure it is for SYSLIB 2.7) from SIMTEL20 or SIG/M.

Rick