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