* Copyright 2005, 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
* Stefano Ceccherini
*/
* functionality.
*/
#include <Entry.h>
#include <LocaleRoster.h>
#include <Path.h>
#include <Query.h>
#include <String.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "FilteredQuery.h"
extern const char *__progname;
static const char *kProgramName = __progname;
struct folder_params
{
BPath path;
bool includeSubFolders;
};
static bool
FilterByFolder(const entry_ref *ref, void *arg)
{
folder_params* params = static_cast<folder_params*>(arg);
BPath& wantedPath = params->path;
bool includeSub = params->includeSubFolders;
BPath path(ref);
if (includeSub) {
if (!strncmp(path.Path(), wantedPath.Path(),
strlen(wantedPath.Path())))
return true;
} else {
if (path.GetParent(&path) == B_OK &&
path == wantedPath)
return true;
}
return false;
}
static bool sAllVolumes = false;
static bool sEscapeMetaChars = true;
static bool sFilesOnly = false;
static bool sLocalizedAppNames = false;
static bool sSubFolders = false;
void
usage(void)
{
printf("usage: %s [ -ef ] [ -p <path-to-search> ] [ -s ] [ -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"
" -l\t\tmatch expression with localized application names\n"
" -p <path>\tsearch only in the given path.\n"
" -s\t\tinclude subfolders (only meaningful when used with \"-p\")\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=foo' will find files named \"foo\"\n",
kProgramName, kProgramName);
exit(0);
}
void
perform_query(BVolume &volume, const char *predicate, const char *filterpath)
{
TFilteredQuery query;
query.SetVolume(&volume);
if (sLocalizedAppNames)
query.SetPredicate("BEOS:APP_SIG=*");
else
query.SetPredicate(predicate);
folder_params options;
if (filterpath != NULL && filterpath[0] != '\0') {
options.path = filterpath;
options.includeSubFolders = sSubFolders;
query.AddFilter(FilterByFolder, &options);
}
status_t status = query.Fetch();
if (status == B_BAD_VALUE) {
BString string = "name=";
string << predicate;
query.SetPredicate(string.String());
status = query.Fetch();
}
if (status != B_OK) {
fprintf(stderr, "%s: bad query expression\n", kProgramName);
return;
}
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;
}
BString string;
if (sLocalizedAppNames && predicate != NULL) {
entry_ref ref;
if (entry.GetRef(&ref) != B_OK || BLocaleRoster::Default()
->GetLocalizedFileName(string, ref) != B_OK)
continue;
if (string.IFindFirst(predicate) < 0)
continue;
}
string = path.Path();
if (sEscapeMetaChars)
string.CharacterEscape(" ()?*&\"'[]^\\~|;!<>*$\t", '\\');
printf("%s\n", string.String());
}
}
int
main(int argc, char **argv)
{
if (argc < 2)
usage();
char volumePath[B_FILE_NAME_LENGTH];
strcpy(volumePath, ".");
char directoryPath[B_PATH_NAME_LENGTH] = { '\0' };
int opt;
while ((opt = getopt(argc, argv, "efsalv:p:")) != -1) {
switch(opt) {
case 'e':
sEscapeMetaChars = false;
break;
case 'f':
sFilesOnly = true;
break;
case 's':
sSubFolders = true;
break;
case 'a':
sAllVolumes = true;
break;
case 'l':
sLocalizedAppNames = true;
break;
case 'v':
strlcpy(volumePath, optarg, B_FILE_NAME_LENGTH);
break;
case 'p':
strlcpy(directoryPath, optarg, B_PATH_NAME_LENGTH);
break;
default:
usage();
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
perform_query(volume, argv[optind], directoryPath);
} else {
BVolumeRoster volumeRoster;
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
if (volume.KnowsQuery())
perform_query(volume, argv[optind], directoryPath);
}
}
return 0;
}