1 /* 2 * Copyright 2013, Haiku, Inc. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Ingo Weinhold, ingo_weinhold@gmx.de 7 */ 8 9 10 #include "VirtualDirectoryEntryList.h" 11 12 #include <AutoLocker.h> 13 #include <storage_support.h> 14 15 #include "Model.h" 16 #include "VirtualDirectoryManager.h" 17 18 19 namespace BPrivate { 20 21 22 VirtualDirectoryEntryList::VirtualDirectoryEntryList(Model* model) 23 : 24 EntryListBase(), 25 fDefinitionFileRef(), 26 fMergedDirectory(BMergedDirectory::B_ALWAYS_FIRST) 27 { 28 VirtualDirectoryManager* manager = VirtualDirectoryManager::Instance(); 29 if (manager == NULL) { 30 fStatus = B_NO_MEMORY; 31 return; 32 } 33 34 AutoLocker<VirtualDirectoryManager> managerLocker(manager); 35 BStringList directoryPaths; 36 fStatus = manager->ResolveDirectoryPaths(*model->NodeRef(), 37 *model->EntryRef(), directoryPaths, &fDefinitionFileRef); 38 if (fStatus != B_OK) 39 return; 40 41 fStatus = _InitMergedDirectory(directoryPaths); 42 } 43 44 45 VirtualDirectoryEntryList::VirtualDirectoryEntryList( 46 const node_ref& definitionFileRef, const BStringList& directoryPaths) 47 : 48 EntryListBase(), 49 fDefinitionFileRef(definitionFileRef), 50 fMergedDirectory(BMergedDirectory::B_ALWAYS_FIRST) 51 { 52 fStatus = _InitMergedDirectory(directoryPaths); 53 } 54 55 56 VirtualDirectoryEntryList::~VirtualDirectoryEntryList() 57 { 58 } 59 60 61 status_t 62 VirtualDirectoryEntryList::InitCheck() const 63 { 64 return EntryListBase::InitCheck(); 65 } 66 67 68 status_t 69 VirtualDirectoryEntryList::GetNextEntry(BEntry* entry, bool traverse) 70 { 71 entry_ref ref; 72 status_t error = GetNextRef(&ref); 73 if (error != B_OK) 74 return error; 75 76 return entry->SetTo(&ref, traverse); 77 } 78 79 80 status_t 81 VirtualDirectoryEntryList::GetNextRef(entry_ref* ref) 82 { 83 BPrivate::Storage::LongDirEntry entry; 84 int32 result = GetNextDirents(&entry, sizeof(entry), 1); 85 if (result < 0) 86 return result; 87 if (result == 0) 88 return B_ENTRY_NOT_FOUND; 89 90 ref->device = entry.d_pdev; 91 ref->directory = entry.d_pino; 92 return ref->set_name(entry.d_name); 93 } 94 95 96 int32 97 VirtualDirectoryEntryList::GetNextDirents(struct dirent* buffer, size_t length, 98 int32 count) 99 { 100 if (count > 1) 101 count = 1; 102 103 int32 countRead = fMergedDirectory.GetNextDirents(buffer, length, count); 104 if (countRead != 1) 105 return countRead; 106 107 // deal with directories 108 entry_ref ref; 109 ref.device = buffer->d_pdev; 110 ref.directory = buffer->d_pino; 111 if (ref.set_name(buffer->d_name) == B_OK && BEntry(&ref).IsDirectory()) { 112 if (VirtualDirectoryManager* manager 113 = VirtualDirectoryManager::Instance()) { 114 AutoLocker<VirtualDirectoryManager> managerLocker(manager); 115 manager->TranslateDirectoryEntry(fDefinitionFileRef, buffer); 116 } 117 } 118 119 return countRead; 120 } 121 122 123 status_t 124 VirtualDirectoryEntryList::Rewind() 125 { 126 return fMergedDirectory.Rewind(); 127 } 128 129 130 int32 131 VirtualDirectoryEntryList::CountEntries() 132 { 133 return 0; 134 } 135 136 137 status_t 138 VirtualDirectoryEntryList::_InitMergedDirectory( 139 const BStringList& directoryPaths) 140 { 141 status_t error = fMergedDirectory.Init(); 142 if (error != B_OK) 143 return error; 144 145 int32 count = directoryPaths.CountStrings(); 146 for (int32 i = 0; i < count; i++) 147 fMergedDirectory.AddDirectory(directoryPaths.StringAt(i)); 148 149 return B_OK; 150 } 151 152 153 } // namespace BPrivate 154