#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 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 */