xref: /original-bsd/bin/df/df.c (revision 6c57d260)
1 static	char *sccsid = "@(#)df.c	4.5 (Berkeley) 03/22/81";
2 #include <stdio.h>
3 #include <fstab.h>
4 #include <sys/param.h>
5 #include <sys/filsys.h>
6 #include <sys/fblk.h>
7 #include <sys/stat.h>
8 /*
9  * df
10  */
11 
12 #define NFS	20	/* Max number of filesystems */
13 
14 struct {
15 	char path[32];
16 	char spec[32];
17 } mtab[NFS];
18 char root[32];
19 
20 char *mpath();
21 
22 daddr_t	blkno	= 1;
23 
24 int	lflag;
25 int	iflag;
26 
27 struct	filsys sblock;
28 
29 int	fi;
30 daddr_t	alloc();
31 
32 main(argc, argv)
33 char **argv;
34 {
35 	int i;
36 	char buf[128];
37 
38 	while (argc >= 1 && argv[1][0]=='-') {
39 		switch(argv[1][1]) {
40 
41 		case 'l':
42 			lflag++;
43 			break;
44 
45 		case 'i':
46 			iflag++;
47 			break;
48 
49 		default:
50 			fprintf(stderr, "usage: df [ -il ] [ filsys... ]\n");
51 			exit(0);
52 		}
53 		argc--, argv++;
54 	}
55 
56 	if ((i=open("/etc/mtab", 0)) >= 0) {
57 		read(i, mtab, sizeof mtab);	/* Probably returns short */
58 		close(i);
59 	}
60 	printf("Filesystem  Mounted on  kbytes\t  used\t  free");
61 	if (lflag)
62 		printf("\thardway");
63 	printf("\t%% used");
64 	if (iflag)
65 		printf("\tiused\tifree\t%%iused");
66 	putchar('\n');
67 	if(argc <= 1) {
68 		struct	fstab	*fsp;
69 		if (setfsent() == 0)
70 			perror(FSTAB), exit(1);
71 		while( (fsp = getfsent()) != 0){
72 			if (  (strcmp(fsp->fs_type, FSTAB_RW) != 0)
73 			    &&(strcmp(fsp->fs_type, FSTAB_RO) != 0) )
74 				continue;
75 			if (root[0] == 0)
76 				strcpy(root, fsp->fs_spec);
77 			dfree(fsp->fs_spec);
78 		}
79 		endfsent();
80 		exit(0);
81 	}
82 
83 	for(i=1; i<argc; i++) {
84 		dfree(argv[i]);
85 	}
86 }
87 
88 dfree(file)
89 char *file;
90 {
91 	daddr_t i;
92 	long	blocks;
93 	long	free;
94 	long	used;
95 	long	hardway;
96 	char	*mp;
97 	struct	stat stbuf;
98 
99 	if(stat(file, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) != S_IFCHR
100 	  && (stbuf.st_mode&S_IFMT) != S_IFBLK) {
101 		int mt = open("/etc/mtab", 0), len;
102 		char *str = "/dev/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
103 		char mtab[32];
104 		struct stat mstbuf;
105 		while((len = read(mt, mtab, 32)) == 32) {
106 			read(mt, &str[5], 32);
107 			if(stat(str, &mstbuf) == 0 && mstbuf.st_rdev == stbuf.st_dev) {
108 				file = str;
109 				break;
110 			}
111 		}
112 		close(mt);
113 		if(len == 0) {
114 			fprintf(stderr, "%s: mounted on unknown device\n", file);
115 			return;
116 		}
117 	}
118 	fi = open(file, 0);
119 	if(fi < 0) {
120 		fprintf(stderr,"cannot open %s\n", file);
121 		return;
122 	}
123 	sync();
124 	bread(1L, (char *)&sblock, sizeof(sblock));
125 	printf("%-12.12s%s", file, mp = mpath(file));
126 	if (strlen(mp) < 4)
127 		putchar('\t');
128 
129 	blocks = (long) sblock.s_fsize - (long)sblock.s_isize;
130 	free = sblock.s_tfree;
131 	used = blocks - free;
132 
133 	printf("\t%6ld", blocks);
134 	printf("\t%6ld", used);
135 	printf("\t%6ld", free);
136 	if (lflag) {
137 		hardway = 0;
138 		while(alloc())
139 			hardway++;
140 		printf("\t%6ld", free=hardway);
141 	}
142 	printf("\t%5.0f%%",
143 	    blocks == 0 ? 0.0 : (double) used / (double)blocks * 100.0);
144 	if (iflag) {
145 		int inodes = (sblock.s_isize - 2) * INOPB;
146 		used = inodes - sblock.s_tinode;
147 		printf("\t%5ld\t%5ld\t%5.0f%%", used, sblock.s_tinode,
148 		    inodes == 0 ? 0.0 : (double)used/(double)inodes*100.0);
149 	}
150 	printf("\n");
151 	close(fi);
152 }
153 
154 daddr_t
155 alloc()
156 {
157 	int i;
158 	daddr_t b;
159 	struct fblk buf;
160 
161 	i = --sblock.s_nfree;
162 	if(i<0 || i>=NICFREE) {
163 		printf("bad free count, b=%D\n", blkno);
164 		return(0);
165 	}
166 	b = sblock.s_free[i];
167 	if(b == 0)
168 		return(0);
169 	if(b<sblock.s_isize || b>=sblock.s_fsize) {
170 		printf("bad free block (%D)\n", b);
171 		return(0);
172 	}
173 	if(sblock.s_nfree <= 0) {
174 		bread(b, (char *)&buf, sizeof(buf));
175 		blkno = b;
176 		sblock.s_nfree = buf.df_nfree;
177 		for(i=0; i<NICFREE; i++)
178 			sblock.s_free[i] = buf.df_free[i];
179 	}
180 	return(b);
181 }
182 
183 bread(bno, buf, cnt)
184 daddr_t bno;
185 char *buf;
186 {
187 	int n;
188 	extern errno;
189 
190 	lseek(fi, bno<<BSHIFT, 0);
191 	if((n=read(fi, buf, cnt)) != cnt) {
192 		printf("\nread error bno = %ld\n", bno);
193 		printf("count = %d; errno = %d\n", n, errno);
194 		exit(0);
195 	}
196 }
197 
198 /*
199  * Given a name like /dev/rrp0h, returns the mounted path, like /usr.
200  */
201 char *mpath(file)
202 char *file;
203 {
204 	register int i;
205 
206 	if (eq(file, root))
207 		return "/";
208 	for (i=0; i<NFS; i++)
209 		if (eq(file, mtab[i].spec))
210 			return mtab[i].path;
211 	return "";
212 }
213 
214 eq(f1, f2)
215 char *f1, *f2;
216 {
217 	if (strncmp(f1, "/dev/", 5) == 0)
218 		f1 += 5;
219 	if (strncmp(f2, "/dev/", 5) == 0)
220 		f2 += 5;
221 	if (strcmp(f1, f2) == 0)
222 		return 1;
223 	if (*f1 == 'r' && strcmp(f1+1, f2) == 0)
224 		return 1;
225 	if (*f2 == 'r' && strcmp(f1, f2+1) == 0)
226 		return 1;
227 	if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0)
228 		return 1;
229 	return 0;
230 }
231