|
|
1.1 root 1: static char *sccsid = "@(#)df.c 4.6 (Berkeley) 7/8/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 32 /* Max number of filesystems */
13:
14: struct mtab {
15: char path[FSNMLG];
16: char spec[FSNMLG];
17: } mtab[NFS];
18: struct stat stb;
19: int dev;
20: #define L10BS 6
21: #define L10IS 5
22: #define PCTFW 3
23: int DEVNMLG; /* length of longest device name */
24: int DIRNMLG; /* length of longest mount point name */
25:
26: char *mpath();
27:
28: daddr_t blkno = 1;
29:
30: int lflag;
31: int iflag;
32:
33: struct filsys sblock;
34:
35: int fi;
36: daddr_t alloc();
37:
38: main(argc, argv)
39: register int argc;
40: register char **argv;
41: {
42: register int i;
43: register int r = 0;
44:
45: while (argc >= 1 && argv[1][0]=='-') {
46: switch(argv[1][1]) {
47:
48: case 'l':
49: lflag++;
50: break;
51:
52: case 'i':
53: iflag++;
54: break;
55:
56: default:
57: fprintf(stderr, "usage: df [-i] [-l] [filsys...]\n");
58: exit(0);
59: }
60: argc--, argv++;
61: }
62:
63: if ((i=open("/etc/mtab", 0)) >= 0) {
64: r = read(i, mtab, sizeof mtab); /* Probably returns short */
65: (void) close(i);
66: r /= sizeof mtab[0];
67: }
68: devlen(r); /* reads in all of /etc/fstab, too */
69: printf("%-*.*s %-*.*s %*.*s %*.*s %*.*s",
70: DIRNMLG, DIRNMLG, "dir",
71: DEVNMLG, DEVNMLG, "dev",
72: L10BS, L10BS, "kbytes",
73: L10BS, L10BS, "used",
74: L10BS, L10BS, "free");
75: if (lflag)
76: printf(" %*.*s", L10BS, L10BS, "hardway");
77: printf(" %*.*s", PCTFW + 1, PCTFW + 1, "%use");
78: if (iflag)
79: printf(" %*.*s %*.*s %*.*s",
80: L10IS, L10IS, "iused",
81: L10IS, L10IS, "ifree",
82: PCTFW + 1, PCTFW + 1, "%ino");
83: putchar('\n');
84: if(argc <= 1) {
85: for (i = 0; i < NFS && mtab[i].spec[0]; ++i)
86: dfree(mtab[i].path);
87: return (0);
88: }
89:
90: for(i=1; i<argc; i++)
91: dfree(argv[i]);
92: return (0);
93: }
94:
95: dfree(file)
96: char *file;
97: {
98: register daddr_t i;
99: register char *mp;
100: long blocks;
101: long free;
102: long used;
103: long hardway;
104: struct stat stbuf;
105: static char specbuf[FSNMLG + sizeof "/dev/"] = "/dev/";
106:
107: if(stat(file, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) == S_IFDIR)
108: {
109: struct stat mstbuf;
110:
111: for (i = 0; i < NFS && mtab[i].spec[0]; ++i)
112: {
113: strcpy(&specbuf[5], mtab[i].spec);
114: if(!stat(specbuf, &mstbuf) && mstbuf.st_rdev == stbuf.st_dev)
115: {
116: file = specbuf;
117: break;
118: }
119: }
120: if (i == NFS || mtab[i].spec[0] == '\0')
121: {
122: fprintf(stderr, "%s mounted on unknown device\n", file);
123: return;
124: }
125: }
126: else
127: if (strncmp("/dev/", file, sizeof "/dev/" - 1) != 0)
128: strcpy(&specbuf[5], file), file = specbuf;
129: fi = open(file, 0);
130: if(fi < 0)
131: {
132: fprintf(stderr,"cannot open %s\n", file);
133: return;
134: }
135: fstat(fi, &stb);
136: dev = stb.st_rdev;
137: if (lflag)
138: sync();
139: bread(1L, (char *)&sblock, sizeof(sblock));
140: blocks = (long) sblock.s_fsize - (long)sblock.s_isize;
141: free = sblock.s_tfree;
142: used = blocks - free;
143: if(BITFS(dev)) {
144: blocks *= BSIZE(dev) / BSIZE(0);
145: free *= BSIZE(dev) / BSIZE(0);
146: used *= BSIZE(dev) / BSIZE(0);
147: }
148: printf("%-*.*s %-*.*s %*ld %*ld %*ld",
149: DIRNMLG, DIRNMLG, mp = mpath(file),
150: DEVNMLG, DEVNMLG, file + sizeof "/dev",
151: L10BS, blocks, L10BS, used, L10BS, free);
152:
153: if (lflag) {
154: hardway = 0;
155: if(BITFS(dev))
156: hardway = alloc();
157: else
158: while(alloc())
159: hardway++;
160: printf(" %*ld", L10BS, free = hardway);
161: }
162: printf(" %*.0f%%",
163: PCTFW, blocks == 0 ?
164: 0.0 : (double) used / (double) blocks * 100.0);
165: if (iflag) {
166: int inodes = (sblock.s_isize - 2) * INOPB(dev);
167: used = inodes - sblock.s_tinode;
168: printf(" %*ld %*ld %*.0f%%",
169: L10IS, used,
170: L10IS, sblock.s_tinode,
171: PCTFW, inodes == 0 ?
172: 0.0 : (double) used / (double) inodes * 100.0);
173: }
174: printf("\n");
175: close(fi);
176: }
177:
178: daddr_t
179: alloc()
180: {
181: int i, j, n;
182: daddr_t b;
183: struct fblk buf;
184:
185: if(!BITFS(dev)) {
186: i = --sblock.s_nfree;
187: if(i<0 || i>=NICFREE) {
188: printf("bad free count, b=%D\n", blkno);
189: return(0);
190: }
191: b = sblock.s_free[i];
192: if(b == 0)
193: return(0);
194: if(b<sblock.s_isize || b>=sblock.s_fsize) {
195: printf("bad free block (%D)\n", b);
196: return(0);
197: }
198: if(sblock.s_nfree <= 0) {
199: bread(b, (char *)&buf, sizeof(buf));
200: blkno = b;
201: sblock.s_nfree = buf.df_nfree;
202: for(i=0; i<NICFREE; i++)
203: sblock.s_free[i] = buf.df_free[i];
204: }
205: return(b);
206: }
207: n = 0;
208: for(i = 0; i < BITMAP; i++)
209: for(j = 0; j < 32; j++) /* 32: bits per int */
210: if(sblock.s_bfree[i] & (1 << j))
211: n++;
212: return(n * BSIZE(dev) / BSIZE(0));
213: }
214:
215: bread(bno, buf, cnt)
216: daddr_t bno;
217: char *buf;
218: {
219: register int n;
220: extern errno;
221:
222: lseek(fi, bno<<BSHIFT(dev), 0);
223: if((n=read(fi, buf, cnt)) != cnt) {
224: printf("\nread error bno = %ld\n", bno);
225: printf("count = %d; errno = %d\n", n, errno);
226: exit(0);
227: }
228: }
229:
230: /*
231: * Given a name like /dev/rrp0h, returns the mounted path, like /usr.
232: */
233: char *mpath(file)
234: char *file;
235: {
236: register int i;
237:
238: for (i=0; i<NFS; i++)
239: if (eq(file, mtab[i].spec))
240: return mtab[i].path;
241: return "";
242: }
243:
244: eq(f1, f2)
245: char *f1, *f2;
246: {
247: if (strncmp(f1, "/dev/", 5) == 0)
248: f1 += 5;
249: if (strncmp(f2, "/dev/", 5) == 0)
250: f2 += 5;
251: if (strcmp(f1, f2) == 0)
252: return 1;
253: if (*f1 == 'r' && strcmp(f1+1, f2) == 0)
254: return 1;
255: if (*f2 == 'r' && strcmp(f1, f2+1) == 0)
256: return 1;
257: if (*f1 == 'r' && *f2 == 'r' && strcmp(f1+1, f2+1) == 0)
258: return 1;
259: return 0;
260: }
261:
262: mtabcmp(mp0, mp1)
263: struct mtab *mp0;
264: struct mtab *mp1;
265: {
266: /*
267: * don't let empty mtab slots sort to the front
268: * as dfree will break
269: * the wrong way to fix it: the whole algorithm is wrong
270: */
271: if (mp0->path[0] == 0)
272: return (1);
273: if (mp1->path[0] == 0)
274: return (-1);
275: return (strncmp(mp0->path, mp1->path, sizeof (mp0->path)));
276: }
277:
278: devlen(r)
279: register int r;
280: {
281: register struct fstab *fsp;
282: register int i;
283:
284: DEVNMLG = 0;
285: DIRNMLG = 0;
286: if (setfsent() == 0)
287: perror(FSTAB), exit(1);
288: while( (fsp = getfsent()) != 0){
289: if ( (strcmp(fsp->fs_type, FSTAB_RW) != 0)
290: &&(strcmp(fsp->fs_type, FSTAB_RO) != 0) )
291: continue;
292: for (i = 0; mtab[i].spec[0]; ++i)
293: {
294: if (strncmp(mtab[i].spec, fsp->fs_spec + 5,
295: sizeof fsp->fs_spec - 5) == 0)
296: break;
297: }
298: if (i == r && i < NFS)
299: {
300: strncpy(mtab[r].spec, fsp->fs_spec + 5,
301: sizeof fsp->fs_spec - 5);
302: strncpy(mtab[r].path, fsp->fs_file, sizeof fsp->fs_file);
303: ++r;
304: }
305: if (DEVNMLG < (i = strlen(fsp->fs_spec)))
306: DEVNMLG = i;
307: if (DIRNMLG < (i = strlen(fsp->fs_file)))
308: DIRNMLG = i;
309: }
310: endfsent();
311: DEVNMLG -= sizeof "/dev";
312: if (DEVNMLG < sizeof "dev" - 1)
313: DEVNMLG = sizeof "dev" - 1;
314: if (DIRNMLG < sizeof "dir" - 1)
315: DIRNMLG = sizeof "dir" - 1;
316: qsort(&mtab[0], r, sizeof mtab[0], mtabcmp);
317: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.