1 1.104 christos /* $NetBSD: df.c,v 1.104 2024/10/06 17:03:28 christos Exp $ */ 2 1.19 cgd 3 1.12 cgd /* 4 1.15 mycroft * Copyright (c) 1980, 1990, 1993, 1994 5 1.15 mycroft * The Regents of the University of California. All rights reserved. 6 1.12 cgd * (c) UNIX System Laboratories, Inc. 7 1.12 cgd * All or some portions of this file are derived from material licensed 8 1.12 cgd * to the University of California by American Telephone and Telegraph 9 1.12 cgd * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 1.12 cgd * the permission of UNIX System Laboratories, Inc. 11 1.12 cgd * 12 1.12 cgd * Redistribution and use in source and binary forms, with or without 13 1.12 cgd * modification, are permitted provided that the following conditions 14 1.12 cgd * are met: 15 1.12 cgd * 1. Redistributions of source code must retain the above copyright 16 1.12 cgd * notice, this list of conditions and the following disclaimer. 17 1.12 cgd * 2. Redistributions in binary form must reproduce the above copyright 18 1.12 cgd * notice, this list of conditions and the following disclaimer in the 19 1.12 cgd * documentation and/or other materials provided with the distribution. 20 1.49 agc * 3. Neither the name of the University nor the names of its contributors 21 1.12 cgd * may be used to endorse or promote products derived from this software 22 1.12 cgd * without specific prior written permission. 23 1.12 cgd * 24 1.12 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 1.12 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 1.12 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 1.12 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 1.12 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 1.12 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 1.12 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 1.12 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 1.12 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 1.12 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 1.12 cgd * SUCH DAMAGE. 35 1.12 cgd */ 36 1.12 cgd 37 1.24 thorpej #include <sys/cdefs.h> 38 1.12 cgd #ifndef lint 39 1.24 thorpej __COPYRIGHT( 40 1.83 lukem "@(#) Copyright (c) 1980, 1990, 1993, 1994\ 41 1.83 lukem The Regents of the University of California. All rights reserved."); 42 1.12 cgd #endif /* not lint */ 43 1.12 cgd 44 1.12 cgd #ifndef lint 45 1.19 cgd #if 0 46 1.19 cgd static char sccsid[] = "@(#)df.c 8.7 (Berkeley) 4/2/94"; 47 1.19 cgd #else 48 1.104 christos __RCSID("$NetBSD: df.c,v 1.104 2024/10/06 17:03:28 christos Exp $"); 49 1.19 cgd #endif 50 1.12 cgd #endif /* not lint */ 51 1.12 cgd 52 1.12 cgd #include <sys/param.h> 53 1.12 cgd #include <sys/stat.h> 54 1.12 cgd #include <sys/mount.h> 55 1.27 mrg 56 1.75 christos #include <assert.h> 57 1.15 mycroft #include <err.h> 58 1.12 cgd #include <errno.h> 59 1.94 christos #include <stdbool.h> 60 1.12 cgd #include <fcntl.h> 61 1.82 christos #include <locale.h> 62 1.44 provos #include <util.h> 63 1.12 cgd #include <stdio.h> 64 1.12 cgd #include <stdlib.h> 65 1.12 cgd #include <string.h> 66 1.12 cgd #include <unistd.h> 67 1.87 christos #include <util.h> 68 1.12 cgd 69 1.87 christos static char *getmntpt(const char *); 70 1.98 ginsbach static void addstat(struct statvfs *, const struct statvfs *); 71 1.95 christos static void prtstat(const struct statvfs *, int); 72 1.87 christos static int selected(const char *, size_t); 73 1.87 christos static void maketypelist(char *); 74 1.87 christos static size_t regetmntinfo(struct statvfs **, size_t); 75 1.87 christos __dead static void usage(void); 76 1.96 ryo static void prthumanval(int64_t, int); 77 1.94 christos static void prthuman(const struct statvfs *, int64_t, int64_t); 78 1.87 christos 79 1.100 kre static int aflag, cflag, fflag, gflag, hflag, iflag, lflag; 80 1.103 kre static int Mflag, Nflag, nflag, Pflag, qflag, Wflag; 81 1.87 christos static long usize; 82 1.87 christos static char **typelist; 83 1.100 kre static size_t mntcount; 84 1.12 cgd 85 1.97 ryo #define WIDTH_INODE 10 86 1.97 ryo #define WIDTH_BLKSIZE 12 87 1.97 ryo static int blksize_width = WIDTH_BLKSIZE; 88 1.96 ryo 89 1.100 kre static int fudgeunits = 0; 90 1.100 kre 91 1.103 kre #define streq(a, b) (strcmp((a), (b)) == 0) 92 1.103 kre #define warnq(args) do { if (!qflag) warnx args; } while (0) 93 1.103 kre 94 1.12 cgd int 95 1.41 enami main(int argc, char *argv[]) 96 1.12 cgd { 97 1.12 cgd struct stat stbuf; 98 1.98 ginsbach struct statvfs *mntbuf, totals; 99 1.94 christos int ch, maxwidth, width; 100 1.100 kre size_t i; 101 1.12 cgd char *mntpt; 102 1.12 cgd 103 1.82 christos setprogname(argv[0]); 104 1.82 christos (void)setlocale(LC_ALL, ""); 105 1.82 christos 106 1.103 kre while ((ch = getopt(argc, argv, "abcfGgHhiklMmNnPqt:W")) != -1) 107 1.15 mycroft switch (ch) { 108 1.34 christos case 'a': 109 1.34 christos aflag = 1; 110 1.34 christos break; 111 1.100 kre case 'b': 112 1.100 kre hflag = 0; 113 1.100 kre usize = 512; 114 1.100 kre break; 115 1.98 ginsbach case 'c': 116 1.98 ginsbach cflag = 1; 117 1.98 ginsbach break; 118 1.100 kre case 'f': 119 1.100 kre fflag = 1; 120 1.100 kre break; 121 1.81 christos case 'g': 122 1.71 christos hflag = 0; 123 1.71 christos usize = 1024 * 1024 * 1024; 124 1.46 grant break; 125 1.81 christos case 'G': 126 1.73 christos gflag = 1; 127 1.73 christos break; 128 1.100 kre case 'H': 129 1.100 kre fudgeunits = HN_DIVISOR_1000; 130 1.100 kre /* FALL THROUGH */ 131 1.44 provos case 'h': 132 1.44 provos hflag = 1; 133 1.71 christos usize = 0; 134 1.44 provos break; 135 1.12 cgd case 'i': 136 1.12 cgd iflag = 1; 137 1.12 cgd break; 138 1.12 cgd case 'k': 139 1.71 christos hflag = 0; 140 1.71 christos usize = 1024; 141 1.12 cgd break; 142 1.12 cgd case 'l': 143 1.17 mycroft lflag = 1; 144 1.12 cgd break; 145 1.103 kre case 'M': 146 1.103 kre Mflag = 1; 147 1.103 kre break; 148 1.36 hubertf case 'm': 149 1.71 christos hflag = 0; 150 1.71 christos usize = 1024 * 1024; 151 1.36 hubertf break; 152 1.100 kre case 'N': 153 1.100 kre Nflag = 1; 154 1.100 kre break; 155 1.12 cgd case 'n': 156 1.12 cgd nflag = 1; 157 1.12 cgd break; 158 1.35 kleink case 'P': 159 1.35 kleink Pflag = 1; 160 1.35 kleink break; 161 1.103 kre case 'q': 162 1.103 kre qflag = 1; 163 1.103 kre break; 164 1.94 christos case 'W': 165 1.94 christos Wflag = 1; 166 1.94 christos break; 167 1.16 mycroft case 't': 168 1.17 mycroft if (typelist != NULL) 169 1.80 christos errx(EXIT_FAILURE, 170 1.80 christos "only one -t option may be specified."); 171 1.17 mycroft maketypelist(optarg); 172 1.16 mycroft break; 173 1.12 cgd case '?': 174 1.12 cgd default: 175 1.12 cgd usage(); 176 1.12 cgd } 177 1.73 christos 178 1.100 kre if (fflag && (Pflag || gflag)) 179 1.100 kre errx(EXIT_FAILURE, 180 1.100 kre "only one of -f -G and -P may be specified"); 181 1.73 christos if (gflag && (Pflag || iflag)) 182 1.80 christos errx(EXIT_FAILURE, 183 1.81 christos "only one of -G and -P or -i may be specified"); 184 1.73 christos if (Pflag && iflag) 185 1.80 christos errx(EXIT_FAILURE, 186 1.80 christos "only one of -P and -i may be specified"); 187 1.100 kre if (fflag) 188 1.100 kre Nflag = 1; 189 1.100 kre 190 1.80 christos #if 0 191 1.80 christos /* 192 1.80 christos * The block size cannot be checked until after getbsize() is called. 193 1.80 christos */ 194 1.75 christos if (Pflag && (hflag || (usize != 1024 && usize != 512))) 195 1.80 christos errx(EXIT_FAILURE, 196 1.80 christos "non-standard block size incompatible with -P"); 197 1.80 christos #endif 198 1.12 cgd argc -= optind; 199 1.12 cgd argv += optind; 200 1.12 cgd 201 1.94 christos mntcount = getmntinfo(&mntbuf, MNT_NOWAIT); 202 1.94 christos if (mntcount == 0) 203 1.80 christos err(EXIT_FAILURE, 204 1.80 christos "retrieving information on mounted file systems"); 205 1.15 mycroft 206 1.41 enami if (*argv == NULL) { 207 1.94 christos mntcount = regetmntinfo(&mntbuf, mntcount); 208 1.17 mycroft } else { 209 1.94 christos if ((mntbuf = calloc(argc, sizeof(*mntbuf))) == NULL) 210 1.80 christos err(EXIT_FAILURE, "can't allocate statvfs array"); 211 1.94 christos mntcount = 0; 212 1.80 christos for (/*EMPTY*/; *argv != NULL; argv++) { 213 1.17 mycroft if (stat(*argv, &stbuf) < 0) { 214 1.17 mycroft if ((mntpt = getmntpt(*argv)) == 0) { 215 1.103 kre if (!qflag) 216 1.103 kre warn("%s", *argv); 217 1.12 cgd continue; 218 1.12 cgd } 219 1.18 mycroft } else if (S_ISBLK(stbuf.st_mode)) { 220 1.43 soren if ((mntpt = getmntpt(*argv)) == 0) 221 1.43 soren mntpt = *argv; 222 1.17 mycroft } else 223 1.17 mycroft mntpt = *argv; 224 1.103 kre 225 1.17 mycroft /* 226 1.17 mycroft * Statfs does not take a `wait' flag, so we cannot 227 1.17 mycroft * implement nflag here. 228 1.17 mycroft */ 229 1.103 kre if (!statvfs(mntpt, &mntbuf[mntcount])) { 230 1.103 kre if (Mflag && 231 1.103 kre !streq(mntpt, mntbuf[mntcount].f_mntonname)) 232 1.103 kre warnq(("%s is not a mount point", 233 1.103 kre mntpt)); 234 1.103 kre else if (lflag && 235 1.94 christos (mntbuf[mntcount].f_flag & MNT_LOCAL) == 0) 236 1.103 kre warnq(("Warning: %s is not a local %s", 237 1.103 kre *argv, "file system")); 238 1.23 thorpej else if 239 1.94 christos (!selected(mntbuf[mntcount].f_fstypename, 240 1.94 christos sizeof(mntbuf[mntcount].f_fstypename))) 241 1.103 kre warnq(("Warning: %s mounted as a %s %s", 242 1.23 thorpej *argv, 243 1.94 christos mntbuf[mntcount].f_fstypename, 244 1.103 kre "file system")); 245 1.23 thorpej else 246 1.94 christos ++mntcount; 247 1.103 kre } else if (!qflag) 248 1.17 mycroft warn("%s", *argv); 249 1.12 cgd } 250 1.12 cgd } 251 1.17 mycroft 252 1.98 ginsbach if (cflag) { 253 1.98 ginsbach memset(&totals, 0, sizeof(totals)); 254 1.99 simonb totals.f_frsize = DEV_BSIZE; 255 1.98 ginsbach strlcpy(totals.f_mntfromname, "total", 256 1.98 ginsbach sizeof(totals.f_mntfromname)); 257 1.98 ginsbach } 258 1.98 ginsbach 259 1.17 mycroft maxwidth = 0; 260 1.94 christos for (i = 0; i < mntcount; i++) { 261 1.102 kre width = 0; 262 1.102 kre if (Wflag && mntbuf[i].f_mntfromlabel[0]) { 263 1.102 kre /* +5 is for "NAME=" added later */ 264 1.102 kre width = (int)strlen(mntbuf[i].f_mntfromlabel) + 5; 265 1.102 kre } 266 1.102 kre if (width == 0) 267 1.102 kre width = (int)strlen(mntbuf[i].f_mntfromname); 268 1.17 mycroft if (width > maxwidth) 269 1.17 mycroft maxwidth = width; 270 1.98 ginsbach if (cflag) 271 1.98 ginsbach addstat(&totals, &mntbuf[i]); 272 1.17 mycroft } 273 1.98 ginsbach 274 1.100 kre if (cflag == 0 || fflag == 0) 275 1.100 kre for (i = 0; i < mntcount; i++) 276 1.100 kre prtstat(&mntbuf[i], maxwidth); 277 1.100 kre 278 1.100 kre mntcount = fflag; 279 1.98 ginsbach if (cflag) 280 1.98 ginsbach prtstat(&totals, maxwidth); 281 1.98 ginsbach 282 1.87 christos return 0; 283 1.12 cgd } 284 1.12 cgd 285 1.87 christos static char * 286 1.87 christos getmntpt(const char *name) 287 1.12 cgd { 288 1.100 kre size_t count, i; 289 1.62 christos struct statvfs *mntbuf; 290 1.12 cgd 291 1.100 kre count = getmntinfo(&mntbuf, MNT_NOWAIT); 292 1.100 kre if (count == 0) 293 1.87 christos err(EXIT_FAILURE, "Can't get mount information"); 294 1.100 kre for (i = 0; i < count; i++) { 295 1.103 kre if (streq(mntbuf[i].f_mntfromname, name)) 296 1.87 christos return mntbuf[i].f_mntonname; 297 1.12 cgd } 298 1.87 christos return 0; 299 1.12 cgd } 300 1.12 cgd 301 1.17 mycroft static enum { IN_LIST, NOT_IN_LIST } which; 302 1.17 mycroft 303 1.87 christos static int 304 1.76 christos selected(const char *type, size_t len) 305 1.17 mycroft { 306 1.17 mycroft char **av; 307 1.17 mycroft 308 1.17 mycroft /* If no type specified, it's always selected. */ 309 1.17 mycroft if (typelist == NULL) 310 1.87 christos return 1; 311 1.17 mycroft for (av = typelist; *av != NULL; ++av) 312 1.76 christos if (!strncmp(type, *av, len)) 313 1.87 christos return which == IN_LIST ? 1 : 0; 314 1.87 christos return which == IN_LIST ? 0 : 1; 315 1.17 mycroft } 316 1.16 mycroft 317 1.87 christos static void 318 1.41 enami maketypelist(char *fslist) 319 1.16 mycroft { 320 1.87 christos size_t i; 321 1.17 mycroft char *nextcp, **av; 322 1.16 mycroft 323 1.17 mycroft if ((fslist == NULL) || (fslist[0] == '\0')) 324 1.80 christos errx(EXIT_FAILURE, "empty type list"); 325 1.16 mycroft 326 1.17 mycroft /* 327 1.17 mycroft * XXX 328 1.17 mycroft * Note: the syntax is "noxxx,yyy" for no xxx's and 329 1.17 mycroft * no yyy's, not the more intuitive "noyyy,noyyy". 330 1.17 mycroft */ 331 1.17 mycroft if (fslist[0] == 'n' && fslist[1] == 'o') { 332 1.17 mycroft fslist += 2; 333 1.17 mycroft which = NOT_IN_LIST; 334 1.17 mycroft } else 335 1.17 mycroft which = IN_LIST; 336 1.17 mycroft 337 1.17 mycroft /* Count the number of types. */ 338 1.24 thorpej for (i = 1, nextcp = fslist; 339 1.24 thorpej (nextcp = strchr(nextcp, ',')) != NULL; i++) 340 1.17 mycroft ++nextcp; 341 1.17 mycroft 342 1.17 mycroft /* Build an array of that many types. */ 343 1.94 christos if ((av = typelist = calloc((i + 1), sizeof(*av))) == NULL) 344 1.80 christos err(EXIT_FAILURE, "can't allocate type array"); 345 1.17 mycroft av[0] = fslist; 346 1.24 thorpej for (i = 1, nextcp = fslist; 347 1.24 thorpej (nextcp = strchr(nextcp, ',')) != NULL; i++) { 348 1.17 mycroft *nextcp = '\0'; 349 1.17 mycroft av[i] = ++nextcp; 350 1.16 mycroft } 351 1.17 mycroft /* Terminate the array. */ 352 1.17 mycroft av[i] = NULL; 353 1.17 mycroft } 354 1.16 mycroft 355 1.17 mycroft /* 356 1.17 mycroft * Make a pass over the filesystem info in ``mntbuf'' filtering out 357 1.17 mycroft * filesystem types not in ``fsmask'' and possibly re-stating to get 358 1.62 christos * current (not cached) info. Returns the new count of valid statvfs bufs. 359 1.17 mycroft */ 360 1.87 christos static size_t 361 1.100 kre regetmntinfo(struct statvfs **mntbufp, size_t count) 362 1.17 mycroft { 363 1.87 christos size_t i, j; 364 1.62 christos struct statvfs *mntbuf; 365 1.16 mycroft 366 1.42 christos if (!lflag && typelist == NULL && aflag) 367 1.100 kre return nflag ? count : (size_t)getmntinfo(mntbufp, MNT_WAIT); 368 1.16 mycroft 369 1.17 mycroft mntbuf = *mntbufp; 370 1.17 mycroft j = 0; 371 1.100 kre for (i = 0; i < count; i++) { 372 1.62 christos if (!aflag && (mntbuf[i].f_flag & MNT_IGNORE) != 0) 373 1.34 christos continue; 374 1.62 christos if (lflag && (mntbuf[i].f_flag & MNT_LOCAL) == 0) 375 1.17 mycroft continue; 376 1.76 christos if (!selected(mntbuf[i].f_fstypename, 377 1.76 christos sizeof(mntbuf[i].f_fstypename))) 378 1.17 mycroft continue; 379 1.17 mycroft if (nflag) 380 1.17 mycroft mntbuf[j] = mntbuf[i]; 381 1.32 sommerfe else { 382 1.62 christos struct statvfs layerbuf = mntbuf[i]; 383 1.62 christos (void)statvfs(mntbuf[i].f_mntonname, &mntbuf[j]); 384 1.32 sommerfe /* 385 1.32 sommerfe * If the FS name changed, then new data is for 386 1.32 sommerfe * a different layer and we don't want it. 387 1.32 sommerfe */ 388 1.41 enami if (memcmp(layerbuf.f_mntfromname, 389 1.41 enami mntbuf[j].f_mntfromname, MNAMELEN)) 390 1.41 enami mntbuf[j] = layerbuf; 391 1.32 sommerfe } 392 1.17 mycroft j++; 393 1.16 mycroft } 394 1.87 christos return j; 395 1.16 mycroft } 396 1.16 mycroft 397 1.87 christos static void 398 1.96 ryo prthumanval(int64_t bytes, int width) 399 1.44 provos { 400 1.59 enami char buf[6]; 401 1.44 provos 402 1.80 christos (void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 403 1.59 enami bytes, "", HN_AUTOSCALE, 404 1.100 kre HN_B | HN_NOSPACE | HN_DECIMAL | fudgeunits); 405 1.44 provos 406 1.96 ryo (void)printf("%*s", width, buf); 407 1.44 provos } 408 1.44 provos 409 1.87 christos static void 410 1.94 christos prthuman(const struct statvfs *sfsp, int64_t used, int64_t bavail) 411 1.44 provos { 412 1.60 enami 413 1.97 ryo prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), blksize_width); 414 1.97 ryo prthumanval((int64_t)(used * sfsp->f_frsize), 1 + blksize_width); 415 1.97 ryo prthumanval((int64_t)(bavail * sfsp->f_frsize), 1 + blksize_width); 416 1.44 provos } 417 1.44 provos 418 1.12 cgd /* 419 1.62 christos * Convert statvfs returned filesystem size into BLOCKSIZE units. 420 1.15 mycroft * Attempts to avoid overflow for large filesystems. 421 1.15 mycroft */ 422 1.41 enami #define fsbtoblk(num, fsbs, bs) \ 423 1.84 lukem (((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ? \ 424 1.63 martin (int64_t)(num) / (int64_t)((bs) / (fsbs)) : \ 425 1.85 lukem (int64_t)(num) * (int64_t)((fsbs) / (bs))) 426 1.15 mycroft 427 1.98 ginsbach static void 428 1.98 ginsbach addstat(struct statvfs *totalfsp, const struct statvfs *sfsp) 429 1.98 ginsbach { 430 1.98 ginsbach uint64_t frsize; 431 1.98 ginsbach 432 1.98 ginsbach frsize = sfsp->f_frsize / totalfsp->f_frsize; 433 1.98 ginsbach totalfsp->f_blocks += sfsp->f_blocks * frsize; 434 1.98 ginsbach totalfsp->f_bfree += sfsp->f_bfree * frsize; 435 1.98 ginsbach totalfsp->f_bavail += sfsp->f_bavail * frsize; 436 1.98 ginsbach totalfsp->f_bresvd += sfsp->f_bresvd * frsize; 437 1.98 ginsbach totalfsp->f_files += sfsp->f_files; 438 1.98 ginsbach totalfsp->f_ffree += sfsp->f_ffree; 439 1.98 ginsbach totalfsp->f_favail += sfsp->f_favail; 440 1.98 ginsbach totalfsp->f_fresvd += sfsp->f_fresvd; 441 1.98 ginsbach } 442 1.98 ginsbach 443 1.15 mycroft /* 444 1.12 cgd * Print out status about a filesystem. 445 1.12 cgd */ 446 1.87 christos static void 447 1.95 christos prtstat(const struct statvfs *sfsp, int maxwidth) 448 1.12 cgd { 449 1.17 mycroft static long blocksize; 450 1.12 cgd static int headerlen, timesthrough; 451 1.68 christos static const char *header; 452 1.87 christos static const char full[] = "100"; 453 1.87 christos static const char empty[] = " 0"; 454 1.62 christos int64_t used, availblks, inodes; 455 1.60 enami int64_t bavail; 456 1.87 christos char pb[64]; 457 1.95 christos char mntfromname[sizeof(sfsp->f_mntfromname) + 10]; 458 1.94 christos 459 1.95 christos if (Wflag && sfsp->f_mntfromlabel[0]) { 460 1.94 christos snprintf(mntfromname, sizeof(mntfromname), "NAME=%s", 461 1.95 christos sfsp->f_mntfromlabel); 462 1.94 christos } else { 463 1.94 christos strlcpy(mntfromname, sfsp->f_mntfromname, sizeof(mntfromname)); 464 1.94 christos } 465 1.12 cgd 466 1.73 christos if (gflag) { 467 1.73 christos /* 468 1.73 christos * From SunOS-5.6: 469 1.73 christos * 470 1.80 christos * /var (/dev/dsk/c0t0d0s3 ): 8192 block size 1024 frag size 471 1.75 christos * 984242 total blocks 860692 free blocks 859708 available 249984 total files 472 1.80 christos * 248691 free files 8388611 filesys id 473 1.75 christos * ufs fstype 0x00000004 flag 255 filename length 474 1.73 christos * 475 1.73 christos */ 476 1.73 christos (void)printf("%10s (%-12s): %7ld block size %12ld frag size\n", 477 1.94 christos sfsp->f_mntonname, mntfromname, 478 1.91 christos sfsp->f_bsize, /* On UFS/FFS systems this is 479 1.73 christos * also called the "optimal 480 1.73 christos * transfer block size" but it 481 1.73 christos * is of course the file 482 1.73 christos * system's block size too. 483 1.73 christos */ 484 1.91 christos sfsp->f_frsize); /* not so surprisingly the 485 1.73 christos * "fundamental file system 486 1.73 christos * block size" is the frag 487 1.73 christos * size. 488 1.73 christos */ 489 1.80 christos (void)printf("%10" PRId64 " total blocks %10" PRId64 490 1.73 christos " free blocks %10" PRId64 " available\n", 491 1.73 christos (uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree, 492 1.73 christos (uint64_t)sfsp->f_bavail); 493 1.75 christos (void)printf("%10" PRId64 " total files %10" PRId64 494 1.73 christos " free files %12lx filesys id\n", 495 1.104 christos (uint64_t)sfsp->f_files, (uint64_t)sfsp->f_ffree, 496 1.73 christos sfsp->f_fsid); 497 1.75 christos (void)printf("%10s fstype %#15lx flag %17ld filename " 498 1.73 christos "length\n", sfsp->f_fstypename, sfsp->f_flag, 499 1.73 christos sfsp->f_namemax); 500 1.73 christos (void)printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64 501 1.73 christos " asyncwrites\n\n", (unsigned long)sfsp->f_owner, 502 1.73 christos sfsp->f_syncwrites, sfsp->f_asyncwrites); 503 1.73 christos 504 1.73 christos /* 505 1.73 christos * a concession by the structured programming police to the 506 1.73 christos * indentation police.... 507 1.73 christos */ 508 1.73 christos return; 509 1.73 christos } 510 1.73 christos if (maxwidth < 12) 511 1.73 christos maxwidth = 12; 512 1.12 cgd if (++timesthrough == 1) { 513 1.71 christos switch (blocksize = usize) { 514 1.100 kre case 512: 515 1.100 kre header = "512-blocks"; 516 1.100 kre headerlen = (int)strlen(header); 517 1.100 kre break; 518 1.71 christos case 1024: 519 1.35 kleink header = Pflag ? "1024-blocks" : "1K-blocks"; 520 1.80 christos headerlen = (int)strlen(header); 521 1.71 christos break; 522 1.71 christos case 1024 * 1024: 523 1.75 christos header = "1M-blocks"; 524 1.80 christos headerlen = (int)strlen(header); 525 1.71 christos break; 526 1.71 christos case 1024 * 1024 * 1024: 527 1.75 christos header = "1G-blocks"; 528 1.80 christos headerlen = (int)strlen(header); 529 1.71 christos break; 530 1.71 christos default: 531 1.71 christos if (hflag) { 532 1.75 christos header = "Size"; 533 1.80 christos headerlen = (int)strlen(header); 534 1.97 ryo blksize_width = 6; 535 1.71 christos } else 536 1.71 christos header = getbsize(&headerlen, &blocksize); 537 1.71 christos break; 538 1.71 christos } 539 1.97 ryo 540 1.97 ryo if (blocksize >= 1024 * 1024) 541 1.97 ryo blksize_width -= 3; 542 1.97 ryo if (blocksize >= 1024 * 1024 * 1024) 543 1.97 ryo blksize_width -= 3; 544 1.97 ryo if (blksize_width < headerlen) 545 1.97 ryo blksize_width = headerlen; 546 1.97 ryo 547 1.73 christos if (Pflag) { 548 1.73 christos /* 549 1.75 christos * either: 550 1.75 christos * "Filesystem 1024-blocks Used Available Capacity Mounted on\n" 551 1.75 christos * or: 552 1.75 christos * "Filesystem 512-blocks Used Available Capacity Mounted on\n" 553 1.73 christos */ 554 1.80 christos if (blocksize != 1024 && blocksize != 512) 555 1.80 christos errx(EXIT_FAILURE, 556 1.80 christos "non-standard block size incompatible with -P"); 557 1.73 christos (void)printf("Filesystem %s Used Available Capacity " 558 1.73 christos "Mounted on\n", header); 559 1.100 kre } else if (!Nflag) { 560 1.96 ryo (void)printf("%-*.*s %*s %*s %*s %%Cap", 561 1.96 ryo maxwidth, maxwidth, "Filesystem", 562 1.97 ryo blksize_width, header, 563 1.97 ryo blksize_width, "Used", 564 1.97 ryo blksize_width, "Avail"); 565 1.96 ryo if (iflag) { 566 1.96 ryo (void)printf(" %*s %*s %%iCap", 567 1.96 ryo WIDTH_INODE, "iUsed", 568 1.96 ryo WIDTH_INODE, "iAvail"); 569 1.96 ryo } 570 1.73 christos (void)printf(" Mounted on\n"); 571 1.73 christos } 572 1.12 cgd } 573 1.12 cgd used = sfsp->f_blocks - sfsp->f_bfree; 574 1.62 christos bavail = sfsp->f_bfree - sfsp->f_bresvd; 575 1.62 christos availblks = bavail + used; 576 1.73 christos if (Pflag) { 577 1.75 christos assert(hflag == 0); 578 1.75 christos assert(blocksize > 0); 579 1.73 christos /* 580 1.73 christos * "%s %d %d %d %s %s\n", <file system name>, <total space>, 581 1.73 christos * <space used>, <space free>, <percentage used>, 582 1.80 christos * <file system root> 583 1.73 christos */ 584 1.87 christos (void)printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s%% %s\n", 585 1.94 christos mntfromname, 586 1.86 mlelstv fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), 587 1.86 mlelstv fsbtoblk(used, sfsp->f_frsize, blocksize), 588 1.86 mlelstv fsbtoblk(bavail, sfsp->f_frsize, blocksize), 589 1.90 christos availblks == 0 ? full : strspct(pb, sizeof(pb), used, 590 1.87 christos availblks, 0), sfsp->f_mntonname); 591 1.73 christos /* 592 1.73 christos * another concession by the structured programming police to 593 1.73 christos * the indentation police.... 594 1.73 christos * 595 1.73 christos * Note iflag cannot be set when Pflag is set. 596 1.73 christos */ 597 1.73 christos return; 598 1.73 christos } 599 1.73 christos 600 1.100 kre if (fflag) { 601 1.100 kre if (iflag) 602 1.100 kre (void)printf("%jd", sfsp->f_ffree); 603 1.100 kre else if (hflag) 604 1.100 kre prthumanval(bavail * sfsp->f_frsize, 1); 605 1.100 kre else 606 1.100 kre (void)printf("%jd", fsbtoblk(bavail, 607 1.100 kre sfsp->f_frsize, blocksize)); 608 1.100 kre 609 1.100 kre if (mntcount != 1) 610 1.100 kre (void)printf(" %s\n", sfsp->f_mntonname); 611 1.100 kre else 612 1.100 kre (void)printf("\n"); 613 1.100 kre return; 614 1.100 kre } 615 1.100 kre 616 1.94 christos (void)printf("%-*.*s ", maxwidth, maxwidth, mntfromname); 617 1.73 christos 618 1.44 provos if (hflag) 619 1.65 enami prthuman(sfsp, used, bavail); 620 1.61 enami else 621 1.96 ryo (void)printf("%*" PRId64 " %*" PRId64 " %*" PRId64, 622 1.97 ryo blksize_width, 623 1.62 christos fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), 624 1.97 ryo blksize_width, fsbtoblk(used, sfsp->f_frsize, blocksize), 625 1.97 ryo blksize_width, fsbtoblk(bavail, sfsp->f_frsize, blocksize)); 626 1.87 christos (void)printf(" %3s%%", 627 1.66 enami availblks == 0 ? full : 628 1.90 christos strspct(pb, sizeof(pb), used, availblks, 0)); 629 1.12 cgd if (iflag) { 630 1.12 cgd inodes = sfsp->f_files; 631 1.12 cgd used = inodes - sfsp->f_ffree; 632 1.96 ryo (void)printf(" %*jd %*jd %4s%%", 633 1.96 ryo WIDTH_INODE, (intmax_t)used, 634 1.96 ryo WIDTH_INODE, (intmax_t)sfsp->f_ffree, 635 1.57 enami inodes == 0 ? (used == 0 ? empty : full) : 636 1.90 christos strspct(pb, sizeof(pb), used, inodes, 0)); 637 1.73 christos } 638 1.73 christos (void)printf(" %s\n", sfsp->f_mntonname); 639 1.12 cgd } 640 1.12 cgd 641 1.87 christos static void 642 1.41 enami usage(void) 643 1.12 cgd { 644 1.41 enami 645 1.34 christos (void)fprintf(stderr, 646 1.103 kre "Usage: %s [-aclMnqW] [-G|-bkP|-bfgHhikmN] [-t type] [file | " 647 1.100 kre "file_system]...\n", 648 1.40 cgd getprogname()); 649 1.12 cgd exit(1); 650 1.30 mycroft /* NOTREACHED */ 651 1.12 cgd } 652