[comp.sys.ibm.pc] HELP! How to find disk space on joined directories?

pete@octopus.UUCP (Pete Holzmann) (01/06/89)

I ran into an interesting problem today. I wonder if anybody out there
has dealt with it already? Please attempt to email answers since this
is pretty esoteric. I'll summarize the solution to the net (if one is found!)

I have a program that wants to test for remaining space in a temp hard
disk area before creating some mongo files. The normal disk-space DOS
(and MS/Turbo C) routines return remaining space on the current *drive*,
but not for the current *directory*. This is not important in pre-JOIN
days, but now things can get messed up:

	C: has 8 MB free
	C:\foo (current directory, where the user wants to put their stuff)
		has 2 MB free (drive D: is JOINed to C:\foo)

    The DOS call tells me I have 8 MB to play with. I try to use it and get
    blown away 'cuz really there are only 2!

Anybody know how to resolve this? I can't even find anything that shows
me if/how the current directory relates to JOINed disk drives!

Thanks!

Pete
-- 
  OOO   __| ___      Peter Holzmann, Octopus Enterprises
 OOOOOOO___/ _______ USPS: 19611 La Mar Court, Cupertino, CA 95014
  OOOOO \___/        UUCP: {hpda,pyramid}!octopus!pete
___| \_____          Phone: 408/996-7746

nelson@sun.soe.clarkson.edu (Russ Nelson) (01/07/89)

In article <467@octopus.UUCP> pete@octopus.UUCP (Pete Holzmann) writes:

   I have a program that wants to test for remaining space in a temp hard
   disk area before creating some mongo files. The normal disk-space DOS
   (and MS/Turbo C) routines return remaining space on the current *drive*,
   but not for the current *directory*.

   Anybody know how to resolve this? I can't even find anything that shows
   me if/how the current directory relates to JOINed disk drives!

Seek and ye shall find!  I just finished writing a program that works like
Unix's df(1).  It searches through the drive tables to see which are join'ed
and which are subst'ed, and gets the correct free space.  Df will compile
under TC 1.0, TC 1.5, and TC 2.0.   I imagine that it will not be difficult
to port to MSC.

Since it's short and illustrates a solution to the problem of disk space for
join'ed and subst'ed drives as well as identifying those drives, I'll include
it right here:

/* df - dump filesystems.
 *
 * Copyright 1988 By Russell Nelson.  Don't try to make money off of it, and
 * don't pretend that you wrote it.
 *
 * Compile with: tcc -mc df.c
 *
 * usage: df [drive letters]
 * (The default drives to dump are all existing drives, unless an
 * environment variable called 'df' exists, in which case only the drives
 * specified by the variable are dumped.  For example, I use "DF=acd" because
 * I have two hard disks.
 * 
 * Compu$erve: 70441,205
 * GEnie: BH01
 * Internet: nelson@clutx.clarkson.edu
 * BITNET: NELSON@CLUTX
 * Fido/Opus:  Russ Nelson@1:260/360
 */

#include <stdio.h>
#include <dos.h>
#include <dir.h>
#include <string.h>
#include <alloc.h>
#include <ctype.h>
#include <stdlib.h>

#define DOS3	1		/* this program requires DOS 3 */


/* the following is undocumented */
struct drive_info {
	char current_path[64+2+1];
	int flags;			/* flags: */
#define SUBST	0x1000
#define JOIN	0x2000
#define PHYS	0x4000
	char far *disk_block;
	int current_track;		/* ??? Current track or block? -1 if never accessed. */
	char far *bar;			/* ??? I see -1 always */
	unsigned baz;			/* ??? I see 2 always */
};

/* the following is undocumented */
struct list_of_lists {
	unsigned first_mcb;
	char far *first_disk_block;
	char far *first_dos_file;
	char far *clock_driver;
	char far *con_driver;
#ifdef DOS2
	char drive_count;	/* Number of logical drives in system */
	unsigned bytes_per_block;	/* Maximum bytes/block of any block device */
	unsigned foo,bar;		/* ??? */
#endif
#ifdef DOS3
	unsigned bytes_per_block;	/* Maximum bytes/block of any block device */
	char far *first_disk_buffer;	/* Pointer to first disk buffer */
	struct drive_info far *first_drive;	/* Pointer to array of drive info: */
	char far *fcb_table;		/* Pointer to FCB table (if CONFIG.SYS contains FCBS=) */
	unsigned fcb_size;		/* Size of FCB table */
	unsigned char block_devices;	/* Number of block devices */
	unsigned char lastdrive;	/* Value of LASTDRIVE command in CONFIG.SYS (default 5) */
#endif
/* NUL device driver appears here */
} *list_ptr;

/* find a volume label.  Search in subdirectory if the disk is mounted there. */
char *volume_name(int i, char *mounted)
{
	struct ffblk ffblk;
	char root[64];

	if (*mounted) sprintf(root, "%s\\*.*", mounted);
	else sprintf(root, "%c:\\*.*", 'A' + i);
	if (!findfirst(root, &ffblk, FA_LABEL)) {
		char *dot = strchr(ffblk.ff_name, '.');
		if (dot) strcpy(dot, dot+1);
		return ffblk.ff_name;
	}
	else return("");
}

/* given a list of drives, enable those drives */
set_drives(char *drives, char *specifier)
{
	char *drive_ptr;

	for (drive_ptr = specifier; *drive_ptr; ) {
		if (drive_ptr[1] == '-' &&
		    tolower(drive_ptr[2]) >= tolower(drive_ptr[0])) {
			memset(&drives[tolower(drive_ptr[0]) - 'a'], 1, tolower(drive_ptr[2]) - tolower(drive_ptr[0]) + 1);
			drive_ptr+=3;
		} else if (isalpha(*drive_ptr)) {
			drives[tolower(*drive_ptr) - 'a'] = 1;
			drive_ptr++;
		} else drive_ptr++;
	}
}


main(int argc, char *argv[])
{
	int i;
	char *dskbuf;
	char drives[64], *drive_ptr;

	/* enable only the drives that we want */
	memset(drives, 0, sizeof(drives));
	if (argc == 1 && (drive_ptr = getenv("DF")) != NULL)
		set_drives(drives, drive_ptr);
	else if (argc == 1)
		memset(drives, 1, sizeof(drives));
	else set_drives(drives, argv[1]);

	/* get MS-LOSS's list of lists (undocumented) */
	_AH = 0x52;
	geninterrupt(0x21);
	list_ptr = MK_FP(_ES, _BX - 2);

	/* ensure that we have a buffer that's big enough for any drive. */
	dskbuf = malloc(list_ptr->bytes_per_block);

	printf(	"      block   total  kbytes  kbytes  percent\n"
		"disk   size  kbytes    used    free    used     volume       mount\n");
	for (i = 0; i < list_ptr->lastdrive; i++) if (drives[i]) {
		struct drive_info *drive_ptr = &(list_ptr->first_drive[i]);
		struct dfree dtable;
		unsigned int block_size, percent;
		unsigned long total, used, free;
		char *mount_point;

		printf("  %c:", 'A' + i);
		if (drive_ptr->flags & SUBST) {
			printf("  Subsituting for %s\n", drive_ptr->current_path);
		} else if (absread(i, 1, 0, dskbuf) < 0) {
			printf("  %40s[Not Ready]\n", "");
		} else {
			getdfree(i+1, &dtable);
			mount_point = drive_ptr->flags & JOIN?drive_ptr->current_path:"";
			block_size = dtable.df_bsec * dtable.df_sclus;
			total = (long)dtable.df_total * (long)block_size;
			used = ((long)dtable.df_total - (long)dtable.df_avail) * (long)block_size;
			free = (long)dtable.df_avail * (long)block_size;
			percent = (long)(dtable.df_total - dtable.df_avail) * 100L / (long)dtable.df_total;
			printf("%6u %7lu %7lu %7lu %6u%%    %-12s %s\n",
				block_size,
				total / 1024L,
				used / 1024L,
				free / 1024L,
				percent,
				volume_name(i, mount_point),
				mount_point);
		}
	}
}
--
--russ (nelson@clutx [.bitnet | .clarkson.edu])
"I saved the whales!" - Rebecca L. Nelson, 3.5 years old, on receiving her
Christmas present of a whale "adoption" certificate.  Bless her liberal heart.