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