1 /* 2 * Copyright 2005, Haiku Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT license. 4 * 5 * Authors: 6 * Ficus Kirkpatrick (ficus@ior.com) 7 * Jérôme Duval 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 /* A shell utility for somewhat emulating the Tracker's "Find By Formula" 12 * functionality. 13 */ 14 15 16 #include <Path.h> 17 #include <Query.h> 18 #include <Entry.h> 19 #include <Volume.h> 20 #include <VolumeRoster.h> 21 #include <String.h> 22 23 #include <stdio.h> 24 #include <string.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 28 29 extern const char *__progname; 30 static const char *kProgramName = __progname; 31 32 // Option variables. 33 static bool sAllVolumes = false; // Query all volumes? 34 static bool sEscapeMetaChars = true; // Escape metacharacters? 35 static bool sFilesOnly = false; // Show only files? 36 37 38 void 39 usage(void) 40 { 41 printf("usage: %s [ -ef ] [ -a || -v <path-to-volume> ] expression\n" 42 " -e\t\tdon't escape meta-characters\n" 43 " -f\t\tshow only files (ie. no directories or symbolic links)\n" 44 " -a\t\tperform the query on all volumes\n" 45 " -v <file>\tperform the query on just one volume; <file> can be any\n" 46 "\t\tfile on that volume. Defaults to the current volume.\n" 47 " Hint: '%s name=foo' will find files named \"foo\"\n", 48 kProgramName, kProgramName); 49 exit(0); 50 } 51 52 53 void 54 perform_query(BVolume &volume, const char *predicate) 55 { 56 BQuery query; 57 58 // Set up the volume and predicate for the query. 59 query.SetVolume(&volume); 60 query.SetPredicate(predicate); 61 62 status_t status = query.Fetch(); 63 if (status == B_BAD_VALUE) { 64 // the "name=" part may be omitted in our arguments 65 BString string = "name="; 66 string << predicate; 67 68 query.SetPredicate(string.String()); 69 status = query.Fetch(); 70 } 71 if (status != B_OK) { 72 fprintf(stderr, "%s: bad query expression\n", kProgramName); 73 return; 74 } 75 76 BEntry entry; 77 BPath path; 78 while (query.GetNextEntry(&entry) == B_OK) { 79 if (sFilesOnly && !entry.IsFile()) 80 continue; 81 82 if (entry.GetPath(&path) < B_OK) { 83 fprintf(stderr, "%s: could not get path for entry\n", kProgramName); 84 continue; 85 } 86 87 printf("%s\n", sEscapeMetaChars ? 88 BString().CharacterEscape(path.Path(), " ()?*&\"'[]^\\~|;!<>*$\t", '\\').String() 89 : path.Path()); 90 } 91 } 92 93 94 int 95 main(int argc, char **argv) 96 { 97 // Make sure we have the minimum number of arguments. 98 if (argc < 2) 99 usage(); 100 101 // Which volume do we make the query on? 102 // Default to the current volume. 103 char volumePath[B_FILE_NAME_LENGTH]; 104 strcpy(volumePath, "."); 105 106 // Parse command-line arguments. 107 int opt; 108 while ((opt = getopt(argc, argv, "efav:")) != -1) { 109 switch(opt) { 110 case 'e': 111 sEscapeMetaChars = false; 112 break; 113 case 'f': 114 sFilesOnly = true; 115 break; 116 case 'a': 117 sAllVolumes = true; 118 break; 119 case 'v': 120 strncpy(volumePath, optarg, B_FILE_NAME_LENGTH); 121 break; 122 123 default: 124 usage(); 125 break; 126 } 127 } 128 129 BVolume volume; 130 131 if (!sAllVolumes) { 132 // Find the volume that the query should be performed on, 133 // and set the query to it. 134 BEntry entry(volumePath); 135 if (entry.InitCheck() != B_OK) { 136 fprintf(stderr, "%s: \"%s\" is not a valid file\n", kProgramName, volumePath); 137 exit(1); 138 } 139 140 status_t status = entry.GetVolume(&volume); 141 if (status != B_OK) { 142 fprintf(stderr, "%s: could not get volume: %s\n", kProgramName, strerror(status)); 143 exit(1); 144 } 145 146 if (!volume.KnowsQuery()) 147 fprintf(stderr, "%s: volume containing %s is not query-enabled\n", kProgramName, volumePath); 148 else 149 perform_query(volume, argv[optind]); 150 } else { 151 // Okay, we want to query all the disks -- so iterate over 152 // them, one by one, running the query. 153 BVolumeRoster volumeRoster; 154 while (volumeRoster.GetNextVolume(&volume) == B_OK) { 155 // We don't print errors here -- this will catch /pipe and 156 // other filesystems we don't care about. 157 if (volume.KnowsQuery()) 158 perform_query(volume, argv[optind]); 159 } 160 } 161 162 return 0; 163 } 164