xref: /haiku/src/bin/mkindex.cpp (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
1 /*
2  * Copyright (c) 2003-2005, Haiku
3  *
4  * This software is part of the Haiku distribution and is covered
5  * by the MIT license.
6  *
7  * Authors:
8  *		Scott Dellinger (dellinsd@myrealbox.com)
9  *		Axel Dörfler, axeld@pinc-software.de.
10  */
11 
12 /**	Description: Adds an index to a volume. */
13 
14 
15 #include <fs_info.h>
16 #include <fs_index.h>
17 #include <TypeConstants.h>
18 #include <Directory.h>
19 #include <Path.h>
20 #include <Volume.h>
21 
22 #include <getopt.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 
28 
29 static struct option const kLongOptions[] = {
30 	{"volume", required_argument, 0, 'd'},
31 	{"type", required_argument, 0, 't'},
32 	{"copy-from", required_argument, 0, 'f'},
33 	{"verbose", no_argument, 0, 'v'},
34 	{"help", no_argument, 0, 'h'},
35 	{NULL}
36 };
37 
38 extern const char *__progname;
39 static const char *kProgramName = __progname;
40 
41 
42 static void
43 copy_indexes(dev_t from, dev_t to, bool verbose)
44 {
45 	DIR *indexes = fs_open_index_dir(from);
46 
47 	if (verbose)
48 		puts("Copying indexes:");
49 
50 	while (dirent *dirent = fs_read_index_dir(indexes)) {
51 		if (!strcmp(dirent->d_name, "name")
52 			|| !strcmp(dirent->d_name, "size")
53 			|| !strcmp(dirent->d_name, "last_modified"))
54 			continue;
55 
56 		index_info info;
57 		if (fs_stat_index(from, dirent->d_name, &info) != 0) {
58 			fprintf(stderr, "%s: Skipped index \"%s\": %s\n",
59 				kProgramName, dirent->d_name, strerror(errno));
60 			continue;
61 		}
62 
63 		if (fs_create_index(to, dirent->d_name, info.type, 0) != 0) {
64 			if (errno == B_BAD_VALUE || errno == B_FILE_EXISTS) {
65 				// B_BAD_VALUE is what BeOS returns here...
66 				continue;
67 			}
68 			fprintf(stderr, "%s: Could not create index \"%s\": %s\n",
69 				kProgramName, dirent->d_name, strerror(errno));
70 		} else if (verbose)
71 			printf("\t%s\n", dirent->d_name);
72 	}
73 
74 	fs_close_index_dir(indexes);
75 }
76 
77 
78 static void
79 usage(int status)
80 {
81 	fprintf(stderr,
82 		"Usage: %s [options] <attribute>\n"
83 		"Creates a new index for the specified attribute.\n"
84 		"\n"
85 		"  -d, --volume=PATH\ta path on the volume to which the index will be added,\n"
86 		"\t\t\tdefaults to current volume.\n"
87 		"  -t, --type=TYPE	the type of the attribute being indexed.  One of \"int\",\n"
88 		"\t\t\t\"llong\", \"string\", \"float\", or \"double\".\n"
89 		"\t\t\tDefaults to \"string\".\n"
90 		"      --copy-from\tpath to volume to copy the indexes from.\n"
91 		"  -v, --verbose\t\tprint information about the index being created\n",
92 		kProgramName);
93 
94 	exit(status);
95 }
96 
97 
98 int
99 main(int argc, char **argv)
100 {
101 	const char *indexTypeName = "string";
102 	int indexType = B_STRING_TYPE;
103 	char *indexName = NULL;
104 	bool verbose = false;
105 	dev_t device = -1, copyFromDevice = -1;
106 
107 	int c;
108 	while ((c = getopt_long(argc, argv, "d:ht:v", kLongOptions, NULL)) != -1) {
109 		switch (c) {
110 			case 0:
111 				break;
112 			case 'd':
113 				device = dev_for_path(optarg);
114 				if (device < 0) {
115 					fprintf(stderr, "%s: can't get information about volume: %s\n",
116 						kProgramName, optarg);
117 					return -1;
118 				}
119 				break;
120 			case 'f':
121 				copyFromDevice = dev_for_path(optarg);
122 				if (copyFromDevice < 0) {
123 					fprintf(stderr, "%s: can't get information about volume: %s\n",
124 						kProgramName, optarg);
125 					return -1;
126 				}
127 				break;
128 			case 'h':
129 				usage(0);
130 				break;
131 			case 't':
132 				indexTypeName = optarg;
133 				if (strncmp("int", optarg, 3) == 0)
134 					indexType = B_INT32_TYPE;
135 				else if (strncmp("llong", optarg, 5) == 0)
136 					indexType = B_INT64_TYPE;
137 				else if (strncmp("string", optarg, 6) == 0)
138 					indexType = B_STRING_TYPE;
139 				else if (strncmp("float", optarg, 5) == 0)
140 					indexType = B_FLOAT_TYPE;
141 				else if (strncmp("double", optarg, 6) == 0)
142 					indexType = B_DOUBLE_TYPE;
143 				else
144 					usage(1);
145 				break;
146 			case 'v':
147 				verbose = 1;
148 				break;
149 			default:
150 				usage(1);
151 				break;
152 		}
153 	}
154 
155 	if (device == -1) {
156 		// Create the index on the volume of the current
157 		// directory if no volume was specified.
158 
159 		device = dev_for_path(".");
160 		if (device < 0) {
161 			fprintf(stderr, "%s: can't get information about current volume\n", kProgramName);
162 			return -1;
163 		}
164 	}
165 
166 	if (copyFromDevice != -1) {
167 		copy_indexes(copyFromDevice, device, verbose);
168 		return 0;
169 	}
170 
171 	if (argc - optind == 1) {
172 		// last argument
173 		indexName = argv[optind];
174 	} else
175 		usage(1);
176 
177 	if (verbose) {
178 		/* Get the mount point of the specified volume. */
179 		BVolume volume(device);
180 		BDirectory dir;
181 		volume.GetRootDirectory(&dir);
182 		BPath path(&dir, NULL);
183 
184 		printf("Creating index \"%s\" of type %s on volume mounted at %s.\n",
185 			indexName, indexTypeName, path.Path());
186 	}
187 
188 	if (fs_create_index(device, indexName, indexType, 0) != 0)
189 		fprintf(stderr, "%s: Could not create index: %s\n", kProgramName, strerror(errno));
190 
191 	return 0;
192 }
193