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