You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by dl...@apache.org on 2007/08/12 23:09:11 UTC

svn commit: r565150 - /harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c

Author: dlydick
Date: Sun Aug 12 14:09:10 2007
New Revision: 565150

URL: http://svn.apache.org/viewvc?view=rev&rev=565150
Log:
Conditionally place 'tmparea' into CLASSPATH.

Demand absolute path names for Windows CLASSPATH entries.
Do not support relative paths: D:..\dir\name

Make classpath_isjar() more intelligent.

Comment out classpath_inner_class_adjust().

Have classpath_get_from_prchar() return (classpath_get_from_prchar).
It also calls jarutil_find_member().

Added classpath_free_search_result().

Modified:
    harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c

Modified: harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c
URL: http://svn.apache.org/viewvc/harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c?view=diff&rev=565150&r1=565149&r2=565150
==============================================================================
--- harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c (original)
+++ harmony/enhanced/sandbox/bootjvm/bootJVM/jvm/src/classpath.c Sun Aug 12 14:09:10 2007
@@ -9,8 +9,9 @@
  * into it and not depend on the argument or environment pointers
  * to always be unchanged.
  *
- * The tmparea_init() function must have been called before these
- * functions so the internal @b CLASSPATH can be set up properly.
+ * If the @link #JVMCFG_TMPAREA_IN_USE temporary directory area@endlink
+ * is in use, the tmparea_init() function must have been called before
+ * these functions so the internal @b CLASSPATH can be set up properly.
  *
  *
  * @section Control
@@ -73,10 +74,11 @@
  * Break @b CLASSPATH apart into its constituent paths.  Run once
  * during startup to parse @b CLASSPATH.  Heap management must be
  * started before calling this function via HEAP_INIT().  The
- * command line must also have been scanned via argv_init().
+ * command line must also have been scanned via jvmargv_init().
  *
- * The tmparea_init() function must have been called before these
- * functions so the internal @b CLASSPATH can be set up properly.
+ * If the @link #JVMCFG_TMPAREA_IN_USE temporary directory area@endlink
+ * is in use, the tmparea_init() function must have been called before
+ * these functions so the internal @b CLASSPATH can be set up properly.
  *
  *
  * @param  argc    Number of arguments on command line
@@ -118,13 +120,20 @@
     rint pathcount;
 
     /*
-     * Prepare to concatenate the temp directory area with actual
-     * @b CLASSPATH, followed by potential
+     * Prepare to concatenate startup JAR file and the
+     * possible temporary directory area 'tmparea' with
+     * actual @b CLASSPATH, followed by potential
      * CONFIG_HACKED_xxx definitions.
      */
-    rchar *tmpclasspath;             /* @b CLASSPATH dlm */
-    rint tmpcplen =
+    rchar *moreclasspath;             /* @b CLASSPATH dlm */
+    rint morecplen;
+    morecplen = (pjvm->startjar)
+                ? (portable_strlen(pjvm->startjar) + sizeof(rchar))
+                : 0;
+    morecplen +=
+#if JVMCFG_TMPAREA_IN_USE
         portable_strlen(tmparea_get())   + sizeof(rchar)   +
+#endif
         portable_strlen(pjvm->classpath) + sizeof(rchar);
 
     /*
@@ -133,89 +142,114 @@
      */
 #ifdef CONFIG_HACKED_BOOTCLASSPATH
                                                  /* @b CLASSPATH dlm */
-    tmpcplen +=
+    morecplen +=
         portable_strlen(CONFIG_HACKED_BOOTCLASSPATH) + sizeof(rchar);
 #endif
 #ifdef CONFIG_HACKED_RTJARFILE
 
     /* For $JAVA_HOME/$CONFIG_HACKED_RTJARFILE */
-    tmpcplen += portable_strlen(pjvm->java_home);
-    tmpcplen += sizeof(rchar);
-    tmpcplen += portable_strlen(CONFIG_HACKED_RTJARFILE) +sizeof(rchar);
+    morecplen += portable_strlen(pjvm->java_home);
+    morecplen += sizeof(rchar);
+    morecplen += portable_strlen(CONFIG_HACKED_RTJARFILE)+sizeof(rchar);
 #endif
-    tmpcplen += sizeof(rchar);/* NUL byte, possibly 1 more than needed*/
+    morecplen += sizeof(rchar);/*NUL byte, possibly 1 more than needed*/
 
     /*
      * Allocate space for classpath image with temp area and
      * possible CONFIG_HACKED_xxx adjustments
      */
-    tmpclasspath = HEAP_GET_DATA(tmpcplen, rfalse);
+    moreclasspath = HEAP_GET_DATA(morecplen, rfalse);
 
     /*
      * Generate concatenation of
      *
-     * pjvm->TMPAREA:classpath:
-@link #CONFIG_HACKED_BOOTCLASSPATH CONFIG_HACKED_BOOTCLASSPATH@endlink:
-     * @link #CONFIG_HACKED_RTJARFILE CONFIG_HACKED_RTJARFILE@endlink
+     * 1 pjvm->startjar:
+     * 2 pjvm->tmparea:
+     * 3 CLASSPATH:
+     * 4 @link #CONFIG_HACKED_BOOTCLASSPATH
+                CONFIG_HACKED_BOOTCLASSPATH@endlink:
+     * 5 @link #CONFIG_HACKED_RTJARFILE CONFIG_HACKED_RTJARFILE@endlink
      */
-    portable_strcpy(tmpclasspath, tmparea_get());
-    i = portable_strlen(tmpclasspath);
-    tmpclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
-    tmpclasspath[i + 1] = '\0';
 
-    portable_strcat(tmpclasspath, pjvm->classpath);
+    moreclasspath[0] = '\0';
+
+    if (pjvm->startjar) /* When using '-jar start.class.jar.file' form*/
+    {
+         portable_strcat(moreclasspath, pjvm->startjar);
+         i = portable_strlen(moreclasspath);
+         moreclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
+         moreclasspath[i + 1] = '\0';
+    }
+#if JVMCFG_TMPAREA_IN_USE
+    portable_strcat(moreclasspath, tmparea_get());
+    i = portable_strlen(moreclasspath);
+    moreclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
+    moreclasspath[i + 1] = '\0';
+#endif
+
+    portable_strcat(moreclasspath, pjvm->classpath);
 
 #ifdef CONFIG_HACKED_BOOTCLASSPATH
-     i = portable_strlen(tmpclasspath);
-    tmpclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
-    tmpclasspath[i + 1] = '\0';
-    portable_strcat(tmpclasspath, CONFIG_HACKED_BOOTCLASSPATH);
+    i = portable_strlen(moreclasspath);
+    moreclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
+    moreclasspath[i + 1] = '\0';
+    portable_strcat(moreclasspath, CONFIG_HACKED_BOOTCLASSPATH);
 #endif
+
 #ifdef CONFIG_HACKED_RTJARFILE
-     i = portable_strlen(tmpclasspath);
-    tmpclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
-    tmpclasspath[i + 1] = '\0';
-    portable_strcat(tmpclasspath, pjvm->java_home);
-
-     i = portable_strlen(tmpclasspath);
-    tmpclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
-    tmpclasspath[i + 1] = '\0';
-    portable_strcat(tmpclasspath, CONFIG_HACKED_RTJARFILE);
+    i = portable_strlen(moreclasspath);
+    moreclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
+    moreclasspath[i + 1] = '\0';
+    portable_strcat(moreclasspath, pjvm->java_home);
+
+    i = portable_strlen(moreclasspath);
+    moreclasspath[i] = CLASSPATH_ITEM_DELIMITER_CHAR;
+    moreclasspath[i + 1] = '\0';
+    portable_strcat(moreclasspath, CONFIG_HACKED_RTJARFILE);
 #endif
     HEAP_FREE_DATA(pjvm->classpath); /* May or may not be on heap */
-    pjvm->classpath = tmpclasspath;  /* Keep for duration of pgm run */
-    
+    pjvm->classpath = moreclasspath;  /* Keep for duration of pgm run */
+
+    rint tcplen = portable_strlen(moreclasspath);
+
 
     /* @warning  NON-STANDARD TERMINATION CONDITION <= VERSUS < */
-    for (i = 0, pathcount = 0; i <= portable_strlen(tmpclasspath); i++)
+    for (i = 0, pathcount = 0; i <= tcplen; i++)
     {
-        if ((CLASSPATH_ITEM_DELIMITER_CHAR == tmpclasspath[i]) ||
-            (i == portable_strlen(tmpclasspath)))
+        if ((CLASSPATH_ITEM_DELIMITER_CHAR == moreclasspath[i]) ||
+            (i == tcplen))
         {
             pathcount++;
         }
     }
 
-
-    /* Allocate space for list of @b CLASSPATH entries */
+    /* Allocate space for list of @b CLASSPATH entries, and using
+     * /absolute/path/names */
     classpath_list = HEAP_GET_DATA(pathcount * sizeof(rchar *), rtrue);
 
     rchar *nextpath;
     rint  thislen;
     classpath_list_len = 0;
 
+    /*!
+     * @todo  HARMONY-6-jvm-classpath.c-7 Check `pwd` overflow
+     *        and @link #rnull rnull@endlink returned
+     */
+    rchar *pwd = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
+    portable_getwd(pwd);
+    portable_strcat(pwd, JVMCFG_PATHNAME_DELIMITER_STRING);
+    rint   pwdlen = portable_strlen(pwd);
+
     /* @warning  NON-STANDARD TERMINATION CONDITION <= VERSUS < */
-    for (i = 0, nextpath = tmpclasspath;
-         i <= portable_strlen(tmpclasspath);
-         i++)
+    for (i = 0, nextpath = moreclasspath; i <= tcplen; i++)
     {
 
         /* If found item delimiter OR END OF STRING (SEE ABOVE) */
-        if ((CLASSPATH_ITEM_DELIMITER_CHAR == tmpclasspath[i]) ||
-            (i == portable_strlen(tmpclasspath)))
+        if ((CLASSPATH_ITEM_DELIMITER_CHAR == moreclasspath[i]) ||
+            (i == tcplen))
         {
             /* calculate length of this @b CLASSPATH entry */
-            thislen = (&tmpclasspath[i]) - nextpath;
+            thislen = (&moreclasspath[i]) - nextpath;
 
             /*
              * Ignore double-delimiter cases.
@@ -227,33 +261,91 @@
             if (0 == thislen)
             {
                 /* Pretend it was valid */
-                nextpath = &tmpclasspath[i + 1];
+                nextpath = &moreclasspath[i + 1];
                 continue;
             }
 
             /*
              * Allocate enough space for item, plus final '\0'.
+             * Add space for prefixed PWD if not already absolute.
+             * (For Windows, paths less than 3 characters cannot contain
+             *  'VOLUME:\...' form and so are copied directly.)
              * Since we are scanning for a delimiter or EOS,
              * the current length calculation includes the "1 + x"
              * for the '\0'.  The string[x] location is set to '\0'.
+             *
+             * If the path is of the form,
+             * /absolute/path/name or C:\absolute\path\name then
+             * simply copy it.  Otherwise prefix /present/working/dir
+             * to make it absolute.
+             *
+             * Do not support Windows relative paths with volume
+             * prefix:  D:..\dir\name
+             *
+             */
+
+            /*!
+             * @todo HARMONY-6-jvm-classpath.c-8 Document the lack of
+             * support for Windows relative paths with volume
+             * prefix:  D:..\\dir\\name
+             *
              */
-            classpath_list[classpath_list_len] =
-                HEAP_GET_DATA(thislen + sizeof(rchar), rfalse);
+            if (
+#if defined(CONFIG_WINDOWS) || defined(CONFIG_CYGWIN)
+                (
+                 (3 > thislen)                                   ||
+                 (isalpha(nextpath[0])                      &&
+                  (JVMCFG_PATHNAME_VOLUME_DELIMITER_CHAR ==
+                   nextpath[1])                             &&
+                  (JVMCFG_PATHNAME_DELIMITER_CHAR ==
+                   nextpath[2])))
+#if defined(CONFIG_CYGWIN)
+                                                                      ||
+                (JVMCFG_PATHNAME_ALT_DELIMITER_CHAR == nextpath[0]) 
+#endif
+#else
+                JVMCFG_PATHNAME_DELIMITER_CHAR == nextpath[0]
+#endif
+               )
+            {
+                classpath_list[classpath_list_len] =
+                    HEAP_GET_DATA(thislen + sizeof(rchar), rfalse);
+                /* Store current @b CLASSPATH item, incl. final '\0' */
+                portable_memcpy(classpath_list[classpath_list_len],
+                                nextpath, 
+                                thislen);
+                classpath_list[classpath_list_len][thislen] = '\0';
+            }
+            else
+            {
+                classpath_list[classpath_list_len] =
+                    HEAP_GET_DATA(thislen + pwdlen + sizeof(rchar),
+                                  rfalse);
+
+                portable_strcpy(classpath_list[classpath_list_len],
+                                pwd);
+
+                /* Store current @b CLASSPATH item, incl. final '\0' */
+                portable_memcpy(&classpath_list[classpath_list_len]
+                                               [pwdlen],
+                                nextpath, 
+                                thislen);
+                classpath_list[classpath_list_len][thislen + pwdlen] =
+                                                                   '\0';
+            }
 
-            /* Store current @b CLASSPATH item, including final '\0' */
-            portable_memcpy(classpath_list[classpath_list_len],
-                            nextpath, 
-                            thislen);
-            classpath_list[classpath_list_len][thislen] = '\0';
             classpath_list_len++;
 
             /* Start looking at next @b CLASSPATH item */
-            nextpath = &tmpclasspath[i + 1];
+            nextpath = &moreclasspath[i + 1];
 
-        } /* if tmpclasspath[i] */
+        } /* if moreclasspath[i] */
 
     } /* for i */
 
+    /* Clean up */
+    HEAP_FREE_DATA(pwd);
+
     /* Declare this module initialized */
     jvm_classpath_initialized = rtrue;
 
@@ -268,7 +360,8 @@
  *
  * A JAR file will be named @c @b /path/name/filename.jar, while a
  * file name in a directory will be named
- * @c @b /path/name/ClassName.class .
+ * @c @b /path/name/ClassName.class .  A JAR file may also be
+ * named @c @b /path/name/filename.zip for legacy reasons.
  *
  *
  * @param  pclasspath  String from @b CLASSPATH list
@@ -282,37 +375,42 @@
 {
     ARCH_FUNCTION_NAME(classpath_isjar);
 
-    rint len, jarlen;
+    rint len, jarlen, ext;
 
-    /* Lengths of test string and of JAR extension (w/ name.ext dlm) */
-    len = portable_strlen(pclasspath);
-    jarlen = portable_strlen(JVMCFG_EXTENSION_DELIMITER_STRING) +
-             portable_strlen(CLASSFILE_EXTENSION_JAR);
+    rchar *ext_list[2] = { CLASSFILE_EXTENSION_JAR,
+                           CLASSFILE_EXTENSION_ZIP };
 
-    /* For VERY short @b CLASSPATH entries, it cannot be a JAR file */
-    if (jarlen >= len)
+    for (ext = 0; ext < 2; ext++)
     {
-        return(rfalse);
-    }
+        /* Lengths of test string and of extension (w/ name.ext dlm) */
+        len = portable_strlen(pclasspath);
+        jarlen = portable_strlen(JVMCFG_EXTENSION_DELIMITER_STRING) +
+                 portable_strlen(ext_list[ext]);
 
-    /* Check if name.ext delimiter present in test string */
-    if (JVMCFG_EXTENSION_DELIMITER_CHAR != pclasspath[len - jarlen])
-    {
-        return(rfalse);
-    }
+        /* For VERY short @b CLASSPATH entries,it cannot be a JAR file*/
+        if (jarlen >= len)
+        {
+            continue;
+        }
 
-    /* Now go test JAR extension since delimiter is present */
-    jarlen--;
-    if (0 == portable_strncmp(&pclasspath[len - jarlen],
-                              CLASSFILE_EXTENSION_JAR,
-                              jarlen))
-    {
-        return(rtrue);
-    }
-    else
-    {
-        return(rfalse);
-    }
+        /* Check if name.ext delimiter present in test string */
+        if (JVMCFG_EXTENSION_DELIMITER_CHAR != pclasspath[len - jarlen])
+        {
+            continue;
+        }
+
+        /* Now go test JAR extension since delimiter is present */
+        jarlen--;
+        if (0 == portable_strncmp(&pclasspath[len - jarlen],
+                                  ext_list[ext],
+                                  jarlen))
+        {
+            return(rtrue);
+        }
+    } /* for ext */
+
+    /* JAR extension not found in list */
+    return(rfalse);
 
 } /* END of classpath_isjar() */
 
@@ -387,6 +485,7 @@
 } /* END of classpath_external2internal_classname_inplace() */
 
 
+#if 0
 /*!
  * @brief Adjust class name string for shell expansion artifacts.
  *
@@ -455,6 +554,7 @@
     return(outbfr);
 
 } /* END of classpath_inner_class_adjust() */
+#endif
 
 
 /*!
@@ -475,20 +575,28 @@
  * to search for classes.
  *
  *
- * @param  clsname  Name of class, without @c @b .class
- *                  extension, as either @c @b some.class.name
- *                  or @c @b some/class/name , that is,
- *                  the internal form of the class name.  The string
- *                  may or may not contain class formatting of the
- *                  form @c @b [[[Lsome/class/name;
- *
- *
- * @returns Heap pointer into @b CLASSPATH of directory or JAR file
- *          containing class (for a regular .class file).
- *          For a JAR file, report the name of the .jar file
- *          as for a .class file, but also call classpath_isjar()
- *          to distinguish between them.  Thus the usage is,
- *          Return @link #rnull rnull@endlink if no match.
+ * @param  clsname  Name of class, without @c @b .class extension, as
+ *                  as either @c @b some.package.name.SomeClassName
+ *                  or @c @b some/package/name/SomeClassName , that
+ *                  is, the external and internal forms of the class
+ *                  name, respectively.  The string may or may not
+ *                  contain class formatting of the form
+ *                  @c @b [[[Lsome/package/name/SomeClassName;
+ *
+ *
+ * @returns Heap pointer containing @b CLASSPATH search result.  This
+ *          result will be a non-null pointer in one member of this
+ *          structure which will indicate either a JAR file member or
+ *          a simple class file.  If result is a class file, simply
+ *          open it, read, and close.  If it is a JAR file member, read
+ *          it with jarutil_read_current_member(), retrieve its buffer
+ *          pointer, and close it.  In both cases, free the indicated
+ *          pointer when done.  After this, free the heap pointer
+ *          that was returned.  (In other words, @e two heap pointers
+ *          will need to be freed when done with the result.)  If the
+ *          returned heap pointer was @link #rnull rnull@endlink,
+ *          then the class was not found in the @b CLASSPATH and an
+ *          error needs to be indicated.
  *
  * @todo HARMONY-6-jvm-classpath.c-2 VM Spec section 5.3.1:  Throw
  *       @b NoClassDeffoundError if no match.
@@ -501,27 +609,9 @@
  *       no <b><code>package some.package.name</code></b> statement
  *       in source.
  *
- * @verbatim
-               rchar *p = classpath_get_from_prchar(
-                                     "some/package/name/SomeClassName");
-  
-               if (rnull != p)
-               {
-             
-                   if (rtrue == classpath_isjar(p))
-                   {
-                       ** Extract class from JAR file **
-                   }
-                   else
-                   {
-                       ** Read class file directly **
-                   }
-               }
-   @endverbatim
- *
  */
 
-rchar *classpath_get_from_prchar(rchar *clsname)
+classpath_search *classpath_get_from_prchar(rchar *clsname)
 {
     ARCH_FUNCTION_NAME(classpath_get_from_prchar);
 
@@ -531,13 +621,12 @@
     rchar *name;
     int baselen;
 
-    rchar *class_location = HEAP_GET_DATA(JVMCFG_PATH_MAX, rfalse);
-
     if (rtrue == nts_prchar_isclassformatted(clsname))
     {
         /*
          * Convert @c @b [[[Lpath/name/ClassName; into
-         * @c @b path/name/ClassName
+         * @c @b path/name/ClassName form using array dimensions plus
+         * data type specifier character 'L' (ie, add 1)
          */
         jvm_array_dim arraydims = nts_get_prchar_arraydims(clsname);
         name = &clsname[1 + arraydims];
@@ -564,7 +653,17 @@
         baselen = portable_strlen(name);
     }
 
+    /*
+     * Allocate result structure, zero it out since one member
+     * must be NULL upon return.
+     */
+    classpath_search *rc =HEAP_GET_DATA(sizeof(classpath_search),rtrue);
+
+    rchar *class_location = HEAP_GET_DATA(JVMCFG_PATH_MAX, rfalse);
+
+#if 0
     rchar *jarscript = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
+#endif
 
     /*
      * Search through each entry in @b CLASSPATH for a file by
@@ -573,185 +672,109 @@
 
     for (i = 0; i < classpath_list_len; i++)
     {
-        int clen;
-
         /* Test for JAR files in @b CLASSPATH */
         if (rtrue == classpath_isjar(classpath_list[i]))
         {
             /* Convert input parm to internal form, append suffix */
-            portable_strcpy(class_location, name);
-            clen = portable_strlen(class_location);
+            portable_strncpy(class_location, name, baselen);
+            class_location[baselen] = '\0';
+
             (rvoid) classpath_external2internal_classname_inplace(
                                                         class_location);
-            class_location[clen] = JVMCFG_EXTENSION_DELIMITER_CHAR;
-            class_location[clen + 1] = '\0';
+            class_location[baselen] = JVMCFG_EXTENSION_DELIMITER_CHAR;
+            class_location[baselen + 1] = '\0';
             portable_strcat(class_location,
                             CLASSFILE_EXTENSION_DEFAULT);
 
-            rchar *inner_class_location =
-                classpath_inner_class_adjust(class_location);
-
-            /*!
-             * @internal Build up JAR command using internal class name
-             *           with suffix.  Make @e sure all files are
-             *           writeable for final <b><code>rm -rf</code></b>.
-             */
-            sprintfLocal(jarscript,
-                         JVMCFG_JARFILE_DATA_EXTRACT_SCRIPT,
-                         tmparea_get(),
-                         pjvm->java_home,
-                         pjvm->java_home,
-                         JVMCFG_PATHNAME_DELIMITER_CHAR,
-                         classpath_list[i],
-                         inner_class_location);
-
-#if defined(CONFIG_WINDOWS) || defined(CONFIG_CYGWIN)
-
+            jar_state *pjs = jarutil_find_member(classpath_list[i],
+                                                 class_location,
+                                                 HEAP_GET_DATA,
+                                                 HEAP_FREE_DATA);
             /*
-             * @todo HARMONY-6-jvm-classpath.c-3
-             *   gmj : awful hack - need to escape out every \ in paths
-             *   or it doesn't seem to get across into the batch file
-             *   correctly
+             * Ignore this @b CLASSPATH entry if something was wrong
+             * with an input parameter, either the @b CLASSPATH entry
+             * itself or the @b clsname.
              */
-            rchar *fixscript = HEAP_GET_DATA(JVMCFG_SCRIPT_MAX, rfalse);
-
-            char *buffptr = fixscript;
-            char *jarscriptPtr = jarscript;
-
-            char c;
-            while((c = *jarscriptPtr++))
+            if (rnull == pjs)
             {
-                *buffptr++ = c;
-
-#if defined(CONFIG_WINDOWS)
-                if (c == JVMCFG_PATHNAME_DELIMITER_CHAR)
-                {
-                    *buffptr++ = JVMCFG_PATHNAME_DELIMITER_CHAR;
-                }
-#endif
-#if defined(CONFIG_CYGWIN)
-                /*
-                 * CygWin can have both--
-                 *    such as C:\\path\\name/more/path/name
-                 */
-                if (c == JVMCFG_PATHNAME_ALT_DELIMITER_CHAR)
-                {
-                    *buffptr++ = JVMCFG_PATHNAME_ALT_DELIMITER_CHAR;
-                }
-#endif
+                continue;
             }
-            *buffptr = '\0';
-
-            portable_strcpy(jarscript, fixscript);
-            HEAP_FREE_DATA(fixscript);
-
-#endif
-
-            HEAP_FREE_DATA(inner_class_location);
 
-            int rc = portable_system(jarscript);
-
-            if (0 != rc)
+            /* If match found, report to caller.  Else keep looking */
+            if (pjs->jar_code != JAR_OKAY)
             {
-                sysErrMsg(arch_function_name,
-                          "Cannot extract '%s' from JAR file %s",
-                          inner_class_location,
-                          classpath_list[i]);
-
-                HEAP_FREE_DATA(class_location);
-                HEAP_FREE_DATA(jarscript);
+                if (JAR_MEMBER_IMPOSSIBLE_OPEN_FD != pjs->fd)
+                {
+                    portable_close(pjs->fd);
+                }
 
-                exit_jvm(EXIT_CLASSPATH_JAR);
-/*NOTREACHED*/
+                HEAP_FREE_DATA(pjs);
+                continue;
             }
 
-            /*
-             * @todo  HARMONY-6-jvm-classpath.c-4 Make sure that this
-             *        sprintf/stat works with both CONFIG_WINDOWS and
-             *        CONFIG_CYGWIN.
-             *
-             */
-
-            /* Location of extracted file */
-            sprintfLocal(jarscript,
-                         "%s%c%s",
-                         tmparea_get(),
-                         JVMCFG_PATHNAME_DELIMITER_CHAR,
-                         class_location);
-
-            statbfr = portable_stat(jarscript);
-            HEAP_FREE_DATA(statbfr);
-
-            /*
-             * If file was extracted, report result
-             * in heap-allocated bfr
-             */
-            if (rnull != statbfr)
-            {
-                HEAP_FREE_DATA(class_location);
+            HEAP_FREE_DATA(class_location);
 
-                return(jarscript);
-            }
+            rc->jarfile_member_state = pjs;
 
-            HEAP_FREE_DATA(jarscript);
+            return(rc);
         }
         else
         {
-            /*
-             * @todo  HARMONY-6-jvm-classpath.c-4 Make sure that this
+            /*!
+             * @todo  HARMONY-6-jvm-classpath.c-6 Make sure that this
              *        sprintf/stat works with both CONFIG_WINDOWS and
              *        CONFIG_CYGWIN.
              *
              */
 
-            /* Convert input parm to internal form */
+            /* Convert input parm (directory name) to internal form */
             sprintfLocal(class_location,
                          "%s%c\0",
                          classpath_list[i],
                          JVMCFG_PATHNAME_DELIMITER_CHAR);
 
-            clen = portable_strlen(class_location);
+            int clen = portable_strlen(class_location);
 
             portable_strcat(class_location, name);
 
             /*
              * Convert input parm to internal format and append
              * class suffix, but convert @e only the @b name part
-             * just appended, and not if if it is a JAR file.
+             * just appended.
              */
-            if (rfalse == classpath_isjar(class_location))
-            {
-                (rvoid) classpath_external2internal_classname_inplace(
+            (rvoid) classpath_external2internal_classname_inplace(
                                                  &class_location[clen]);
 
 
-                class_location[clen + baselen] =
+            class_location[clen + baselen] =
                                         JVMCFG_EXTENSION_DELIMITER_CHAR;
-                class_location[clen + baselen + 1] = '\0';
+            class_location[clen + baselen + 1] = '\0';
 
-                portable_strcat(class_location,
-                                CLASSFILE_EXTENSION_DEFAULT);
-            }
+            portable_strcat(class_location,CLASSFILE_EXTENSION_DEFAULT);
 
             /* Test for existence of valid class file */
             statbfr = portable_stat(class_location);
             HEAP_FREE_DATA(statbfr);
 
-            /* If match found, report result in heap-allocated bfr */
-            if (rnull != statbfr)
+            /* If match found, report to caller.  Else keep looking */
+            if (rnull == statbfr)
             {
-                HEAP_FREE_DATA(jarscript);
-
-                return(class_location);
+                HEAP_FREE_DATA(class_location);
             }
+
+            rc->classfile_name = class_location;
+
+            return(rc);
         }
     } /* for i */
 
     /* Class not found in @b CLASSPATH */
     HEAP_FREE_DATA(class_location);
+#if JVMCFG_TMPAREA_IN_USE
     HEAP_FREE_DATA(jarscript);
+#endif
 
-    return((rchar *) rnull);
+    return((classpath_search *) rnull);
 
 } /* END of classpath_get_from_prchar() */
 
@@ -770,30 +793,72 @@
  *
  * @param  clsname  Name of class, without @c @b .class
  *                  extension, as either @c @b some.class.name
- *                  or @c @b some/class/name , that is,
- *                  the internal form of the class name.  The string
+ *                  or @c @b some/package/name/SomePackageName , that
+ *                  is, the internal form of the class name.  The string
  *                  may or may not contain class formatting of the
- *                  form @c @b [[[Lsome/class/name;
+ *                  form @c @b [[[Lsome/package/name/SomeClassName;
  *
  *
- * @returns Heap pointer into @b CLASSPATH of directory or JAR file
- *          containing class (for a regular .class file).
+ * @returns Heap pointer containing @b CLASSPATH search result.  If
+ *          result is a class file, simply open it, read, and close.
+ *          If it is a JAR file member, read it with
+ *          jarutil_read_current_member(), retrieve its buffer pointer,
+ *          and close it.
  *
  */
 
-rchar *classpath_get_from_cp_entry_utf(cp_info_mem_align *clsname)
+classpath_search *classpath_get_from_cp_entry_utf(cp_info_mem_align
+                                                               *clsname)
 {
     ARCH_FUNCTION_NAME(classpath_get_from_cp_entry_utf);
 
     rchar *prchar_clsname = utf_utf2prchar(PTR_THIS_CP_Utf8(clsname));
 
-    rchar *rc = classpath_get_from_prchar(prchar_clsname);
+    classpath_search *rc = classpath_get_from_prchar(prchar_clsname);
 
     HEAP_FREE_DATA(prchar_clsname);
 
     return(rc);
 
 } /* END of classpath_get_from_cp_entry_utf() */
+
+
+/*!
+ * @brief Free up @b CLASSPATH search result pointer
+ *
+ * This structure contains two pointers, one of which is always NULL.
+ * Free the other one by attempting to free any non-NULL pointer, then
+ * free the enclosing structure pointer.
+ *
+ * 
+ * @param pcpsr Heap pointer containing @b CLASSPATH search result to
+ *              be freed.
+ *
+ * @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid classpath_free_search_result(classpath_search *pcpsr)
+{
+    /* Nothing to do if NULL pointer */
+    if (rnull == pcpsr)
+    {
+        return;
+    }
+
+    if (rnull != pcpsr->classfile_name)
+    {
+        HEAP_FREE_DATA(pcpsr->classfile_name);
+    }
+
+    if (rnull != pcpsr->jarfile_member_state)
+    {
+        HEAP_FREE_DATA(pcpsr->jarfile_member_state);
+    }
+
+    HEAP_FREE_DATA(pcpsr);
+    return;
+
+} /* END of classpath_free_search_result() */
 
 
 /*!