home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
c
/
du.arc
/
DU.C
next >
Wrap
C/C++ Source or Header
|
1987-12-26
|
6KB
|
217 lines
/*
* DU - Disk Usage. A Unix style utility. Written by Peter Lim 07-Dec-87.
*
* Usage: du [-s] [-a] [-z] [-c] [-r] [-h] [-nnnn] [pathname(s) ... ]
* where,
* -s : Summary listing only (Toggle, default=off).
* -a : Generate a list of all files
* (Toggle, default=off).
* -z : Show total statistics (Toggle, default=on).
* -c : Show cluster size (Toggle, default=on).
* -r : Recursive traversal of sub-directories
* (Toggle, default=on).
* -h : Include HIDDEN & SYSTEM files
* (Toggle, default=off).
* -nnnn : Force cluster size to be nnnn bytes.
* nnnn = 0 releases previous forcing.
* Default pathname is the current directory on current drive.
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "msd_dir.h"
#include <dos.h>
#include <strings.h>
#include <ctype.h>
unsigned long traverse_dir();
unsigned long get_cluster_size();
unsigned long get_path_size ();
#define print_size(size, path) printf ("%-11lu%s\n", size, path)
unsigned long bpc; /* number of bytes per cluster */
int filecnt=0, dircnt=0;
int summary=0, show_all=0, show_stat=1,
show_cluster=1, force_cluster=0, recurse=1, incl_hidn=0;
unsigned int att_mask;
main (argc, argv)
int argc;
char **argv;
{
unsigned long total=0;
int path_specified=0;
for (; --argc > 0; ) {
*++argv;
if (**argv == '-')
switch ((*argv)[1]) {
case 's' :
case 'S' :
summary = !summary;
continue;
case 'z' :
case 'Z' :
show_stat = !show_stat;
continue;
case 'a' :
case 'A' :
show_all = !show_all;
continue;
case 'c' :
case 'C' :
show_cluster = !show_cluster;
continue;
case 'r' :
case 'R' :
recurse = !recurse;
continue;
case 'h' :
case 'H' :
incl_hidn = !incl_hidn;
continue;
default :
if (!sscanf (*argv, "-%lu", &bpc))
printf ("Unknown option %s\n", *argv);
else
force_cluster = bpc ? 1 : 0;
continue;
}
path_specified = 1;
/* At this point we know at least one path is specified. */
total += get_path_size(*argv);
}
if (!path_specified)
total = get_path_size(".");
/* If no pathname were specified. */
if (show_stat) {
printf ("Total %d files in %d directories.\n", filecnt, dircnt);
printf ("Total disk space used = %lu bytes (%.2lfk).\n",
total, total / 1024.0);
}
}
unsigned long get_path_size (pathname)
char *pathname;
{
unsigned char drive_id;
unsigned long total;
if (incl_hidn)
att_mask = (A_HIDDEN | A_SYSTEM);
else
att_mask = 0; /* Set attribute mask for files to find.
A_DIR will always be set. */
if (!force_cluster) {
if (isalpha (*pathname) && (pathname[1] == ':'))
drive_id = *pathname - ((islower(*pathname)) ? 'a' : 'A') + 1;
else
drive_id = 0;
if (!(bpc = get_cluster_size(drive_id))) {
printf ("Invalid drive %c\:\n", *pathname);
exit (1);
}
}
if (show_cluster)
printf ("Cluster size = %lu bytes.\n", bpc);
total = traverse_dir(pathname);
if (summary)
print_size (total, pathname);
/* At least say something even if only summary is required. */
return (total);
}
unsigned long traverse_dir(cur_path)
char *cur_path;
{
DIR *dp;
struct direct *direntry;
char s[MAXPATHLEN+1];
char c;
unsigned long total, file_size;
unsigned int dir_ent_cnt; /* Count the number of directory entry. */
#define bpdent (unsigned int) 32
/* Number of bytes per directory entry,
= 32 from DOS 2.10 tech ref pp. 4-5. lim@mullian.oz */
int not_root_dir;
total = 0;
if (!(dp=opendir(cur_path, att_mask))) {
printf ("Can't open directory \"%s\" or memory allocation failure.\n",
cur_path);
exit(2);
}
if (recurse) {
while (direntry=readdir(dp))
if (((*direntry).d_attribute == A_DIR)
&& (strcmp ((*direntry).d_name, "."))
&& (strcmp ((*direntry).d_name, ".."))) {
strcpy (s, cur_path);
if ((c = s[strlen(s)-1]) != '\\' &&
c != '/' && c != ':')
strcat (s, "\\");
strcat (s, (*direntry).d_name);
total += traverse_dir(s);
}
(void) rewinddir(dp);
}
dir_ent_cnt = not_root_dir = 0;
while (direntry=readdir(dp)) {
dir_ent_cnt++;
if ((*direntry).d_attribute != A_DIR) {
total += file_size = ( ((*direntry).d_size / bpc) +
(((*direntry).d_size % bpc) ? 1 : 0) ) * bpc;
if (show_all) {
strcpy (s, cur_path);
if ((c = s[strlen(s)-1]) != '\\' && c != '/')
strcat (s, "\\");
print_size (file_size, strcat (s, (*direntry).d_name));
}
filecnt++; /* Counting all files (exclude dir). */
}
else if (!strcmp ((*direntry).d_name, ".")) {
dircnt++; /* Counting every occurance of ".". */
not_root_dir = 1;
/* Not root directory if "." exist. */
}
}
if (not_root_dir)
total += ( ((dir_ent_cnt * bpdent) / bpc) +
(((dir_ent_cnt * bpdent) % bpc) ? 1 : 0) ) * bpc;
/* Add the number of directory entry counted * bytes per entry rounded
up to the nearest cluster. The only things missed by this method of
counting are the directories with a lot of erased files. Can't be
helped without resorting to very low level FAT probing.
NOTE: The root directory uses zero byte here - complying
with CHKDSK from MS DOS. Another MS DOS quirk. */
if (!summary)
print_size (total, cur_path);
closedir(dp);
return (total);
}
#define DOSI_GDFREE 0x36;
static union REGS reg, nreg;
unsigned long get_cluster_size(drive_id)
unsigned char drive_id;
{
reg.h.ah = DOSI_GDFREE;
reg.h.dl = drive_id;
intdos(®, &nreg);
if (nreg.x.ax == 0xffff)
return ((unsigned long) 0);
else
return ((unsigned long) nreg.x.cx * nreg.x.ax);
}