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 void
21 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 } ARGEND
61 if(argc==0)
62 print(fmt, du(".", dirstat(".")), ".");
63 else
64 for(i=0; i<argc; i++)
65 print(fmt, du(argv[i], dirstat(argv[i])), argv[i]);
66 exits(0);
67 }
69 vlong
70 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;
101 if(qflag)
102 t = d->qid.path;
103 print(fmt, t, file);
105 continue;
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;
119 if(qflag)
120 t = d->qid.path;
121 if(!sflag)
122 print(fmt, t, file);
124 free(buf);
126 if(n < 0)
127 warn(name);
129 close(fd);
130 if(tflag) {
131 if(uflag)
132 return dir->atime;
133 return dir->mtime;
135 if(qflag)
136 return dir->qid.path;
137 return nk;
140 #define NCACHE 128 /* must be power of two */
141 typedef struct Cache Cache;
142 struct Cache
144 Dir* cache;
145 int n;
146 int max;
147 } cache[NCACHE];
149 int
150 seen(Dir *dir)
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(c->cache == 0)
166 err("malloc failure");
168 c->cache[c->n++] = *dir;
169 return 0;
172 void
173 err(char *s)
175 fprint(2, "du: %s: %r\n", s);
176 exits(s);
179 int
180 warn(char *s)
182 if(fflag == 0)
183 fprint(2, "du: %s: %r\n", s);
184 return 0;
187 vlong
188 k(vlong n)
190 if(nflag)
191 return n;
192 n = (n+blocksize-1)/blocksize;
193 return n*blocksize/1024LL;