V9/cmd/du.c
#include <stdio.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/dir.h>
#define EQ(x,y) (strcmp(x,y)==0)
#define ML 1000
struct stat Statb;
char path[BUFSIZE], name[BUFSIZE];
int Aflag = 0,
Sflag = 0,
Noarg = 0;
struct {
int dev,
ino;
} ml[ML];
long descend();
char *rindex();
char *strcpy();
main(argc, argv)
char **argv;
{
register i = 1;
long blocks = 0;
register char *np;
if (argc>1) {
if(EQ(argv[i], "-s")) {
++i;
++Sflag;
} else if(EQ(argv[i], "-a")) {
++i;
++Aflag;
}
}
if(i == argc)
++Noarg;
do {
strcpy(path, Noarg? ".": argv[i]);
strcpy(name, path);
if(np = rindex(name, '/')) {
*np++ = '\0';
if(chdir(*name? name: "/") == -1) {
perror(*name? name: "/");
exit(1);
}
} else
np = path;
blocks = descend(path, *np? np: ".", 0);
if(Sflag)
printf("%ld\t%s\n", blocks, path);
} while(++i < argc);
exit(0);
}
long
descend(np, fname, depth)
char *np, *fname;
{
int dir = 0, /* open directory */
offset,
dsize,
entries,
dirsize;
struct direct dentry[BUFSIZE/sizeof(struct direct)];
register struct direct *dp;
register char *c1, *c2;
int i;
char *endofname;
long blocks = 0;
if(lstat(fname,&Statb)<0) {
perror(name);
fprintf(stderr, "--bad status < %s %s >\n", fname, name);
return 0L;
}
if(Statb.st_nlink > 1 && (Statb.st_mode&S_IFMT)!=S_IFDIR) {
static linked = 0;
for(i = 0; i <= linked; ++i) {
if(ml[i].ino==Statb.st_ino && ml[i].dev==Statb.st_dev)
return 0;
}
if (linked < ML) {
ml[linked].dev = Statb.st_dev;
ml[linked].ino = Statb.st_ino;
++linked;
}
}
blocks = ((Statb.st_size+BSIZE(Statb.st_dev)-1)>>BSHIFT(Statb.st_dev)) *
(BSIZE(Statb.st_dev)/BSIZE(0));
if((Statb.st_mode&S_IFMT)!=S_IFDIR) {
if(Aflag)
printf("%ld\t%s\n", blocks, np);
return(blocks);
}
if(Aflag)
printf("%ld\t%s/\n", blocks, np);
for(c1 = np; *c1; ++c1);
if(*(c1-1) == '/')
--c1;
endofname = c1;
dirsize = Statb.st_size;
if(chdir(fname) == -1)
return 0;
for(offset=0; offset < dirsize; offset += BUFSIZE) { /* each block */
dsize = BUFSIZE<(dirsize-offset)? BUFSIZE: (dirsize-offset);
if(!dir) {
if((dir=open(".",0))<0) {
perror(".");
fprintf(stderr, "--cannot open < %s >\n",
np);
goto ret;
}
if(offset) lseek(dir, (long)offset, 0);
if(read(dir, (char *)dentry, dsize)<0) {
perror("read");
fprintf(stderr, "--cannot read < %s >\n",
np);
goto ret;
}
if(dir > 15) {
close(dir);
dir = 0;
}
} else
if(read(dir, (char *)dentry, dsize)<0) {
perror("read");
fprintf(stderr, "--cannot read < %s >\n", np);
goto ret;
}
entries = dsize / sizeof(struct direct);
for(dp=dentry; entries; --entries, ++dp) {
/* each directory entry */
if(dp->d_ino==0 || EQ(dp->d_name, ".") || EQ(dp->d_name, ".."))
continue;
c1 = endofname;
*c1++ = '/';
c2 = dp->d_name;
for(i=0; i<DIRSIZ; ++i)
if(*c2)
*c1++ = *c2++;
else
break;
*c1 = '\0';
if(c1 == endofname) /* ?? */
return 0L;
blocks += descend(np, endofname+1, depth+1);
}
}
*endofname = '\0';
if(!Sflag)
printf("%ld\t%s\n", blocks, np);
ret:
if(dir)
close(dir);
if(chdir("..") == -1) {
*endofname = '\0';
perror("..");
fprintf(stderr, "Bad directory <%s>\n", np);
while(*--endofname != '/');
*endofname = '\0';
if(chdir(np) == -1)
exit(1);
}
return(blocks);
}