[5179] in Athena Bugs

home help back first fref pref prev next nref lref last post

df patches

daemon@ATHENA.MIT.EDU (John Carr)
Thu Jun 14 02:50:36 1990

To: bugs@ATHENA.MIT.EDU
Date: Thu, 14 Jun 90 02:50:12 EDT
From: John Carr <jfc@ATHENA.MIT.EDU>


These are patches to df, written making the assumptions that stat is
expensive and statfs is better that reading raw disk devices.  After
the patch is an updated version of df(1).

This version of df should not be made setuid or setgid (makefile
change NOT included).

I assumed ANSI C.  The changes for old C compilers are trivial.

*** /source/bsd-4.3/common/bin/df.c	Wed Apr 13 14:08:41 1988
--- df.c	Thu Jun 14 02:42:57 1990
***************
*** 1,6 ****
! /* NFSSRC @(#)df.c	2.1 86/04/17 */
! #ifndef lint
! static	char sccsid[] = "@(#)df.c 1.1 86/02/03 SMI"; /* from UCB 4.18 84/02/02 */
! #endif
  /*
   * df
--- 1,4 ----
! static const char *version = "df.c (Athena, from df.c 2.1 86/04/17 SMI)";
! /* from UCB 4.18 84/02/02 */
  /*
   * df
***************
*** 17,32 ****
  char	*mpath();
  int	iflag;
- int	type;
- char	*typestr;
  
! struct mntent *getmntpt(), *mntdup();
  
- union {
- 	struct fs iu_fs;
- 	char dummy[SBSIZE];
- } sb;
- #define sblock sb.iu_fs
- 
- 
  main(argc, argv)
  	int argc;
--- 15,21 ----
  char	*mpath();
  int	iflag;
  
! struct mntent *getmntpt();
  
  main(argc, argv)
  	int argc;
***************
*** 33,49 ****
  	char **argv;
  {
! 	int i;
  	struct stat statb;
- 	char tmpname[1024];
  
  	while (argc > 1 && argv[1][0]=='-') {
  		switch (argv[1][1]) {
  
  		case 'i':
! 			iflag++;
  			break;
  
  		case 't':
! 			type++;
  			typestr = argv[2];
  			argv++;
--- 22,41 ----
  	char **argv;
  {
! 	int i, qflag = 0, type = 0;
! 	char	*typestr = 0;
  	struct stat statb;
  
  	while (argc > 1 && argv[1][0]=='-') {
  		switch (argv[1][1]) {
+ 		case 'q':
+ 			qflag = 1;
+ 			break;
  
  		case 'i':
! 			iflag = 1;
  			break;
  
  		case 't':
! 			type = 1;
  			typestr = argv[2];
  			argv++;
***************
*** 59,63 ****
  		usage();
  	}
- 	sync();
  	if (iflag)
  		printf("Filesystem             iused   ifree  %%iused");
--- 51,54 ----
***************
*** 71,75 ****
  		if ((mtabp = setmntent(MOUNTED, "r")) == 0) {
  			perror(MOUNTED);
! 			exit(1);
  		}
  		while (mnt = getmntent(mtabp)) {
--- 62,66 ----
  		if ((mtabp = setmntent(MOUNTED, "r")) == 0) {
  			perror(MOUNTED);
! 			exit(2);
  		}
  		while (mnt = getmntent(mtabp)) {
***************
*** 77,93 ****
  			    strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
  				continue;
- 			if (!strcmp(mnt->mnt_type, MNTTYPE_NFS) && iflag)
- 				continue;
  			if (type && strcmp(typestr, mnt->mnt_type)) {
  				continue;
  			}
! 			if ((stat(mnt->mnt_fsname, &statb) >= 0) &&
! 			   (((statb.st_mode & S_IFBLK) == S_IFBLK) ||
! 			    ((statb.st_mode & S_IFCHR) == S_IFCHR))) {
! 				strcpy(tmpname, mnt->mnt_fsname);
! 				dfreedev(tmpname);
! 			} else {
! 				dfreemnt(mnt->mnt_dir, mnt);
! 			}
  		}
  		endmntent(mtabp);
--- 68,75 ----
  			    strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
  				continue;
  			if (type && strcmp(typestr, mnt->mnt_type)) {
  				continue;
  			}
! 			dfreemnt(mnt->mnt_dir, mnt);
  		}
  		endmntent(mtabp);
***************
*** 97,114 ****
  		struct mntent *mnt;
  
  		if (stat(argv[i], &statb) < 0) {
  			perror(argv[i]);
  		} else {
! 			if ((statb.st_mode & S_IFBLK) == S_IFBLK ||
! 			    (statb.st_mode & S_IFCHR) == S_IFCHR) {
! 				dfreedev(argv[i]);
! 			} else {
! 				if ((mnt = getmntpt(argv[i])) != NULL)
! 					if (type &&
! 					    strcmp(typestr, mnt->mnt_type)) {
! 						continue;
! 					}
! 					dfreemnt(argv[i], mnt);
! 			}
  		}
  	}
--- 79,98 ----
  		struct mntent *mnt;
  
+ 		if (qflag) {
+ 			dfreemnt(argv[i], 0);
+ 			continue;
+ 		}
  		if (stat(argv[i], &statb) < 0) {
  			perror(argv[i]);
+ 			continue;
+ 		}
+ 		if ((statb.st_mode & S_IFMT) == S_IFBLK ||
+ 		    (statb.st_mode & S_IFMT) == S_IFCHR) {
+ 			dfreedev(argv[i]);
  		} else {
! 			if ((mnt = getmntpt(argv[i], &statb)) &&
! 			    type && strcmp(typestr, mnt->mnt_type))
! 				continue;
! 			dfreemnt(argv[i], mnt);
  		}
  	}
***************
*** 121,125 ****
--- 105,132 ----
  	long totalblks, availblks, avail, free, used;
  	int fi;
+ 	union {
+ 		struct fs iu_fs;
+ 		char dummy[SBSIZE];
+ 	} sb;
+ #define sblock sb.iu_fs
  
+ #if 1
+ 	static const char *warnstr =
+   "\nWARNING: You have given as a file name a character or block special device.\n\
+ If you want the usage information of the partition containing the device\n\
+ you should use a different filename, because to preserve the tradition of\n\
+ earlier, broken versions of df, this version considers a file name which is\n\
+ a character special device a request to open the device, read a filesystem\n\
+ superblock, and parse the fields of the supberblock to get usage information.\n\
+ This means the following information is INCORRECT if the filesystem format has\n\
+ changed since df was compiled.\n\n";
+ 
+ 	static int warned;
+ 
+ 	if(warned == 0) {
+ 		warned = 1;
+ 		write(2, warnstr, strlen(warnstr));
+ 	}
+ #endif
  	fi = open(file, 0);
  	if (fi < 0) {
***************
*** 162,165 ****
--- 169,173 ----
  	struct statfs fs;
  
+ 	bzero(&fs, sizeof(fs));
  	if (statfs(file, &fs) < 0) {
  		perror(file);
***************
*** 167,177 ****
  	}
  
! 	if (strlen(mnt->mnt_fsname) > 20) {
  		printf("%s\n", mnt->mnt_fsname);
  		printf("                    ");
  	} else {
! 		printf("%-20.20s", mnt->mnt_fsname);
  	}
! 	if (iflag) {
  		long files, used;
  
--- 175,186 ----
  	}
  
! 	if (mnt && strlen(mnt->mnt_fsname) > 20) {
  		printf("%s\n", mnt->mnt_fsname);
  		printf("                    ");
  	} else {
! 		printf("%-20.20s", mnt ? mnt->mnt_fsname : file);
  	}
! 	/* if fs.f_files is still zero, assume no inodes for this fs type */
! 	if (iflag && fs.f_files) {
  		long files, used;
  
***************
*** 197,201 ****
  		printf("  ");
  	}
! 	printf("  %s\n", mnt->mnt_dir);
  }
  
--- 206,210 ----
  		printf("  ");
  	}
! 	printf("  %s\n", mnt ? mnt->mnt_dir : "???");
  }
  
***************
*** 205,226 ****
   */
  struct mntent *
! getmntpt(file)
  	char *file;
  {
  	FILE *mntp;
! 	struct mntent *mnt, *mntsave;
! 	struct stat filestat, dirstat;
  
- 	if (stat(file, &filestat) < 0) {
- 		perror(file);
- 		return(NULL);
- 	}
- 
  	if ((mntp = setmntent(MOUNTED, "r")) == 0) {
  		perror(MOUNTED);
! 		exit(1);
  	}
  
- 	mntsave = NULL;
  	while ((mnt = getmntent(mntp)) != 0) {
  		if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
--- 214,230 ----
   */
  struct mntent *
! getmntpt(file, statp)
  	char *file;
+ 	struct stat *statp;
  {
  	FILE *mntp;
! 	struct mntent *mnt;
! 	struct stat dirstat;
  
  	if ((mntp = setmntent(MOUNTED, "r")) == 0) {
  		perror(MOUNTED);
! 		exit(3);
  	}
  
  	while ((mnt = getmntent(mntp)) != 0) {
  		if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 ||
***************
*** 227,242 ****
  		    strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
  			continue;
! 		if ((stat(mnt->mnt_dir, &dirstat) >= 0) &&
! 		   (filestat.st_dev == dirstat.st_dev)) {
! 			mntsave = mntdup(mnt);
  		}
  	}
  	endmntent(mntp);
! 	if (mntsave) {
! 		return(mntsave);
! 	} else {
! 		fprintf(stderr, "Couldn't find mount point for %s\n", file);
! 		exit(1);
! 	}
  	/*NOTREACHED*/
  }
--- 231,246 ----
  		    strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0)
  			continue;
! 		if (!strcmp(mnt->mnt_dir, file) || 
! 		    (stat(mnt->mnt_dir, &dirstat) >= 0) &&
! 		    (statp->st_dev == dirstat.st_dev)) {
! 			/* It is safe to return mnt here, since getmntent
! 			   won't be called again before it is used */
! 			endmntent(mntp);
! 			return mnt;
  		}
  	}
  	endmntent(mntp);
! 	fprintf(stderr, "Couldn't find mount point for %s\n", file);
! 	return (struct mntent *)0;
  	/*NOTREACHED*/
  }
***************
*** 254,258 ****
  	if ((mntp = setmntent(MOUNTED, "r")) == 0) {
  		perror(MOUNTED);
! 		exit(1);
  	}
  
--- 258,262 ----
  	if ((mntp = setmntent(MOUNTED, "r")) == 0) {
  		perror(MOUNTED);
! 		exit(5);
  	}
  
***************
*** 264,268 ****
  	}
  	endmntent(mntp);
! 	return "";
  }
  
--- 268,272 ----
  	}
  	endmntent(mntp);
! 	return "(not mounted)";
  }
  
***************
*** 275,287 ****
  {
  	int n;
- 	extern errno;
  
  	(void) lseek(fi, (long)(bno * DEV_BSIZE), 0);
  	if ((n=read(fi, buf, cnt)) != cnt) {
! 		/* probably a dismounted disk if errno == EIO */
! 		if (errno != EIO) {
! 			printf("\nread error bno = %ld\n", bno);
! 			printf("count = %d; errno = %d\n", n, errno);
! 		}
  		return (0);
  	}
--- 279,293 ----
  {
  	int n;
  
  	(void) lseek(fi, (long)(bno * DEV_BSIZE), 0);
  	if ((n=read(fi, buf, cnt)) != cnt) {
! 		if (n < 0)
! 			fprintf(stderr, 
! 				"\nread error bno = %ld: %s\n", bno,
! 				errno > sys_nerr ? "Unknown error" :
! 				sys_errlist[errno]);
! 		else
! 			fprintf(stderr, "\nshort read bno %ld count %d\n",
! 				bno, cnt);
  		return (0);
  	}
***************
*** 289,335 ****
  }
  
- char *
- xmalloc(size)
- 	int size;
- {
- 	char *ret;
- 	
- 	if ((ret = (char *)malloc(size)) == NULL) {
- 		fprintf(stderr, "umount: ran out of memory!\n");
- 		exit(1);
- 	}
- 	return (ret);
- }
- 
- struct mntent *
- mntdup(mnt)
- 	struct mntent *mnt;
- {
- 	struct mntent *new;
- 
- 	new = (struct mntent *)xmalloc(sizeof(*new));
- 
- 	new->mnt_fsname = (char *)xmalloc(strlen(mnt->mnt_fsname) + 1);
- 	strcpy(new->mnt_fsname, mnt->mnt_fsname);
- 
- 	new->mnt_dir = (char *)xmalloc(strlen(mnt->mnt_dir) + 1);
- 	strcpy(new->mnt_dir, mnt->mnt_dir);
- 
- 	new->mnt_type = (char *)xmalloc(strlen(mnt->mnt_type) + 1);
- 	strcpy(new->mnt_type, mnt->mnt_type);
- 
- 	new->mnt_opts = (char *)xmalloc(strlen(mnt->mnt_opts) + 1);
- 	strcpy(new->mnt_opts, mnt->mnt_opts);
- 
- 	new->mnt_freq = mnt->mnt_freq;
- 	new->mnt_passno = mnt->mnt_passno;
- 
- 	return (new);
- }
- 
  usage()
  {
! 
! 	fprintf(stderr, "usage: df [ -i ] [-t type | file... ]\n");
! 	exit(0);
  }
--- 295,301 ----
  }
  
  usage()
  {
! 	fprintf(stderr, "usage: df [ -i ] [-t type | [ -q ] file... ]\n");
! 	exit(1);
  }


----------------------------------------------------------------
New df(1):

.\" Copyright (c) 1980 Regents of the University of California.
.\" All rights reserved.  The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\"	@(#)df.1	6.1 (Berkeley) 4/29/85
.\"
.TH DF 1 "June 14, 1900"
.UC 4
.SH NAME
df \- disk free
.SH SYNOPSIS
.B df
[
.B \-i
] [
.B \-t
mount-type ] [ [
.B \-q
] file ... ]
.SH DESCRIPTION
.I Df
prints out the amount of free disk space
available on the specified
.I filesystem.
Unless the
.B \-q
flag is used,
.I file
can be a special device, e.g. ``/dev/ra0a''.
If the
.B \-q
flag is used, or if the file is not a special device,
the filesystem containing
.I file,
e.g. ``$HOME'',
is used.
If no file system is specified,
the free space on all of the mounted file systems is printed.
The reported numbers are in kilobytes.
.PP
Other options are:
.TP
.B \-i
Report also the number of inodes which are used and free.
.TP
.B \-t \fImount\-type\fR
Report only on those filesystems of the given
.IR mount\-type .  
For instance, 
.I df -t 4.2 
will show you statistics only
about the 4.2 filesystems which are mounted.
.SH BUGS
The -i option does not work over NFS
.SH FILES
/etc/fstab	list of normally mounted filesystems
.SH "SEE ALSO"
fstab(5), icheck(8), quot(8)

home help back first fref pref prev next nref lref last post