/* * lr: list directories recursively * version: 1.1 * date: 2005/02/18 * auther: Kenar(Kenji Arisawa) * Email: arisawa@aichi-u.ac.jp */ #include #include #include void usage(void) { fprint(2,"usage: lr [-lnpw] [-d depth] [path ...]\n"); exits("usage"); } enum { LFMT = 1, nFMT = 2, }; char *mods[]={"---","--x","-w-","-wx","r--","r-x","rw-","rwx"}; int mode = 0; Biobuf out; int quit = 0; int wflag = 0; /* warning for empty files/dirs */ static int notefun(void *a, char *msg) { USED(a); USED(msg); quit = 1; noted(NCONT); return 0; } char* modefmt(ulong m) { static char buf[32]; char *e, *s; s = buf; e = s + sizeof buf; s[0] = s[1] = '-'; if(m & DMDIR) s[0] = 'd'; else{ if(m & DMAPPEND) s[0] = 'a'; if(m & DMEXCL) s[1] = 'l'; } s += 2; s = seprint(s,e, "%s", mods[(m & 0700) >> 6]); s = seprint(s,e, "%s", mods[(m & 070) >> 3]); s = seprint(s,e, "%s", mods[m & 07]); return buf; } char * datefmt(ulong t) { static char buf[48]; Tm *tm; if(mode & nFMT){ snprint(buf,sizeof buf, "%lud", t); return buf; } tm = localtime(t); snprint(buf,sizeof buf,"%04d/%02d/%02d %02d:%02d:%02d", tm->year + 1900,tm->mon + 1,tm->mday, tm->hour, tm->min, tm->sec); return buf; } /* * don't use d->name, the name is in path */ void ls(char *path, Dir *d) { if(mode & LFMT){ Bprint(&out,"%s %s %s %8llud %s %s\n", modefmt(d->mode), d->uid, d->gid, d->length, datefmt(d->mtime), path); } else Bprint(&out,"%s\n", path); if(wflag && d->length == 0 && (d->mode & DMDIR) == 0) fprint(2, "# empty file: %s\n", path); } int compar(Dir *a, Dir *b) { return strcmp(a->name, b->name); } void list(char *path, char *ep, int depth) { Dir *db; int fd, i,n; ulong m; if(quit) return; if(path[0] == '.' && path[1] == '/') path += 2; db = dirstat(path); if(db == nil){ fprint(2, "# %s: non-existent or dead\n", path); return; } ls(path, db); m = db->mode; free(db); if((m & DMDIR) == 0) return; if(depth == 0) return; depth--; fd = open(path, OREAD); if(fd < 0){ fprint(2, "# %s: unreadable\n", path); return; } n = dirreadall(fd, &db); close(fd); if(n < 0){ fprint(2, "# %s: %r\n", path); return; } /* sort by name */ qsort(db, n, sizeof(Dir), (int (*)(void*, void*))compar); for(i = 0; i < n; i++){ m = strlen(path); seprint(path + m,ep,"/%s", db[i].name); list(path, ep, depth); path[m] = 0; } free(db); if(wflag && n == 0) fprint(2, "# empty dir: %s\n", path); } void main(int argc, char *argv[]) { char path[4096]; char wd[512]; char *ep, *ap; int pflag = 0; int depth = -1; ARGBEGIN{ case 'd': ap = ARGF(); if(!ap) usage(); depth = atoi(ap); break; case 'l': mode |= LFMT; break; case 'n': mode |= nFMT; break; case 'p': pflag = 1; break; case 'w': wflag = 1; break; default: usage(); }ARGEND Binit(&out, 1, OWRITE); ep = path + sizeof path; if(*argv == nil){ strcpy(path,"."); list(path, ep, depth); exits(nil); } if(pflag){ getwd(wd, sizeof(wd)); atnotify(notefun,1); } while(*argv){ if(pflag){ chdir(*argv); *argv = "."; } strecpy(path, ep, *argv); list(path, ep, depth); argv++; } if(pflag) chdir(wd); }