#include #include #include Biobuf bout; int tflag; /* long form: name time size 0 */ int dflag; /* include one line per directory */ #define NCACHE 4096 /* must be power of two */ struct cache { Dir *cache; int n; int max; } cache[NCACHE]; void err(char *s) { fprint(2, "lsr: "); perror(s); exits(s); } int warn(char *s) { fprint(2, "lsr: "); perror(s); return 0; } int seen(Dir *dir) { Dir *dp; int i; struct cache *c; c = &cache[dir->qid.path&(NCACHE-1)]; dp = c->cache; for(i=0; in; i++,dp++) if(dir->qid.path==dp->qid.path && dir->type==dp->type && dir->dev==dp->dev) return 1; if(c->n == c->max){ c->cache = realloc(c->cache, (c->max+=20)*sizeof(Dir)); if(cache == 0) err("malloc failure"); } c->cache[c->n++] = *dir; return 0; } int du(char *name, Dir *dir) { int fd, i, n; char file[256], *cleanfile; Dir *dirn; if(dir==0){ dir = dirstat(name); if(dir==0) return warn(name); if((dir->mode&DMDIR)==0){ if(tflag) Bprint(&bout, "%s %lud %llud 0\n", name, dir->mtime, dir->length); else Bprint(&bout, "%s\n",name); return 0; }else if(dflag){ cleanfile = file; if(file[0]=='.' && file[1]=='/') cleanfile += 2; Bprint(&bout, "%s/\n", cleanfile); } } fd=open(name, OREAD); if(fd<0) return warn(name); while((n=dirread(fd, &dirn))>0){ for(i = 0; imode&DMDIR)==0){ sprint(file, "%s/%s", name, dir->name); cleanfile = file; if(file[0]=='.' && file[1]=='/') cleanfile += 2; if(tflag) Bprint(&bout, "%s %lud %llud 0\n", cleanfile, dir->mtime, dir->length); else Bprint(&bout, "%s\n",cleanfile); continue; }else if(dflag){ cleanfile = file; if(file[0]=='.' && file[1]=='/') cleanfile += 2; Bprint(&bout, "%s/\n", cleanfile); } if(strcmp(dir->name, ".")==0 || strcmp(dir->name, "..")==0 || seen(dir)){ continue; } sprint(file, "%s/%s", name, dir->name); du(file, dir); } free(dirn); } close(fd); return 0; } void main(int argc, char *argv[]) { int i; ARGBEGIN{ case 't': tflag=1; break; case 'd': dflag=1; break; }ARGEND Binit(&bout, 1, OWRITE); if(argc==0) du(".", 0); else for(i=0; i