1 /* 2 * Copyright 2003-2006 Haiku Inc. 3 * Distributed under the terms of the MIT license 4 * 5 * Authors: 6 * Scott Dellinger (dellinsd@myrealbox.com) 7 * Jérôme Duval 8 */ 9 10 11 #include <fs_info.h> 12 #include <fs_index.h> 13 #include <TypeConstants.h> 14 15 #include <errno.h> 16 #include <getopt.h> 17 #include <glob.h> 18 #include <stdio.h> 19 #include <stdlib.h> 20 #include <string.h> 21 22 23 extern const char *__progname; 24 const char *kProgramName = __progname; 25 26 dev_t gCurrentDevice; 27 28 // The following enum and #define are copied from gnu/sys2.h, because it 29 // didn't want to compile when including that directly. Since that file 30 // is marked as being temporary and getting migrated into system.h, 31 // assume these'll go away soon. 32 33 /* These enum values cannot possibly conflict with the option values 34 ordinarily used by commands, including CHAR_MAX + 1, etc. Avoid 35 CHAR_MIN - 1, as it may equal -1, the getopt end-of-options value. */ 36 enum { 37 GETOPT_HELP_CHAR = (CHAR_MIN - 2), 38 GETOPT_VERSION_CHAR = (CHAR_MIN - 3) 39 }; 40 41 static struct option const longopts[] = { 42 {"volume", required_argument, 0, 'd'}, 43 {"type", required_argument, 0, 't'}, 44 {"pattern", no_argument, 0, 'p'}, 45 {"verbose", no_argument, 0, 'v'}, 46 {"help", no_argument, 0, GETOPT_HELP_CHAR}, 47 {0, 0, 0, 0} 48 }; 49 50 51 void 52 usage(int status) 53 { 54 fprintf (stderr, 55 "Usage: %s [OPTION]... INDEX_NAME\n" 56 "\n" 57 "Removes the index named INDEX_NAME from a disk volume. Once this has been\n" 58 "done, it will no longer be possible to use the query system to search for\n" 59 "files with the INDEX_NAME attribute.\n" 60 "\n" 61 " -d, --volume=PATH a path on the volume from which the index will be\n" 62 " removed\n" 63 " -h, --help display this help and exit\n" 64 " -p, --pattern INDEX_NAME is a pattern\n" 65 " -v, --verbose print information about the index being removed\n" 66 "\n" 67 "INDEX_NAME is the name of a file attribute.\n" 68 "\n" 69 "If no volume is specified, the volume of the current directory is assumed.\n", 70 kProgramName); 71 72 exit(status); 73 } 74 75 76 const char* 77 lookup_index_type(uint32 device_type) 78 { 79 switch (device_type) { 80 case B_DOUBLE_TYPE: 81 return "double"; 82 case B_FLOAT_TYPE: 83 return "float"; 84 case B_INT64_TYPE: 85 return "llong"; 86 case B_INT32_TYPE: 87 return "int"; 88 case B_STRING_TYPE: 89 return "string"; 90 91 default: 92 return "unknown"; 93 } 94 } 95 96 97 int 98 remove_index(dev_t device, const char* indexName, bool verbose) 99 { 100 if (verbose) { 101 // Get the index type 102 index_info info; 103 status_t status = fs_stat_index(device, indexName, &info); 104 if (status != B_OK) { 105 fprintf(stderr, "%s: Can't get type of index %s: %s\n", 106 kProgramName, indexName, strerror(errno)); 107 return -1; 108 } 109 110 fprintf(stdout, "Removing index \"%s\" of type %s.\n", 111 indexName, lookup_index_type(info.type)); 112 } 113 114 if (fs_remove_index(device, indexName) != 0) { 115 fprintf(stderr, "%s: Cannot remove index %s: %s\n", kProgramName, indexName, strerror(errno)); 116 return -1; 117 } 118 119 return 0; 120 } 121 122 123 void * 124 open_index_dir(const char* /*path*/) 125 { 126 return fs_open_index_dir(gCurrentDevice); 127 } 128 129 130 int 131 stat_index(const char* /*index*/, struct stat* stat) 132 { 133 memset(stat, 0, sizeof(struct stat)); 134 stat->st_mode = S_IFREG; 135 return 0; 136 } 137 138 139 int 140 remove_indices(dev_t device, const char* indexPattern, bool verbose) 141 { 142 glob_t glob; 143 memset(&glob, 0, sizeof(glob_t)); 144 145 glob.gl_closedir = (void (*)(void *))fs_close_index_dir; 146 glob.gl_readdir = (dirent *(*)(void *))fs_read_index_dir; 147 glob.gl_opendir = open_index_dir; 148 glob.gl_lstat = stat_index; 149 glob.gl_stat = stat_index; 150 151 // for open_attr_dir(): 152 gCurrentDevice = device; 153 154 int result = ::glob(indexPattern, GLOB_ALTDIRFUNC, NULL, &glob); 155 if (result < 0) { 156 errno = B_BAD_VALUE; 157 return -1; 158 } 159 160 bool error = false; 161 162 for (int i = 0; i < glob.gl_pathc; i++) { 163 if (remove_index(device, glob.gl_pathv[i], verbose) != 0) 164 error = true; 165 } 166 167 return error ? -1 : 0; 168 } 169 170 171 int 172 main(int32 argc, char **argv) 173 { 174 bool isPattern = false; 175 bool verbose = false; 176 dev_t device = 0; 177 char *indexName = NULL; 178 char *path = NULL; 179 180 int c; 181 while ((c = getopt_long(argc, argv, "d:ht:pv", longopts, NULL)) != -1) { 182 switch (c) { 183 case 0: 184 break; 185 case 'd': 186 path = optarg; 187 break; 188 case GETOPT_HELP_CHAR: 189 usage(0); 190 break; 191 case 'p': 192 isPattern = true; 193 break; 194 case 'v': 195 verbose = true; 196 break; 197 default: 198 usage(1); 199 break; 200 } 201 } 202 203 // Remove the index from the volume of the current 204 // directory if no volume was specified. 205 if (path == NULL) 206 path = "."; 207 208 device = dev_for_path(path); 209 if (device < 0) { 210 fprintf(stderr, "%s: can't get information about volume %s\n", kProgramName, path); 211 return 1; 212 } 213 214 if (argc - optind == 1) { 215 // last argument 216 indexName = argv[optind]; 217 } else 218 usage(1); 219 220 int result; 221 if (isPattern) 222 result = remove_indices(device, indexName, verbose); 223 else 224 result = remove_index(device, indexName, verbose); 225 226 return result == 0 ? 0 : 1; 227 } 228