xref: /haiku/src/bin/mkindex.cpp (revision 0644703068ca08535bb57369fd63f90f1300d5bc)
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 
75 
76 static void
77 usage(int status)
78 {
79 	fprintf(stderr,
80 		"Usage: %s [options] <attribute>\n"
81 		"Creates a new index for the specified attribute.\n"
82 		"\n"
83 		"  -d, --volume=PATH\ta path on the volume to which the index will be added,\n"
84 		"\t\t\tdefaults to current volume.\n"
85 		"  -t, --type=TYPE	the type of the attribute being indexed.  One of \"int\",\n"
86 		"\t\t\t\"llong\", \"string\", \"float\", or \"double\".\n"
87 		"\t\t\tDefaults to \"string\".\n"
88 		"      --copy-from\tpath to volume to copy the indexes from.\n"
89 		"  -v, --verbose\t\tprint information about the index being created\n",
90 		kProgramName);
91 
92 	exit(status);
93 }
94 
95 
96 int
97 main(int argc, char **argv)
98 {
99 	char *indexTypeName = "string";
100 	int indexType = B_STRING_TYPE;
101 	char *indexName = NULL;
102 	bool verbose = false;
103 	dev_t device = -1, copyFromDevice = -1;
104 
105 	int c;
106 	while ((c = getopt_long(argc, argv, "d:ht:v", kLongOptions, NULL)) != -1) {
107 		switch (c) {
108 			case 0:
109 				break;
110 			case 'd':
111 				device = dev_for_path(optarg);
112 				if (device < 0) {
113 					fprintf(stderr, "%s: can't get information about volume: %s\n",
114 						kProgramName, optarg);
115 					return -1;
116 				}
117 				break;
118 			case 'f':
119 				copyFromDevice = dev_for_path(optarg);
120 				if (copyFromDevice < 0) {
121 					fprintf(stderr, "%s: can't get information about volume: %s\n",
122 						kProgramName, optarg);
123 					return -1;
124 				}
125 				break;
126 			case 'h':
127 				usage(0);
128 				break;
129 			case 't':
130 				indexTypeName = optarg;
131 				if (strncmp("int", optarg, 3) == 0)
132 					indexType = B_INT32_TYPE;
133 				else if (strncmp("llong", optarg, 5) == 0)
134 					indexType = B_INT64_TYPE;
135 				else if (strncmp("string", optarg, 6) == 0)
136 					indexType = B_STRING_TYPE;
137 				else if (strncmp("float", optarg, 5) == 0)
138 					indexType = B_FLOAT_TYPE;
139 				else if (strncmp("double", optarg, 6) == 0)
140 					indexType = B_DOUBLE_TYPE;
141 				else
142 					usage(1);
143 				break;
144 			case 'v':
145 				verbose = 1;
146 				break;
147 			default:
148 				usage(1);
149 				break;
150 		}
151 	}
152 
153 	if (device == -1) {
154 		// Create the index on the volume of the current
155 		// directory if no volume was specified.
156 
157 		device = dev_for_path(".");
158 		if (device < 0) {
159 			fprintf(stderr, "%s: can't get information about current volume\n", kProgramName);
160 			return -1;
161 		}
162 	}
163 
164 	if (copyFromDevice != -1) {
165 		copy_indexes(copyFromDevice, device, verbose);
166 		return 0;
167 	}
168 
169 	if (argc - optind == 1) {
170 		// last argument
171 		indexName = argv[optind];
172 	} else
173 		usage(1);
174 
175 	if (verbose) {
176 		/* Get the mount point of the specified volume. */
177 		BVolume volume(device);
178 		BDirectory dir;
179 		volume.GetRootDirectory(&dir);
180 		BPath path(&dir, NULL);
181 
182 		printf("Creating index \"%s\" of type %s on volume mounted at %s.\n",
183 			indexName, indexTypeName, path.Path());
184 	}
185 
186 	if (fs_create_index(device, indexName, indexType, 0) != 0)
187 		fprintf(stderr, "%s: Could not create index: %s\n", kProgramName, strerror(errno));
188 
189 	return 0;
190 }
191