/*
* lr: list directories recursively
* version: 1.1
* date: 2005/02/18
* auther: Kenar(Kenji Arisawa)
* Email: [email protected]
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
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);
}
|