19ddb49cbSWarner Losh /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro 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 } 257f3895a82SKris Kennaway } else if (S_ISCHR(stbuf.st_mode)) { 25811ed25f2SUlrich Spörlein if ((mntpt = getmntpt(*argv)) == NULL) { 259*e3e94324SBrooks Davis #ifdef MOUNT_CHAR_DEVS 260*e3e94324SBrooks Davis xo_warnx( 261*e3e94324SBrooks Davis "df on unmounted devices is deprecated"); 262f3895a82SKris Kennaway mdev.fspec = *argv; 263f3895a82SKris Kennaway mntpath = strdup("/tmp/df.XXXXXX"); 264f3895a82SKris Kennaway if (mntpath == NULL) { 265b6ff8745SMarcel Moolenaar xo_warn("strdup failed"); 266f3895a82SKris Kennaway rv = 1; 2674b88c807SRodney W. Grimes continue; 268f3895a82SKris Kennaway } 269f3895a82SKris Kennaway mntpt = mkdtemp(mntpath); 270f3895a82SKris Kennaway if (mntpt == NULL) { 271b6ff8745SMarcel Moolenaar xo_warn("mkdtemp(\"%s\") failed", mntpath); 272f3895a82SKris Kennaway rv = 1; 273f3895a82SKris Kennaway free(mntpath); 274f3895a82SKris Kennaway continue; 275f3895a82SKris Kennaway } 276facc3cb0SBrooks Davis if (iov != NULL) 277facc3cb0SBrooks Davis free_iovec(&iov, &iovlen); 278facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "fstype", "%s", 279facc3cb0SBrooks Davis fstype); 280facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "fspath", "%s", 281facc3cb0SBrooks Davis mntpath); 282facc3cb0SBrooks Davis build_iovec_argf(&iov, &iovlen, "from", "%s", 283facc3cb0SBrooks Davis *argv); 284facc3cb0SBrooks Davis build_iovec(&iov, &iovlen, "errmsg", errmsg, 285facc3cb0SBrooks Davis sizeof(errmsg)); 286facc3cb0SBrooks Davis if (nmount(iov, iovlen, 287facc3cb0SBrooks Davis MNT_RDONLY|MNT_NOEXEC) < 0) { 288facc3cb0SBrooks Davis if (errmsg[0]) 289facc3cb0SBrooks Davis xo_warn("%s: %s", *argv, 290facc3cb0SBrooks Davis errmsg); 291facc3cb0SBrooks Davis else 292b6ff8745SMarcel Moolenaar xo_warn("%s", *argv); 293532aff98SPoul-Henning Kamp rv = 1; 294f3895a82SKris Kennaway (void)rmdir(mntpt); 295f3895a82SKris Kennaway free(mntpath); 296f3895a82SKris Kennaway continue; 297f3895a82SKris Kennaway } else if (statfs(mntpt, &statfsbuf) == 0) { 298f3895a82SKris Kennaway statfsbuf.f_mntonname[0] = '\0'; 29962edbd31SIan Dowse prtstat(&statfsbuf, &maxwidths); 300076419d2SDavid E. O'Brien if (cflag) 301076419d2SDavid E. O'Brien addstat(&totalbuf, &statfsbuf); 302f3895a82SKris Kennaway } else { 303b6ff8745SMarcel Moolenaar xo_warn("%s", *argv); 304f3895a82SKris Kennaway rv = 1; 305f3895a82SKris Kennaway } 306f3895a82SKris Kennaway (void)unmount(mntpt, 0); 307f3895a82SKris Kennaway (void)rmdir(mntpt); 308f3895a82SKris Kennaway free(mntpath); 309f3895a82SKris Kennaway continue; 310*e3e94324SBrooks Davis #else 311*e3e94324SBrooks Davis xo_warnx("%s: not mounted", *argv); 312*e3e94324SBrooks Davis rv = 1; 313*e3e94324SBrooks Davis continue; 314176d3efdSBrooks Davis #endif 315*e3e94324SBrooks Davis } 3164b88c807SRodney W. Grimes } else 3174b88c807SRodney W. Grimes mntpt = *argv; 3180e7d023fSBruce Evans 3194b88c807SRodney W. Grimes /* 3204b88c807SRodney W. Grimes * Statfs does not take a `wait' flag, so we cannot 3214b88c807SRodney W. Grimes * implement nflag here. 3224b88c807SRodney W. Grimes */ 3234b88c807SRodney W. Grimes if (statfs(mntpt, &statfsbuf) < 0) { 324b6ff8745SMarcel Moolenaar xo_warn("%s", mntpt); 325b8904f2aSJoerg Wunsch rv = 1; 3264b88c807SRodney W. Grimes continue; 3274b88c807SRodney W. Grimes } 3280e7d023fSBruce Evans 3290e7d023fSBruce Evans /* 3300e7d023fSBruce Evans * Check to make sure the arguments we've been given are 3310e7d023fSBruce Evans * satisfied. Return an error if we have been asked to 3320e7d023fSBruce Evans * list a mount point that does not match the other args 3330e7d023fSBruce Evans * we've been given (-l, -t, etc.). 334c22acefbSJordan K. Hubbard */ 335c22acefbSJordan K. Hubbard if (checkvfsname(statfsbuf.f_fstypename, vfslist)) { 3360e7d023fSBruce Evans rv = 1; 337c22acefbSJordan K. Hubbard continue; 338c22acefbSJordan K. Hubbard } 3390e7d023fSBruce Evans 3407b0514faSDag-Erling Smørgrav /* the user asked for it, so ignore the ignore flag */ 3417b0514faSDag-Erling Smørgrav statfsbuf.f_flags &= ~MNT_IGNORE; 3427b0514faSDag-Erling Smørgrav 3437b0514faSDag-Erling Smørgrav /* add to list */ 3447b0514faSDag-Erling Smørgrav mntbuf[mntsize++] = statfsbuf; 3457b0514faSDag-Erling Smørgrav } 3467b0514faSDag-Erling Smørgrav 34711ed25f2SUlrich Spörlein memset(&maxwidths, 0, sizeof(maxwidths)); 3487b0514faSDag-Erling Smørgrav for (i = 0; i < mntsize; i++) { 3497b0514faSDag-Erling Smørgrav if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) { 3507b0514faSDag-Erling Smørgrav update_maxwidths(&maxwidths, &mntbuf[i]); 351076419d2SDavid E. O'Brien if (cflag) 3527b0514faSDag-Erling Smørgrav addstat(&totalbuf, &mntbuf[i]); 3534b88c807SRodney W. Grimes } 3547b0514faSDag-Erling Smørgrav } 3557b0514faSDag-Erling Smørgrav for (i = 0; i < mntsize; i++) 3567b0514faSDag-Erling Smørgrav if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) 3577b0514faSDag-Erling Smørgrav prtstat(&mntbuf[i], &maxwidths); 358b6ff8745SMarcel Moolenaar 359b6ff8745SMarcel Moolenaar xo_close_list("filesystem"); 360b6ff8745SMarcel Moolenaar 361076419d2SDavid E. O'Brien if (cflag) 362076419d2SDavid E. O'Brien prtstat(&totalbuf, &maxwidths); 363b6ff8745SMarcel Moolenaar 364b6ff8745SMarcel Moolenaar xo_close_container("storage-system-information"); 365b6ff8745SMarcel Moolenaar xo_finish(); 366d5183594SXin LI exit(rv); 3674b88c807SRodney W. Grimes } 3684b88c807SRodney W. Grimes 369532aff98SPoul-Henning Kamp static char * 370b7dbd3e9SMark Murray getmntpt(const char *name) 3714b88c807SRodney W. Grimes { 372be2c4e54SDavid E. O'Brien size_t mntsize, i; 3734b88c807SRodney W. Grimes struct statfs *mntbuf; 3744b88c807SRodney W. Grimes 3754b88c807SRodney W. Grimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 3764b88c807SRodney W. Grimes for (i = 0; i < mntsize; i++) { 3774b88c807SRodney W. Grimes if (!strcmp(mntbuf[i].f_mntfromname, name)) 3784b88c807SRodney W. Grimes return (mntbuf[i].f_mntonname); 3794b88c807SRodney W. Grimes } 38011ed25f2SUlrich Spörlein return (NULL); 3814b88c807SRodney W. Grimes } 3824b88c807SRodney W. Grimes 3834b88c807SRodney W. Grimes /* 3844b88c807SRodney W. Grimes * Make a pass over the file system info in ``mntbuf'' filtering out 385a78192e3SBruce Evans * file system types not in vfslist and possibly re-stating to get 3864b88c807SRodney W. Grimes * current (not cached) info. Returns the new count of valid statfs bufs. 3874b88c807SRodney W. Grimes */ 388be2c4e54SDavid E. O'Brien static size_t 389532aff98SPoul-Henning Kamp regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) 3904b88c807SRodney W. Grimes { 391239c9e60SChristian S.J. Peron int error, i, j; 3924b88c807SRodney W. Grimes struct statfs *mntbuf; 3934b88c807SRodney W. Grimes 394a78192e3SBruce Evans if (vfslist == NULL) 3954b88c807SRodney W. Grimes return (nflag ? mntsize : getmntinfo(mntbufp, MNT_WAIT)); 3964b88c807SRodney W. Grimes 3974b88c807SRodney W. Grimes mntbuf = *mntbufp; 398a78192e3SBruce Evans for (j = 0, i = 0; i < mntsize; i++) { 399a78192e3SBruce Evans if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 400a78192e3SBruce Evans continue; 401239c9e60SChristian S.J. Peron /* 402239c9e60SChristian S.J. Peron * XXX statfs(2) can fail for various reasons. It may be 403239c9e60SChristian S.J. Peron * possible that the user does not have access to the 404239c9e60SChristian S.J. Peron * pathname, if this happens, we will fall back on 405239c9e60SChristian S.J. Peron * "stale" filesystem statistics. 406239c9e60SChristian S.J. Peron */ 407239c9e60SChristian S.J. Peron error = statfs(mntbuf[i].f_mntonname, &mntbuf[j]); 408239c9e60SChristian S.J. Peron if (nflag || error < 0) 409239c9e60SChristian S.J. Peron if (i != j) { 410239c9e60SChristian S.J. Peron if (error < 0) 411b6ff8745SMarcel Moolenaar xo_warnx("%s stats possibly stale", 412239c9e60SChristian S.J. Peron mntbuf[i].f_mntonname); 4134b88c807SRodney W. Grimes mntbuf[j] = mntbuf[i]; 414239c9e60SChristian S.J. Peron } 4154b88c807SRodney W. Grimes j++; 4164b88c807SRodney W. Grimes } 4174b88c807SRodney W. Grimes return (j); 4184b88c807SRodney W. Grimes } 4194b88c807SRodney W. Grimes 420532aff98SPoul-Henning Kamp static void 421fde81c7dSKirk McKusick prthuman(const struct statfs *sfsp, int64_t used) 422dd6d33e8SMichael Haro { 423dd6d33e8SMichael Haro 424b6ff8745SMarcel Moolenaar prthumanval(" {:blocks/%6s}", sfsp->f_blocks * sfsp->f_bsize); 425b6ff8745SMarcel Moolenaar prthumanval(" {:used/%6s}", used * sfsp->f_bsize); 426b6ff8745SMarcel Moolenaar prthumanval(" {:available/%6s}", sfsp->f_bavail * sfsp->f_bsize); 427dd6d33e8SMichael Haro } 428dd6d33e8SMichael Haro 429532aff98SPoul-Henning Kamp static void 430b6ff8745SMarcel Moolenaar prthumanval(const char *fmt, int64_t bytes) 431dd6d33e8SMichael Haro { 4327d3940bbSPawel Jakub Dawidek char buf[6]; 4337d3940bbSPawel Jakub Dawidek int flags; 434dd6d33e8SMichael Haro 4357d3940bbSPawel Jakub Dawidek flags = HN_B | HN_NOSPACE | HN_DECIMAL; 4367d3940bbSPawel Jakub Dawidek if (hflag == UNITS_SI) 4377d3940bbSPawel Jakub Dawidek flags |= HN_DIVISOR_1000; 438dd6d33e8SMichael Haro 4397d3940bbSPawel Jakub Dawidek humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 4407d3940bbSPawel Jakub Dawidek bytes, "", HN_AUTOSCALE, flags); 4417d3940bbSPawel Jakub Dawidek 442b6ff8745SMarcel Moolenaar xo_attr("value", "%lld", (long long) bytes); 443b6ff8745SMarcel Moolenaar xo_emit(fmt, buf); 444dd6d33e8SMichael Haro } 445dd6d33e8SMichael Haro 446dd6d33e8SMichael Haro /* 447b93ce3b7SSimon L. B. Nielsen * Print an inode count in "human-readable" format. 448b93ce3b7SSimon L. B. Nielsen */ 449b93ce3b7SSimon L. B. Nielsen static void 450b6ff8745SMarcel Moolenaar prthumanvalinode(const char *fmt, int64_t bytes) 451b93ce3b7SSimon L. B. Nielsen { 452b93ce3b7SSimon L. B. Nielsen char buf[6]; 453b93ce3b7SSimon L. B. Nielsen int flags; 454b93ce3b7SSimon L. B. Nielsen 455b93ce3b7SSimon L. B. Nielsen flags = HN_NOSPACE | HN_DECIMAL | HN_DIVISOR_1000; 456b93ce3b7SSimon L. B. Nielsen 457b93ce3b7SSimon L. B. Nielsen humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), 458b93ce3b7SSimon L. B. Nielsen bytes, "", HN_AUTOSCALE, flags); 459b93ce3b7SSimon L. B. Nielsen 460b6ff8745SMarcel Moolenaar xo_attr("value", "%lld", (long long) bytes); 461b6ff8745SMarcel Moolenaar xo_emit(fmt, buf); 462b93ce3b7SSimon L. B. Nielsen } 463b93ce3b7SSimon L. B. Nielsen 464b93ce3b7SSimon L. B. Nielsen /* 4654b88c807SRodney W. Grimes * Convert statfs returned file system size into BLOCKSIZE units. 4664b88c807SRodney W. Grimes */ 467841fe8e8SDavid Schultz static intmax_t 468841fe8e8SDavid Schultz fsbtoblk(int64_t num, uint64_t fsbs, u_long bs) 469841fe8e8SDavid Schultz { 4706b7aceb8SGreg Lehey return (num * (intmax_t) fsbs / (int64_t) bs); 471841fe8e8SDavid Schultz } 4724b88c807SRodney W. Grimes 4734b88c807SRodney W. Grimes /* 4744b88c807SRodney W. Grimes * Print out status about a file system. 4754b88c807SRodney W. Grimes */ 476532aff98SPoul-Henning Kamp static void 47762edbd31SIan Dowse prtstat(struct statfs *sfsp, struct maxwidths *mwp) 4784b88c807SRodney W. Grimes { 4792897dce8SAlexander Kabaev static long blocksize; 480b7dbd3e9SMark Murray static int headerlen, timesthrough = 0; 481a95a13bbSKris Kennaway static const char *header; 482fde81c7dSKirk McKusick int64_t used, availblks, inodes; 483019e4a53SGreg Lehey const char *format; 4844b88c807SRodney W. Grimes 4854b88c807SRodney W. Grimes if (++timesthrough == 1) { 4860bd9f151SIan Dowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem")); 487b56ca465SPawel Jakub Dawidek mwp->fstype = imax(mwp->fstype, (int)strlen("Type")); 488019e4a53SGreg Lehey if (thousands) { /* make space for commas */ 489019e4a53SGreg Lehey mwp->total += (mwp->total - 1) / 3; 490019e4a53SGreg Lehey mwp->used += (mwp->used - 1) / 3; 491019e4a53SGreg Lehey mwp->avail += (mwp->avail - 1) / 3; 492019e4a53SGreg Lehey mwp->iused += (mwp->iused - 1) / 3; 493019e4a53SGreg Lehey mwp->ifree += (mwp->ifree - 1) / 3; 494019e4a53SGreg Lehey } 495dd6d33e8SMichael Haro if (hflag) { 496dd6d33e8SMichael Haro header = " Size"; 4970bd9f151SIan Dowse mwp->total = mwp->used = mwp->avail = 4980bd9f151SIan Dowse (int)strlen(header); 499dd6d33e8SMichael Haro } else { 500dd6d33e8SMichael Haro header = getbsize(&headerlen, &blocksize); 5010bd9f151SIan Dowse mwp->total = imax(mwp->total, headerlen); 502dd6d33e8SMichael Haro } 5030bd9f151SIan Dowse mwp->used = imax(mwp->used, (int)strlen("Used")); 5040bd9f151SIan Dowse mwp->avail = imax(mwp->avail, (int)strlen("Avail")); 50562edbd31SIan Dowse 506b6ff8745SMarcel Moolenaar xo_emit("{T:/%-*s}", mwp->mntfrom, "Filesystem"); 507b56ca465SPawel Jakub Dawidek if (Tflag) 508b6ff8745SMarcel Moolenaar xo_emit(" {T:/%-*s}", mwp->fstype, "Type"); 509dfde8e4bSPhil Shafer xo_emit(" {T:/%*s} {T:/%*s} {T:/%*s} {T:Capacity}", 510b6ff8745SMarcel Moolenaar mwp->total, header, 5110bd9f151SIan Dowse mwp->used, "Used", mwp->avail, "Avail"); 51262edbd31SIan Dowse if (iflag) { 513b93ce3b7SSimon L. B. Nielsen mwp->iused = imax(hflag ? 0 : mwp->iused, 514b93ce3b7SSimon L. B. Nielsen (int)strlen(" iused")); 515b93ce3b7SSimon L. B. Nielsen mwp->ifree = imax(hflag ? 0 : mwp->ifree, 516b93ce3b7SSimon L. B. Nielsen (int)strlen("ifree")); 517b6ff8745SMarcel Moolenaar xo_emit(" {T:/%*s} {T:/%*s} {T:\%iused}", 5180bd9f151SIan Dowse mwp->iused - 2, "iused", mwp->ifree, "ifree"); 51962edbd31SIan Dowse } 520b6ff8745SMarcel Moolenaar xo_emit(" {T:Mounted on}\n"); 5214b88c807SRodney W. Grimes } 522b6ff8745SMarcel Moolenaar 523b6ff8745SMarcel Moolenaar xo_open_instance("filesystem"); 52471cfc678SGreg Lehey /* Check for 0 block size. Can this happen? */ 52571cfc678SGreg Lehey if (sfsp->f_bsize == 0) { 526b6ff8745SMarcel Moolenaar xo_warnx ("File system %s does not have a block size, assuming 512.", 52771cfc678SGreg Lehey sfsp->f_mntonname); 52871cfc678SGreg Lehey sfsp->f_bsize = 512; 52971cfc678SGreg Lehey } 530b6ff8745SMarcel Moolenaar xo_emit("{tk:name/%-*s}", mwp->mntfrom, sfsp->f_mntfromname); 531b56ca465SPawel Jakub Dawidek if (Tflag) 532b6ff8745SMarcel Moolenaar xo_emit(" {:type/%-*s}", mwp->fstype, sfsp->f_fstypename); 5334b88c807SRodney W. Grimes used = sfsp->f_blocks - sfsp->f_bfree; 5344b88c807SRodney W. Grimes availblks = sfsp->f_bavail + used; 535dd6d33e8SMichael Haro if (hflag) { 536dd6d33e8SMichael Haro prthuman(sfsp, used); 537dd6d33e8SMichael Haro } else { 538019e4a53SGreg Lehey if (thousands) 539b6ff8745SMarcel Moolenaar format = " {t:total-blocks/%*j'd} {t:used-blocks/%*j'd} " 540b6ff8745SMarcel Moolenaar "{t:available-blocks/%*j'd}"; 541019e4a53SGreg Lehey else 542b6ff8745SMarcel Moolenaar format = " {t:total-blocks/%*jd} {t:used-blocks/%*jd} " 543b6ff8745SMarcel Moolenaar "{t:available-blocks/%*jd}"; 544b6ff8745SMarcel Moolenaar xo_emit(format, 545841fe8e8SDavid Schultz mwp->total, fsbtoblk(sfsp->f_blocks, 5460bd9f151SIan Dowse sfsp->f_bsize, blocksize), 547841fe8e8SDavid Schultz mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize), 548841fe8e8SDavid Schultz mwp->avail, fsbtoblk(sfsp->f_bavail, 5490bd9f151SIan Dowse sfsp->f_bsize, blocksize)); 550dd6d33e8SMichael Haro } 551b6ff8745SMarcel Moolenaar xo_emit(" {:used-percent/%5.0f}{U:%%}", 5524b88c807SRodney W. Grimes availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); 5534b88c807SRodney W. Grimes if (iflag) { 5544b88c807SRodney W. Grimes inodes = sfsp->f_files; 5554b88c807SRodney W. Grimes used = inodes - sfsp->f_ffree; 556b93ce3b7SSimon L. B. Nielsen if (hflag) { 557b6ff8745SMarcel Moolenaar xo_emit(" "); 558b6ff8745SMarcel Moolenaar prthumanvalinode(" {:inodes-used/%5s}", used); 559b6ff8745SMarcel Moolenaar prthumanvalinode(" {:inodes-free/%5s}", sfsp->f_ffree); 560b93ce3b7SSimon L. B. Nielsen } else { 561019e4a53SGreg Lehey if (thousands) 562b6ff8745SMarcel Moolenaar format = " {:inodes-used/%*j'd} {:inodes-free/%*j'd}"; 563019e4a53SGreg Lehey else 564b6ff8745SMarcel Moolenaar format = " {:inodes-used/%*jd} {:inodes-free/%*jd}"; 565b6ff8745SMarcel Moolenaar xo_emit(format, mwp->iused, (intmax_t)used, 566b93ce3b7SSimon L. B. Nielsen mwp->ifree, (intmax_t)sfsp->f_ffree); 567b93ce3b7SSimon L. B. Nielsen } 568b6ff8745SMarcel Moolenaar xo_emit(" {:inodes-used-percent/%4.0f}{U:%%} ", 569b6ff8745SMarcel Moolenaar inodes == 0 ? 100.0 : 5700bd9f151SIan Dowse (double)used / (double)inodes * 100.0); 571cca108e6SDavid E. O'Brien } else 572b6ff8745SMarcel Moolenaar xo_emit(" "); 573c6f13844SDavid E. O'Brien if (strncmp(sfsp->f_mntfromname, "total", MNAMELEN) != 0) 574b6ff8745SMarcel Moolenaar xo_emit(" {:mounted-on}", sfsp->f_mntonname); 575b6ff8745SMarcel Moolenaar xo_emit("\n"); 576b6ff8745SMarcel Moolenaar xo_close_instance("filesystem"); 577076419d2SDavid E. O'Brien } 578076419d2SDavid E. O'Brien 579431586a8SXin LI static void 580076419d2SDavid E. O'Brien addstat(struct statfs *totalfsp, struct statfs *statfsp) 581076419d2SDavid E. O'Brien { 582c6f13844SDavid E. O'Brien uint64_t bsize; 583076419d2SDavid E. O'Brien 584c6f13844SDavid E. O'Brien bsize = statfsp->f_bsize / totalfsp->f_bsize; 585076419d2SDavid E. O'Brien totalfsp->f_blocks += statfsp->f_blocks * bsize; 586076419d2SDavid E. O'Brien totalfsp->f_bfree += statfsp->f_bfree * bsize; 587076419d2SDavid E. O'Brien totalfsp->f_bavail += statfsp->f_bavail * bsize; 588076419d2SDavid E. O'Brien totalfsp->f_files += statfsp->f_files; 589076419d2SDavid E. O'Brien totalfsp->f_ffree += statfsp->f_ffree; 5904b88c807SRodney W. Grimes } 5914b88c807SRodney W. Grimes 5924b88c807SRodney W. Grimes /* 59362edbd31SIan Dowse * Update the maximum field-width information in `mwp' based on 59462edbd31SIan Dowse * the file system specified by `sfsp'. 59562edbd31SIan Dowse */ 596532aff98SPoul-Henning Kamp static void 597b7dbd3e9SMark Murray update_maxwidths(struct maxwidths *mwp, const struct statfs *sfsp) 59862edbd31SIan Dowse { 5992897dce8SAlexander Kabaev static long blocksize = 0; 600dc474219SMike Barcroft int dummy; 60162edbd31SIan Dowse 60262edbd31SIan Dowse if (blocksize == 0) 60362edbd31SIan Dowse getbsize(&dummy, &blocksize); 60462edbd31SIan Dowse 6050bd9f151SIan Dowse mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname)); 606b56ca465SPawel Jakub Dawidek mwp->fstype = imax(mwp->fstype, (int)strlen(sfsp->f_fstypename)); 6070bd9f151SIan Dowse mwp->total = imax(mwp->total, int64width( 608fde81c7dSKirk McKusick fsbtoblk((int64_t)sfsp->f_blocks, sfsp->f_bsize, blocksize))); 6090bd9f151SIan Dowse mwp->used = imax(mwp->used, 6100bd9f151SIan Dowse int64width(fsbtoblk((int64_t)sfsp->f_blocks - 611fde81c7dSKirk McKusick (int64_t)sfsp->f_bfree, sfsp->f_bsize, blocksize))); 6120bd9f151SIan Dowse mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail, 61362edbd31SIan Dowse sfsp->f_bsize, blocksize))); 6140bd9f151SIan Dowse mwp->iused = imax(mwp->iused, int64width((int64_t)sfsp->f_files - 61562edbd31SIan Dowse sfsp->f_ffree)); 6160bd9f151SIan Dowse mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree)); 61762edbd31SIan Dowse } 61862edbd31SIan Dowse 6190bd9f151SIan Dowse /* Return the width in characters of the specified value. */ 6200bd9f151SIan Dowse static int 621fde81c7dSKirk McKusick int64width(int64_t val) 62262edbd31SIan Dowse { 6230bd9f151SIan Dowse int len; 62462edbd31SIan Dowse 62562edbd31SIan Dowse len = 0; 62662edbd31SIan Dowse /* Negative or zero values require one extra digit. */ 62762edbd31SIan Dowse if (val <= 0) { 62862edbd31SIan Dowse val = -val; 62962edbd31SIan Dowse len++; 63062edbd31SIan Dowse } 63162edbd31SIan Dowse while (val > 0) { 63262edbd31SIan Dowse len++; 63362edbd31SIan Dowse val /= 10; 63462edbd31SIan Dowse } 63562edbd31SIan Dowse 63662edbd31SIan Dowse return (len); 63762edbd31SIan Dowse } 63862edbd31SIan Dowse 639532aff98SPoul-Henning Kamp static void 640f9bcb0beSWarner Losh usage(void) 6414b88c807SRodney W. Grimes { 642dd6d33e8SMichael Haro 643b6ff8745SMarcel Moolenaar xo_error( 6447eb55d4dSXin LI "usage: df [-b | -g | -H | -h | -k | -m | -P] [-acilnT] [-t type] [-,]\n" 6457eb55d4dSXin LI " [file | filesystem ...]\n"); 646dd6d33e8SMichael Haro exit(EX_USAGE); 6474b88c807SRodney W. Grimes } 648a25695c3SJim Pirzyk 649532aff98SPoul-Henning Kamp static char * 650f9bcb0beSWarner Losh makenetvfslist(void) 651a25695c3SJim Pirzyk { 652a25695c3SJim Pirzyk char *str, *strptr, **listptr; 653b7dbd3e9SMark Murray struct xvfsconf *xvfsp, *keep_xvfsp; 6545965373eSMaxime Henrion size_t buflen; 6555965373eSMaxime Henrion int cnt, i, maxvfsconf; 656a25695c3SJim Pirzyk 6575965373eSMaxime Henrion if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0) { 658b6ff8745SMarcel Moolenaar xo_warn("sysctl(vfs.conflist)"); 659a25695c3SJim Pirzyk return (NULL); 660a25695c3SJim Pirzyk } 6615965373eSMaxime Henrion xvfsp = malloc(buflen); 6625965373eSMaxime Henrion if (xvfsp == NULL) { 663b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 6645965373eSMaxime Henrion return (NULL); 6655965373eSMaxime Henrion } 666b7dbd3e9SMark Murray keep_xvfsp = xvfsp; 6675965373eSMaxime Henrion if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) { 668b6ff8745SMarcel Moolenaar xo_warn("sysctl(vfs.conflist)"); 669b7dbd3e9SMark Murray free(keep_xvfsp); 6705965373eSMaxime Henrion return (NULL); 6715965373eSMaxime Henrion } 6725965373eSMaxime Henrion maxvfsconf = buflen / sizeof(struct xvfsconf); 673a25695c3SJim Pirzyk 674a25695c3SJim Pirzyk if ((listptr = malloc(sizeof(char*) * maxvfsconf)) == NULL) { 675b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 676b7dbd3e9SMark Murray free(keep_xvfsp); 677a25695c3SJim Pirzyk return (NULL); 678a25695c3SJim Pirzyk } 679a25695c3SJim Pirzyk 6805965373eSMaxime Henrion for (cnt = 0, i = 0; i < maxvfsconf; i++) { 6815965373eSMaxime Henrion if (xvfsp->vfc_flags & VFCF_NETWORK) { 6825965373eSMaxime Henrion listptr[cnt++] = strdup(xvfsp->vfc_name); 683a067aeceSGarrett Wollman if (listptr[cnt-1] == NULL) { 684b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 685b7dbd3e9SMark Murray free(listptr); 686b7dbd3e9SMark Murray free(keep_xvfsp); 687a25695c3SJim Pirzyk return (NULL); 688a25695c3SJim Pirzyk } 689a25695c3SJim Pirzyk } 6905965373eSMaxime Henrion xvfsp++; 6915965373eSMaxime Henrion } 692a25695c3SJim Pirzyk 693cf5b29e1SRuslan Ermilov if (cnt == 0 || 694cf5b29e1SRuslan Ermilov (str = malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) { 695cf5b29e1SRuslan Ermilov if (cnt > 0) 696b6ff8745SMarcel Moolenaar xo_warnx("malloc failed"); 697a25695c3SJim Pirzyk free(listptr); 698b7dbd3e9SMark Murray free(keep_xvfsp); 699a25695c3SJim Pirzyk return (NULL); 700a25695c3SJim Pirzyk } 701a25695c3SJim Pirzyk 702a25695c3SJim Pirzyk *str = 'n'; *(str + 1) = 'o'; 703a25695c3SJim Pirzyk for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) { 704d7c881e8SWarner Losh strlcpy(strptr, listptr[i], 32); 705a25695c3SJim Pirzyk strptr += strlen(listptr[i]); 706a25695c3SJim Pirzyk *strptr = ','; 707a25695c3SJim Pirzyk free(listptr[i]); 708a25695c3SJim Pirzyk } 70916fc3635SMark Murray *(--strptr) = '\0'; 710a25695c3SJim Pirzyk 711b7dbd3e9SMark Murray free(keep_xvfsp); 712a25695c3SJim Pirzyk free(listptr); 713a25695c3SJim Pirzyk return (str); 714a25695c3SJim Pirzyk } 715