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*6b9a91ebSPawel Dziepak cookie->fSpecial = 0; 12609dbdd36SPawel Dziepak cookie->fSnapshot = NULL; 12709dbdd36SPawel Dziepak cookie->fCurrent = NULL; 12809dbdd36SPawel Dziepak cookie->fEOF = false; 1292a73e4c5SPawel Dziepak 13078fc85a6SPawel Dziepak fFileSystem->Root()->MakeInfoInvalid(); 13178fc85a6SPawel Dziepak 1322a73e4c5SPawel Dziepak return B_OK; 1332a73e4c5SPawel Dziepak } while (true); 1342a73e4c5SPawel Dziepak } 1352a73e4c5SPawel Dziepak 1362a73e4c5SPawel Dziepak 1372a73e4c5SPawel Dziepak status_t 1382a73e4c5SPawel Dziepak Inode::_ReadDirOnce(DirEntry** dirents, uint32* count, OpenDirCookie* cookie, 13909dbdd36SPawel Dziepak bool* eof, uint64* change, uint64* dirCookie, uint64* dirCookieVerf) 1402a73e4c5SPawel Dziepak { 1412a73e4c5SPawel Dziepak do { 14200a8558cSPawel Dziepak RPC::Server* serv = fFileSystem->Server(); 1432a73e4c5SPawel Dziepak Request request(serv); 1442a73e4c5SPawel Dziepak RequestBuilder& req = request.Builder(); 1452a73e4c5SPawel Dziepak 146a28e8732SPawel Dziepak req.PutFH(fInfo.fHandle); 1472a73e4c5SPawel Dziepak 14809dbdd36SPawel Dziepak Attribute dirAttr[] = { FATTR4_CHANGE }; 14909dbdd36SPawel Dziepak if (*change == 0) 15009dbdd36SPawel Dziepak req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute)); 15109dbdd36SPawel Dziepak 1522a73e4c5SPawel Dziepak Attribute attr[] = { FATTR4_FSID, FATTR4_FILEID }; 15309dbdd36SPawel Dziepak req.ReadDir(*count, *dirCookie, *dirCookieVerf, attr, 1542a73e4c5SPawel Dziepak sizeof(attr) / sizeof(Attribute)); 1552a73e4c5SPawel Dziepak 15609dbdd36SPawel Dziepak req.GetAttr(dirAttr, sizeof(dirAttr) / sizeof(Attribute)); 15709dbdd36SPawel Dziepak 1582a73e4c5SPawel Dziepak status_t result = request.Send(cookie); 1592a73e4c5SPawel Dziepak if (result != B_OK) 1602a73e4c5SPawel Dziepak return result; 1612a73e4c5SPawel Dziepak 1622a73e4c5SPawel Dziepak ReplyInterpreter& reply = request.Reply(); 1632a73e4c5SPawel Dziepak 1642a73e4c5SPawel Dziepak if (_HandleErrors(reply.NFS4Error(), serv)) 1652a73e4c5SPawel Dziepak continue; 1662a73e4c5SPawel Dziepak 1672a73e4c5SPawel Dziepak reply.PutFH(); 16809dbdd36SPawel Dziepak 16909dbdd36SPawel Dziepak AttrValue* before = NULL; 17009dbdd36SPawel Dziepak uint32 attrCount; 17109dbdd36SPawel Dziepak if (*change == 0) { 17209dbdd36SPawel Dziepak result = reply.GetAttr(&before, &attrCount); 17309dbdd36SPawel Dziepak if (result != B_OK) 17409dbdd36SPawel Dziepak return result; 17509dbdd36SPawel Dziepak } 17609dbdd36SPawel Dziepak 17709dbdd36SPawel Dziepak result = reply.ReadDir(dirCookie, dirCookieVerf, dirents, 1782a73e4c5SPawel Dziepak count, eof); 17909dbdd36SPawel Dziepak if (result != B_OK) { 18009dbdd36SPawel Dziepak delete[] before; 18109dbdd36SPawel Dziepak return result; 18209dbdd36SPawel Dziepak } 18309dbdd36SPawel Dziepak 18409dbdd36SPawel Dziepak AttrValue* after; 18509dbdd36SPawel Dziepak result = reply.GetAttr(&after, &attrCount); 18609dbdd36SPawel Dziepak if (result != B_OK) { 18709dbdd36SPawel Dziepak delete[] before; 18809dbdd36SPawel Dziepak return result; 18909dbdd36SPawel Dziepak } 19009dbdd36SPawel Dziepak 19109dbdd36SPawel Dziepak if (*change == 0 && before[0].fData.fValue64 == after[0].fData.fValue64 19209dbdd36SPawel Dziepak || *change == after[0].fData.fValue64) 19309dbdd36SPawel Dziepak *change = after[0].fData.fValue64; 19409dbdd36SPawel Dziepak else 19509dbdd36SPawel Dziepak return B_ERROR; 19609dbdd36SPawel Dziepak 19709dbdd36SPawel Dziepak delete[] before; 19809dbdd36SPawel Dziepak delete[] after; 19909dbdd36SPawel Dziepak 20009dbdd36SPawel Dziepak return B_OK; 2012a73e4c5SPawel Dziepak } while (true); 2022a73e4c5SPawel Dziepak } 2032a73e4c5SPawel Dziepak 2042a73e4c5SPawel Dziepak 2052a73e4c5SPawel Dziepak status_t 2062a73e4c5SPawel Dziepak Inode::_FillDirEntry(struct dirent* de, ino_t id, const char* name, uint32 pos, 2072a73e4c5SPawel Dziepak uint32 size) 2082a73e4c5SPawel Dziepak { 2092a73e4c5SPawel Dziepak uint32 nameSize = strlen(name); 2102a73e4c5SPawel Dziepak const uint32 entSize = sizeof(struct dirent); 2112a73e4c5SPawel Dziepak 2122a73e4c5SPawel Dziepak if (pos + entSize + nameSize > size) 2132a73e4c5SPawel Dziepak return B_BUFFER_OVERFLOW; 2142a73e4c5SPawel Dziepak 21500a8558cSPawel Dziepak de->d_dev = fFileSystem->DevId(); 2162a73e4c5SPawel Dziepak de->d_ino = id; 2172a73e4c5SPawel Dziepak de->d_reclen = entSize + nameSize; 2182a73e4c5SPawel Dziepak if (de->d_reclen % 8 != 0) 2192a73e4c5SPawel Dziepak de->d_reclen += 8 - de->d_reclen % 8; 2202a73e4c5SPawel Dziepak 2212a73e4c5SPawel Dziepak strcpy(de->d_name, name); 2222a73e4c5SPawel Dziepak 2232a73e4c5SPawel Dziepak return B_OK; 2242a73e4c5SPawel Dziepak } 2252a73e4c5SPawel Dziepak 2262a73e4c5SPawel Dziepak 2272a73e4c5SPawel Dziepak status_t 2282a73e4c5SPawel Dziepak Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size) 2292a73e4c5SPawel Dziepak { 2302a73e4c5SPawel Dziepak do { 23100a8558cSPawel Dziepak RPC::Server* serv = fFileSystem->Server(); 2322a73e4c5SPawel Dziepak Request request(serv); 2332a73e4c5SPawel Dziepak RequestBuilder& req = request.Builder(); 2342a73e4c5SPawel Dziepak 235a28e8732SPawel Dziepak req.PutFH(fInfo.fHandle); 2362a73e4c5SPawel Dziepak req.LookUpUp(); 2372a73e4c5SPawel Dziepak req.GetFH(); 2382a73e4c5SPawel Dziepak 23900a8558cSPawel Dziepak if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) { 2402a73e4c5SPawel Dziepak Attribute attr[] = { FATTR4_FILEID }; 2412a73e4c5SPawel Dziepak req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); 2422a73e4c5SPawel Dziepak } 2432a73e4c5SPawel Dziepak 2442a73e4c5SPawel Dziepak status_t result = request.Send(); 2452a73e4c5SPawel Dziepak if (result != B_OK) 2462a73e4c5SPawel Dziepak return result; 2472a73e4c5SPawel Dziepak 2482a73e4c5SPawel Dziepak ReplyInterpreter& reply = request.Reply(); 2492a73e4c5SPawel Dziepak 2502a73e4c5SPawel Dziepak if (_HandleErrors(reply.NFS4Error(), serv)) 2512a73e4c5SPawel Dziepak continue; 2522a73e4c5SPawel Dziepak 2532a73e4c5SPawel Dziepak reply.PutFH(); 2542a73e4c5SPawel Dziepak result = reply.LookUpUp(); 2552a73e4c5SPawel Dziepak if (result != B_OK) 2562a73e4c5SPawel Dziepak return result; 2572a73e4c5SPawel Dziepak 25800a8558cSPawel Dziepak FileHandle fh; 2592a73e4c5SPawel Dziepak reply.GetFH(&fh); 2602a73e4c5SPawel Dziepak 2612a73e4c5SPawel Dziepak uint64 fileId; 26200a8558cSPawel Dziepak if (fFileSystem->IsAttrSupported(FATTR4_FILEID)) { 2632a73e4c5SPawel Dziepak AttrValue* values; 2642a73e4c5SPawel Dziepak uint32 count; 2652a73e4c5SPawel Dziepak reply.GetAttr(&values, &count); 2662a73e4c5SPawel Dziepak if (result != B_OK) 2672a73e4c5SPawel Dziepak return result; 2682a73e4c5SPawel Dziepak 2692a73e4c5SPawel Dziepak fileId = values[0].fData.fValue64; 2702a73e4c5SPawel Dziepak delete[] values; 2712a73e4c5SPawel Dziepak } else 27200a8558cSPawel Dziepak fileId = fFileSystem->AllocFileId(); 2732a73e4c5SPawel Dziepak 2742a73e4c5SPawel Dziepak return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size); 2752a73e4c5SPawel Dziepak } while (true); 2762a73e4c5SPawel Dziepak } 2772a73e4c5SPawel Dziepak 27809dbdd36SPawel Dziepak 2792a73e4c5SPawel Dziepak status_t 28009dbdd36SPawel Dziepak Inode::_GetDirSnapshot(DirectoryCacheSnapshot** _snapshot, 28109dbdd36SPawel Dziepak OpenDirCookie* cookie, uint64* _change) 2822a73e4c5SPawel Dziepak { 28309dbdd36SPawel Dziepak DirectoryCacheSnapshot* snapshot = new DirectoryCacheSnapshot; 28409dbdd36SPawel Dziepak if (snapshot == NULL) 28509dbdd36SPawel Dziepak return B_NO_MEMORY; 28609dbdd36SPawel Dziepak 28709dbdd36SPawel Dziepak uint64 change = 0; 28809dbdd36SPawel Dziepak uint64 dirCookie = 0; 28909dbdd36SPawel Dziepak uint64 dirCookieVerf = 0; 2902a73e4c5SPawel Dziepak bool eof = false; 2912a73e4c5SPawel Dziepak 29209dbdd36SPawel Dziepak while (!eof) { 29309dbdd36SPawel Dziepak uint32 count; 29409dbdd36SPawel Dziepak DirEntry* dirents; 2952a73e4c5SPawel Dziepak 29609dbdd36SPawel Dziepak status_t result = _ReadDirOnce(&dirents, &count, cookie, &eof, &change, 29709dbdd36SPawel Dziepak &dirCookie, &dirCookieVerf); 29809dbdd36SPawel Dziepak if (result != B_OK) { 29909dbdd36SPawel Dziepak delete snapshot; 30009dbdd36SPawel Dziepak return result; 30109dbdd36SPawel Dziepak } 30209dbdd36SPawel Dziepak 30309dbdd36SPawel Dziepak uint32 i; 30409dbdd36SPawel Dziepak for (i = 0; i < count; i++) { 30509dbdd36SPawel Dziepak 30609dbdd36SPawel Dziepak // FATTR4_FSID is mandatory 30709dbdd36SPawel Dziepak void* data = dirents[i].fAttrs[0].fData.fPointer; 30809dbdd36SPawel Dziepak FileSystemId* fsid = reinterpret_cast<FileSystemId*>(data); 30909dbdd36SPawel Dziepak if (*fsid != fFileSystem->FsId()) 31009dbdd36SPawel Dziepak continue; 31109dbdd36SPawel Dziepak 31209dbdd36SPawel Dziepak ino_t id; 31309dbdd36SPawel Dziepak if (dirents[i].fAttrCount == 2) 31409dbdd36SPawel Dziepak id = _FileIdToInoT(dirents[i].fAttrs[1].fData.fValue64); 31509dbdd36SPawel Dziepak else 31609dbdd36SPawel Dziepak id = _FileIdToInoT(fFileSystem->AllocFileId()); 31709dbdd36SPawel Dziepak 31809dbdd36SPawel Dziepak NameCacheEntry* entry = new NameCacheEntry(dirents[i].fName, id); 31909dbdd36SPawel Dziepak if (entry == NULL || entry->fName == NULL) { 32009dbdd36SPawel Dziepak if (entry->fName == NULL) 32109dbdd36SPawel Dziepak delete entry; 32209dbdd36SPawel Dziepak delete snapshot; 32309dbdd36SPawel Dziepak delete[] dirents; 32409dbdd36SPawel Dziepak return B_NO_MEMORY; 32509dbdd36SPawel Dziepak } 32609dbdd36SPawel Dziepak snapshot->fEntries.Add(entry); 32709dbdd36SPawel Dziepak } 32809dbdd36SPawel Dziepak 32909dbdd36SPawel Dziepak delete[] dirents; 33009dbdd36SPawel Dziepak } 33109dbdd36SPawel Dziepak 33209dbdd36SPawel Dziepak *_snapshot = snapshot; 33309dbdd36SPawel Dziepak *_change = change; 33409dbdd36SPawel Dziepak 33509dbdd36SPawel Dziepak return B_OK; 33609dbdd36SPawel Dziepak } 33709dbdd36SPawel Dziepak 3382a73e4c5SPawel Dziepak 33909dbdd36SPawel Dziepak status_t 34009dbdd36SPawel Dziepak Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, 34109dbdd36SPawel Dziepak OpenDirCookie* cookie) 34209dbdd36SPawel Dziepak { 34309dbdd36SPawel Dziepak if (cookie->fEOF) { 34409dbdd36SPawel Dziepak *_count = 0; 34509dbdd36SPawel Dziepak return B_OK; 34609dbdd36SPawel Dziepak } 3472a73e4c5SPawel Dziepak 34809dbdd36SPawel Dziepak status_t result; 34909dbdd36SPawel Dziepak if (cookie->fSnapshot == NULL) { 35009dbdd36SPawel Dziepak fFileSystem->Revalidator().Lock(); 35109dbdd36SPawel Dziepak if (fCache->Lock() != B_OK) { 35209dbdd36SPawel Dziepak fCache->ResetAndLock(); 35309dbdd36SPawel Dziepak } else { 35409dbdd36SPawel Dziepak fFileSystem->Revalidator().RemoveDirectory(fCache); 35509dbdd36SPawel Dziepak } 35609dbdd36SPawel Dziepak 35709dbdd36SPawel Dziepak cookie->fSnapshot = fCache->GetSnapshot(); 35809dbdd36SPawel Dziepak if (cookie->fSnapshot == NULL) { 35909dbdd36SPawel Dziepak uint64 change; 36009dbdd36SPawel Dziepak result = _GetDirSnapshot(&cookie->fSnapshot, cookie, &change); 36109dbdd36SPawel Dziepak if (result != B_OK) { 36209dbdd36SPawel Dziepak fCache->Unlock(); 36309dbdd36SPawel Dziepak fFileSystem->Revalidator().Unlock(); 3642a73e4c5SPawel Dziepak return result; 36509dbdd36SPawel Dziepak } 36609dbdd36SPawel Dziepak fCache->ValidateChangeInfo(change); 36709dbdd36SPawel Dziepak fCache->SetSnapshot(cookie->fSnapshot); 36809dbdd36SPawel Dziepak } 36909dbdd36SPawel Dziepak cookie->fSnapshot->AcquireReference(); 37009dbdd36SPawel Dziepak fFileSystem->Revalidator().AddDirectory(fCache); 37109dbdd36SPawel Dziepak fCache->Unlock(); 37209dbdd36SPawel Dziepak fFileSystem->Revalidator().Unlock(); 37309dbdd36SPawel Dziepak } 3742a73e4c5SPawel Dziepak 37509dbdd36SPawel Dziepak char* buffer = reinterpret_cast<char*>(_buffer); 37609dbdd36SPawel Dziepak uint32 pos = 0; 377*6b9a91ebSPawel Dziepak uint32 i = 0; 378*6b9a91ebSPawel Dziepak bool overflow = false; 379*6b9a91ebSPawel Dziepak 380*6b9a91ebSPawel Dziepak if (cookie->fSpecial == 0 && i < *_count) { 381*6b9a91ebSPawel Dziepak struct dirent* de = reinterpret_cast<dirent*>(buffer + pos); 382*6b9a91ebSPawel Dziepak 383*6b9a91ebSPawel Dziepak status_t result; 384*6b9a91ebSPawel Dziepak result = _FillDirEntry(de, fInfo.fFileId, ".", pos, size); 385*6b9a91ebSPawel Dziepak 386*6b9a91ebSPawel Dziepak if (result == B_BUFFER_OVERFLOW) 387*6b9a91ebSPawel Dziepak overflow = true; 388*6b9a91ebSPawel Dziepak else if (result == B_OK) { 389*6b9a91ebSPawel Dziepak pos += de->d_reclen; 390*6b9a91ebSPawel Dziepak i++; 391*6b9a91ebSPawel Dziepak cookie->fSpecial++; 392*6b9a91ebSPawel Dziepak } else 393*6b9a91ebSPawel Dziepak return result; 394*6b9a91ebSPawel Dziepak } 395*6b9a91ebSPawel Dziepak 396*6b9a91ebSPawel Dziepak if (cookie->fSpecial == 1 && i < *_count) { 397*6b9a91ebSPawel Dziepak struct dirent* de = reinterpret_cast<dirent*>(buffer + pos); 398*6b9a91ebSPawel Dziepak 399*6b9a91ebSPawel Dziepak status_t result; 400*6b9a91ebSPawel Dziepak if (strcmp(fInfo.fName, "/")) 401*6b9a91ebSPawel Dziepak result = _ReadDirUp(de, pos, size); 402*6b9a91ebSPawel Dziepak else 403*6b9a91ebSPawel Dziepak result = _FillDirEntry(de, _FileIdToInoT(fInfo.fFileId), "..", pos, size); 404*6b9a91ebSPawel Dziepak 405*6b9a91ebSPawel Dziepak if (result == B_BUFFER_OVERFLOW) 406*6b9a91ebSPawel Dziepak overflow = true; 407*6b9a91ebSPawel Dziepak else if (result == B_OK) { 408*6b9a91ebSPawel Dziepak pos += de->d_reclen; 409*6b9a91ebSPawel Dziepak i++; 410*6b9a91ebSPawel Dziepak cookie->fSpecial++; 411*6b9a91ebSPawel Dziepak } else 412*6b9a91ebSPawel Dziepak return result; 413*6b9a91ebSPawel Dziepak } 41409dbdd36SPawel Dziepak 41509dbdd36SPawel Dziepak MutexLocker _(cookie->fSnapshot->fLock); 416*6b9a91ebSPawel Dziepak for (; !overflow && i < *_count; i++) { 4172a73e4c5SPawel Dziepak struct dirent* de = reinterpret_cast<dirent*>(buffer + pos); 4182a73e4c5SPawel Dziepak 41909dbdd36SPawel Dziepak if (cookie->fCurrent == NULL) 42009dbdd36SPawel Dziepak cookie->fCurrent = cookie->fSnapshot->fEntries.Head(); 42109dbdd36SPawel Dziepak else { 42209dbdd36SPawel Dziepak cookie->fCurrent 42309dbdd36SPawel Dziepak = cookie->fSnapshot->fEntries.GetNext(cookie->fCurrent); 42409dbdd36SPawel Dziepak } 4252a73e4c5SPawel Dziepak 42609dbdd36SPawel Dziepak if (cookie->fCurrent == NULL) { 42709dbdd36SPawel Dziepak cookie->fEOF = true; 42809dbdd36SPawel Dziepak break; 42909dbdd36SPawel Dziepak } 4302a73e4c5SPawel Dziepak 43109dbdd36SPawel Dziepak if (_FillDirEntry(de, cookie->fCurrent->fNode, cookie->fCurrent->fName, 43209dbdd36SPawel Dziepak pos, size) == B_BUFFER_OVERFLOW) { 4332a73e4c5SPawel Dziepak overflow = true; 4342a73e4c5SPawel Dziepak break; 4352a73e4c5SPawel Dziepak } 4362a73e4c5SPawel Dziepak 4372a73e4c5SPawel Dziepak pos += de->d_reclen; 4382a73e4c5SPawel Dziepak } 4392a73e4c5SPawel Dziepak 44009dbdd36SPawel Dziepak if (i == 0 && overflow) 4412a73e4c5SPawel Dziepak return B_BUFFER_OVERFLOW; 4422a73e4c5SPawel Dziepak 44309dbdd36SPawel Dziepak *_count = i; 4442a73e4c5SPawel Dziepak 4452a73e4c5SPawel Dziepak return B_OK; 4462a73e4c5SPawel Dziepak } 4472a73e4c5SPawel Dziepak 448