Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/bin/wildcard.c
38767 views
1
/*
2
* Copyright (c) 2005, 2013, 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
static int
104
exists(const char* filename)
105
{
106
#ifdef _WIN32
107
return _access(filename, 0) == 0;
108
#else
109
return access(filename, F_OK) == 0;
110
#endif
111
}
112
113
#define NEW_(TYPE) ((TYPE) JLI_MemAlloc(sizeof(struct TYPE##_)))
114
115
/*
116
* Wildcard directory iteration.
117
* WildcardIterator_for(wildcard) returns an iterator.
118
* Each call to that iterator's next() method returns the basename
119
* of an entry in the wildcard's directory. The basename's memory
120
* belongs to the iterator. The caller is responsible for prepending
121
* the directory name and file separator, if necessary.
122
* When done with the iterator, call the close method to clean up.
123
*/
124
typedef struct WildcardIterator_* WildcardIterator;
125
126
#ifdef _WIN32
127
struct WildcardIterator_
128
{
129
HANDLE handle;
130
char *firstFile; /* Stupid FindFirstFile...FindNextFile */
131
};
132
// since this is used repeatedly we keep it here.
133
static WIN32_FIND_DATA find_data;
134
static WildcardIterator
135
WildcardIterator_for(const char *wildcard)
136
{
137
WildcardIterator it = NEW_(WildcardIterator);
138
HANDLE handle = FindFirstFile(wildcard, &find_data);
139
if (handle == INVALID_HANDLE_VALUE) {
140
JLI_MemFree(it);
141
return NULL;
142
}
143
it->handle = handle;
144
it->firstFile = find_data.cFileName;
145
return it;
146
}
147
148
static char *
149
WildcardIterator_next(WildcardIterator it)
150
{
151
if (it->firstFile != NULL) {
152
char *firstFile = it->firstFile;
153
it->firstFile = NULL;
154
return firstFile;
155
}
156
return FindNextFile(it->handle, &find_data)
157
? find_data.cFileName : NULL;
158
}
159
160
static void
161
WildcardIterator_close(WildcardIterator it)
162
{
163
if (it) {
164
FindClose(it->handle);
165
JLI_MemFree(it->firstFile);
166
JLI_MemFree(it);
167
}
168
}
169
170
#else /* Unix */
171
struct WildcardIterator_
172
{
173
DIR *dir;
174
};
175
176
static WildcardIterator
177
WildcardIterator_for(const char *wildcard)
178
{
179
DIR *dir;
180
int wildlen = JLI_StrLen(wildcard);
181
if (wildlen < 2) {
182
dir = opendir(".");
183
} else {
184
char *dirname = JLI_StringDup(wildcard);
185
dirname[wildlen - 1] = '\0';
186
dir = opendir(dirname);
187
JLI_MemFree(dirname);
188
}
189
if (dir == NULL)
190
return NULL;
191
else {
192
WildcardIterator it = NEW_(WildcardIterator);
193
it->dir = dir;
194
return it;
195
}
196
}
197
198
static char *
199
WildcardIterator_next(WildcardIterator it)
200
{
201
struct dirent* dirp = readdir(it->dir);
202
return dirp ? dirp->d_name : NULL;
203
}
204
205
static void
206
WildcardIterator_close(WildcardIterator it)
207
{
208
if (it) {
209
closedir(it->dir);
210
JLI_MemFree(it);
211
}
212
}
213
#endif /* Unix */
214
215
static int
216
equal(const char *s1, const char *s2)
217
{
218
return JLI_StrCmp(s1, s2) == 0;
219
}
220
221
/*
222
* FileList ADT - a dynamic list of C filenames
223
*/
224
struct FileList_
225
{
226
char **files;
227
int size;
228
int capacity;
229
};
230
typedef struct FileList_ *FileList;
231
232
static FileList
233
FileList_new(int capacity)
234
{
235
FileList fl = NEW_(FileList);
236
fl->capacity = capacity;
237
fl->files = (char **) JLI_MemAlloc(capacity * sizeof(fl->files[0]));
238
fl->size = 0;
239
return fl;
240
}
241
242
243
244
static void
245
FileList_free(FileList fl)
246
{
247
if (fl) {
248
if (fl->files) {
249
int i;
250
for (i = 0; i < fl->size; i++)
251
JLI_MemFree(fl->files[i]);
252
JLI_MemFree(fl->files);
253
}
254
JLI_MemFree(fl);
255
}
256
}
257
258
static void
259
FileList_ensureCapacity(FileList fl, int capacity)
260
{
261
if (fl->capacity < capacity) {
262
while (fl->capacity < capacity)
263
fl->capacity *= 2;
264
fl->files = JLI_MemRealloc(fl->files,
265
fl->capacity * sizeof(fl->files[0]));
266
}
267
}
268
269
static void
270
FileList_add(FileList fl, char *file)
271
{
272
FileList_ensureCapacity(fl, fl->size+1);
273
fl->files[fl->size++] = file;
274
}
275
276
static void
277
FileList_addSubstring(FileList fl, const char *beg, int len)
278
{
279
char *filename = (char *) JLI_MemAlloc(len+1);
280
memcpy(filename, beg, len);
281
filename[len] = '\0';
282
FileList_ensureCapacity(fl, fl->size+1);
283
fl->files[fl->size++] = filename;
284
}
285
286
static char *
287
FileList_join(FileList fl, char sep)
288
{
289
int i;
290
int size;
291
char *path;
292
char *p;
293
for (i = 0, size = 1; i < fl->size; i++)
294
size += (int)JLI_StrLen(fl->files[i]) + 1;
295
296
path = JLI_MemAlloc(size);
297
298
for (i = 0, p = path; i < fl->size; i++) {
299
int len = (int)JLI_StrLen(fl->files[i]);
300
if (i > 0) *p++ = sep;
301
memcpy(p, fl->files[i], len);
302
p += len;
303
}
304
*p = '\0';
305
306
return path;
307
}
308
309
static FileList
310
FileList_split(const char *path, char sep)
311
{
312
const char *p, *q;
313
int len = (int)JLI_StrLen(path);
314
int count;
315
FileList fl;
316
for (count = 1, p = path; p < path + len; p++)
317
count += (*p == sep);
318
fl = FileList_new(count);
319
for (p = path;;) {
320
for (q = p; q <= path + len; q++) {
321
if (*q == sep || *q == '\0') {
322
FileList_addSubstring(fl, p, q - p);
323
if (*q == '\0')
324
return fl;
325
p = q + 1;
326
}
327
}
328
}
329
}
330
331
static int
332
isJarFileName(const char *filename)
333
{
334
int len = (int)JLI_StrLen(filename);
335
return (len >= 4) &&
336
(filename[len - 4] == '.') &&
337
(equal(filename + len - 3, "jar") ||
338
equal(filename + len - 3, "JAR")) &&
339
/* Paranoia: Maybe filename is "DIR:foo.jar" */
340
(JLI_StrChr(filename, PATH_SEPARATOR) == NULL);
341
}
342
343
static char *
344
wildcardConcat(const char *wildcard, const char *basename)
345
{
346
int wildlen = (int)JLI_StrLen(wildcard);
347
int baselen = (int)JLI_StrLen(basename);
348
char *filename = (char *) JLI_MemAlloc(wildlen + baselen);
349
/* Replace the trailing '*' with basename */
350
memcpy(filename, wildcard, wildlen-1);
351
memcpy(filename+wildlen-1, basename, baselen+1);
352
return filename;
353
}
354
355
static FileList
356
wildcardFileList(const char *wildcard)
357
{
358
const char *basename;
359
FileList fl = FileList_new(16);
360
WildcardIterator it = WildcardIterator_for(wildcard);
361
362
if (it == NULL)
363
{
364
FileList_free(fl);
365
return NULL;
366
}
367
368
while ((basename = WildcardIterator_next(it)) != NULL)
369
if (isJarFileName(basename))
370
FileList_add(fl, wildcardConcat(wildcard, basename));
371
WildcardIterator_close(it);
372
return fl;
373
}
374
375
static int
376
isWildcard(const char *filename)
377
{
378
int len = (int)JLI_StrLen(filename);
379
return (len > 0) &&
380
(filename[len - 1] == '*') &&
381
(len == 1 || IS_FILE_SEPARATOR(filename[len - 2])) &&
382
(! exists(filename));
383
}
384
385
static void
386
FileList_expandWildcards(FileList fl)
387
{
388
int i, j;
389
for (i = 0; i < fl->size; i++) {
390
if (isWildcard(fl->files[i])) {
391
FileList expanded = wildcardFileList(fl->files[i]);
392
if (expanded != NULL && expanded->size > 0) {
393
JLI_MemFree(fl->files[i]);
394
FileList_ensureCapacity(fl, fl->size + expanded->size);
395
for (j = fl->size - 1; j >= i+1; j--)
396
fl->files[j+expanded->size-1] = fl->files[j];
397
for (j = 0; j < expanded->size; j++)
398
fl->files[i+j] = expanded->files[j];
399
i += expanded->size - 1;
400
fl->size += expanded->size - 1;
401
/* fl expropriates expanded's elements. */
402
expanded->size = 0;
403
}
404
FileList_free(expanded);
405
}
406
}
407
}
408
409
const char *
410
JLI_WildcardExpandClasspath(const char *classpath)
411
{
412
char *expanded;
413
FileList fl;
414
415
if (JLI_StrChr(classpath, '*') == NULL)
416
return classpath;
417
fl = FileList_split(classpath, PATH_SEPARATOR);
418
FileList_expandWildcards(fl);
419
expanded = FileList_join(fl, PATH_SEPARATOR);
420
FileList_free(fl);
421
if (getenv(JLDEBUG_ENV_ENTRY) != 0)
422
printf("Expanded wildcards:\n"
423
" before: \"%s\"\n"
424
" after : \"%s\"\n",
425
classpath, expanded);
426
return expanded;
427
}
428
429
#ifdef DEBUG_WILDCARD
430
static void
431
FileList_print(FileList fl)
432
{
433
int i;
434
putchar('[');
435
for (i = 0; i < fl->size; i++) {
436
if (i > 0) printf(", ");
437
printf("\"%s\"",fl->files[i]);
438
}
439
putchar(']');
440
}
441
442
static void
443
wildcardExpandArgv(const char ***argv)
444
{
445
int i;
446
for (i = 0; (*argv)[i]; i++) {
447
if (equal((*argv)[i], "-cp") ||
448
equal((*argv)[i], "-classpath")) {
449
i++;
450
(*argv)[i] = wildcardExpandClasspath((*argv)[i]);
451
}
452
}
453
}
454
455
static void
456
debugPrintArgv(char *argv[])
457
{
458
int i;
459
putchar('[');
460
for (i = 0; argv[i]; i++) {
461
if (i > 0) printf(", ");
462
printf("\"%s\"", argv[i]);
463
}
464
printf("]\n");
465
}
466
467
int
468
main(int argc, char *argv[])
469
{
470
argv[0] = "java";
471
wildcardExpandArgv((const char***)&argv);
472
debugPrintArgv(argv);
473
/* execvp("java", argv); */
474
return 0;
475
}
476
#endif /* DEBUG_WILDCARD */
477
478
/* Cute little perl prototype implementation....
479
480
my $sep = ($^O =~ /^(Windows|cygwin)/) ? ";" : ":";
481
482
sub expand($) {
483
opendir DIR, $_[0] or return $_[0];
484
join $sep, map {"$_[0]/$_"} grep {/\.(jar|JAR)$/} readdir DIR;
485
}
486
487
sub munge($) {
488
join $sep,
489
map {(! -r $_ and s/[\/\\]+\*$//) ? expand $_ : $_} split $sep, $_[0];
490
}
491
492
for (my $i = 0; $i < @ARGV - 1; $i++) {
493
$ARGV[$i+1] = munge $ARGV[$i+1] if $ARGV[$i] =~ /^-c(p|lasspath)$/;
494
}
495
496
$ENV{CLASSPATH} = munge $ENV{CLASSPATH} if exists $ENV{CLASSPATH};
497
@ARGV = ("java", @ARGV);
498
print "@ARGV\n";
499
exec @ARGV;
500
501
*/
502
503