update - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 56196e76fd80ff6fdd6365d8fa028d8b4675ff4b | |
parent f61f650899ccc18561eb21fce96e4770508adb71 | |
Author: Anselm R Garbe <[email protected]> | |
Date: Mon, 10 Aug 2009 15:05:01 +0100 | |
update | |
Diffstat: | |
A du/Makefile | 6 ++++++ | |
A du/du.1 | 9 +++++++++ | |
A du/du.c | 194 ++++++++++++++++++++++++++++++ | |
3 files changed, 209 insertions(+), 0 deletions(-) | |
--- | |
diff --git a/du/Makefile b/du/Makefile | |
@@ -0,0 +1,6 @@ | |
+# du - du unix port from plan9 | |
+# Depends on ../lib9 | |
+ | |
+TARG = du | |
+ | |
+include ../std.mk | |
diff --git a/du/du.1 b/du/du.1 | |
@@ -0,0 +1,9 @@ | |
+.TH DU 1 | |
+.SH NAME | |
+du | |
+.SH SYNOPSIS | |
+.B du | |
+.SH DESCRIPTION | |
+.I du | |
+.SH SOURCE | |
+.B \*9/src/cmd/du.c | |
diff --git a/du/du.c b/du/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-… | |
+ 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; | |
+} |