412 lines
8.3 KiB
C
412 lines
8.3 KiB
C
#ifndef lint
|
|
static char sccsid[] = "@(#)df.c.bak 1.1 92/07/30 SMI"; /* from UCB 4.18 84/02/02 */
|
|
#endif
|
|
/*
|
|
* df
|
|
*/
|
|
#include <sys/param.h>
|
|
#include <errno.h>
|
|
#include <ufs/fs.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/vfs.h>
|
|
|
|
#include <stdio.h>
|
|
#include <mntent.h>
|
|
|
|
void usage(), pheader();
|
|
char *mpath();
|
|
int iflag;
|
|
int aflag;
|
|
int type;
|
|
char *typestr;
|
|
|
|
union {
|
|
struct fs iu_fs;
|
|
char dummy[SBSIZE];
|
|
} sb;
|
|
#define sblock sb.iu_fs
|
|
|
|
/*
|
|
* This structure is used to build a list of mntent structures
|
|
* in reverse order from /etc/mtab.
|
|
*/
|
|
struct mntlist {
|
|
struct mntent *mntl_mnt;
|
|
struct mntlist *mntl_next;
|
|
};
|
|
|
|
struct mntlist *mkmntlist();
|
|
struct mntent *mntdup();
|
|
|
|
int
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
register struct mntent *mnt;
|
|
|
|
/*
|
|
* Skip over command name, if present.
|
|
*/
|
|
if (argc > 0) {
|
|
argv++;
|
|
argc--;
|
|
}
|
|
|
|
while (argc > 0 && (*argv)[0]=='-') {
|
|
switch ((*argv)[1]) {
|
|
|
|
case 'i':
|
|
iflag++;
|
|
break;
|
|
|
|
case 't':
|
|
type++;
|
|
argv++;
|
|
argc--;
|
|
if (argc <= 0)
|
|
usage();
|
|
typestr = *argv;
|
|
break;
|
|
|
|
case 'a':
|
|
aflag++;
|
|
break;
|
|
|
|
default:
|
|
usage();
|
|
}
|
|
argc--, argv++;
|
|
}
|
|
if (argc > 0 && type) {
|
|
usage();
|
|
}
|
|
sync();
|
|
if (argc <= 0) {
|
|
register FILE *mtabp;
|
|
|
|
if ((mtabp = setmntent(MOUNTED, "r")) == NULL) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(MOUNTED);
|
|
exit(1);
|
|
}
|
|
pheader();
|
|
while ((mnt = getmntent(mtabp)) != NULL) {
|
|
if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
|
|
strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
|
|
continue;
|
|
if (type && strcmp(typestr, mnt->mnt_type) != 0) {
|
|
continue;
|
|
}
|
|
dfreemnt(mnt->mnt_dir, mnt);
|
|
}
|
|
(void) endmntent(mtabp);
|
|
} else {
|
|
int num = argc ;
|
|
int i ;
|
|
struct mntlist *mntl ;
|
|
|
|
pheader();
|
|
aflag++;
|
|
/*
|
|
* Reverse the list and start comparing.
|
|
*/
|
|
for (mntl = mkmntlist(); mntl != NULL && num ;
|
|
mntl = mntl->mntl_next) {
|
|
struct stat dirstat, filestat ;
|
|
|
|
mnt = mntl->mntl_mnt ;
|
|
if (stat(mnt->mnt_dir, &dirstat)<0) {
|
|
continue ;
|
|
}
|
|
for (i = 0; i < argc; i++) {
|
|
if (argv[i]==NULL) continue ;
|
|
if (stat(argv[i], &filestat) < 0) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(argv[i]);
|
|
argv[i] = NULL ;
|
|
--num;
|
|
} else {
|
|
if ((filestat.st_mode & S_IFMT) == S_IFBLK ||
|
|
(filestat.st_mode & S_IFMT) == S_IFCHR) {
|
|
char *cp ;
|
|
|
|
cp = mpath(argv[i]);
|
|
if (*cp == '\0') {
|
|
dfreedev(argv[i]);
|
|
argv[i] = NULL ;
|
|
--num;
|
|
continue;
|
|
}
|
|
else {
|
|
if (stat(cp, &filestat) < 0) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(argv[i]);
|
|
argv[i] = NULL ;
|
|
--num;
|
|
continue ;
|
|
}
|
|
}
|
|
}
|
|
if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
|
|
strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
|
|
continue;
|
|
if ((filestat.st_dev == dirstat.st_dev) &&
|
|
(!type || strcmp(typestr, mnt->mnt_type)==0)){
|
|
dfreemnt(mnt->mnt_dir, mnt);
|
|
argv[i] = NULL ;
|
|
--num ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (num) {
|
|
for (i = 0; i < argc; i++)
|
|
if (argv[i]==NULL)
|
|
continue ;
|
|
else
|
|
(void) fprintf(stderr,
|
|
"Could not find mount point for %s\n", argv[i]) ;
|
|
}
|
|
}
|
|
exit(0);
|
|
/*NOTREACHED*/
|
|
}
|
|
|
|
void
|
|
pheader()
|
|
{
|
|
if (iflag)
|
|
(void) printf("Filesystem iused ifree %%iused");
|
|
else
|
|
(void) printf("Filesystem kbytes used avail capacity");
|
|
(void) printf(" Mounted on\n");
|
|
}
|
|
|
|
/*
|
|
* Report on a block or character special device. Assumed not to be
|
|
* mounted. N.B. checks for a valid 4.2BSD superblock.
|
|
*/
|
|
dfreedev(file)
|
|
char *file;
|
|
{
|
|
long totalblks, availblks, avail, free, used;
|
|
int fi;
|
|
|
|
fi = open(file, 0);
|
|
if (fi < 0) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(file);
|
|
return;
|
|
}
|
|
if (bread(file, fi, SBLOCK, (char *)&sblock, SBSIZE) == 0) {
|
|
(void) close(fi);
|
|
return;
|
|
}
|
|
if (sblock.fs_magic != FS_MAGIC) {
|
|
(void) fprintf(stderr, "df: %s: not a UNIX filesystem\n",
|
|
file);
|
|
(void) close(fi);
|
|
return;
|
|
}
|
|
(void) printf("%-20.20s", file);
|
|
if (iflag) {
|
|
int inodes = sblock.fs_ncg * sblock.fs_ipg;
|
|
used = inodes - sblock.fs_cstotal.cs_nifree;
|
|
(void) printf("%8ld%8ld%6.0f%% ", used, sblock.fs_cstotal.cs_nifree,
|
|
inodes == 0 ? 0.0 : (double)used / (double)inodes * 100.0);
|
|
} else {
|
|
totalblks = sblock.fs_dsize;
|
|
free = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
|
|
sblock.fs_cstotal.cs_nffree;
|
|
used = totalblks - free;
|
|
availblks = totalblks * (100 - sblock.fs_minfree) / 100;
|
|
avail = availblks > used ? availblks - used : 0;
|
|
(void) printf("%8d%8d%8d",
|
|
totalblks * sblock.fs_fsize / 1024,
|
|
used * sblock.fs_fsize / 1024,
|
|
avail * sblock.fs_fsize / 1024);
|
|
(void) printf("%6.0f%%",
|
|
availblks==0? 0.0: (double)used/(double)availblks * 100.0);
|
|
(void) printf(" ");
|
|
}
|
|
(void) printf(" %s\n", mpath(file));
|
|
(void) close(fi);
|
|
}
|
|
|
|
dfreemnt(file, mnt)
|
|
char *file;
|
|
struct mntent *mnt;
|
|
{
|
|
struct statfs fs;
|
|
|
|
if (statfs(file, &fs) < 0) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(file);
|
|
return;
|
|
}
|
|
|
|
if (!aflag && fs.f_blocks == 0) {
|
|
return;
|
|
}
|
|
if (strlen(mnt->mnt_fsname) > 20) {
|
|
(void) printf("%s\n", mnt->mnt_fsname);
|
|
(void) printf(" ");
|
|
} else {
|
|
(void) printf("%-20.20s", mnt->mnt_fsname);
|
|
}
|
|
if (iflag) {
|
|
long files, used;
|
|
|
|
files = fs.f_files;
|
|
used = files - fs.f_ffree;
|
|
(void) printf("%8ld%8ld%6.0f%% ", used, fs.f_ffree,
|
|
files == 0? 0.0: (double)used / (double)files * 100.0);
|
|
} else {
|
|
long totalblks, avail, free, used, reserved;
|
|
|
|
totalblks = fs.f_blocks;
|
|
free = fs.f_bfree;
|
|
used = totalblks - free;
|
|
avail = fs.f_bavail;
|
|
reserved = free - avail;
|
|
if (avail < 0)
|
|
avail = 0;
|
|
(void) printf("%8d%8d%8d", totalblks * fs.f_bsize / 1024,
|
|
used * fs.f_bsize / 1024, avail * fs.f_bsize / 1024);
|
|
totalblks -= reserved;
|
|
(void) printf("%6.0f%%",
|
|
totalblks==0? 0.0: (double)used/(double)totalblks * 100.0);
|
|
(void) printf(" ");
|
|
}
|
|
(void) printf(" %s\n", mnt->mnt_dir);
|
|
}
|
|
|
|
/*
|
|
* Given a name like /dev/rrp0h, returns the mounted path, like /usr.
|
|
*/
|
|
char *
|
|
mpath(file)
|
|
char *file;
|
|
{
|
|
FILE *mntp;
|
|
register struct mntent *mnt;
|
|
|
|
if ((mntp = setmntent(MOUNTED, "r")) == 0) {
|
|
(void) fprintf(stderr, "df: ");
|
|
perror(MOUNTED);
|
|
exit(1);
|
|
}
|
|
|
|
while ((mnt = getmntent(mntp)) != 0) {
|
|
if (strcmp(file, mnt->mnt_fsname) == 0) {
|
|
(void) endmntent(mntp);
|
|
return (mnt->mnt_dir);
|
|
}
|
|
}
|
|
(void) endmntent(mntp);
|
|
return "";
|
|
}
|
|
|
|
long lseek();
|
|
|
|
int
|
|
bread(file, fi, bno, buf, cnt)
|
|
char *file;
|
|
int fi;
|
|
daddr_t bno;
|
|
char *buf;
|
|
int cnt;
|
|
{
|
|
register int n;
|
|
extern int errno;
|
|
|
|
(void) lseek(fi, (long)(bno * DEV_BSIZE), 0);
|
|
if ((n = read(fi, buf, (unsigned) cnt)) < 0) {
|
|
/* probably a dismounted disk if errno == EIO */
|
|
if (errno != EIO) {
|
|
(void) fprintf(stderr, "df: read error on ");
|
|
perror(file);
|
|
(void) fprintf(stderr, "bno = %ld\n", bno);
|
|
} else {
|
|
(void) fprintf(stderr, "df: premature EOF on %s\n",
|
|
file);
|
|
(void) fprintf(stderr,
|
|
"bno = %ld expected = %d count = %d\n", bno, cnt, n);
|
|
}
|
|
return (0);
|
|
}
|
|
return (1);
|
|
}
|
|
|
|
char *
|
|
xmalloc(size)
|
|
unsigned int size;
|
|
{
|
|
register char *ret;
|
|
char *malloc();
|
|
|
|
if ((ret = (char *)malloc(size)) == NULL) {
|
|
(void) fprintf(stderr, "umount: ran out of memory!\n");
|
|
exit(1);
|
|
}
|
|
return (ret);
|
|
}
|
|
|
|
struct mntent *
|
|
mntdup(mnt)
|
|
register struct mntent *mnt;
|
|
{
|
|
register struct mntent *new;
|
|
|
|
new = (struct mntent *)xmalloc(sizeof(*new));
|
|
|
|
new->mnt_fsname = (char *)xmalloc(strlen(mnt->mnt_fsname) + 1);
|
|
(void) strcpy(new->mnt_fsname, mnt->mnt_fsname);
|
|
|
|
new->mnt_dir = (char *)xmalloc(strlen(mnt->mnt_dir) + 1);
|
|
(void) strcpy(new->mnt_dir, mnt->mnt_dir);
|
|
|
|
new->mnt_type = (char *)xmalloc(strlen(mnt->mnt_type) + 1);
|
|
(void) strcpy(new->mnt_type, mnt->mnt_type);
|
|
|
|
new->mnt_opts = (char *)xmalloc(strlen(mnt->mnt_opts) + 1);
|
|
(void) strcpy(new->mnt_opts, mnt->mnt_opts);
|
|
|
|
new->mnt_freq = mnt->mnt_freq;
|
|
new->mnt_passno = mnt->mnt_passno;
|
|
|
|
return (new);
|
|
}
|
|
|
|
void
|
|
usage()
|
|
{
|
|
|
|
(void) fprintf(stderr, "usage: df [ -i ] [ -a ] [ -t type | file... ]\n");
|
|
exit(0);
|
|
}
|
|
|
|
struct mntlist *
|
|
mkmntlist()
|
|
{
|
|
FILE *mounted;
|
|
struct mntlist *mntl;
|
|
struct mntlist *mntst = NULL;
|
|
struct mntent *mnt;
|
|
|
|
if ((mounted = setmntent(MOUNTED, "r"))== NULL) {
|
|
(void) fprintf(stderr, "df : ") ;
|
|
perror(MOUNTED);
|
|
exit(1);
|
|
}
|
|
while ((mnt = getmntent(mounted)) != NULL) {
|
|
mntl = (struct mntlist *)xmalloc(sizeof(*mntl));
|
|
mntl->mntl_mnt = mntdup(mnt);
|
|
mntl->mntl_next = mntst;
|
|
mntst = mntl;
|
|
}
|
|
(void) endmntent(mounted);
|
|
return(mntst);
|
|
}
|