9dir.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. if(de->mode & ModeTemporary){
  53. dir.qid.type |= QTTMP;
  54. dir.mode |= DMTMP;
  55. }
  56. dir.atime = de->atime;
  57. dir.mtime = de->mtime;
  58. dir.length = de->size;
  59. dir.name = de->elem;
  60. if((dir.uid = unameByUid(de->uid)) == nil)
  61. dir.uid = smprint("(%s)", de->uid);
  62. if((dir.gid = unameByUid(de->gid)) == nil)
  63. dir.gid = smprint("(%s)", de->gid);
  64. if((dir.muid = unameByUid(de->mid)) == nil)
  65. dir.muid = smprint("(%s)", de->mid);
  66. n = convD2M(&dir, p, np);
  67. vtMemFree(dir.muid);
  68. vtMemFree(dir.gid);
  69. vtMemFree(dir.uid);
  70. return n;
  71. }
  72. int
  73. dirRead(Fid* fid, uchar* p, int count, vlong offset)
  74. {
  75. int n, nb;
  76. DirBuf *db;
  77. /*
  78. * special case of rewinding a directory
  79. * otherwise ignore the offset
  80. */
  81. if(offset == 0 && fid->db){
  82. dirBufFree(fid->db);
  83. fid->db = nil;
  84. }
  85. if(fid->db == nil)
  86. fid->db = dirBufAlloc(fid->file);
  87. db = fid->db;
  88. for(nb = 0; nb < count; nb += n){
  89. if(!db->valid){
  90. n = deeRead(db->dee, &db->de);
  91. if(n < 0)
  92. return -1;
  93. if(n == 0)
  94. break;
  95. db->valid = 1;
  96. }
  97. n = dirDe2M(&db->de, p+nb, count-nb);
  98. if(n <= BIT16SZ)
  99. break;
  100. db->valid = 0;
  101. deCleanup(&db->de);
  102. }
  103. return nb;
  104. }