117a014aaSJérôme Duval/*
217a014aaSJérôme Duval * Copyright 2003-2006 Haiku Inc.
317a014aaSJérôme Duval * Distributed under the terms of the MIT license
417a014aaSJérôme Duval *
517a014aaSJérôme Duval * Authors:
617a014aaSJérôme Duval *		Scott Dellinger (dellinsd@myrealbox.com)
717a014aaSJérôme Duval *		J��r��me Duval
817a014aaSJérôme Duval */
994e5d19cSPhil Greenway
1094e5d19cSPhil Greenway
1194e5d19cSPhil Greenway#include <fs_info.h>
1294e5d19cSPhil Greenway#include <fs_index.h>
1394e5d19cSPhil Greenway#include <TypeConstants.h>
1494e5d19cSPhil Greenway
15a91b2ce4SAxel Dörfler#include <errno.h>
1694e5d19cSPhil Greenway#include <getopt.h>
1779b25dd7SAxel Dörfler#include <glob.h>
18a91b2ce4SAxel Dörfler#include <stdio.h>
19a91b2ce4SAxel Dörfler#include <stdlib.h>
20a91b2ce4SAxel Dörfler#include <string.h>
21a91b2ce4SAxel Dörfler
2294e5d19cSPhil Greenway
2379b25dd7SAxel Dörflerextern const char *__progname;
2479b25dd7SAxel Dörflerconst char *kProgramName = __progname;
2579b25dd7SAxel Dörfler
2679b25dd7SAxel Dörflerdev_t gCurrentDevice;
2779b25dd7SAxel Dörfler
2894e5d19cSPhil Greenway// The following enum and #define are copied from gnu/sys2.h, because it
2994e5d19cSPhil Greenway// didn't want to compile when including that directly.  Since that file
3094e5d19cSPhil Greenway// is marked as being temporary and getting migrated into system.h,
3194e5d19cSPhil Greenway// assume these'll go away soon.
3294e5d19cSPhil Greenway
3394e5d19cSPhil Greenway/* These enum values cannot possibly conflict with the option values
3494e5d19cSPhil Greenway   ordinarily used by commands, including CHAR_MAX + 1, etc.  Avoid
3594e5d19cSPhil Greenway   CHAR_MIN - 1, as it may equal -1, the getopt end-of-options value.  */
3679b25dd7SAxel Dörflerenum {
3794e5d19cSPhil Greenway  GETOPT_HELP_CHAR = (CHAR_MIN - 2),
3894e5d19cSPhil Greenway  GETOPT_VERSION_CHAR = (CHAR_MIN - 3)
3994e5d19cSPhil Greenway};
4094e5d19cSPhil Greenway
41a91b2ce4SAxel Dörflerstatic struct option const longopts[] = {
4294e5d19cSPhil Greenway	{"volume", required_argument, 0, 'd'},
4394e5d19cSPhil Greenway	{"type", required_argument, 0, 't'},
4479b25dd7SAxel Dörfler	{"pattern", no_argument, 0, 'p'},
4594e5d19cSPhil Greenway	{"verbose", no_argument, 0, 'v'},
4679b25dd7SAxel Dörfler	{"help", no_argument, 0, GETOPT_HELP_CHAR},
4794e5d19cSPhil Greenway	{0, 0, 0, 0}
4894e5d19cSPhil Greenway};
4994e5d19cSPhil Greenway
50a91b2ce4SAxel Dörfler
5179b25dd7SAxel Dörflervoid
5279b25dd7SAxel Dörflerusage(int status)
5394e5d19cSPhil Greenway{
5494e5d19cSPhil Greenway	fprintf (stderr,
5579b25dd7SAxel Dörfler		"Usage: %s [OPTION]... INDEX_NAME\n"
5694e5d19cSPhil Greenway		"\n"
5794e5d19cSPhil Greenway		"Removes the index named INDEX_NAME from a disk volume.  Once this has been\n"
5894e5d19cSPhil Greenway		"done, it will no longer be possible to use the query system to search for\n"
5994e5d19cSPhil Greenway		"files with the INDEX_NAME attribute.\n"
6094e5d19cSPhil Greenway		"\n"
6194e5d19cSPhil Greenway		"  -d, --volume=PATH	a path on the volume from which the index will be\n"
6294e5d19cSPhil Greenway		"                         removed\n"
6394e5d19cSPhil Greenway		"  -h, --help		display this help and exit\n"
6479b25dd7SAxel Dörfler		"  -p, --pattern		INDEX_NAME is a pattern\n"
6579b25dd7SAxel Dörfler		"  -v, --verbose		print information about the index being removed\n"
6694e5d19cSPhil Greenway		"\n"
6794e5d19cSPhil Greenway		"INDEX_NAME is the name of a file attribute.\n"
6894e5d19cSPhil Greenway		"\n"
6979b25dd7SAxel Dörfler		"If no volume is specified, the volume of the current directory is assumed.\n",
7079b25dd7SAxel Dörfler		kProgramName);
7194e5d19cSPhil Greenway
7294e5d19cSPhil Greenway	exit(status);
7394e5d19cSPhil Greenway}
7494e5d19cSPhil Greenway
7517a014aaSJérôme Duval
7617a014aaSJérôme Duvalconst char*
7717a014aaSJérôme Duvallookup_index_type(uint32 device_type)
7894e5d19cSPhil Greenway{
7917a014aaSJérôme Duval	switch (device_type) {
8094e5d19cSPhil Greenway		case B_DOUBLE_TYPE:
8194e5d19cSPhil Greenway		  return "double";
8294e5d19cSPhil Greenway		case B_FLOAT_TYPE:
8394e5d19cSPhil Greenway		  return "float";
8494e5d19cSPhil Greenway		case B_INT64_TYPE:
8594e5d19cSPhil Greenway		  return "llong";
8694e5d19cSPhil Greenway		case B_INT32_TYPE:
8794e5d19cSPhil Greenway		  return "int";
8894e5d19cSPhil Greenway		case B_STRING_TYPE:
8994e5d19cSPhil Greenway		  return "string";
9079b25dd7SAxel Dörfler
9194e5d19cSPhil Greenway		default:
9294e5d19cSPhil Greenway		  return "unknown";
9394e5d19cSPhil Greenway	}
9494e5d19cSPhil Greenway}
9579b25dd7SAxel Dörfler
9679b25dd7SAxel Dörfler
9779b25dd7SAxel Dörflerint
9879b25dd7SAxel Dörflerremove_index(dev_t device, const char* indexName, bool verbose)
9979b25dd7SAxel Dörfler{
10079b25dd7SAxel Dörfler	if (verbose) {
10179b25dd7SAxel Dörfler		// Get the index type
10279b25dd7SAxel Dörfler		index_info info;
10379b25dd7SAxel Dörfler		status_t status = fs_stat_index(device, indexName, &info);
10479b25dd7SAxel Dörfler		if (status != B_OK) {
10579b25dd7SAxel Dörfler			fprintf(stderr, "%s: Can't get type of index %s: %s\n",
10679b25dd7SAxel Dörfler				kProgramName, indexName, strerror(errno));
10779b25dd7SAxel Dörfler			return -1;
10879b25dd7SAxel Dörfler		}
10979b25dd7SAxel Dörfler
11079b25dd7SAxel Dörfler		fprintf(stdout, "Removing index \"%s\" of type %s.\n",
11179b25dd7SAxel Dörfler			indexName, lookup_index_type(info.type));
11279b25dd7SAxel Dörfler	}
11379b25dd7SAxel Dörfler
11479b25dd7SAxel Dörfler	if (fs_remove_index(device, indexName) != 0) {
11579b25dd7SAxel Dörfler		fprintf(stderr, "%s: Cannot remove index %s: %s\n", kProgramName, indexName, strerror(errno));
11679b25dd7SAxel Dörfler		return -1;
11779b25dd7SAxel Dörfler	}
11879b25dd7SAxel Dörfler
11979b25dd7SAxel Dörfler	return 0;
12079b25dd7SAxel Dörfler}
12179b25dd7SAxel Dörfler
12279b25dd7SAxel Dörfler
12379b25dd7SAxel Dörflervoid *
12479b25dd7SAxel Dörfleropen_index_dir(const char* /*path*/)
12579b25dd7SAxel Dörfler{
12679b25dd7SAxel Dörfler	return fs_open_index_dir(gCurrentDevice);
12779b25dd7SAxel Dörfler}
12879b25dd7SAxel Dörfler
12979b25dd7SAxel Dörfler
13079b25dd7SAxel Dörflerint
13179b25dd7SAxel Dörflerstat_index(const char* /*index*/, struct stat* stat)
13279b25dd7SAxel Dörfler{
13379b25dd7SAxel Dörfler	memset(stat, 0, sizeof(struct stat));
13479b25dd7SAxel Dörfler	stat->st_mode = S_IFREG;
13579b25dd7SAxel Dörfler	return 0;
13679b25dd7SAxel Dörfler}
13779b25dd7SAxel Dörfler
13879b25dd7SAxel Dörfler
13979b25dd7SAxel Dörflerint
14079b25dd7SAxel Dörflerremove_indices(dev_t device, const char* indexPattern, bool verbose)
14179b25dd7SAxel Dörfler{
14279b25dd7SAxel Dörfler	glob_t glob;
14379b25dd7SAxel Dörfler	memset(&glob, 0, sizeof(glob_t));
14479b25dd7SAxel Dörfler
14579b25dd7SAxel Dörfler	glob.gl_closedir = (void (*)(void *))fs_close_index_dir;
1466c05095cSIthamar R. Adema	glob.gl_readdir = (dirent *(*)(void *))fs_read_index_dir;
14779b25dd7SAxel Dörfler	glob.gl_opendir = open_index_dir;
14879b25dd7SAxel Dörfler	glob.gl_lstat = stat_index;
14979b25dd7SAxel Dörfler	glob.gl_stat = stat_index;
15079b25dd7SAxel Dörfler
15179b25dd7SAxel Dörfler	// for open_attr_dir():
15279b25dd7SAxel Dörfler	gCurrentDevice = device;
15379b25dd7SAxel Dörfler
15479b25dd7SAxel Dörfler	int result = ::glob(indexPattern, GLOB_ALTDIRFUNC, NULL, &glob);
15579b25dd7SAxel Dörfler	if (result < 0) {
15679b25dd7SAxel Dörfler		errno = B_BAD_VALUE;
15779b25dd7SAxel Dörfler		return -1;
15879b25dd7SAxel Dörfler	}
15979b25dd7SAxel Dörfler
16079b25dd7SAxel Dörfler	bool error = false;
16179b25dd7SAxel Dörfler
16279b25dd7SAxel Dörfler	for (int i = 0; i < glob.gl_pathc; i++) {
16379b25dd7SAxel Dörfler		if (remove_index(device, glob.gl_pathv[i], verbose) != 0)
16479b25dd7SAxel Dörfler			error = true;
16579b25dd7SAxel Dörfler	}
16679b25dd7SAxel Dörfler
16779b25dd7SAxel Dörfler	return error ? -1 : 0;
16879b25dd7SAxel Dörfler}
16979b25dd7SAxel Dörfler
17079b25dd7SAxel Dörfler
17179b25dd7SAxel Dörflerint
17206447030SMichael Lotzmain(int argc, char **argv)
17379b25dd7SAxel Dörfler{
17479b25dd7SAxel Dörfler	bool isPattern = false;
17579b25dd7SAxel Dörfler	bool verbose = false;
17679b25dd7SAxel Dörfler	dev_t device = 0;
17779b25dd7SAxel Dörfler	char *indexName = NULL;
17879b25dd7SAxel Dörfler	char *path = NULL;
17979b25dd7SAxel Dörfler
18079b25dd7SAxel Dörfler	int c;
18179b25dd7SAxel Dörfler	while ((c = getopt_long(argc, argv, "d:ht:pv", longopts, NULL)) != -1) {
18279b25dd7SAxel Dörfler		switch (c) {
18379b25dd7SAxel Dörfler			case 0:
18479b25dd7SAxel Dörfler				break;
18579b25dd7SAxel Dörfler			case 'd':
18679b25dd7SAxel Dörfler				path = optarg;
18779b25dd7SAxel Dörfler			  	break;
18879b25dd7SAxel Dörfler			case GETOPT_HELP_CHAR:
18979b25dd7SAxel Dörfler				usage(0);
19079b25dd7SAxel Dörfler				break;
19179b25dd7SAxel Dörfler			case 'p':
19279b25dd7SAxel Dörfler				isPattern = true;
19379b25dd7SAxel Dörfler				break;
19479b25dd7SAxel Dörfler			case 'v':
19579b25dd7SAxel Dörfler				verbose = true;
19679b25dd7SAxel Dörfler				break;
19779b25dd7SAxel Dörfler			default:
19879b25dd7SAxel Dörfler	  			usage(1);
19979b25dd7SAxel Dörfler		  		break;
20079b25dd7SAxel Dörfler		}
20179b25dd7SAxel Dörfler	}
20279b25dd7SAxel Dörfler
20379b25dd7SAxel Dörfler	// Remove the index from the volume of the current
20479b25dd7SAxel Dörfler	// directory if no volume was specified.
20579b25dd7SAxel Dörfler	if (path == NULL)
20679b25dd7SAxel Dörfler		path = ".";
20779b25dd7SAxel Dörfler
20879b25dd7SAxel Dörfler	device = dev_for_path(path);
20979b25dd7SAxel Dörfler	if (device < 0) {
21079b25dd7SAxel Dörfler		fprintf(stderr, "%s: can't get information about volume %s\n", kProgramName, path);
21179b25dd7SAxel Dörfler		return 1;
21279b25dd7SAxel Dörfler	}
21379b25dd7SAxel Dörfler
21479b25dd7SAxel Dörfler	if (argc - optind == 1) {
21579b25dd7SAxel Dörfler		// last argument
21679b25dd7SAxel Dörfler		indexName = argv[optind];
21779b25dd7SAxel Dörfler	} else
21879b25dd7SAxel Dörfler		usage(1);
21979b25dd7SAxel Dörfler
22079b25dd7SAxel Dörfler	int result;
22179b25dd7SAxel Dörfler	if (isPattern)
22279b25dd7SAxel Dörfler		result = remove_indices(device, indexName, verbose);
22379b25dd7SAxel Dörfler	else
22479b25dd7SAxel Dörfler		result = remove_index(device, indexName, verbose);
22579b25dd7SAxel Dörfler
22679b25dd7SAxel Dörfler	return result == 0 ? 0 : 1;
22779b25dd7SAxel Dörfler}