aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/du.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@swtch.com>2014-11-17 11:21:06 -0500
committerRuss Cox <rsc@swtch.com>2014-11-17 11:21:06 -0500
commitc9ed52730b352448c7c644f6942d310dd3509bf6 (patch)
treed9723cd78c8b632e76e90f51ae43bd65c2139116 /src/cmd/du.c
parent08e793723cad1c7aed2e8cb16c8592aba5ad05e9 (diff)
downloadplan9port-c9ed52730b352448c7c644f6942d310dd3509bf6.tar.gz
plan9port-c9ed52730b352448c7c644f6942d310dd3509bf6.tar.bz2
plan9port-c9ed52730b352448c7c644f6942d310dd3509bf6.zip
cmd: rename *.C to *.c
These were *.C back in 2003, before the 9 script, to avoid conflicts with the system utilities. A later change renamed them, but that change seems to have been lost during the hg->git conversion because I ran the conversion on a case-insensitive file system. Change-Id: Id32c99cb9571ef0e185c3cc9e8c8d6d5b48ca195
Diffstat (limited to 'src/cmd/du.c')
-rw-r--r--src/cmd/du.c194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/cmd/du.c b/src/cmd/du.c
new file mode 100644
index 00000000..f62c45b7
--- /dev/null
+++ b/src/cmd/du.c
@@ -0,0 +1,194 @@
+#include <u.h>
+#include <libc.h>
+
+extern vlong du(char*, Dir*);
+extern vlong k(vlong);
+extern void err(char*);
+extern int warn(char*);
+extern int seen(Dir*);
+
+int aflag;
+int fflag;
+int nflag;
+int sflag;
+int tflag;
+int uflag;
+int qflag;
+char *fmt = "%llud\t%s\n";
+vlong blocksize = 1024LL;
+
+void
+main(int argc, char *argv[])
+{
+ int i;
+ char *s, *ss;
+
+ ARGBEGIN {
+ case 'a': /* all files */
+ aflag = 1;
+ break;
+ case 's': /* only top level */
+ sflag = 1;
+ break;
+ case 'f': /* ignore errors */
+ fflag = 1;
+ break;
+ case 'n': /* all files, number of bytes */
+ aflag = 1;
+ nflag = 1;
+ break;
+ case 't': /* return modified/accessed time */
+ tflag = 1;
+ break;
+ case 'u': /* accessed time */
+ uflag = 1;
+ break;
+ case 'q': /* qid */
+ fmt = "%.16llux\t%s\n";
+ qflag = 1;
+ break;
+ case 'b': /* block size */
+ s = ARGF();
+ if(s) {
+ blocksize = strtoul(s, &ss, 0);
+ if(s == ss)
+ blocksize = 1;
+ if(*ss == 'k')
+ blocksize *= 1024;
+ }
+ break;
+ } ARGEND
+ if(argc==0)
+ print(fmt, du(".", dirstat(".")), ".");
+ else
+ for(i=0; i<argc; i++)
+ print(fmt, du(argv[i], dirstat(argv[i])), argv[i]);
+ exits(0);
+}
+
+vlong
+du(char *name, Dir *dir)
+{
+ int fd, i, n;
+ Dir *buf, *d;
+ char file[256];
+ vlong nk, t;
+
+ if(dir == nil)
+ return warn(name);
+
+ fd = open(name, OREAD);
+ if(fd < 0)
+ return warn(name);
+
+ if((dir->qid.type&QTDIR) == 0)
+ nk = k(dir->length);
+ else{
+ nk = 0;
+ while((n=dirread(fd, &buf)) > 0) {
+ d = buf;
+ for(i=0; i<n; i++, d++) {
+ if((d->qid.type&QTDIR) == 0) {
+ t = k(d->length);
+ nk += t;
+ if(aflag) {
+ sprint(file, "%s/%s", name, d->name);
+ if(tflag) {
+ t = d->mtime;
+ if(uflag)
+ t = d->atime;
+ }
+ if(qflag)
+ t = d->qid.path;
+ print(fmt, t, file);
+ }
+ continue;
+ }
+ if(strcmp(d->name, ".") == 0 ||
+ strcmp(d->name, "..") == 0 ||
+ seen(d))
+ continue;
+ sprint(file, "%s/%s", name, d->name);
+ t = du(file, d);
+ nk += t;
+ if(tflag) {
+ t = d->mtime;
+ if(uflag)
+ t = d->atime;
+ }
+ if(qflag)
+ t = d->qid.path;
+ if(!sflag)
+ print(fmt, t, file);
+ }
+ free(buf);
+ }
+ if(n < 0)
+ warn(name);
+ }
+ close(fd);
+ if(tflag) {
+ if(uflag)
+ return dir->atime;
+ return dir->mtime;
+ }
+ if(qflag)
+ return dir->qid.path;
+ return nk;
+}
+
+#define NCACHE 128 /* must be power of two */
+typedef struct Cache Cache;
+struct Cache
+{
+ Dir* cache;
+ int n;
+ int max;
+} cache[NCACHE];
+
+int
+seen(Dir *dir)
+{
+ Dir *dp;
+ int i;
+ Cache *c;
+
+ c = &cache[dir->qid.path&(NCACHE-1)];
+ dp = c->cache;
+ for(i=0; i<c->n; i++, dp++)
+ if(dir->qid.path == dp->qid.path &&
+ dir->type == dp->type &&
+ dir->dev == dp->dev)
+ return 1;
+ if(c->n == c->max){
+ c->cache = realloc(c->cache, (c->max+=20)*sizeof(Dir));
+ if(c->cache == 0)
+ err("malloc failure");
+ }
+ c->cache[c->n++] = *dir;
+ return 0;
+}
+
+void
+err(char *s)
+{
+ fprint(2, "du: %s: %r\n", s);
+ exits(s);
+}
+
+int
+warn(char *s)
+{
+ if(fflag == 0)
+ fprint(2, "du: %s: %r\n", s);
+ return 0;
+}
+
+vlong
+k(vlong n)
+{
+ if(nflag)
+ return n;
+ n = (n+blocksize-1)/blocksize;
+ return n*blocksize/1024LL;
+}