| Commit | Line | Data |
|---|---|---|
| 984263bc MD |
1 | /* |
| 2 | * Copyright (c) 1980, 1990, 1993, 1994 | |
| 3 | * The Regents of the University of California. All rights reserved. | |
| 4 | * (c) UNIX System Laboratories, Inc. | |
| 5 | * All or some portions of this file are derived from material licensed | |
| 6 | * to the University of California by American Telephone and Telegraph | |
| 7 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | |
| 8 | * the permission of UNIX System Laboratories, Inc. | |
| 9 | * | |
| 10 | * Redistribution and use in source and binary forms, with or without | |
| 11 | * modification, are permitted provided that the following conditions | |
| 12 | * are met: | |
| 13 | * 1. Redistributions of source code must retain the above copyright | |
| 14 | * notice, this list of conditions and the following disclaimer. | |
| 15 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 16 | * notice, this list of conditions and the following disclaimer in the | |
| 17 | * documentation and/or other materials provided with the distribution. | |
| 18 | * 3. All advertising materials mentioning features or use of this software | |
| 19 | * must display the following acknowledgement: | |
| 20 | * This product includes software developed by the University of | |
| 21 | * California, Berkeley and its contributors. | |
| 22 | * 4. Neither the name of the University nor the names of its contributors | |
| 23 | * may be used to endorse or promote products derived from this software | |
| 24 | * without specific prior written permission. | |
| 25 | * | |
| 26 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| 27 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| 30 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 31 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 32 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 33 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 34 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 35 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 36 | * SUCH DAMAGE. | |
| 1de703da MD |
37 | * |
| 38 | * @(#) Copyright (c) 1980, 1990, 1993, 1994 The Regents of the University of California. All rights reserved. | |
| 39 | * @(#)df.c 8.9 (Berkeley) 5/8/95 | |
| 40 | * $FreeBSD: src/bin/df/df.c,v 1.23.2.9 2002/07/01 00:14:24 iedowse Exp $ | |
| 984263bc MD |
41 | */ |
| 42 | ||
| 984263bc MD |
43 | #include <sys/param.h> |
| 44 | #include <sys/stat.h> | |
| 45 | #include <sys/mount.h> | |
| 46 | #include <sys/sysctl.h> | |
| 799e4f0b | 47 | #include <sys/statvfs.h> |
| 67ad9090 MD |
48 | |
| 49 | #include <vfs/ufs/dinode.h> | |
| 38a690d7 | 50 | #include <vfs/ufs/fs.h> |
| 67ad9090 | 51 | #include <vfs/ufs/ufsmount.h> |
| 984263bc MD |
52 | |
| 53 | #include <err.h> | |
| 54 | #include <errno.h> | |
| 55 | #include <fcntl.h> | |
| 56 | #include <fstab.h> | |
| da3084db | 57 | #include <libutil.h> |
| 984263bc MD |
58 | #include <stdio.h> |
| 59 | #include <stdlib.h> | |
| 60 | #include <string.h> | |
| 61 | #include <sysexits.h> | |
| 62 | #include <unistd.h> | |
| 63 | ||
| 64 | #define UNITS_SI 1 | |
| 65 | #define UNITS_2 2 | |
| 66 | ||
| 984263bc MD |
67 | /* Maximum widths of various fields. */ |
| 68 | struct maxwidths { | |
| 69 | int mntfrom; | |
| 70 | int total; | |
| 71 | int used; | |
| 72 | int avail; | |
| 73 | int iused; | |
| 74 | int ifree; | |
| 75 | }; | |
| 76 | ||
| 984263bc MD |
77 | int bread(off_t, void *, int); |
| 78 | int checkvfsname(const char *, char **); | |
| 79 | char *getmntpt(char *); | |
| 799e4f0b | 80 | int quadwidth(int64_t); |
| 984263bc MD |
81 | char *makenetvfslist(void); |
| 82 | char **makevfslist(char *); | |
| 4b378413 | 83 | void prthuman(struct statvfs *, int64_t); |
| da3084db | 84 | void prthumanval(int64_t); |
| 799e4f0b MD |
85 | void prtstat(struct statfs *, struct statvfs *, struct maxwidths *); |
| 86 | long regetmntinfo(struct statfs **, struct statvfs **, long, char **); | |
| 984263bc | 87 | int ufs_df(char *, struct maxwidths *); |
| 799e4f0b | 88 | void update_maxwidths(struct maxwidths *, struct statfs *, struct statvfs *); |
| 984263bc MD |
89 | void usage(void); |
| 90 | ||
| 91 | int aflag = 0, hflag, iflag, nflag; | |
| 92 | struct ufs_args mdev; | |
| 93 | ||
| 1f0f7b35 SW |
94 | static __inline int |
| 95 | imax(int a, int b) | |
| 984263bc MD |
96 | { |
| 97 | return (a > b ? a : b); | |
| 98 | } | |
| 99 | ||
| 799e4f0b MD |
100 | static __inline int64_t |
| 101 | qmax(int64_t a, int64_t b) | |
| 102 | { | |
| 103 | return (a > b ? a : b); | |
| 104 | } | |
| 105 | ||
| 984263bc | 106 | int |
| b5744197 | 107 | main(int argc, char **argv) |
| 984263bc MD |
108 | { |
| 109 | struct stat stbuf; | |
| 110 | struct statfs statfsbuf, *mntbuf; | |
| 799e4f0b | 111 | struct statvfs statvfsbuf, *mntvbuf; |
| 984263bc MD |
112 | struct maxwidths maxwidths; |
| 113 | const char *fstype; | |
| 114 | char *mntpath, *mntpt, **vfslist; | |
| 115 | long mntsize; | |
| 116 | int ch, i, rv; | |
| 117 | ||
| 118 | fstype = "ufs"; | |
| 119 | ||
| 120 | vfslist = NULL; | |
| 121 | while ((ch = getopt(argc, argv, "abgHhiklmnPt:")) != -1) | |
| 122 | switch (ch) { | |
| 123 | case 'a': | |
| 124 | aflag = 1; | |
| 125 | break; | |
| 126 | case 'b': | |
| 127 | /* FALLTHROUGH */ | |
| 128 | case 'P': | |
| 5d0641a4 PA |
129 | if (setenv("BLOCKSIZE", "512", 1) != 0) |
| 130 | warn("setenv: cannot set BLOCKSIZE=512"); | |
| 984263bc MD |
131 | hflag = 0; |
| 132 | break; | |
| 133 | case 'g': | |
| 5d0641a4 PA |
134 | if (setenv("BLOCKSIZE", "1g", 1) != 0) |
| 135 | warn("setenv: cannot set BLOCKSIZE=1g"); | |
| 984263bc MD |
136 | hflag = 0; |
| 137 | break; | |
| 138 | case 'H': | |
| 139 | hflag = UNITS_SI; | |
| 984263bc MD |
140 | break; |
| 141 | case 'h': | |
| 142 | hflag = UNITS_2; | |
| 984263bc MD |
143 | break; |
| 144 | case 'i': | |
| 145 | iflag = 1; | |
| 146 | break; | |
| 147 | case 'k': | |
| 5d0641a4 PA |
148 | if (setenv("BLOCKSIZE", "1k", 1) != 0) |
| 149 | warn("setenv: cannot set BLOCKSIZE=1k"); | |
| 984263bc MD |
150 | hflag = 0; |
| 151 | break; | |
| 152 | case 'l': | |
| 153 | if (vfslist != NULL) | |
| 154 | errx(1, "-l and -t are mutually exclusive."); | |
| 155 | vfslist = makevfslist(makenetvfslist()); | |
| 156 | break; | |
| 157 | case 'm': | |
| 5d0641a4 PA |
158 | if (setenv("BLOCKSIZE", "1m", 1) != 0) |
| 159 | warn("setenv: cannot set BLOCKSIZE=1m"); | |
| 984263bc MD |
160 | hflag = 0; |
| 161 | break; | |
| 162 | case 'n': | |
| 163 | nflag = 1; | |
| 164 | break; | |
| 165 | case 't': | |
| 166 | if (vfslist != NULL) | |
| 167 | errx(1, "only one -t option may be specified"); | |
| 168 | fstype = optarg; | |
| 169 | vfslist = makevfslist(optarg); | |
| 170 | break; | |
| 171 | case '?': | |
| 172 | default: | |
| 173 | usage(); | |
| 174 | } | |
| 175 | argc -= optind; | |
| 176 | argv += optind; | |
| 177 | ||
| 799e4f0b | 178 | mntsize = getmntvinfo(&mntbuf, &mntvbuf, MNT_NOWAIT); |
| 984263bc MD |
179 | bzero(&maxwidths, sizeof(maxwidths)); |
| 180 | for (i = 0; i < mntsize; i++) | |
| 799e4f0b | 181 | update_maxwidths(&maxwidths, &mntbuf[i], &mntvbuf[i]); |
| 984263bc MD |
182 | |
| 183 | rv = 0; | |
| 184 | if (!*argv) { | |
| 799e4f0b | 185 | mntsize = regetmntinfo(&mntbuf, &mntvbuf, mntsize, vfslist); |
| 984263bc MD |
186 | bzero(&maxwidths, sizeof(maxwidths)); |
| 187 | for (i = 0; i < mntsize; i++) | |
| 799e4f0b | 188 | update_maxwidths(&maxwidths, &mntbuf[i], &mntvbuf[i]); |
| 984263bc MD |
189 | for (i = 0; i < mntsize; i++) { |
| 190 | if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) | |
| 799e4f0b | 191 | prtstat(&mntbuf[i], &mntvbuf[i], &maxwidths); |
| 984263bc MD |
192 | } |
| 193 | exit(rv); | |
| 194 | } | |
| 195 | ||
| 196 | for (; *argv; argv++) { | |
| 197 | if (stat(*argv, &stbuf) < 0) { | |
| 678e8cc6 | 198 | if ((mntpt = getmntpt(*argv)) == NULL) { |
| 984263bc MD |
199 | warn("%s", *argv); |
| 200 | rv = 1; | |
| 201 | continue; | |
| 202 | } | |
| 203 | } else if (S_ISCHR(stbuf.st_mode)) { | |
| 678e8cc6 | 204 | if ((mntpt = getmntpt(*argv)) == NULL) { |
| 984263bc MD |
205 | mdev.fspec = *argv; |
| 206 | mntpath = strdup("/tmp/df.XXXXXX"); | |
| 207 | if (mntpath == NULL) { | |
| 208 | warn("strdup failed"); | |
| 209 | rv = 1; | |
| 210 | continue; | |
| 211 | } | |
| 212 | mntpt = mkdtemp(mntpath); | |
| 213 | if (mntpt == NULL) { | |
| 214 | warn("mkdtemp(\"%s\") failed", mntpath); | |
| 215 | rv = 1; | |
| 216 | free(mntpath); | |
| 217 | continue; | |
| 218 | } | |
| 219 | if (mount(fstype, mntpt, MNT_RDONLY, | |
| 220 | &mdev) != 0) { | |
| 221 | rv = ufs_df(*argv, &maxwidths) || rv; | |
| 57fed2af | 222 | rmdir(mntpt); |
| 984263bc MD |
223 | free(mntpath); |
| 224 | continue; | |
| 799e4f0b MD |
225 | } else if (statfs(mntpt, &statfsbuf) == 0 && |
| 226 | statvfs(mntpt, &statvfsbuf) == 0) { | |
| 984263bc | 227 | statfsbuf.f_mntonname[0] = '\0'; |
| 799e4f0b | 228 | prtstat(&statfsbuf, &statvfsbuf, &maxwidths); |
| 984263bc MD |
229 | } else { |
| 230 | warn("%s", *argv); | |
| 231 | rv = 1; | |
| 232 | } | |
| 57fed2af EN |
233 | unmount(mntpt, 0); |
| 234 | rmdir(mntpt); | |
| 984263bc MD |
235 | free(mntpath); |
| 236 | continue; | |
| 237 | } | |
| 238 | } else | |
| 239 | mntpt = *argv; | |
| 240 | /* | |
| 241 | * Statfs does not take a `wait' flag, so we cannot | |
| 242 | * implement nflag here. | |
| 243 | */ | |
| 244 | if (statfs(mntpt, &statfsbuf) < 0) { | |
| 245 | warn("%s", mntpt); | |
| 246 | rv = 1; | |
| 247 | continue; | |
| 248 | } | |
| 799e4f0b MD |
249 | if (statvfs(mntpt, &statvfsbuf) < 0) { |
| 250 | warn("%s", mntpt); | |
| 251 | rv = 1; | |
| 252 | continue; | |
| 253 | } | |
| 0d0db296 AHJ |
254 | /* |
| 255 | * Check to make sure the arguments we've been given are | |
| 256 | * satisfied. Return an error if we have been asked to | |
| 257 | * list a mount point that does not match the other args | |
| 258 | * we've been given (-l, -t, etc.). | |
| 259 | */ | |
| 260 | if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { | |
| 966d637c SW |
261 | rv = 1; |
| 262 | continue; | |
| 0d0db296 AHJ |
263 | } |
| 264 | ||
| 984263bc MD |
265 | if (argc == 1) { |
| 266 | bzero(&maxwidths, sizeof(maxwidths)); | |
| 799e4f0b | 267 | update_maxwidths(&maxwidths, &statfsbuf, &statvfsbuf); |
| 984263bc | 268 | } |
| 799e4f0b | 269 | prtstat(&statfsbuf, &statvfsbuf, &maxwidths); |
| 984263bc MD |
270 | } |
| 271 | return (rv); | |
| 272 | } | |
| 273 | ||
| 274 | char * | |
| 275 | getmntpt(char *name) | |
| 276 | { | |
| 277 | long mntsize, i; | |
| 278 | struct statfs *mntbuf; | |
| 799e4f0b | 279 | struct statvfs *mntvbuf; |
| 984263bc | 280 | |
| 799e4f0b | 281 | mntsize = getmntvinfo(&mntbuf, &mntvbuf, MNT_NOWAIT); |
| 984263bc MD |
282 | for (i = 0; i < mntsize; i++) { |
| 283 | if (!strcmp(mntbuf[i].f_mntfromname, name)) | |
| 284 | return (mntbuf[i].f_mntonname); | |
| 285 | } | |
| 286 | return (0); | |
| 287 | } | |
| 288 | ||
| 289 | /* | |
| 290 | * Make a pass over the filesystem info in ``mntbuf'' filtering out | |
| 291 | * filesystem types not in vfslist and possibly re-stating to get | |
| 292 | * current (not cached) info. Returns the new count of valid statfs bufs. | |
| 293 | */ | |
| 294 | long | |
| 799e4f0b | 295 | regetmntinfo(struct statfs **mntbufp, struct statvfs **mntvbufp, long mntsize, char **vfslist) |
| 984263bc MD |
296 | { |
| 297 | int i, j; | |
| 298 | struct statfs *mntbuf; | |
| 799e4f0b | 299 | struct statvfs *mntvbuf; |
| 984263bc MD |
300 | |
| 301 | if (vfslist == NULL) | |
| 799e4f0b | 302 | return (nflag ? mntsize : getmntvinfo(mntbufp, mntvbufp, MNT_WAIT)); |
| 984263bc MD |
303 | |
| 304 | mntbuf = *mntbufp; | |
| 799e4f0b | 305 | mntvbuf = *mntvbufp; |
| 984263bc MD |
306 | for (j = 0, i = 0; i < mntsize; i++) { |
| 307 | if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) | |
| 308 | continue; | |
| 799e4f0b | 309 | if (!nflag) { |
| 57fed2af | 310 | statfs(mntbuf[i].f_mntonname,&mntbuf[j]); |
| 799e4f0b MD |
311 | statvfs(mntbuf[i].f_mntonname,&mntvbuf[j]); |
| 312 | } else if (i != j) { | |
| 984263bc | 313 | mntbuf[j] = mntbuf[i]; |
| 799e4f0b MD |
314 | mntvbuf[j] = mntvbuf[i]; |
| 315 | } | |
| 984263bc MD |
316 | j++; |
| 317 | } | |
| 318 | return (j); | |
| 319 | } | |
| 320 | ||
| 984263bc | 321 | void |
| 4b378413 | 322 | prthuman(struct statvfs *vsfsp, int64_t used) |
| 984263bc | 323 | { |
| da3084db SW |
324 | prthumanval(vsfsp->f_blocks * vsfsp->f_bsize); |
| 325 | prthumanval(used * vsfsp->f_bsize); | |
| 326 | prthumanval(vsfsp->f_bavail * vsfsp->f_bsize); | |
| 984263bc MD |
327 | } |
| 328 | ||
| 329 | void | |
| da3084db | 330 | prthumanval(int64_t bytes) |
| 984263bc | 331 | { |
| da3084db SW |
332 | char buf[6]; |
| 333 | int flags; | |
| 334 | ||
| 335 | flags = HN_B | HN_NOSPACE | HN_DECIMAL; | |
| 336 | if (hflag == UNITS_SI) | |
| 337 | flags |= HN_DIVISOR_1000; | |
| 984263bc | 338 | |
| da3084db SW |
339 | humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), |
| 340 | bytes, "", HN_AUTOSCALE, flags); | |
| 984263bc | 341 | |
| da3084db | 342 | printf(" %6s", buf); |
| 984263bc MD |
343 | } |
| 344 | ||
| 345 | /* | |
| 346 | * Convert statfs returned filesystem size into BLOCKSIZE units. | |
| 347 | * Attempts to avoid overflow for large filesystems. | |
| 348 | */ | |
| 91a6f290 SW |
349 | static intmax_t |
| 350 | fsbtoblk(int64_t num, uint64_t bsize, u_long reqbsize) | |
| 799e4f0b | 351 | { |
| 91a6f290 SW |
352 | if (bsize != 0 && bsize < reqbsize) |
| 353 | return (num / (intmax_t)(reqbsize / bsize)); | |
| 799e4f0b | 354 | else |
| 91a6f290 | 355 | return (num * (intmax_t)(bsize / reqbsize)); |
| 799e4f0b | 356 | } |
| 984263bc MD |
357 | |
| 358 | /* | |
| 359 | * Print out status about a filesystem. | |
| 360 | */ | |
| 361 | void | |
| 799e4f0b | 362 | prtstat(struct statfs *sfsp, struct statvfs *vsfsp, struct maxwidths *mwp) |
| 984263bc MD |
363 | { |
| 364 | static long blocksize; | |
| 365 | static int headerlen, timesthrough; | |
| 366 | static const char *header; | |
| 799e4f0b | 367 | int64_t used, availblks, inodes; |
| 984263bc MD |
368 | |
| 369 | if (++timesthrough == 1) { | |
| 370 | mwp->mntfrom = imax(mwp->mntfrom, strlen("Filesystem")); | |
| 371 | if (hflag) { | |
| 372 | header = " Size"; | |
| 373 | mwp->total = mwp->used = mwp->avail = strlen(header); | |
| 374 | } else { | |
| 375 | header = getbsize(&headerlen, &blocksize); | |
| 376 | mwp->total = imax(mwp->total, headerlen); | |
| 377 | } | |
| 378 | mwp->used = imax(mwp->used, strlen("Used")); | |
| 379 | mwp->avail = imax(mwp->avail, strlen("Avail")); | |
| 380 | ||
| 57fed2af | 381 | printf("%-*s %-*s %*s %*s Capacity", mwp->mntfrom, |
| 984263bc MD |
382 | "Filesystem", mwp->total, header, mwp->used, "Used", |
| 383 | mwp->avail, "Avail"); | |
| 384 | if (iflag) { | |
| 385 | mwp->iused = imax(mwp->iused, strlen(" iused")); | |
| 386 | mwp->ifree = imax(mwp->ifree, strlen("ifree")); | |
| 57fed2af | 387 | printf(" %*s %*s %%iused", mwp->iused - 2, |
| 984263bc MD |
388 | "iused", mwp->ifree, "ifree"); |
| 389 | } | |
| 57fed2af | 390 | printf(" Mounted on\n"); |
| 984263bc | 391 | } |
| 57fed2af | 392 | printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname); |
| 799e4f0b MD |
393 | used = vsfsp->f_blocks - vsfsp->f_bfree; |
| 394 | availblks = vsfsp->f_bavail + used; | |
| 984263bc | 395 | if (hflag) { |
| 799e4f0b | 396 | prthuman(vsfsp, used); |
| 984263bc | 397 | } else { |
| 91a6f290 | 398 | printf(" %*jd %*jd %*jd", mwp->total, |
| 799e4f0b MD |
399 | fsbtoblk(vsfsp->f_blocks, vsfsp->f_bsize, blocksize), |
| 400 | mwp->used, fsbtoblk(used, vsfsp->f_bsize, blocksize), | |
| 401 | mwp->avail, fsbtoblk(vsfsp->f_bavail, vsfsp->f_bsize, | |
| 984263bc MD |
402 | blocksize)); |
| 403 | } | |
| 57fed2af | 404 | printf(" %5.0f%%", |
| 984263bc MD |
405 | availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); |
| 406 | if (iflag) { | |
| 799e4f0b MD |
407 | inodes = vsfsp->f_files; |
| 408 | used = inodes - vsfsp->f_ffree; | |
| 91a6f290 SW |
409 | printf(" %*jd %*jd %4.0f%% ", mwp->iused, (intmax_t)used, |
| 410 | mwp->ifree, (intmax_t)vsfsp->f_ffree, inodes == 0 ? 100.0 : | |
| 984263bc MD |
411 | (double)used / (double)inodes * 100.0); |
| 412 | } else | |
| 57fed2af EN |
413 | printf(" "); |
| 414 | printf(" %s\n", sfsp->f_mntonname); | |
| 984263bc MD |
415 | } |
| 416 | ||
| 417 | /* | |
| 418 | * Update the maximum field-width information in `mwp' based on | |
| 419 | * the filesystem specified by `sfsp'. | |
| 420 | */ | |
| 421 | void | |
| 799e4f0b | 422 | update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp, struct statvfs *vsfsp) |
| 984263bc MD |
423 | { |
| 424 | static long blocksize; | |
| 425 | int dummy; | |
| 426 | ||
| 427 | if (blocksize == 0) | |
| 428 | getbsize(&dummy, &blocksize); | |
| 429 | ||
| 430 | mwp->mntfrom = imax(mwp->mntfrom, strlen(sfsp->f_mntfromname)); | |
| 799e4f0b MD |
431 | mwp->total = imax(mwp->total, quadwidth(fsbtoblk(vsfsp->f_blocks, |
| 432 | vsfsp->f_bsize, blocksize))); | |
| 433 | mwp->used = imax(mwp->used, quadwidth(fsbtoblk(vsfsp->f_blocks - | |
| 434 | vsfsp->f_bfree, vsfsp->f_bsize, blocksize))); | |
| 435 | mwp->avail = imax(mwp->avail, quadwidth(fsbtoblk(vsfsp->f_bavail, | |
| 436 | vsfsp->f_bsize, blocksize))); | |
| 437 | mwp->iused = imax(mwp->iused, quadwidth(vsfsp->f_files - | |
| 438 | vsfsp->f_ffree)); | |
| 439 | mwp->ifree = imax(mwp->ifree, quadwidth(vsfsp->f_ffree)); | |
| 984263bc MD |
440 | } |
| 441 | ||
| 442 | /* Return the width in characters of the specified long. */ | |
| 443 | int | |
| 799e4f0b | 444 | quadwidth(int64_t val) |
| 984263bc MD |
445 | { |
| 446 | int len; | |
| 447 | ||
| 448 | len = 0; | |
| 449 | /* Negative or zero values require one extra digit. */ | |
| 450 | if (val <= 0) { | |
| 451 | val = -val; | |
| 452 | len++; | |
| 453 | } | |
| 454 | while (val > 0) { | |
| 455 | len++; | |
| 456 | val /= 10; | |
| 457 | } | |
| 984263bc MD |
458 | return (len); |
| 459 | } | |
| 460 | ||
| 461 | /* | |
| 462 | * This code constitutes the pre-system call Berkeley df code for extracting | |
| 463 | * information from filesystem superblocks. | |
| 464 | */ | |
| 465 | ||
| 466 | union { | |
| 467 | struct fs iu_fs; | |
| 468 | char dummy[SBSIZE]; | |
| 469 | } sb; | |
| 470 | #define sblock sb.iu_fs | |
| 471 | ||
| 472 | int rfd; | |
| 473 | ||
| 474 | int | |
| 475 | ufs_df(char *file, struct maxwidths *mwp) | |
| 476 | { | |
| 477 | struct statfs statfsbuf; | |
| 799e4f0b | 478 | struct statvfs statvfsbuf; |
| 984263bc | 479 | struct statfs *sfsp; |
| 799e4f0b | 480 | struct statvfs *vsfsp; |
| 984263bc MD |
481 | const char *mntpt; |
| 482 | static int synced; | |
| 483 | ||
| 484 | if (synced++ == 0) | |
| 485 | sync(); | |
| 486 | ||
| 487 | if ((rfd = open(file, O_RDONLY)) < 0) { | |
| 488 | warn("%s", file); | |
| 489 | return (1); | |
| 490 | } | |
| 491 | if (bread((off_t)SBOFF, &sblock, SBSIZE) == 0) { | |
| 57fed2af | 492 | close(rfd); |
| 984263bc MD |
493 | return (1); |
| 494 | } | |
| 495 | sfsp = &statfsbuf; | |
| 799e4f0b | 496 | vsfsp = &statvfsbuf; |
| 984263bc MD |
497 | sfsp->f_type = 1; |
| 498 | strcpy(sfsp->f_fstypename, "ufs"); | |
| 499 | sfsp->f_flags = 0; | |
| 799e4f0b MD |
500 | sfsp->f_bsize = vsfsp->f_bsize = sblock.fs_fsize; |
| 501 | sfsp->f_iosize = vsfsp->f_frsize = sblock.fs_bsize; | |
| 502 | sfsp->f_blocks = vsfsp->f_blocks = sblock.fs_dsize; | |
| 503 | sfsp->f_bfree = vsfsp->f_bfree = | |
| 504 | sblock.fs_cstotal.cs_nbfree * sblock.fs_frag + | |
| 984263bc | 505 | sblock.fs_cstotal.cs_nffree; |
| 799e4f0b MD |
506 | sfsp->f_bavail = vsfsp->f_bavail = freespace(&sblock, sblock.fs_minfree); |
| 507 | sfsp->f_files = vsfsp->f_files = sblock.fs_ncg * sblock.fs_ipg; | |
| 508 | sfsp->f_ffree = vsfsp->f_ffree = sblock.fs_cstotal.cs_nifree; | |
| 984263bc MD |
509 | sfsp->f_fsid.val[0] = 0; |
| 510 | sfsp->f_fsid.val[1] = 0; | |
| 678e8cc6 | 511 | if ((mntpt = getmntpt(file)) == NULL) |
| 984263bc MD |
512 | mntpt = ""; |
| 513 | memmove(&sfsp->f_mntonname[0], mntpt, (size_t)MNAMELEN); | |
| 514 | memmove(&sfsp->f_mntfromname[0], file, (size_t)MNAMELEN); | |
| 799e4f0b | 515 | prtstat(sfsp, vsfsp, mwp); |
| 57fed2af | 516 | close(rfd); |
| 984263bc MD |
517 | return (0); |
| 518 | } | |
| 519 | ||
| 520 | int | |
| 521 | bread(off_t off, void *buf, int cnt) | |
| 522 | { | |
| 523 | ssize_t nr; | |
| 524 | ||
| 57fed2af | 525 | lseek(rfd, off, SEEK_SET); |
| 984263bc MD |
526 | if ((nr = read(rfd, buf, (size_t)cnt)) != (ssize_t)cnt) { |
| 527 | /* Probably a dismounted disk if errno == EIO. */ | |
| 528 | if (errno != EIO) | |
| 57fed2af | 529 | fprintf(stderr, "\ndf: %lld: %s\n", |
| 984263bc MD |
530 | (long long)off, strerror(nr > 0 ? EIO : errno)); |
| 531 | return (0); | |
| 532 | } | |
| 533 | return (1); | |
| 534 | } | |
| 535 | ||
| 536 | void | |
| 537 | usage(void) | |
| 538 | { | |
| 539 | ||
| 57fed2af | 540 | fprintf(stderr, |
| 984263bc MD |
541 | "usage: df [-b | -H | -h | -k | -m | -P] [-ailn] [-t type] [file | filesystem ...]\n"); |
| 542 | exit(EX_USAGE); | |
| 543 | } | |
| 544 | ||
| 545 | char * | |
| 546 | makenetvfslist(void) | |
| 547 | { | |
| 548 | char *str, *strptr, **listptr; | |
| 549 | int mib[3], maxvfsconf, cnt=0, i; | |
| 550 | size_t miblen; | |
| 551 | struct ovfsconf *ptr; | |
| 552 | ||
| 553 | mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM; | |
| 554 | miblen=sizeof(maxvfsconf); | |
| 555 | if (sysctl(mib, (unsigned int)(sizeof(mib) / sizeof(mib[0])), | |
| 556 | &maxvfsconf, &miblen, NULL, 0)) { | |
| 557 | warnx("sysctl failed"); | |
| 558 | return (NULL); | |
| 559 | } | |
| 560 | ||
| 561 | if ((listptr = malloc(sizeof(char*) * maxvfsconf)) == NULL) { | |
| 562 | warnx("malloc failed"); | |
| 563 | return (NULL); | |
| 564 | } | |
| 565 | ||
| 566 | for (ptr = getvfsent(); ptr; ptr = getvfsent()) | |
| 567 | if (ptr->vfc_flags & VFCF_NETWORK) { | |
| 568 | listptr[cnt++] = strdup(ptr->vfc_name); | |
| 569 | if (listptr[cnt-1] == NULL) { | |
| 570 | warnx("malloc failed"); | |
| 571 | return (NULL); | |
| 572 | } | |
| 573 | } | |
| 574 | ||
| 575 | if (cnt == 0 || | |
| 576 | (str = malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) { | |
| 577 | if (cnt > 0) | |
| 578 | warnx("malloc failed"); | |
| 579 | free(listptr); | |
| 580 | return (NULL); | |
| 581 | } | |
| 582 | ||
| 583 | *str = 'n'; *(str + 1) = 'o'; | |
| 584 | for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) { | |
| 585 | strncpy(strptr, listptr[i], 32); | |
| 586 | strptr += strlen(listptr[i]); | |
| 587 | *strptr = ','; | |
| 588 | free(listptr[i]); | |
| 589 | } | |
| eecd52b2 | 590 | *(--strptr) = '\0'; |
| 984263bc MD |
591 | |
| 592 | free(listptr); | |
| 593 | return (str); | |
| 594 | } |