Category : C Source Code
Archive   : DU.ZIP
Filename : DU.C

 
Output of file : DU.C contained in archive : DU.ZIP

/*
* du.c:
*
* `Du' is a disk usage utility which computes the diskusage of
* all the files in a directory and it's subdirectories.
*
* This utility is comparable with the UNIX du program.
*
* Usage: du [-s] [-a] [d:path ...]
*
* Option -s (/s) does not show subdirectories (short listing).
* Option -a (/a) shows size of all the files.
*
* Copyright: Tom Vijlbrief, Baarn, The Netherlands
* Date: Fri May 8 13:53:29 GMT+1:00 1987
*
* This program may be distributed freely for non commercial purposes
* and with this Copyright notice unchanged.
*/

/*
* Compilation must be performed with structure packing and larger stack:
* Microsoft C 4.00: -Zp -F2000
*/

#include
#include
#include
#include
#include
#include
#include
#include

#define BLOCK_SIZE 512
#define ALL_FILES (0x1 | 0x2 | 0x4 | 0x10 |0x20)
#define DIRECTORIES (0x10)

#define NAME_LEN 8
#define EXT_LEN 3

#define MAX_CWD 256

typedef unsigned char byte;

typedef struct {
byte FF;
byte zero_5[5];
byte attribute;
byte drive;
char name[NAME_LEN];
char extension[EXT_LEN];
unsigned cur_block;
unsigned rec_size;
unsigned fs_low;
unsigned fs_high;
unsigned date;
byte unused2[10];
byte cur_record;
unsigned ran_low;
unsigned ran_high;
} ext_fcb;

char *get_first(char *, int, ext_fcb *);
char *get_next(ext_fcb *);
long scan();


byte sector[BLOCK_SIZE];

int cluster_size;

int a_flag;
int s_flag;
int in_tree;

ext_fcb return_fcb;

main(argc, argv)

int argc;
char *argv[];
{
char *option_p;
static char cur_cwd[MAX_CWD];
int drive_nr;
int cur_drive;

while (argc > 1) {
option_p= *++argv;

if (*option_p == '-' || *option_p == '/') {
for (option_p++; *option_p; option_p++) {
switch (*option_p) {
case 'a':
a_flag++;
break;
case 's':
s_flag++;
break;
default:
fprintf(stderr,
"Unknown option: %c\n", *option_p);
fprintf(stderr,
"Usage: du [-s] [-a] [d:path ...]\n");
exit(1);
}
}
argc--;
} else
break;
}

if (argc == 1) {
cluster_size= comp_cluster(get_drive());
scan();
} else {
for (; argc > 1; argc--, argv++) {
cur_drive= get_drive();
getcwd(cur_cwd, MAX_CWD - 1);
if ((*argv)[1] == ':')
set_drive(tolower((*argv)[0]) - 'a');
if (chdir(*argv) != 0) {
perror(*argv);
set_drive(cur_drive);
continue;
}
cluster_size= comp_cluster(get_drive());
scan();
set_drive(cur_drive);
if (chdir(cur_cwd) != 0) {
perror(cur_cwd);
exit(1);
}

in_tree= 0;
}
}
}


static struct stat the_stat;
static char cwd[MAX_CWD];

long scan()
{
char *p;
long file_size;
long disk_use;
int tree_flag;
ext_fcb the_fcb;
char pattern[NAME_LEN + EXT_LEN + 2];

tree_flag= in_tree;
disk_use= 0;

strcpy(pattern, "????????.???");

p= get_first(pattern, ALL_FILES, &the_fcb);
for (; p != NULL; p= get_next(&the_fcb)) {
if (strcmp(p, ".. . ") == 0
|| strcmp(p, ". . ") == 0)
continue;

if (stat(p, &the_stat) != 0) {
perror(p);
exit(1);
}

if (the_stat.st_mode & S_IFDIR) {
if (a_flag) {
printf("%s\n", p);
printf("========================\n");
}
chdir(p);
in_tree= 1;
disk_use+= scan();
chdir("..");
} else {
disk_use+= ((file_size= the_stat.st_size) + (cluster_size - 1))
/ cluster_size * cluster_size;
if (a_flag) {
printf("%s: %10ld\n", p, file_size);
}
}
}

if (a_flag)
printf("========================\n");
if (!s_flag || !tree_flag)
printf("Disk Usage : %10ld (%s)\n", disk_use,
getcwd(cwd, MAX_CWD - 1));
if (a_flag)
printf("\n");

return(disk_use);
}


/*
* get_first returns the first_name in a directory matching the
* pattern (e.g. ????????.OBJ) and attribute
*/

char *get_first (pattern, attribute, fcb_p)

char *pattern;
int attribute;
ext_fcb *fcb_p;
{
set_dta(&return_fcb);

strncpy(fcb_p->name, pattern, NAME_LEN);
strncpy(fcb_p->extension, pattern + NAME_LEN + 1, EXT_LEN);
fcb_p->attribute= attribute;
fcb_p->FF= 0xFF;
fcb_p->drive= get_drive() + 1;

if ((bdos(0x11, (int) fcb_p, 0) & 0xFF) == 0) {
strncpy(pattern, return_fcb.name, NAME_LEN);
strncpy(pattern + NAME_LEN + 1, return_fcb.extension, EXT_LEN);
return(pattern);
} else
return(NULL);
}


char *get_next(fcb_p)

ext_fcb *fcb_p;
{
static char pattern[]= "12345678.123";

set_dta(&return_fcb);

if ((bdos(0x12, (int) fcb_p, 0) & 0xFF) == 0) {
strncpy(pattern, return_fcb.name, NAME_LEN);
strncpy(pattern + NAME_LEN + 1, return_fcb.extension, EXT_LEN);
pattern[NAME_LEN + EXT_LEN + 1]= '\0';
return(pattern);
} else {
return(NULL);
}
}


/*
* `set_drive' changes the current drive. (A = 0, etc).
*/
int set_drive(drive_nr)

int drive_nr;
{
return(bdos(0xE, drive_nr, 0) & 0xFF);
}

/*
* `get_drive' returns the number of the current drive. (A = 0, etc).
*/
int get_drive()

{
return(bdos(0x19, 0, 0) & 0xFF);
}



set_dta(p)

ext_fcb *p;
{
return(bdos(0x1A, (int) p, 0) & 0xFF);
}



#define DISK 0x13
#define READ_SECT 0x2
#define RESET_DISK 0x0

#define FLOP_RETRIES 3

int readsect(buffer, drive, head, cyl, sector, n_sectors)

char *buffer;
unsigned int drive;
unsigned int head;
unsigned int cyl;
unsigned int sector;
unsigned int n_sectors;
{
int result;
int retries;
int max_retries;
union REGS inregs,
outregs;
struct SREGS segregs;

segread(&segregs);
segregs.es= segregs.ds;

if (drive < 0x80)
max_retries= FLOP_RETRIES;
else
max_retries= 1;

for (retries= 0; retries < max_retries; retries++) {
if (drive < 0x80) {
inregs.h.ah= RESET_DISK;
inregs.h.dl= drive;
int86(DISK, &inregs, &outregs);
}

inregs.h.ah= READ_SECT;
inregs.x.bx= (unsigned) buffer;
inregs.h.dl= drive;
inregs.h.dh= head;
inregs.h.ch= cyl;
inregs.h.cl= sector | ((cyl & ~0xFF) >> 2);
inregs.h.al= n_sectors;

result= (unsigned) int86x(DISK, &inregs, &outregs, &segregs) >> 8;

if (outregs.x.cflag)
continue;
else
break;
}
if (retries == max_retries)
return(-result);
else
return(0);
}



int comp_cluster(drive_nr)

int drive_nr;
{
int nr_sectors;
int head_nr;
int high_head;
int sector_nr;

if (drive_nr > 1)
drive_nr+= 0x80 - 2;

high_head= max_head(drive_nr);

for (head_nr= 0; head_nr <= high_head; head_nr++) {
for (sector_nr= 1; sector_nr <= 8; sector_nr++) {
if (readsect(sector, drive_nr, head_nr, 0, sector_nr, 1) != 0) {
fprintf(stderr, "Cannot read bootblock from disk\n");
exit(1);
}
if (sector[0] == 0xEB)
break;
}
if (sector[0] == 0xEB)
break;
}
if (sector_nr > 8 || (nr_sectors= sector[13]) > 16) {
nr_sectors= 4;
fprintf(stderr,
"Unknown bootblock, clustersize of 4 sectors assumed\n");
}
if (nr_sectors == 0)
nr_sectors= 2;
return(nr_sectors * BLOCK_SIZE);
}



#define GET_PARAM 0x8

int max_head(drive)

unsigned int drive;
{
union REGS inregs,
outregs;

inregs.h.ah= GET_PARAM;
inregs.h.dl= drive;

int86(DISK, &inregs, &outregs);

if (outregs.x.cflag)
return(0);
else
return(outregs.h.dh);
}