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