Files
Digital-Research-Source-Code/CONTRIBUTIONS/cpm-handbook/cpmsrc/SPACE.C
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

229 lines
7.2 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#define VN "1.0 02/11/83"
/* SPACE - This utility displays a map showing on the amount of space
(expressed as relative percentages) occupied in each user number
for each logical disk). It also shows the relative amount of space
free. */
#include <LIBRARY.H>
struct _dirpb dir_pb; /* directory management parameter block */
struct _dir *dir_entry; /* pointer to directory entry */
struct _scb scb; /* search control block */
struct _dpb dpb; /* CP/M's disk parameter block */
char file_name[20]; /* formatted for display : un/d:FILENAME.TYP */
short cur_disk; /* current logical disk at start of program
NZ = show map of number of files */
int count; /* used to access the allocation block numbers
in each directory entry */
int user; /* used to access the disk map when calculating */
/* The array below is used to tabulate the results for each
disk drive, and for each user number on the drive.
In addition, two extra "users" have been added for "Free"
and "Used" values.
*/
unsigned disk_map[16][18]; /* Disk A -> P, Users 0 -> 15, Free, Used */
#define USED_COUNT 16 /* "user" number for Used entities */
#define FREE_COUNT 17 /* "user" number for Free entities */
main(argc,argv)
short argc; /* argument count */
char *argv[]; /* argument vector (pointer to an array of chars) */
{
printf("\nSPACE Version %s (Library %s)",VN,LIBVN);
chk_use(argc); /* check usage */
cur_disk = bdos(GETDISK); /* get current default disk */
dm_clr(disk_map); /* reset disk map */
ssetscb(scb,argv[1]); /* special version : set disks,
name, type */
for (scb.scb_disk = 0; /* starting with logical disk A: */
scb.scb_disk < 16; /* until logical disk P: */
scb.scb_disk++) /* move to next logical disk */
{
/* check if current disk has been selected for search */
if (!(scb.scb_adisks & (1 << scb.scb_disk)))
continue; /* no - so bypass this disk */
printf("\nSearching disk : %c",(scb.scb_disk + 'A'));
dir_pb.dp_disk = scb.scb_disk; /* set to disk to be searched*/
/* set the directory to "closed", and force the get_nde
function to open it. */
dir_pb.dp_open = 0;
/* while not at the end of the directory, set a pointer
to the next entry in the directory */
while (dir_entry = get_nde(dir_pb))
{
if (dir_entry -> de_userno == 0xE5)
continue; /* bypass inactive entries */
for (count = 0; /* start with the first alloc. block */
count < dir_pb.dp_nabpde; /* for number of alloc. blks per dir. entry */
count++)
{
if (dir_pb.dp_nabpde == 8) /* assume 8 2-byte numbers */
{
disk_map[scb.scb_disk][dir_entry -> de_userno]
+= (dir_entry -> _dirab.de_long[count] > 0 ? 1 : 0);
}
else /* assume 16 1-byte numbers */
{
disk_map[scb.scb_disk][dir_entry -> de_userno]
+= (dir_entry -> _dirab.de_short[count] > 0 ? 1 : 0);
}
} /* all allocation blocks processed */
} /* end of directory for this disk */
/* Compute the storage used by multiplying the number of
allocation blocks counted by the number of Kbytes in
each allocation block. */
for (user = 0; /* start with user 0 */
user < 16; /* end with user 15 */
user ++) /* move to next user number */
{
/* compute size occupied in Kbytes */
disk_map[scb.scb_disk][user] *= dir_pb.dp_absize;
/* build up sum for this disk */
disk_map[scb.scb_disk][USED_COUNT] += disk_map[scb.scb_disk][user];
}
/* free space = (# of alloc. blks * # of kbyte per blk)
- used Kbytes
- (directory entries * 32) / 1024 ... or divide by 32 */
disk_map[scb.scb_disk][FREE_COUNT] = (dir_pb.dp_nab * dir_pb.dp_absize)
- disk_map[scb.scb_disk][USED_COUNT]
- (dir_pb.dp_nument >> 5); /* same as / 32 */
} /* all disks processed */
printf("\n Numbers show space used in kilobytes.");
printf("\n --- User Numbers --- Space (Kb)");
dm_disp(disk_map,scb.scb_adisks); /* display disk map */
bdos(SETDISK,cur_disk); /* reset to current disk */
}
ssetscb(scb,ldisks) /* special version of - set search control block */
/* This function sets up a search control block according
to just the logical disks specified. The disk are specified as
a single string of characters without any separators. An
asterisk means "all disks". For example -
ABGH (disks A:, B:, G: and H: )
* (all disks for which SELDSK has tables)
It sets the bit map according to which disks should be searched.
For each selected disk, it checks to see if an error is generated
when selecting the disk (i.e. if there are disk tables in the BIOS
for the disk).
The file name, type and extent number are all set to '?' to match
all possible entries in the directory. */
/* Entry Parameters */
struct _scb *scb; /* pointer to search control block */
char *ldisks; /* pointer to the logical disks */
/* Exit Parameters
None.
*/
{
int disk; /* disk number currently being checked */
unsigned adisks; /* bit map for active disks */
adisks = 0; /* assume no disks to search */
if (*ldisks) /* some values specified */
{
if (*ldisks == '*') /* check if "all disks" */
{
adisks = 0xFFFF; /* set all bits */
}
else /* set specific disks */
{
while(*ldisks) /* until end of disks reached */
{
/* build the bit map by getting the next disk
id. (A - P), converting it to a number
in the range 0 - 15, and shifting a 1-bit
left that many places and OR-ing it into
the current active disks.
*/
adisks |= 1 << (toupper(*ldisks) - 'A');
++ldisks; /* move to next character */
}
}
}
else /* use only current default disk */
{
/* set just the bit corresponding to the current disk */
adisks = 1 << bdos(GETDISK);
}
/* set the user number, file name, type and extent to '?'
so that all active directory entries will match */
/* 0123456789012 */
strcpy(&scb -> scb_userno,"?????????????");
/* Make calls to the BIOS SELDSK routine to make sure that
all of the active disk drives indeed do have disk tables
for them in the BIOS. If they don't, turn off the corresponding
bits in the bit map. */
for (disk = 0; /* start with disk A: */
disk < 16; /* until disk P: */
disk++) /* use next disk */
{
if ( !((1 << disk) & adisks) ) /* avoid unnecessary selects */
continue;
if (biosh(SELDSK,disk) == 0) /* make BIOS SELDSK call */
{ /* returns 0 if invalid disk */
/* turn OFF corresponding bit in mask
by ANDing it with bit mask having
all the other bits set = 1. */
adisks &= ((1 << disk) ^ 0xFFFF);
}
}
scb -> scb_adisks = adisks; /* set bit map in scb */
} /* end ssetscb */
chk_use(argc) /* check usage */
/* This function checks that the correct number of
parameters has been specified, outputting instructions
if not. */
/* Entry Parameter */
int argc; /* Count of the number of arguments on the command line */
{
/* The minimum value of argc is 1 (for the program name itself),
so argc is always one greater than the number of parameters
on the command line */
if (argc != 2)
{
printf("\nUsage :");
printf("\n\tSPACE * (All disks)");
printf("\n\tSPACE ABCD..OP (Selected Disks)");
exit();
}
} /* end chk_use */