Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
	if(db->dee == nil){
20
		/* can happen if dir is removed from under us */
21
		vtMemFree(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
	vtMemFree(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
	vtMemFree(dir.muid);
86
	vtMemFree(dir.gid);
87
	vtMemFree(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
}