Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/du.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 * du - print disk usage
3
 */
4
#include <u.h>
5
#include <libc.h>
6
#include <String.h>
7
 
8
extern	vlong	du(char*, Dir*);
9
extern	void	err(char*);
10
extern	vlong	blkmultiple(vlong);
11
extern	int	seen(Dir*);
12
extern	int	warn(char*);
13
 
14
enum {
15
	Vkilo = 1024LL,
16
};
17
 
18
/* rounding up, how many units does amt occupy? */
19
#define HOWMANY(amt, unit)	(((amt)+(unit)-1) / (unit))
20
#define ROUNDUP(amt, unit)	(HOWMANY(amt, unit) * (unit))
21
 
22
int	aflag;
23
int	autoscale;
24
int	fflag;
25
int	fltflag;
26
int	qflag;
27
int	readflg;
28
int	sflag;
29
int	tflag;
30
int	uflag;
31
 
32
char	*fmt = "%llud\t%q\n";
33
char	*readbuf;
34
vlong	blocksize = Vkilo;	/* actually more likely to be 4K or 8K */
35
vlong	unit;			/* scale factor for output */
36
 
37
static char *pfxes[] = {	/* SI prefixes for units > 1 */
38
	"",
39
	"k", "M", "G",
40
	"T", "P", "E",
41
	"Z", "Y",
42
	nil,
43
};
44
 
45
void
46
usage(void)
47
{
48
	fprint(2, "usage: du [-aefhnqstu] [-b size] [-p si-pfx] [file ...]\n");
49
	exits("usage");
50
}
51
 
52
void
53
printamt(vlong amt, char *name)
54
{
55
	if (readflg)
56
		return;
57
	if (autoscale) {
58
		int scale = 0;
59
		double val = (double)amt/unit;
60
 
61
		while (fabs(val) >= 1024 && scale < nelem(pfxes)-1) {
62
			scale++;
63
			val /= 1024;
64
		}
65
		print("%.6g%s\t%q\n", val, pfxes[scale], name);
66
	} else if (fltflag)
67
		print("%.6g\t%q\n", (double)amt/unit, name);
68
	else
69
		print(fmt, HOWMANY(amt, unit), name);
70
}
71
 
72
void
73
main(int argc, char *argv[])
74
{
75
	int i, scale;
76
	char *s, *ss, *name;
77
 
78
	doquote = needsrcquote;
79
	quotefmtinstall();
80
 
81
	ARGBEGIN {
82
	case 'a':	/* all files */
83
		aflag = 1;
84
		break;
85
	case 'b':	/* block size */
86
		s = ARGF();
87
		if(s) {
88
			blocksize = strtoul(s, &ss, 0);
89
			if(s == ss)
90
				blocksize = 1;
91
			while(*ss++ == 'k')
92
				blocksize *= 1024;
93
		}
94
		break;
95
	case 'e':	/* print in %g notation */
96
		fltflag = 1;
97
		break;
98
	case 'f':	/* don't print warnings */
99
		fflag = 1;
100
		break;
101
	case 'h':	/* similar to -h in bsd but more precise */
102
		autoscale = 1;
103
		break;
104
	case 'n':	/* all files, number of bytes */
105
		aflag = 1;
106
		blocksize = 1;
107
		unit = 1;
108
		break;
109
	case 'p':
110
		s = ARGF();
111
		if(s) {
112
			for (scale = 0; pfxes[scale] != nil; scale++)
113
				if (cistrcmp(s, pfxes[scale]) == 0)
114
					break;
115
			if (pfxes[scale] == nil)
116
				sysfatal("unknown suffix %s", s);
117
			unit = 1;
118
			while (scale-- > 0)
119
				unit *= Vkilo;
120
		}
121
		break;
122
	case 'q':	/* qid */
123
		fmt = "%.16llux\t%q\n";
124
		qflag = 1;
125
		break;
126
	case 'r':
127
		/* undocumented: just read & ignore every block of every file */
128
		readflg = 1;
129
		break;
130
	case 's':	/* only top level */
131
		sflag = 1;
132
		break;
133
	case 't':	/* return modified/accessed time */
134
		tflag = 1;
135
		break;
136
	case 'u':	/* accessed time */
137
		uflag = 1;
138
		break;
139
	default:
140
		usage();
141
	} ARGEND
142
 
143
	if (unit == 0)
144
		if (qflag || tflag || uflag || autoscale)
145
			unit = 1;
146
		else
147
			unit = Vkilo;
148
	if (blocksize < 1)
149
		blocksize = 1;
150
 
151
	if (readflg) {
152
		readbuf = malloc(blocksize);
153
		if (readbuf == nil)
154
			sysfatal("out of memory");
155
	}
156
	if(argc==0)
157
		printamt(du(".", dirstat(".")), ".");
158
	else
159
		for(i=0; i<argc; i++) {
160
			name = argv[i];
161
			printamt(du(name, dirstat(name)), name);
162
		}
163
	exits(0);
164
}
165
 
166
vlong
167
dirval(Dir *d, vlong size)
168
{
169
	if(qflag)
170
		return d->qid.path;
171
	else if(tflag) {
172
		if(uflag)
173
			return d->atime;
174
		return d->mtime;
175
	} else
176
		return size;
177
}
178
 
179
void
180
readfile(char *name)
181
{
182
	int n, fd = open(name, OREAD);
183
 
184
	if(fd < 0) {
185
		warn(name);
186
		return;
187
	}
188
	while ((n = read(fd, readbuf, blocksize)) > 0)
189
		continue;
190
	if (n < 0)
191
		warn(name);
192
	close(fd);
193
}
194
 
195
vlong
196
dufile(char *name, Dir *d)
197
{
198
	vlong t = blkmultiple(d->length);
199
 
200
	if(aflag || readflg) {
201
		String *file = s_copy(name);
202
 
203
		s_append(file, "/");
204
		s_append(file, d->name);
205
		if (readflg)
206
			readfile(s_to_c(file));
207
		t = dirval(d, t);
208
		printamt(t, s_to_c(file));
209
		s_free(file);
210
	}
211
	return t;
212
}
213
 
214
vlong
215
du(char *name, Dir *dir)
216
{
217
	int fd, i, n;
218
	Dir *buf, *d;
219
	String *file;
220
	vlong nk, t;
221
 
222
	if(dir == nil)
223
		return warn(name);
224
 
225
	if((dir->qid.type&QTDIR) == 0)
226
		return dirval(dir, blkmultiple(dir->length));
227
 
228
	fd = open(name, OREAD);
229
	if(fd < 0)
230
		return warn(name);
231
	nk = 0;
232
	while((n=dirread(fd, &buf)) > 0) {
233
		d = buf;
234
		for(i = n; i > 0; i--, d++) {
235
			if((d->qid.type&QTDIR) == 0) {
236
				nk += dufile(name, d);
237
				continue;
238
			}
239
 
240
			if(strcmp(d->name, ".") == 0 ||
241
			   strcmp(d->name, "..") == 0 ||
242
			   /* !readflg && */ seen(d))
243
				continue;	/* don't get stuck */
244
 
245
			file = s_copy(name);
246
			s_append(file, "/");
247
			s_append(file, d->name);
248
 
249
			t = du(s_to_c(file), d);
250
 
251
			nk += t;
252
			t = dirval(d, t);
253
			if(!sflag)
254
				printamt(t, s_to_c(file));
255
			s_free(file);
256
		}
257
		free(buf);
258
	}
259
	if(n < 0)
260
		warn(name);
261
	close(fd);
262
	return dirval(dir, nk);
263
}
264
 
265
#define	NCACHE	256	/* must be power of two */
266
 
267
typedef struct
268
{
269
	Dir*	cache;
270
	int	n;
271
	int	max;
272
} Cache;
273
Cache cache[NCACHE];
274
 
275
int
276
seen(Dir *dir)
277
{
278
	Dir *dp;
279
	int i;
280
	Cache *c;
281
 
282
	c = &cache[dir->qid.path&(NCACHE-1)];
283
	dp = c->cache;
284
	for(i=0; i<c->n; i++, dp++)
285
		if(dir->qid.path == dp->qid.path &&
286
		   dir->type == dp->type &&
287
		   dir->dev == dp->dev)
288
			return 1;
289
	if(c->n == c->max){
290
		if (c->max == 0)
291
			c->max = 8;
292
		else
293
			c->max += c->max/2;
294
		c->cache = realloc(c->cache, c->max*sizeof(Dir));
295
		if(c->cache == nil)
296
			err("malloc failure");
297
	}
298
	c->cache[c->n++] = *dir;
299
	return 0;
300
}
301
 
302
void
303
err(char *s)
304
{
305
	fprint(2, "du: %s: %r\n", s);
306
	exits(s);
307
}
308
 
309
int
310
warn(char *s)
311
{
312
	if(fflag == 0)
313
		fprint(2, "du: %s: %r\n", s);
314
	return 0;
315
}
316
 
317
/* round up n to nearest block */
318
vlong
319
blkmultiple(vlong n)
320
{
321
	if(blocksize == 1)		/* no quantization */
322
		return n;
323
	return ROUNDUP(n, blocksize);
324
}