2 * Copyright 2010, Axel Dörfler, axeld@pinc-software.de.
3 * This file may be used under the terms of the MIT License.
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
)
32 BQueryFile::BQueryFile(const BEntry
& entry
)
38 BQueryFile::BQueryFile(const char* path
)
44 BQueryFile::BQueryFile(BQuery
& query
)
50 BQueryFile::~BQueryFile()
56 BQueryFile::InitCheck() const
63 BQueryFile::SetTo(const entry_ref
& ref
)
68 fStatus
= node
.InitCheck();
72 ssize_t bytesRead
= node
.ReadAttrString(kAttrQueryString
, &fPredicate
);
74 return fStatus
= bytesRead
;
76 bool searchAllVolumes
= true;
78 if (node
.GetAttrInfo(kAttrQueryVolume
, &info
) == B_OK
) {
79 void* buffer
= malloc(info
.size
);
81 return fStatus
= B_NO_MEMORY
;
84 fStatus
= message
.Unflatten((const char*)buffer
);
85 if (fStatus
== B_OK
) {
86 for (int32 index
= 0; index
< 100; index
++) {
88 status_t status
= BPrivate::MatchArchivedVolume(&volume
,
91 fStatus
= AddVolume(volume
);
95 searchAllVolumes
= false;
96 } else if (status
!= B_DEV_BAD_DRIVE_NUM
) {
97 // Volume doesn't seem to be mounted
107 if (searchAllVolumes
) {
108 // add all volumes to query
109 BVolumeRoster roster
;
111 while (roster
.GetNextVolume(&volume
) == B_OK
) {
112 if (volume
.IsPersistent() && volume
.KnowsQuery())
122 BQueryFile::SetTo(const BEntry
& entry
)
125 fStatus
= entry
.GetRef(&ref
);
134 BQueryFile::SetTo(const char* path
)
137 fStatus
= get_ref_for_path(path
, &ref
);
146 BQueryFile::SetTo(BQuery
& query
)
151 query
.GetPredicate(&predicate
);
153 fStatus
= SetPredicate(predicate
.String());
157 return fStatus
= AddVolume(query
.TargetDevice());
165 fCurrentVolumeIndex
= -1;
166 fVolumes
.MakeEmpty();
173 BQueryFile::SetPredicate(const char* predicate
)
175 fPredicate
= predicate
;
181 BQueryFile::AddVolume(const BVolume
& volume
)
183 return fVolumes
.AddItem((void*)(addr_t
)volume
.Device()) ? B_OK
: B_NO_MEMORY
;
188 BQueryFile::AddVolume(dev_t device
)
190 return fVolumes
.AddItem((void*)(addr_t
)device
) ? B_OK
: B_NO_MEMORY
;
195 BQueryFile::Predicate() const
197 return fPredicate
.String();
202 BQueryFile::CountVolumes() const
204 return fVolumes
.CountItems();
209 BQueryFile::VolumeAt(int32 index
) const
211 if (index
< 0 || index
>= fVolumes
.CountItems())
214 return (dev_t
)(addr_t
)fVolumes
.ItemAt(index
);
219 BQueryFile::WriteTo(const entry_ref
& ref
)
222 return B_NOT_SUPPORTED
;
227 BQueryFile::WriteTo(const char* path
)
230 status_t status
= get_ref_for_path(path
, &ref
);
238 // #pragma mark - BEntryList implementation
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);
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
)
260 // Continue with next volume, if any
261 status
= _SetQuery(++fCurrentVolumeIndex
);
269 BQueryFile::GetNextRef(entry_ref
* ref
)
271 if (fCurrentVolumeIndex
== -1) {
272 // Start with first volume
273 fCurrentVolumeIndex
= 0;
275 status_t status
= _SetQuery(0);
280 status_t status
= B_ENTRY_NOT_FOUND
;
282 while (fCurrentVolumeIndex
< CountVolumes()) {
283 status
= fQuery
.GetNextRef(ref
);
284 if (status
!= B_ENTRY_NOT_FOUND
)
287 // Continue with next volume, if any
288 status
= _SetQuery(++fCurrentVolumeIndex
);
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);
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
)
314 // Continue with next volume, if any
315 status
= _SetQuery(++fCurrentVolumeIndex
);
325 fCurrentVolumeIndex
= -1;
331 BQueryFile::CountEntries()
338 /*static*/ const char*
339 BQueryFile::MimeType()
341 return B_QUERY_MIMETYPE
;
346 BQueryFile::_SetQuery(int32 index
)
348 if (fCurrentVolumeIndex
>= CountVolumes())
349 return B_ENTRY_NOT_FOUND
;
351 BVolume
volume(VolumeAt(fCurrentVolumeIndex
));
353 fQuery
.SetPredicate(fPredicate
.String());
354 fQuery
.SetVolume(&volume
);
356 return fQuery
.Fetch();