]> git.saurik.com Git - apple/file_cmds.git/blobdiff - df/df.c
file_cmds-321.100.10.0.1.tar.gz
[apple/file_cmds.git] / df / df.c
diff --git a/df/df.c b/df/df.c
index fa104d2b64381b542afac53951e0596af414defc..7e576d781b8de05968fbcef810b8f1fc02ae45ba 100644 (file)
--- a/df/df.c
+++ b/df/df.c
@@ -36,8 +36,9 @@
  * SUCH DAMAGE.
  */
 
+#include <sys/cdefs.h>
 #ifndef lint
-static const char copyright[] =
+__used static const char copyright[] =
 "@(#) Copyright (c) 1980, 1990, 1993, 1994\n\
        The Regents of the University of California.  All rights reserved.\n";
 #endif /* not lint */
@@ -46,15 +47,13 @@ static const char copyright[] =
 #if 0
 static char sccsid[] = "@(#)df.c       8.9 (Berkeley) 5/8/95";
 #else
-static const char rcsid[] =
+__used static const char rcsid[] =
   "$FreeBSD: src/bin/df/df.c,v 1.23.2.9 2002/07/01 00:14:24 iedowse Exp $";
 #endif
 #endif /* not lint */
 
 #ifdef __APPLE__
 #define MNT_IGNORE 0
-#include <sys/types.h> 
-typedef int32_t ufs_daddr_t;
 #endif
 
 #include <sys/cdefs.h>
@@ -62,9 +61,6 @@ typedef int32_t ufs_daddr_t;
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <sys/sysctl.h>
-#include <ufs/ufs/ufsmount.h>
-#include <ufs/ffs/fs.h>
-
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -75,6 +71,13 @@ typedef int32_t ufs_daddr_t;
 #include <string.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <libutil.h>
+
+#ifdef __APPLE__
+#include "get_compat.h"
+#else
+#define COMPAT_MODE(func, mode) 1
+#endif
 
 #define UNITS_SI 1
 #define UNITS_2 2
@@ -118,20 +121,18 @@ unit_t unitp [] = { NONE, KILO, MEGA, GIGA, TERA, PETA };
 int      bread(off_t, void *, int);
 int      checkvfsname(const char *, char **);
 char    *getmntpt(char *);
-int      longwidth(long long);
+int      int64width(int64_t);
 char    *makenetvfslist(void);
-char   **makevfslist(char *);
-void     prthuman(struct statfs *, long);
-void     prthumanval(double);
+char   **makevfslist(const char *);
+void     prthuman(struct statfs *, uint64_t);
+void     prthumanval(int64_t);
 void     prtstat(struct statfs *, struct maxwidths *);
 long     regetmntinfo(struct statfs **, long, char **);
-int      ufs_df(char *, struct maxwidths *);
 unit_t   unit_adjust(double *);
 void     update_maxwidths(struct maxwidths *, struct statfs *);
 void     usage(void);
 
 int    aflag = 0, hflag, iflag, nflag;
-struct ufs_args mdev;
 
 static __inline int imax(int a, int b)
 {
@@ -144,15 +145,22 @@ main(int argc, char *argv[])
        struct stat stbuf;
        struct statfs statfsbuf, *mntbuf;
        struct maxwidths maxwidths;
-       const char *fstype;
-       char *mntpath, *mntpt, **vfslist;
+       char *mntpt, **vfslist;
        long mntsize;
-       int ch, i, rv, tflag = 0;
-
-       fstype = "ufs";
+       int ch, i, rv, tflag = 0, kludge_tflag = 0;
+       int kflag = 0;
+       const char *options = "abgHhiklmnPt:T:";
+       if (COMPAT_MODE("bin/df", "unix2003")) {
+               /* Unix2003 requires -t be "include total capacity". which df
+                 already does, but it conflicts with the old -t so we need to
+                 *not* expect a string after -t (we provide -T in both cases
+                 to cover the old use of -t) */
+               options = "abgHhiklmnPtT:";
+               iflag = 1;
+       }
 
        vfslist = NULL;
-       while ((ch = getopt(argc, argv, "abgHhiklmnPt:")) != -1)
+       while ((ch = getopt(argc, argv, options)) != -1)
                switch (ch) {
                case 'a':
                        aflag = 1;
@@ -160,7 +168,15 @@ main(int argc, char *argv[])
                case 'b':
                                /* FALLTHROUGH */
                case 'P':
-                       putenv("BLOCKSIZE=512");
+                       if (COMPAT_MODE("bin/df", "unix2003")) {
+                               if (!kflag) {
+                                       /* -k overrides -P */
+                                       putenv("BLOCKSIZE=512");
+                               }
+                               iflag = 0;
+                       } else {
+                               putenv("BLOCKSIZE=512");
+                       }
                        hflag = 0;
                        break;
                case 'g':
@@ -179,12 +195,17 @@ main(int argc, char *argv[])
                        iflag = 1;
                        break;
                case 'k':
-                       putenv("BLOCKSIZE=1k");
+                       if (COMPAT_MODE("bin/df", "unix2003")) {
+                               putenv("BLOCKSIZE=1024");
+                       } else {
+                               putenv("BLOCKSIZE=1k");
+                       }
+                       kflag = 1;
                        hflag = 0;
                        break;
                case 'l':
                        if (tflag)
-                               errx(1, "-l and -t are mutually exclusive.");
+                               errx(1, "-l and -T are mutually exclusive.");
                        if (vfslist != NULL)
                                break;
                        vfslist = makevfslist(makenetvfslist());
@@ -197,14 +218,19 @@ main(int argc, char *argv[])
                        nflag = 1;
                        break;
                case 't':
+                       /* Unix2003 uses -t for something we do by default */
+                       if (COMPAT_MODE("bin/df", "unix2003")) {
+                           kludge_tflag = 1;
+                           break;
+                       }
+               case 'T':
                        if (vfslist != NULL) {
                                if (tflag)
-                                       errx(1, "only one -t option may be specified");
+                                       errx(1, "only one -%c option may be specified", ch);
                                else
-                                       errx(1, "-l and -t are mutually exclusive.");
+                                       errx(1, "-l and -%c are mutually exclusive.", ch);
                        }
                        tflag++;
-                       fstype = optarg;
                        vfslist = makevfslist(optarg);
                        break;
                case '?':
@@ -214,6 +240,14 @@ main(int argc, char *argv[])
        argc -= optind;
        argv += optind;
 
+       /* If we are in unix2003 mode, have seen a -t but no -T and the first
+         non switch arg isn't a file, let's pretend they used -T on it.
+         This makes the Lexmark printer installer happy (PR-3918471) */
+       if (tflag == 0 && kludge_tflag && *argv && stat(*argv, &stbuf) < 0
+         && errno == ENOENT) {
+           vfslist = makevfslist(*argv++);
+       }
+
        mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
        bzero(&maxwidths, sizeof(maxwidths));
        for (i = 0; i < mntsize; i++)
@@ -239,40 +273,10 @@ main(int argc, char *argv[])
                                rv = 1;
                                continue;
                        }
-               } else if (S_ISCHR(stbuf.st_mode)) {
-                       if ((mntpt = getmntpt(*argv)) == 0) {
-                               mdev.fspec = *argv;
-                               mntpath = strdup("/tmp/df.XXXXXX");
-                               if (mntpath == NULL) {
-                                       warn("strdup failed");
-                                       rv = 1;
-                                       continue;
-                               }
-                               mntpt = mkdtemp(mntpath);
-                               if (mntpt == NULL) {
-                                       warn("mkdtemp(\"%s\") failed", mntpath);
-                                       rv = 1;
-                                       free(mntpath);
-                                       continue;
-                               }
-                               if (mount(fstype, mntpt, MNT_RDONLY,
-                                   &mdev) != 0) {
-                                       rv = ufs_df(*argv, &maxwidths) || rv;
-                                       (void)rmdir(mntpt);
-                                       free(mntpath);
-                                       continue;
-                               } else if (statfs(mntpt, &statfsbuf) == 0) {
-                                       statfsbuf.f_mntonname[0] = '\0';
-                                       prtstat(&statfsbuf, &maxwidths);
-                               } else {
-                                       warn("%s", *argv);
-                                       rv = 1;
-                               }
-                               (void)unmount(mntpt, 0);
-                               (void)rmdir(mntpt);
-                               free(mntpath);
-                               continue;
-                       }
+               } else if (S_ISCHR(stbuf.st_mode) || S_ISBLK(stbuf.st_mode)) {
+                       warnx("%s: Raw devices not supported", *argv);
+                       rv = 1;
+                       continue;
                } else
                        mntpt = *argv;
                /*
@@ -293,8 +297,9 @@ main(int argc, char *argv[])
                        rv++;
                        continue;
                }
+
                if (argc == 1) {
-                       bzero(&maxwidths, sizeof(maxwidths));
+                       bzero(&maxwidths, sizeof(maxwidths));
                        update_maxwidths(&maxwidths, &statfsbuf);
                }
                prtstat(&statfsbuf, &maxwidths);
@@ -371,36 +376,56 @@ unit_adjust(double *val)
 }
 
 void
-prthuman(struct statfs *sfsp, long used)
+prthuman(struct statfs *sfsp, uint64_t used)
 {
-
-       prthumanval((double)sfsp->f_blocks * (double)sfsp->f_bsize);
-       prthumanval((double)used * (double)sfsp->f_bsize);
-       prthumanval((double)sfsp->f_bavail * (double)sfsp->f_bsize);
+       int64_t value;
+
+       value = sfsp->f_blocks;
+       value *= sfsp->f_bsize;
+        prthumanval(value);
+       value = used;
+       value *= sfsp->f_bsize;
+        prthumanval(value);
+       value = sfsp->f_bavail;
+       value *= sfsp->f_bsize;
+       prthumanval(value);
 }
 
 void
-prthumanval(double bytes)
+prthumanval(int64_t bytes)
 {
+        char buf[6];
+        int flags;
 
-       unit_t unit;
-       unit = unit_adjust(&bytes);
+        flags = HN_B | HN_NOSPACE | HN_DECIMAL;
+        if (hflag == UNITS_SI)
+                flags |= HN_DIVISOR_1000;
 
-       if (bytes == 0)
-               (void)printf("     0B");
-       else if (bytes > 10)
-               (void)printf(" %5.0f%c", bytes, "BKMGTPE"[unit]);
+        humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1),
+                       bytes, "", HN_AUTOSCALE, flags);
+
+       if (hflag == UNITS_SI)
+               (void)printf(" %6s", buf);
        else
-               (void)printf(" %5.1f%c", bytes, "BKMGTPE"[unit]);
+               (void)printf("%6si", buf);
+           
 }
 
 /*
  * Convert statfs returned filesystem size into BLOCKSIZE units.
  * Attempts to avoid overflow for large filesystems.
  */
-#define fsbtoblk(num, fsbs, bs) \
-       (((fsbs) != 0 && (fsbs) < (bs)) ? \
-               ((off_t)((unsigned)num)) / ((unsigned)(bs) / ((off_t)((unsigned)fsbs))) : ((off_t)((unsigned)num)) * ((off_t)((unsigned)fsbs)) / (bs))
+static intmax_t fsbtoblk(int64_t num, uint64_t fsbs, u_long bs, char *fs) 
+{
+       if (num < 0) {
+               warnx("negative filesystem block count/size from fs %s", fs);
+               return 0;
+       } else if ((fsbs != 0) && (fsbs < bs)) {
+               return (num / (intmax_t) (bs / fsbs));
+       } else {
+               return (num * (intmax_t) (fsbs / bs));
+       }
+}
 
 /*
  * Print out status about a filesystem.
@@ -411,26 +436,32 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
        static long blocksize;
        static int headerlen, timesthrough;
        static const char *header;
-       unsigned long used, availblks, inodes;
+       uint64_t used, availblks, inodes;
+       char * avail_str;
 
        if (++timesthrough == 1) {
-               mwp->mntfrom = imax(mwp->mntfrom, strlen("Filesystem"));
+               mwp->mntfrom = imax(mwp->mntfrom, (int)strlen("Filesystem"));
                if (hflag) {
                        header = "  Size";
-                       mwp->total = mwp->used = mwp->avail = strlen(header);
+                       mwp->total = mwp->used = mwp->avail = (int)strlen(header);
                } else {
                        header = getbsize(&headerlen, &blocksize);
                        mwp->total = imax(mwp->total, headerlen);
                }
-               mwp->used = imax(mwp->used, strlen("Used"));
-               mwp->avail = imax(mwp->avail, strlen("Avail"));
+               mwp->used = imax(mwp->used, (int)strlen("Used"));
+               if (COMPAT_MODE("bin/df", "unix2003") && !hflag) {
+                       avail_str = "Available";
+               } else {
+                       avail_str = "Avail";
+               }
+               mwp->avail = imax(mwp->avail, (int)strlen(avail_str));
 
-               (void)printf("%-*s %-*s %*s %*s Capacity", mwp->mntfrom,
+               (void)printf("%-*s %*s %*s %*s Capacity", mwp->mntfrom,
                    "Filesystem", mwp->total, header, mwp->used, "Used",
-                   mwp->avail, "Avail");
+                   mwp->avail, avail_str);
                if (iflag) {
-                       mwp->iused = imax(mwp->iused, strlen("  iused"));
-                       mwp->ifree = imax(mwp->ifree, strlen("ifree"));
+                       mwp->iused = imax(mwp->iused, (int)strlen("  iused"));
+                       mwp->ifree = imax(mwp->ifree, (int)strlen("ifree"));
                        (void)printf(" %*s %*s %%iused", mwp->iused - 2,
                            "iused", mwp->ifree, "ifree");
                }
@@ -438,24 +469,39 @@ prtstat(struct statfs *sfsp, struct maxwidths *mwp)
        }
 
        (void)printf("%-*s", mwp->mntfrom, sfsp->f_mntfromname);
-       used = (off_t)((unsigned)sfsp->f_blocks) - (off_t)((unsigned)sfsp->f_bfree);
+       if (sfsp->f_blocks > sfsp->f_bfree)
+               used = sfsp->f_blocks - sfsp->f_bfree;
+       else
+               used = 0;
        availblks = sfsp->f_bavail + used;
        if (hflag) {
                prthuman(sfsp, used);
        } else {
-               (void)printf(" %*lld %*lld %*lld", mwp->total,
-                   fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize),
-                   mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize),
-                   mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize,
-                   blocksize));
+               (void)printf(" %*jd %*jd %*jd", mwp->total,
+                            fsbtoblk(sfsp->f_blocks, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+                            mwp->used, fsbtoblk(used, sfsp->f_bsize, blocksize, sfsp->f_mntonname),
+                            mwp->avail, fsbtoblk(sfsp->f_bavail, sfsp->f_bsize, blocksize, sfsp->f_mntonname));
+       }
+       if (COMPAT_MODE("bin/df", "unix2003")) {
+               /* Standard says percentage must be rounded UP to next
+                  integer value, not truncated */
+               double value;
+               if (availblks == 0)
+                       value = 100.0;
+               else {
+                       value = (double)used / (double)availblks * 100.0;
+                       if ((value-(int)value) > 0.0) value = value + 1.0;
+               }
+               (void)printf(" %5.0f%%", trunc(value));
+       } else {
+               (void)printf(" %5.0f%%",
+                   availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
        }
-       (void)printf(" %5.0f%%",
-           availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0);
        if (iflag) {
-               inodes = (unsigned)sfsp->f_files;
+               inodes = sfsp->f_files;
                used = inodes - sfsp->f_ffree;
-               (void)printf(" %*lu %*lu %4.0f%% ", mwp->iused, used,
-                   mwp->ifree, (unsigned long)sfsp->f_ffree, inodes == 0 ? 100.0 :
+               (void)printf(" %*llu %*llu %4.0f%% ", mwp->iused, used,
+                   mwp->ifree, sfsp->f_ffree, inodes == 0 ? 100.0 :
                    (double)used / (double)inodes * 100.0);
        } else
                (void)printf("  ");
@@ -475,21 +521,21 @@ update_maxwidths(struct maxwidths *mwp, struct statfs *sfsp)
        if (blocksize == 0)
                getbsize(&dummy, &blocksize);
 
-       mwp->mntfrom = imax(mwp->mntfrom, strlen(sfsp->f_mntfromname));
-       mwp->total = imax(mwp->total, longwidth(fsbtoblk(sfsp->f_blocks,
-           sfsp->f_bsize, blocksize)));
-       mwp->used = imax(mwp->used, longwidth(fsbtoblk(sfsp->f_blocks -
-           sfsp->f_bfree, sfsp->f_bsize, blocksize)));
-       mwp->avail = imax(mwp->avail, longwidth(fsbtoblk(sfsp->f_bavail,
-           sfsp->f_bsize, blocksize)));
-       mwp->iused = imax(mwp->iused, longwidth((unsigned)(sfsp->f_files -
-           sfsp->f_ffree)));
-       mwp->ifree = imax(mwp->ifree, longwidth((unsigned)(sfsp->f_ffree)));
+       mwp->mntfrom = imax(mwp->mntfrom, (int)strlen(sfsp->f_mntfromname));
+       mwp->total = imax(mwp->total, int64width(fsbtoblk(sfsp->f_blocks,
+                                                        sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+       if (sfsp->f_blocks >= sfsp->f_bfree)
+               mwp->used = imax(mwp->used, int64width(fsbtoblk(sfsp->f_blocks -
+                                                              sfsp->f_bfree, sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+       mwp->avail = imax(mwp->avail, int64width(fsbtoblk(sfsp->f_bavail,
+                                                        sfsp->f_bsize, blocksize, sfsp->f_mntonname)));
+       mwp->iused = imax(mwp->iused, int64width(sfsp->f_files - sfsp->f_ffree));
+       mwp->ifree = imax(mwp->ifree, int64width(sfsp->f_ffree));
 }
 
 /* Return the width in characters of the specified long. */
 int
-longwidth(long long val)
+int64width(int64_t val)
 {
        int len;
 
@@ -507,83 +553,13 @@ longwidth(long long val)
        return (len);
 }
 
-/*
- * This code constitutes the pre-system call Berkeley df code for extracting
- * information from filesystem superblocks.
- */
-
-union {
-       struct fs iu_fs;
-       char dummy[SBSIZE];
-} sb;
-#define sblock sb.iu_fs
-
-int    rfd;
-
-int
-ufs_df(char *file, struct maxwidths *mwp)
-{
-       struct statfs statfsbuf;
-       struct statfs *sfsp;
-       const char *mntpt;
-       static int synced;
-
-       if (synced++ == 0)
-               sync();
-
-       if ((rfd = open(file, O_RDONLY)) < 0) {
-               warn("%s", file);
-               return (1);
-       }
-       if (bread((off_t)SBOFF, &sblock, SBSIZE) == 0) {
-               (void)close(rfd);
-               return (1);
-       }
-       sfsp = &statfsbuf;
-       sfsp->f_type = 1;
-       strcpy(sfsp->f_fstypename, "ufs");
-       sfsp->f_flags = 0;
-       sfsp->f_bsize = sblock.fs_fsize;
-       sfsp->f_iosize = sblock.fs_bsize;
-       sfsp->f_blocks = sblock.fs_dsize;
-       sfsp->f_bfree = sblock.fs_cstotal.cs_nbfree * sblock.fs_frag +
-               sblock.fs_cstotal.cs_nffree;
-       sfsp->f_bavail = freespace(&sblock, sblock.fs_minfree);
-       sfsp->f_files =  sblock.fs_ncg * sblock.fs_ipg;
-       sfsp->f_ffree = sblock.fs_cstotal.cs_nifree;
-       sfsp->f_fsid.val[0] = 0;
-       sfsp->f_fsid.val[1] = 0;
-       if ((mntpt = getmntpt(file)) == 0)
-               mntpt = "";
-       memmove(&sfsp->f_mntonname[0], mntpt, (size_t)MNAMELEN);
-       memmove(&sfsp->f_mntfromname[0], file, (size_t)MNAMELEN);
-       prtstat(sfsp, mwp);
-       (void)close(rfd);
-       return (0);
-}
-
-int
-bread(off_t off, void *buf, int cnt)
-{
-       ssize_t nr;
-
-       (void)lseek(rfd, off, SEEK_SET);
-       if ((nr = read(rfd, buf, (size_t)cnt)) != (ssize_t)cnt) {
-               /* Probably a dismounted disk if errno == EIO. */
-               if (errno != EIO)
-                       (void)fprintf(stderr, "\ndf: %lld: %s\n",
-                           (long long)off, strerror(nr > 0 ? EIO : errno));
-               return (0);
-       }
-       return (1);
-}
-
 void
 usage(void)
 {
 
+       char *t_flag = COMPAT_MODE("bin/df", "unix2003") ? "[-t]" : "[-t type]";
        (void)fprintf(stderr,
-           "usage: df [-b | -H | -h | -k | -m | -P] [-ailn] [-t type] [file | filesystem ...]\n");
+           "usage: df [-b | -H | -h | -k | -m | -g | -P] [-ailn] [-T type] %s [filesystem ...]\n", t_flag);
        exit(EX_USAGE);
 }
 
@@ -603,9 +579,9 @@ makenetvfslist(void)
 
        mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM;
        miblen=sizeof(maxvfsconf);
-       if (sysctl(mib, (unsigned int)(sizeof(mib) / sizeof(mib[0])),
+       if (sysctl(mib, 3,
            &maxvfsconf, &miblen, NULL, 0)) {
-               warnx("sysctl failed");
+               warn("sysctl failed");
                return (NULL);
        }
 
@@ -632,6 +608,7 @@ makenetvfslist(void)
                        if (!(vfc.vfc_flags & MNT_LOCAL)) {
                                listptr[cnt++] = strdup(vfc.vfc_name);
                                if (listptr[cnt-1] == NULL) {
+                                       free(listptr);
                                        warnx("malloc failed");
                                        return (NULL);
                                }
@@ -655,7 +632,7 @@ makenetvfslist(void)
                *strptr = ',';
                free(listptr[i]);
        }
-       *(--strptr) = NULL;
+       *(--strptr) = '\0';
 
        free(listptr);
        return (str);