xref: /haiku/src/bin/finddir.c (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /*
2  * Copyright 2002, Sebastian Nozzi <sebnozzi@gmx.net>.
3  * Copyright 2004, Francois Revol.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include <FindDirectory.h>
12 #include <fs_info.h>
13 
14 
15 #define NO_ERRORS			0
16 #define ARGUMENT_MISSING	1
17 #define WRONG_DIR_TYPE		2
18 
19 typedef struct {
20 	const char *key;
21 	directory_which value;
22 } directoryType;
23 
24 #define KEYVALUE_PAIR(key) {#key, key}
25 
26 directoryType directoryTypes[] = {
27 	// Generic directories
28 	KEYVALUE_PAIR(B_DESKTOP_DIRECTORY),
29 	KEYVALUE_PAIR(B_TRASH_DIRECTORY),
30 	KEYVALUE_PAIR(B_APPS_DIRECTORY),
31 	KEYVALUE_PAIR(B_PACKAGE_LINKS_DIRECTORY),
32 	KEYVALUE_PAIR(B_PREFERENCES_DIRECTORY),
33 	KEYVALUE_PAIR(B_UTILITIES_DIRECTORY),
34 
35 	// System directories
36 	KEYVALUE_PAIR(B_SYSTEM_DIRECTORY),
37 	KEYVALUE_PAIR(B_SYSTEM_ADDONS_DIRECTORY),
38 	KEYVALUE_PAIR(B_SYSTEM_BOOT_DIRECTORY),
39 	KEYVALUE_PAIR(B_SYSTEM_FONTS_DIRECTORY),
40 	KEYVALUE_PAIR(B_SYSTEM_LIB_DIRECTORY),
41 	KEYVALUE_PAIR(B_SYSTEM_SERVERS_DIRECTORY),
42 	KEYVALUE_PAIR(B_SYSTEM_APPS_DIRECTORY),
43 	KEYVALUE_PAIR(B_SYSTEM_BIN_DIRECTORY),
44 	KEYVALUE_PAIR(B_SYSTEM_DOCUMENTATION_DIRECTORY),
45 	KEYVALUE_PAIR(B_SYSTEM_PREFERENCES_DIRECTORY),
46 	KEYVALUE_PAIR(B_SYSTEM_TRANSLATORS_DIRECTORY),
47 	KEYVALUE_PAIR(B_SYSTEM_MEDIA_NODES_DIRECTORY),
48 	KEYVALUE_PAIR(B_SYSTEM_SOUNDS_DIRECTORY),
49 	KEYVALUE_PAIR(B_SYSTEM_DATA_DIRECTORY),
50 	KEYVALUE_PAIR(B_SYSTEM_DEVELOP_DIRECTORY),
51 	KEYVALUE_PAIR(B_SYSTEM_PACKAGES_DIRECTORY),
52 	KEYVALUE_PAIR(B_SYSTEM_HEADERS_DIRECTORY),
53 
54 	// Writable system directories
55 	KEYVALUE_PAIR(B_SYSTEM_ETC_DIRECTORY),
56 	KEYVALUE_PAIR(B_SYSTEM_SETTINGS_DIRECTORY),
57 	KEYVALUE_PAIR(B_SYSTEM_LOG_DIRECTORY),
58 	KEYVALUE_PAIR(B_SYSTEM_SPOOL_DIRECTORY),
59 	KEYVALUE_PAIR(B_SYSTEM_TEMP_DIRECTORY),
60 	KEYVALUE_PAIR(B_SYSTEM_VAR_DIRECTORY),
61 	KEYVALUE_PAIR(B_SYSTEM_CACHE_DIRECTORY),
62 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_DIRECTORY),
63 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY),
64 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY),
65 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY),
66 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_BIN_DIRECTORY),
67 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_DATA_DIRECTORY),
68 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY),
69 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY),
70 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY),
71 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_LIB_DIRECTORY),
72 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY),
73 	KEYVALUE_PAIR(B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY),
74 
75 	// User directories
76 	KEYVALUE_PAIR(B_USER_DIRECTORY),
77 	KEYVALUE_PAIR(B_USER_CONFIG_DIRECTORY),
78 	KEYVALUE_PAIR(B_USER_ADDONS_DIRECTORY),
79 	KEYVALUE_PAIR(B_USER_BOOT_DIRECTORY),
80 	KEYVALUE_PAIR(B_USER_FONTS_DIRECTORY),
81 	KEYVALUE_PAIR(B_USER_LIB_DIRECTORY),
82 	KEYVALUE_PAIR(B_USER_SETTINGS_DIRECTORY),
83 	KEYVALUE_PAIR(B_USER_DESKBAR_DIRECTORY),
84 	KEYVALUE_PAIR(B_USER_PRINTERS_DIRECTORY),
85 	KEYVALUE_PAIR(B_USER_TRANSLATORS_DIRECTORY),
86 	KEYVALUE_PAIR(B_USER_MEDIA_NODES_DIRECTORY),
87 	KEYVALUE_PAIR(B_USER_SOUNDS_DIRECTORY),
88 	KEYVALUE_PAIR(B_USER_DATA_DIRECTORY),
89 	KEYVALUE_PAIR(B_USER_CACHE_DIRECTORY),
90 	KEYVALUE_PAIR(B_USER_PACKAGES_DIRECTORY),
91 	KEYVALUE_PAIR(B_USER_DEVELOP_DIRECTORY),
92 	KEYVALUE_PAIR(B_USER_DOCUMENTATION_DIRECTORY),
93 	KEYVALUE_PAIR(B_USER_HEADERS_DIRECTORY),
94 	KEYVALUE_PAIR(B_USER_SERVERS_DIRECTORY),
95 	KEYVALUE_PAIR(B_USER_APPS_DIRECTORY),
96 	KEYVALUE_PAIR(B_USER_BIN_DIRECTORY),
97 	KEYVALUE_PAIR(B_USER_PREFERENCES_DIRECTORY),
98 	KEYVALUE_PAIR(B_USER_ETC_DIRECTORY),
99 	KEYVALUE_PAIR(B_USER_LOG_DIRECTORY),
100 	KEYVALUE_PAIR(B_USER_SPOOL_DIRECTORY),
101 	KEYVALUE_PAIR(B_USER_VAR_DIRECTORY),
102 	KEYVALUE_PAIR(B_USER_NONPACKAGED_DIRECTORY),
103 	KEYVALUE_PAIR(B_USER_NONPACKAGED_ADDONS_DIRECTORY),
104 	KEYVALUE_PAIR(B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY),
105 	KEYVALUE_PAIR(B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY),
106 	KEYVALUE_PAIR(B_USER_NONPACKAGED_BIN_DIRECTORY),
107 	KEYVALUE_PAIR(B_USER_NONPACKAGED_DATA_DIRECTORY),
108 	KEYVALUE_PAIR(B_USER_NONPACKAGED_FONTS_DIRECTORY),
109 	KEYVALUE_PAIR(B_USER_NONPACKAGED_SOUNDS_DIRECTORY),
110 	KEYVALUE_PAIR(B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY),
111 	KEYVALUE_PAIR(B_USER_NONPACKAGED_LIB_DIRECTORY),
112 	KEYVALUE_PAIR(B_USER_NONPACKAGED_HEADERS_DIRECTORY),
113 	KEYVALUE_PAIR(B_USER_NONPACKAGED_DEVELOP_DIRECTORY),
114 
115 	// Legacy system directories
116 	KEYVALUE_PAIR(B_BEOS_DIRECTORY),
117 	KEYVALUE_PAIR(B_BEOS_SYSTEM_DIRECTORY),
118 	KEYVALUE_PAIR(B_BEOS_ADDONS_DIRECTORY),
119 	KEYVALUE_PAIR(B_BEOS_BOOT_DIRECTORY),
120 	KEYVALUE_PAIR(B_BEOS_FONTS_DIRECTORY),
121 	KEYVALUE_PAIR(B_BEOS_LIB_DIRECTORY),
122 	KEYVALUE_PAIR(B_BEOS_SERVERS_DIRECTORY),
123 	KEYVALUE_PAIR(B_BEOS_APPS_DIRECTORY),
124 	KEYVALUE_PAIR(B_BEOS_BIN_DIRECTORY),
125 	KEYVALUE_PAIR(B_BEOS_ETC_DIRECTORY),
126 	KEYVALUE_PAIR(B_BEOS_DOCUMENTATION_DIRECTORY),
127 	KEYVALUE_PAIR(B_BEOS_PREFERENCES_DIRECTORY),
128 	KEYVALUE_PAIR(B_BEOS_TRANSLATORS_DIRECTORY),
129 	KEYVALUE_PAIR(B_BEOS_MEDIA_NODES_DIRECTORY),
130 	KEYVALUE_PAIR(B_BEOS_SOUNDS_DIRECTORY),
131 	KEYVALUE_PAIR(B_BEOS_DATA_DIRECTORY),
132 
133 	// Legacy "common" directories, for BeOS compatibility only.
134 	{"B_COMMON_DIRECTORY", B_SYSTEM_NONPACKAGED_DIRECTORY},
135 	{"B_COMMON_SYSTEM_DIRECTORY", B_SYSTEM_NONPACKAGED_DIRECTORY},
136 	{"B_COMMON_ADDONS_DIRECTORY", B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY},
137 	{"B_COMMON_BIN_DIRECTORY", B_SYSTEM_NONPACKAGED_BIN_DIRECTORY},
138 	{"B_COMMON_DEVELOP_DIRECTORY", B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY},
139 	{"B_COMMON_DOCUMENTATION_DIRECTORY",
140 		B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY},
141 	{"B_COMMON_FONTS_DIRECTORY",B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY},
142 	{"B_COMMON_LIB_DIRECTORY", B_SYSTEM_NONPACKAGED_LIB_DIRECTORY},
143 
144 	{"B_COMMON_BOOT_DIRECTORY", B_SYSTEM_BOOT_DIRECTORY},
145 	{"B_COMMON_ETC_DIRECTORY", B_SYSTEM_ETC_DIRECTORY},
146 	{"B_COMMON_LOG_DIRECTORY", B_SYSTEM_LOG_DIRECTORY},
147 	{"B_COMMON_SERVERS_DIRECTORY", B_SYSTEM_SERVERS_DIRECTORY},
148 	{"B_COMMON_SETTINGS_DIRECTORY", B_SYSTEM_SETTINGS_DIRECTORY},
149 	{"B_COMMON_SPOOL_DIRECTORY", B_SYSTEM_SPOOL_DIRECTORY},
150 	{"B_COMMON_TEMP_DIRECTORY", B_SYSTEM_TEMP_DIRECTORY},
151 	{"B_COMMON_VAR_DIRECTORY", B_SYSTEM_VAR_DIRECTORY},
152 
153 	{NULL, B_USER_DESKBAR_DIRECTORY}
154 };
155 
156 
157 static void
158 listDirectoryWhich(void)
159 {
160 	int i;
161 
162 	for (i = 0; directoryTypes[i].key; i++) {
163 		printf("%s\n", directoryTypes[i].key);
164 	}
165 }
166 
167 
168 static bool
169 retrieveDirValue(directoryType *list, const char *key,
170 	directory_which *valueOut)
171 {
172 	unsigned i = 0;
173 
174 	while (list[i].key != NULL) {
175 		if (strcmp(list[i].key, key) == 0) {
176 			*valueOut = list[i].value;
177 			return true;
178 		}
179 
180 		i++;
181 	}
182 
183 	return false;
184 }
185 
186 
187 static void
188 usageMsg()
189 {
190 	printf("usage:  /bin/finddir -l | [ -v volume ] directory_which\n");
191 	printf("\t-l\t    list valid which constants to use\n");
192 	printf("\t-v <file>   use the specified volume for directory\n");
193 	printf("\t\t    constants that are volume-specific.\n");
194 	printf("\t\t    <file> can be any file on that volume.\n");
195 	printf("\t\t    defaults to the boot volume.\n");
196 	printf(" For a description of recognized directory_which constants,\n");
197 	printf(" see the find_directory(...) documentation in the Be Book.\n");
198 }
199 
200 
201 int
202 main(int argc, char *argv[])
203 {
204 	int directoryArgNr;
205 	int status;
206 	dev_t volume;
207 	directory_which dirType;
208 	int returnCode;
209 
210 	status = NO_ERRORS;
211 	directoryArgNr = 1;
212 	returnCode = 0;
213 
214 	dirType = B_BEOS_DIRECTORY; /* so that it compiles */
215 
216 	/* By default use boot volume*/
217 	volume = dev_for_path("/boot");
218 
219 	if (argc <= 1) {
220 		status = ARGUMENT_MISSING;
221 	} else {
222 		if (strcmp(argv[1], "-l") == 0 ) {
223 			listDirectoryWhich();
224 			return 0;
225 		}
226 		if (strcmp(argv[1], "-v") == 0 ) {
227 			if (argc >= 3) {
228 				dev_t temp_volume;
229 				/* get volume from second arg */
230 				temp_volume = dev_for_path(argv[2]);
231 
232 				/* Keep default value in case of error */
233 				if (temp_volume >= 0)
234 					volume = temp_volume;
235 
236 				/* two arguments were used for volume */
237 				directoryArgNr+=2;
238 			} else {
239 				/* set status to argument missing */
240 				status = ARGUMENT_MISSING;
241 			}
242 		}
243 	}
244 
245 	if (status == NO_ERRORS && argc > directoryArgNr) {
246 		/* get directory constant from next argument */
247 
248 		if (!retrieveDirValue(directoryTypes, argv[directoryArgNr], &dirType))
249 			status = WRONG_DIR_TYPE;
250 	} else {
251 		status = ARGUMENT_MISSING;
252 	}
253 
254 	/* Do the actual directoy finding */
255 
256 	if (status == NO_ERRORS) {
257 		/* Question: would B_PATH_NAME_LENGTH alone have been enough? */
258 		char buffer[B_PATH_NAME_LENGTH+B_FILE_NAME_LENGTH];
259 		status_t result = find_directory (dirType, volume, false, buffer,
260 			sizeof(buffer));
261 		if (result == B_OK) {
262 			printf("%s\n", buffer);
263 		} else {
264 			fprintf(stderr, "Failed to get directory: %s\n", strerror(result));
265 			return 1;
266 		}
267 	}
268 
269 	/* Error messages and return code setting */
270 
271 	if (status == WRONG_DIR_TYPE) {
272 		fprintf(stderr, "%s: unrecognized directory_which constant \'%s\'\n", argv[0],
273 			argv[directoryArgNr]);
274 		returnCode = 252;
275 	}
276 
277 	if (status == ARGUMENT_MISSING) {
278 		usageMsg();
279 		returnCode = 255;
280 	}
281 
282 	return returnCode;
283 }
284 
285