From: Alan Cox Date: Fri, 3 Nov 2017 12:23:32 +0000 (+0000) Subject: du: switch version X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=7fb7bcbe506c424db5cc918bdf7f700146e7d255;p=FUZIX.git du: switch version Use the tidied up MWC one. It's nicer, smaller and calculates stuff like indirect block cost. --- diff --git a/Applications/MWC/cmd/du.c b/Applications/MWC/cmd/du.c new file mode 100644 index 00000000..a76a8aaf --- /dev/null +++ b/Applications/MWC/cmd/du.c @@ -0,0 +1,313 @@ +/* + * Print a disc usage summary for + * some directories. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; lpl_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; i1 && *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