9dir.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #include "stdinc.h"
  2. #include "9.h"
  3. /* one entry buffer for reading directories */
  4. struct DirBuf {
  5. DirEntryEnum* dee;
  6. int valid;
  7. DirEntry de;
  8. };
  9. static DirBuf*
  10. dirBufAlloc(File* file)
  11. {
  12. DirBuf *db;
  13. db = vtMemAllocZ(sizeof(DirBuf));
  14. db->dee = deeOpen(file);
  15. return db;
  16. }
  17. void
  18. dirBufFree(DirBuf* db)
  19. {
  20. if(db == nil)
  21. return;
  22. if(db->valid)
  23. deCleanup(&db->de);
  24. deeClose(db->dee);
  25. vtMemFree(db);
  26. }
  27. int
  28. dirDe2M(DirEntry* de, uchar* p, int np)
  29. {
  30. int n;
  31. Dir dir;
  32. memset(&dir, 0, sizeof(Dir));
  33. dir.qid.path = de->qid;
  34. dir.qid.vers = de->mcount;
  35. dir.mode = de->mode & 0777;
  36. if(de->mode & ModeAppend){
  37. dir.qid.type |= QTAPPEND;
  38. dir.mode |= DMAPPEND;
  39. }
  40. if(de->mode & ModeExclusive){
  41. dir.qid.type |= QTEXCL;
  42. dir.mode |= DMEXCL;
  43. }
  44. if(de->mode & ModeDir){
  45. dir.qid.type |= QTDIR;
  46. dir.mode |= DMDIR;
  47. }
  48. if(de->mode & ModeSnapshot){
  49. dir.qid.type |= QTMOUNT; /* just for debugging */
  50. dir.mode |= DMMOUNT;
  51. }
  52. dir.atime = de->atime;
  53. dir.mtime = de->mtime;
  54. dir.length = de->size;
  55. dir.name = de->elem;
  56. if((dir.uid = unameByUid(de->uid)) == nil)
  57. dir.uid = smprint("(%s)", de->uid);
  58. if((dir.gid = unameByUid(de->gid)) == nil)
  59. dir.gid = smprint("(%s)", de->gid);
  60. if((dir.muid = unameByUid(de->mid)) == nil)
  61. dir.muid = smprint("(%s)", de->mid);
  62. n = convD2M(&dir, p, np);
  63. vtMemFree(dir.muid);
  64. vtMemFree(dir.gid);
  65. vtMemFree(dir.uid);
  66. return n;
  67. }
  68. int
  69. dirRead(Fid* fid, uchar* p, int count, vlong offset)
  70. {
  71. int n, nb;
  72. DirBuf *db;
  73. /*
  74. * special case of rewinding a directory
  75. * otherwise ignore the offset
  76. */
  77. if(offset == 0 && fid->db){
  78. dirBufFree(fid->db);
  79. fid->db = nil;
  80. }
  81. if(fid->db == nil)
  82. fid->db = dirBufAlloc(fid->file);
  83. db = fid->db;
  84. for(nb = 0; nb < count; nb += n){
  85. if(!db->valid){
  86. n = deeRead(db->dee, &db->de);
  87. if(n < 0)
  88. return -1;
  89. if(n == 0)
  90. break;
  91. db->valid = 1;
  92. }
  93. n = dirDe2M(&db->de, p+nb, count-nb);
  94. if(n <= BIT16SZ)
  95. break;
  96. db->valid = 0;
  97. deCleanup(&db->de);
  98. }
  99. return nb;
  100. }