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