xref: /haiku/src/add-ons/kernel/file_systems/nfs4/InodeDir.cpp (revision 268f99dd7dc4bd7474a8bd2742d3f1ec1de6752a)
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
CreateDir(const char * name,int mode,ino_t * id)21b352cbf6SPawel Dziepak Inode::CreateDir(const char* name, int mode, ino_t* id)
222a73e4c5SPawel Dziepak {
23b352cbf6SPawel Dziepak 	return CreateObject(name, NULL, mode, NF4DIR, id);
242a73e4c5SPawel Dziepak }
252a73e4c5SPawel Dziepak 
262a73e4c5SPawel Dziepak 
272a73e4c5SPawel Dziepak status_t
OpenDir(OpenDirCookie * cookie)282a73e4c5SPawel Dziepak Inode::OpenDir(OpenDirCookie* cookie)
292a73e4c5SPawel Dziepak {
301e67a2cdSPawel Dziepak 	ASSERT(cookie != NULL);
311e67a2cdSPawel Dziepak 
322a73e4c5SPawel Dziepak 	if (fType != NF4DIR)
332a73e4c5SPawel Dziepak 		return B_NOT_A_DIRECTORY;
342a73e4c5SPawel Dziepak 
350dbff361SPawel Dziepak 	status_t result = Access(R_OK);
362a73e4c5SPawel Dziepak 	if (result != B_OK)
372a73e4c5SPawel Dziepak 		return result;
382a73e4c5SPawel Dziepak 
396b9a91ebSPawel Dziepak 	cookie->fSpecial = 0;
4009dbdd36SPawel Dziepak 	cookie->fSnapshot = NULL;
4109dbdd36SPawel Dziepak 	cookie->fCurrent = NULL;
4209dbdd36SPawel Dziepak 	cookie->fEOF = false;
43f7c35cf4SPawel Dziepak 	cookie->fAttrDir = false;
44f7c35cf4SPawel Dziepak 
45f7c35cf4SPawel Dziepak 	return B_OK;
46f7c35cf4SPawel Dziepak }
47f7c35cf4SPawel Dziepak 
48f7c35cf4SPawel Dziepak 
49f7c35cf4SPawel Dziepak status_t
OpenAttrDir(OpenDirCookie * cookie)50f7c35cf4SPawel Dziepak Inode::OpenAttrDir(OpenDirCookie* cookie)
51f7c35cf4SPawel Dziepak {
521e67a2cdSPawel Dziepak 	ASSERT(cookie != NULL);
531e67a2cdSPawel Dziepak 
54f7c35cf4SPawel Dziepak 	cookie->fSpecial = 0;
55f7c35cf4SPawel Dziepak 	cookie->fSnapshot = NULL;
56f7c35cf4SPawel Dziepak 	cookie->fCurrent = NULL;
57f7c35cf4SPawel Dziepak 	cookie->fEOF = false;
58f7c35cf4SPawel Dziepak 	cookie->fAttrDir = true;
59f7c35cf4SPawel Dziepak 
6020d1b02eSPawel Dziepak 	return LoadAttrDirHandle();
6120d1b02eSPawel Dziepak }
6220d1b02eSPawel Dziepak 
6320d1b02eSPawel Dziepak 
6420d1b02eSPawel Dziepak status_t
LoadAttrDirHandle()6520d1b02eSPawel Dziepak Inode::LoadAttrDirHandle()
6620d1b02eSPawel Dziepak {
6770472e11SPawel Dziepak 	if (fInfo.fAttrDir.fSize != 0)
6870472e11SPawel Dziepak 		return B_OK;
69a5ae9b47SPawel Dziepak 
70f7c35cf4SPawel Dziepak 	FileHandle handle;
7170472e11SPawel Dziepak 	status_t result;
72060a4636SPawel Dziepak 
73060a4636SPawel Dziepak 	if (fFileSystem->NamedAttrs()) {
74060a4636SPawel Dziepak 		result = NFS4Inode::OpenAttrDir(&handle);
75060a4636SPawel Dziepak 		if (result == B_OK) {
76060a4636SPawel Dziepak 			fInfo.fAttrDir = handle;
77060a4636SPawel Dziepak 			return B_OK;
78060a4636SPawel Dziepak 		}
79060a4636SPawel Dziepak 
80060a4636SPawel Dziepak 		if (result != B_UNSUPPORTED)
81060a4636SPawel Dziepak 			return result;
82060a4636SPawel Dziepak 
83060a4636SPawel Dziepak 		fFileSystem->SetNamedAttrs(false);
84060a4636SPawel Dziepak 	}
85060a4636SPawel Dziepak 
86060a4636SPawel Dziepak 	if (!fFileSystem->GetConfiguration().fEmulateNamedAttrs)
87060a4636SPawel Dziepak 		return B_UNSUPPORTED;
88060a4636SPawel Dziepak 
8970472e11SPawel Dziepak 	char* attrDir
90da950cb2SPawel Dziepak 		= reinterpret_cast<char*>(malloc(strlen(Name()) + 32));
9170472e11SPawel Dziepak 	if (attrDir == NULL)
9270472e11SPawel Dziepak 		return B_NO_MEMORY;
9370472e11SPawel Dziepak 	strcpy(attrDir, ".");
94da950cb2SPawel Dziepak 	strcat(attrDir, Name());
9570472e11SPawel Dziepak 	strcat(attrDir, "-haiku-attrs");
96f7c35cf4SPawel Dziepak 
9770472e11SPawel Dziepak 	result = NFS4Inode::LookUp(attrDir, NULL, NULL, &handle, true);
9870472e11SPawel Dziepak 	if (result == B_ENTRY_NOT_FOUND) {
9970472e11SPawel Dziepak 		ChangeInfo change;
10070472e11SPawel Dziepak 		struct stat st;
10170472e11SPawel Dziepak 		Stat(&st);
10270472e11SPawel Dziepak 		st.st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
10370472e11SPawel Dziepak 		result = NFS4Inode::CreateObject(attrDir, NULL, st.st_mode, NF4DIR,
10470472e11SPawel Dziepak 			&change, NULL, &handle, true);
10570472e11SPawel Dziepak 	}
10670472e11SPawel Dziepak 
10770472e11SPawel Dziepak 	free(attrDir);
108a5ae9b47SPawel Dziepak 
109f7c35cf4SPawel Dziepak 	if (result != B_OK)
110f7c35cf4SPawel Dziepak 		return result;
111f7c35cf4SPawel Dziepak 
112f7c35cf4SPawel Dziepak 	fInfo.fAttrDir = handle;
1132a73e4c5SPawel Dziepak 	return B_OK;
1142a73e4c5SPawel Dziepak }
1152a73e4c5SPawel Dziepak 
1162a73e4c5SPawel Dziepak 
1172a73e4c5SPawel Dziepak status_t
FillDirEntry(struct dirent * de,ino_t id,const char * name,uint32 pos,uint32 size)1180dbff361SPawel Dziepak Inode::FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos,
1192a73e4c5SPawel Dziepak 	uint32 size)
1202a73e4c5SPawel Dziepak {
1211e67a2cdSPawel Dziepak 	ASSERT(de != NULL);
1221e67a2cdSPawel Dziepak 	ASSERT(name != NULL);
1231e67a2cdSPawel Dziepak 
124eed5b716SPawel Dziepak 	uint32 nameSize = strlen(name) + 1;
125*711e2dc0SAugustin Cavalier 	const uint32 entSize = offsetof(struct dirent, d_name);
1262a73e4c5SPawel Dziepak 
1272a73e4c5SPawel Dziepak 	if (pos + entSize + nameSize > size)
1282a73e4c5SPawel Dziepak 		return B_BUFFER_OVERFLOW;
1292a73e4c5SPawel Dziepak 
13000a8558cSPawel Dziepak 	de->d_dev = fFileSystem->DevId();
1312a73e4c5SPawel Dziepak 	de->d_ino = id;
1322a73e4c5SPawel Dziepak 	de->d_reclen = entSize + nameSize;
1332a73e4c5SPawel Dziepak 	if (de->d_reclen % 8 != 0)
1342a73e4c5SPawel Dziepak 		de->d_reclen += 8 - de->d_reclen % 8;
1352a73e4c5SPawel Dziepak 
1362a73e4c5SPawel Dziepak 	strcpy(de->d_name, name);
1372a73e4c5SPawel Dziepak 
1382a73e4c5SPawel Dziepak 	return B_OK;
1392a73e4c5SPawel Dziepak }
1402a73e4c5SPawel Dziepak 
1412a73e4c5SPawel Dziepak 
1422a73e4c5SPawel Dziepak status_t
ReadDirUp(struct dirent * de,uint32 pos,uint32 size)1430dbff361SPawel Dziepak Inode::ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
1442a73e4c5SPawel Dziepak {
1451e67a2cdSPawel Dziepak 	ASSERT(de != NULL);
1461e67a2cdSPawel Dziepak 
147fa1ca5e2SPawel Dziepak 	uint32 attempt = 0;
1482a73e4c5SPawel Dziepak 	do {
14900a8558cSPawel Dziepak 		RPC::Server* serv = fFileSystem->Server();
150060a4636SPawel Dziepak 		Request request(serv, fFileSystem);
1512a73e4c5SPawel Dziepak 		RequestBuilder& req = request.Builder();
1522a73e4c5SPawel Dziepak 
153a28e8732SPawel Dziepak 		req.PutFH(fInfo.fHandle);
1542a73e4c5SPawel Dziepak 		req.LookUpUp();
1552a73e4c5SPawel Dziepak 		req.GetFH();
1562a73e4c5SPawel Dziepak 
15700a8558cSPawel Dziepak 		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
1582a73e4c5SPawel Dziepak 			Attribute attr[] = { FATTR4_FILEID };
1592a73e4c5SPawel Dziepak 			req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
1602a73e4c5SPawel Dziepak 		}
1612a73e4c5SPawel Dziepak 
1622a73e4c5SPawel Dziepak 		status_t result = request.Send();
1632a73e4c5SPawel Dziepak 		if (result != B_OK)
1642a73e4c5SPawel Dziepak 			return result;
1652a73e4c5SPawel Dziepak 
1662a73e4c5SPawel Dziepak 		ReplyInterpreter& reply = request.Reply();
1672a73e4c5SPawel Dziepak 
168fa1ca5e2SPawel Dziepak 		if (HandleErrors(attempt, reply.NFS4Error(), serv))
1692a73e4c5SPawel Dziepak 			continue;
1702a73e4c5SPawel Dziepak 
1712a73e4c5SPawel Dziepak 		reply.PutFH();
1722a73e4c5SPawel Dziepak 		result = reply.LookUpUp();
1732a73e4c5SPawel Dziepak 		if (result != B_OK)
1742a73e4c5SPawel Dziepak 			return result;
1752a73e4c5SPawel Dziepak 
17600a8558cSPawel Dziepak 		FileHandle fh;
1772a73e4c5SPawel Dziepak 		reply.GetFH(&fh);
1782a73e4c5SPawel Dziepak 
1792a73e4c5SPawel Dziepak 		uint64 fileId;
18000a8558cSPawel Dziepak 		if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) {
1812a73e4c5SPawel Dziepak 			AttrValue* values;
1822a73e4c5SPawel Dziepak 			uint32 count;
183c689b9f5SPawel Dziepak 			result = reply.GetAttr(&values, &count);
1842a73e4c5SPawel Dziepak 			if (result != B_OK)
1852a73e4c5SPawel Dziepak 				return result;
1862a73e4c5SPawel Dziepak 
1872a73e4c5SPawel Dziepak 			fileId = values[0].fData.fValue64;
1882a73e4c5SPawel Dziepak 			delete[] values;
1892a73e4c5SPawel Dziepak 		} else
19000a8558cSPawel Dziepak 			fileId = fFileSystem->AllocFileId();
1912a73e4c5SPawel Dziepak 
1920dbff361SPawel Dziepak 		return FillDirEntry(de, FileIdToInoT(fileId), "..", pos, size);
1932a73e4c5SPawel Dziepak 	} while (true);
1942a73e4c5SPawel Dziepak }
1952a73e4c5SPawel Dziepak 
19609dbdd36SPawel Dziepak 
19770472e11SPawel Dziepak static char*
FileToAttrName(const char * path)19870472e11SPawel Dziepak FileToAttrName(const char* path)
19970472e11SPawel Dziepak {
2001e67a2cdSPawel Dziepak 	ASSERT(path != NULL);
2011e67a2cdSPawel Dziepak 
20270472e11SPawel Dziepak 	char* name = strdup(path);
20370472e11SPawel Dziepak 	if (name == NULL)
20470472e11SPawel Dziepak 		return NULL;
20570472e11SPawel Dziepak 
20670472e11SPawel Dziepak 	char* current = strpbrk(name, "#$");
20770472e11SPawel Dziepak 	while (current != NULL) {
20870472e11SPawel Dziepak 		switch (*current) {
20970472e11SPawel Dziepak 			case '#':
21070472e11SPawel Dziepak 				*current = '/';
21170472e11SPawel Dziepak 				break;
21270472e11SPawel Dziepak 			case '$':
21370472e11SPawel Dziepak 				*current = ':';
21470472e11SPawel Dziepak 				break;
21570472e11SPawel Dziepak 		}
21670472e11SPawel Dziepak 		current = strpbrk(name, "#$");
21770472e11SPawel Dziepak 	}
21870472e11SPawel Dziepak 
21970472e11SPawel Dziepak 	return name;
22070472e11SPawel Dziepak }
22170472e11SPawel Dziepak 
22270472e11SPawel Dziepak 
2232a73e4c5SPawel Dziepak status_t
GetDirSnapshot(DirectoryCacheSnapshot ** _snapshot,OpenDirCookie * cookie,uint64 * _change,bool attribute)2240dbff361SPawel Dziepak Inode::GetDirSnapshot(DirectoryCacheSnapshot** _snapshot,
2252314d073SPawel Dziepak 	OpenDirCookie* cookie, uint64* _change, bool attribute)
2262a73e4c5SPawel Dziepak {
2271e67a2cdSPawel Dziepak 	ASSERT(_snapshot != NULL);
2281e67a2cdSPawel Dziepak 
22909dbdd36SPawel Dziepak 	DirectoryCacheSnapshot* snapshot = new DirectoryCacheSnapshot;
23009dbdd36SPawel Dziepak 	if (snapshot == NULL)
23109dbdd36SPawel Dziepak 		return B_NO_MEMORY;
23209dbdd36SPawel Dziepak 
23309dbdd36SPawel Dziepak 	uint64 change = 0;
23409dbdd36SPawel Dziepak 	uint64 dirCookie = 0;
23509dbdd36SPawel Dziepak 	uint64 dirCookieVerf = 0;
2362a73e4c5SPawel Dziepak 	bool eof = false;
2372a73e4c5SPawel Dziepak 
23809dbdd36SPawel Dziepak 	while (!eof) {
23909dbdd36SPawel Dziepak 		uint32 count;
24009dbdd36SPawel Dziepak 		DirEntry* dirents;
2412a73e4c5SPawel Dziepak 
2420dbff361SPawel Dziepak 		status_t result = ReadDirOnce(&dirents, &count, cookie, &eof, &change,
2432314d073SPawel Dziepak 			&dirCookie, &dirCookieVerf, attribute);
24409dbdd36SPawel Dziepak 		if (result != B_OK) {
24509dbdd36SPawel Dziepak 			delete snapshot;
24609dbdd36SPawel Dziepak 			return result;
24709dbdd36SPawel Dziepak 		}
24809dbdd36SPawel Dziepak 
24909dbdd36SPawel Dziepak 		uint32 i;
25009dbdd36SPawel Dziepak 		for (i = 0; i < count; i++) {
25109dbdd36SPawel Dziepak 
25209dbdd36SPawel Dziepak 			// FATTR4_FSID is mandatory
25309dbdd36SPawel Dziepak 			void* data = dirents[i].fAttrs[0].fData.fPointer;
25409dbdd36SPawel Dziepak 			FileSystemId* fsid = reinterpret_cast<FileSystemId*>(data);
25509dbdd36SPawel Dziepak 			if (*fsid != fFileSystem->FsId())
25609dbdd36SPawel Dziepak 				continue;
25709dbdd36SPawel Dziepak 
25870472e11SPawel Dziepak 			if (strstr(dirents[i].fName, "-haiku-attrs") != NULL)
25970472e11SPawel Dziepak 				continue;
26070472e11SPawel Dziepak 
26109dbdd36SPawel Dziepak 			ino_t id;
2622314d073SPawel Dziepak 			if (!attribute) {
26309dbdd36SPawel Dziepak 				if (dirents[i].fAttrCount == 2)
2640dbff361SPawel Dziepak 					id = FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64);
26509dbdd36SPawel Dziepak 				else
2660dbff361SPawel Dziepak 					id = FileIdToInoT(fFileSystem->AllocFileId());
267f7c35cf4SPawel Dziepak 			} else
268f7c35cf4SPawel Dziepak 				id = 0;
26909dbdd36SPawel Dziepak 
27070472e11SPawel Dziepak 			const char* name = dirents[i].fName;
27170472e11SPawel Dziepak 			if (attribute)
27270472e11SPawel Dziepak 				name = FileToAttrName(name);
27370472e11SPawel Dziepak 			if (name == NULL) {
27470472e11SPawel Dziepak 				delete snapshot;
27570472e11SPawel Dziepak 				delete[] dirents;
27670472e11SPawel Dziepak 				return B_NO_MEMORY;
27770472e11SPawel Dziepak 			}
27870472e11SPawel Dziepak 
27970472e11SPawel Dziepak 			NameCacheEntry* entry = new NameCacheEntry(name, id);
28070472e11SPawel Dziepak 			if (attribute)
28170472e11SPawel Dziepak 				free(const_cast<char*>(name));
28270472e11SPawel Dziepak 
28309dbdd36SPawel Dziepak 			if (entry == NULL || entry->fName == NULL) {
284eed5b716SPawel Dziepak 				if (entry != NULL)
28509dbdd36SPawel Dziepak 					delete entry;
28609dbdd36SPawel Dziepak 				delete snapshot;
28709dbdd36SPawel Dziepak 				delete[] dirents;
28809dbdd36SPawel Dziepak 				return B_NO_MEMORY;
28909dbdd36SPawel Dziepak 			}
29009dbdd36SPawel Dziepak 			snapshot->fEntries.Add(entry);
29109dbdd36SPawel Dziepak 		}
29209dbdd36SPawel Dziepak 
29309dbdd36SPawel Dziepak 		delete[] dirents;
29409dbdd36SPawel Dziepak 	}
29509dbdd36SPawel Dziepak 
29609dbdd36SPawel Dziepak 	*_snapshot = snapshot;
29709dbdd36SPawel Dziepak 	*_change = change;
29809dbdd36SPawel Dziepak 
29909dbdd36SPawel Dziepak 	return B_OK;
30009dbdd36SPawel Dziepak }
30109dbdd36SPawel Dziepak 
3022a73e4c5SPawel Dziepak 
30309dbdd36SPawel Dziepak status_t
ReadDir(void * _buffer,uint32 size,uint32 * _count,OpenDirCookie * cookie)30409dbdd36SPawel Dziepak Inode::ReadDir(void* _buffer, uint32 size, uint32* _count,
30509dbdd36SPawel Dziepak 	OpenDirCookie* cookie)
30609dbdd36SPawel Dziepak {
3071e67a2cdSPawel Dziepak 	ASSERT(_buffer != NULL);
3081e67a2cdSPawel Dziepak 	ASSERT(_count != NULL);
3091e67a2cdSPawel Dziepak 	ASSERT(cookie != NULL);
3101e67a2cdSPawel Dziepak 
31109dbdd36SPawel Dziepak 	if (cookie->fEOF) {
31209dbdd36SPawel Dziepak 		*_count = 0;
31309dbdd36SPawel Dziepak 		return B_OK;
31409dbdd36SPawel Dziepak 	}
3152a73e4c5SPawel Dziepak 
31609dbdd36SPawel Dziepak 	status_t result;
317f7c35cf4SPawel Dziepak 	DirectoryCache* cache = cookie->fAttrDir ? fAttrCache : fCache;
31809dbdd36SPawel Dziepak 	if (cookie->fSnapshot == NULL) {
319cae470f9SPawel Dziepak 		cache->Lock();
3204d120407SPawel Dziepak 		result = cache->Revalidate();
32109dbdd36SPawel Dziepak 		if (result != B_OK) {
322f7c35cf4SPawel Dziepak 			cache->Unlock();
3232a73e4c5SPawel Dziepak 			return result;
32409dbdd36SPawel Dziepak 		}
3254d120407SPawel Dziepak 
32665edbee7SPawel Dziepak 		DirectoryCacheSnapshot* snapshot;
32765edbee7SPawel Dziepak 		result = cache->GetSnapshot(&snapshot);
32865edbee7SPawel Dziepak 		if (result != B_OK) {
32965edbee7SPawel Dziepak 			cache->Unlock();
33065edbee7SPawel Dziepak 			return result;
33165edbee7SPawel Dziepak 		}
3324d120407SPawel Dziepak 
333eed5b716SPawel Dziepak 		cookie->fSnapshot = new DirectoryCacheSnapshot(*snapshot);
334f7c35cf4SPawel Dziepak 		cache->Unlock();
3354d120407SPawel Dziepak 
3364d120407SPawel Dziepak 		if (cookie->fSnapshot == NULL)
3374d120407SPawel Dziepak 			return B_NO_MEMORY;
33809dbdd36SPawel Dziepak 	}
3392a73e4c5SPawel Dziepak 
34009dbdd36SPawel Dziepak 	char* buffer = reinterpret_cast<char*>(_buffer);
34109dbdd36SPawel Dziepak 	uint32 pos = 0;
3426b9a91ebSPawel Dziepak 	uint32 i = 0;
3436b9a91ebSPawel Dziepak 	bool overflow = false;
3446b9a91ebSPawel Dziepak 
345f7c35cf4SPawel Dziepak 	if (cookie->fSpecial == 0 && i < *_count && !cookie->fAttrDir) {
3466b9a91ebSPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
3476b9a91ebSPawel Dziepak 
3486b9a91ebSPawel Dziepak 		status_t result;
3490dbff361SPawel Dziepak 		result = FillDirEntry(de, fInfo.fFileId, ".", pos, size);
3506b9a91ebSPawel Dziepak 
3516b9a91ebSPawel Dziepak 		if (result == B_BUFFER_OVERFLOW)
3526b9a91ebSPawel Dziepak 			overflow = true;
3536b9a91ebSPawel Dziepak 		else if (result == B_OK) {
3546b9a91ebSPawel Dziepak 			pos += de->d_reclen;
3556b9a91ebSPawel Dziepak 			i++;
3566b9a91ebSPawel Dziepak 			cookie->fSpecial++;
3576b9a91ebSPawel Dziepak 		} else
3586b9a91ebSPawel Dziepak 			return result;
3596b9a91ebSPawel Dziepak 	}
3606b9a91ebSPawel Dziepak 
361f7c35cf4SPawel Dziepak 	if (cookie->fSpecial == 1 && i < *_count && !cookie->fAttrDir) {
3626b9a91ebSPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
3636b9a91ebSPawel Dziepak 
3646b9a91ebSPawel Dziepak 		status_t result;
3650dbff361SPawel Dziepak 		result = ReadDirUp(de, pos, size);
3668afd81baSPawel Dziepak 		if (result == B_ENTRY_NOT_FOUND) {
3670dbff361SPawel Dziepak 			result = FillDirEntry(de, FileIdToInoT(fInfo.fFileId), "..", pos,
3680dbff361SPawel Dziepak 				size);
3690dbff361SPawel Dziepak 		}
3706b9a91ebSPawel Dziepak 
3716b9a91ebSPawel Dziepak 		if (result == B_BUFFER_OVERFLOW)
3726b9a91ebSPawel Dziepak 			overflow = true;
3736b9a91ebSPawel Dziepak 		else if (result == B_OK) {
3746b9a91ebSPawel Dziepak 			pos += de->d_reclen;
3756b9a91ebSPawel Dziepak 			i++;
3766b9a91ebSPawel Dziepak 			cookie->fSpecial++;
3776b9a91ebSPawel Dziepak 		} else
3786b9a91ebSPawel Dziepak 			return result;
3796b9a91ebSPawel Dziepak 	}
38009dbdd36SPawel Dziepak 
38109dbdd36SPawel Dziepak 	MutexLocker _(cookie->fSnapshot->fLock);
3826b9a91ebSPawel Dziepak 	for (; !overflow && i < *_count; i++) {
3832a73e4c5SPawel Dziepak 		struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
384eed5b716SPawel Dziepak 		NameCacheEntry* temp = cookie->fCurrent;
3852a73e4c5SPawel Dziepak 
38609dbdd36SPawel Dziepak 		if (cookie->fCurrent == NULL)
38709dbdd36SPawel Dziepak 			cookie->fCurrent = cookie->fSnapshot->fEntries.Head();
38809dbdd36SPawel Dziepak 		else {
38909dbdd36SPawel Dziepak 			cookie->fCurrent
39009dbdd36SPawel Dziepak 				= cookie->fSnapshot->fEntries.GetNext(cookie->fCurrent);
39109dbdd36SPawel Dziepak 		}
3922a73e4c5SPawel Dziepak 
39309dbdd36SPawel Dziepak 		if (cookie->fCurrent == NULL) {
39409dbdd36SPawel Dziepak 			cookie->fEOF = true;
39509dbdd36SPawel Dziepak 			break;
39609dbdd36SPawel Dziepak 		}
3972a73e4c5SPawel Dziepak 
3980dbff361SPawel Dziepak 		if (FillDirEntry(de, cookie->fCurrent->fNode, cookie->fCurrent->fName,
39909dbdd36SPawel Dziepak 			pos, size) == B_BUFFER_OVERFLOW) {
400eed5b716SPawel Dziepak 			cookie->fCurrent = temp;
4012a73e4c5SPawel Dziepak 			overflow = true;
4022a73e4c5SPawel Dziepak 			break;
4032a73e4c5SPawel Dziepak 		}
4042a73e4c5SPawel Dziepak 
4052a73e4c5SPawel Dziepak 		pos += de->d_reclen;
4062a73e4c5SPawel Dziepak 	}
4072a73e4c5SPawel Dziepak 
40809dbdd36SPawel Dziepak 	if (i == 0 && overflow)
4092a73e4c5SPawel Dziepak 		return B_BUFFER_OVERFLOW;
4102a73e4c5SPawel Dziepak 
41109dbdd36SPawel Dziepak 	*_count = i;
4122a73e4c5SPawel Dziepak 
4132a73e4c5SPawel Dziepak 	return B_OK;
4142a73e4c5SPawel Dziepak }
4152a73e4c5SPawel Dziepak 
416