2 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
12 #include <package/PackageResolvableExpression.h>
13 #include <package/manager/Exceptions.h>
15 #include <PathFinder.h>
16 #include <StringList.h>
19 using namespace BPackageKit::BManager::BPrivate
;
22 extern const char* __progname
;
23 const char* kCommandName
= __progname
;
26 struct DirectoryConstantEntry
{
28 path_base_directory constant
;
29 const char* description
;
32 #define DEFINE_CONSTANT(constant, description) \
33 { #constant, constant, description }
35 static const DirectoryConstantEntry kDirectoryConstants
[] = {
36 DEFINE_CONSTANT(B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY
,
37 "the installation location"),
38 DEFINE_CONSTANT(B_FIND_PATH_ADD_ONS_DIRECTORY
,
39 "the add-ons directory"),
40 DEFINE_CONSTANT(B_FIND_PATH_APPS_DIRECTORY
,
41 "the applications directory"),
42 DEFINE_CONSTANT(B_FIND_PATH_BIN_DIRECTORY
,
43 "the command line programs directory"),
44 DEFINE_CONSTANT(B_FIND_PATH_BOOT_DIRECTORY
,
45 "the boot data directory"),
46 DEFINE_CONSTANT(B_FIND_PATH_CACHE_DIRECTORY
,
47 "the cache directory"),
48 DEFINE_CONSTANT(B_FIND_PATH_DATA_DIRECTORY
,
49 "the data directory"),
50 DEFINE_CONSTANT(B_FIND_PATH_DEVELOP_DIRECTORY
,
51 "the develop directory"),
52 DEFINE_CONSTANT(B_FIND_PATH_DEVELOP_LIB_DIRECTORY
,
53 "the development libraries directory"),
54 DEFINE_CONSTANT(B_FIND_PATH_DOCUMENTATION_DIRECTORY
,
55 "the documentation directory"),
56 DEFINE_CONSTANT(B_FIND_PATH_ETC_DIRECTORY
,
57 "the Unix etc directory (global settings)"),
58 DEFINE_CONSTANT(B_FIND_PATH_FONTS_DIRECTORY
,
59 "the fonts directory"),
60 DEFINE_CONSTANT(B_FIND_PATH_HEADERS_DIRECTORY
,
61 "the development headers directory"),
62 DEFINE_CONSTANT(B_FIND_PATH_LIB_DIRECTORY
,
63 "the libraries directory"),
64 DEFINE_CONSTANT(B_FIND_PATH_LOG_DIRECTORY
,
65 "the logging directory"),
66 DEFINE_CONSTANT(B_FIND_PATH_MEDIA_NODES_DIRECTORY
,
67 "the media node add-ons directory"),
68 DEFINE_CONSTANT(B_FIND_PATH_PACKAGES_DIRECTORY
,
69 "the packages directory"),
70 DEFINE_CONSTANT(B_FIND_PATH_PREFERENCES_DIRECTORY
,
71 "the preference applications directory"),
72 DEFINE_CONSTANT(B_FIND_PATH_SERVERS_DIRECTORY
,
73 "the server programs directory"),
74 DEFINE_CONSTANT(B_FIND_PATH_SETTINGS_DIRECTORY
,
75 "the global settings directory"),
76 DEFINE_CONSTANT(B_FIND_PATH_SOUNDS_DIRECTORY
,
77 "the sound files directory"),
78 DEFINE_CONSTANT(B_FIND_PATH_SPOOL_DIRECTORY
,
79 "the (mail) spool directory"),
80 DEFINE_CONSTANT(B_FIND_PATH_TRANSLATORS_DIRECTORY
,
81 "the translator add-ons directory"),
82 DEFINE_CONSTANT(B_FIND_PATH_VAR_DIRECTORY
,
83 "the Unix var directory (global writable data)"),
84 DEFINE_CONSTANT(B_FIND_PATH_PACKAGE_PATH
,
85 "the path of the package the file specified via -p belongs to"),
88 static const size_t kDirectoryConstantCount
89 = sizeof(kDirectoryConstants
) / sizeof(kDirectoryConstants
[0]);
92 static const char* kUsage
=
93 "Usage: %s [ <options> ] [ <kind> [<subpath>] ]\n"
94 "Prints paths specified by directory constant <kind>. <subpath>, if\n"
95 "specified, is appended to each path. By default a path is printed for\n"
96 "each existing installation location (one per line); the options can\n"
97 "modify this behavior.\n"
100 " -a <architecture>\n"
101 " If the path(s) specified by <kind> are architecture specific, use\n"
102 " architecture <architecture>. If not specified, the primary\n"
103 " architecture is used, unless the -p/--path option is specified, in\n"
104 " which case the architecture associated with the given <path> is\n"
107 " Concatenate the resulting paths, separated only by <separator>,\n"
108 " instead of printing a path per line.\n"
109 " -d, --dependency <dependency>\n"
110 " Modifies the behavior of the -p option. Use the installation "
112 " where the dependency <dependency> of the package that the entry\n"
113 " referred to by <path> belongs to is installed.\n"
115 " Print only paths that refer to existing entries.\n"
117 " Print this usage info.\n"
119 " Print a list of the possible constants for the <kind> parameter.\n"
120 " -p, --path <path>\n"
121 " Print only one path, the one for the installation location that\n"
122 " contains the path <path>.\n"
123 " -r, --resolvable <expression>\n"
124 " Print only one path, the one for the installation location for the\n"
125 " package providing the resolvable matching the expression\n"
126 " <expression>. The expressions can be a simple resolvable name or\n"
127 " a resolvable name with operator and version (e.g.\n"
128 " \"cmd:perl >= 5\"; must be one argument).\n"
130 " Print paths in reverse order, i.e. from most general to most\n"
136 print_usage_and_exit(bool error
)
138 fprintf(error
? stderr
: stdout
, kUsage
, kCommandName
);
144 main(int argc
, const char* const* argv
)
146 const char* architecture
= NULL
;
147 const char* dependency
= NULL
;
148 const char* referencePath
= NULL
;
149 const char* resolvable
= NULL
;
150 bool existingOnly
= false;
151 bool reverseOrder
= false;
152 const char* separator
= NULL
;
155 static struct option sLongOptions
[] = {
156 { "architecture", required_argument
, 0, 'a' },
157 { "dependency", required_argument
, 0, 'd' },
158 { "help", no_argument
, 0, 'h' },
159 { "list", no_argument
, 0, 'l' },
160 { "path", required_argument
, 0, 'p' },
161 { "resolvable", required_argument
, 0, 'pr' },
162 { "reverse", no_argument
, 0, 'R' },
166 opterr
= 0; // don't print errors
167 int c
= getopt_long(argc
, (char**)argv
, "+a:c:d:ehlp:r:R",
174 architecture
= optarg
;
190 print_usage_and_exit(false);
194 for (size_t i
= 0; i
< kDirectoryConstantCount
; i
++) {
195 const DirectoryConstantEntry
& entry
196 = kDirectoryConstants
[i
];
197 printf("%s\n - %s\n", entry
.string
, entry
.description
);
202 referencePath
= optarg
;
214 print_usage_and_exit(true);
219 // The remaining arguments are the kind constant and optionally the subpath.
220 if (optind
>= argc
|| optind
+ 2 < argc
)
221 print_usage_and_exit(true);
223 const char* kindConstant
= argv
[optind
++];
225 const char* subPath
= NULL
;
227 subPath
= argv
[optind
++];
229 // only one of path or resolvable may be specified
230 if (referencePath
!= NULL
&& resolvable
!= NULL
)
231 print_usage_and_exit(true);
233 // resolve the directory constant
234 path_base_directory baseDirectory
= B_FIND_PATH_IMAGE_PATH
;
236 for (size_t i
= 0; i
< kDirectoryConstantCount
; i
++) {
237 const DirectoryConstantEntry
& entry
= kDirectoryConstants
[i
];
238 if (strcmp(kindConstant
, entry
.string
) == 0) {
240 baseDirectory
= entry
.constant
;
246 fprintf(stderr
, "Error: Unsupported directory constant \"%s\".\n",
251 if (referencePath
!= NULL
|| resolvable
!= NULL
) {
253 BPathFinder pathFinder
;
254 if (referencePath
!= NULL
) {
255 pathFinder
.SetTo(referencePath
, dependency
);
258 BPackageKit::BPackageResolvableExpression(resolvable
),
263 status_t error
= pathFinder
.FindPath(architecture
, baseDirectory
,
264 subPath
, existingOnly
? B_FIND_PATH_EXISTING_ONLY
: 0, path
);
266 fprintf(stderr
, "Error: Failed to find path: %s\n",
271 printf("%s\n", path
.Path());
272 } catch(BFatalErrorException
& exception
) {
273 if (!exception
.Details().IsEmpty())
274 fprintf(stderr
, "%s", exception
.Details().String());
275 if (exception
.Error() == B_OK
) {
276 fprintf(stderr
, "Error: %s\n", exception
.Message().String());
278 fprintf(stderr
, "Error: %s: %s\n", exception
.Message().String(),
279 strerror(exception
.Error()));
285 status_t error
= BPathFinder::FindPaths(architecture
, baseDirectory
,
286 subPath
, existingOnly
? B_FIND_PATH_EXISTING_ONLY
: 0, paths
);
288 fprintf(stderr
, "Error: Failed to find paths: %s\n",
293 int32 count
= paths
.CountStrings();
295 for (int32 i
= 0; i
< count
/ 2; i
++)
296 paths
.Swap(i
, count
- i
- 1);
299 if (separator
!= NULL
) {
300 BString result
= paths
.Join(separator
);
301 if (result
.IsEmpty()) {
302 fprintf(stderr
, "Error: Out of memory!\n");
305 printf("%s\n", result
.String());
307 for (int32 i
= 0; i
< count
; i
++)
308 printf("%s\n", paths
.StringAt(i
).String());