* Copyright 2005-2009, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
* Ficus Kirkpatrick (ficus@ior.com)
* JΓ©rΓ΄me Duval
* Axel DΓΆrfler, axeld@pinc-software.de
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <Application.h>
#include <Entry.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <Query.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <String.h>
#include <ObjectList.h>
static const uint32 kMsgAddQuery = 'adqu';
extern const char *__progname;
static const char *kProgramName = __progname;
static bool sAllVolumes = false;
static bool sEscapeMetaChars = true;
static bool sFilesOnly = false;
class LiveQuery : public BApplication {
public:
LiveQuery();
virtual ~LiveQuery();
virtual void ArgvReceived(int32 argc, char** argv);
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
private:
void _PrintUsage();
void _AddQuery(BVolume& volume,
const char* predicate);
void _PerformQuery(BQuery& query);
BObjectList<BQuery> fQueries;
bool fArgsReceived;
};
LiveQuery::LiveQuery()
:
BApplication("application/x-vnd.test-live-query"),
fQueries(10, true),
fArgsReceived(false)
{
}
LiveQuery::~LiveQuery()
{
}
void
LiveQuery::ArgvReceived(int32 argc, char** argv)
{
fArgsReceived = true;
char volumePath[B_FILE_NAME_LENGTH];
strcpy(volumePath, ".");
int opt;
while ((opt = getopt(argc, argv, "efav:")) != -1) {
switch (opt) {
case 'e':
sEscapeMetaChars = false;
break;
case 'f':
sFilesOnly = true;
break;
case 'a':
sAllVolumes = true;
break;
case 'v':
strncpy(volumePath, optarg, B_FILE_NAME_LENGTH);
break;
default:
_PrintUsage();
break;
}
}
BVolume volume;
if (!sAllVolumes) {
BEntry entry(volumePath);
if (entry.InitCheck() != B_OK) {
fprintf(stderr, "%s: \"%s\" is not a valid file\n", kProgramName,
volumePath);
exit(1);
}
status_t status = entry.GetVolume(&volume);
if (status != B_OK) {
fprintf(stderr, "%s: could not get volume: %s\n", kProgramName,
strerror(status));
exit(1);
}
if (!volume.KnowsQuery()) {
fprintf(stderr, "%s: volume containing %s is not query-enabled\n",
kProgramName, volumePath);
} else
_AddQuery(volume, argv[optind]);
} else {
BVolumeRoster volumeRoster;
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
if (volume.KnowsQuery())
_AddQuery(volume, argv[optind]);
}
}
}
void
LiveQuery::ReadyToRun()
{
if (!fArgsReceived)
_PrintUsage();
}
void
LiveQuery::MessageReceived(BMessage* message)
{
switch (message->what) {
case kMsgAddQuery:
{
int32 device;
const char* predicate;
if (message->FindInt32("volume", &device) != B_OK
|| message->FindString("predicate", &predicate) != B_OK)
break;
BVolume volume(device);
BQuery* query = new BQuery;
query->SetVolume(&volume);
query->SetPredicate(predicate);
query->SetTarget(this);
fQueries.AddItem(query);
_PerformQuery(*query);
break;
}
case B_QUERY_UPDATE:
{
int32 what;
message->FindInt32("opcode", &what);
int32 device;
int64 directory;
int64 node;
const char* name;
message->FindInt32("device", &device);
message->FindInt64("directory", &directory);
message->FindInt64("node", &node);
message->FindString("name", &name);
switch (what) {
case B_ENTRY_CREATED:
{
printf("CREATED %s\n", name);
break;
}
case B_ENTRY_REMOVED:
printf("REMOVED %s\n", name);
break;
}
break;
}
default:
BApplication::MessageReceived(message);
break;
}
}
void
LiveQuery::_PrintUsage()
{
printf("usage: %s [ -ef ] [ -a || -v <path-to-volume> ] expression\n"
" -e\t\tdon't escape meta-characters\n"
" -f\t\tshow only files (ie. no directories or symbolic links)\n"
" -a\t\tperform the query on all volumes\n"
" -v <file>\tperform the query on just one volume; <file> can be any\n"
"\t\tfile on that volume. Defaults to the current volume.\n"
" Hint: '%s name=bar' will find files named \"bar\"\n",
kProgramName, kProgramName);
Quit();
}
void
LiveQuery::_AddQuery(BVolume& volume, const char* predicate)
{
BMessage add(kMsgAddQuery);
add.AddInt32("volume", volume.Device());
add.AddString("predicate", predicate);
PostMessage(&add);
}
void
LiveQuery::_PerformQuery(BQuery& query)
{
status_t status = query.Fetch();
if (status != B_OK) {
fprintf(stderr, "%s: bad query expression\n", kProgramName);
return;
}
int32 count = 0;
BEntry entry;
BPath path;
while (query.GetNextEntry(&entry) == B_OK) {
if (sFilesOnly && !entry.IsFile())
continue;
if (entry.GetPath(&path) != B_OK) {
fprintf(stderr, "%s: could not get path for entry\n", kProgramName);
continue;
}
printf("%s\n", sEscapeMetaChars ? BString().CharacterEscape(
path.Path(), " ()?*&\"'[]^\\~|;!<>*$\t", '\\').String()
: path.Path());
count++;
}
printf("FOUND %ld entries\n", count);
}
int
main(int argc, char** argv)
{
LiveQuery query;
query.Run();
return 0;
}