fts(3) updates
[unix-history] / bin / df / df.c
CommitLineData
15637ed4
RG
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
4e97a0eb 41static char sccsid[] = "@(#)df.c 5.30 (Berkeley) 4/23/92";
15637ed4
RG
42#endif /* not lint */
43
15637ed4
RG
44#include <sys/param.h>
45#include <sys/stat.h>
46#include <sys/mount.h>
4e97a0eb 47#include <errno.h>
15637ed4
RG
48#include <fcntl.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <unistd.h>
53
4e97a0eb
NW
54int bread __P((long, char *, int));
55char *getbsize __P((char *, int *, long *));
56char *getmntpt __P((char *));
57void prtstat __P((struct statfs *, long));
58void ufs_df __P((char *, long));
59void usage __P((void));
60
61int iflag, nflag;
15637ed4
RG
62struct ufs_args mdev;
63
64int
65main(argc, argv)
66 int argc;
4e97a0eb 67 char *argv[];
15637ed4 68{
15637ed4
RG
69 struct stat stbuf;
70 struct statfs statfsbuf, *mntbuf;
4e97a0eb
NW
71 long width, maxwidth, mntsize;
72 int err, ch, i;
73 char *mntpt;
15637ed4 74
4e97a0eb 75 while ((ch = getopt(argc, argv, "in")) != EOF)
15637ed4
RG
76 switch(ch) {
77 case 'i':
78 iflag = 1;
79 break;
15637ed4
RG
80 case 'n':
81 nflag = 1;
82 break;
83 case '?':
84 default:
4e97a0eb 85 usage();
15637ed4
RG
86 }
87 argc -= optind;
88 argv += optind;
89
90 mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
91 maxwidth = 0;
92 for (i = 0; i < mntsize; i++) {
93 width = strlen(mntbuf[i].f_mntfromname);
94 if (width > maxwidth)
95 maxwidth = width;
96 }
97 if (!*argv) {
98 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT));
99 for (i = 0; i < mntsize; i++)
100 prtstat(&mntbuf[i], maxwidth);
101 exit(0);
102 }
103 for (; *argv; argv++) {
104 if (stat(*argv, &stbuf) < 0) {
105 err = errno;
106 if ((mntpt = getmntpt(*argv)) == 0) {
107 fprintf(stderr, "df: %s: %s\n", *argv,
108 strerror(err));
109 continue;
110 }
111 } else if ((stbuf.st_mode & S_IFMT) == S_IFCHR) {
112 ufs_df(*argv, maxwidth);
113 continue;
114 } else if ((stbuf.st_mode & S_IFMT) == S_IFBLK) {
115 if ((mntpt = getmntpt(*argv)) == 0) {
116 mntpt = mktemp(strdup("/tmp/df.XXXXXX"));
117 mdev.fspec = *argv;
118 if (mkdir(mntpt, DEFFILEMODE) != 0) {
119 fprintf(stderr, "df: %s: %s\n",
120 mntpt, strerror(errno));
121 continue;
122 }
123 if (mount(MOUNT_UFS, mntpt, MNT_RDONLY,
124 &mdev) != 0) {
125 ufs_df(*argv, maxwidth);
126 (void)rmdir(mntpt);
127 continue;
128 } else if (statfs(mntpt, &statfsbuf)) {
129 statfsbuf.f_mntonname[0] = '\0';
130 prtstat(&statfsbuf, maxwidth);
131 } else
132 fprintf(stderr, "df: %s: %s\n",
133 *argv, strerror(errno));
134 (void)unmount(mntpt, MNT_NOFORCE);
135 (void)rmdir(mntpt);
136 continue;
137 }
138 } else
139 mntpt = *argv;
140 /*
141 * Statfs does not take a `wait' flag, so we cannot
142 * implement nflag here.
143 */
144 if (statfs(mntpt, &statfsbuf) < 0) {
145 fprintf(stderr,
146 "df: %s: %s\n", mntpt, strerror(errno));
147 continue;
148 }
149 if (argc == 1)
150 maxwidth = strlen(statfsbuf.f_mntfromname) + 1;
151 prtstat(&statfsbuf, maxwidth);
152 }
153 return (0);
154}
155
156char *
157getmntpt(name)
158 char *name;
159{
160 long mntsize, i;
161 struct statfs *mntbuf;
162
163 mntsize = getmntinfo(&mntbuf, (nflag ? MNT_NOWAIT : MNT_WAIT));
164 for (i = 0; i < mntsize; i++) {
165 if (!strcmp(mntbuf[i].f_mntfromname, name))
166 return (mntbuf[i].f_mntonname);
167 }
168 return (0);
169}
170
171/*
172 * Print out status about a filesystem.
173 */
174void
175prtstat(sfsp, maxwidth)
176 register struct statfs *sfsp;
177 long maxwidth;
178{
4e97a0eb
NW
179 static long blocksize;
180 static int headerlen, timesthrough;
181 static char *header;
15637ed4 182 long used, availblks, inodes;
15637ed4
RG
183
184 if (maxwidth < 11)
185 maxwidth = 11;
186 if (++timesthrough == 1) {
4e97a0eb
NW
187 header = getbsize("df", &headerlen, &blocksize);
188 (void)printf("%-*.*s %s Used Avail Capacity",
189 maxwidth, maxwidth, "Filesystem", header);
15637ed4 190 if (iflag)
4e97a0eb
NW
191 (void)printf(" iused ifree %%iused");
192 (void)printf(" Mounted on\n");
15637ed4 193 }
4e97a0eb 194 (void)printf("%-*.*s", maxwidth, maxwidth, sfsp->f_mntfromname);
15637ed4
RG
195 used = sfsp->f_blocks - sfsp->f_bfree;
196 availblks = sfsp->f_bavail + used;
4e97a0eb
NW
197 (void)printf(" %*ld %7ld %7ld", headerlen,
198 sfsp->f_blocks * sfsp->f_fsize / blocksize,
199 used * sfsp->f_fsize / blocksize,
200 sfsp->f_bavail * sfsp->f_fsize / blocksize);
201 (void)printf(" %5.0f%%",
15637ed4
RG
202 availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
203 if (iflag) {
204 inodes = sfsp->f_files;
205 used = inodes - sfsp->f_ffree;
4e97a0eb 206 (void)printf(" %7ld %7ld %5.0f%% ", used, sfsp->f_ffree,
15637ed4
RG
207 inodes == 0 ? 100.0 : (double)used / (double)inodes * 100.0);
208 } else
4e97a0eb
NW
209 (void)printf(" ");
210 (void)printf(" %s\n", sfsp->f_mntonname);
15637ed4
RG
211}
212
213/*
214 * This code constitutes the old df code for extracting
215 * information from filesystem superblocks.
216 */
217#include <ufs/fs.h>
218#include <errno.h>
219#include <fstab.h>
220
221union {
222 struct fs iu_fs;
223 char dummy[SBSIZE];
224} sb;
225#define sblock sb.iu_fs
226
227int fi;
15637ed4
RG
228
229void
230ufs_df(file, maxwidth)
231 char *file;
232 long maxwidth;
233{
15637ed4
RG
234 struct statfs statfsbuf;
235 register struct statfs *sfsp;
236 char *mntpt;
237 static int synced;
238
239 if (synced++ == 0)
240 sync();
241
242 if ((fi = open(file, O_RDONLY)) < 0) {
4e97a0eb 243 (void)fprintf(stderr, "df: %s: %s\n", file, strerror(errno));
15637ed4
RG
244 return;
245 }
246 if (bread((long)SBOFF, (char *)&sblock, SBSIZE) == 0) {
4e97a0eb 247 (void)close(fi);
15637ed4
RG
248 return;
249 }
250 sfsp = &statfsbuf;
251 sfsp->f_type = MOUNT_UFS;
252 sfsp->f_flags = 0;
4e97a0eb
NW
253 sfsp->f_bsize = sblock.fs_fsize;
254#ifdef notyet
255 sfsp->f_iosize = sblock.fs_bsize;
256#endif
15637ed4
RG
257 sfsp->f_blocks = sblock.fs_dsize;
258 sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
259 sblock.fs_cstotal.cs_nffree;
260 sfsp->f_bavail = (sblock.fs_dsize * (100 - sblock.fs_minfree) / 100) -
261 (sblock.fs_dsize - sfsp->f_bfree);
262 if (sfsp->f_bavail < 0)
263 sfsp->f_bavail = 0;
264 sfsp->f_files = sblock.fs_ncg * sblock.fs_ipg;
265 sfsp->f_ffree = sblock.fs_cstotal.cs_nifree;
266 sfsp->f_fsid.val[0] = 0;
267 sfsp->f_fsid.val[1] = 0;
268 if ((mntpt = getmntpt(file)) == 0)
269 mntpt = "";
270 bcopy((caddr_t)mntpt, (caddr_t)&sfsp->f_mntonname[0], MNAMELEN);
271 bcopy((caddr_t)file, (caddr_t)&sfsp->f_mntfromname[0], MNAMELEN);
272 prtstat(sfsp, maxwidth);
273 (void) close(fi);
274}
275
15637ed4
RG
276int
277bread(off, buf, cnt)
278 long off;
279 char *buf;
280 int cnt;
281{
282 int n;
15637ed4
RG
283
284 (void) lseek(fi, off, SEEK_SET);
285 if ((n=read(fi, buf, cnt)) != cnt) {
286 /* probably a dismounted disk if errno == EIO */
287 if (errno != EIO) {
4e97a0eb
NW
288 (void)printf("\nread error off = %ld\n", off);
289 (void)printf("count = %d: %s\n", n, strerror(errno));
15637ed4
RG
290 }
291 return (0);
292 }
293 return (1);
294}
4e97a0eb
NW
295
296void
297usage()
298{
299 (void)fprintf(stderr, "usage: df [-in] [file | file_system ...]\n");
300 exit(1);
301}