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 63 dir.atime = de->atime; 64 dir.mtime = de->mtime; 65 dir.length = de->size; 66 67 dir.name = de->elem; 68 if((dir.uid = unameByUid(de->uid)) == nil) 69 dir.uid = smprint("(%s)", de->uid); 70 if((dir.gid = unameByUid(de->gid)) == nil) 71 dir.gid = smprint("(%s)", de->gid); 72 if((dir.muid = unameByUid(de->mid)) == nil) 73 dir.muid = smprint("(%s)", de->mid); 74 75 n = convD2M(&dir, p, np); 76 77 vtMemFree(dir.muid); 78 vtMemFree(dir.gid); 79 vtMemFree(dir.uid); 80 81 return n; 82 } 83 84 int 85 dirRead(Fid* fid, uchar* p, int count, vlong offset) 86 { 87 int n, nb; 88 DirBuf *db; 89 90 /* 91 * special case of rewinding a directory 92 * otherwise ignore the offset 93 */ 94 if(offset == 0 && fid->db){ 95 dirBufFree(fid->db); 96 fid->db = nil; 97 } 98 99 if(fid->db == nil) 100 fid->db = dirBufAlloc(fid->file); 101 102 db = fid->db; 103 104 for(nb = 0; nb < count; nb += n){ 105 if(!db->valid){ 106 n = deeRead(db->dee, &db->de); 107 if(n < 0) 108 return -1; 109 if(n == 0) 110 break; 111 db->valid = 1; 112 } 113 n = dirDe2M(&db->de, p+nb, count-nb); 114 if(n <= BIT16SZ) 115 break; 116 db->valid = 0; 117 deCleanup(&db->de); 118 } 119 120 return nb; 121 } 122