xref: /original-bsd/bin/df/df.c (revision 549425d7)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif /* not lint */
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)df.c	5.5 (Berkeley) 05/09/89";
15 #endif /* not lint */
16 
17 #include <sys/param.h>
18 #include <sys/fs.h>
19 #include <sys/stat.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <fstab.h>
23 #include <mtab.h>
24 #include "pathnames.h"
25 
26 /*
27  * df
28  */
29 struct	mtab mtab[NMOUNT];
30 char	root[32];
31 char	*mpath();
32 
33 int	iflag;
34 
35 union {
36 	struct fs iu_fs;
37 	char dummy[SBSIZE];
38 } sb;
39 #define sblock sb.iu_fs
40 
41 int	fi;
42 daddr_t	alloc();
43 char	*strcpy();
44 
45 main(argc, argv)
46 	int argc;
47 	char **argv;
48 {
49 	extern int errno, optind;
50 	int ch, i;
51 	char *strerror();
52 
53 	while ((ch = getopt(argc, argv, "i")) != EOF)
54 		switch(ch) {
55 		case 'i':
56 			iflag++;
57 			break;
58 		case '?':
59 		default:
60 			fprintf(stderr, "usage: df [-i] [filsys ...]\n");
61 			exit(1);
62 		}
63 	argc -= optind;
64 	argv += optind;
65 
66 	if ((i = open(_PATH_MTAB, 0)) < 0) {
67 		fprintf(stderr, "df: %s: %s\n", _PATH_MTAB, strerror(errno));
68 		exit(1);
69 	}
70 	(void) read(i, (char *)mtab, sizeof (mtab));
71 	(void) close(i);
72 	sync();
73 	printf("Filesystem    kbytes    used   avail capacity");
74 	if (iflag)
75 		printf(" iused   ifree  %%iused");
76 	printf("  Mounted on\n");
77 	if (!*argv) {
78 		struct fstab *fsp;
79 
80 		if (setfsent() == 0)
81 			perror(FSTAB), exit(1);
82 		while (fsp = getfsent()) {
83 			if (strcmp(fsp->fs_type, FSTAB_RW) &&
84 			    strcmp(fsp->fs_type, FSTAB_RO) &&
85 			    strcmp(fsp->fs_type, FSTAB_RQ))
86 				continue;
87 			if (root[0] == 0)
88 				(void) strcpy(root, fsp->fs_spec);
89 			dfree(fsp->fs_spec, 1);
90 		}
91 		(void)endfsent();
92 		exit(0);
93 	}
94 	while (*argv)
95 		dfree(*argv++, 0);
96 }
97 
98 dfree(file, infsent)
99 	char *file;
100 	int infsent;
101 {
102 	extern int errno;
103 	long totalblks, availblks, avail, free, used;
104 	struct stat stbuf;
105 	struct fstab *fsp;
106 	char *strerror();
107 
108 	if (stat(file, &stbuf) == 0 &&
109 	    (stbuf.st_mode&S_IFMT) != S_IFCHR &&
110 	    (stbuf.st_mode&S_IFMT) != S_IFBLK) {
111 		if (infsent) {
112 			fprintf(stderr, "%s: screwy fstab entry\n", file);
113 			return;
114 		}
115 		(void)setfsent();
116 		while (fsp = getfsent()) {
117 			struct stat stb;
118 
119 			if (stat(fsp->fs_spec, &stb) == 0 &&
120 			    stb.st_rdev == stbuf.st_dev) {
121 				file = fsp->fs_spec;
122 				(void)endfsent();
123 				goto found;
124 			}
125 		}
126 		(void)endfsent();
127 		fprintf(stderr, "%s: mounted on unknown device\n", file);
128 		return;
129 	}
130 found:
131 	if ((fi = open(file, 0)) < 0) {
132 		fprintf(stderr, "df: %s: %s\n", file, strerror(errno));
133 		return;
134 	}
135 	if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) {
136 		(void) close(fi);
137 		return;
138 	}
139 	printf("%-12.12s", file);
140 	totalblks = sblock.fs_dsize;
141 	free = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
142 	    sblock.fs_cstotal.cs_nffree;
143 	used = totalblks - free;
144 	availblks = totalblks * (100 - sblock.fs_minfree) / 100;
145 	avail = availblks > used ? availblks - used : 0;
146 	printf("%8ld%8ld%8ld", totalblks * sblock.fs_fsize / 1024,
147 	    used * sblock.fs_fsize / 1024, avail * sblock.fs_fsize / 1024);
148 	printf("%6.0f%%",
149 	    availblks == 0 ? 0.0 : (double) used / (double) availblks * 100.0);
150 	if (iflag) {
151 		int inodes = sblock.fs_ncg * sblock.fs_ipg;
152 		used = inodes - sblock.fs_cstotal.cs_nifree;
153 		printf("%8ld%8ld%6.0f%% ", used, sblock.fs_cstotal.cs_nifree,
154 		    inodes == 0 ? 0.0 : (double)used / (double)inodes * 100.0);
155 	} else
156 		printf("  ");
157 	printf("  %s\n", mpath(file));
158 	(void) close(fi);
159 }
160 
161 long lseek();
162 
163 bread(off, buf, cnt)
164 	long off;
165 	char *buf;
166 {
167 	int n;
168 	extern errno;
169 
170 	(void) lseek(fi, off, 0);
171 	if ((n=read(fi, buf, cnt)) != cnt) {
172 		/* probably a dismounted disk if errno == EIO */
173 		if (errno != EIO) {
174 			printf("\nread error off = %ld\n", off);
175 			printf("count = %d; errno = %d\n", n, errno);
176 		}
177 		return (0);
178 	}
179 	return (1);
180 }
181 
182 /*
183  * Given a name like /dev/rrp0h, returns the mounted path, like /usr.
184  */
185 char *
186 mpath(file)
187 	char *file;
188 {
189 	register struct mtab *mp;
190 
191 	if (eq(file, root))
192 		return ("/");
193 	for (mp = mtab; mp < mtab + NMOUNT; mp++)
194 		if (eq(file, mp->m_dname))
195 			return (mp->m_path);
196 	return "";
197 }
198 
199 eq(f1, f2)
200 	char *f1, *f2;
201 {
202 
203 	if (strncmp(f1, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
204 		f1 += 5;
205 	if (strncmp(f2, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0)
206 		f2 += 5;
207 	if (!strcmp(f1, f2))
208 		return (1);
209 	if (*f1 == 'r' && !strcmp(f1+1, f2))
210 		return (1);
211 	if (*f2 == 'r' && !strcmp(f1, f2+1))
212 		return (1);
213 	if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0)
214 		return (1);
215 	return (0);
216 }
217