2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
12 #include <package/PackageResolvableExpression.h>
14 #include <PathFinder.h>
15 #include <StringList.h>
18 extern const char* __progname
;
19 const char* kCommandName
= __progname
;
22 struct DirectoryConstantEntry
{
24 path_base_directory constant
;
25 const char* description
;
28 #define DEFINE_CONSTANT(constant, description) \
29 { #constant, constant, description }
31 static const DirectoryConstantEntry kDirectoryConstants
[] = {
32 DEFINE_CONSTANT(B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY
,
33 "the installation location"),
34 DEFINE_CONSTANT(B_FIND_PATH_ADD_ONS_DIRECTORY
,
35 "the add-ons directory"),
36 DEFINE_CONSTANT(B_FIND_PATH_APPS_DIRECTORY
,
37 "the applications directory"),
38 DEFINE_CONSTANT(B_FIND_PATH_BIN_DIRECTORY
,
39 "the command line programs directory"),
40 DEFINE_CONSTANT(B_FIND_PATH_BOOT_DIRECTORY
,
41 "the boot data directory"),
42 DEFINE_CONSTANT(B_FIND_PATH_CACHE_DIRECTORY
,
43 "the cache directory"),
44 DEFINE_CONSTANT(B_FIND_PATH_DATA_DIRECTORY
,
45 "the data directory"),
46 DEFINE_CONSTANT(B_FIND_PATH_DEVELOP_DIRECTORY
,
47 "the develop directory"),
48 DEFINE_CONSTANT(B_FIND_PATH_DEVELOP_LIB_DIRECTORY
,
49 "the development libraries directory"),
50 DEFINE_CONSTANT(B_FIND_PATH_DOCUMENTATION_DIRECTORY
,
51 "the documentation directory"),
52 DEFINE_CONSTANT(B_FIND_PATH_ETC_DIRECTORY
,
53 "the Unix etc directory (global settings)"),
54 DEFINE_CONSTANT(B_FIND_PATH_FONTS_DIRECTORY
,
55 "the fonts directory"),
56 DEFINE_CONSTANT(B_FIND_PATH_HEADERS_DIRECTORY
,
57 "the development headers directory"),
58 DEFINE_CONSTANT(B_FIND_PATH_LIB_DIRECTORY
,
59 "the libraries directory"),
60 DEFINE_CONSTANT(B_FIND_PATH_LOG_DIRECTORY
,
61 "the logging directory"),
62 DEFINE_CONSTANT(B_FIND_PATH_MEDIA_NODES_DIRECTORY
,
63 "the media node add-ons directory"),
64 DEFINE_CONSTANT(B_FIND_PATH_PACKAGES_DIRECTORY
,
65 "the packages directory"),
66 DEFINE_CONSTANT(B_FIND_PATH_PREFERENCES_DIRECTORY
,
67 "the preference applications directory"),
68 DEFINE_CONSTANT(B_FIND_PATH_SERVERS_DIRECTORY
,
69 "the server programs directory"),
70 DEFINE_CONSTANT(B_FIND_PATH_SETTINGS_DIRECTORY
,
71 "the global settings directory"),
72 DEFINE_CONSTANT(B_FIND_PATH_SOUNDS_DIRECTORY
,
73 "the sound files directory"),
74 DEFINE_CONSTANT(B_FIND_PATH_SPOOL_DIRECTORY
,
75 "the (mail) spool directory"),
76 DEFINE_CONSTANT(B_FIND_PATH_TRANSLATORS_DIRECTORY
,
77 "the translator add-ons directory"),
78 DEFINE_CONSTANT(B_FIND_PATH_VAR_DIRECTORY
,
79 "the Unix var directory (global writable data)"),
80 DEFINE_CONSTANT(B_FIND_PATH_PACKAGE_PATH
,
81 "the path of the package the file specified via -p belongs to"),
84 static const size_t kDirectoryConstantCount
85 = sizeof(kDirectoryConstants
) / sizeof(kDirectoryConstants
[0]);
88 static const char* kUsage
=
89 "Usage: %s [ <options> ] [ <kind> [<subpath>] ]\n"
90 "Prints paths specified by directory constant <kind>. <subpath>, if\n"
91 "specified, is appended to each path. By default a path is printed for\n"
92 "each existing installation location (one per line); the options can\n"
93 "modify this behavior.\n"
96 " -a <architecture>\n"
97 " If the path(s) specified by <kind> are architecture specific, use\n"
98 " architecture <architecture>. If not specified, the primary\n"
99 " architecture is used, unless the -p/--path option is specified, in\n"
100 " which case the architecture associated with the given <path> is\n"
103 " Concatenate the resulting paths, separated only by <separator>,\n"
104 " instead of printing a path per line.\n"
105 " -d, --dependency <dependency>\n"
106 " Modifies the behavior of the -p option. Use the installation "
108 " where the dependency <dependency> of the package that the entry\n"
109 " referred to by <path> belongs to is installed.\n"
111 " Print only paths that refer to existing entries.\n"
113 " Print this usage info.\n"
115 " Print a list of the possible constants for the <kind> parameter.\n"
116 " -p, --path <path>\n"
117 " Print only one path, the one for the installation location that\n"
118 " contains the path <path>.\n"
119 " -r, --resolvable <expression>\n"
120 " Print only one path, the one for the installation location for the\n"
121 " package providing the resolvable matching the expression\n"
122 " <expression>. The expressions can be a simple resolvable name or\n"
123 " a resolvable name with operator and version (e.g.\n"
124 " \"cmd:perl >= 5\"; must be one argument).\n"
126 " Print paths in reverse order, i.e. from most general to most\n"
132 print_usage_and_exit(bool error
)
134 fprintf(error
? stderr
: stdout
, kUsage
, kCommandName
);
140 main(int argc
, const char* const* argv
)
142 const char* architecture
= NULL
;
143 const char* dependency
= NULL
;
144 const char* referencePath
= NULL
;
145 const char* resolvable
= NULL
;
146 bool existingOnly
= false;
147 bool reverseOrder
= false;
148 const char* separator
= NULL
;
151 static struct option sLongOptions
[] = {
152 { "architecture", required_argument
, 0, 'a' },
153 { "dependency", required_argument
, 0, 'd' },
154 { "help", no_argument
, 0, 'h' },
155 { "list", no_argument
, 0, 'l' },
156 { "path", required_argument
, 0, 'p' },
157 { "resolvable", required_argument
, 0, 'pr' },
158 { "reverse", no_argument
, 0, 'R' },
162 opterr
= 0; // don't print errors
163 int c
= getopt_long(argc
, (char**)argv
, "+a:c:d:ehlp:r:R",
170 architecture
= optarg
;
186 print_usage_and_exit(false);
190 for (size_t i
= 0; i
< kDirectoryConstantCount
; i
++) {
191 const DirectoryConstantEntry
& entry
192 = kDirectoryConstants
[i
];
193 printf("%s\n - %s\n", entry
.string
, entry
.description
);
198 referencePath
= optarg
;
210 print_usage_and_exit(true);
215 // The remaining arguments are the kind constant and optionally the subpath.
216 if (optind
>= argc
|| optind
+ 2 < argc
)
217 print_usage_and_exit(true);
219 const char* kindConstant
= argv
[optind
++];
221 const char* subPath
= NULL
;
223 subPath
= argv
[optind
++];
225 // only one of path or resolvable may be specified
226 if (referencePath
!= NULL
&& resolvable
!= NULL
)
227 print_usage_and_exit(true);
229 // resolve the directory constant
230 path_base_directory baseDirectory
= B_FIND_PATH_IMAGE_PATH
;
232 for (size_t i
= 0; i
< kDirectoryConstantCount
; i
++) {
233 const DirectoryConstantEntry
& entry
= kDirectoryConstants
[i
];
234 if (strcmp(kindConstant
, entry
.string
) == 0) {
236 baseDirectory
= entry
.constant
;
242 fprintf(stderr
, "Error: Unsupported directory constant \"%s\".\n",
247 if (referencePath
!= NULL
|| resolvable
!= NULL
) {
248 BPathFinder pathFinder
;
249 if (referencePath
!= NULL
) {
250 pathFinder
.SetTo(referencePath
, dependency
);
253 BPackageKit::BPackageResolvableExpression(resolvable
),
258 status_t error
= pathFinder
.FindPath(architecture
, baseDirectory
,
259 subPath
, existingOnly
? B_FIND_PATH_EXISTING_ONLY
: 0, path
);
261 fprintf(stderr
, "Error: Failed to find path: %s\n",
266 printf("%s\n", path
.Path());
269 status_t error
= BPathFinder::FindPaths(architecture
, baseDirectory
,
270 subPath
, existingOnly
? B_FIND_PATH_EXISTING_ONLY
: 0, paths
);
272 fprintf(stderr
, "Error: Failed to find paths: %s\n",
277 int32 count
= paths
.CountStrings();
279 for (int32 i
= 0; i
< count
/ 2; i
++)
280 paths
.Swap(i
, count
- i
- 1);
283 if (separator
!= NULL
) {
284 BString result
= paths
.Join(separator
);
285 if (result
.IsEmpty()) {
286 fprintf(stderr
, "Error: Out of memory!\n");
289 printf("%s\n", result
.String());
291 for (int32 i
= 0; i
< count
; i
++)
292 printf("%s\n", paths
.StringAt(i
).String());