du: switch version
authorAlan Cox <alan@linux.intel.com>
Fri, 3 Nov 2017 12:23:32 +0000 (12:23 +0000)
committerAlan Cox <alan@linux.intel.com>
Fri, 3 Nov 2017 12:23:32 +0000 (12:23 +0000)
Use the tidied up MWC one. It's nicer, smaller and calculates stuff like
indirect block cost.

Applications/MWC/cmd/du.c [new file with mode: 0644]
Applications/MWC/cmd/fuzix-cmd.pkg
Applications/util/fuzix-util.pkg

diff --git a/Applications/MWC/cmd/du.c b/Applications/MWC/cmd/du.c
new file mode 100644 (file)
index 0000000..a76a8aa
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * Print a disc usage summary for
+ * some directories.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#define        NLINK   500             /* Size of link table */
+#define        NFNAME  512             /* Size of filename */
+#define        NRECUR  12              /* Depth of recursion < NFILE-3-2 */
+
+int    aflag;                  /* do files as well */
+int    sflag;                  /* only give total */
+int    depth;                  /* recursion depth */
+
+int    nfile;                  /* files allowed open */
+
+struct linktab {
+       ino_t   l_ino;
+       dev_t   l_dev;
+}      linktab[NLINK];
+
+struct linktab *ltp;
+char   fname[NFNAME];
+
+char   toodeep[] = "directory structure too deep to traverse";
+
+struct stat    sb;
+
+#define ND     20
+#define NBN    256
+
+/*
+ * indirect block overhead based upon size of file
+ */
+long   ranges[] = {
+       ND,                             /* direct blocks */
+       ND + NBN,                       /* single indirect */
+       ND + NBN*NBN,                   /* double indirect */
+       ND + NBN*NBN*NBN                /* tripple indirect */
+};
+
+extern long dufork(const char *ep);
+
+void usage(void)
+{
+       write(2, "Usage: du [-s] [name ...]\n", 26);
+       exit(1);
+}
+
+static void writes(int fd, const char *p)
+{
+       write(fd, p, strlen(p));
+}
+
+void dumsg(const char *x, const char *p)
+{
+       writes(2, x);
+       if (p) {
+               write(2, " `", 2);
+               writes(2, p);
+               write(2, "'\n", 2);
+       } else
+               write(2, "\n", 1);
+}
+
+void duerr(const char *x, const char *p)
+{
+       dumsg(x, p);
+       exit (1);
+}
+
+/*
+ * Build up the next entry
+ * in the name.
+ */
+char *buildname(struct dirent *dp, char *ep)
+{
+       char *cp = dp->d_name;
+       size_t s = strlen(dp->d_name);
+
+       if (ep + s + 2 >= &fname[NFNAME]) {
+               dumsg(toodeep, NULL);
+               return (NULL);
+       }
+       if (ep[-1] != '/')
+               *ep++ = '/';
+       strcpy(ep, cp);
+       return (ep + s);
+}
+
+/*
+ * Add an entry to the table
+ * of i-numbers with multiple links.
+ * If there are too many multi-link files,
+ * they will get counted twice.
+ * Return 1 if already there.
+ */
+int addlink(dev_t dev, ino_t ino)
+{
+       struct linktab *lp;
+
+       for (lp = linktab; lp<ltp; lp++)
+               if (lp->l_ino==ino && lp->l_dev==dev)
+                       return (1);
+       if (lp-linktab >= NLINK)
+               return (0);
+       lp->l_ino = ino;
+       lp->l_dev = dev;
+       ltp++;
+       return (0);
+}
+
+
+/*
+ * Print out a size line.
+ */
+
+void prsize(uint16_t blocks)
+{
+       writes(1, _itoa(blocks));
+       writes(1, "\t");
+       writes(1, fname);
+       write(1, "\n", 1);
+}
+
+/*
+ * Do a du on a single file.
+ * Now takes into account indirect blocks.
+ */
+long dusize(void)
+{
+       int i;
+       long blocks;
+
+       if ((sb.st_mode & S_IFMT) != S_IFDIR
+        && sb.st_nlink > 1
+        && addlink(sb.st_dev, sb.st_ino))
+               return (0);
+       blocks = (sb.st_size+BUFSIZ-1) / BUFSIZ;
+       for (i = 0; i < sizeof(ranges)/sizeof(ranges[0]); ++i)
+               if (blocks <= ranges[i])
+                       break;
+       return (blocks + i);
+}
+
+/*
+ * Do a du on a single entry
+ * The pointer is the end pointer
+ * into the fname buffer.
+ */
+long duentry(char *ep)
+{
+       uint16_t total;
+       uint32_t fsize;
+       char *np;
+       DIR *fd;
+       struct dirent *dp;
+       int dirf;
+
+       switch (sb.st_mode & S_IFMT) {
+       case S_IFREG:
+               return dusize();
+
+       case S_IFDIR:
+               total = dusize();
+               if (++depth >= NRECUR) {
+                       depth = 0;
+                       return dufork(ep);
+               }
+               if ((fd = opendir(fname)) == NULL) {
+                       dumsg(fname, "cannot open");
+                       return (0);
+               }
+               while ((dp = readdir(fd)) != NULL) {
+                       np = dp->d_name;
+                       if (*np++=='.'
+                         && (*np=='\0' || (*np++=='.' && *np=='\0')))
+                               continue;
+                       if ((np = buildname(dp, ep)) == NULL)
+                               continue;
+                       if (stat(fname, &sb) < 0) {
+                               dumsg("stat failed on", fname);
+                               continue;
+                       }
+                       dirf = (sb.st_mode&S_IFMT)==S_IFDIR;
+                       fsize = duentry(np);
+                       if (aflag && !sflag && !dirf)
+                               prsize(fsize);
+                       total += fsize;
+               }
+               closedir(fd);
+               *ep = '\0';
+               if (!sflag)
+                       prsize(total);
+               --depth;
+               return total;
+
+       default:
+               return 0;
+       }
+}
+
+/*
+ * Fork to do a du on recursive directory
+ * structure that is too deep to fit into
+ * user's open files.
+ */
+long dufork(char *ep)
+{
+       int i;
+       int pid;
+       int pfd[2] = {0, 0};
+       int status;
+       long sz = 0;
+
+       fflush(stdout);
+       if (pipe(pfd)<0 || (pid = fork())<0) {
+               if (pfd[0]) {
+                       close(pfd[0]);
+                       close(pfd[1]);
+               }
+               dumsg(toodeep, NULL);
+               return (0);
+       }
+       if (pid) {
+               close(pfd[1]);
+               while (wait(&status) >= 0)
+                       ;
+               if (status || read(pfd[0], &sz, sizeof(long)) != sizeof(long))
+                       sz = 0;
+               close(pfd[0]);
+               return (sz);
+       }
+       for (i=3; i<nfile; i++)
+               if (i != pfd[1])
+                       close(i);
+       sz = duentry(ep);
+       write(pfd[1], &sz, sizeof(long));
+       close(pfd[1]);
+       exit(0);
+}
+
+/*
+ * Print out disc usage summary
+ */
+static int du(char *name)
+{
+       char *ep, *cp;
+       uint32_t size;
+       int nondir;
+
+       ltp = linktab;
+       cp = name;
+       ep = fname;
+       while (*cp)
+               *ep++ = *cp++;
+       *ep = '\0';
+       if (stat(name, &sb) < 0)
+               duerr("nonexistent", name);
+       nondir = (sb.st_mode&S_IFMT) != S_IFDIR;
+       size = duentry(ep);
+       if (sflag || nondir) {
+               writes(1, _ltoa(size));
+               write(1, "\t", 1);
+               writes(1, fname);
+               write(1, "\n", 1);
+       }
+       return (0);
+}
+       
+void main(int argc, char *argv[])
+{
+       int i;
+       char *ap;
+       int estat;
+       
+       int nfile = sysconf(_SC_OPEN_MAX);
+
+       while (argc>1 && *argv[1]=='-') {
+               for (ap = &argv[1][1]; *ap != '\0'; ap++)
+                       switch (*ap) {
+                       case 'a':
+                               aflag = 1;
+                               break;
+
+                       case 's':
+                               sflag = 1;
+                               break;
+
+                       default:
+                               usage();
+                       }
+               argc--;
+               argv++;
+       }
+       if (argc < 2)
+               estat = du(".");
+       else {
+               estat = 0;
+               for (i=1; i<argc; i++)
+                       estat |= du(argv[i]);
+       }
+       exit (estat);
+}
+
index e1e57ec..2d5a5c8 100644 (file)
@@ -7,6 +7,7 @@ f 0755 /usr/bin/at         at
 f 0755 /usr/bin/calendar   calendar
 f 0755 /usr/bin/col        col
 f 0755 /usr/bin/deroff     deroff
+f 0755 /bin/du            du
 f 0755 /usr/bin/expr       expr
 f 0755 /usr/bin/find       find
 f 0755 /usr/bin/m4         m4
index 1e0e883..a588bb4 100644 (file)
@@ -60,7 +60,6 @@ f 0755 /bin/cut         cut
 f 0755 /bin/decomp16    decomp16
 f 0755 /bin/dirname     dirname
 f 0755 /bin/dosread     dosread
-f 0755 /bin/du          du
 f 0755 /bin/env         env
 f 0755 /bin/factor      factor
 f 0755 /bin/false       false