xref: /haiku/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp (revision 09dbdd3644142673a8df63ae77ff8ccd4524c835)
12a73e4c5SPawel Dziepak /*
22a73e4c5SPawel Dziepak  * Copyright 2012 Haiku, Inc. All rights reserved.
32a73e4c5SPawel Dziepak  * Distributed under the terms of the MIT License.
42a73e4c5SPawel Dziepak  *
52a73e4c5SPawel Dziepak  * Authors:
62a73e4c5SPawel Dziepak  *		Paweł Dziepak, pdziepak@quarnos.org
72a73e4c5SPawel Dziepak  */
82a73e4c5SPawel Dziepak 
92a73e4c5SPawel Dziepak 
102a73e4c5SPawel Dziepak #include "Inode.h"
112a73e4c5SPawel Dziepak 
122a73e4c5SPawel Dziepak #include <dirent.h>
132a73e4c5SPawel Dziepak #include <string.h>
142a73e4c5SPawel Dziepak 
15b2cea80cSPawel Dziepak #include "IdMap.h"
162a73e4c5SPawel Dziepak #include "Request.h"
172a73e4c5SPawel Dziepak #include "RootInode.h"
182a73e4c5SPawel Dziepak 
192a73e4c5SPawel Dziepak 
202a73e4c5SPawel Dziepak status_t
212a73e4c5SPawel Dziepak Inode::CreateDir(const char* name, int mode)
222a73e4c5SPawel Dziepak {
238f57d30eSPawel Dziepak 	bool badOwner = false;
248f57d30eSPawel Dziepak 
252a73e4c5SPawel Dziepak 	do {
2600a8558cSPawel Dziepak 		RPC::Server* serv = fFileSystem->Server();
272a73e4c5SPawel Dziepak 		Request request(serv);
282a73e4c5SPawel Dziepak 		RequestBuilder& req = request.Builder();
292a73e4c5SPawel Dziepak 
30a28e8732SPawel Dziepak 		req.PutFH(fInfo.fHandle);
312a73e4c5SPawel Dziepak 
32b2cea80cSPawel Dziepak 		uint32 i = 0;
33b2cea80cSPawel Dziepak 		AttrValue cattr[3];
34b2cea80cSPawel Dziepak 		cattr[i].fAttribute = FATTR4_MODE;
35b2cea80cSPawel Dziepak 		cattr[i].fFreePointer = false;
36b2cea80cSPawel Dziepak 		cattr[i].fData.fValue32 = mode;
37b2cea80cSPawel Dziepak 		i++;
38b2cea80cSPawel Dziepak 
3900a8558cSPawel Dziepak 		if (!badOwner && fFileSystem->IsAttrSupported(FATTR4_OWNER)) {
40b2cea80cSPawel Dziepak 			cattr[i].fAttribute = FATTR4_OWNER;
41b2cea80cSPawel Dziepak 			cattr[i].fFreePointer = true;
42b2cea80cSPawel Dziepak 			cattr[i].fData.fPointer = gIdMapper->GetOwner(getuid());
43b2cea80cSPawel Dziepak 			i++;
44ed097dd0SPawel Dziepak 		}
45b2cea80cSPawel Dziepak 
4600a8558cSPawel Dziepak 		if (!badOwner && fFileSystem->IsAttrSupported(FATTR4_OWNER_GROUP)) {
47b2cea80cSPawel Dziepak 			cattr[i].fAttribute = FATTR4_OWNER_GROUP;
48b2cea80cSPawel Dziepak 			cattr[i].fFreePointer = true;
49b2cea80cSPawel Dziepak 			cattr[i].fData.fPointer = gIdMapper->GetOwnerGroup(getgid());
50b2cea80cSPawel Dziepak 			i++;
51ed097dd0SPawel Dziepak 		}
52b2cea80cSPawel Dziepak 
53b2cea80cSPawel Dziepak 		req.Create(NF4DIR, name, cattr, i);
542a73e4c5SPawel Dziepak 
552a73e4c5SPawel Dziepak 		status_t result = request.Send();
562a73e4c5SPawel Dziepak 		if (result != B_OK)
572a73e4c5SPawel Dziepak 			return result;
582a73e4c5SPawel Dziepak 
592a73e4c5SPawel Dziepak 		ReplyInterpreter& reply = request.Reply();
602a73e4c5SPawel Dziepak 
618f57d30eSPawel Dziepak 		if (reply.NFS4Error() == NFS4ERR_BADOWNER) {
628f57d30eSPawel Dziepak 			badOwner = true;
638f57d30eSPawel Dziepak 			continue;
648f57d30eSPawel Dziepak 		}
652a73e4c5SPawel Dziepak 		if (_HandleErrors(reply.NFS4Error(), serv))
662a73e4c5SPawel Dziepak 			continue;
672a73e4c5SPawel Dziepak 
682a73e4c5SPawel Dziepak 		reply.PutFH();
692a73e4c5SPawel Dziepak 
707b6f80feSPawel Dziepak 		uint64 before, after;
717b6f80feSPawel Dziepak 		bool atomic;
727b6f80feSPawel Dziepak 		result = reply.Create(&before, &after, atomic);
737b6f80feSPawel Dziepak 
747b6f80feSPawel Dziepak 		fFileSystem->Root()->MakeInfoInvalid();
757b6f80feSPawel Dziepak 
767b6f80feSPawel Dziepak 		if (fCache->Lock() == B_OK) {
777b6f80feSPawel Dziepak 			if (atomic && fCache->ChangeInfo() == before) {
787b6f80feSPawel Dziepak 				// TODO: update cache
797b6f80feSPawel Dziepak 				//fCache->AddEntry(name, );
807b6f80feSPawel Dziepak 				fCache->SetChangeInfo(after);
817b6f80feSPawel Dziepak 			} else if (fCache->ChangeInfo() != before)
827b6f80feSPawel Dziepak 				fCache->Trash();
837b6f80feSPawel Dziepak 			fCache->Unlock();
847b6f80feSPawel Dziepak 		}
857b6f80feSPawel Dziepak 
867b6f80feSPawel Dziepak 		return result;
872a73e4c5SPawel Dziepak 	} while (true);
882a73e4c5SPawel Dziepak }
892a73e4c5SPawel Dziepak 
902a73e4c5SPawel Dziepak 
912a73e4c5SPawel Dziepak status_t
922a73e4c5SPawel Dziepak Inode::OpenDir(OpenDirCookie* cookie)
932a73e4c5SPawel Dziepak {
942a73e4c5SPawel Dziepak 	if (fType != NF4DIR)
952a73e4c5SPawel Dziepak 		return B_NOT_A_DIRECTORY;
962a73e4c5SPawel Dziepak 
972a73e4c5SPawel Dziepak 	do {
9800a8558cSPawel Dziepak 		RPC::Server* serv = fFileSystem->Server();
992a73e4c5SPawel Dziepak 		Request request(serv);
1002a73e4c5SPawel Dziepak 		RequestBuilder& req = request.Builder();
1012a73e4c5SPawel Dziepak 
102a28e8732SPawel Dziepak 		req.PutFH(fInfo.fHandle);
1032a73e4c5SPawel Dziepak 		req.Access();
1042a73e4c5SPawel Dziepak 
1052a73e4c5SPawel Dziepak 		status_t result = request.Send();
1062a73e4c5SPawel Dziepak 		if (result != B_OK)
1072a73e4c5SPawel Dziepak 			return result;
1082a73e4c5SPawel Dziepak 
1092a73e4c5SPawel Dziepak 		ReplyInterpreter& reply = request.Reply();
1102a73e4c5SPawel Dziepak 
1112a73e4c5SPawel Dziepak 		if (_HandleErrors(reply.NFS4Error(), serv))
1122a73e4c5SPawel Dziepak 			continue;
1132a73e4c5SPawel Dziepak 
1142a73e4c5SPawel Dziepak 		reply.PutFH();
1152a73e4c5SPawel Dziepak 
1162a73e4c5SPawel Dziepak 		uint32 allowed;
1172a73e4c5SPawel Dziepak 		result = reply.Access(NULL, &allowed);
1182a73e4c5SPawel Dziepak 		if (result != B_OK)
1192a73e4c5SPawel Dziepak 			return result;
1202a73e4c5SPawel Dziepak 
1212a73e4c5SPawel Dziepak 		if (allowed & ACCESS4_READ != ACCESS4_READ)
1222a73e4c5SPawel Dziepak 			return B_PERMISSION_DENIED;
1232a73e4c5SPawel Dziepak 
12400a8558cSPawel Dziepak 		cookie->fFileSystem = fFileSystem;
125*09dbdd36SPawel Dziepak 		cookie->fSnapshot = NULL;
126*09dbdd36SPawel Dziepak 		cookie->fCurrent = NULL;
127*09dbdd36SPawel Dziepak 		cookie->fEOF = false;
1282a73e4c5SPawel Dziepak 
12978fc85a6SPawel Dziepak 		fFileSystem->Root()->MakeInfoInvalid();
13078fc85a6SPawel Dziepak 
1312a73e4c5SPawel Dziepak 		return B_OK;
1322a73e4c5SPawel Dziepak 	} while (true);
1332a73e4c5SPawel Dziepak }
1342a73e4c5SPawel Dziepak 
1352a73e4c5SPawel Dziepak 
1362a73e4c5SPawel Dziepak status_t
1372a73e4c5SPawel Dziepak Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie,
138*09dbdd36SPawel Dziepak 	bool* eof, uint64* change, uint64* dirCookie, uint64* dirCookieVerf)
1392a73e4c5SPawel Dziepak {
1402a73e4c5SPawel Dziepak 	do {
14100a8558cSPawel Dziepak 		RPC::Server* serv = fFileSystem->Server();
1422a73e4c5SPawel Dziepak 		Request request(serv);
1432a73e4c5SPawel Dziepak 		RequestBuilder& req = request.Builder();
1442a73e4c5SPawel Dziepak 
145a28e8732SPawel Dziepak 		req.PutFH(fInfo.fHandle);
1462a73e4c5SPawel Dziepak 
147*09dbdd36SPawel Dziepak 		Attribute dirAttr[] = { FATTR4_CHANGE };
148*09dbdd36SPawel Dziepak 		if (*change == 0)
149*09dbdd36SPawel Dziepak 			req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute));
150*09dbdd36SPawel Dziepak 
1512a73e4c5SPawel Dziepak 		Attribute attr[] = { FATTR4_FSID, FATTR4_FILEID };
152*09dbdd36SPawel Dziepak 		req.ReadDir(*count, *dirCookie, *dirCookieVerf, attr,
1532a73e4c5SPawel Dziepak 			sizeof(attr) / sizeof(Attribute));
1542a73e4c5SPawel Dziepak 
155*09dbdd36SPawel Dziepak 		req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute));
156*09dbdd36SPawel Dziepak 
1572a73e4c5SPawel Dziepak 		status_t result = request.Send(cookie);
1582a73e4c5SPawel Dziepak 		if (result != B_OK)
1592a73e4c5SPawel Dziepak 			return result;
1602a73e4c5SPawel Dziepak 
1612a73e4c5SPawel Dziepak 		ReplyInterpreter& reply = request.Reply();
1622a73e4c5SPawel Dziepak 
1632a73e4c5SPawel Dziepak 		if (_HandleErrors(reply.NFS4Error(), serv))
1642a73e4c5SPawel Dziepak 			continue;
1652a73e4c5SPawel Dziepak 
1662a73e4c5SPawel Dziepak 		reply.PutFH();
167*09dbdd36SPawel Dziepak 
168*09dbdd36SPawel Dziepak 		AttrValue* before = NULL;
169*09dbdd36SPawel Dziepak 		uint32 attrCount;
170*09dbdd36SPawel Dziepak 		if (*change == 0) {
171*09dbdd36SPawel Dziepak 			result = reply.GetAttr(&before, &attrCount);
172*09dbdd36SPawel Dziepak 			if (result != B_OK)
173*09dbdd36SPawel Dziepak 				return result;
174*09dbdd36SPawel Dziepak 		}
175*09dbdd36SPawel Dziepak 
176*09dbdd36SPawel Dziepak 		result = reply.ReadDir(dirCookie, dirCookieVerf, dirents,
1772a73e4c5SPawel Dziepak 			count, eof);
178*09dbdd36SPawel Dziepak 		if (result != B_OK) {
179*09dbdd36SPawel Dziepak 			delete[] before;
180*09dbdd36SPawel Dziepak 			return result;
181*09dbdd36SPawel Dziepak 		}
182*09dbdd36SPawel Dziepak 
183*09dbdd36SPawel Dziepak 		AttrValue* after;
184*09dbdd36SPawel Dziepak 		result = reply.GetAttr(&after, &attrCount);
185*09dbdd36SPawel Dziepak 		if (result != B_OK) {
186*09dbdd36SPawel Dziepak 			delete[] before;
187*09dbdd36SPawel Dziepak 			return result;
188*09dbdd36SPawel Dziepak 		}
189*09dbdd36SPawel Dziepak 
190*09dbdd36SPawel Dziepak 		if (*change == 0 && before[0].fData.fValue64 == after[0].fData.fValue64
191*09dbdd36SPawel Dziepak 			|| *change == after[0].fData.fValue64)
192*09dbdd36SPawel Dziepak 			*change = after[0].fData.fValue64;
193*09dbdd36SPawel Dziepak 		else
194*09dbdd36SPawel Dziepak 			return B_ERROR;
195*09dbdd36SPawel Dziepak 
196*09dbdd36SPawel Dziepak 		delete[] before;
197*09dbdd36SPawel Dziepak 		delete[] after;
198*09dbdd36SPawel Dziepak 
199*09dbdd36SPawel Dziepak 		return B_OK;
2002a73e4c5SPawel Dziepak 	} while (true);
2012a73e4c5SPawel Dziepak }
2022a73e4c5SPawel Dziepak 
2032a73e4c5SPawel Dziepak 
2042a73e4c5SPawel Dziepak status_t
2052a73e4c5SPawel Dziepak Inode::_FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos,
2062a73e4c5SPawel Dziepak 	uint32 size)
2072a73e4c5SPawel Dziepak {
2082a73e4c5SPawel Dziepak 	uint32 nameSize = strlen(name);
2092a73e4c5SPawel Dziepak 	const uint32 entSize = sizeof(struct dirent);
2102a73e4c5SPawel Dziepak 
2112a73e4c5SPawel Dziepak 	if (pos + entSize + nameSize > size)
2122a73e4c5SPawel Dziepak 		return B_BUFFER_OVERFLOW;
2132a73e4c5SPawel Dziepak 
21400a8558cSPawel Dziepak 	de->d_dev = fFileSystem->DevId();
2152a73e4c5SPawel Dziepak 	de->d_ino = id;
2162a73e4c5SPawel Dziepak 	de->d_reclen = entSize + nameSize;
2172a73e4c5SPawel Dziepak 	if (de->d_reclen % 8 != 0)
2182a73e4c5SPawel Dziepak 		de->d_reclen += 8 - de->d_reclen % 8;
2192a73e4c5SPawel Dziepak 
2202a73e4c5SPawel Dziepak 	strcpy(de->d_name, name);
2212a73e4c5SPawel Dziepak 
2222a73e4c5SPawel Dziepak 	return B_OK;
2232a73e4c5SPawel Dziepak }
2242a73e4c5SPawel Dziepak 
2252a73e4c5SPawel Dziepak 
2262a73e4c5SPawel Dziepak status_t
2272a73e4c5SPawel Dziepak Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
2282a73e4c5SPawel Dziepak {
2292a73e4c5SPawel Dziepak 	do {
23000a8558cSPawel Dziepak 		RPC::Server* serv = fFileSystem->Server();
2312a73e4c5SPawel Dziepak 		Request request(serv);
2322a73e4c5SPawel Dziepak 		RequestBuilder& req = request.Builder();
2332a73e4c5SPawel Dziepak 
234a28e8732SPawel Dziepak 		req.PutFH(fInfo.fHandle);
2352a73e4c5SPawel Dziepak 		req.LookUpUp();
2362a73e4c5SPawel Dziepak 		req.GetFH();
2372a73e4c5SPawel Dziepak 
23800a8558cSPawel Dziepak 		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
2392a73e4c5SPawel Dziepak 			Attribute attr[] = { FATTR4_FILEID };
2402a73e4c5SPawel Dziepak 			req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
2412a73e4c5SPawel Dziepak 		}
2422a73e4c5SPawel Dziepak 
2432a73e4c5SPawel Dziepak 		status_t result = request.Send();
2442a73e4c5SPawel Dziepak 		if (result != B_OK)
2452a73e4c5SPawel Dziepak 			return result;
2462a73e4c5SPawel Dziepak 
2472a73e4c5SPawel Dziepak 		ReplyInterpreter& reply = request.Reply();
2482a73e4c5SPawel Dziepak 
2492a73e4c5SPawel Dziepak 		if (_HandleErrors(reply.NFS4Error(), serv))
2502a73e4c5SPawel Dziepak 			continue;
2512a73e4c5SPawel Dziepak 
2522a73e4c5SPawel Dziepak 		reply.PutFH();
2532a73e4c5SPawel Dziepak 		result = reply.LookUpUp();
2542a73e4c5SPawel Dziepak 		if (result != B_OK)
2552a73e4c5SPawel Dziepak 			return result;
2562a73e4c5SPawel Dziepak 
25700a8558cSPawel Dziepak 		FileHandle fh;
2582a73e4c5SPawel Dziepak 		reply.GetFH(&fh);
2592a73e4c5SPawel Dziepak 
2602a73e4c5SPawel Dziepak 		uint64 fileId;
26100a8558cSPawel Dziepak 		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
2622a73e4c5SPawel Dziepak 			AttrValue* values;
2632a73e4c5SPawel Dziepak 			uint32 count;
2642a73e4c5SPawel Dziepak 			reply.GetAttr(&values, &count);
2652a73e4c5SPawel Dziepak 			if (result != B_OK)
2662a73e4c5SPawel Dziepak 				return result;
2672a73e4c5SPawel Dziepak 
2682a73e4c5SPawel Dziepak 			fileId = values[0].fData.fValue64;
2692a73e4c5SPawel Dziepak 			delete[] values;
2702a73e4c5SPawel Dziepak 		} else
27100a8558cSPawel Dziepak 			fileId = fFileSystem->AllocFileId();
2722a73e4c5SPawel Dziepak 
2732a73e4c5SPawel Dziepak 		return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
2742a73e4c5SPawel Dziepak 	} while (true);
2752a73e4c5SPawel Dziepak }
2762a73e4c5SPawel Dziepak 
277*09dbdd36SPawel Dziepak 
2782a73e4c5SPawel Dziepak status_t
279*09dbdd36SPawel Dziepak Inode::_GetDirSnapshot(DirectoryCacheSnapshot** _snapshot,
280*09dbdd36SPawel Dziepak 	OpenDirCookie* cookie, uint64* _change)
2812a73e4c5SPawel Dziepak {
282*09dbdd36SPawel Dziepak 	DirectoryCacheSnapshot* snapshot = new DirectoryCacheSnapshot;
283*09dbdd36SPawel Dziepak 	if (snapshot == NULL)
284*09dbdd36SPawel Dziepak 		return B_NO_MEMORY;
285*09dbdd36SPawel Dziepak 
286*09dbdd36SPawel Dziepak 	uint64 change = 0;
287*09dbdd36SPawel Dziepak 	uint64 dirCookie = 0;
288*09dbdd36SPawel Dziepak 	uint64 dirCookieVerf = 0;
2892a73e4c5SPawel Dziepak 	bool eof = false;
2902a73e4c5SPawel Dziepak 
291*09dbdd36SPawel Dziepak 	while (!eof) {
292*09dbdd36SPawel Dziepak 		uint32 count;
293*09dbdd36SPawel Dziepak 		DirEntry* dirents;
2942a73e4c5SPawel Dziepak 
295*09dbdd36SPawel Dziepak 		status_t result = _ReadDirOnce(&dirents, &count, cookie, &eof, &change,
296*09dbdd36SPawel Dziepak 			&dirCookie, &dirCookieVerf);
297*09dbdd36SPawel Dziepak 		if (result != B_OK) {
298*09dbdd36SPawel Dziepak 			delete snapshot;
299*09dbdd36SPawel Dziepak 			return result;
300*09dbdd36SPawel Dziepak 		}
301*09dbdd36SPawel Dziepak 
302*09dbdd36SPawel Dziepak 		uint32 i;
303*09dbdd36SPawel Dziepak 		for (i = 0; i < count; i++) {
304*09dbdd36SPawel Dziepak 
305*09dbdd36SPawel Dziepak 			// FATTR4_FSID is mandatory
306*09dbdd36SPawel Dziepak 			void* data = dirents[i].fAttrs[0].fData.fPointer;
307*09dbdd36SPawel Dziepak 			FileSystemId* fsid = reinterpret_cast<FileSystemId*>(data);
308*09dbdd36SPawel Dziepak 			if (*fsid != fFileSystem->FsId())
309*09dbdd36SPawel Dziepak 				continue;
310*09dbdd36SPawel Dziepak 
311*09dbdd36SPawel Dziepak 			ino_t id;
312*09dbdd36SPawel Dziepak 			if (dirents[i].fAttrCount == 2)
313*09dbdd36SPawel Dziepak 				id = _FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64);
314*09dbdd36SPawel Dziepak 			else
315*09dbdd36SPawel Dziepak 				id = _FileIdToInoT(fFileSystem->AllocFileId());
316*09dbdd36SPawel Dziepak 
317*09dbdd36SPawel Dziepak 			NameCacheEntry* entry = new NameCacheEntry(dirents[i].fName, id);
318*09dbdd36SPawel Dziepak 			if (entry == NULL || entry->fName == NULL) {
319*09dbdd36SPawel Dziepak 				if (entry->fName == NULL)
320*09dbdd36SPawel Dziepak 					delete entry;
321*09dbdd36SPawel Dziepak 				delete snapshot;
322*09dbdd36SPawel Dziepak 				delete[] dirents;
323*09dbdd36SPawel Dziepak 				return B_NO_MEMORY;
324*09dbdd36SPawel Dziepak 			}
325*09dbdd36SPawel Dziepak 			snapshot->fEntries.Add(entry);
326*09dbdd36SPawel Dziepak 		}
327*09dbdd36SPawel Dziepak 
328*09dbdd36SPawel Dziepak 		delete[] dirents;
329*09dbdd36SPawel Dziepak 	}
330*09dbdd36SPawel Dziepak 
331*09dbdd36SPawel Dziepak 	*_snapshot = snapshot;
332*09dbdd36SPawel Dziepak 	*_change = change;
333*09dbdd36SPawel Dziepak 
334*09dbdd36SPawel Dziepak 	return B_OK;
335*09dbdd36SPawel Dziepak }
336*09dbdd36SPawel Dziepak 
337*09dbdd36SPawel Dziepak /*
3382a73e4c5SPawel Dziepak 	if (cookie->fCookie == 0 && cookie->fCookieVerf == 2 && count < *_count) {
3392a73e4c5SPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
3402a73e4c5SPawel Dziepak 
341a28e8732SPawel Dziepak 		_FillDirEntry(de, fInfo.fFileId, ".", pos, size);
3422a73e4c5SPawel Dziepak 
3432a73e4c5SPawel Dziepak 		pos += de->d_reclen;
3442a73e4c5SPawel Dziepak 		count++;
3452a73e4c5SPawel Dziepak 		cookie->fCookieVerf--;
3462a73e4c5SPawel Dziepak 	}
3472a73e4c5SPawel Dziepak 
3482a73e4c5SPawel Dziepak 	if (cookie->fCookie == 0 && cookie->fCookieVerf == 1 && count < *_count) {
3492a73e4c5SPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
3502a73e4c5SPawel Dziepak 
351a28e8732SPawel Dziepak 		if (strcmp(fInfo.fName, "/"))
3522a73e4c5SPawel Dziepak 			_ReadDirUp(de, pos, size);
3532a73e4c5SPawel Dziepak 		else
354a28e8732SPawel Dziepak 			_FillDirEntry(de, _FileIdToInoT(fInfo.fFileId), "..", pos, size);
3552a73e4c5SPawel Dziepak 
3562a73e4c5SPawel Dziepak 		pos += de->d_reclen;
3572a73e4c5SPawel Dziepak 		count++;
3582a73e4c5SPawel Dziepak 		cookie->fCookieVerf--;
3592a73e4c5SPawel Dziepak 	}
360*09dbdd36SPawel Dziepak */
3612a73e4c5SPawel Dziepak 
362*09dbdd36SPawel Dziepak status_t
363*09dbdd36SPawel Dziepak Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
364*09dbdd36SPawel Dziepak 	OpenDirCookie* cookie)
365*09dbdd36SPawel Dziepak {
366*09dbdd36SPawel Dziepak 	if (cookie->fEOF) {
367*09dbdd36SPawel Dziepak 		*_count = 0;
368*09dbdd36SPawel Dziepak 		return B_OK;
369*09dbdd36SPawel Dziepak 	}
3702a73e4c5SPawel Dziepak 
371*09dbdd36SPawel Dziepak 	status_t result;
372*09dbdd36SPawel Dziepak 	if (cookie->fSnapshot == NULL) {
373*09dbdd36SPawel Dziepak 		fFileSystem->Revalidator().Lock();
374*09dbdd36SPawel Dziepak 		if (fCache->Lock() != B_OK) {
375*09dbdd36SPawel Dziepak 			fCache->ResetAndLock();
376*09dbdd36SPawel Dziepak 		} else {
377*09dbdd36SPawel Dziepak 			fFileSystem->Revalidator().RemoveDirectory(fCache);
378*09dbdd36SPawel Dziepak 		}
379*09dbdd36SPawel Dziepak 
380*09dbdd36SPawel Dziepak 		cookie->fSnapshot = fCache->GetSnapshot();
381*09dbdd36SPawel Dziepak 		if (cookie->fSnapshot == NULL) {
382*09dbdd36SPawel Dziepak 			uint64 change;
383*09dbdd36SPawel Dziepak 			result = _GetDirSnapshot(&cookie->fSnapshot, cookie, &change);
384*09dbdd36SPawel Dziepak 			if (result != B_OK) {
385*09dbdd36SPawel Dziepak 				fCache->Unlock();
386*09dbdd36SPawel Dziepak 				fFileSystem->Revalidator().Unlock();
3872a73e4c5SPawel Dziepak 				return result;
388*09dbdd36SPawel Dziepak 			}
389*09dbdd36SPawel Dziepak 			fCache->ValidateChangeInfo(change);
390*09dbdd36SPawel Dziepak 			fCache->SetSnapshot(cookie->fSnapshot);
391*09dbdd36SPawel Dziepak 		}
392*09dbdd36SPawel Dziepak 		cookie->fSnapshot->AcquireReference();
393*09dbdd36SPawel Dziepak 		fFileSystem->Revalidator().AddDirectory(fCache);
394*09dbdd36SPawel Dziepak 		fCache->Unlock();
395*09dbdd36SPawel Dziepak 		fFileSystem->Revalidator().Unlock();
396*09dbdd36SPawel Dziepak 	}
3972a73e4c5SPawel Dziepak 
398*09dbdd36SPawel Dziepak 	char* buffer = reinterpret_cast<char*>(_buffer);
399*09dbdd36SPawel Dziepak 	uint32 pos = 0;
400*09dbdd36SPawel Dziepak 
401*09dbdd36SPawel Dziepak 	MutexLocker _(cookie->fSnapshot->fLock);
402*09dbdd36SPawel Dziepak 	uint32 i;
403*09dbdd36SPawel Dziepak 	bool overflow = false;
404*09dbdd36SPawel Dziepak 	for (i = 0; i < *_count; i++) {
4052a73e4c5SPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
4062a73e4c5SPawel Dziepak 
407*09dbdd36SPawel Dziepak 		if (cookie->fCurrent == NULL)
408*09dbdd36SPawel Dziepak 			cookie->fCurrent = cookie->fSnapshot->fEntries.Head();
409*09dbdd36SPawel Dziepak 		else {
410*09dbdd36SPawel Dziepak 			cookie->fCurrent
411*09dbdd36SPawel Dziepak 				= cookie->fSnapshot->fEntries.GetNext(cookie->fCurrent);
412*09dbdd36SPawel Dziepak 		}
4132a73e4c5SPawel Dziepak 
414*09dbdd36SPawel Dziepak 		if (cookie->fCurrent == NULL) {
415*09dbdd36SPawel Dziepak 			cookie->fEOF = true;
416*09dbdd36SPawel Dziepak 			break;
417*09dbdd36SPawel Dziepak 		}
4182a73e4c5SPawel Dziepak 
419*09dbdd36SPawel Dziepak 		if (_FillDirEntry(de, cookie->fCurrent->fNode, cookie->fCurrent->fName,
420*09dbdd36SPawel Dziepak 			pos, size) == B_BUFFER_OVERFLOW) {
4212a73e4c5SPawel Dziepak 			overflow = true;
4222a73e4c5SPawel Dziepak 			break;
4232a73e4c5SPawel Dziepak 		}
4242a73e4c5SPawel Dziepak 
4252a73e4c5SPawel Dziepak 		pos += de->d_reclen;
4262a73e4c5SPawel Dziepak 	}
4272a73e4c5SPawel Dziepak 
428*09dbdd36SPawel Dziepak 	if (i == 0 && overflow)
4292a73e4c5SPawel Dziepak 		return B_BUFFER_OVERFLOW;
4302a73e4c5SPawel Dziepak 
431*09dbdd36SPawel Dziepak 	*_count = i;
4322a73e4c5SPawel Dziepak 
4332a73e4c5SPawel Dziepak 	return B_OK;
4342a73e4c5SPawel Dziepak }
4352a73e4c5SPawel Dziepak 
436