du.c 3.2 KB

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