1139969Simp/*- 21556Srgrimes * Copyright (c) 1980, 1990, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * (c) UNIX System Laboratories, Inc. 51556Srgrimes * All or some portions of this file are derived from material licensed 61556Srgrimes * to the University of California by American Telephone and Telegraph 71556Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 81556Srgrimes * the permission of UNIX System Laboratories, Inc. 91556Srgrimes * 101556Srgrimes * Redistribution and use in source and binary forms, with or without 111556Srgrimes * modification, are permitted provided that the following conditions 121556Srgrimes * are met: 131556Srgrimes * 1. Redistributions of source code must retain the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer. 151556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161556Srgrimes * notice, this list of conditions and the following disclaimer in the 171556Srgrimes * documentation and/or other materials provided with the distribution. 181556Srgrimes * 4. Neither the name of the University nor the names of its contributors 191556Srgrimes * may be used to endorse or promote products derived from this software 201556Srgrimes * without specific prior written permission. 211556Srgrimes * 221556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 231556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 241556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 251556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 261556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 271556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 281556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 291556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 301556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 311556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 321556Srgrimes * SUCH DAMAGE. 331556Srgrimes */ 341556Srgrimes 35114433Sobrien#if 0 361556Srgrimes#ifndef lint 3727962Sstevestatic const char copyright[] = 381556Srgrimes"@(#) Copyright (c) 1980, 1990, 1993, 1994\n\ 391556Srgrimes The Regents of the University of California. All rights reserved.\n"; 401556Srgrimes#endif /* not lint */ 411556Srgrimes 421556Srgrimes#ifndef lint 4327962Sstevestatic char sccsid[] = "@(#)df.c 8.9 (Berkeley) 5/8/95"; 44114433Sobrien#endif /* not lint */ 4527962Ssteve#endif 4699109Sobrien#include <sys/cdefs.h> 4799109Sobrien__FBSDID("$FreeBSD: stable/10/bin/df/df.c 310380 2016-12-21 23:59:58Z brooks $"); 481556Srgrimes 491556Srgrimes#include <sys/param.h> 501556Srgrimes#include <sys/stat.h> 511556Srgrimes#include <sys/mount.h> 5277734Spirzyk#include <sys/sysctl.h> 53310380Sbrooks#ifdef MOUNT_CHAR_DEVS 5423852Sbde#include <ufs/ufs/ufsmount.h> 55310380Sbrooks#endif 561556Srgrimes#include <err.h> 57129678Spjd#include <libutil.h> 58243049Sgrog#include <locale.h> 59310380Sbrooks#ifdef MOUNT_CHAR_DEVS 60310380Sbrooks#include <mntopts.h> 61310380Sbrooks#endif 62125611Siedowse#include <stdint.h> 631556Srgrimes#include <stdio.h> 641556Srgrimes#include <stdlib.h> 651556Srgrimes#include <string.h> 6654621Smharo#include <sysexits.h> 671556Srgrimes#include <unistd.h> 681556Srgrimes 6996470Sphk#include "extern.h" 7096470Sphk 71129678Spjd#define UNITS_SI 1 72129678Spjd#define UNITS_2 2 7354621Smharo 7493246Siedowse/* Maximum widths of various fields. */ 7593246Siedowsestruct maxwidths { 76125611Siedowse int mntfrom; 77185200Spjd int fstype; 78125611Siedowse int total; 79125611Siedowse int used; 80125611Siedowse int avail; 81125611Siedowse int iused; 82125611Siedowse int ifree; 8393246Siedowse}; 8493246Siedowse 85128555Sobrienstatic void addstat(struct statfs *, struct statfs *); 86114579Smarkmstatic char *getmntpt(const char *); 87125611Siedowsestatic int int64width(int64_t); 8896470Sphkstatic char *makenetvfslist(void); 89122537Smckusickstatic void prthuman(const struct statfs *, int64_t); 90129678Spjdstatic void prthumanval(int64_t); 91130060Sdasstatic intmax_t fsbtoblk(int64_t, uint64_t, u_long); 9296470Sphkstatic void prtstat(struct statfs *, struct maxwidths *); 93120037Sobrienstatic size_t regetmntinfo(struct statfs **, long, const char **); 94114579Smarkmstatic void update_maxwidths(struct maxwidths *, const struct statfs *); 9596470Sphkstatic void usage(void); 961556Srgrimes 97125611Siedowsestatic __inline int 98125611Siedowseimax(int a, int b) 9993246Siedowse{ 100114579Smarkm return (a > b ? a : b); 10193246Siedowse} 10293246Siedowse 103185200Spjdstatic int aflag = 0, cflag, hflag, iflag, kflag, lflag = 0, nflag, Tflag; 104243049Sgrogstatic int thousands; 105310380Sbrooks#ifdef MOUNT_CHAR_DEVS 10696470Sphkstatic struct ufs_args mdev; 107310380Sbrooks#endif 10896470Sphk 1091556Srgrimesint 11090108Simpmain(int argc, char *argv[]) 1111556Srgrimes{ 1121556Srgrimes struct stat stbuf; 113128555Sobrien struct statfs statfsbuf, totalbuf; 11493246Siedowse struct maxwidths maxwidths; 115128555Sobrien struct statfs *mntbuf; 116310380Sbrooks#ifdef MOUNT_CHAR_DEVS 117310380Sbrooks struct iovec *iov = NULL; 118310380Sbrooks#endif 11976873Skris const char *fstype; 120310380Sbrooks#ifdef MOUNT_CHAR_DEVS 121310380Sbrooks char *mntpath; 122310380Sbrooks char errmsg[255] = {0}; 123310380Sbrooks#endif 124310380Sbrooks char *mntpt; 12596470Sphk const char **vfslist; 126226502Sdes int i, mntsize; 127120037Sobrien int ch, rv; 128310380Sbrooks#ifdef MOUNT_CHAR_DEVS 129310380Sbrooks int iovlen = 0; 130310380Sbrooks#endif 1311556Srgrimes 13276404Skris fstype = "ufs"; 133243049Sgrog (void)setlocale(LC_ALL, ""); 134249698Suqs memset(&maxwidths, 0, sizeof(maxwidths)); 135128555Sobrien memset(&totalbuf, 0, sizeof(totalbuf)); 136128410Sobrien totalbuf.f_bsize = DEV_BSIZE; 137161470Simp strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN); 13823852Sbde vfslist = NULL; 139243049Sgrog while ((ch = getopt(argc, argv, "abcgHhiklmnPt:T,")) != -1) 1401556Srgrimes switch (ch) { 14152735Sjulian case 'a': 14252735Sjulian aflag = 1; 14352735Sjulian break; 14454621Smharo case 'b': 14554621Smharo /* FALLTHROUGH */ 14654621Smharo case 'P': 147162483Scsjp /* 148218909Sbrucec * POSIX specifically discusses the behavior of 149162483Scsjp * both -k and -P. It states that the blocksize should 150162483Scsjp * be set to 1024. Thus, if this occurs, simply break 151162483Scsjp * rather than clobbering the old blocksize. 152162483Scsjp */ 153162483Scsjp if (kflag) 154162483Scsjp break; 155171195Sscf setenv("BLOCKSIZE", "512", 1); 15654621Smharo hflag = 0; 15754621Smharo break; 158128555Sobrien case 'c': 159128555Sobrien cflag = 1; 160128555Sobrien break; 16161227Sjwd case 'g': 162171195Sscf setenv("BLOCKSIZE", "1g", 1); 16361227Sjwd hflag = 0; 16461227Sjwd break; 16554621Smharo case 'H': 16654621Smharo hflag = UNITS_SI; 16754621Smharo break; 16854621Smharo case 'h': 16954621Smharo hflag = UNITS_2; 17054621Smharo break; 1711556Srgrimes case 'i': 1721556Srgrimes iflag = 1; 1731556Srgrimes break; 1742008Swollman case 'k': 175162483Scsjp kflag++; 176171195Sscf setenv("BLOCKSIZE", "1024", 1); 17754621Smharo hflag = 0; 1782008Swollman break; 17977734Spirzyk case 'l': 18077734Spirzyk if (vfslist != NULL) 18177734Spirzyk errx(1, "-l and -t are mutually exclusive."); 18277734Spirzyk vfslist = makevfslist(makenetvfslist()); 183167326Swill lflag = 1; 18477734Spirzyk break; 18554621Smharo case 'm': 186171195Sscf setenv("BLOCKSIZE", "1m", 1); 18754621Smharo hflag = 0; 18854621Smharo break; 1891556Srgrimes case 'n': 1901556Srgrimes nflag = 1; 1911556Srgrimes break; 1921556Srgrimes case 't': 193167326Swill if (lflag) 194167326Swill errx(1, "-l and -t are mutually exclusive."); 19523852Sbde if (vfslist != NULL) 19687666Scharnier errx(1, "only one -t option may be specified"); 19780795Sobrien fstype = optarg; 19823852Sbde vfslist = makevfslist(optarg); 1991556Srgrimes break; 200185200Spjd case 'T': 201185200Spjd Tflag = 1; 202185200Spjd break; 203243049Sgrog case ',': 204243049Sgrog thousands = 1; 205243049Sgrog break; 2061556Srgrimes case '?': 2071556Srgrimes default: 2081556Srgrimes usage(); 2091556Srgrimes } 2101556Srgrimes argc -= optind; 2111556Srgrimes argv += optind; 2121556Srgrimes 21330340Sjoerg rv = 0; 2141556Srgrimes if (!*argv) { 215226502Sdes /* everything (modulo -t) */ 216226502Sdes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 21723852Sbde mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); 218226502Sdes } else { 219226502Sdes /* just the filesystems specified on the command line */ 220226502Sdes mntbuf = malloc(argc * sizeof(*mntbuf)); 221249698Suqs if (mntbuf == NULL) 222226502Sdes err(1, "malloc()"); 223226502Sdes mntsize = 0; 224226502Sdes /* continued in for loop below */ 2251556Srgrimes } 2261556Srgrimes 227226502Sdes /* iterate through specified filesystems */ 2281556Srgrimes for (; *argv; argv++) { 2291556Srgrimes if (stat(*argv, &stbuf) < 0) { 230249698Suqs if ((mntpt = getmntpt(*argv)) == NULL) { 2311556Srgrimes warn("%s", *argv); 23230340Sjoerg rv = 1; 2331556Srgrimes continue; 2341556Srgrimes } 235310380Sbrooks#ifdef MOUNT_CHAR_DEVS 23676404Skris } else if (S_ISCHR(stbuf.st_mode)) { 237249698Suqs if ((mntpt = getmntpt(*argv)) == NULL) { 23876404Skris mdev.fspec = *argv; 23976404Skris mntpath = strdup("/tmp/df.XXXXXX"); 24076404Skris if (mntpath == NULL) { 24176404Skris warn("strdup failed"); 24276404Skris rv = 1; 24376404Skris continue; 24476404Skris } 24576404Skris mntpt = mkdtemp(mntpath); 24676404Skris if (mntpt == NULL) { 24776404Skris warn("mkdtemp(\"%s\") failed", mntpath); 24876404Skris rv = 1; 24976404Skris free(mntpath); 25076404Skris continue; 25176404Skris } 252310380Sbrooks if (iov != NULL) 253310380Sbrooks free_iovec(&iov, &iovlen); 254310380Sbrooks build_iovec_argf(&iov, &iovlen, "fstype", "%s", 255310380Sbrooks fstype); 256310380Sbrooks build_iovec_argf(&iov, &iovlen, "fspath", "%s", 257310380Sbrooks mntpath); 258310380Sbrooks build_iovec_argf(&iov, &iovlen, "from", "%s", 259310380Sbrooks *argv); 260310380Sbrooks build_iovec(&iov, &iovlen, "errmsg", errmsg, 261310380Sbrooks sizeof(errmsg)); 262310380Sbrooks if (nmount(iov, iovlen, 263310380Sbrooks MNT_RDONLY|MNT_NOEXEC) < 0) { 264310380Sbrooks if (errmsg[0]) 265310380Sbrooks warn("%s: %s", *argv, 266310380Sbrooks errmsg); 267310380Sbrooks else 268310380Sbrooks warn("%s", *argv); 26996470Sphk rv = 1; 27076404Skris (void)rmdir(mntpt); 27176404Skris free(mntpath); 27276404Skris continue; 27376404Skris } else if (statfs(mntpt, &statfsbuf) == 0) { 27476404Skris statfsbuf.f_mntonname[0] = '\0'; 27593246Siedowse prtstat(&statfsbuf, &maxwidths); 276128410Sobrien if (cflag) 277128410Sobrien addstat(&totalbuf, &statfsbuf); 27876404Skris } else { 27976404Skris warn("%s", *argv); 28076404Skris rv = 1; 28176404Skris } 28276404Skris (void)unmount(mntpt, 0); 28376404Skris (void)rmdir(mntpt); 28476404Skris free(mntpath); 28576404Skris continue; 28676404Skris } 287310380Sbrooks#endif 2881556Srgrimes } else 2891556Srgrimes mntpt = *argv; 290115769Sbde 2911556Srgrimes /* 2921556Srgrimes * Statfs does not take a `wait' flag, so we cannot 2931556Srgrimes * implement nflag here. 2941556Srgrimes */ 2951556Srgrimes if (statfs(mntpt, &statfsbuf) < 0) { 2961556Srgrimes warn("%s", mntpt); 29730340Sjoerg rv = 1; 2981556Srgrimes continue; 2991556Srgrimes } 300115769Sbde 301115769Sbde /* 302115769Sbde * Check to make sure the arguments we've been given are 303115769Sbde * satisfied. Return an error if we have been asked to 304115769Sbde * list a mount point that does not match the other args 305115769Sbde * we've been given (-l, -t, etc.). 306115744Sjkh */ 307115744Sjkh if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { 308115769Sbde rv = 1; 309115744Sjkh continue; 310115744Sjkh } 311115769Sbde 312226502Sdes /* the user asked for it, so ignore the ignore flag */ 313226502Sdes statfsbuf.f_flags &= ~MNT_IGNORE; 314226502Sdes 315226502Sdes /* add to list */ 316226502Sdes mntbuf[mntsize++] = statfsbuf; 317226502Sdes } 318226502Sdes 319249698Suqs memset(&maxwidths, 0, sizeof(maxwidths)); 320226502Sdes for (i = 0; i < mntsize; i++) { 321226502Sdes if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) { 322226502Sdes update_maxwidths(&maxwidths, &mntbuf[i]); 323226502Sdes if (cflag) 324226502Sdes addstat(&totalbuf, &mntbuf[i]); 32593246Siedowse } 3261556Srgrimes } 327226502Sdes for (i = 0; i < mntsize; i++) 328226502Sdes if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) 329226502Sdes prtstat(&mntbuf[i], &maxwidths); 330128410Sobrien if (cflag) 331128410Sobrien prtstat(&totalbuf, &maxwidths); 332287790Sdelphij exit(rv); 3331556Srgrimes} 3341556Srgrimes 33596470Sphkstatic char * 336114579Smarkmgetmntpt(const char *name) 3371556Srgrimes{ 338120037Sobrien size_t mntsize, i; 3391556Srgrimes struct statfs *mntbuf; 3401556Srgrimes 3411556Srgrimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 3421556Srgrimes for (i = 0; i < mntsize; i++) { 3431556Srgrimes if (!strcmp(mntbuf[i].f_mntfromname, name)) 3441556Srgrimes return (mntbuf[i].f_mntonname); 3451556Srgrimes } 346249698Suqs return (NULL); 3471556Srgrimes} 3481556Srgrimes 3491556Srgrimes/* 350102230Strhodes * Make a pass over the file system info in ``mntbuf'' filtering out 351102230Strhodes * file system types not in vfslist and possibly re-stating to get 3521556Srgrimes * current (not cached) info. Returns the new count of valid statfs bufs. 3531556Srgrimes */ 354120037Sobrienstatic size_t 35596470Sphkregetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) 3561556Srgrimes{ 357132465Scsjp int error, i, j; 3581556Srgrimes struct statfs *mntbuf; 3591556Srgrimes 36023852Sbde if (vfslist == NULL) 3611556Srgrimes return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT)); 3621556Srgrimes 3631556Srgrimes mntbuf = *mntbufp; 36423852Sbde for (j = 0, i = 0; i < mntsize; i++) { 36523852Sbde if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 36623852Sbde continue; 367132465Scsjp /* 368132465Scsjp * XXX statfs(2) can fail for various reasons. It may be 369132465Scsjp * possible that the user does not have access to the 370132465Scsjp * pathname, if this happens, we will fall back on 371132465Scsjp * "stale" filesystem statistics. 372132465Scsjp */ 373132465Scsjp error = statfs(mntbuf[i].f_mntonname, &mntbuf[j]); 374132465Scsjp if (nflag || error < 0) 375132465Scsjp if (i != j) { 376132465Scsjp if (error < 0) 377132465Scsjp warnx("%s stats possibly stale", 378132465Scsjp mntbuf[i].f_mntonname); 379132465Scsjp mntbuf[j] = mntbuf[i]; 380132465Scsjp } 38123852Sbde j++; 3821556Srgrimes } 3831556Srgrimes return (j); 3841556Srgrimes} 3851556Srgrimes 38696470Sphkstatic void 387122537Smckusickprthuman(const struct statfs *sfsp, int64_t used) 38854621Smharo{ 38954621Smharo 390129678Spjd prthumanval(sfsp->f_blocks * sfsp->f_bsize); 391129678Spjd prthumanval(used * sfsp->f_bsize); 392129678Spjd prthumanval(sfsp->f_bavail * sfsp->f_bsize); 39354621Smharo} 39454621Smharo 39596470Sphkstatic void 396129678Spjdprthumanval(int64_t bytes) 39754621Smharo{ 398129678Spjd char buf[6]; 399129678Spjd int flags; 40054621Smharo 401129678Spjd flags = HN_B | HN_NOSPACE | HN_DECIMAL; 402129678Spjd if (hflag == UNITS_SI) 403129678Spjd flags |= HN_DIVISOR_1000; 40454621Smharo 405129678Spjd humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 406129678Spjd bytes, "", HN_AUTOSCALE, flags); 407129678Spjd 408129678Spjd (void)printf(" %6s", buf); 40954621Smharo} 41054621Smharo 41154621Smharo/* 412193629Ssimon * Print an inode count in "human-readable" format. 413193629Ssimon */ 414193629Ssimonstatic void 415193629Ssimonprthumanvalinode(int64_t bytes) 416193629Ssimon{ 417193629Ssimon char buf[6]; 418193629Ssimon int flags; 419193629Ssimon 420193629Ssimon flags = HN_NOSPACE | HN_DECIMAL | HN_DIVISOR_1000; 421193629Ssimon 422193629Ssimon humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 423193629Ssimon bytes, "", HN_AUTOSCALE, flags); 424193629Ssimon 425193629Ssimon (void)printf(" %5s", buf); 426193629Ssimon} 427193629Ssimon 428193629Ssimon/* 429102230Strhodes * Convert statfs returned file system size into BLOCKSIZE units. 4301556Srgrimes */ 431130060Sdasstatic intmax_t 432130060Sdasfsbtoblk(int64_t num, uint64_t fsbs, u_long bs) 433130060Sdas{ 434244134Sgrog return (num * (intmax_t) fsbs / (int64_t) bs); 435130060Sdas} 436130060Sdas 4371556Srgrimes/* 438102230Strhodes * Print out status about a file system. 4391556Srgrimes */ 44096470Sphkstatic void 44193246Siedowseprtstat(struct statfs *sfsp, struct maxwidths *mwp) 4421556Srgrimes{ 443168428Skan static long blocksize; 444114579Smarkm static int headerlen, timesthrough = 0; 44576873Skris static const char *header; 446122537Smckusick int64_t used, availblks, inodes; 447243049Sgrog const char *format; 4481556Srgrimes 4491556Srgrimes if (++timesthrough == 1) { 450125611Siedowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem")); 451185200Spjd mwp->fstype = imax(mwp->fstype, (int)strlen("Type")); 452243049Sgrog if (thousands) { /* make space for commas */ 453243049Sgrog mwp->total += (mwp->total - 1) / 3; 454243049Sgrog mwp->used += (mwp->used - 1) / 3; 455243049Sgrog mwp->avail += (mwp->avail - 1) / 3; 456243049Sgrog mwp->iused += (mwp->iused - 1) / 3; 457243049Sgrog mwp->ifree += (mwp->ifree - 1) / 3; 458243049Sgrog } 45954621Smharo if (hflag) { 460128553Sobrien header = " Size"; 461125611Siedowse mwp->total = mwp->used = mwp->avail = 462125611Siedowse (int)strlen(header); 46354621Smharo } else { 46454621Smharo header = getbsize(&headerlen, &blocksize); 465125611Siedowse mwp->total = imax(mwp->total, headerlen); 46654621Smharo } 467125611Siedowse mwp->used = imax(mwp->used, (int)strlen("Used")); 468125611Siedowse mwp->avail = imax(mwp->avail, (int)strlen("Avail")); 46993246Siedowse 470185200Spjd (void)printf("%-*s", mwp->mntfrom, "Filesystem"); 471185200Spjd if (Tflag) 472185200Spjd (void)printf(" %-*s", mwp->fstype, "Type"); 473243049Sgrog (void)printf(" %*s %*s %*s Capacity", mwp->total, header, 474125611Siedowse mwp->used, "Used", mwp->avail, "Avail"); 47593246Siedowse if (iflag) { 476193629Ssimon mwp->iused = imax(hflag ? 0 : mwp->iused, 477193629Ssimon (int)strlen(" iused")); 478193629Ssimon mwp->ifree = imax(hflag ? 0 : mwp->ifree, 479193629Ssimon (int)strlen("ifree")); 480114582Smarkm (void)printf(" %*s %*s %%iused", 481125611Siedowse mwp->iused - 2, "iused", mwp->ifree, "ifree"); 48293246Siedowse } 4831556Srgrimes (void)printf(" Mounted on\n"); 4841556Srgrimes } 485243129Sgrog /* Check for 0 block size. Can this happen? */ 486243129Sgrog if (sfsp->f_bsize == 0) { 487243129Sgrog warnx ("File system %s does not have a block size, assuming 512.", 488243129Sgrog sfsp->f_mntonname); 489243129Sgrog sfsp->f_bsize = 512; 490243129Sgrog } 491125611Siedowse (void)printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname); 492185200Spjd if (Tflag) 493185200Spjd (void)printf(" %-*s", mwp->fstype, sfsp->f_fstypename); 4941556Srgrimes used = sfsp->f_blocks - sfsp->f_bfree; 4951556Srgrimes availblks = sfsp->f_bavail + used; 49654621Smharo if (hflag) { 49754621Smharo prthuman(sfsp, used); 49854621Smharo } else { 499243049Sgrog if (thousands) 500243049Sgrog format = " %*j'd %*j'd %*j'd"; 501243049Sgrog else 502243049Sgrog format = " %*jd %*jd %*jd"; 503243049Sgrog (void)printf(format, 504130060Sdas mwp->total, fsbtoblk(sfsp->f_blocks, 505125611Siedowse sfsp->f_bsize, blocksize), 506130060Sdas mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize), 507130060Sdas mwp->avail, fsbtoblk(sfsp->f_bavail, 508125611Siedowse sfsp->f_bsize, blocksize)); 50954621Smharo } 5101556Srgrimes (void)printf(" %5.0f%%", 5111556Srgrimes availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 5121556Srgrimes if (iflag) { 5131556Srgrimes inodes = sfsp->f_files; 5141556Srgrimes used = inodes - sfsp->f_ffree; 515193629Ssimon if (hflag) { 516193629Ssimon (void)printf(" "); 517193629Ssimon prthumanvalinode(used); 518193629Ssimon prthumanvalinode(sfsp->f_ffree); 519193629Ssimon } else { 520243049Sgrog if (thousands) 521243049Sgrog format = " %*j'd %*j'd"; 522243049Sgrog else 523243049Sgrog format = " %*jd %*jd"; 524243049Sgrog (void)printf(format, mwp->iused, (intmax_t)used, 525193629Ssimon mwp->ifree, (intmax_t)sfsp->f_ffree); 526193629Ssimon } 527193629Ssimon (void)printf(" %4.0f%% ", inodes == 0 ? 100.0 : 528125611Siedowse (double)used / (double)inodes * 100.0); 529128553Sobrien } else 530128553Sobrien (void)printf(" "); 531128555Sobrien if (strncmp(sfsp->f_mntfromname, "total", MNAMELEN) != 0) 532128410Sobrien (void)printf(" %s", sfsp->f_mntonname); 533128410Sobrien (void)printf("\n"); 5341556Srgrimes} 5351556Srgrimes 536194795Sdelphijstatic void 537128410Sobrienaddstat(struct statfs *totalfsp, struct statfs *statfsp) 538128410Sobrien{ 539128555Sobrien uint64_t bsize; 540128410Sobrien 541128555Sobrien bsize = statfsp->f_bsize / totalfsp->f_bsize; 542128410Sobrien totalfsp->f_blocks += statfsp->f_blocks * bsize; 543128410Sobrien totalfsp->f_bfree += statfsp->f_bfree * bsize; 544128410Sobrien totalfsp->f_bavail += statfsp->f_bavail * bsize; 545128410Sobrien totalfsp->f_files += statfsp->f_files; 546128410Sobrien totalfsp->f_ffree += statfsp->f_ffree; 547128410Sobrien} 548128410Sobrien 5491556Srgrimes/* 55093246Siedowse * Update the maximum field-width information in `mwp' based on 551102230Strhodes * the file system specified by `sfsp'. 55293246Siedowse */ 55396470Sphkstatic void 554114579Smarkmupdate_maxwidths(struct maxwidths *mwp, const struct statfs *sfsp) 55593246Siedowse{ 556168428Skan static long blocksize = 0; 557108452Smike int dummy; 55893246Siedowse 55993246Siedowse if (blocksize == 0) 56093246Siedowse getbsize(&dummy, &blocksize); 56193246Siedowse 562125611Siedowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname)); 563185200Spjd mwp->fstype = imax(mwp->fstype, (int)strlen(sfsp->f_fstypename)); 564125611Siedowse mwp->total = imax(mwp->total, int64width( 565122537Smckusick fsbtoblk((int64_t)sfsp->f_blocks, sfsp->f_bsize, blocksize))); 566125611Siedowse mwp->used = imax(mwp->used, 567125611Siedowse int64width(fsbtoblk((int64_t)sfsp->f_blocks - 568122537Smckusick (int64_t)sfsp->f_bfree, sfsp->f_bsize, blocksize))); 569125611Siedowse mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail, 57093246Siedowse sfsp->f_bsize, blocksize))); 571125611Siedowse mwp->iused = imax(mwp->iused, int64width((int64_t)sfsp->f_files - 57293246Siedowse sfsp->f_ffree)); 573125611Siedowse mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree)); 57493246Siedowse} 57593246Siedowse 576125611Siedowse/* Return the width in characters of the specified value. */ 577125611Siedowsestatic int 578122537Smckusickint64width(int64_t val) 57993246Siedowse{ 580125611Siedowse int len; 58193246Siedowse 58293246Siedowse len = 0; 58393246Siedowse /* Negative or zero values require one extra digit. */ 58493246Siedowse if (val <= 0) { 58593246Siedowse val = -val; 58693246Siedowse len++; 58793246Siedowse } 58893246Siedowse while (val > 0) { 58993246Siedowse len++; 59093246Siedowse val /= 10; 59193246Siedowse } 59293246Siedowse 59393246Siedowse return (len); 59493246Siedowse} 59593246Siedowse 59696470Sphkstatic void 59790108Simpusage(void) 5981556Srgrimes{ 59954621Smharo 60023852Sbde (void)fprintf(stderr, 601245871Sdelphij"usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,]\n" 602245871Sdelphij" [file | filesystem ...]\n"); 60354621Smharo exit(EX_USAGE); 6041556Srgrimes} 60577734Spirzyk 60696470Sphkstatic char * 60790108Simpmakenetvfslist(void) 60877734Spirzyk{ 60977734Spirzyk char *str, *strptr, **listptr; 610114579Smarkm struct xvfsconf *xvfsp, *keep_xvfsp; 611101651Smux size_t buflen; 612101651Smux int cnt, i, maxvfsconf; 61377734Spirzyk 614101651Smux if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0) { 615101651Smux warn("sysctl(vfs.conflist)"); 61677734Spirzyk return (NULL); 61777734Spirzyk } 618101651Smux xvfsp = malloc(buflen); 619101651Smux if (xvfsp == NULL) { 620101651Smux warnx("malloc failed"); 621101651Smux return (NULL); 622101651Smux } 623114579Smarkm keep_xvfsp = xvfsp; 624101651Smux if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) { 625101651Smux warn("sysctl(vfs.conflist)"); 626114579Smarkm free(keep_xvfsp); 627101651Smux return (NULL); 628101651Smux } 629101651Smux maxvfsconf = buflen / sizeof(struct xvfsconf); 63077734Spirzyk 63179791Swollman if ((listptr = malloc(sizeof(char*) * maxvfsconf)) == NULL) { 63277734Spirzyk warnx("malloc failed"); 633114579Smarkm free(keep_xvfsp); 63477734Spirzyk return (NULL); 63577734Spirzyk } 63677734Spirzyk 637101651Smux for (cnt = 0, i = 0; i < maxvfsconf; i++) { 638101651Smux if (xvfsp->vfc_flags & VFCF_NETWORK) { 639101651Smux listptr[cnt++] = strdup(xvfsp->vfc_name); 64079791Swollman if (listptr[cnt-1] == NULL) { 64177734Spirzyk warnx("malloc failed"); 642114579Smarkm free(listptr); 643114579Smarkm free(keep_xvfsp); 64477734Spirzyk return (NULL); 64577734Spirzyk } 64677734Spirzyk } 647101651Smux xvfsp++; 648101651Smux } 64977734Spirzyk 65088182Sru if (cnt == 0 || 65188182Sru (str = malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) { 65288182Sru if (cnt > 0) 65388182Sru warnx("malloc failed"); 65477734Spirzyk free(listptr); 655114579Smarkm free(keep_xvfsp); 65677734Spirzyk return (NULL); 65777734Spirzyk } 65877734Spirzyk 65979791Swollman *str = 'n'; *(str + 1) = 'o'; 66079791Swollman for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) { 661161470Simp strlcpy(strptr, listptr[i], 32); 66279791Swollman strptr += strlen(listptr[i]); 66379791Swollman *strptr = ','; 66477734Spirzyk free(listptr[i]); 66577734Spirzyk } 666126643Smarkm *(--strptr) = '\0'; 66777734Spirzyk 668114579Smarkm free(keep_xvfsp); 66977734Spirzyk free(listptr); 67077734Spirzyk return (str); 67177734Spirzyk} 672