xref: /plan9/sys/src/cmd/fossil/9dir.c (revision 418f3c223ba97d6d4f967eee6f77a8629a37a7eb)
15e96a66cSDavid du Colombier #include "stdinc.h"
25e96a66cSDavid du Colombier 
35e96a66cSDavid du Colombier #include "9.h"
45e96a66cSDavid du Colombier 
55e96a66cSDavid du Colombier /* one entry buffer for reading directories */
65e96a66cSDavid du Colombier struct DirBuf {
75e96a66cSDavid du Colombier 	DirEntryEnum*	dee;
85e96a66cSDavid du Colombier 	int		valid;
95e96a66cSDavid du Colombier 	DirEntry	de;
105e96a66cSDavid du Colombier };
115e96a66cSDavid du Colombier 
125e96a66cSDavid du Colombier static DirBuf*
dirBufAlloc(File * file)135e96a66cSDavid du Colombier dirBufAlloc(File* file)
145e96a66cSDavid du Colombier {
155e96a66cSDavid du Colombier 	DirBuf *db;
165e96a66cSDavid du Colombier 
175e96a66cSDavid du Colombier 	db = vtMemAllocZ(sizeof(DirBuf));
185e96a66cSDavid du Colombier 	db->dee = deeOpen(file);
19*418f3c22SDavid du Colombier 	if(db->dee == nil){
20*418f3c22SDavid du Colombier 		/* can happen if dir is removed from under us */
21*418f3c22SDavid du Colombier 		vtMemFree(db);
22*418f3c22SDavid du Colombier 		return nil;
23*418f3c22SDavid du Colombier 	}
245e96a66cSDavid du Colombier 	return db;
255e96a66cSDavid du Colombier }
265e96a66cSDavid du Colombier 
275e96a66cSDavid du Colombier void
dirBufFree(DirBuf * db)285e96a66cSDavid du Colombier dirBufFree(DirBuf* db)
295e96a66cSDavid du Colombier {
305e96a66cSDavid du Colombier 	if(db == nil)
315e96a66cSDavid du Colombier 		return;
325e96a66cSDavid du Colombier 
335e96a66cSDavid du Colombier 	if(db->valid)
345e96a66cSDavid du Colombier 		deCleanup(&db->de);
355e96a66cSDavid du Colombier 	deeClose(db->dee);
365e96a66cSDavid du Colombier 	vtMemFree(db);
375e96a66cSDavid du Colombier }
385e96a66cSDavid du Colombier 
395e96a66cSDavid du Colombier int
dirDe2M(DirEntry * de,uchar * p,int np)405e96a66cSDavid du Colombier dirDe2M(DirEntry* de, uchar* p, int np)
415e96a66cSDavid du Colombier {
425e96a66cSDavid du Colombier 	int n;
435e96a66cSDavid du Colombier 	Dir dir;
445e96a66cSDavid du Colombier 
455e96a66cSDavid du Colombier 	memset(&dir, 0, sizeof(Dir));
465e96a66cSDavid du Colombier 
475e96a66cSDavid du Colombier 	dir.qid.path = de->qid;
485e96a66cSDavid du Colombier 	dir.qid.vers = de->mcount;
495e96a66cSDavid du Colombier 	dir.mode = de->mode & 0777;
505e96a66cSDavid du Colombier 	if(de->mode & ModeAppend){
515e96a66cSDavid du Colombier 		dir.qid.type |= QTAPPEND;
525e96a66cSDavid du Colombier 		dir.mode |= DMAPPEND;
535e96a66cSDavid du Colombier 	}
545e96a66cSDavid du Colombier 	if(de->mode & ModeExclusive){
555e96a66cSDavid du Colombier 		dir.qid.type |= QTEXCL;
565e96a66cSDavid du Colombier 		dir.mode |= DMEXCL;
575e96a66cSDavid du Colombier 	}
585e96a66cSDavid du Colombier 	if(de->mode & ModeDir){
595e96a66cSDavid du Colombier 		dir.qid.type |= QTDIR;
605e96a66cSDavid du Colombier 		dir.mode |= DMDIR;
615e96a66cSDavid du Colombier 	}
625e96a66cSDavid du Colombier 	if(de->mode & ModeSnapshot){
635e96a66cSDavid du Colombier 		dir.qid.type |= QTMOUNT;	/* just for debugging */
645e96a66cSDavid du Colombier 		dir.mode |= DMMOUNT;
655e96a66cSDavid du Colombier 	}
66fe853e23SDavid du Colombier 	if(de->mode & ModeTemporary){
67fe853e23SDavid du Colombier 		dir.qid.type |= QTTMP;
68fe853e23SDavid du Colombier 		dir.mode |= DMTMP;
69fe853e23SDavid du Colombier 	}
705e96a66cSDavid du Colombier 
715e96a66cSDavid du Colombier 	dir.atime = de->atime;
725e96a66cSDavid du Colombier 	dir.mtime = de->mtime;
735e96a66cSDavid du Colombier 	dir.length = de->size;
745e96a66cSDavid du Colombier 
755e96a66cSDavid du Colombier 	dir.name = de->elem;
765e96a66cSDavid du Colombier 	if((dir.uid = unameByUid(de->uid)) == nil)
775e96a66cSDavid du Colombier 		dir.uid = smprint("(%s)", de->uid);
785e96a66cSDavid du Colombier 	if((dir.gid = unameByUid(de->gid)) == nil)
795e96a66cSDavid du Colombier 		dir.gid = smprint("(%s)", de->gid);
805e96a66cSDavid du Colombier 	if((dir.muid = unameByUid(de->mid)) == nil)
815e96a66cSDavid du Colombier 		dir.muid = smprint("(%s)", de->mid);
825e96a66cSDavid du Colombier 
835e96a66cSDavid du Colombier 	n = convD2M(&dir, p, np);
845e96a66cSDavid du Colombier 
855e96a66cSDavid du Colombier 	vtMemFree(dir.muid);
865e96a66cSDavid du Colombier 	vtMemFree(dir.gid);
875e96a66cSDavid du Colombier 	vtMemFree(dir.uid);
885e96a66cSDavid du Colombier 
895e96a66cSDavid du Colombier 	return n;
905e96a66cSDavid du Colombier }
915e96a66cSDavid du Colombier 
925e96a66cSDavid du Colombier int
dirRead(Fid * fid,uchar * p,int count,vlong offset)935e96a66cSDavid du Colombier dirRead(Fid* fid, uchar* p, int count, vlong offset)
945e96a66cSDavid du Colombier {
955e96a66cSDavid du Colombier 	int n, nb;
965e96a66cSDavid du Colombier 	DirBuf *db;
975e96a66cSDavid du Colombier 
985e96a66cSDavid du Colombier 	/*
995e96a66cSDavid du Colombier 	 * special case of rewinding a directory
1005e96a66cSDavid du Colombier 	 * otherwise ignore the offset
1015e96a66cSDavid du Colombier 	 */
1025e96a66cSDavid du Colombier 	if(offset == 0 && fid->db){
1035e96a66cSDavid du Colombier 		dirBufFree(fid->db);
1045e96a66cSDavid du Colombier 		fid->db = nil;
1055e96a66cSDavid du Colombier 	}
1065e96a66cSDavid du Colombier 
107*418f3c22SDavid du Colombier 	if(fid->db == nil){
1085e96a66cSDavid du Colombier 		fid->db = dirBufAlloc(fid->file);
109*418f3c22SDavid du Colombier 		if(fid->db == nil)
110*418f3c22SDavid du Colombier 			return -1;
111*418f3c22SDavid du Colombier 	}
1125e96a66cSDavid du Colombier 
1135e96a66cSDavid du Colombier 	db = fid->db;
1145e96a66cSDavid du Colombier 
1155e96a66cSDavid du Colombier 	for(nb = 0; nb < count; nb += n){
1165e96a66cSDavid du Colombier 		if(!db->valid){
1175e96a66cSDavid du Colombier 			n = deeRead(db->dee, &db->de);
1185e96a66cSDavid du Colombier 			if(n < 0)
1195e96a66cSDavid du Colombier 				return -1;
1205e96a66cSDavid du Colombier 			if(n == 0)
1215e96a66cSDavid du Colombier 				break;
1225e96a66cSDavid du Colombier 			db->valid = 1;
1235e96a66cSDavid du Colombier 		}
1245e96a66cSDavid du Colombier 		n = dirDe2M(&db->de, p+nb, count-nb);
1255e96a66cSDavid du Colombier 		if(n <= BIT16SZ)
1265e96a66cSDavid du Colombier 			break;
1275e96a66cSDavid du Colombier 		db->valid = 0;
1285e96a66cSDavid du Colombier 		deCleanup(&db->de);
1295e96a66cSDavid du Colombier 	}
1305e96a66cSDavid du Colombier 
1315e96a66cSDavid du Colombier 	return nb;
1325e96a66cSDavid du Colombier }
133