19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <mp.h>
49a747e4fSDavid du Colombier #include <libsec.h>
59a747e4fSDavid du Colombier #include "SConn.h"
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier static long
ls(char * p,Dir ** dirbuf)89a747e4fSDavid du Colombier ls(char *p, Dir **dirbuf)
99a747e4fSDavid du Colombier {
109a747e4fSDavid du Colombier int fd;
119a747e4fSDavid du Colombier long n;
129a747e4fSDavid du Colombier Dir *db;
139a747e4fSDavid du Colombier
149a747e4fSDavid du Colombier if((db = dirstat(p)) == nil ||
159a747e4fSDavid du Colombier !(db->qid.type & QTDIR) ||
169a747e4fSDavid du Colombier (fd = open(p, OREAD)) < 0 )
179a747e4fSDavid du Colombier return -1;
189a747e4fSDavid du Colombier free(db);
199a747e4fSDavid du Colombier n = dirreadall(fd, dirbuf);
209a747e4fSDavid du Colombier close(fd);
219a747e4fSDavid du Colombier return n;
229a747e4fSDavid du Colombier }
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier static uchar*
sha1file(char * pfx,char * nm)259a747e4fSDavid du Colombier sha1file(char *pfx, char *nm)
269a747e4fSDavid du Colombier {
279a747e4fSDavid du Colombier int n, fd, len;
289a747e4fSDavid du Colombier char *tmp;
299a747e4fSDavid du Colombier uchar buf[8192];
309a747e4fSDavid du Colombier static uchar digest[SHA1dlen];
319a747e4fSDavid du Colombier DigestState *s;
329a747e4fSDavid du Colombier
339a747e4fSDavid du Colombier len = strlen(pfx)+1+strlen(nm)+1;
349a747e4fSDavid du Colombier tmp = emalloc(len);
359a747e4fSDavid du Colombier snprint(tmp, len, "%s/%s", pfx, nm);
369a747e4fSDavid du Colombier if((fd = open(tmp, OREAD)) < 0){
379a747e4fSDavid du Colombier free(tmp);
389a747e4fSDavid du Colombier return nil;
399a747e4fSDavid du Colombier }
409a747e4fSDavid du Colombier free(tmp);
419a747e4fSDavid du Colombier s = nil;
429a747e4fSDavid du Colombier while((n = read(fd, buf, sizeof buf)) > 0)
439a747e4fSDavid du Colombier s = sha1(buf, n, nil, s);
449a747e4fSDavid du Colombier close(fd);
459a747e4fSDavid du Colombier sha1(nil, 0, digest, s);
469a747e4fSDavid du Colombier return digest;
479a747e4fSDavid du Colombier }
489a747e4fSDavid du Colombier
499a747e4fSDavid du Colombier static int
compare(Dir * a,Dir * b)509a747e4fSDavid du Colombier compare(Dir *a, Dir *b)
519a747e4fSDavid du Colombier {
529a747e4fSDavid du Colombier return strcmp(a->name, b->name);
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier
559a747e4fSDavid du Colombier /* list the (name mtime size sum) of regular, readable files in path */
569a747e4fSDavid du Colombier char *
dirls(char * path)579a747e4fSDavid du Colombier dirls(char *path)
589a747e4fSDavid du Colombier {
599a747e4fSDavid du Colombier char *list, *date, dig[30], buf[128];
609a747e4fSDavid du Colombier int m, nmwid, lenwid;
619a747e4fSDavid du Colombier long i, n, ndir, len;
629a747e4fSDavid du Colombier Dir *dirbuf;
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier if(path==nil || (ndir = ls(path, &dirbuf)) < 0)
659a747e4fSDavid du Colombier return nil;
669a747e4fSDavid du Colombier
679a747e4fSDavid du Colombier qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(void *, void *))compare);
689a747e4fSDavid du Colombier for(nmwid=lenwid=i=0; i<ndir; i++){
699a747e4fSDavid du Colombier if((m = strlen(dirbuf[i].name)) > nmwid)
709a747e4fSDavid du Colombier nmwid = m;
719a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "%ulld", dirbuf[i].length);
729a747e4fSDavid du Colombier if((m = strlen(buf)) > lenwid)
739a747e4fSDavid du Colombier lenwid = m;
749a747e4fSDavid du Colombier }
759a747e4fSDavid du Colombier for(list=nil, len=0, i=0; i<ndir; i++){
769a747e4fSDavid du Colombier date = ctime(dirbuf[i].mtime);
779a747e4fSDavid du Colombier date[28] = 0; // trim newline
789a747e4fSDavid du Colombier n = snprint(buf, sizeof buf, "%*ulld %s", lenwid, dirbuf[i].length, date+4);
799a747e4fSDavid du Colombier n += enc64(dig, sizeof dig, sha1file(path, dirbuf[i].name), SHA1dlen);
809a747e4fSDavid du Colombier n += nmwid+3+strlen(dirbuf[i].name);
819a747e4fSDavid du Colombier list = erealloc(list, len+n+1);
829a747e4fSDavid du Colombier len += snprint(list+len, n+1, "%-*s\t%s %s\n", nmwid, dirbuf[i].name, buf, dig);
839a747e4fSDavid du Colombier }
84*be0c1e85SDavid du Colombier free(dirbuf);
859a747e4fSDavid du Colombier return list;
869a747e4fSDavid du Colombier }
879a747e4fSDavid du Colombier
88