|
|
1.1 root 1: /*
2: * df.c
3: * 7/28/93
4: * Usage: df [-fitv] [directory ...] [filesystem ...]
5: * or: df [-ait] [directory ...] [filesystem ...] (if DF_OLD is set)
6: * Print information regarding the
7: * remaining space available on a file system.
8: * This command also considers a directory
9: * to represent the filesystem.
10: *
11: * 4-24-92 Fixed minor bug for looking /etc/mtab table. Vlad
12: */
13:
14: #include <stdio.h>
15: #include <stdlib.h>
16: #include <sys/filsys.h>
17: #include <sys/stat.h>
18: #include <sys/dir.h>
19: #include <mnttab.h>
20: #include <canon.h>
21: #if 1
22: #include <mtab.h>
23: #endif
24:
25: #define NMOUNT 64 /* Maximum mounted file systems */
26:
27: /* New format options */
28: int fflag; /* supress information on i-nodes */
29: int vflag; /* Print % blocks used */
30: int tflag; /* Print total device size */
31: int iflag; /* Print information on i-nodes */
32:
33: /* Old format options - also -t and -i are valid */
34: int aflag; /* Print for each mounted fs */
35: int oflag; /* switch to old style */
36:
37: char buf[BSIZE]; /* Basic file system reading buffer */
38: struct mnttab m_tab[NMOUNT];
39: struct mnttab *emtabp;
40: int noarg; /* Was df called without any options */
41:
42: char *devname();
43:
44: main(argc, argv)
45: int argc;
46: char *argv[];
47: {
48: register char *ap;
49: register int i;
50: register int estat = 0;
51: char *s;
52:
53: if ((s = getenv("DF_OLD")) != NULL && strcmp(s, "0") != 0)
54: oflag++;
55:
56: while (argc > 1 && *argv[1] == '-') {
57: for (ap = &argv[1][1]; *ap != '\0'; ap++)
58: switch (*ap) {
59: case 'a':
60: if (oflag)
61: aflag++;
62: else
63: usage("illegal option -a");
64: break;
65:
66: case 'f':
67: if (!oflag)
68: fflag++;
69: else
70: usage("illegal option -f");
71: break;
72:
73: case 'i':
74: iflag++;
75: break;
76:
77: case 't':
78: tflag++;
79: break;
80:
81: case 'v':
82: vflag++;
83: break;
84:
85: default:
86: usage("illegal option");
87: }
88: argc--;
89: argv++;
90: }
91:
92: if (!oflag)
93: {
94: if (vflag && iflag)
95: usage("Cannot use -v with -i");
96: else if (vflag)
97: printf("Mount Dir Filesystem blocks "
98: " used free %%used\n");
99: else if (iflag)
100: printf("Mount Dir Filesystem iused i"
101: "free itotal %%iused\n");
102: }
103: minit();
104: sync();
105: if (argc < 2) {
106: if (!oflag || aflag)
107: estat = dfmtab();
108: else {
109: noarg = 1;
110: estat = df(".", NULL);
111: }
112: } else {
113: for (i = 1; i < argc; i++)
114: estat |= df(argv[i], NULL);
115: if (aflag)
116: estat |= dfmtab();
117: }
118: exit(estat);
119: }
120:
121: /*
122: * Read the mount table, looking for file systems
123: * to run df on.
124: */
125: dfmtab()
126: {
127: register struct mnttab *mp;
128: int estat;
129: int name[MNAMSIZ + 10];
130:
131: estat = 0;
132: for (mp = m_tab; mp < emtabp; mp++) {
133: if (mp->mt_dev[0]=='\0' || mp->mt_filsys[0]=='\0')
134: continue;
135: sprintf(name, "/dev/%s", mp->mt_filsys);
136: estat |= df(name, mp->mt_dev);
137: }
138: return (estat);
139: }
140:
141: /*
142: * Look at the file system
143: * and find out free space.
144: */
145: df(fs, name)
146: register char *fs, *name;
147: {
148: register struct filsys *sbp;
149: struct stat sb;
150: int fd;
151: long btotal;
152: long bfree;
153: long itotal;
154: long ifree;
155: long percent;
156: char *nfs = fs;
157:
158:
159: if (stat(fs, &sb) < 0) {
160: cmsg("cannot stat '%s'", fs);
161: return (1);
162: }
163: switch (sb.st_mode & S_IFMT) {
164: case S_IFDIR:
165: {
166: if ((nfs = devname(sb.st_dev)) == NULL) {
167: cmsg("no file system device found for directory '%s'",
168: fs);
169: return (1);
170: }
171: if (noarg)
172: fs = nfs;
173: break;
174: }
175:
176: case S_IFBLK:
177: case S_IFCHR:
178: break;
179:
180: default:
181: cmsg("unknown file type '%s'", fs);
182: return (1);
183: }
184: if ((fd = open(nfs, 0)) < 0) {
185: cmsg("cannot open '%s'", nfs);
186: return (1);
187: }
188: lseek(fd, (long)BSIZE * SUPERI, 0);
189: if (read(fd, buf, BSIZE) != BSIZE) {
190: cmsg("read error on '%s'", nfs);
191: close(fd);
192: return (1);
193: }
194: close(fd);
195: sbp = &buf[0];
196: canf(sbp);
197: if (tstf(sbp) == 0) {
198: cmsg("badly formed super block on '%s'", nfs);
199: return (1);
200: }
201:
202: bfree = sbp->s_tfree;
203: btotal = sbp->s_fsize - sbp->s_isize;
204: itotal = (sbp->s_isize-INODEI)*INOPB;
205: ifree = sbp->s_tinode;
206:
207:
208: if (!oflag)
209: {
210: printf("%-12s (%-20s): ", name == NULL ? fs : name, nfs);
211: if (vflag)
212: {
213: percent = ((btotal - bfree) * 1000L) / btotal;
214: printf(" %7lu %7lu %7lu %2ld.%1ld%%", btotal,
215: btotal - bfree, bfree, percent/10L, percent%10L);
216: }
217: else if (iflag)
218: {
219: percent = ((itotal - ifree) * 1000L) / itotal;
220: printf(" %7lu %7lu %7lu %2ld.%1ld%%",
221: itotal-ifree, ifree, itotal, percent/10L, percent%10L);
222: }
223: else
224: {
225: printf(" %7lu blocks", bfree);
226: if (!fflag)
227: printf(" %7lu inodes", ifree);
228: if (tflag)
229: {
230: printf("\n\t\t\t\tTotal:\t%7lu blocks", btotal);
231: if (!fflag)
232: printf(" %7lu inodes", itotal);
233: }
234: }
235: }
236: else
237: {
238: printf("%-11s", nfs);
239: report(bfree, btotal);
240: if (iflag)
241: {
242: printf(", ");
243: report(ifree, itotal);
244: }
245: if (tflag)
246: printf(", %lu", sbp->s_fsize);
247: }
248: printf("\n");
249: return (0);
250: }
251:
252: report(free, total)
253: long free;
254: long total;
255: {
256: long percent;
257:
258: printf(" %6lu", free);
259: percent = (free * 1000L) / total;
260: printf("/%6lu = %2ld.%1ld%%", total , percent/10L, percent%10L);
261: }
262:
263: /*
264: * Initialise mount table
265: * in memory.
266: */
267: minit()
268: {
269: register int fd;
270: register int n;
271:
272: emtabp = &m_tab[0];
273: if ((fd = open("/etc/mnttab", 0)) >= 0) {
274: if ((n = read(fd, (char *)&m_tab[0], sizeof m_tab)) > 0)
275: emtabp = (char *)(&m_tab[0]) + n;
276: close(fd);
277: return;
278: }
279: #if 1
280: if ((fd = open("/etc/mtab", 0)) >= 0) {
281: while (read(fd, (char *)emtabp, sizeof(struct mtab))
282: == sizeof(struct mtab))
283: emtabp++;
284: close(fd);
285: }
286: #endif
287: }
288:
289: /*
290: * Return the name of the block special file
291: * (in directory '/dev') which corresponds to
292: * the device given in argument.
293: */
294: char *
295: devname(dev)
296: dev_t dev;
297: {
298: register struct direct *dp;
299: register int n;
300: int fd;
301: static char name[25];
302: struct stat sb;
303:
304: if ((fd = open("/dev", 0)) < 0)
305: return (NULL);
306: while ((n = read(fd, buf, sizeof buf)) > 0) {
307: for (dp = &buf[0]; dp < &buf[n]; dp++) {
308: canino(dp->d_ino);
309: if (dp->d_ino == 0)
310: continue;
311: strcpy(name, "/dev/");
312: strncat(name, dp->d_name, DIRSIZ);
313: if (stat(name, &sb) < 0)
314: continue;
315: if ((sb.st_mode & S_IFMT) != S_IFBLK)
316: continue;
317: if (sb.st_rdev != dev)
318: continue;
319: close(fd);
320: return (name);
321: }
322: }
323: close(fd);
324: return (NULL);
325: }
326:
327: /*
328: * Canonicalize and check superblock for consistency.
329: */
330: canf(fp)
331: register struct filsys *fp;
332: {
333: register daddr_t *dp;
334: register ino_t *ip;
335:
336: canshort(fp->s_isize);
337: candaddr(fp->s_fsize);
338: canshort(fp->s_nfree);
339: for (dp = &fp->s_free[0]; dp < &fp->s_free[NICFREE]; dp += 1)
340: candaddr(*dp);
341: canshort(fp->s_ninode);
342: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[NICINOD]; ip += 1)
343: canino(*ip);
344: candaddr(fp->s_tfree);
345: canino(fp->s_tinode);
346: }
347:
348: tstf(fp)
349: register struct filsys *fp;
350: {
351: register daddr_t *dp;
352: register ino_t *ip;
353: register ino_t maxinode;
354:
355: maxinode = (fp->s_isize - INODEI) * INOPB + 1;
356: if (fp->s_isize >= fp->s_fsize)
357: return (0);
358: if (fp->s_tfree < fp->s_nfree
359: || fp->s_tfree >= fp->s_fsize - fp->s_isize + 1)
360: return (0);
361: if (fp->s_tinode < fp->s_ninode
362: || fp->s_tinode >= maxinode-1)
363: return (0);
364: for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
365: if (*dp < fp->s_isize || *dp >= fp->s_fsize)
366: return (0);
367: for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
368: if (*ip < 1 || *ip > maxinode)
369: return (0);
370: return (1);
371: }
372:
373:
374: /*
375: * Errors and warnings.
376: */
377: /* VARARGS */
378: cerr(arg)
379: char *arg;
380: {
381: fprintf(stderr, "df: %r\n", &arg);
382: exit(1);
383: }
384:
385: /* VARARGS */
386: cmsg(arg)
387: char *arg;
388: {
389: fprintf(stderr, "df: %r\n", &arg);
390: }
391:
392: usage(str)
393: char *str;
394: {
395:
396: fprintf(stderr, "df: %s\n", str);
397: fprintf(stderr, "Usage: df [-%s] [directory ...] [filesystem ...]\n",
398: oflag ? "ait" : "fitv");
399: exit(1);
400: }
401:
402: /* end of df.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.