217 lines
4.7 KiB
C
217 lines
4.7 KiB
C
/* df - disk free block printout Author: Andy Tanenbaum */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <limits.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
#include <minix/config.h>
|
|
#include <minix/const.h>
|
|
#include <minix/type.h>
|
|
#include "../fs/const.h"
|
|
#include "../fs/type.h"
|
|
#include "../fs/super.h"
|
|
|
|
#define block_nr long /* Allow big devices even if FS doesn't */
|
|
|
|
extern int errno;
|
|
long bit_count();
|
|
char *mtab = "/etc/mtab";
|
|
|
|
#define REPORT 0
|
|
#define SILENT 1
|
|
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
register int i;
|
|
|
|
sync(); /* have to make sure disk is up-to-date */
|
|
fprintf(stdout, "\nDevice Inodes Inodes Inodes Blocks Blocks Blocks ");
|
|
if (argc == 1)
|
|
fprintf(stdout, "Mounted on\n");
|
|
else
|
|
fprintf(stdout, "\n");
|
|
|
|
fprintf(stdout, " total used free total used free\n");
|
|
fprintf(stdout, " ----- ----- ----- ----- ----- -----\n");
|
|
|
|
if (argc == 1) defaults();
|
|
|
|
for (i = 1; i < argc; i++) df(argv[i], "", SILENT);
|
|
exit(0);
|
|
}
|
|
|
|
|
|
#define percent(num, tot) ((int) ((100L * (num) + ((tot) - 1)) / (tot)))
|
|
|
|
df(name, mnton, silent)
|
|
char *name, *mnton;
|
|
int silent;
|
|
{
|
|
register int fd;
|
|
ino_t i_count;
|
|
long z_count;
|
|
block_nr totblocks, busyblocks;
|
|
int i, j;
|
|
char buf[BLOCK_SIZE], *s0;
|
|
struct super_block super, *sp;
|
|
|
|
if ((fd = open(name, O_RDONLY)) < 0) {
|
|
if (!silent) {
|
|
int e = errno;
|
|
|
|
fprintf(stderr, "df: ");
|
|
errno = e;
|
|
perror(name);
|
|
}
|
|
return;
|
|
}
|
|
lseek(fd, (long) BLOCK_SIZE, SEEK_SET); /* skip boot block */
|
|
if (read(fd, (char *) &super, SUPER_SIZE) != (int) SUPER_SIZE) {
|
|
fprintf(stderr, "df: Can't read super block of %s\n", name);
|
|
close(fd);
|
|
return;
|
|
}
|
|
lseek(fd, (long) BLOCK_SIZE * 2L, SEEK_SET); /* skip rest of super block */
|
|
sp = &super;
|
|
if (sp->s_magic != SUPER_MAGIC) {
|
|
fprintf(stderr, "df: %s: Not a valid file system\n", name);
|
|
close(fd);
|
|
return;
|
|
}
|
|
i_count = (ino_t) bit_count(sp->s_imap_blocks, sp->s_ninodes + 1, fd);
|
|
if (i_count == -1) {
|
|
fprintf(stderr, "df: Can't find bit maps of %s\n", name);
|
|
close(fd);
|
|
return;
|
|
}
|
|
i_count--; /* There is no inode 0. */
|
|
|
|
z_count = bit_count(sp->s_zmap_blocks, sp->s_nzones, fd);
|
|
if (z_count == -1) {
|
|
fprintf(stderr, "df: Can't find bit maps of %s\n", name);
|
|
close(fd);
|
|
return;
|
|
}
|
|
totblocks = (block_nr) sp->s_nzones << sp->s_log_zone_size;
|
|
busyblocks = (block_nr) z_count << sp->s_log_zone_size;
|
|
|
|
/* Print results. */
|
|
fprintf(stdout, "%s", name);
|
|
j = 10 - strlen(name);
|
|
while (j > 0) {
|
|
fprintf(stdout, " ");
|
|
j--;
|
|
}
|
|
|
|
fprintf(stdout, " %5u %5u %5u %7ld %7ld %7ld %s\n",
|
|
sp->s_ninodes, /* total inodes */
|
|
i_count, /* inodes used */
|
|
sp->s_ninodes - i_count,/* inodes free */
|
|
|
|
totblocks, /* total blocks */
|
|
busyblocks, /* blocks used */
|
|
totblocks - busyblocks, /* blocsk free */
|
|
|
|
strcmp(mnton, "device") == 0 ? "(root dev)" : mnton
|
|
|
|
);
|
|
close(fd);
|
|
}
|
|
|
|
long bit_count(blocks, bits, fd)
|
|
unsigned blocks;
|
|
unsigned bits;
|
|
int fd;
|
|
{
|
|
register char *wptr;
|
|
register int i;
|
|
register int b;
|
|
register unsigned busy; /* bits fits in unsigned, so busy does too */
|
|
register char *wlim;
|
|
register int j;
|
|
static char buf[BLOCK_SIZE];
|
|
static unsigned bits_in_char[1 << CHAR_BIT];
|
|
|
|
/* Precalculate bitcount for each char. */
|
|
if (bits_in_char[1] != 1) {
|
|
for (b = (1 << 0); b < (1 << CHAR_BIT); b <<= 1)
|
|
for (i = 0; i < (1 << CHAR_BIT); i++)
|
|
if (i & b) bits_in_char[i]++;
|
|
}
|
|
|
|
/* Loop on blocks, reading one at a time and counting bits. */
|
|
busy = 0;
|
|
for (i = 0; i < blocks && bits != 0; i++) {
|
|
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) return(-1);
|
|
|
|
wptr = &buf[0];
|
|
if (bits >= CHAR_BIT * BLOCK_SIZE) {
|
|
wlim = &buf[BLOCK_SIZE];
|
|
bits -= CHAR_BIT * BLOCK_SIZE;
|
|
} else {
|
|
b = bits / CHAR_BIT; /* whole chars in map */
|
|
wlim = &buf[b];
|
|
bits -= b * CHAR_BIT; /* bits in last char, if any */
|
|
b = *wlim & ((1 << bits) - 1); /* bit pattern from last ch */
|
|
busy += bits_in_char[b];
|
|
bits = 0;
|
|
}
|
|
|
|
/* Loop on the chars of a block. */
|
|
while (wptr != wlim)
|
|
busy += bits_in_char[*wptr++ & ((1 << CHAR_BIT) - 1)];
|
|
}
|
|
return(busy);
|
|
}
|
|
|
|
|
|
char mtabbuf[1024];
|
|
int mtabcnt;
|
|
|
|
getname(d, m)
|
|
char **d, **m;
|
|
{
|
|
int c;
|
|
static char *mp = mtabbuf;
|
|
|
|
*d = mp;
|
|
*m = "";
|
|
|
|
do {
|
|
if (--mtabcnt < 0) exit(0);
|
|
c = *mp++;
|
|
if (c == ' ') {
|
|
mp[-1] = 0;
|
|
*m = mp;
|
|
}
|
|
} while (c != '\n');
|
|
mp[-1] = 0;
|
|
}
|
|
|
|
defaults()
|
|
{
|
|
/* Use the root file system and all mounted file systems. */
|
|
|
|
char *dev, *dir;
|
|
|
|
close(0);
|
|
if (open(mtab, O_RDONLY) < 0 || (mtabcnt = read(0, mtabbuf, sizeof(mtabbuf))) <= 0) {
|
|
fprintf(stderr, "df: cannot read %s\n", mtab);
|
|
exit(1);
|
|
}
|
|
|
|
/* Read /etc/mtab and iterate on the lines. */
|
|
while (1) {
|
|
getname(&dev, &dir); /* getname exits upon hitting EOF */
|
|
df(dev, dir, REPORT);
|
|
}
|
|
|
|
}
|