dirls.c 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <mp.h>
  12. #include <libsec.h>
  13. #include "SConn.h"
  14. static int32_t
  15. ls(char *p, Dir **dirbuf)
  16. {
  17. int fd;
  18. int32_t n;
  19. Dir *db;
  20. if((db = dirstat(p)) == nil ||
  21. !(db->qid.type & QTDIR) ||
  22. (fd = open(p, OREAD)) < 0 )
  23. return -1;
  24. free(db);
  25. n = dirreadall(fd, dirbuf);
  26. close(fd);
  27. return n;
  28. }
  29. static uint8_t*
  30. sha1file(char *pfx, char *nm)
  31. {
  32. int n, fd, len;
  33. char *tmp;
  34. uint8_t buf[8192];
  35. static uint8_t digest[SHA1dlen];
  36. DigestState *s;
  37. len = strlen(pfx)+1+strlen(nm)+1;
  38. tmp = emalloc(len);
  39. snprint(tmp, len, "%s/%s", pfx, nm);
  40. if((fd = open(tmp, OREAD)) < 0){
  41. free(tmp);
  42. return nil;
  43. }
  44. free(tmp);
  45. s = nil;
  46. while((n = read(fd, buf, sizeof buf)) > 0)
  47. s = sha1(buf, n, nil, s);
  48. close(fd);
  49. sha1(nil, 0, digest, s);
  50. return digest;
  51. }
  52. static int
  53. compare(const Dir *a, const Dir *b)
  54. {
  55. return strcmp(a->name, b->name);
  56. }
  57. /* list the (name mtime size sum) of regular, readable files in path */
  58. char *
  59. dirls(char *path)
  60. {
  61. char *list, *date, dig[30], buf[128];
  62. int m, nmwid, lenwid;
  63. int32_t i, n, ndir, len;
  64. Dir *dirbuf;
  65. if(path==nil || (ndir = ls(path, &dirbuf)) < 0)
  66. return nil;
  67. qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void *, const void *))compare);
  68. for(nmwid=lenwid=i=0; i<ndir; i++){
  69. if((m = strlen(dirbuf[i].name)) > nmwid)
  70. nmwid = m;
  71. snprint(buf, sizeof(buf), "%llu", dirbuf[i].length);
  72. if((m = strlen(buf)) > lenwid)
  73. lenwid = m;
  74. }
  75. for(list=nil, len=0, i=0; i<ndir; i++){
  76. date = ctime(dirbuf[i].mtime);
  77. date[28] = 0; // trim newline
  78. n = snprint(buf, sizeof buf, "%*ulld %s", lenwid, dirbuf[i].length, date+4);
  79. n += enc64(dig, sizeof dig, sha1file(path, dirbuf[i].name), SHA1dlen);
  80. n += nmwid+3+strlen(dirbuf[i].name);
  81. list = erealloc(list, len+n+1);
  82. len += snprint(list+len, n+1, "%-*s\t%s %s\n", nmwid, dirbuf[i].name, buf, dig);
  83. }
  84. free(dirbuf);
  85. return list;
  86. }