vfs: check userland buffers before reading them.
[haiku.git] / src / servers / index / IndexServer.cpp
blob73ab2c3e887749496af1038fd062775cbd2de59e
1 /*
2 * Copyright 2010-2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * John Scipione, jscipione@gmail.com
7 * Clemens Zeidler, haiku@clemens-zeidler.de
8 */
11 #include "IndexServer.h"
13 #include <Path.h>
14 #include <String.h>
17 VolumeObserverHandler::VolumeObserverHandler(IndexServer* indexServer)
19 fIndexServer(indexServer)
25 void
26 VolumeObserverHandler::MessageReceived(BMessage* message)
28 if (message->what != B_NODE_MONITOR)
29 return;
31 dev_t device;
32 int32 opcode;
33 message->FindInt32("opcode", &opcode) ;
34 switch (opcode) {
35 case B_DEVICE_MOUNTED :
36 message->FindInt32("new device", &device);
37 fIndexServer->AddVolume(BVolume(device));
38 break ;
40 case B_DEVICE_UNMOUNTED :
41 message->FindInt32("device", &device);
42 fIndexServer->RemoveVolume(BVolume(device));
43 break ;
48 AnalyserMonitorHandler::AnalyserMonitorHandler(IndexServer* indexServer)
50 fIndexServer(indexServer)
56 void
57 AnalyserMonitorHandler::AddOnEnabled(const add_on_entry_info* entryInfo)
59 entry_ref ref;
60 make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node,
61 entryInfo->name, &ref);
62 fIndexServer->RegisterAddOn(ref);
66 void
67 AnalyserMonitorHandler::AddOnDisabled(const add_on_entry_info* entryInfo)
69 entry_ref ref;
70 make_entry_ref(entryInfo->dir_nref.device, entryInfo->dir_nref.node,
71 entryInfo->name, &ref);
72 fIndexServer->UnregisterAddOn(ref);
76 IndexServer::IndexServer()
78 BApplication("application/x-vnd.Haiku-index_server"),
79 fVolumeObserverHandler(this),
80 fAddOnMonitorHandler(this),
81 fPulseRunner(NULL)
83 AddHandler(&fVolumeObserverHandler);
84 AddHandler(&fAddOnMonitorHandler);
88 IndexServer::~IndexServer()
90 for (int i = 0; i < fAddOnList.CountItems(); i++) {
91 IndexServerAddOn* addon = fAddOnList.ItemAt(i);
92 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++)
93 fVolumeWatcherList.ItemAt(i)->RemoveAnalyser(addon->Name());
94 image_id image = addon->ImageId();
95 delete addon;
96 unload_add_on(image);
99 _StopWatchingVolumes();
101 delete fPulseRunner;
103 RemoveHandler(&fVolumeObserverHandler);
104 RemoveHandler(&fAddOnMonitorHandler);
108 void
109 IndexServer::ReadyToRun()
111 _StartWatchingAddOns();
112 _StartWatchingVolumes();
116 void
117 IndexServer::MessageReceived(BMessage *message)
119 BApplication::MessageReceived(message);
123 bool
124 IndexServer::QuitRequested()
126 _StopWatchingVolumes();
127 return BApplication::QuitRequested();
131 void
132 IndexServer::AddVolume(const BVolume& volume)
134 // ignore volumes like / or /dev
135 if (volume.Capacity() == 0)
136 return;
138 // check if volume is already in our list
139 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++) {
140 VolumeWatcher* current = fVolumeWatcherList.ItemAt(i);
141 if (current->Volume() == volume)
142 return;
145 char name[256];
146 volume.GetName(name);
147 STRACE("IndexServer::AddVolume %s\n", name);
149 VolumeWatcher* watcher = new VolumeWatcher(volume);
150 /* if (!watcher->Enabled()) {
151 delete watcher;
152 return;
154 fVolumeWatcherList.AddItem(watcher);
155 _SetupVolumeWatcher(watcher);
156 watcher->StartWatching();
160 void
161 IndexServer::RemoveVolume(const BVolume& volume)
163 VolumeWatcher* watcher = NULL;
164 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++) {
165 VolumeWatcher* current = fVolumeWatcherList.ItemAt(i);
166 if (current->Volume() == volume) {
167 watcher = current;
168 break;
172 if (!watcher)
173 return;
175 watcher->Stop();
176 fVolumeWatcherList.RemoveItem(watcher);
177 watcher->PostMessage(B_QUIT_REQUESTED);
181 void
182 IndexServer::RegisterAddOn(entry_ref ref)
184 STRACE("RegisterAddOn %s\n", ref.name);
186 BPath path(&ref);
187 image_id image = load_add_on(path.Path());
188 if (image < 0)
189 return;
191 create_index_server_addon* createFunc;
193 // Get the instantiation function
194 status_t status = get_image_symbol(image, "instantiate_index_server_addon",
195 B_SYMBOL_TYPE_TEXT, (void**)&createFunc);
196 if (status != B_OK) {
197 unload_add_on(image);
198 return;
201 IndexServerAddOn* addon = createFunc(image, ref.name);
202 if (!addon) {
203 unload_add_on(image);
204 return;
206 if (!fAddOnList.AddItem(addon)) {
207 unload_add_on(image);
208 return;
211 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++) {
212 VolumeWatcher* watcher = fVolumeWatcherList.ItemAt(i);
213 FileAnalyser* analyser = _SetupFileAnalyser(addon, watcher->Volume());
214 if (!analyser)
215 continue;
216 if (!watcher->AddAnalyser(analyser))
217 delete analyser;
223 void
224 IndexServer::UnregisterAddOn(entry_ref ref)
226 IndexServerAddOn* addon = _FindAddon(ref.name);
227 if (!addon)
228 return;
230 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++)
231 fVolumeWatcherList.ItemAt(i)->RemoveAnalyser(addon->Name());
233 fAddOnList.RemoveItem(addon);
234 unload_add_on(addon->ImageId());
235 delete addon;
239 FileAnalyser*
240 IndexServer::CreateFileAnalyser(const BString& name, const BVolume& volume)
242 Lock();
243 IndexServerAddOn* addon = _FindAddon(name);
244 if (!addon) {
245 Unlock();
246 return NULL;
248 FileAnalyser* analyser = addon->CreateFileAnalyser(volume);
249 Unlock();
250 return analyser;
254 void
255 IndexServer::_StartWatchingVolumes()
257 BVolume volume;
258 while (fVolumeRoster.GetNextVolume(&volume) != B_BAD_VALUE)
259 AddVolume(volume);
260 fVolumeRoster.StartWatching(this);
264 void
265 IndexServer::_StopWatchingVolumes()
267 STRACE("_StopWatchingVolumes\n");
269 for (int i = 0; i < fVolumeWatcherList.CountItems(); i++) {
270 VolumeWatcher* watcher = fVolumeWatcherList.ItemAt(i);
271 watcher->Stop();
272 watcher->PostMessage(B_QUIT_REQUESTED);
274 fVolumeWatcherList.MakeEmpty();
278 void
279 IndexServer::_SetupVolumeWatcher(VolumeWatcher* watcher)
281 for (int i = 0; i < fAddOnList.CountItems(); i++) {
282 IndexServerAddOn* addon = fAddOnList.ItemAt(i);
283 FileAnalyser* analyser = _SetupFileAnalyser(addon, watcher->Volume());
284 if (!analyser)
285 continue;
286 if (!watcher->AddAnalyser(analyser))
287 delete analyser;
292 FileAnalyser*
293 IndexServer::_SetupFileAnalyser(IndexServerAddOn* addon, const BVolume& volume)
295 FileAnalyser* analyser = addon->CreateFileAnalyser(volume);
296 if (!analyser)
297 return NULL;
298 AnalyserSettings* settings = new AnalyserSettings(analyser->Name(),
299 analyser->Volume());
300 BReference<AnalyserSettings> settingsRef(settings, true);
301 if (!settings) {
302 delete analyser;
303 return NULL;
305 analyser->SetSettings(settings);
306 return analyser;
310 void
311 IndexServer::_StartWatchingAddOns()
313 AddHandler(&fAddOnMonitorHandler);
315 BMessage pulse(B_PULSE);
316 fPulseRunner = new BMessageRunner(&fAddOnMonitorHandler, &pulse, 1000000LL);
317 // the monitor handler needs a pulse to check if add-ons are ready
319 fAddOnMonitorHandler.AddAddOnDirectories("index_server");
323 IndexServerAddOn*
324 IndexServer::_FindAddon(const BString& name)
326 for (int i = 0; i < fAddOnList.CountItems(); i++) {
327 IndexServerAddOn* current = fAddOnList.ItemAt(i);
328 if (current->Name() == name)
329 return current;
331 return NULL;