xref: /haiku/src/bin/rmindex.cpp (revision 1d9d47fc72028bb71b5f232a877231e59cfe2438)
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