allow printing of statistics for unmounted special devices
[unix-history] / usr / src / bin / df / df.c
CommitLineData
bcf1365c 1/*
704aadd2
KM
2 * Copyright (c) 1980 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
bcf1365c
DF
16 */
17
18#ifndef lint
19char copyright[] =
704aadd2 20"@(#) Copyright (c) 1980 The Regents of the University of California.\n\
bcf1365c 21 All rights reserved.\n";
7e8aa4e0 22#endif /* not lint */
bcf1365c 23
97dd7000 24#ifndef lint
439847aa 25static char sccsid[] = "@(#)df.c 5.9 (Berkeley) %G%";
7e8aa4e0 26#endif /* not lint */
a98f5f82 27
8d335f7d
BJ
28/*
29 * df
30 */
704aadd2
KM
31#include <stdio.h>
32#include <sys/types.h>
1e568652 33#include <sys/stat.h>
704aadd2
KM
34#include <sys/mount.h>
35#include "pathnames.h"
c7b72342 36
1e568652 37char *getmntpt();
c7b72342 38int iflag;
704aadd2
KM
39#ifdef COMPAT_43
40int oflag;
41#endif /* COMPAT_43 */
c7b72342
BJ
42
43main(argc, argv)
a98f5f82
BJ
44 int argc;
45 char **argv;
c7b72342 46{
dbdc06d4
KB
47 extern int errno, optind;
48 int ch, i;
704aadd2 49 long mntsize;
1e568652
KM
50 char *mntpt;
51 struct stat stbuf;
704aadd2 52 struct statfs statfsbuf, *mntbuf;
439847aa 53 struct ufs_args mdev;
c7b72342 54
704aadd2 55 while ((ch = getopt(argc, argv, "io")) != EOF)
dbdc06d4 56 switch(ch) {
8a7d0cad
SL
57 case 'i':
58 iflag++;
59 break;
704aadd2
KM
60#ifdef COMPAT_43
61 case 'o':
62 oflag++;
63 break;
64#endif /* COMPAT_43 */
dbdc06d4 65 case '?':
8a7d0cad 66 default:
dbdc06d4
KB
67 fprintf(stderr, "usage: df [-i] [filsys ...]\n");
68 exit(1);
8a7d0cad 69 }
dbdc06d4
KB
70 argc -= optind;
71 argv += optind;
72
704aadd2
KM
73 printf("Filesystem kbytes used avail capacity");
74 if (iflag)
75 printf(" iused ifree %%iused");
76 printf(" Mounted on\n");
77#ifdef COMPAT_43
78 if (oflag) {
79 olddf(argv);
80 exit(0);
81 }
82#endif /* COMPAT_43 */
83 if (!*argv) {
1e568652 84 mntsize = getmntinfo(&mntbuf);
704aadd2
KM
85 for (i = 0; i < mntsize; i++)
86 prtstat(&mntbuf[i]);
87 exit(0);
88 }
89 for (; *argv; argv++) {
1e568652
KM
90 if (stat(*argv, &stbuf) < 0) {
91 if ((mntpt = getmntpt(*argv)) == 0)
92 continue;
93 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
94 if ((mntpt = getmntpt(*argv)) == 0)
439847aa
KM
95 mntpt = "/tmp/.mnt";
96 mdev.fspec = *argv;
97 if (!mkdir(mntpt) &&
98 !mount(MOUNT_UFS, mntpt, M_RDONLY, &mdev) &&
99 !statfs(mntpt, &statfsbuf)) {
100 statfsbuf.f_mntonname[0] = '\0';
101 prtstat(&statfsbuf);
102 } else {
103 perror(*argv);
104 }
105 umount(mntpt, MNT_NOFORCE);
106 rmdir(mntpt);
1e568652
KM
107 continue;
108 } else
109 mntpt = *argv;
110 if (statfs(mntpt, &statfsbuf) < 0) {
111 perror(mntpt);
704aadd2
KM
112 continue;
113 }
114 prtstat(&statfsbuf);
115 }
116 exit(0);
117}
118
1e568652
KM
119getmntinfo(mntbufp)
120 struct statfs **mntbufp;
121{
122 int i;
123 static long mntsize;
124 static struct statfs *mntbuf = 0;
125 char *malloc();
126
127 if (mntbuf) {
128 *mntbufp = mntbuf;
129 return (mntsize);
130 }
131 if ((mntsize = getfsstat((struct statfs *)0, 0)) < 0) {
132 perror("df");
133 exit(1);
134 }
135 mntbuf = 0;
136 do {
137 if (mntbuf)
138 free((char *)mntbuf);
139 i = (mntsize + 1) * sizeof(struct statfs);
140 if ((mntbuf = (struct statfs *)malloc((unsigned)i)) == 0) {
141 fprintf(stderr,
142 "no space for mount table buffer\n");
143 exit(1);
144 }
145 if ((mntsize = getfsstat(mntbuf, i)) < 0) {
146 perror("df");
147 exit(1);
148 }
149 } while (i == mntsize * sizeof(struct statfs));
150 *mntbufp = mntbuf;
151 return (mntsize);
152}
153
154char *
155getmntpt(name)
156 char *name;
157{
158 long mntsize, i;
159 struct statfs *mntbuf;
160
161 mntsize = getmntinfo(&mntbuf);
162 for (i = 0; i < mntsize; i++) {
163 if (!strcmp(mntbuf[i].f_mntfromname, name))
164 return (mntbuf[i].f_mntonname);
165 }
166 return (0);
167}
168
704aadd2
KM
169/*
170 * Print out status about a filesystem.
171 */
172prtstat(sfsp)
173 register struct statfs *sfsp;
174{
175 long used, availblks, inodes;
176
177 printf("%-12.12s", sfsp->f_mntfromname);
178 used = sfsp->f_blocks - sfsp->f_bfree;
179 availblks = sfsp->f_bavail + used;
180 printf("%8ld%8ld%8ld", sfsp->f_blocks * sfsp->f_fsize / 1024,
181 used * sfsp->f_fsize / 1024, sfsp->f_bavail * sfsp->f_fsize / 1024);
182 printf("%6.0f%%",
183 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
184 if (iflag) {
185 inodes = sfsp->f_files;
186 used = inodes - sfsp->f_ffree;
187 printf("%8ld%8ld%6.0f%% ", used, sfsp->f_ffree,
188 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
189 } else
190 printf(" ");
191 printf(" %s\n", sfsp->f_mntonname);
192}
193
194#ifdef COMPAT_43
195/*
196 * This code constitutes the old df code for extracting
197 * information from filesystem superblocks.
198 */
199#include <sys/param.h>
200#include <ufs/fs.h>
704aadd2
KM
201#include <errno.h>
202#include <fstab.h>
704aadd2 203
704aadd2 204char root[32];
704aadd2
KM
205
206union {
207 struct fs iu_fs;
208 char dummy[SBSIZE];
209} sb;
210#define sblock sb.iu_fs
211
212int fi;
213char *strcpy();
214
215olddf(argv)
216 char *argv[];
217{
218 struct fstab *fsp;
219 char *strerror();
704aadd2 220
dda19894 221 sync();
dbdc06d4 222 if (!*argv) {
8d335f7d 223 if (setfsent() == 0)
3b72df1c 224 perror(_PATH_FSTAB), exit(1);
a98f5f82 225 while (fsp = getfsent()) {
1f65a82f 226 if (strcmp(fsp->fs_type, FSTAB_RW) &&
351ef297
SL
227 strcmp(fsp->fs_type, FSTAB_RO) &&
228 strcmp(fsp->fs_type, FSTAB_RQ))
f0861f40 229 continue;
c7b72342 230 if (root[0] == 0)
f4d092e2 231 (void) strcpy(root, fsp->fs_spec);
a98f5f82 232 dfree(fsp->fs_spec, 1);
c7b72342 233 }
6c5c8ac3 234 (void)endfsent();
c7b72342
BJ
235 exit(0);
236 }
dbdc06d4
KB
237 while (*argv)
238 dfree(*argv++, 0);
704aadd2 239 exit(0);
c7b72342
BJ
240}
241
a98f5f82
BJ
242dfree(file, infsent)
243 char *file;
244 int infsent;
c7b72342 245{
dbdc06d4 246 extern int errno;
a98f5f82 247 struct stat stbuf;
704aadd2
KM
248 struct statfs statfsbuf;
249 register struct statfs *sfsp;
a98f5f82 250 struct fstab *fsp;
1e568652 251 char *mntpt, *strerror();
a98f5f82
BJ
252
253 if (stat(file, &stbuf) == 0 &&
254 (stbuf.st_mode&S_IFMT) != S_IFCHR &&
255 (stbuf.st_mode&S_IFMT) != S_IFBLK) {
256 if (infsent) {
f6c7ec9d 257 fprintf(stderr, "%s: screwy fstab entry\n", file);
8d335f7d
BJ
258 return;
259 }
6c5c8ac3 260 (void)setfsent();
a98f5f82
BJ
261 while (fsp = getfsent()) {
262 struct stat stb;
263
264 if (stat(fsp->fs_spec, &stb) == 0 &&
265 stb.st_rdev == stbuf.st_dev) {
266 file = fsp->fs_spec;
6c5c8ac3 267 (void)endfsent();
a98f5f82
BJ
268 goto found;
269 }
270 }
6c5c8ac3 271 (void)endfsent();
a98f5f82
BJ
272 fprintf(stderr, "%s: mounted on unknown device\n", file);
273 return;
8d335f7d 274 }
a98f5f82 275found:
dbdc06d4
KB
276 if ((fi = open(file, 0)) < 0) {
277 fprintf(stderr, "df: %s: %s\n", file, strerror(errno));
c7b72342
BJ
278 return;
279 }
6c5c8ac3 280 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) {
f5064bf4
RC
281 (void) close(fi);
282 return;
283 }
704aadd2
KM
284 sfsp = &statfsbuf;
285 sfsp->f_type = MOUNT_UFS;
286 sfsp->f_flags = 0;
287 sfsp->f_fsize = sblock.fs_fsize;
288 sfsp->f_bsize = sblock.fs_bsize;
289 sfsp->f_blocks = sblock.fs_dsize;
290 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
291 sblock.fs_cstotal.cs_nffree;
292 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) -
293 (sblock.fs_dsize - sfsp->f_bfree);
294 if (sfsp->f_bavail < 0)
295 sfsp->f_bavail = 0;
296 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg;
297 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree;
298 sfsp->f_fsid.val[0] = 0;
299 sfsp->f_fsid.val[1] = 0;
1e568652
KM
300 if ((mntpt = getmntpt(file)) == 0)
301 mntpt = "";
302 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN);
704aadd2
KM
303 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN);
304 prtstat(sfsp);
f4d092e2 305 (void) close(fi);
c7b72342
BJ
306}
307
f4d092e2
KM
308long lseek();
309
6c5c8ac3
KM
310bread(off, buf, cnt)
311 long off;
a98f5f82 312 char *buf;
c7b72342
BJ
313{
314 int n;
315 extern errno;
316
6c5c8ac3 317 (void) lseek(fi, off, 0);
a98f5f82 318 if ((n=read(fi, buf, cnt)) != cnt) {
f5064bf4
RC
319 /* probably a dismounted disk if errno == EIO */
320 if (errno != EIO) {
6c5c8ac3 321 printf("\nread error off = %ld\n", off);
f5064bf4
RC
322 printf("count = %d; errno = %d\n", n, errno);
323 }
324 return (0);
c7b72342 325 }
f5064bf4 326 return (1);
c7b72342 327}
704aadd2 328#endif /* COMPAT_43 */