xref: /haiku/src/kits/tracker/VirtualDirectoryEntryList.cpp (revision b617a7b410c05275effb95f4b2f5608359d9b7b9)
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