| #include <u.h> |
| #include <libc.h> |
| #include <mp.h> |
| #include <libsec.h> |
| #include "SConn.h" |
| |
| static long |
| ls(char *p, Dir **dirbuf) |
| { |
| int fd; |
| long n; |
| Dir *db; |
| |
| if((db = dirstat(p)) == nil || |
| !(db->qid.type & QTDIR) || |
| (fd = open(p, OREAD)) < 0 ) |
| return -1; |
| free(db); |
| n = dirreadall(fd, dirbuf); |
| close(fd); |
| return n; |
| } |
| |
| static uchar* |
| sha1file(char *pfx, char *nm) |
| { |
| int n, fd, len; |
| char *tmp; |
| uchar buf[8192]; |
| static uchar digest[SHA1dlen]; |
| DigestState *s; |
| |
| len = strlen(pfx)+1+strlen(nm)+1; |
| tmp = emalloc(len); |
| snprint(tmp, len, "%s/%s", pfx, nm); |
| if((fd = open(tmp, OREAD)) < 0){ |
| free(tmp); |
| return nil; |
| } |
| free(tmp); |
| s = nil; |
| while((n = read(fd, buf, sizeof buf)) > 0) |
| s = sha1(buf, n, nil, s); |
| close(fd); |
| sha1(nil, 0, digest, s); |
| return digest; |
| } |
| |
| static int |
| compare(Dir *a, Dir *b) |
| { |
| return strcmp(a->name, b->name); |
| } |
| |
| /* list the (name mtime size sum) of regular, readable files in path */ |
| char * |
| dirls(char *path) |
| { |
| char *list, *date, dig[30], buf[128]; |
| int m, nmwid, lenwid; |
| long i, n, ndir, len; |
| Dir *dirbuf; |
| |
| if(path==nil || (ndir = ls(path, &dirbuf)) < 0) |
| return nil; |
| |
| qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void *, const void *))compare); |
| for(nmwid=lenwid=i=0; i<ndir; i++){ |
| if((m = strlen(dirbuf[i].name)) > nmwid) |
| nmwid = m; |
| snprint(buf, sizeof(buf), "%ulld", dirbuf[i].length); |
| if((m = strlen(buf)) > lenwid) |
| lenwid = m; |
| } |
| for(list=nil, len=0, i=0; i<ndir; i++){ |
| date = ctime(dirbuf[i].mtime); |
| date[28] = 0; /* trim newline */ |
| n = snprint(buf, sizeof buf, "%*ulld %s", lenwid, dirbuf[i].length, date+4); |
| n += enc64(dig, sizeof dig, sha1file(path, dirbuf[i].name), SHA1dlen); |
| n += nmwid+3+strlen(dirbuf[i].name); |
| list = erealloc(list, len+n+1); |
| len += snprint(list+len, n+1, "%-*s\t%s %s\n", nmwid, dirbuf[i].name, buf, dig); |
| } |
| free(dirbuf); |
| return list; |
| } |
| |