Blob
1 #include <u.h>2 #include <libc.h>4 extern vlong du(char*, Dir*);5 extern vlong k(vlong);6 extern void err(char*);7 extern int warn(char*);8 extern int seen(Dir*);10 int aflag;11 int fflag;12 int nflag;13 int sflag;14 int tflag;15 int uflag;16 int qflag;17 char *fmt = "%llud\t%s\n";18 vlong blocksize = 1024LL;20 void21 main(int argc, char *argv[])22 {23 int i;24 char *s, *ss;26 ARGBEGIN {27 case 'a': /* all files */28 aflag = 1;29 break;30 case 's': /* only top level */31 sflag = 1;32 break;33 case 'f': /* ignore errors */34 fflag = 1;35 break;36 case 'n': /* all files, number of bytes */37 aflag = 1;38 nflag = 1;39 break;40 case 't': /* return modified/accessed time */41 tflag = 1;42 break;43 case 'u': /* accessed time */44 uflag = 1;45 break;46 case 'q': /* qid */47 fmt = "%.16llux\t%s\n";48 qflag = 1;49 break;50 case 'b': /* block size */51 s = ARGF();52 if(s) {53 blocksize = strtoul(s, &ss, 0);54 if(s == ss)55 blocksize = 1;56 if(*ss == 'k')57 blocksize *= 1024;58 }59 break;60 } ARGEND61 if(argc==0)62 print(fmt, du(".", dirstat(".")), ".");63 else64 for(i=0; i<argc; i++)65 print(fmt, du(argv[i], dirstat(argv[i])), argv[i]);66 exits(0);67 }69 vlong70 du(char *name, Dir *dir)71 {72 int fd, i, n;73 Dir *buf, *d;74 char file[256];75 vlong nk, t;77 if(dir == nil)78 return warn(name);80 fd = open(name, OREAD);81 if(fd < 0)82 return warn(name);84 if((dir->qid.type&QTDIR) == 0)85 nk = k(dir->length);86 else{87 nk = 0;88 while((n=dirread(fd, &buf)) > 0) {89 d = buf;90 for(i=0; i<n; i++, d++) {91 if((d->qid.type&QTDIR) == 0) {92 t = k(d->length);93 nk += t;94 if(aflag) {95 sprint(file, "%s/%s", name, d->name);96 if(tflag) {97 t = d->mtime;98 if(uflag)99 t = d->atime;100 }101 if(qflag)102 t = d->qid.path;103 print(fmt, t, file);104 }105 continue;106 }107 if(strcmp(d->name, ".") == 0 ||108 strcmp(d->name, "..") == 0 ||109 seen(d))110 continue;111 sprint(file, "%s/%s", name, d->name);112 t = du(file, d);113 nk += t;114 if(tflag) {115 t = d->mtime;116 if(uflag)117 t = d->atime;118 }119 if(qflag)120 t = d->qid.path;121 if(!sflag)122 print(fmt, t, file);123 }124 free(buf);125 }126 if(n < 0)127 warn(name);128 }129 close(fd);130 if(tflag) {131 if(uflag)132 return dir->atime;133 return dir->mtime;134 }135 if(qflag)136 return dir->qid.path;137 return nk;138 }140 #define NCACHE 128 /* must be power of two */141 typedef struct Cache Cache;142 struct Cache143 {144 Dir* cache;145 int n;146 int max;147 } cache[NCACHE];149 int150 seen(Dir *dir)151 {152 Dir *dp;153 int i;154 Cache *c;156 c = &cache[dir->qid.path&(NCACHE-1)];157 dp = c->cache;158 for(i=0; i<c->n; i++, dp++)159 if(dir->qid.path == dp->qid.path &&160 dir->type == dp->type &&161 dir->dev == dp->dev)162 return 1;163 if(c->n == c->max){164 c->cache = realloc(c->cache, (c->max+=20)*sizeof(Dir));165 if(cache == 0)166 err("malloc failure");167 }168 c->cache[c->n++] = *dir;169 return 0;170 }172 void173 err(char *s)174 {175 fprint(2, "du: %s: %r\n", s);176 exits(s);177 }179 int180 warn(char *s)181 {182 if(fflag == 0)183 fprint(2, "du: %s: %r\n", s);184 return 0;185 }187 vlong188 k(vlong n)189 {190 if(nflag)191 return n;192 n = (n+blocksize-1)/blocksize;193 return n*blocksize/1024LL;194 }