dal@syntel.UUCP (Dale Schumacher) (06/25/89)
This version of 'df' uses the '/etc/mtab' file (as Minix-PC v1.4?) to keep
track of what is mounted, and assumes '/etc/mount' and '/etc/umount' will
update that file properly. In addition, something like the following
should be in your '/etc/rc' file.
echo "/dev/hd3 is mounted on /" > /etc/mtab
chmod 644 /etc/mtab
This allows 'df' to display stats on all mounted devices if it is run with
no parameters, all of which is no surprise to Minix-PC users. What is new
in this version of 'df' is that it radically alters the output format to
start with a single header line (describing the fields) and adds two new
fields. One showing percent of disk blocks used, and the other showing
the mount point for each device. Here is some sample output:
device inodes: used free blocks: used free %use mount point
/dev/hd3 106 222 354 606 36% /
/dev/hd4 2392 5749 14909 9491 61% /usr
/dev/ram 6 35 93 7 93% /rbin
/dev/dd0 37 211 708 12 98% /user
The context diffs were almost as big as the whole source, so I'm posting
the new source directly.
PS. I'll be incommunicado from 6/26 to 6/30, but I'll answer mail as
soon after that as possible.
----------------------------------------------------------------------------
/* df - disk free block printout Author: Andy Tanenbaum */
#include <minix/const.h>
#include <minix/type.h>
#include <fs/const.h>
#include <fs/type.h>
#include <fs/super.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
extern char *itoa();
char *mtab = "/etc/mtab";
main(argc, argv)
int argc;
char *argv[];
{
register int i;
sync(); /* have to make sure disk is up-to-date */
prints(
"device inodes: used free blocks: used free %use mount point\n");
defaults((argc > 1) ? argv[1] : ((char *) 0));
exit(0); /* redundant, defaults() doesn't return */
}
df(name, mountpoint)
char *name, *mountpoint;
{
register int fd;
int i_count, z_count, totblocks, busyblocks, i;
long freepercent;
char buf[BLOCK_SIZE];
struct super_block super, *sp;
struct stat statbuf;
if ( (fd = open(name,0)) < 0) {
perror(name);
return;
}
/* Is it a block special file? */
if (fstat(fd, &statbuf) < 0) {
stderr2(name, ": Cannot stat\n");
return;
}
if ( (statbuf.st_mode & S_IFMT) != S_IFBLK) {
stderr2(name, ": not a block special file\n");
return;
}
lseek(fd, (long)BLOCK_SIZE, 0); /* skip boot block */
if (read(fd, &super, SUPER_SIZE) != SUPER_SIZE) {
stderr2(name, ": Can't read super block\n");
close(fd);
return;
}
lseek(fd, (long) BLOCK_SIZE * 2L, 0); /* skip rest of super block */
sp = &super;
if (sp->s_magic != SUPER_MAGIC) {
stderr2(name, ": Not a valid file system\n");
close(fd);
return;
}
i_count = bit_count(sp->s_imap_blocks, sp->s_ninodes+1, fd);
if (i_count < 0) {
stderr2(name, ": can't find bit maps\n");
close(fd);
return;
}
z_count = bit_count(sp->s_zmap_blocks, sp->s_nzones, fd);
if (z_count < 0) {
stderr2(name, ": can't find bit maps\n");
close(fd);
return;
}
totblocks = sp->s_nzones << sp->s_log_zone_size;
busyblocks = z_count << sp->s_log_zone_size;
/* Print results. */
sfield(name, -14);
sfield(itoa(i_count - 1), 7);
sfield(itoa(sp->s_ninodes + 1 - i_count), 7);
prints(" ");
sfield(itoa(busyblocks), 7);
sfield(itoa(totblocks - busyblocks), 7);
freepercent = ((long) busyblocks) * 100L;
freepercent /= (long) totblocks;
sfield(itoa((int) freepercent), 4);
prints("% ");
prints(mountpoint);
prints("\n");
close(fd);
}
bit_count(blocks, bits, fd)
int blocks;
int bits;
int fd;
{
register int i, b;
int busy, count, w;
int *wptr, *wlim;
int buf[BLOCK_SIZE/sizeof(int)];
/* Loop on blocks, reading one at a time and counting bits. */
busy = 0;
count = 0;
for (i = 0; i < blocks; i++) {
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) return(-1);
wptr = &buf[0];
wlim = &buf[BLOCK_SIZE/sizeof(int)];
/* Loop on the words of a block */
while (wptr != wlim) {
w = *wptr++;
/* Loop on the bits of a word. */
for (b = 0; b < 8*sizeof(int); b++) {
if ( (w>>b) & 1) busy++;
if (++count == bits) return(busy);
}
}
}
return(0);
}
stderr2(s1, s2)
char *s1, *s2;
{
std_err(s1);
std_err(s2);
}
sfield(s, n)
char *s;
int n;
{
char pad[128], *p;
int m, x;
m = strlen(s); /* compute and create padding string */
for(p=pad, x=((n<0)?-n:n); (m < x); ++m)
*p++ = ' ';
*p = '\0';
if(n > 0) /* right justification */
prints(pad);
prints(s);
if(n < 0) /* left justification */
prints(pad);
return(m); /* characters printed */
}
defaults(device)
char *device;
{
/* Use the root file system and all mounted file systems. */
/* If a device is specified, only display that device. */
char mdev[256], *mdir, *getname();
close(0);
if (open(mtab, 0) < 0) {
std_err("df: cannot open ");
std_err(mtab);
std_err("\n");
exit(1);
}
/* Read /etc/mtab and iterate on the lines. */
while (1) {
mdir = getname(mdev); /* getname exits upon hitting EOF */
if(!device || (strcmp(device, mdev) == 0))
df(mdev, mdir);
}
}
char *getname(p)
char *p;
{
int c;
while (1) {
c = getchar();
if (c == EOF)
exit(0);
if (c == ' ')
c = 0;
if (c == '\n') {
*p = '\0';
while(*--p)
;
return(++p);
}
*p++ = (char)c;
}
}
----------------------------------------------------------------------------
--
Dale Schumacher 399 Beacon Ave.
(alias: Dalnefre') St. Paul, MN 55104-3527
...bungia!midgard.mn.org!syntel!dal United States of America
"I may be competitive, but I'm never ruthless"