libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / bin / filteredquery / query.cpp
blob4377c003a808aa076080ae561c15f0c22ae7a185
1 // query.cpp
2 //
3 // A shell utility for somewhat emulating the Tracker's "Find By Formula"
4 // functionality.
5 //
6 // by Ficus Kirkpatrick (ficus@ior.com)
7 //
8 // Modified by Jerome Duval on November 03, 2003
9 //
10 // Filtering capability added by Stefano Ceccherini on January 14, 2005
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <unistd.h>
18 #include <Path.h>
19 #include <Query.h>
20 #include <Entry.h>
21 #include <Volume.h>
22 #include <VolumeRoster.h>
23 #include <SupportDefs.h>
24 #include <String.h>
26 #include "FilteredQuery.h"
28 extern const char *__progname;
30 struct folder_params
32 BPath path;
33 bool includeSubFolders;
37 static bool
38 FilterByFolder(const entry_ref *ref, void *arg)
40 folder_params* params = static_cast<folder_params*>(arg);
41 BPath& wantedPath = params->path;
42 bool includeSub = params->includeSubFolders;
44 BPath path(ref);
45 if (includeSub) {
46 if (!strncmp(path.Path(), wantedPath.Path(),
47 strlen(wantedPath.Path())))
48 return true;
49 } else {
50 if (path.GetParent(&path) == B_OK &&
51 path == wantedPath)
52 return true;
54 return false;
58 // Option variables.
59 bool o_all_volumes = false; // Query all volumes?
60 bool o_escaping = true; // Escape metacharacters?
61 bool o_subfolders = false;
63 void
64 usage(void)
66 printf("usage: %s [ -e ] [ -a || -v <path-to-volume> ] expression\n"
67 " -e\t\tdon't escape meta-characters\n"
68 " -p <path>\tsearch only in the given path\n"
69 " -s\t\tinclude subfolders (valid only if -p is used)\n"
70 " -a\t\tperform the query on all volumes\n"
71 " -v <file>\tperform the query on just one volume; <file> can be any\n"
72 "\t\tfile on that volume. Defaults to the current volume.\n"
73 " Hint: '%s name=foo' will find files named \"foo\"\n",
74 __progname, __progname);
75 exit(0);
79 void
80 perform_query(BVolume &volume, const char *predicate, const char *filterpath)
82 TFilteredQuery query;
84 // Set up the volume and predicate for the query.
85 query.SetVolume(&volume);
86 query.SetPredicate(predicate);
87 if (filterpath != NULL) {
88 folder_params options;
89 options.path = filterpath;
90 options.includeSubFolders = o_subfolders;
91 query.AddFilter(FilterByFolder, &options);
94 status_t status = query.Fetch();
95 if (status == B_BAD_VALUE) {
96 // the "name=" part may be omitted in our arguments
97 BString string = "name=";
98 string << predicate;
100 query.SetPredicate(string.String());
101 status = query.Fetch();
103 if (status != B_OK) {
104 printf("query: bad query expression\n");
105 return;
108 BEntry entry;
109 BPath path;
110 while (query.GetNextEntry(&entry) == B_OK) {
111 if (entry.GetPath(&path) < B_OK) {
112 fprintf(stderr, "%s: could not get path for entry\n", __progname);
113 continue;
116 printf("%s\n", o_escaping ?
117 BString().CharacterEscape(path.Path(), " ()?*&\"'[]^\\~|;!<>*$", '\\').String()
118 : path.Path());
124 main(int32 argc, const char **argv)
126 // Make sure we have the minimum number of arguments.
127 if (argc < 2)
128 usage();
130 // Which volume do we make the query on?
131 // Default to the current volume.
132 char volumePath[B_FILE_NAME_LENGTH];
133 char directoryPath[B_PATH_NAME_LENGTH];
135 strcpy(volumePath, ".");
136 strcpy(directoryPath, ".");
138 // Parse command-line arguments.
139 int opt;
140 while ((opt = getopt(argc, (char **)argv, "eavsd:")) != -1) {
141 switch(opt) {
142 case 'a':
143 o_all_volumes = true;
144 break;
146 case 'e':
147 o_escaping = false;
148 break;
150 case 'v':
151 strncpy(volumePath, optarg, B_FILE_NAME_LENGTH);
152 break;
154 case 'p':
155 strncpy(directoryPath, optarg, B_PATH_NAME_LENGTH);
156 break;
158 case 's':
159 o_subfolders = true;
160 break;
162 default:
163 usage();
164 break;
168 BVolume volume;
170 if (!o_all_volumes) {
171 // Find the volume that the query should be performed on,
172 // and set the query to it.
173 BEntry entry(volumePath);
174 if (entry.InitCheck() != B_OK) {
175 printf("query: %s is not a valid file\n", volumePath);
176 exit(1);
179 status_t status = entry.GetVolume(&volume);
180 if (status != B_OK) {
181 fprintf(stderr, "%s: could not get volume: %s\n", __progname, strerror(status));
182 exit(1);
185 if (!volume.KnowsQuery())
186 printf("query: volume containing %s is not query-enabled\n", volumePath);
187 else
188 perform_query(volume, argv[optind], directoryPath);
189 } else {
190 // Okay, we want to query all the disks -- so iterate over
191 // them, one by one, running the query.
192 BVolumeRoster volumeRoster;
193 while (volumeRoster.GetNextVolume(&volume) == B_OK) {
194 // We don't print errors here -- this will catch /pipe and
195 // other filesystems we don't care about.
196 if (volume.KnowsQuery())
197 perform_query(volume, argv[optind], directoryPath);
201 return 0;