9dir.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. if(db->dee == nil){
  16. /* can happen if dir is removed from under us */
  17. vtMemFree(db);
  18. return nil;
  19. }
  20. return db;
  21. }
  22. void
  23. dirBufFree(DirBuf* db)
  24. {
  25. if(db == nil)
  26. return;
  27. if(db->valid)
  28. deCleanup(&db->de);
  29. deeClose(db->dee);
  30. vtMemFree(db);
  31. }
  32. int
  33. dirDe2M(DirEntry* de, uchar* p, int np)
  34. {
  35. int n;
  36. Dir dir;
  37. memset(&dir, 0, sizeof(Dir));
  38. dir.qid.path = de->qid;
  39. dir.qid.vers = de->mcount;
  40. dir.mode = de->mode & 0777;
  41. if(de->mode & ModeAppend){
  42. dir.qid.type |= QTAPPEND;
  43. dir.mode |= DMAPPEND;
  44. }
  45. if(de->mode & ModeExclusive){
  46. dir.qid.type |= QTEXCL;
  47. dir.mode |= DMEXCL;
  48. }
  49. if(de->mode & ModeDir){
  50. dir.qid.type |= QTDIR;
  51. dir.mode |= DMDIR;
  52. }
  53. if(de->mode & ModeSnapshot){
  54. dir.qid.type |= QTMOUNT; /* just for debugging */
  55. dir.mode |= DMMOUNT;
  56. }
  57. if(de->mode & ModeTemporary){
  58. dir.qid.type |= QTTMP;
  59. dir.mode |= DMTMP;
  60. }
  61. dir.atime = de->atime;
  62. dir.mtime = de->mtime;
  63. dir.length = de->size;
  64. dir.name = de->elem;
  65. if((dir.uid = unameByUid(de->uid)) == nil)
  66. dir.uid = smprint("(%s)", de->uid);
  67. if((dir.gid = unameByUid(de->gid)) == nil)
  68. dir.gid = smprint("(%s)", de->gid);
  69. if((dir.muid = unameByUid(de->mid)) == nil)
  70. dir.muid = smprint("(%s)", de->mid);
  71. n = convD2M(&dir, p, np);
  72. vtMemFree(dir.muid);
  73. vtMemFree(dir.gid);
  74. vtMemFree(dir.uid);
  75. return n;
  76. }
  77. int
  78. dirRead(Fid* fid, uchar* p, int count, vlong offset)
  79. {
  80. int n, nb;
  81. DirBuf *db;
  82. /*
  83. * special case of rewinding a directory
  84. * otherwise ignore the offset
  85. */
  86. if(offset == 0 && fid->db){
  87. dirBufFree(fid->db);
  88. fid->db = nil;
  89. }
  90. if(fid->db == nil){
  91. fid->db = dirBufAlloc(fid->file);
  92. if(fid->db == nil)
  93. return -1;
  94. }
  95. db = fid->db;
  96. for(nb = 0; nb < count; nb += n){
  97. if(!db->valid){
  98. n = deeRead(db->dee, &db->de);
  99. if(n < 0)
  100. return -1;
  101. if(n == 0)
  102. break;
  103. db->valid = 1;
  104. }
  105. n = dirDe2M(&db->de, p+nb, count-nb);
  106. if(n <= BIT16SZ)
  107. break;
  108. db->valid = 0;
  109. deCleanup(&db->de);
  110. }
  111. return nb;
  112. }