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 entry; 86 int32 result = GetNextDirents(&entry, sizeof(entry), 1); 87 if (result < 0) 88 return result; 89 if (result == 0) 90 return B_ENTRY_NOT_FOUND; 91 92 ref->device = entry.d_pdev; 93 ref->directory = entry.d_pino; 94 return ref->set_name(entry.d_name); 95 } 96 97 98 int32 99 VirtualDirectoryEntryList::GetNextDirents(struct dirent* buffer, size_t length, 100 int32 count) 101 { 102 if (count > 1) 103 count = 1; 104 105 int32 countRead = fMergedDirectory.GetNextDirents(buffer, length, count); 106 if (countRead != 1) 107 return countRead; 108 109 // deal with directories 110 entry_ref ref; 111 ref.device = buffer->d_pdev; 112 ref.directory = buffer->d_pino; 113 if (ref.set_name(buffer->d_name) == B_OK && BEntry(&ref).IsDirectory()) { 114 if (VirtualDirectoryManager* manager 115 = VirtualDirectoryManager::Instance()) { 116 AutoLocker<VirtualDirectoryManager> managerLocker(manager); 117 manager->TranslateDirectoryEntry(fDefinitionFileRef, buffer); 118 } 119 } 120 121 return countRead; 122 } 123 124 125 status_t 126 VirtualDirectoryEntryList::Rewind() 127 { 128 return fMergedDirectory.Rewind(); 129 } 130 131 132 int32 133 VirtualDirectoryEntryList::CountEntries() 134 { 135 return 0; 136 } 137 138 139 status_t 140 VirtualDirectoryEntryList::_InitMergedDirectory( 141 const BStringList& directoryPaths) 142 { 143 status_t error = fMergedDirectory.Init(); 144 if (error != B_OK) 145 return error; 146 147 int32 count = directoryPaths.CountStrings(); 148 for (int32 i = 0; i < count; i++) 149 fMergedDirectory.AddDirectory(directoryPaths.StringAt(i)); 150 151 return B_OK; 152 } 153 154 } // namespace BPrivate 155