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