xref: /original-bsd/bin/df/df.c (revision de38840f)
1 static	char *sccsid = "@(#)df.c	4.7 (Berkeley) 07/10/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 [ -i ] [ -l ] [ 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 	if (lflag)
124 		sync();
125 	bread(1L, (char *)&sblock, sizeof(sblock));
126 	printf("%-12.12s%s", file, mp = mpath(file));
127 	if (strlen(mp) < 4)
128 		putchar('\t');
129 
130 	blocks = (long) sblock.s_fsize - (long)sblock.s_isize;
131 	free = sblock.s_tfree;
132 	used = blocks - free;
133 
134 	printf("\t%6ld", blocks);
135 	printf("\t%6ld", used);
136 	printf("\t%6ld", free);
137 	if (lflag) {
138 		hardway = 0;
139 		while(alloc())
140 			hardway++;
141 		printf("\t%6ld", free=hardway);
142 	}
143 	printf("\t%5.0f%%",
144 	    blocks == 0 ? 0.0 : (double) used / (double)blocks * 100.0);
145 	if (iflag) {
146 		int inodes = (sblock.s_isize - 2) * INOPB;
147 		used = inodes - sblock.s_tinode;
148 		printf("\t%5ld\t%5ld\t%5.0f%%", used, sblock.s_tinode,
149 		    inodes == 0 ? 0.0 : (double)used/(double)inodes*100.0);
150 	}
151 	printf("\n");
152 	close(fi);
153 }
154 
155 daddr_t
156 alloc()
157 {
158 	int i;
159 	daddr_t b;
160 	struct fblk buf;
161 
162 	i = --sblock.s_nfree;
163 	if(i<0 || i>=NICFREE) {
164 		printf("bad free count, b=%D\n", blkno);
165 		return(0);
166 	}
167 	b = sblock.s_free[i];
168 	if(b == 0)
169 		return(0);
170 	if(b<sblock.s_isize || b>=sblock.s_fsize) {
171 		printf("bad free block (%D)\n", b);
172 		return(0);
173 	}
174 	if(sblock.s_nfree <= 0) {
175 		bread(b, (char *)&buf, sizeof(buf));
176 		blkno = b;
177 		sblock.s_nfree = buf.df_nfree;
178 		for(i=0; i<NICFREE; i++)
179 			sblock.s_free[i] = buf.df_free[i];
180 	}
181 	return(b);
182 }
183 
184 bread(bno, buf, cnt)
185 daddr_t bno;
186 char *buf;
187 {
188 	int n;
189 	extern errno;
190 
191 	lseek(fi, bno<<BSHIFT, 0);
192 	if((n=read(fi, buf, cnt)) != cnt) {
193 		printf("\nread error bno = %ld\n", bno);
194 		printf("count = %d; errno = %d\n", n, errno);
195 		exit(0);
196 	}
197 }
198 
199 /*
200  * Given a name like /dev/rrp0h, returns the mounted path, like /usr.
201  */
202 char *mpath(file)
203 char *file;
204 {
205 	register int i;
206 
207 	if (eq(file, root))
208 		return "/";
209 	for (i=0; i<NFS; i++)
210 		if (eq(file, mtab[i].spec))
211 			return mtab[i].path;
212 	return "";
213 }
214 
215 eq(f1, f2)
216 char *f1, *f2;
217 {
218 	if (strncmp(f1, "/dev/", 5) == 0)
219 		f1 += 5;
220 	if (strncmp(f2, "/dev/", 5) == 0)
221 		f2 += 5;
222 	if (strcmp(f1, f2) == 0)
223 		return 1;
224 	if (*f1 == 'r' && strcmp(f1+1, f2) == 0)
225 		return 1;
226 	if (*f2 == 'r' && strcmp(f1, f2+1) == 0)
227 		return 1;
228 	if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0)
229 		return 1;
230 	return 0;
231 }
232