/* * a modified 'ls' that works by processing proto(3) files */ #include #include #include #include /* dirmodefmt */ #include #include #include #define dirbuf p9dirbuf /* avoid conflict on sun */ int errs = 0; int aflag; int lflag; int mflag; int pflag; int qflag; int Qflag; int sflag; int Fflag; int Dflag; int ls(char*, int); char* asciitime(long); void format(Dir*, char*); void output(void); ulong clk; int swidth; /* max width of -s size */ int qwidth; /* max width of -q version */ int vwidth; /* max width of dev */ int uwidth; /* max width of userid */ int mwidth; /* max width of muid */ int glwidth; /* max width of groupid and length */ void usage(void); char *argv0; Biobuf *b; Biobuf bin; char *proto; char *root; static void addprotofile(char *new, char *old, Dir *d, void *a); static int digestfmt(Fmt *fmt) { char buf[MD5dlen*2+1]; uchar *p; int i; p = va_arg(fmt->args, uchar*); for(i=0; iname); } // skip directories if listing for tar format if(!(aflag && (QTDIR & d->qid.type))){ char *p, *name; p = utfrune(new, '/'); name = p+1; // skips the default '/' format(d, name); Bflush(&bin); } } char* fileflag(Dir *db) { if(Fflag == 0) return ""; if(QTDIR & db->qid.type) return "/"; if(0111 & db->mode) return "*"; return ""; } void format(Dir *db, char *name) { if(sflag) Bprint(&bin, "%*llud ", swidth, (db->length+1023)/1024); if(qflag) Bprint(&bin, "(%.16llux %*lud %.2ux) ", db->qid.path, qwidth, db->qid.vers, db->qid.type); if(lflag) Bprint(&bin, "%M %C %*ud %*s %s %*llud %s ", db->mode, db->type, vwidth, db->dev, -uwidth, db->uid, db->gid, (int)(glwidth-strlen(db->gid)), db->length, asciitime(db->mtime)); if(mflag) { uchar digest[MD5dlen]; memset(digest, 0, sizeof digest); if(!(QTDIR & db->qid.type)) { int n, fd; uchar buf[8192]; DigestState *s; String *path = nil; path = s_new(); s_append(path, root); s_append(path, "/"); s_append(path, name); fd = open(s_to_c(path), OREAD); if(path) s_free(path); if(fd < 0){ Bprint(&bin, "md5sum: can't open %s: %r\n", name); return; } s = md5(nil, 0, nil, nil); while((n = read(fd, buf, sizeof buf)) > 0) md5(buf, n, nil, s); md5(nil, 0, digest, s); close(fd); } Bprint(&bin, "%m\t", digest); } if(!pflag) if(strcmp(root, ".") != 0) Bprint(&bin, "%s/", root); if(pflag) { char *p = utfrrune(name, '/'); if(p){ name = p+1; } } Bprint(&bin, Qflag? "%s%s\n" : "%q%s\n", name, fileflag(db)); } char* asciitime(long l) { static char buf[32]; char *t; t = ctime(l); /* 6 months in the past or a day in the future */ if(l