src/share/tools/launcher/wildcard.c

Fri, 29 Mar 2013 14:18:40 -0700

author
ccheung
date
Fri, 29 Mar 2013 14:18:40 -0700
changeset 4887
bad3bed4b323
parent 2327
cb2d0a362639
permissions
-rw-r--r--

8006006: [parfait] Memory leak at hotspot/src/share/tools/launcher/wildcard.c
Summary: a simple fix to add FileList_free(fl) before returning NULL.
Reviewed-by: zgu, coleenp, minqi

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

mercurial