dirls.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <mp.h>
  4. #include <libsec.h>
  5. #include "SConn.h"
  6. static long
  7. ls(char *p, Dir **dirbuf)
  8. {
  9. int fd;
  10. long n;
  11. Dir *db;
  12. if((db = dirstat(p)) == nil ||
  13. !(db->qid.type & QTDIR) ||
  14. (fd = open(p, OREAD)) < 0 )
  15. return -1;
  16. free(db);
  17. n = dirreadall(fd, dirbuf);
  18. close(fd);
  19. return n;
  20. }
  21. static uchar*
  22. sha1file(char *pfx, char *nm)
  23. {
  24. int n, fd, len;
  25. char *tmp;
  26. uchar buf[8192];
  27. static uchar digest[SHA1dlen];
  28. DigestState *s;
  29. len = strlen(pfx)+1+strlen(nm)+1;
  30. tmp = emalloc(len);
  31. snprint(tmp, len, "%s/%s", pfx, nm);
  32. if((fd = open(tmp, OREAD)) < 0){
  33. free(tmp);
  34. return nil;
  35. }
  36. free(tmp);
  37. s = nil;
  38. while((n = read(fd, buf, sizeof buf)) > 0)
  39. s = sha1(buf, n, nil, s);
  40. close(fd);
  41. sha1(nil, 0, digest, s);
  42. return digest;
  43. }
  44. static int
  45. compare(Dir *a, Dir *b)
  46. {
  47. return strcmp(a->name, b->name);
  48. }
  49. /* list the (name mtime size sum) of regular, readable files in path */
  50. char *
  51. dirls(char *path)
  52. {
  53. char *list, *date, dig[30], buf[128];
  54. int m, nmwid, lenwid;
  55. long i, n, ndir, len;
  56. Dir *dirbuf;
  57. if(path==nil || (ndir = ls(path, &dirbuf)) < 0)
  58. return nil;
  59. qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(void *, void *))compare);
  60. for(nmwid=lenwid=i=0; i<ndir; i++){
  61. if((m = strlen(dirbuf[i].name)) > nmwid)
  62. nmwid = m;
  63. snprint(buf, sizeof(buf), "%ulld", dirbuf[i].length);
  64. if((m = strlen(buf)) > lenwid)
  65. lenwid = m;
  66. }
  67. for(list=nil, len=0, i=0; i<ndir; i++){
  68. date = ctime(dirbuf[i].mtime);
  69. date[28] = 0; // trim newline
  70. n = snprint(buf, sizeof buf, "%*ulld %s", lenwid, dirbuf[i].length, date+4);
  71. n += enc64(dig, sizeof dig, sha1file(path, dirbuf[i].name), SHA1dlen);
  72. n += nmwid+3+strlen(dirbuf[i].name);
  73. list = erealloc(list, len+n+1);
  74. len += snprint(list+len, n+1, "%-*s\t%s %s\n", nmwid, dirbuf[i].name, buf, dig);
  75. }
  76. free(dirbuf);
  77. return list;
  78. }