386BSD 0.0 development
[unix-history] / usr / src / bin / df / df.c
CommitLineData
a2d188f4
WJ
1/*
2 * Copyright (c) 1980, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1980, 1990 The Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)df.c 5.24 (Berkeley) 3/6/91";
42#endif /* not lint */
43
44/*
45 * df
46 */
47#include <sys/param.h>
48#include <sys/stat.h>
49#include <sys/mount.h>
50#include <fcntl.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <unistd.h>
55
56char *getmntpt();
57void ufs_df(), prtstat();
58int iflag, kflag, nflag;
59struct ufs_args mdev;
60
61int
62main(argc, argv)
63 int argc;
64 char **argv;
65{
66 extern int errno, optind;
67 int err, ch, i;
68 long width, maxwidth, mntsize;
69 char *mntpt, *mktemp();
70 struct stat stbuf;
71 struct statfs statfsbuf, *mntbuf;
72
73 while ((ch = getopt(argc, argv, "ikn")) != EOF)
74 switch(ch) {
75 case 'i':
76 iflag = 1;
77 break;
78 case 'k':
79 kflag = 1;
80 break;
81 case 'n':
82 nflag = 1;
83 break;
84 case '?':
85 default:
86 fprintf(stderr,
87 "usage: df [-ikn] [file | file_system ...]\n");
88 exit(1);
89 }
90 argc -= optind;
91 argv += optind;
92
93 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
94 maxwidth = 0;
95 for (i = 0; i < mntsize; i++) {
96 width = strlen(mntbuf[i].f_mntfromname);
97 if (width > maxwidth)
98 maxwidth = width;
99 }
100 if (!*argv) {
101 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT));
102 for (i = 0; i < mntsize; i++)
103 prtstat(&mntbuf[i], maxwidth);
104 exit(0);
105 }
106 for (; *argv; argv++) {
107 if (stat(*argv, &stbuf) < 0) {
108 err = errno;
109 if ((mntpt = getmntpt(*argv)) == 0) {
110 fprintf(stderr, "df: %s: %s\n", *argv,
111 strerror(err));
112 continue;
113 }
114 } else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
115 ufs_df(*argv, maxwidth);
116 continue;
117 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
118 if ((mntpt = getmntpt(*argv)) == 0) {
119 mntpt = mktemp(strdup("/tmp/df.XXXXXX"));
120 mdev.fspec = *argv;
121 if (mkdir(mntpt, DEFFILEMODE) != 0) {
122 fprintf(stderr, "df: %s: %s\n",
123 mntpt, strerror(errno));
124 continue;
125 }
126 if (mount(MOUNT_UFS, mntpt, MNT_RDONLY,
127 &mdev) != 0) {
128 ufs_df(*argv, maxwidth);
129 (void)rmdir(mntpt);
130 continue;
131 } else if (statfs(mntpt, &statfsbuf)) {
132 statfsbuf.f_mntonname[0] = '\0';
133 prtstat(&statfsbuf, maxwidth);
134 } else
135 fprintf(stderr, "df: %s: %s\n",
136 *argv, strerror(errno));
137 (void)unmount(mntpt, MNT_NOFORCE);
138 (void)rmdir(mntpt);
139 continue;
140 }
141 } else
142 mntpt = *argv;
143 /*
144 * Statfs does not take a `wait' flag, so we cannot
145 * implement nflag here.
146 */
147 if (statfs(mntpt, &statfsbuf) < 0) {
148 fprintf(stderr,
149 "df: %s: %s\n", mntpt, strerror(errno));
150 continue;
151 }
152 if (argc == 1)
153 maxwidth = strlen(statfsbuf.f_mntfromname) + 1;
154 prtstat(&statfsbuf, maxwidth);
155 }
156 return (0);
157}
158
159char *
160getmntpt(name)
161 char *name;
162{
163 long mntsize, i;
164 struct statfs *mntbuf;
165
166 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT));
167 for (i = 0; i < mntsize; i++) {
168 if (!strcmp(mntbuf[i].f_mntfromname, name))
169 return (mntbuf[i].f_mntonname);
170 }
171 return (0);
172}
173
174/*
175 * Print out status about a filesystem.
176 */
177void
178prtstat(sfsp, maxwidth)
179 register struct statfs *sfsp;
180 long maxwidth;
181{
182 long used, availblks, inodes;
183 static int timesthrough;
184
185 if (maxwidth < 11)
186 maxwidth = 11;
187 if (++timesthrough == 1) {
188 printf("%-*.*s%s used avail capacity",
189 maxwidth, maxwidth, "Filesystem",
190 kflag ? " kbytes" : "512-blks");
191 if (iflag)
192 printf(" iused ifree %%iused");
193 printf(" Mounted on\n");
194 }
195 printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
196 used = sfsp->f_blocks - sfsp->f_bfree;
197 availblks = sfsp->f_bavail + used;
198 printf("%8ld%8ld%8ld",
199 sfsp->f_blocks * sfsp->f_fsize / (kflag ? 1024 : 512),
200 used * sfsp->f_fsize / (kflag ? 1024 : 512),
201 sfsp->f_bavail * sfsp->f_fsize / (kflag ? 1024 : 512));
202 printf("%6.0f%%",
203 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
204 if (iflag) {
205 inodes = sfsp->f_files;
206 used = inodes - sfsp->f_ffree;
207 printf("%8ld%8ld%6.0f%% ", used, sfsp->f_ffree,
208 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
209 } else
210 printf(" ");
211 printf(" %s\n", sfsp->f_mntonname);
212}
213
214/*
215 * This code constitutes the old df code for extracting
216 * information from filesystem superblocks.
217 */
218#include <ufs/fs.h>
219#include <errno.h>
220#include <fstab.h>
221
222union {
223 struct fs iu_fs;
224 char dummy[SBSIZE];
225} sb;
226#define sblock sb.iu_fs
227
228int fi;
229int bread();
230
231void
232ufs_df(file, maxwidth)
233 char *file;
234 long maxwidth;
235{
236 extern int errno;
237 struct statfs statfsbuf;
238 register struct statfs *sfsp;
239 char *mntpt;
240 static int synced;
241
242 if (synced++ == 0)
243 sync();
244
245 if ((fi = open(file, O_RDONLY)) < 0) {
246 fprintf(stderr, "df: %s: %s\n", file, strerror(errno));
247 return;
248 }
249 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) {
250 (void) close(fi);
251 return;
252 }
253 sfsp = &statfsbuf;
254 sfsp->f_type = MOUNT_UFS;
255 sfsp->f_flags = 0;
256 sfsp->f_fsize = sblock.fs_fsize;
257 sfsp->f_bsize = sblock.fs_bsize;
258 sfsp->f_blocks = sblock.fs_dsize;
259 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
260 sblock.fs_cstotal.cs_nffree;
261 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) -
262 (sblock.fs_dsize - sfsp->f_bfree);
263 if (sfsp->f_bavail < 0)
264 sfsp->f_bavail = 0;
265 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg;
266 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree;
267 sfsp->f_fsid.val[0] = 0;
268 sfsp->f_fsid.val[1] = 0;
269 if ((mntpt = getmntpt(file)) == 0)
270 mntpt = "";
271 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN);
272 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN);
273 prtstat(sfsp, maxwidth);
274 (void) close(fi);
275}
276
277long lseek();
278
279int
280bread(off, buf, cnt)
281 long off;
282 char *buf;
283 int cnt;
284{
285 int n;
286 extern errno;
287
288 (void) lseek(fi, off, SEEK_SET);
289 if ((n=read(fi, buf, cnt)) != cnt) {
290 /* probably a dismounted disk if errno == EIO */
291 if (errno != EIO) {
292 printf("\nread error off = %ld\n", off);
293 printf("count = %d; errno = %d\n", n, errno);
294 }
295 return (0);
296 }
297 return (1);
298}