| 1 | /*	$NetBSD: df.c,v 1.93 2018/08/26 23:34:52 sevan Exp $ */ | 
| 2 |  | 
| 3 | /* | 
| 4 |  * Copyright (c) 1980, 1990, 1993, 1994 | 
| 5 |  *	The Regents of the University of California.  All rights reserved. | 
| 6 |  * (c) UNIX System Laboratories, Inc. | 
| 7 |  * All or some portions of this file are derived from material licensed | 
| 8 |  * to the University of California by American Telephone and Telegraph | 
| 9 |  * Co. or Unix System Laboratories, Inc. and are reproduced herein with | 
| 10 |  * the permission of UNIX System Laboratories, Inc. | 
| 11 |  * | 
| 12 |  * Redistribution and use in source and binary forms, with or without | 
| 13 |  * modification, are permitted provided that the following conditions | 
| 14 |  * are met: | 
| 15 |  * 1. Redistributions of source code must retain the above copyright | 
| 16 |  *    notice, this list of conditions and the following disclaimer. | 
| 17 |  * 2. Redistributions in binary form must reproduce the above copyright | 
| 18 |  *    notice, this list of conditions and the following disclaimer in the | 
| 19 |  *    documentation and/or other materials provided with the distribution. | 
| 20 |  * 3. Neither the name of the University nor the names of its contributors | 
| 21 |  *    may be used to endorse or promote products derived from this software | 
| 22 |  *    without specific prior written permission. | 
| 23 |  * | 
| 24 |  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 
| 25 |  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 26 |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 
| 27 |  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 
| 28 |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
| 29 |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 
| 30 |  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 
| 31 |  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 
| 32 |  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 
| 33 |  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
| 34 |  * SUCH DAMAGE. | 
| 35 |  */ | 
| 36 |  | 
| 37 | #include <sys/cdefs.h> | 
| 38 | #ifndef lint | 
| 39 | __COPYRIGHT( | 
| 40 | "@(#) Copyright (c) 1980, 1990, 1993, 1994\  | 
| 41 |  The Regents of the University of California.  All rights reserved." ); | 
| 42 | #endif /* not lint */ | 
| 43 |  | 
| 44 | #ifndef lint | 
| 45 | #if 0 | 
| 46 | static char sccsid[] = "@(#)df.c	8.7 (Berkeley) 4/2/94" ; | 
| 47 | #else | 
| 48 | __RCSID("$NetBSD: df.c,v 1.93 2018/08/26 23:34:52 sevan Exp $" ); | 
| 49 | #endif | 
| 50 | #endif /* not lint */ | 
| 51 |  | 
| 52 | #include <sys/param.h> | 
| 53 | #include <sys/stat.h> | 
| 54 | #include <sys/mount.h> | 
| 55 |  | 
| 56 | #include <assert.h> | 
| 57 | #include <err.h> | 
| 58 | #include <errno.h> | 
| 59 | #include <fcntl.h> | 
| 60 | #include <locale.h> | 
| 61 | #include <util.h> | 
| 62 | #include <stdio.h> | 
| 63 | #include <stdlib.h> | 
| 64 | #include <string.h> | 
| 65 | #include <unistd.h> | 
| 66 | #include <util.h> | 
| 67 |  | 
| 68 | static char	*getmntpt(const char *); | 
| 69 | static void	 prtstat(struct statvfs *, int); | 
| 70 | static int	 selected(const char *, size_t); | 
| 71 | static void	 maketypelist(char *); | 
| 72 | static size_t	 regetmntinfo(struct statvfs **, size_t); | 
| 73 | __dead static void usage(void); | 
| 74 | static void	 prthumanval(int64_t, const char *); | 
| 75 | static void	 prthuman(struct statvfs *, int64_t, int64_t); | 
| 76 |  | 
| 77 | static int	 aflag, gflag, hflag, iflag, lflag, nflag, Pflag; | 
| 78 | static long	 usize; | 
| 79 | static char	**typelist; | 
| 80 |  | 
| 81 | int | 
| 82 | main(int argc, char *argv[]) | 
| 83 | { | 
| 84 | 	struct stat stbuf; | 
| 85 | 	struct statvfs *mntbuf; | 
| 86 | 	long mntsize; | 
| 87 | 	int ch, i, maxwidth, width; | 
| 88 | 	char *mntpt; | 
| 89 |  | 
| 90 | 	setprogname(argv[0]); | 
| 91 | 	(void)setlocale(LC_ALL, "" ); | 
| 92 |  | 
| 93 | 	while ((ch = getopt(argc, argv, "aGghiklmnPt:" )) != -1) | 
| 94 | 		switch (ch) { | 
| 95 | 		case 'a': | 
| 96 | 			aflag = 1; | 
| 97 | 			break; | 
| 98 | 		case 'g': | 
| 99 | 			hflag = 0; | 
| 100 | 			usize = 1024 * 1024 * 1024; | 
| 101 | 			break; | 
| 102 | 		case 'G': | 
| 103 | 			gflag = 1; | 
| 104 | 			break; | 
| 105 | 		case 'h': | 
| 106 | 			hflag = 1; | 
| 107 | 			usize = 0; | 
| 108 | 			break; | 
| 109 | 		case 'i': | 
| 110 | 			iflag = 1; | 
| 111 | 			break; | 
| 112 | 		case 'k': | 
| 113 | 			hflag = 0; | 
| 114 | 			usize = 1024; | 
| 115 | 			break; | 
| 116 | 		case 'l': | 
| 117 | 			lflag = 1; | 
| 118 | 			break; | 
| 119 | 		case 'm': | 
| 120 | 			hflag = 0; | 
| 121 | 			usize = 1024 * 1024; | 
| 122 | 			break; | 
| 123 | 		case 'n': | 
| 124 | 			nflag = 1; | 
| 125 | 			break; | 
| 126 | 		case 'P': | 
| 127 | 			Pflag = 1; | 
| 128 | 			break; | 
| 129 | 		case 't': | 
| 130 | 			if (typelist != NULL) | 
| 131 | 				errx(EXIT_FAILURE, | 
| 132 | 				    "only one -t option may be specified." ); | 
| 133 | 			maketypelist(optarg); | 
| 134 | 			break; | 
| 135 | 		case '?': | 
| 136 | 		default: | 
| 137 | 			usage(); | 
| 138 | 		} | 
| 139 |  | 
| 140 | 	if (gflag && (Pflag || iflag)) | 
| 141 | 		errx(EXIT_FAILURE, | 
| 142 | 		    "only one of -G and -P or -i may be specified" ); | 
| 143 | 	if (Pflag && iflag) | 
| 144 | 		errx(EXIT_FAILURE, | 
| 145 | 		    "only one of -P and -i may be specified" ); | 
| 146 | #if 0 | 
| 147 | 	/* | 
| 148 | 	 * The block size cannot be checked until after getbsize() is called. | 
| 149 | 	 */ | 
| 150 | 	if (Pflag && (hflag || (usize != 1024 && usize != 512))) | 
| 151 | 		errx(EXIT_FAILURE, | 
| 152 | 		    "non-standard block size incompatible with -P" ); | 
| 153 | #endif | 
| 154 | 	argc -= optind; | 
| 155 | 	argv += optind; | 
| 156 |  | 
| 157 | 	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | 
| 158 | 	if (mntsize == 0) | 
| 159 | 		err(EXIT_FAILURE, | 
| 160 | 		    "retrieving information on mounted file systems" ); | 
| 161 |  | 
| 162 | 	if (*argv == NULL) { | 
| 163 | 		mntsize = regetmntinfo(&mntbuf, mntsize); | 
| 164 | 	} else { | 
| 165 | 		if ((mntbuf = malloc(argc * sizeof(*mntbuf))) == NULL) | 
| 166 | 			err(EXIT_FAILURE, "can't allocate statvfs array" ); | 
| 167 | 		mntsize = 0; | 
| 168 | 		for (/*EMPTY*/; *argv != NULL; argv++) { | 
| 169 | 			if (stat(*argv, &stbuf) < 0) { | 
| 170 | 				if ((mntpt = getmntpt(*argv)) == 0) { | 
| 171 | 					warn("%s" , *argv); | 
| 172 | 					continue; | 
| 173 | 				} | 
| 174 | 			} else if (S_ISBLK(stbuf.st_mode)) { | 
| 175 | 				if ((mntpt = getmntpt(*argv)) == 0) | 
| 176 | 					mntpt = *argv; | 
| 177 | 			} else | 
| 178 | 				mntpt = *argv; | 
| 179 | 			/* | 
| 180 | 			 * Statfs does not take a `wait' flag, so we cannot | 
| 181 | 			 * implement nflag here. | 
| 182 | 			 */ | 
| 183 | 			if (!statvfs(mntpt, &mntbuf[mntsize])) | 
| 184 | 				if (lflag && | 
| 185 | 				    (mntbuf[mntsize].f_flag & MNT_LOCAL) == 0) | 
| 186 | 					warnx("Warning: %s is not a local %s" , | 
| 187 | 					    *argv, "file system" ); | 
| 188 | 				else if | 
| 189 | 				    (!selected(mntbuf[mntsize].f_fstypename, | 
| 190 | 					sizeof(mntbuf[mntsize].f_fstypename))) | 
| 191 | 					warnx("Warning: %s mounted as a %s %s" , | 
| 192 | 					    *argv, | 
| 193 | 					    mntbuf[mntsize].f_fstypename, | 
| 194 | 					    "file system" ); | 
| 195 | 				else | 
| 196 | 					++mntsize; | 
| 197 | 			else | 
| 198 | 				warn("%s" , *argv); | 
| 199 | 		} | 
| 200 | 	} | 
| 201 |  | 
| 202 | 	maxwidth = 0; | 
| 203 | 	for (i = 0; i < mntsize; i++) { | 
| 204 | 		width = (int)strlen(mntbuf[i].f_mntfromname); | 
| 205 | 		if (width > maxwidth) | 
| 206 | 			maxwidth = width; | 
| 207 | 	} | 
| 208 | 	for (i = 0; i < mntsize; i++) | 
| 209 | 		prtstat(&mntbuf[i], maxwidth); | 
| 210 | 	return 0; | 
| 211 | } | 
| 212 |  | 
| 213 | static char * | 
| 214 | getmntpt(const char *name) | 
| 215 | { | 
| 216 | 	size_t mntsize, i; | 
| 217 | 	struct statvfs *mntbuf; | 
| 218 |  | 
| 219 | 	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | 
| 220 | 	if (mntsize == 0) | 
| 221 | 		err(EXIT_FAILURE, "Can't get mount information" ); | 
| 222 | 	for (i = 0; i < mntsize; i++) { | 
| 223 | 		if (!strcmp(mntbuf[i].f_mntfromname, name)) | 
| 224 | 			return mntbuf[i].f_mntonname; | 
| 225 | 	} | 
| 226 | 	return 0; | 
| 227 | } | 
| 228 |  | 
| 229 | static enum { IN_LIST, NOT_IN_LIST } which; | 
| 230 |  | 
| 231 | static int | 
| 232 | selected(const char *type, size_t len) | 
| 233 | { | 
| 234 | 	char **av; | 
| 235 |  | 
| 236 | 	/* If no type specified, it's always selected. */ | 
| 237 | 	if (typelist == NULL) | 
| 238 | 		return 1; | 
| 239 | 	for (av = typelist; *av != NULL; ++av) | 
| 240 | 		if (!strncmp(type, *av, len)) | 
| 241 | 			return which == IN_LIST ? 1 : 0; | 
| 242 | 	return which == IN_LIST ? 0 : 1; | 
| 243 | } | 
| 244 |  | 
| 245 | static void | 
| 246 | maketypelist(char *fslist) | 
| 247 | { | 
| 248 | 	size_t i; | 
| 249 | 	char *nextcp, **av; | 
| 250 |  | 
| 251 | 	if ((fslist == NULL) || (fslist[0] == '\0')) | 
| 252 | 		errx(EXIT_FAILURE, "empty type list" ); | 
| 253 |  | 
| 254 | 	/* | 
| 255 | 	 * XXX | 
| 256 | 	 * Note: the syntax is "noxxx,yyy" for no xxx's and | 
| 257 | 	 * no yyy's, not the more intuitive "noyyy,noyyy". | 
| 258 | 	 */ | 
| 259 | 	if (fslist[0] == 'n' && fslist[1] == 'o') { | 
| 260 | 		fslist += 2; | 
| 261 | 		which = NOT_IN_LIST; | 
| 262 | 	} else | 
| 263 | 		which = IN_LIST; | 
| 264 |  | 
| 265 | 	/* Count the number of types. */ | 
| 266 | 	for (i = 1, nextcp = fslist; | 
| 267 | 	    (nextcp = strchr(nextcp, ',')) != NULL; i++) | 
| 268 | 		++nextcp; | 
| 269 |  | 
| 270 | 	/* Build an array of that many types. */ | 
| 271 | 	if ((av = typelist = malloc((i + 1) * sizeof(*av))) == NULL) | 
| 272 | 		err(EXIT_FAILURE, "can't allocate type array" ); | 
| 273 | 	av[0] = fslist; | 
| 274 | 	for (i = 1, nextcp = fslist; | 
| 275 | 	    (nextcp = strchr(nextcp, ',')) != NULL; i++) { | 
| 276 | 		*nextcp = '\0'; | 
| 277 | 		av[i] = ++nextcp; | 
| 278 | 	} | 
| 279 | 	/* Terminate the array. */ | 
| 280 | 	av[i] = NULL; | 
| 281 | } | 
| 282 |  | 
| 283 | /* | 
| 284 |  * Make a pass over the filesystem info in ``mntbuf'' filtering out | 
| 285 |  * filesystem types not in ``fsmask'' and possibly re-stating to get | 
| 286 |  * current (not cached) info.  Returns the new count of valid statvfs bufs. | 
| 287 |  */ | 
| 288 | static size_t | 
| 289 | regetmntinfo(struct statvfs **mntbufp, size_t mntsize) | 
| 290 | { | 
| 291 | 	size_t i, j; | 
| 292 | 	struct statvfs *mntbuf; | 
| 293 |  | 
| 294 | 	if (!lflag && typelist == NULL && aflag) | 
| 295 | 		return nflag ? mntsize : (size_t)getmntinfo(mntbufp, MNT_WAIT); | 
| 296 |  | 
| 297 | 	mntbuf = *mntbufp; | 
| 298 | 	j = 0; | 
| 299 | 	for (i = 0; i < mntsize; i++) { | 
| 300 | 		if (!aflag && (mntbuf[i].f_flag & MNT_IGNORE) != 0) | 
| 301 | 			continue; | 
| 302 | 		if (lflag && (mntbuf[i].f_flag & MNT_LOCAL) == 0) | 
| 303 | 			continue; | 
| 304 | 		if (!selected(mntbuf[i].f_fstypename, | 
| 305 | 		    sizeof(mntbuf[i].f_fstypename))) | 
| 306 | 			continue; | 
| 307 | 		if (nflag) | 
| 308 | 			mntbuf[j] = mntbuf[i]; | 
| 309 | 		else { | 
| 310 | 			struct statvfs layerbuf = mntbuf[i]; | 
| 311 | 			(void)statvfs(mntbuf[i].f_mntonname, &mntbuf[j]); | 
| 312 | 			/* | 
| 313 | 			 * If the FS name changed, then new data is for | 
| 314 | 			 * a different layer and we don't want it. | 
| 315 | 			 */ | 
| 316 | 			if (memcmp(layerbuf.f_mntfromname, | 
| 317 | 			    mntbuf[j].f_mntfromname, MNAMELEN)) | 
| 318 | 				mntbuf[j] = layerbuf; | 
| 319 | 		} | 
| 320 | 		j++; | 
| 321 | 	} | 
| 322 | 	return j; | 
| 323 | } | 
| 324 |  | 
| 325 | static void | 
| 326 | prthumanval(int64_t bytes, const char *pad) | 
| 327 | { | 
| 328 | 	char buf[6]; | 
| 329 |  | 
| 330 | 	(void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), | 
| 331 | 	    bytes, "" , HN_AUTOSCALE, | 
| 332 | 	    HN_B | HN_NOSPACE | HN_DECIMAL); | 
| 333 |  | 
| 334 | 	(void)printf("%s %6s" , pad, buf); | 
| 335 | } | 
| 336 |  | 
| 337 | static void | 
| 338 | prthuman(struct statvfs *sfsp, int64_t used, int64_t bavail) | 
| 339 | { | 
| 340 |  | 
| 341 | 	prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), "   " ); | 
| 342 | 	prthumanval((int64_t)(used * sfsp->f_frsize), "    " ); | 
| 343 | 	prthumanval((int64_t)(bavail * sfsp->f_frsize), "    " ); | 
| 344 | } | 
| 345 |  | 
| 346 | /* | 
| 347 |  * Convert statvfs returned filesystem size into BLOCKSIZE units. | 
| 348 |  * Attempts to avoid overflow for large filesystems. | 
| 349 |  */ | 
| 350 | #define fsbtoblk(num, fsbs, bs)					\ | 
| 351 | 	(((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ?	\ | 
| 352 | 	    (int64_t)(num) / (int64_t)((bs) / (fsbs)) :		\ | 
| 353 | 	    (int64_t)(num) * (int64_t)((fsbs) / (bs))) | 
| 354 |  | 
| 355 | /* | 
| 356 |  * Print out status about a filesystem. | 
| 357 |  */ | 
| 358 | static void | 
| 359 | prtstat(struct statvfs *sfsp, int maxwidth) | 
| 360 | { | 
| 361 | 	static long blocksize; | 
| 362 | 	static int , timesthrough; | 
| 363 | 	static const char *; | 
| 364 | 	static const char full[] = "100" ; | 
| 365 | 	static const char empty[] = "  0" ; | 
| 366 | 	int64_t used, availblks, inodes; | 
| 367 | 	int64_t bavail; | 
| 368 | 	char pb[64]; | 
| 369 |  | 
| 370 | 	if (gflag) { | 
| 371 | 		/* | 
| 372 | 		 * From SunOS-5.6: | 
| 373 | 		 * | 
| 374 | 		 * /var               (/dev/dsk/c0t0d0s3 ):         8192 block size          1024 frag size | 
| 375 | 		 *   984242 total blocks     860692 free blocks   859708 available         249984 total files | 
| 376 | 		 *   248691 free files      8388611 filesys id | 
| 377 | 		 *      ufs fstype       0x00000004 flag             255 filename length | 
| 378 | 		 * | 
| 379 | 		 */ | 
| 380 | 		(void)printf("%10s (%-12s): %7ld block size %12ld frag size\n" , | 
| 381 | 		    sfsp->f_mntonname, sfsp->f_mntfromname, | 
| 382 | 		    sfsp->f_bsize,	/* On UFS/FFS systems this is | 
| 383 | 					 * also called the "optimal | 
| 384 | 					 * transfer block size" but it | 
| 385 | 					 * is of course the file | 
| 386 | 					 * system's block size too. | 
| 387 | 					 */ | 
| 388 | 		    sfsp->f_frsize);	/* not so surprisingly the | 
| 389 | 					 * "fundamental file system | 
| 390 | 					 * block size" is the frag | 
| 391 | 					 * size. | 
| 392 | 					 */ | 
| 393 | 		(void)printf("%10"  PRId64 " total blocks %10"  PRId64 | 
| 394 | 		    " free blocks  %10"  PRId64 " available\n" , | 
| 395 | 		    (uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree, | 
| 396 | 		    (uint64_t)sfsp->f_bavail); | 
| 397 | 		(void)printf("%10"  PRId64 " total files  %10"  PRId64 | 
| 398 | 		    " free files %12lx filesys id\n" , | 
| 399 | 		    (uint64_t)sfsp->f_ffree, (uint64_t)sfsp->f_files, | 
| 400 | 		    sfsp->f_fsid); | 
| 401 | 		(void)printf("%10s fstype  %#15lx flag  %17ld filename "  | 
| 402 | 		    "length\n" , sfsp->f_fstypename, sfsp->f_flag, | 
| 403 | 		    sfsp->f_namemax); | 
| 404 | 		(void)printf("%10lu owner %17"  PRId64 " syncwrites %12"  PRId64 | 
| 405 | 		    " asyncwrites\n\n" , (unsigned long)sfsp->f_owner, | 
| 406 | 		    sfsp->f_syncwrites, sfsp->f_asyncwrites); | 
| 407 |  | 
| 408 | 		/* | 
| 409 | 		 * a concession by the structured programming police to the | 
| 410 | 		 * indentation police.... | 
| 411 | 		 */ | 
| 412 | 		return; | 
| 413 | 	} | 
| 414 | 	if (maxwidth < 12) | 
| 415 | 		maxwidth = 12; | 
| 416 | 	if (++timesthrough == 1) { | 
| 417 | 		switch (blocksize = usize) { | 
| 418 | 		case 1024: | 
| 419 | 			header = Pflag ? "1024-blocks"  : "1K-blocks" ; | 
| 420 | 			headerlen = (int)strlen(header); | 
| 421 | 			break; | 
| 422 | 		case 1024 * 1024: | 
| 423 | 			header = "1M-blocks" ; | 
| 424 | 			headerlen = (int)strlen(header); | 
| 425 | 			break; | 
| 426 | 		case 1024 * 1024 * 1024: | 
| 427 | 			header = "1G-blocks" ; | 
| 428 | 			headerlen = (int)strlen(header); | 
| 429 | 			break; | 
| 430 | 		default: | 
| 431 | 			if (hflag) { | 
| 432 | 				header = "Size" ; | 
| 433 | 				headerlen = (int)strlen(header); | 
| 434 | 			} else | 
| 435 | 				header = getbsize(&headerlen, &blocksize); | 
| 436 | 			break; | 
| 437 | 		} | 
| 438 | 		if (Pflag) { | 
| 439 | 			/* | 
| 440 | 			 * either: | 
| 441 | 			 *  "Filesystem 1024-blocks Used Available Capacity Mounted on\n" | 
| 442 | 			 * or: | 
| 443 | 			 *  "Filesystem 512-blocks Used Available Capacity Mounted on\n" | 
| 444 | 			 */ | 
| 445 | 			if (blocksize != 1024 && blocksize != 512) | 
| 446 | 				errx(EXIT_FAILURE, | 
| 447 | 				    "non-standard block size incompatible with -P" ); | 
| 448 | 			(void)printf("Filesystem %s Used Available Capacity "  | 
| 449 | 			    "Mounted on\n" , header); | 
| 450 | 		} else { | 
| 451 | 			(void)printf("%-*.*s %s       Used      Avail %%Cap" , | 
| 452 | 			    maxwidth - (headerlen - 10), | 
| 453 | 			    maxwidth - (headerlen - 10), | 
| 454 | 			    "Filesystem" , header); | 
| 455 | 			if (iflag) | 
| 456 | 				(void)printf("    iUsed   iAvail %%iCap" ); | 
| 457 | 			(void)printf(" Mounted on\n" ); | 
| 458 | 		} | 
| 459 | 	} | 
| 460 | 	used = sfsp->f_blocks - sfsp->f_bfree; | 
| 461 | 	bavail = sfsp->f_bfree - sfsp->f_bresvd; | 
| 462 | 	availblks = bavail + used; | 
| 463 | 	if (Pflag) { | 
| 464 | 		assert(hflag == 0); | 
| 465 | 		assert(blocksize > 0); | 
| 466 | 		/* | 
| 467 | 		 * "%s %d %d %d %s %s\n", <file system name>, <total space>, | 
| 468 | 		 * <space used>, <space free>, <percentage used>, | 
| 469 | 		 * <file system root> | 
| 470 | 		 */ | 
| 471 | 		(void)printf("%s %"  PRId64 " %"  PRId64 " %"  PRId64 " %s%% %s\n" , | 
| 472 | 		    sfsp->f_mntfromname, | 
| 473 | 		    fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), | 
| 474 | 		    fsbtoblk(used, sfsp->f_frsize, blocksize), | 
| 475 | 		    fsbtoblk(bavail, sfsp->f_frsize, blocksize), | 
| 476 | 		    availblks == 0 ? full : strspct(pb, sizeof(pb), used, | 
| 477 | 		    availblks, 0), sfsp->f_mntonname); | 
| 478 | 		/* | 
| 479 | 		 * another concession by the structured programming police to | 
| 480 | 		 * the indentation police.... | 
| 481 | 		 * | 
| 482 | 		 * Note iflag cannot be set when Pflag is set. | 
| 483 | 		 */ | 
| 484 | 		return; | 
| 485 | 	} | 
| 486 |  | 
| 487 | 	(void)printf("%-*.*s " , maxwidth, maxwidth, sfsp->f_mntfromname); | 
| 488 |  | 
| 489 | 	if (hflag) | 
| 490 | 		prthuman(sfsp, used, bavail); | 
| 491 | 	else | 
| 492 | 		(void)printf("%10"  PRId64 " %10"  PRId64 " %10"  PRId64, | 
| 493 | 		    fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), | 
| 494 | 		    fsbtoblk(used, sfsp->f_frsize, blocksize), | 
| 495 | 		    fsbtoblk(bavail, sfsp->f_frsize, blocksize)); | 
| 496 | 	(void)printf(" %3s%%" , | 
| 497 | 	    availblks == 0 ? full : | 
| 498 | 	    strspct(pb, sizeof(pb), used, availblks, 0)); | 
| 499 | 	if (iflag) { | 
| 500 | 		inodes = sfsp->f_files; | 
| 501 | 		used = inodes - sfsp->f_ffree; | 
| 502 | 		(void)printf(" %8jd %8jd %4s%%" , | 
| 503 | 		    (intmax_t)used, (intmax_t)sfsp->f_ffree, | 
| 504 | 		    inodes == 0 ? (used == 0 ? empty : full) : | 
| 505 | 		    strspct(pb, sizeof(pb), used, inodes, 0)); | 
| 506 | 	} | 
| 507 | 	(void)printf(" %s\n" , sfsp->f_mntonname); | 
| 508 | } | 
| 509 |  | 
| 510 | static void | 
| 511 | usage(void) | 
| 512 | { | 
| 513 |  | 
| 514 | 	(void)fprintf(stderr, | 
| 515 | 	    "Usage: %s [-agln] [-Ghkm|-ihkm|-Pk] [-t type] [file | "  | 
| 516 | 	    "file_system ...]\n" , | 
| 517 | 	    getprogname()); | 
| 518 | 	exit(1); | 
| 519 | 	/* NOTREACHED */ | 
| 520 | } | 
| 521 |  |