URI: 
       du.c - 9base - revived minimalist port of Plan 9 userland to Unix
  HTML git clone git://git.suckless.org/9base
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       du.c (3101B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 
            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 
           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;
           19 
           20 void
           21 main(int argc, char *argv[])
           22 {
           23         int i;
           24         char *s, *ss;
           25 
           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 }
           68 
           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;
           76 
           77         if(dir == nil)
           78                 return warn(name);
           79 
           80         fd = open(name, OREAD);
           81         if(fd < 0)
           82                 return warn(name);
           83 
           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 }
          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 
          149 int
          150 seen(Dir *dir)
          151 {
          152         Dir *dp;
          153         int i;
          154         Cache *c;
          155 
          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");
          167         }
          168         c->cache[c->n++] = *dir;
          169         return 0;
          170 }
          171 
          172 void
          173 err(char *s)
          174 {
          175         fprint(2, "du: %s: %r\n", s);
          176         exits(s);
          177 }
          178 
          179 int
          180 warn(char *s)
          181 {
          182         if(fflag == 0)
          183                 fprint(2, "du: %s: %r\n", s);
          184         return 0;
          185 }
          186 
          187 vlong
          188 k(vlong n)
          189 {
          190         if(nflag)
          191                 return n;
          192         n = (n+blocksize-1)/blocksize;
          193         return n*blocksize/1024LL;
          194 }