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