/* * Copyright 2003-2006 Haiku Inc. * Distributed under the terms of the MIT license * * Authors: * Scott Dellinger (dellinsd@myrealbox.com) * Jérôme Duval */ #include #include #include #include #include #include #include #include #include extern const char *__progname; const char *kProgramName = __progname; dev_t gCurrentDevice; // The following enum and #define are copied from gnu/sys2.h, because it // didn't want to compile when including that directly. Since that file // is marked as being temporary and getting migrated into system.h, // assume these'll go away soon. /* These enum values cannot possibly conflict with the option values ordinarily used by commands, including CHAR_MAX + 1, etc. Avoid CHAR_MIN - 1, as it may equal -1, the getopt end-of-options value. */ enum { GETOPT_HELP_CHAR = (CHAR_MIN - 2), GETOPT_VERSION_CHAR = (CHAR_MIN - 3) }; static struct option const longopts[] = { {"volume", required_argument, 0, 'd'}, {"type", required_argument, 0, 't'}, {"pattern", no_argument, 0, 'p'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, GETOPT_HELP_CHAR}, {0, 0, 0, 0} }; void usage(int status) { fprintf (stderr, "Usage: %s [OPTION]... INDEX_NAME\n" "\n" "Removes the index named INDEX_NAME from a disk volume. Once this has been\n" "done, it will no longer be possible to use the query system to search for\n" "files with the INDEX_NAME attribute.\n" "\n" " -d, --volume=PATH a path on the volume from which the index will be\n" " removed\n" " -h, --help display this help and exit\n" " -p, --pattern INDEX_NAME is a pattern\n" " -v, --verbose print information about the index being removed\n" "\n" "INDEX_NAME is the name of a file attribute.\n" "\n" "If no volume is specified, the volume of the current directory is assumed.\n", kProgramName); exit(status); } const char* lookup_index_type(uint32 device_type) { switch (device_type) { case B_DOUBLE_TYPE: return "double"; case B_FLOAT_TYPE: return "float"; case B_INT64_TYPE: return "llong"; case B_INT32_TYPE: return "int"; case B_STRING_TYPE: return "string"; default: return "unknown"; } } int remove_index(dev_t device, const char* indexName, bool verbose) { if (verbose) { // Get the index type index_info info; status_t status = fs_stat_index(device, indexName, &info); if (status != B_OK) { fprintf(stderr, "%s: Can't get type of index %s: %s\n", kProgramName, indexName, strerror(errno)); return -1; } fprintf(stdout, "Removing index \"%s\" of type %s.\n", indexName, lookup_index_type(info.type)); } if (fs_remove_index(device, indexName) != 0) { fprintf(stderr, "%s: Cannot remove index %s: %s\n", kProgramName, indexName, strerror(errno)); return -1; } return 0; } void * open_index_dir(const char* /*path*/) { return fs_open_index_dir(gCurrentDevice); } int stat_index(const char* /*index*/, struct stat* stat) { memset(stat, 0, sizeof(struct stat)); stat->st_mode = S_IFREG; return 0; } int remove_indices(dev_t device, const char* indexPattern, bool verbose) { glob_t glob; memset(&glob, 0, sizeof(glob_t)); glob.gl_closedir = (void (*)(void *))fs_close_index_dir; glob.gl_readdir = (dirent *(*)(void *))fs_read_index_dir; glob.gl_opendir = open_index_dir; glob.gl_lstat = stat_index; glob.gl_stat = stat_index; // for open_attr_dir(): gCurrentDevice = device; int result = ::glob(indexPattern, GLOB_ALTDIRFUNC, NULL, &glob); if (result < 0) { errno = B_BAD_VALUE; return -1; } bool error = false; for (int i = 0; i < glob.gl_pathc; i++) { if (remove_index(device, glob.gl_pathv[i], verbose) != 0) error = true; } return error ? -1 : 0; } int main(int argc, char **argv) { bool isPattern = false; bool verbose = false; dev_t device = 0; char *indexName = NULL; char *path = NULL; int c; while ((c = getopt_long(argc, argv, "d:ht:pv", longopts, NULL)) != -1) { switch (c) { case 0: break; case 'd': path = optarg; break; case GETOPT_HELP_CHAR: usage(0); break; case 'p': isPattern = true; break; case 'v': verbose = true; break; default: usage(1); break; } } // Remove the index from the volume of the current // directory if no volume was specified. if (path == NULL) path = "."; device = dev_for_path(path); if (device < 0) { fprintf(stderr, "%s: can't get information about volume %s\n", kProgramName, path); return 1; } if (argc - optind == 1) { // last argument indexName = argv[optind]; } else usage(1); int result; if (isPattern) result = remove_indices(device, indexName, verbose); else result = remove_index(device, indexName, verbose); return result == 0 ? 0 : 1; }