1/*
2 * Copyright 2002-2020, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		jonas.sundstrom@kirilla.com
7 *		revol@free.fr
8 *		Axel D��rfler, axeld@pinc-software.de
9 */
10
11
12#include <TypeConstants.h>
13#include <fs_info.h>
14#include <fs_index.h>
15
16#include <stdio.h>
17#include <string.h>
18#include <errno.h>
19
20
21static void
22print_help(void)
23{
24	fprintf (stderr,
25		"Usage: lsindex [--help | -v | --verbose | --mkindex | -l | --long] [volume path]\n"
26		"   -l --long\t outputs long listing\n"
27		"   -v --verbose\t gives index type, dates and owner\n"
28		"      --mkindex\t outputs mkindex commands to recreate all the indices\n"
29		"      --help\t prints out this text\n\n"
30		"   If no volume is specified, the volume of the current directory is assumed.\n");
31}
32
33
34static const char *
35print_index_type(const index_info &info, bool mkindexOutput)
36{
37	static char buffer[30];
38
39	switch (info.type) {
40		case B_INT32_TYPE:
41			return mkindexOutput ? "int" : "Int-32";
42		case B_INT64_TYPE:
43			return mkindexOutput ? "llong" : "Int-64";
44		case B_STRING_TYPE:
45			return mkindexOutput ? "string" : "Text";
46		case B_FLOAT_TYPE:
47			return mkindexOutput ? "float" : "Float";
48		case B_DOUBLE_TYPE:
49			return mkindexOutput ? "double" : "Double";
50
51		default:
52			sprintf(buffer, mkindexOutput
53				 ? "0x%08" B_PRIx32
54				 : "Unknown type (0x%" B_PRIx32 ")",
55					info.type);
56			return buffer;
57	}
58}
59
60
61static const char *
62type_string(type_code type)
63{
64	// all types from <TypeConstants.h> listed for completeness,
65	// even though they don't all apply to attribute indices
66
67#define RETURN_TYPE(x) case x: return #x
68
69	switch (type) {
70		RETURN_TYPE(B_ANY_TYPE);
71		RETURN_TYPE(B_BOOL_TYPE);
72		RETURN_TYPE(B_CHAR_TYPE);
73		RETURN_TYPE(B_COLOR_8_BIT_TYPE);
74		RETURN_TYPE(B_DOUBLE_TYPE);
75		RETURN_TYPE(B_FLOAT_TYPE);
76		RETURN_TYPE(B_GRAYSCALE_8_BIT_TYPE);
77		RETURN_TYPE(B_INT64_TYPE);
78		RETURN_TYPE(B_INT32_TYPE);
79		RETURN_TYPE(B_INT16_TYPE);
80		RETURN_TYPE(B_INT8_TYPE);
81		RETURN_TYPE(B_MESSAGE_TYPE);
82		RETURN_TYPE(B_MESSENGER_TYPE);
83		RETURN_TYPE(B_MIME_TYPE);
84		RETURN_TYPE(B_MONOCHROME_1_BIT_TYPE);
85		RETURN_TYPE(B_OBJECT_TYPE);
86		RETURN_TYPE(B_OFF_T_TYPE);
87		RETURN_TYPE(B_PATTERN_TYPE);
88		RETURN_TYPE(B_POINTER_TYPE);
89		RETURN_TYPE(B_POINT_TYPE);
90		RETURN_TYPE(B_RAW_TYPE);
91		RETURN_TYPE(B_RECT_TYPE);
92		RETURN_TYPE(B_REF_TYPE);
93		RETURN_TYPE(B_RGB_32_BIT_TYPE);
94		RETURN_TYPE(B_RGB_COLOR_TYPE);
95		RETURN_TYPE(B_SIZE_T_TYPE);
96		RETURN_TYPE(B_SSIZE_T_TYPE);
97		RETURN_TYPE(B_STRING_TYPE);
98		RETURN_TYPE(B_TIME_TYPE);
99		RETURN_TYPE(B_UINT64_TYPE);
100		RETURN_TYPE(B_UINT32_TYPE);
101		RETURN_TYPE(B_UINT16_TYPE);
102		RETURN_TYPE(B_UINT8_TYPE);
103		RETURN_TYPE(B_MEDIA_PARAMETER_TYPE);
104		RETURN_TYPE(B_MEDIA_PARAMETER_WEB_TYPE);
105		RETURN_TYPE(B_MEDIA_PARAMETER_GROUP_TYPE);
106		RETURN_TYPE(B_ASCII_TYPE);
107
108		default:
109			return NULL;
110	}
111#undef RETURN_TYPE
112}
113
114
115static void
116print_index_long_stat(const index_info &info, char *name)
117{
118	char modified[30];
119	strftime(modified, 30, "%m/%d/%Y %I:%M %p",
120		localtime(&info.modification_time));
121	printf("%16s  %s  %8" B_PRIdOFF " %s\n",
122		print_index_type(info, false), modified, info.size, name);
123}
124
125
126static void
127print_index_verbose_stat(const index_info &info, char *name)
128{
129	printf("%-18s\t", name);
130
131	// Type
132	const char *typeString = type_string(info.type);
133	if (typeString != NULL)
134		printf("%-10s\t", typeString);
135	else
136		printf("%" B_PRIu32 "\t", info.type);
137
138	// Size
139	printf("%10" B_PRIdOFF "  ", info.size);
140
141	// Created
142	char string[30];
143	strftime(string, sizeof(string), "%Y-%m-%d %H:%M",
144		localtime(&info.creation_time));
145	printf("%s  ", string);
146
147	// Modified
148	strftime(string, sizeof(string), "%Y-%m-%d %H:%M",
149		localtime(&info.modification_time));
150	printf("%s", string);
151
152	// User
153	printf("%5d", info.uid);
154
155	// Group
156	printf("%5d\n", info.gid);
157}
158
159
160int
161main(int argc, char **argv)
162{
163	dev_t device = dev_for_path(".");
164	DIR *indices = NULL;
165	bool verbose = false;
166	bool longListing = false;
167	bool mkindexOutput = false; /* mkindex-ready output */
168
169	for (int i = 1; i < argc; i++) {
170		if (argv[i][0] == '-') {
171			if (!strcmp(argv[i], "--help")) {
172				print_help();
173				return 0;
174			}
175			if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v"))
176				verbose = true;
177			else if (!strcmp(argv[i], "--long") || !strcmp(argv[i], "-l"))
178				longListing = true;
179			else if (!strcmp(argv[i], "--mkindex"))
180				mkindexOutput = true;
181			else {
182				fprintf(stderr, "%s: option %s is not understood (use --help "
183					"for help)\n", argv[0], argv[i]);
184				return -1;
185			}
186		} else {
187			device = dev_for_path(argv[i]);
188			if (device < 0) {
189				fprintf(stderr, "%s: can't get information about volume: %s\n",
190					argv[0], argv[i]);
191				return -1;
192			}
193		}
194	}
195
196	indices = fs_open_index_dir(device);
197	if (indices == NULL) {
198		fprintf(stderr, "%s: can't open index dir of device %" B_PRIdDEV "\n",
199			argv[0], device);
200		return -1;
201	}
202
203	if (verbose) {
204		printf(" Name   Type   Size   Created   Modified   User   Group\n");
205		printf("********************************************************\n");
206	}
207
208	while (1) {
209		// We have to reset errno before calling fs_read_index_dir().
210		errno = 0;
211		dirent *index = fs_read_index_dir(indices);
212		if (index == NULL) {
213			if (errno != B_ENTRY_NOT_FOUND && errno != B_OK) {
214				printf("%s: fs_read_index_dir: (%d) %s\n", argv[0], errno,
215					strerror(errno));
216				return errno;
217			}
218			break;
219		}
220
221		if (verbose || longListing || mkindexOutput) {
222			index_info info;
223
224			if (fs_stat_index(device, index->d_name, &info) != B_OK) {
225				printf("%s: fs_stat_index(): (%d) %s\n", argv[0], errno,
226					strerror(errno));
227				return errno;
228			}
229
230			if (verbose)
231				print_index_verbose_stat(info, index->d_name);
232			else if (longListing)
233				print_index_long_stat(info, index->d_name);
234			else {
235				// mkindex output
236				printf("mkindex -t %s '%s'\n", print_index_type(info, true),
237					index->d_name);
238			}
239		} else
240			printf("%s\n", index->d_name);
241	}
242
243	fs_close_index_dir(indices);
244	return 0;
245}
246
247