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