19ddb49cbSWarner Losh /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro F. Giffuni * 44b88c807SRodney W. Grimes * Copyright (c) 1980, 1990, 1993, 1994 54b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 64b88c807SRodney W. Grimes * (c) UNIX System Laboratories, Inc. 74b88c807SRodney W. Grimes * All or some portions of this file are derived from material licensed 84b88c807SRodney W. Grimes * to the University of California by American Telephone and Telegraph 94b88c807SRodney W. Grimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with 104b88c807SRodney W. Grimes * the permission of UNIX System Laboratories, Inc. 114b88c807SRodney W. Grimes * 124b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 134b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 144b88c807SRodney W. Grimes * are met: 154b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 164b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 174b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 184b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 194b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 20fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 354b88c807SRodney W. Grimes */ 364b88c807SRodney W. Grimes 3709a80d48SDavid E. O'Brien #if 0 384b88c807SRodney W. Grimes #ifndef lint 3916cc192aSSteve Price static const char copyright[] = 404b88c807SRodney W. Grimes "@(#) Copyright (c) 1980, 1990, 1993, 1994\n\ 414b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 424b88c807SRodney W. Grimes #endif /* not lint */ 434b88c807SRodney W. Grimes 444b88c807SRodney W. Grimes #ifndef lint 4516cc192aSSteve Price static char sccsid[] = "@(#)df.c 8.9 (Berkeley) 5/8/95"; 464b88c807SRodney W. Grimes #endif /* not lint */ 4709a80d48SDavid E. O'Brien #endif 485eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 495eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 504b88c807SRodney W. Grimes 514b88c807SRodney W. Grimes #include <sys/param.h> 524b88c807SRodney W. Grimes #include <sys/stat.h> 534b88c807SRodney W. Grimes #include <sys/mount.h> 54a25695c3SJim Pirzyk #include <sys/sysctl.h> 55176d3efdSBrooks Davis #ifdef MOUNT_CHAR_DEVS 56a78192e3SBruce Evans #include <ufs/ufs/ufsmount.h> 57176d3efdSBrooks Davis #endif 584b88c807SRodney W. Grimes #include <err.h> 59d0bc27e4SKyle Evans #include <getopt.h> 607d3940bbSPawel Jakub Dawidek #include <libutil.h> 61019e4a53SGreg Lehey #include <locale.h> 62facc3cb0SBrooks Davis #ifdef MOUNT_CHAR_DEVS 63facc3cb0SBrooks Davis #include <mntopts.h> 64facc3cb0SBrooks Davis #endif 650bd9f151SIan Dowse #include <stdint.h> 664b88c807SRodney W. Grimes #include <stdio.h> 674b88c807SRodney W. Grimes #include <stdlib.h> 684b88c807SRodney W. Grimes #include <string.h> 69dd6d33e8SMichael Haro #include <sysexits.h> 704b88c807SRodney W. Grimes #include <unistd.h> 71b6ff8745SMarcel Moolenaar #include <libxo/xo.h> 724b88c807SRodney W. Grimes 73532aff98SPoul-Henning Kamp #include "extern.h" 74532aff98SPoul-Henning Kamp 75dd6d33e8SMichael Haro #define UNITS_SI 1 76dd6d33e8SMichael Haro #define UNITS_2 2 77dd6d33e8SMichael Haro 7862edbd31SIan Dowse /* Maximum widths of various fields. */ 7962edbd31SIan Dowse struct maxwidths { 800bd9f151SIan Dowse int mntfrom; 81b56ca465SPawel Jakub Dawidek int fstype; 820bd9f151SIan Dowse int total; 830bd9f151SIan Dowse int used; 840bd9f151SIan Dowse int avail; 850bd9f151SIan Dowse int iused; 860bd9f151SIan Dowse int ifree; 8762edbd31SIan Dowse }; 8862edbd31SIan Dowse 89c6f13844SDavid E. O'Brien static void addstat(struct statfs *, struct statfs *); 90b7dbd3e9SMark Murray static char *getmntpt(const char *); 910bd9f151SIan Dowse static int int64width(int64_t); 92532aff98SPoul-Henning Kamp static char *makenetvfslist(void); 93fde81c7dSKirk McKusick static void prthuman(const struct statfs *, int64_t); 94b6ff8745SMarcel Moolenaar static void prthumanval(const char *, int64_t); 95841fe8e8SDavid Schultz static intmax_t fsbtoblk(int64_t, uint64_t, u_long); 96532aff98SPoul-Henning Kamp static void prtstat(struct statfs *, struct maxwidths *); 97be2c4e54SDavid E. O'Brien static size_t regetmntinfo(struct statfs **, long, const char **); 98b7dbd3e9SMark Murray static void update_maxwidths(struct maxwidths *, const struct statfs *); 99532aff98SPoul-Henning Kamp static void usage(void); 1004b88c807SRodney W. Grimes 1010bd9f151SIan Dowse static __inline int 1020bd9f151SIan Dowse imax(int a, int b) 10362edbd31SIan Dowse { 104b7dbd3e9SMark Murray return (a > b ? a : b); 10562edbd31SIan Dowse } 10662edbd31SIan Dowse 107b56ca465SPawel Jakub Dawidek static int aflag = 0, cflag, hflag, iflag, kflag, lflag = 0, nflag, Tflag; 108019e4a53SGreg Lehey static int thousands; 109176d3efdSBrooks Davis #ifdef MOUNT_CHAR_DEVS 110532aff98SPoul-Henning Kamp static struct ufs_args mdev; 111176d3efdSBrooks Davis #endif 112532aff98SPoul-Henning Kamp 113d0bc27e4SKyle Evans static const struct option long_options[] = 114d0bc27e4SKyle Evans { 115d0bc27e4SKyle Evans { "si", no_argument, NULL, 'H' }, 116d0bc27e4SKyle Evans { NULL, no_argument, NULL, 0 }, 117d0bc27e4SKyle Evans }; 118d0bc27e4SKyle Evans 1194b88c807SRodney W. Grimes int 120f9bcb0beSWarner Losh main(int argc, char *argv[]) 1214b88c807SRodney W. Grimes { 1224b88c807SRodney W. Grimes struct stat stbuf; 123c6f13844SDavid E. O'Brien struct statfs statfsbuf, totalbuf; 12462edbd31SIan Dowse struct maxwidths maxwidths; 125c6f13844SDavid E. O'Brien struct statfs *mntbuf; 126facc3cb0SBrooks Davis #ifdef MOUNT_CHAR_DEVS 127facc3cb0SBrooks Davis struct iovec *iov = NULL; 128facc3cb0SBrooks Davis #endif 129a95a13bbSKris Kennaway const char *fstype; 130176d3efdSBrooks Davis #ifdef MOUNT_CHAR_DEVS 131176d3efdSBrooks Davis char *mntpath; 132facc3cb0SBrooks Davis char errmsg[255] = {0}; 133176d3efdSBrooks Davis #endif 134176d3efdSBrooks Davis char *mntpt; 135532aff98SPoul-Henning Kamp const char **vfslist; 1367b0514faSDag-Erling Smørgrav int i, mntsize; 137be2c4e54SDavid E. O'Brien int ch, rv; 138facc3cb0SBrooks Davis #ifdef MOUNT_CHAR_DEVS 139facc3cb0SBrooks Davis int iovlen = 0; 140facc3cb0SBrooks Davis #endif 141f3895a82SKris Kennaway 142f3895a82SKris Kennaway fstype = "ufs"; 143019e4a53SGreg Lehey (void)setlocale(LC_ALL, ""); 14411ed25f2SUlrich Spörlein memset(&maxwidths, 0, sizeof(maxwidths)); 145076419d2SDavid E. O'Brien memset(&totalbuf, 0, sizeof(totalbuf)); 146076419d2SDavid E. O'Brien totalbuf.f_bsize = DEV_BSIZE; 147d7c881e8SWarner Losh strlcpy(totalbuf.f_mntfromname, "total", MNAMELEN); 148a78192e3SBruce Evans vfslist = NULL; 149b6ff8745SMarcel Moolenaar 150b6ff8745SMarcel Moolenaar argc = xo_parse_args(argc, argv); 151b6ff8745SMarcel Moolenaar if (argc < 0) 152b6ff8745SMarcel Moolenaar exit(1); 153b6ff8745SMarcel Moolenaar 154d0bc27e4SKyle Evans while ((ch = getopt_long(argc, argv, "+abcgHhiklmnPt:T,", long_options, 155d0bc27e4SKyle Evans NULL)) != -1) 1564b88c807SRodney W. Grimes switch (ch) { 1575b42dac8SJulian Elischer case 'a': 1585b42dac8SJulian Elischer aflag = 1; 1595b42dac8SJulian Elischer break; 160dd6d33e8SMichael Haro case 'b': 161dd6d33e8SMichael Haro /* FALLTHROUGH */ 162dd6d33e8SMichael Haro case 'P': 163df464e43SChristian S.J. Peron /* 1646bccea7cSRebecca Cran * POSIX specifically discusses the behavior of 165df464e43SChristian S.J. Peron * both -k and -P. It states that the blocksize should 166df464e43SChristian S.J. Peron * be set to 1024. Thus, if this occurs, simply break 167df464e43SChristian S.J. Peron * rather than clobbering the old blocksize. 168df464e43SChristian S.J. Peron */ 169df464e43SChristian S.J. Peron if (kflag) 170df464e43SChristian S.J. Peron break; 1712966d28cSSean Farley setenv("BLOCKSIZE", "512", 1); 172dd6d33e8SMichael Haro hflag = 0; 173dd6d33e8SMichael Haro break; 174c6f13844SDavid E. O'Brien case 'c': 175c6f13844SDavid E. O'Brien cflag = 1; 176c6f13844SDavid E. O'Brien break; 17793a3fa19SJohn W. De Boskey case 'g': 1782966d28cSSean Farley setenv("BLOCKSIZE", "1g", 1); 17993a3fa19SJohn W. De Boskey hflag = 0; 18093a3fa19SJohn W. De Boskey break; 181dd6d33e8SMichael Haro case 'H': 182dd6d33e8SMichael Haro hflag = UNITS_SI; 183dd6d33e8SMichael Haro break; 184dd6d33e8SMichael Haro case 'h': 185dd6d33e8SMichael Haro hflag = UNITS_2; 186dd6d33e8SMichael Haro break; 1874b88c807SRodney W. Grimes case 'i': 1884b88c807SRodney W. Grimes iflag = 1; 1894b88c807SRodney W. Grimes break; 1907f0eabfdSGarrett Wollman case 'k': 191df464e43SChristian S.J. Peron kflag++; 1922966d28cSSean Farley setenv("BLOCKSIZE", "1024", 1); 193dd6d33e8SMichael Haro hflag = 0; 194dd6d33e8SMichael Haro break; 195a25695c3SJim Pirzyk case 'l': 196246ef54fSConrad Meyer /* Ignore duplicate -l */ 197246ef54fSConrad Meyer if (lflag) 198246ef54fSConrad Meyer break; 199a25695c3SJim Pirzyk if (vfslist != NULL) 200b6ff8745SMarcel Moolenaar xo_errx(1, "-l and -t are mutually exclusive."); 201a25695c3SJim Pirzyk vfslist = makevfslist(makenetvfslist()); 20227f82335SWill Andrews lflag = 1; 203a25695c3SJim Pirzyk break; 204dd6d33e8SMichael Haro case 'm': 2052966d28cSSean Farley setenv("BLOCKSIZE", "1m", 1); 206dd6d33e8SMichael Haro hflag = 0; 2077f0eabfdSGarrett Wollman break; 2084b88c807SRodney W. Grimes case 'n': 2094b88c807SRodney W. Grimes nflag = 1; 2104b88c807SRodney W. Grimes break; 2114b88c807SRodney W. Grimes case 't': 21227f82335SWill Andrews if (lflag) 213b6ff8745SMarcel Moolenaar xo_errx(1, "-l and -t are mutually exclusive."); 214a78192e3SBruce Evans if (vfslist != NULL) 215b6ff8745SMarcel Moolenaar xo_errx(1, "only one -t option may be specified"); 216f3895a82SKris Kennaway fstype = optarg; 217a78192e3SBruce Evans vfslist = makevfslist(optarg); 2184b88c807SRodney W. Grimes break; 219b56ca465SPawel Jakub Dawidek case 'T': 220b56ca465SPawel Jakub Dawidek Tflag = 1; 221b56ca465SPawel Jakub Dawidek break; 222019e4a53SGreg Lehey case ',': 223019e4a53SGreg Lehey thousands = 1; 224019e4a53SGreg Lehey break; 2254b88c807SRodney W. Grimes case '?': 2264b88c807SRodney W. Grimes default: 2274b88c807SRodney W. Grimes usage(); 2284b88c807SRodney W. Grimes } 2294b88c807SRodney W. Grimes argc -= optind; 2304b88c807SRodney W. Grimes argv += optind; 2314b88c807SRodney W. Grimes 232b8904f2aSJoerg Wunsch rv = 0; 2334b88c807SRodney W. Grimes if (!*argv) { 2347b0514faSDag-Erling Smørgrav /* everything (modulo -t) */ 2357b0514faSDag-Erling Smørgrav mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 236a78192e3SBruce Evans mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); 2377b0514faSDag-Erling Smørgrav } else { 2387b0514faSDag-Erling Smørgrav /* just the filesystems specified on the command line */ 2397b0514faSDag-Erling Smørgrav mntbuf = malloc(argc * sizeof(*mntbuf)); 24011ed25f2SUlrich Spörlein if (mntbuf == NULL) 241b6ff8745SMarcel Moolenaar xo_err(1, "malloc()"); 2427b0514faSDag-Erling Smørgrav mntsize = 0; 2437b0514faSDag-Erling Smørgrav /* continued in for loop below */ 2444b88c807SRodney W. Grimes } 2454b88c807SRodney W. Grimes 246b6ff8745SMarcel Moolenaar xo_open_container("storage-system-information"); 247b6ff8745SMarcel Moolenaar xo_open_list("filesystem"); 248b6ff8745SMarcel Moolenaar 2497b0514faSDag-Erling Smørgrav /* iterate through specified filesystems */ 2504b88c807SRodney W. Grimes for (; *argv; argv++) { 2514b88c807SRodney W. Grimes if (stat(*argv, &stbuf) < 0) { 25211ed25f2SUlrich Spörlein if ((mntpt = getmntpt(*argv)) == NULL) { 253b6ff8745SMarcel Moolenaar xo_warn("%s", *argv); 254b8904f2aSJoerg Wunsch rv = 1; 2554b88c807SRodney W. Grimes continue; 2564b88c807SRodney W. Grimes } 257176d3efdSBrooks Davis #ifdef MOUNT_CHAR_DEVS 258f3895a82SKris Kennaway } else if (S_ISCHR(stbuf.st_mode)) { 25911ed25f2SUlrich Spörlein if ((mntpt = getmntpt(*argv)) == NULL) { 260f3895a82SKris Kennaway mdev.fspec = *argv; 261f3895a82SKris Kennaway mntpath = strdup("/tmp/df.XXXXXX"); 262f3895a82SKris Kennaway if (mntpath == NULL) { 263b6ff8745SMarcel Moolenaar xo_warn("strdup failed"); 264f3895a82SKris Kennaway rv = 1; 2654b88c807SRodney W. Grimes continue; 266f3895a82SKris Kennaway } 267f3895a82SKris Kennaway mntpt = mkdtemp(mntpath); 268f3895a82SKris Kennaway if (mntpt == NULL) { 269b6ff8745SMarcel Moolenaar xo_warn("mkdtemp(\"%s\") failed", mntpath); 270f3895a82SKris Kennaway rv = 1; 271f3895a82SKris Kennaway free(mntpath); 272f3895a82SKris Kennaway continue; 273f3895a82SKris Kennaway } 274facc3cb0SBrooks Davis if (iov != NULL) 275facc3cb0SBrooks Davis free_iovec(&iov, &iovlen); 276facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "fstype", "%s", 277facc3cb0SBrooks Davis fstype); 278facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "fspath", "%s", 279facc3cb0SBrooks Davis mntpath); 280facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "from", "%s", 281facc3cb0SBrooks Davis *argv); 282facc3cb0SBrooks Davis build_iovec(&iov, &iovlen, "errmsg", errmsg, 283facc3cb0SBrooks Davis sizeof(errmsg)); 284facc3cb0SBrooks Davis if (nmount(iov, iovlen, 285facc3cb0SBrooks Davis MNT_RDONLY|MNT_NOEXEC) < 0) { 286facc3cb0SBrooks Davis if (errmsg[0]) 287facc3cb0SBrooks Davis xo_warn("%s: %s", *argv, 288facc3cb0SBrooks Davis errmsg); 289facc3cb0SBrooks Davis else 290b6ff8745SMarcel Moolenaar xo_warn("%s", *argv); 291532aff98SPoul-Henning Kamp rv = 1; 292f3895a82SKris Kennaway (void)rmdir(mntpt); 293f3895a82SKris Kennaway free(mntpath); 294f3895a82SKris Kennaway continue; 295f3895a82SKris Kennaway } else if (statfs(mntpt, &statfsbuf) == 0) { 296f3895a82SKris Kennaway statfsbuf.f_mntonname[0] = '\0'; 29762edbd31SIan Dowse prtstat(&statfsbuf, &maxwidths); 298076419d2SDavid E. O'Brien if (cflag) 299076419d2SDavid E. O'Brien addstat(&totalbuf, &statfsbuf); 300f3895a82SKris Kennaway } else { 301b6ff8745SMarcel Moolenaar xo_warn("%s", *argv); 302f3895a82SKris Kennaway rv = 1; 303f3895a82SKris Kennaway } 304f3895a82SKris Kennaway (void)unmount(mntpt, 0); 305f3895a82SKris Kennaway (void)rmdir(mntpt); 306f3895a82SKris Kennaway free(mntpath); 307f3895a82SKris Kennaway continue; 308f3895a82SKris Kennaway } 309176d3efdSBrooks Davis #endif 3104b88c807SRodney W. Grimes } else 3114b88c807SRodney W. Grimes mntpt = *argv; 3120e7d023fSBruce Evans 3134b88c807SRodney W. Grimes /* 3144b88c807SRodney W. Grimes * Statfs does not take a `wait' flag, so we cannot 3154b88c807SRodney W. Grimes * implement nflag here. 3164b88c807SRodney W. Grimes */ 3174b88c807SRodney W. Grimes if (statfs(mntpt, &statfsbuf) < 0) { 318b6ff8745SMarcel Moolenaar xo_warn("%s", mntpt); 319b8904f2aSJoerg Wunsch rv = 1; 3204b88c807SRodney W. Grimes continue; 3214b88c807SRodney W. Grimes } 3220e7d023fSBruce Evans 3230e7d023fSBruce Evans /* 3240e7d023fSBruce Evans * Check to make sure the arguments we've been given are 3250e7d023fSBruce Evans * satisfied. Return an error if we have been asked to 3260e7d023fSBruce Evans * list a mount point that does not match the other args 3270e7d023fSBruce Evans * we've been given (-l, -t, etc.). 328c22acefbSJordan K. Hubbard */ 329c22acefbSJordan K. Hubbard if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { 3300e7d023fSBruce Evans rv = 1; 331c22acefbSJordan K. Hubbard continue; 332c22acefbSJordan K. Hubbard } 3330e7d023fSBruce Evans 3347b0514faSDag-Erling Smørgrav /* the user asked for it, so ignore the ignore flag */ 3357b0514faSDag-Erling Smørgrav statfsbuf.f_flags &= ~MNT_IGNORE; 3367b0514faSDag-Erling Smørgrav 3377b0514faSDag-Erling Smørgrav /* add to list */ 3387b0514faSDag-Erling Smørgrav mntbuf[mntsize++] = statfsbuf; 3397b0514faSDag-Erling Smørgrav } 3407b0514faSDag-Erling Smørgrav 34111ed25f2SUlrich Spörlein memset(&maxwidths, 0, sizeof(maxwidths)); 3427b0514faSDag-Erling Smørgrav for (i = 0; i < mntsize; i++) { 3437b0514faSDag-Erling Smørgrav if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) { 3447b0514faSDag-Erling Smørgrav update_maxwidths(&maxwidths, &mntbuf[i]); 345076419d2SDavid E. O'Brien if (cflag) 3467b0514faSDag-Erling Smørgrav addstat(&totalbuf, &mntbuf[i]); 3474b88c807SRodney W. Grimes } 3487b0514faSDag-Erling Smørgrav } 3497b0514faSDag-Erling Smørgrav for (i = 0; i < mntsize; i++) 3507b0514faSDag-Erling Smørgrav if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) 3517b0514faSDag-Erling Smørgrav prtstat(&mntbuf[i], &maxwidths); 352b6ff8745SMarcel Moolenaar 353b6ff8745SMarcel Moolenaar xo_close_list("filesystem"); 354b6ff8745SMarcel Moolenaar 355076419d2SDavid E. O'Brien if (cflag) 356076419d2SDavid E. O'Brien prtstat(&totalbuf, &maxwidths); 357b6ff8745SMarcel Moolenaar 358b6ff8745SMarcel Moolenaar xo_close_container("storage-system-information"); 359b6ff8745SMarcel Moolenaar xo_finish(); 360d5183594SXin LI exit(rv); 3614b88c807SRodney W. Grimes } 3624b88c807SRodney W. Grimes 363532aff98SPoul-Henning Kamp static char * 364b7dbd3e9SMark Murray getmntpt(const char *name) 3654b88c807SRodney W. Grimes { 366be2c4e54SDavid E. O'Brien size_t mntsize, i; 3674b88c807SRodney W. Grimes struct statfs *mntbuf; 3684b88c807SRodney W. Grimes 3694b88c807SRodney W. Grimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 3704b88c807SRodney W. Grimes for (i = 0; i < mntsize; i++) { 3714b88c807SRodney W. Grimes if (!strcmp(mntbuf[i].f_mntfromname, name)) 3724b88c807SRodney W. Grimes return (mntbuf[i].f_mntonname); 3734b88c807SRodney W. Grimes } 37411ed25f2SUlrich Spörlein return (NULL); 3754b88c807SRodney W. Grimes } 3764b88c807SRodney W. Grimes 3774b88c807SRodney W. Grimes /* 3784b88c807SRodney W. Grimes * Make a pass over the file system info in ``mntbuf'' filtering out 379a78192e3SBruce Evans * file system types not in vfslist and possibly re-stating to get 3804b88c807SRodney W. Grimes * current (not cached) info. Returns the new count of valid statfs bufs. 3814b88c807SRodney W. Grimes */ 382be2c4e54SDavid E. O'Brien static size_t 383532aff98SPoul-Henning Kamp regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) 3844b88c807SRodney W. Grimes { 385239c9e60SChristian S.J. Peron int error, i, j; 3864b88c807SRodney W. Grimes struct statfs *mntbuf; 3874b88c807SRodney W. Grimes 388a78192e3SBruce Evans if (vfslist == NULL) 3894b88c807SRodney W. Grimes return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT)); 3904b88c807SRodney W. Grimes 3914b88c807SRodney W. Grimes mntbuf = *mntbufp; 392a78192e3SBruce Evans for (j = 0, i = 0; i < mntsize; i++) { 393a78192e3SBruce Evans if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 394a78192e3SBruce Evans continue; 395239c9e60SChristian S.J. Peron /* 396239c9e60SChristian S.J. Peron * XXX statfs(2) can fail for various reasons. It may be 397239c9e60SChristian S.J. Peron * possible that the user does not have access to the 398239c9e60SChristian S.J. Peron * pathname, if this happens, we will fall back on 399239c9e60SChristian S.J. Peron * "stale" filesystem statistics. 400239c9e60SChristian S.J. Peron */ 401239c9e60SChristian S.J. Peron error = statfs(mntbuf[i].f_mntonname, &mntbuf[j]); 402239c9e60SChristian S.J. Peron if (nflag || error < 0) 403239c9e60SChristian S.J. Peron if (i != j) { 404239c9e60SChristian S.J. Peron if (error < 0) 405b6ff8745SMarcel Moolenaar xo_warnx("%s stats possibly stale", 406239c9e60SChristian S.J. Peron mntbuf[i].f_mntonname); 4074b88c807SRodney W. Grimes mntbuf[j] = mntbuf[i]; 408239c9e60SChristian S.J. Peron } 4094b88c807SRodney W. Grimes j++; 4104b88c807SRodney W. Grimes } 4114b88c807SRodney W. Grimes return (j); 4124b88c807SRodney W. Grimes } 4134b88c807SRodney W. Grimes 414532aff98SPoul-Henning Kamp static void 415fde81c7dSKirk McKusick prthuman(const struct statfs *sfsp, int64_t used) 416dd6d33e8SMichael Haro { 417dd6d33e8SMichael Haro 418b6ff8745SMarcel Moolenaar prthumanval(" {:blocks/%6s}", sfsp->f_blocks * sfsp->f_bsize); 419b6ff8745SMarcel Moolenaar prthumanval(" {:used/%6s}", used * sfsp->f_bsize); 420b6ff8745SMarcel Moolenaar prthumanval(" {:available/%6s}", sfsp->f_bavail * sfsp->f_bsize); 421dd6d33e8SMichael Haro } 422dd6d33e8SMichael Haro 423532aff98SPoul-Henning Kamp static void 424b6ff8745SMarcel Moolenaar prthumanval(const char *fmt, int64_t bytes) 425dd6d33e8SMichael Haro { 4267d3940bbSPawel Jakub Dawidek char buf[6]; 4277d3940bbSPawel Jakub Dawidek int flags; 428dd6d33e8SMichael Haro 4297d3940bbSPawel Jakub Dawidek flags = HN_B | HN_NOSPACE | HN_DECIMAL; 4307d3940bbSPawel Jakub Dawidek if (hflag == UNITS_SI) 4317d3940bbSPawel Jakub Dawidek flags |= HN_DIVISOR_1000; 432dd6d33e8SMichael Haro 4337d3940bbSPawel Jakub Dawidek humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 4347d3940bbSPawel Jakub Dawidek bytes, "", HN_AUTOSCALE, flags); 4357d3940bbSPawel Jakub Dawidek 436b6ff8745SMarcel Moolenaar xo_attr("value", "%lld", (long long) bytes); 437b6ff8745SMarcel Moolenaar xo_emit(fmt, buf); 438dd6d33e8SMichael Haro } 439dd6d33e8SMichael Haro 440dd6d33e8SMichael Haro /* 441b93ce3b7SSimon L. B. Nielsen * Print an inode count in "human-readable" format. 442b93ce3b7SSimon L. B. Nielsen */ 443b93ce3b7SSimon L. B. Nielsen static void 444b6ff8745SMarcel Moolenaar prthumanvalinode(const char *fmt, int64_t bytes) 445b93ce3b7SSimon L. B. Nielsen { 446b93ce3b7SSimon L. B. Nielsen char buf[6]; 447b93ce3b7SSimon L. B. Nielsen int flags; 448b93ce3b7SSimon L. B. Nielsen 449b93ce3b7SSimon L. B. Nielsen flags = HN_NOSPACE | HN_DECIMAL | HN_DIVISOR_1000; 450b93ce3b7SSimon L. B. Nielsen 451b93ce3b7SSimon L. B. Nielsen humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 452b93ce3b7SSimon L. B. Nielsen bytes, "", HN_AUTOSCALE, flags); 453b93ce3b7SSimon L. B. Nielsen 454b6ff8745SMarcel Moolenaar xo_attr("value", "%lld", (long long) bytes); 455b6ff8745SMarcel Moolenaar xo_emit(fmt, buf); 456b93ce3b7SSimon L. B. Nielsen } 457b93ce3b7SSimon L. B. Nielsen 458b93ce3b7SSimon L. B. Nielsen /* 4594b88c807SRodney W. Grimes * Convert statfs returned file system size into BLOCKSIZE units. 4604b88c807SRodney W. Grimes */ 461841fe8e8SDavid Schultz static intmax_t 462841fe8e8SDavid Schultz fsbtoblk(int64_t num, uint64_t fsbs, u_long bs) 463841fe8e8SDavid Schultz { 4646b7aceb8SGreg Lehey return (num * (intmax_t) fsbs / (int64_t) bs); 465841fe8e8SDavid Schultz } 4664b88c807SRodney W. Grimes 4674b88c807SRodney W. Grimes /* 4684b88c807SRodney W. Grimes * Print out status about a file system. 4694b88c807SRodney W. Grimes */ 470532aff98SPoul-Henning Kamp static void 47162edbd31SIan Dowse prtstat(struct statfs *sfsp, struct maxwidths *mwp) 4724b88c807SRodney W. Grimes { 4732897dce8SAlexander Kabaev static long blocksize; 474b7dbd3e9SMark Murray static int headerlen, timesthrough = 0; 475a95a13bbSKris Kennaway static const char *header; 476fde81c7dSKirk McKusick int64_t used, availblks, inodes; 477019e4a53SGreg Lehey const char *format; 4784b88c807SRodney W. Grimes 4794b88c807SRodney W. Grimes if (++timesthrough == 1) { 4800bd9f151SIan Dowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem")); 481b56ca465SPawel Jakub Dawidek mwp->fstype = imax(mwp->fstype, (int)strlen("Type")); 482019e4a53SGreg Lehey if (thousands) { /* make space for commas */ 483019e4a53SGreg Lehey mwp->total += (mwp->total - 1) / 3; 484019e4a53SGreg Lehey mwp->used += (mwp->used - 1) / 3; 485019e4a53SGreg Lehey mwp->avail += (mwp->avail - 1) / 3; 486019e4a53SGreg Lehey mwp->iused += (mwp->iused - 1) / 3; 487019e4a53SGreg Lehey mwp->ifree += (mwp->ifree - 1) / 3; 488019e4a53SGreg Lehey } 489dd6d33e8SMichael Haro if (hflag) { 490dd6d33e8SMichael Haro header = " Size"; 4910bd9f151SIan Dowse mwp->total = mwp->used = mwp->avail = 4920bd9f151SIan Dowse (int)strlen(header); 493dd6d33e8SMichael Haro } else { 494dd6d33e8SMichael Haro header = getbsize(&headerlen, &blocksize); 4950bd9f151SIan Dowse mwp->total = imax(mwp->total, headerlen); 496dd6d33e8SMichael Haro } 4970bd9f151SIan Dowse mwp->used = imax(mwp->used, (int)strlen("Used")); 4980bd9f151SIan Dowse mwp->avail = imax(mwp->avail, (int)strlen("Avail")); 49962edbd31SIan Dowse 500b6ff8745SMarcel Moolenaar xo_emit("{T:/%-*s}", mwp->mntfrom, "Filesystem"); 501b56ca465SPawel Jakub Dawidek if (Tflag) 502b6ff8745SMarcel Moolenaar xo_emit(" {T:/%-*s}", mwp->fstype, "Type"); 503dfde8e4bSPhil Shafer xo_emit(" {T:/%*s} {T:/%*s} {T:/%*s} {T:Capacity}", 504b6ff8745SMarcel Moolenaar mwp->total, header, 5050bd9f151SIan Dowse mwp->used, "Used", mwp->avail, "Avail"); 50662edbd31SIan Dowse if (iflag) { 507b93ce3b7SSimon L. B. Nielsen mwp->iused = imax(hflag ? 0 : mwp->iused, 508b93ce3b7SSimon L. B. Nielsen (int)strlen(" iused")); 509b93ce3b7SSimon L. B. Nielsen mwp->ifree = imax(hflag ? 0 : mwp->ifree, 510b93ce3b7SSimon L. B. Nielsen (int)strlen("ifree")); 511b6ff8745SMarcel Moolenaar xo_emit(" {T:/%*s} {T:/%*s} {T:\%iused}", 5120bd9f151SIan Dowse mwp->iused - 2, "iused", mwp->ifree, "ifree"); 51362edbd31SIan Dowse } 514b6ff8745SMarcel Moolenaar xo_emit(" {T:Mounted on}\n"); 5154b88c807SRodney W. Grimes } 516b6ff8745SMarcel Moolenaar 517b6ff8745SMarcel Moolenaar xo_open_instance("filesystem"); 51871cfc678SGreg Lehey /* Check for 0 block size. Can this happen? */ 51971cfc678SGreg Lehey if (sfsp->f_bsize == 0) { 520b6ff8745SMarcel Moolenaar xo_warnx ("File system %s does not have a block size, assuming 512.", 52171cfc678SGreg Lehey sfsp->f_mntonname); 52271cfc678SGreg Lehey sfsp->f_bsize = 512; 52371cfc678SGreg Lehey } 524b6ff8745SMarcel Moolenaar xo_emit("{tk:name/%-*s}", mwp->mntfrom, sfsp->f_mntfromname); 525b56ca465SPawel Jakub Dawidek if (Tflag) 526b6ff8745SMarcel Moolenaar xo_emit(" {:type/%-*s}", mwp->fstype, sfsp->f_fstypename); 5274b88c807SRodney W. Grimes used = sfsp->f_blocks - sfsp->f_bfree; 5284b88c807SRodney W. Grimes availblks = sfsp->f_bavail + used; 529dd6d33e8SMichael Haro if (hflag) { 530dd6d33e8SMichael Haro prthuman(sfsp, used); 531dd6d33e8SMichael Haro } else { 532019e4a53SGreg Lehey if (thousands) 533b6ff8745SMarcel Moolenaar format = " {t:total-blocks/%*j'd} {t:used-blocks/%*j'd} " 534b6ff8745SMarcel Moolenaar "{t:available-blocks/%*j'd}"; 535019e4a53SGreg Lehey else 536b6ff8745SMarcel Moolenaar format = " {t:total-blocks/%*jd} {t:used-blocks/%*jd} " 537b6ff8745SMarcel Moolenaar "{t:available-blocks/%*jd}"; 538b6ff8745SMarcel Moolenaar xo_emit(format, 539841fe8e8SDavid Schultz mwp->total, fsbtoblk(sfsp->f_blocks, 5400bd9f151SIan Dowse sfsp->f_bsize, blocksize), 541841fe8e8SDavid Schultz mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize), 542841fe8e8SDavid Schultz mwp->avail, fsbtoblk(sfsp->f_bavail, 5430bd9f151SIan Dowse sfsp->f_bsize, blocksize)); 544dd6d33e8SMichael Haro } 545b6ff8745SMarcel Moolenaar xo_emit(" {:used-percent/%5.0f}{U:%%}", 5464b88c807SRodney W. Grimes availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 5474b88c807SRodney W. Grimes if (iflag) { 5484b88c807SRodney W. Grimes inodes = sfsp->f_files; 5494b88c807SRodney W. Grimes used = inodes - sfsp->f_ffree; 550b93ce3b7SSimon L. B. Nielsen if (hflag) { 551b6ff8745SMarcel Moolenaar xo_emit(" "); 552b6ff8745SMarcel Moolenaar prthumanvalinode(" {:inodes-used/%5s}", used); 553b6ff8745SMarcel Moolenaar prthumanvalinode(" {:inodes-free/%5s}", sfsp->f_ffree); 554b93ce3b7SSimon L. B. Nielsen } else { 555019e4a53SGreg Lehey if (thousands) 556b6ff8745SMarcel Moolenaar format = " {:inodes-used/%*j'd} {:inodes-free/%*j'd}"; 557019e4a53SGreg Lehey else 558b6ff8745SMarcel Moolenaar format = " {:inodes-used/%*jd} {:inodes-free/%*jd}"; 559b6ff8745SMarcel Moolenaar xo_emit(format, mwp->iused, (intmax_t)used, 560b93ce3b7SSimon L. B. Nielsen mwp->ifree, (intmax_t)sfsp->f_ffree); 561b93ce3b7SSimon L. B. Nielsen } 562b6ff8745SMarcel Moolenaar xo_emit(" {:inodes-used-percent/%4.0f}{U:%%} ", 563b6ff8745SMarcel Moolenaar inodes == 0 ? 100.0 : 5640bd9f151SIan Dowse (double)used / (double)inodes * 100.0); 565cca108e6SDavid E. O'Brien } else 566b6ff8745SMarcel Moolenaar xo_emit(" "); 567c6f13844SDavid E. O'Brien if (strncmp(sfsp->f_mntfromname, "total", MNAMELEN) != 0) 568b6ff8745SMarcel Moolenaar xo_emit(" {:mounted-on}", sfsp->f_mntonname); 569b6ff8745SMarcel Moolenaar xo_emit("\n"); 570b6ff8745SMarcel Moolenaar xo_close_instance("filesystem"); 571076419d2SDavid E. O'Brien } 572076419d2SDavid E. O'Brien 573431586a8SXin LI static void 574076419d2SDavid E. O'Brien addstat(struct statfs *totalfsp, struct statfs *statfsp) 575076419d2SDavid E. O'Brien { 576c6f13844SDavid E. O'Brien uint64_t bsize; 577076419d2SDavid E. O'Brien 578c6f13844SDavid E. O'Brien bsize = statfsp->f_bsize / totalfsp->f_bsize; 579076419d2SDavid E. O'Brien totalfsp->f_blocks += statfsp->f_blocks * bsize; 580076419d2SDavid E. O'Brien totalfsp->f_bfree += statfsp->f_bfree * bsize; 581076419d2SDavid E. O'Brien totalfsp->f_bavail += statfsp->f_bavail * bsize; 582076419d2SDavid E. O'Brien totalfsp->f_files += statfsp->f_files; 583076419d2SDavid E. O'Brien totalfsp->f_ffree += statfsp->f_ffree; 5844b88c807SRodney W. Grimes } 5854b88c807SRodney W. Grimes 5864b88c807SRodney W. Grimes /* 58762edbd31SIan Dowse * Update the maximum field-width information in `mwp' based on 58862edbd31SIan Dowse * the file system specified by `sfsp'. 58962edbd31SIan Dowse */ 590532aff98SPoul-Henning Kamp static void 591b7dbd3e9SMark Murray update_maxwidths(struct maxwidths *mwp, const struct statfs *sfsp) 59262edbd31SIan Dowse { 5932897dce8SAlexander Kabaev static long blocksize = 0; 594dc474219SMike Barcroft int dummy; 59562edbd31SIan Dowse 59662edbd31SIan Dowse if (blocksize == 0) 59762edbd31SIan Dowse getbsize(&dummy, &blocksize); 59862edbd31SIan Dowse 5990bd9f151SIan Dowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname)); 600b56ca465SPawel Jakub Dawidek mwp->fstype = imax(mwp->fstype, (int)strlen(sfsp->f_fstypename)); 6010bd9f151SIan Dowse mwp->total = imax(mwp->total, int64width( 602fde81c7dSKirk McKusick fsbtoblk((int64_t)sfsp->f_blocks, sfsp->f_bsize, blocksize))); 6030bd9f151SIan Dowse mwp->used = imax(mwp->used, 6040bd9f151SIan Dowse int64width(fsbtoblk((int64_t)sfsp->f_blocks - 605fde81c7dSKirk McKusick (int64_t)sfsp->f_bfree, sfsp->f_bsize, blocksize))); 6060bd9f151SIan Dowse mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail, 60762edbd31SIan Dowse sfsp->f_bsize, blocksize))); 6080bd9f151SIan Dowse mwp->iused = imax(mwp->iused, int64width((int64_t)sfsp->f_files - 60962edbd31SIan Dowse sfsp->f_ffree)); 6100bd9f151SIan Dowse mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree)); 61162edbd31SIan Dowse } 61262edbd31SIan Dowse 6130bd9f151SIan Dowse /* Return the width in characters of the specified value. */ 6140bd9f151SIan Dowse static int 615fde81c7dSKirk McKusick int64width(int64_t val) 61662edbd31SIan Dowse { 6170bd9f151SIan Dowse int len; 61862edbd31SIan Dowse 61962edbd31SIan Dowse len = 0; 62062edbd31SIan Dowse /* Negative or zero values require one extra digit. */ 62162edbd31SIan Dowse if (val <= 0) { 62262edbd31SIan Dowse val = -val; 62362edbd31SIan Dowse len++; 62462edbd31SIan Dowse } 62562edbd31SIan Dowse while (val > 0) { 62662edbd31SIan Dowse len++; 62762edbd31SIan Dowse val /= 10; 62862edbd31SIan Dowse } 62962edbd31SIan Dowse 63062edbd31SIan Dowse return (len); 63162edbd31SIan Dowse } 63262edbd31SIan Dowse 633532aff98SPoul-Henning Kamp static void 634f9bcb0beSWarner Losh usage(void) 6354b88c807SRodney W. Grimes { 636dd6d33e8SMichael Haro 637b6ff8745SMarcel Moolenaar xo_error( 6387eb55d4dSXin LI "usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,]\n" 6397eb55d4dSXin LI " [file | filesystem ...]\n"); 640dd6d33e8SMichael Haro exit(EX_USAGE); 6414b88c807SRodney W. Grimes } 642a25695c3SJim Pirzyk 643532aff98SPoul-Henning Kamp static char * 644f9bcb0beSWarner Losh makenetvfslist(void) 645a25695c3SJim Pirzyk { 646a25695c3SJim Pirzyk char *str, *strptr, **listptr; 647b7dbd3e9SMark Murray struct xvfsconf *xvfsp, *keep_xvfsp; 6485965373eSMaxime Henrion size_t buflen; 6495965373eSMaxime Henrion int cnt, i, maxvfsconf; 650a25695c3SJim Pirzyk 6515965373eSMaxime Henrion if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0) { 652b6ff8745SMarcel Moolenaar xo_warn("sysctl(vfs.conflist)"); 653a25695c3SJim Pirzyk return (NULL); 654a25695c3SJim Pirzyk } 6555965373eSMaxime Henrion xvfsp = malloc(buflen); 6565965373eSMaxime Henrion if (xvfsp == NULL) { 657b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 6585965373eSMaxime Henrion return (NULL); 6595965373eSMaxime Henrion } 660b7dbd3e9SMark Murray keep_xvfsp = xvfsp; 6615965373eSMaxime Henrion if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) { 662b6ff8745SMarcel Moolenaar xo_warn("sysctl(vfs.conflist)"); 663b7dbd3e9SMark Murray free(keep_xvfsp); 6645965373eSMaxime Henrion return (NULL); 6655965373eSMaxime Henrion } 6665965373eSMaxime Henrion maxvfsconf = buflen / sizeof(struct xvfsconf); 667a25695c3SJim Pirzyk 668a25695c3SJim Pirzyk if ((listptr = malloc(sizeof(char*) * maxvfsconf)) == NULL) { 669b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 670b7dbd3e9SMark Murray free(keep_xvfsp); 671a25695c3SJim Pirzyk return (NULL); 672a25695c3SJim Pirzyk } 673a25695c3SJim Pirzyk 6745965373eSMaxime Henrion for (cnt = 0, i = 0; i < maxvfsconf; i++) { 6755965373eSMaxime Henrion if (xvfsp->vfc_flags & VFCF_NETWORK) { 6765965373eSMaxime Henrion listptr[cnt++] = strdup(xvfsp->vfc_name); 677a067aeceSGarrett Wollman if (listptr[cnt-1] == NULL) { 678b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 679b7dbd3e9SMark Murray free(listptr); 680b7dbd3e9SMark Murray free(keep_xvfsp); 681a25695c3SJim Pirzyk return (NULL); 682a25695c3SJim Pirzyk } 683a25695c3SJim Pirzyk } 6845965373eSMaxime Henrion xvfsp++; 6855965373eSMaxime Henrion } 686a25695c3SJim Pirzyk 687cf5b29e1SRuslan Ermilov if (cnt == 0 || 688cf5b29e1SRuslan Ermilov (str = malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) { 689cf5b29e1SRuslan Ermilov if (cnt > 0) 690b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 691a25695c3SJim Pirzyk free(listptr); 692b7dbd3e9SMark Murray free(keep_xvfsp); 693a25695c3SJim Pirzyk return (NULL); 694a25695c3SJim Pirzyk } 695a25695c3SJim Pirzyk 696a25695c3SJim Pirzyk *str = 'n'; *(str + 1) = 'o'; 697a25695c3SJim Pirzyk for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) { 698d7c881e8SWarner Losh strlcpy(strptr, listptr[i], 32); 699a25695c3SJim Pirzyk strptr += strlen(listptr[i]); 700a25695c3SJim Pirzyk *strptr = ','; 701a25695c3SJim Pirzyk free(listptr[i]); 702a25695c3SJim Pirzyk } 70316fc3635SMark Murray *(--strptr) = '\0'; 704a25695c3SJim Pirzyk 705b7dbd3e9SMark Murray free(keep_xvfsp); 706a25695c3SJim Pirzyk free(listptr); 707a25695c3SJim Pirzyk return (str); 708a25695c3SJim Pirzyk } 709