vfs: check userland buffers before reading them.
[haiku.git] / src / bin / filteredquery / FilteredQuery.cpp
blob2bd17f3cfecad31e76138b518e3aed106b0b3b78
1 #include "FilteredQuery.h"
3 #include <Debug.h>
4 #include <Entry.h>
5 #include <String.h>
6 #include <Volume.h>
8 // Helper function to copy a query.
9 // Used to avoid code duplication in
10 // TFilteredQuery(const BQuery &) and TFilteredQuery(const TFilteredQuery &)
11 static void
12 CopyQuery(const BQuery &query, BQuery *dest)
14 ASSERT(dest);
16 BQuery &nonConst = const_cast<BQuery &>(query);
18 // BQuery doesn't have a copy constructor,
19 // so we have to do the work ourselves...
20 // Copy the predicate
21 BString buffer;
22 nonConst.GetPredicate(&buffer);
23 dest->SetPredicate(buffer.String());
25 // Copy the targetted volume
26 BVolume volume(nonConst.TargetDevice());
27 dest->SetVolume(&volume);
31 TFilteredQuery::TFilteredQuery()
36 TFilteredQuery::TFilteredQuery(const BQuery &query)
38 BQuery()
40 CopyQuery(query, this);
44 TFilteredQuery::TFilteredQuery(const TFilteredQuery &query)
46 BQuery()
48 CopyQuery(query, this);
50 // copy filters
51 fFilters = query.fFilters;
55 TFilteredQuery::~TFilteredQuery()
57 Clear();
61 bool
62 TFilteredQuery::AddFilter(filter_function filter, void *arg)
64 filter_pair *filterPair = new filter_pair(filter, arg);
66 return fFilters.AddItem(filterPair);
70 void
71 TFilteredQuery::RemoveFilter(filter_function function)
73 int32 count = fFilters.CountItems();
74 for (int32 i = 0; i < count; i++) {
75 filter_pair *pair = fFilters.ItemAt(i);
76 if (pair->filter == function) {
77 delete fFilters.RemoveItemAt(i);
78 break;
84 status_t
85 TFilteredQuery::GetNextRef(entry_ref *ref)
87 entry_ref tmpRef;
88 status_t result;
90 int32 filterCount = fFilters.CountItems();
91 while ((result = BQuery::GetNextRef(&tmpRef)) == B_OK) {
92 bool accepted = true;
93 // We have a match, so let the entry_ref go through the filters
94 // and see if it passes all the requirements
95 for (int32 i = 0; i < filterCount; i++) {
96 filter_pair *pair = fFilters.ItemAt(i);
97 filter_function filter = pair->filter;
98 accepted = (*filter)(&tmpRef, pair->args);
99 if (!accepted)
100 break;
103 if (accepted) {
104 // Ok, this entry_ref passed all tests
105 *ref = tmpRef;
106 break;
110 return result;
114 status_t
115 TFilteredQuery::GetNextEntry(BEntry *entry, bool traverse)
117 // This code is almost a full copy/paste from Haiku's
118 // BQuery::GetNextEntry(BEntry *entry, bool traverse)
120 entry_ref ref;
121 status_t error = GetNextRef(&ref);
122 if (error == B_OK)
123 error = entry->SetTo(&ref, traverse);
125 return error;
129 int32
130 TFilteredQuery::GetNextDirents(dirent *buf, size_t length, int32 count)
132 // TODO: Implement ?
133 return 0;
137 status_t
138 TFilteredQuery::Clear()
140 int32 filtersCount = fFilters.CountItems();
141 for (int32 i = 0; i < filtersCount; i++)
142 delete fFilters.RemoveItemAt(i);
144 return BQuery::Clear();