Blame


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