Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/java.base/share/native/libjli/wildcard.c
67707 views
1
/*
2
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
* Class-Path Wildcards
28
*
29
* The syntax for wildcards is a single asterisk. The class path
30
* foo/"*", e.g., loads all jar files in the directory named foo.
31
* (This requires careful quotation when used in shell scripts.)
32
*
33
* Only files whose names end in .jar or .JAR are matched.
34
* Files whose names end in .zip, or which have a particular
35
* magic number, regardless of filename extension, are not
36
* matched.
37
*
38
* Files are considered regardless of whether or not they are
39
* "hidden" in the UNIX sense, i.e., have names beginning with '.'.
40
*
41
* A wildcard only matches jar files, not class files in the same
42
* directory. If you want to load both class files and jar files from
43
* a single directory foo then you can say foo:foo/"*", or foo/"*":foo
44
* if you want the jar files to take precedence.
45
*
46
* Subdirectories are not searched recursively, i.e., foo/"*" only
47
* looks for jar files in foo, not in foo/bar, foo/baz, etc.
48
*
49
* Expansion of wildcards is done early, prior to the invocation of a
50
* program's main method, rather than late, during the class-loading
51
* process itself. Each element of the input class path containing a
52
* wildcard is replaced by the (possibly empty) sequence of elements
53
* generated by enumerating the jar files in the named directory. If
54
* the directory foo contains a.jar, b.jar, and c.jar,
55
* e.g., then the class path foo/"*" is expanded into
56
* foo/a.jar:foo/b.jar:foo/c.jar, and that string would be the value
57
* of the system property java.class.path.
58
*
59
* The order in which the jar files in a directory are enumerated in
60
* the expanded class path is not specified and may vary from platform
61
* to platform and even from moment to moment on the same machine. A
62
* well-constructed application should not depend upon any particular
63
* order. If a specific order is required then the jar files can be
64
* enumerated explicitly in the class path.
65
*
66
* The CLASSPATH environment variable is not treated any differently
67
* from the -classpath (equiv. -cp) command-line option,
68
* i.e. wildcards are honored in all these cases.
69
*
70
* Class-path wildcards are not honored in the Class-Path jar-manifest
71
* header.
72
*
73
* Class-path wildcards are honored not only by the Java launcher but
74
* also by most other command-line tools that accept class paths, and
75
* in particular by javac and javadoc.
76
*
77
* Class-path wildcards are not honored in any other kind of path, and
78
* especially not in the bootstrap class path, which is a mere
79
* artifact of our implementation and not something that developers
80
* should use.
81
*
82
* Classpath wildcards are only expanded in the Java launcher code,
83
* supporting the use of wildcards on the command line and in the
84
* CLASSPATH environment variable. We do not support the use of
85
* wildcards by applications that embed the JVM.
86
*/
87
88
#include <stddef.h>
89
#include <stdio.h>
90
#include <stdlib.h>
91
#include <string.h>
92
#include <sys/types.h>
93
#include "java.h" /* Strictly for PATH_SEPARATOR/FILE_SEPARATOR */
94
#include "jli_util.h"
95
96
#ifdef _WIN32
97
#include <windows.h>
98
#else /* Unix */
99
#include <unistd.h>
100
#include <dirent.h>
101
#endif /* Unix */
102
103
#if defined(_AIX)
104
#define DIR DIR64
105
#define dirent dirent64
106
#define opendir opendir64
107
#define readdir readdir64
108
#define closedir closedir64
109
#endif
110
111
static int
112
exists(const char* filename)
113
{
114
#ifdef _WIN32
115
return _access(filename, 0) == 0;
116
#else
117
return access(filename, F_OK) == 0;
118
#endif
119
}
120
121
#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
122
123
/*
124
* Wildcard directory iteration.
125
* WildcardIterator_for(wildcard) returns an iterator.
126
* Each call to that iterator's next() method returns the basename
127
* of an entry in the wildcard's directory. The basename's memory
128
* belongs to the iterator. The caller is responsible for prepending
129
* the directory name and file separator, if necessary.
130
* When done with the iterator, call the close method to clean up.
131
*/
132
typedef struct WildcardIterator_* WildcardIterator;
133
134
#ifdef _WIN32
135
struct WildcardIterator_
136
{
137
HANDLE handle;
138
char *firstFile; /* Stupid FindFirstFile...FindNextFile */
139
};
140
// since this is used repeatedly we keep it here.
141
static WIN32_FIND_DATA find_data;
142
static WildcardIterator
143
WildcardIterator_for(const char *wildcard)
144
{
145
WildcardIterator it = NEW_(WildcardIterator);
146
HANDLE handle = FindFirstFile(wildcard, &find_data);
147
if (handle == INVALID_HANDLE_VALUE) {
148
JLI_MemFree(it);
149
return NULL;
150
}
151
it->handle = handle;
152
it->firstFile = find_data.cFileName;
153
return it;
154
}
155
156
static char *
157
WildcardIterator_next(WildcardIterator it)
158
{
159
if (it->firstFile != NULL) {
160
char *firstFile = it->firstFile;
161
it->firstFile = NULL;
162
return firstFile;
163
}
164
return FindNextFile(it->handle, &find_data)
165
? find_data.cFileName : NULL;
166
}
167
168
static void
169
WildcardIterator_close(WildcardIterator it)
170
{
171
if (it) {
172
FindClose(it->handle);
173
JLI_MemFree(it->firstFile);
174
JLI_MemFree(it);
175
}
176
}
177
178
#else /* Unix */
179
struct WildcardIterator_
180
{
181
DIR *dir;
182
};
183
184
static WildcardIterator
185
WildcardIterator_for(const char *wildcard)
186
{
187
DIR *dir;
188
int wildlen = JLI_StrLen(wildcard);
189
if (wildlen < 2) {
190
dir = opendir(".");
191
} else {
192
char *dirname = JLI_StringDup(wildcard);
193
dirname[wildlen - 1] = '\0';
194
dir = opendir(dirname);
195
JLI_MemFree(dirname);
196
}
197
if (dir == NULL)
198
return NULL;
199
else {
200
WildcardIterator it = NEW_(WildcardIterator);
201
it->dir = dir;
202
return it;
203
}
204
}
205
206
static char *
207
WildcardIterator_next(WildcardIterator it)
208
{
209
struct dirent* dirp = readdir(it->dir);
210
return dirp ? dirp->d_name : NULL;
211
}
212
213
static void
214
WildcardIterator_close(WildcardIterator it)
215
{
216
if (it) {
217
closedir(it->dir);
218
JLI_MemFree(it);
219
}
220
}
221
#endif /* Unix */
222
223
static int
224
equal(const char *s1, const char *s2)
225
{
226
return JLI_StrCmp(s1, s2) == 0;
227
}
228
229
static int
230
isJarFileName(const char *filename)
231
{
232
int len = (int)JLI_StrLen(filename);
233
return (len >= 4) &&
234
(filename[len - 4] == '.') &&
235
(equal(filename + len - 3, "jar") ||
236
equal(filename + len - 3, "JAR")) &&
237
/* Paranoia: Maybe filename is "DIR:foo.jar" */
238
(JLI_StrChr(filename, PATH_SEPARATOR) == NULL);
239
}
240
241
static char *
242
wildcardConcat(const char *wildcard, const char *basename)
243
{
244
int wildlen = (int)JLI_StrLen(wildcard);
245
int baselen = (int)JLI_StrLen(basename);
246
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
247
/* Replace the trailing '*' with basename */
248
memcpy(filename, wildcard, wildlen-1);
249
memcpy(filename+wildlen-1, basename, baselen+1);
250
return filename;
251
}
252
253
static JLI_List
254
wildcardFileList(const char *wildcard)
255
{
256
const char *basename;
257
JLI_List fl = JLI_List_new(16);
258
WildcardIterator it = WildcardIterator_for(wildcard);
259
260
if (it == NULL)
261
{
262
JLI_List_free(fl);
263
return NULL;
264
}
265
266
while ((basename = WildcardIterator_next(it)) != NULL)
267
if (isJarFileName(basename))
268
JLI_List_add(fl, wildcardConcat(wildcard, basename));
269
WildcardIterator_close(it);
270
return fl;
271
}
272
273
static int
274
isWildcard(const char *filename)
275
{
276
int len = (int)JLI_StrLen(filename);
277
return (len > 0) &&
278
(filename[len - 1] == '*') &&
279
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
280
(! exists(filename));
281
}
282
283
static int
284
FileList_expandWildcards(JLI_List fl)
285
{
286
size_t i, j;
287
int expandedCnt = 0;
288
for (i = 0; i < fl->size; i++) {
289
if (isWildcard(fl->elements[i])) {
290
JLI_List expanded = wildcardFileList(fl->elements[i]);
291
if (expanded != NULL && expanded->size > 0) {
292
expandedCnt++;
293
JLI_MemFree(fl->elements[i]);
294
JLI_List_ensureCapacity(fl, fl->size + expanded->size);
295
for (j = fl->size - 1; j >= i+1; j--)
296
fl->elements[j+expanded->size-1] = fl->elements[j];
297
for (j = 0; j < expanded->size; j++)
298
fl->elements[i+j] = expanded->elements[j];
299
i += expanded->size - 1;
300
fl->size += expanded->size - 1;
301
/* fl expropriates expanded's elements. */
302
expanded->size = 0;
303
}
304
JLI_List_free(expanded);
305
}
306
}
307
return expandedCnt;
308
}
309
310
const char *
311
JLI_WildcardExpandClasspath(const char *classpath)
312
{
313
const char *expanded;
314
JLI_List fl;
315
316
if (JLI_StrChr(classpath, '*') == NULL)
317
return classpath;
318
fl = JLI_List_split(classpath, PATH_SEPARATOR);
319
expanded = FileList_expandWildcards(fl) ?
320
JLI_List_join(fl, PATH_SEPARATOR) : classpath;
321
JLI_List_free(fl);
322
if (getenv(JLDEBUG_ENV_ENTRY) != 0)
323
printf("Expanded wildcards:\n"
324
" before: \"%s\"\n"
325
" after : \"%s\"\n",
326
classpath, expanded);
327
return expanded;
328
}
329
330
#ifdef DEBUG_WILDCARD
331
static void
332
FileList_print(JLI_List fl)
333
{
334
size_t i;
335
putchar('[');
336
for (i = 0; i < fl->size; i++) {
337
if (i > 0) printf(", ");
338
printf("\"%s\"",fl->elements[i]);
339
}
340
putchar(']');
341
}
342
343
static void
344
wildcardExpandArgv(const char ***argv)
345
{
346
int i;
347
for (i = 0; (*argv)[i]; i++) {
348
if (equal((*argv)[i], "-cp") ||
349
equal((*argv)[i], "-classpath")) {
350
i++;
351
(*argv)[i] = wildcardExpandClasspath((*argv)[i]);
352
}
353
}
354
}
355
356
static void
357
debugPrintArgv(char *argv[])
358
{
359
int i;
360
putchar('[');
361
for (i = 0; argv[i]; i++) {
362
if (i > 0) printf(", ");
363
printf("\"%s\"", argv[i]);
364
}
365
printf("]\n");
366
}
367
368
int
369
main(int argc, char *argv[])
370
{
371
argv[0] = "java";
372
wildcardExpandArgv((const char***)&argv);
373
debugPrintArgv(argv);
374
/* execvp("java", argv); */
375
return 0;
376
}
377
#endif /* DEBUG_WILDCARD */
378
379
/* Cute little perl prototype implementation....
380
381
my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
382
383
sub expand($) {
384
opendir DIR, $_[0] or return $_[0];
385
join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
386
}
387
388
sub munge($) {
389
join $sep,
390
map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
391
}
392
393
for (my $i = 0; $i < @ARGV - 1; $i++) {
394
$ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
395
}
396
397
$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
398
@ARGV = ("java", @ARGV);
399
print "@ARGV\n";
400
exec @ARGV;
401
402
*/
403
404