Article 12636 of comp.os.linux:
Path: samba!concert!rutgers!sun-barr!olivea!uunet!world!jrs
From: jrs@world.std.com (Rick Sladkey)
Newsgroups: comp.os.linux
Subject: finally, true disk usage (was: disk defragmentor)
Message-ID: <JRS.92Oct7230625@lepton.world.std.com>
Date: 8 Oct 92 03:06:25 GMT
References: <1992Oct7.042114.11444@monu6.cc.monash.edu.au>
	<1992Oct7.211109.15029@bernina.ethz.ch>
Sender: jrs@world.std.com (Rick Sladkey)
Organization: The Internet
Lines: 58
In-Reply-To: almesber@nessie.cs.id.ethz.ch's message of Wed, 7 Oct 1992 21:11:09 GMT

Werner's frag.c program gave me an idea.  Since du only reports sizes
calculated from the file size, there is no way to find out how many
true blocks a file uses short of deleting the file and watching df.
Here is a variation on his program that counts true block usage, less
indirect blocks.
-----
/* blocks.c - true block usage counter for linux - rick sladkey */

/* based on the program frag.c by Werner Almesberger */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

#define FIBMAP 1

int main(int argc,char **argv)
{
	int i, j, block, blocks, fd;
	struct stat st;

	if (argc == 1) {
		fprintf(stderr,"usage: %s filename ...\n", argv[0]);
		exit(1);
	}
	for (j = 1; j < argc; j++) {
		if ((fd = open(argv[j],O_RDONLY)) < 0) {
			perror(argv[j]);
			exit(1);
		}
		if (fstat(fd,&st) < 0) {
			perror(argv[j]);
			exit(1);
		}
		if (!S_ISREG(st.st_mode)) {
			fprintf(stderr, "%s: not a regular file\n", argv[j]);
			close(fd);
			continue;
		}
		blocks = 0;
		for (i = 0; i < ((st.st_size + 1023) >> 10); i++) {
			block = i;
			if (ioctl(fd, FIBMAP, &block) < 0) {
				perror(argv[1]);
				exit(1);
			}
			if (block)
				blocks++;
		}
		printf("%d\t%s\n", blocks, argv[j]);
		close(fd);
	}
	exit(0);
}
--
Rick Sladkey
jrs@world.std.com


