V10/cmd/du.c

Compare this file to the similar file:
Show the results in this format:

#include "stdio.h"
#include "sys/param.h"
#include "sys/stat.h"
#include "ndir.h"
#include "ftw.h"

enum Params {Maxpathlen=1024, Nlinks=600};
char flags[128];	/* -a, -s */
char buf[Maxpathlen];
unsigned long totlen, dirlen[Maxpathlen];
struct {
	int ino, dev;
} ml[Nlinks];
int nlink, follow, level;
extern int errno;

main(argc, argv)
char **argv;
{	extern char *optarg;
	extern int optind;
	int c;

	while((c = getopt(argc, argv, "as")) != -1)
	switch(c) {
		default:
			fprintf(stderr, "usage: %s [-a] [-s] [files]\n", argv[0]);
			exit(1);
		case 'a': case 's':
			flags[c]++;
			break;
	}
	if(optind >= argc) {
		doit(".");
			if(flags['s'])
				printf("%d\t%s\n", totlen, argv[optind]);
	}
	else
		for(; optind < argc; optind++) {
			follow = 1;
			doit(argv[optind]);
			if(flags['s'])
				printf("%d\t%s\n", totlen, argv[optind]);
			totlen = 0;
		}
	exit(0);
}

fn(name, stb, code, s)
char *name;
struct stat *stb;
struct FTW *s;
{	int n;
	if(follow) {
		follow = 0;
		if(code == FTW_SL) {
			s->quit = FTW_FOLLOW;
			return(0);
		}
	}
	switch(code) {
	case FTW_D:
		dirlen[++level] = 0;
	case FTW_SL:
	case FTW_F:	/* stupid size semantics (BSIZE not networked) */
common:
		if(seenit(stb))
			return(0);
		n = ((stb->st_size + BSIZE(stb->st_dev)-1) >> BSHIFT(stb->st_dev))
			* (BSIZE(stb->st_dev)/1024);
		totlen += n;
		dirlen[level] += n;
		if(flags['a'])
			printf("%d\t%s%s\n", n, name, code==FTW_D? "/": "");
		break;
	case FTW_DP:
		if(!flags['s']) {
			printf("%d\t%s\n", dirlen[level], name);
			fflush(stdout);	/* bogus new stdio */
		}
		dirlen[level-1] += dirlen[level];
		level--;
		break;
	case FTW_DNR:
		perror(name);
		goto common;
	case FTW_NS:
	case FTW_NSL:
		perror(name);
	}
	return(0);
}

doit(s)
char *s;
{
	level = 0;
	ftw(s, fn, 100);
}

seenit(s)
struct stat *s;
{	int i;
	if(s->st_nlink == 1 || (s->st_mode & S_IFMT) != S_IFREG)
		return(0);
	for(i = 0; i < nlink; i++)
		if(ml[i].ino == s->st_ino && ml[i].dev == s->st_dev)
			return(1);
	if(i < Nlinks) {
		ml[i].ino = s->st_ino;
		ml[i].dev = s->st_dev;
		nlink++;
	}
	return(0);
}