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