btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / kits / shared / QueryFile.cpp
blob159c4101c676d1198755d09fbf39bc4870f61cad
1 /*
2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
4 */
7 #include <QueryFile.h>
9 #include <fs_attr.h>
10 #include <Volume.h>
11 #include <VolumeRoster.h>
13 #include "tracker/MimeTypes.h"
14 #include "tracker/Utilities.h"
17 // TODO: add write support
18 // TODO: let Tracker use it?
19 // TODO: live query support?
22 const char* kAttrQueryString = "_trk/qrystr";
23 const char* kAttrQueryVolume = "_trk/qryvol1";
26 BQueryFile::BQueryFile(const entry_ref& ref)
28 SetTo(ref);
32 BQueryFile::BQueryFile(const BEntry& entry)
34 SetTo(entry);
38 BQueryFile::BQueryFile(const char* path)
40 SetTo(path);
44 BQueryFile::BQueryFile(BQuery& query)
46 SetTo(query);
50 BQueryFile::~BQueryFile()
55 status_t
56 BQueryFile::InitCheck() const
58 return fStatus;
62 status_t
63 BQueryFile::SetTo(const entry_ref& ref)
65 Unset();
67 BNode node(&ref);
68 fStatus = node.InitCheck();
69 if (fStatus != B_OK)
70 return fStatus;
72 ssize_t bytesRead = node.ReadAttrString(kAttrQueryString, &fPredicate);
73 if (bytesRead < 0)
74 return fStatus = bytesRead;
76 bool searchAllVolumes = true;
77 attr_info info;
78 if (node.GetAttrInfo(kAttrQueryVolume, &info) == B_OK) {
79 void* buffer = malloc(info.size);
80 if (buffer == NULL)
81 return fStatus = B_NO_MEMORY;
83 BMessage message;
84 fStatus = message.Unflatten((const char*)buffer);
85 if (fStatus == B_OK) {
86 for (int32 index = 0; index < 100; index++) {
87 BVolume volume;
88 status_t status = BPrivate::MatchArchivedVolume(&volume,
89 &message, index);
90 if (status == B_OK) {
91 fStatus = AddVolume(volume);
92 if (fStatus != B_OK)
93 break;
95 searchAllVolumes = false;
96 } else if (status != B_DEV_BAD_DRIVE_NUM) {
97 // Volume doesn't seem to be mounted
98 fStatus = status;
99 break;
104 free(buffer);
107 if (searchAllVolumes) {
108 // add all volumes to query
109 BVolumeRoster roster;
110 BVolume volume;
111 while (roster.GetNextVolume(&volume) == B_OK) {
112 if (volume.IsPersistent() && volume.KnowsQuery())
113 AddVolume(volume);
117 return fStatus;
121 status_t
122 BQueryFile::SetTo(const BEntry& entry)
124 entry_ref ref;
125 fStatus = entry.GetRef(&ref);
126 if (fStatus != B_OK)
127 return fStatus;
129 return SetTo(ref);
133 status_t
134 BQueryFile::SetTo(const char* path)
136 entry_ref ref;
137 fStatus = get_ref_for_path(path, &ref);
138 if (fStatus != B_OK)
139 return fStatus;
141 return SetTo(ref);
145 status_t
146 BQueryFile::SetTo(BQuery& query)
148 Unset();
150 BString predicate;
151 query.GetPredicate(&predicate);
153 fStatus = SetPredicate(predicate.String());
154 if (fStatus != B_OK)
155 return fStatus;
157 return fStatus = AddVolume(query.TargetDevice());
161 void
162 BQueryFile::Unset()
164 fStatus = B_NO_INIT;
165 fCurrentVolumeIndex = -1;
166 fVolumes.MakeEmpty();
167 fQuery.Clear();
168 fPredicate = "";
172 status_t
173 BQueryFile::SetPredicate(const char* predicate)
175 fPredicate = predicate;
176 return B_OK;
180 status_t
181 BQueryFile::AddVolume(const BVolume& volume)
183 return fVolumes.AddItem((void*)(addr_t)volume.Device()) ? B_OK : B_NO_MEMORY;
187 status_t
188 BQueryFile::AddVolume(dev_t device)
190 return fVolumes.AddItem((void*)(addr_t)device) ? B_OK : B_NO_MEMORY;
194 const char*
195 BQueryFile::Predicate() const
197 return fPredicate.String();
201 int32
202 BQueryFile::CountVolumes() const
204 return fVolumes.CountItems();
208 dev_t
209 BQueryFile::VolumeAt(int32 index) const
211 if (index < 0 || index >= fVolumes.CountItems())
212 return -1;
214 return (dev_t)(addr_t)fVolumes.ItemAt(index);
218 status_t
219 BQueryFile::WriteTo(const entry_ref& ref)
221 // TODO: implement
222 return B_NOT_SUPPORTED;
226 status_t
227 BQueryFile::WriteTo(const char* path)
229 entry_ref ref;
230 status_t status = get_ref_for_path(path, &ref);
231 if (status != B_OK)
232 return status;
234 return WriteTo(ref);
238 // #pragma mark - BEntryList implementation
241 status_t
242 BQueryFile::GetNextEntry(BEntry* entry, bool traverse)
244 if (fCurrentVolumeIndex == -1) {
245 // Start with first volume
246 fCurrentVolumeIndex = 0;
248 status_t status = _SetQuery(0);
249 if (status != B_OK)
250 return status;
253 status_t status = B_ENTRY_NOT_FOUND;
255 while (fCurrentVolumeIndex < CountVolumes()) {
256 status = fQuery.GetNextEntry(entry, traverse);
257 if (status != B_ENTRY_NOT_FOUND)
258 break;
260 // Continue with next volume, if any
261 status = _SetQuery(++fCurrentVolumeIndex);
264 return status;
268 status_t
269 BQueryFile::GetNextRef(entry_ref* ref)
271 if (fCurrentVolumeIndex == -1) {
272 // Start with first volume
273 fCurrentVolumeIndex = 0;
275 status_t status = _SetQuery(0);
276 if (status != B_OK)
277 return status;
280 status_t status = B_ENTRY_NOT_FOUND;
282 while (fCurrentVolumeIndex < CountVolumes()) {
283 status = fQuery.GetNextRef(ref);
284 if (status != B_ENTRY_NOT_FOUND)
285 break;
287 // Continue with next volume, if any
288 status = _SetQuery(++fCurrentVolumeIndex);
291 return status;
295 int32
296 BQueryFile::GetNextDirents(struct dirent* buffer, size_t length, int32 count)
298 if (fCurrentVolumeIndex == -1) {
299 // Start with first volume
300 fCurrentVolumeIndex = 0;
302 status_t status = _SetQuery(0);
303 if (status != B_OK)
304 return status;
307 status_t status = B_ENTRY_NOT_FOUND;
309 while (fCurrentVolumeIndex < CountVolumes()) {
310 status = fQuery.GetNextDirents(buffer, length, count);
311 if (status != B_ENTRY_NOT_FOUND)
312 break;
314 // Continue with next volume, if any
315 status = _SetQuery(++fCurrentVolumeIndex);
318 return status;
322 status_t
323 BQueryFile::Rewind()
325 fCurrentVolumeIndex = -1;
326 return B_OK;
330 int32
331 BQueryFile::CountEntries()
333 // not supported
334 return -1;
338 /*static*/ const char*
339 BQueryFile::MimeType()
341 return B_QUERY_MIMETYPE;
345 status_t
346 BQueryFile::_SetQuery(int32 index)
348 if (fCurrentVolumeIndex >= CountVolumes())
349 return B_ENTRY_NOT_FOUND;
351 BVolume volume(VolumeAt(fCurrentVolumeIndex));
352 fQuery.Clear();
353 fQuery.SetPredicate(fPredicate.String());
354 fQuery.SetVolume(&volume);
356 return fQuery.Fetch();