For Review: Sanitise Use of DIR_SEPARATOR in the Front-End

Ranjit Mathew rmathew@hotmail.com
Tue Jan 28 18:41:00 GMT 2003


Hi,

     As I had pointed out in an earlier mail to this list, the Java
front-end assumes that there's only a single DIR_SEPARATOR for a
host. As a result, class files are being generated in the wrong
folder if '\' is used instead of '/' to separate folders on Win32.
(MinGW defines DIR_SEPARATOR to be '/' and DIR_SEPARATOR_2 to be '\'.)

I have tried to track down and fix some of these issues (in the 3.3
front-end) and present the proposed changes below - if these changes
are acceptable, I'll resubmit them as a patch to the java-patches
(as well as the gcc-patches) list. (Yes Andrew, I'll use the
"diff -c2p" form there. ;-))

If any of this looks pathetic to you, do be nice enough to point
out a better way of achieving the same. (The strcasecmp( ) thing
makes the code look ugly - perhaps we can use a function pointer
there?)

And yes, it does fix the class file destination problem noted above.

In addition, I found a small issue with assuming a case-sensitive
filesystem while scanning the classpath for ZIP or JAR files,
and have included the fix for the same.

The rules I followed are:

1. Do not assume just DIR_SEPARATOR, be prepared for a *possible*
    DIR_SEPARATOR_2.

2. Just use the IS_DIR_SEPARATOR( ) macro instead of directly
    comparing against DIR_SEPARATOR, as it correctly handles both
    DIR_SEPARATOR and DIR_SEPARATOR_2.

3. When comparing file names or name components, check if we have
    a case-insensitive filesystem (HAVE_DOS_BASED_FILESYSTEM) and
    strcasecmp( ) (HAVE_STRCASECMP) to do the comparison.


Short Descriptions:

     jcf-io.c (cached_stat): Check additionally for DIR_SEPARATOR_2
     while determining the folder of a file from its name.
     Remember which separator is used in the name of the file.
     Correct minor typos.

     jcf-path.c (add_entry): If on a case-insensitive filesystem
     and have strcasecmp( ), check for ZIP and JAR extensions in
     file names case-insensitively.
     (add_entry): Just use IS_DIR_SEPARATOR instead of explicitly
     checking against '/' and then DIR_SEPARATOR.

     jcf-write.c (make_class_file_name): Check additionally for
     DIR_SEPARATOR_2 while finding the folder of a file.
     Remember which separator is used and use it instead of DIR_SEPARATOR.


-------------------------------- 8< --------------------------------
--- jcf-io.c	2003-01-27 21:33:40.000000000 +0530
+++ jcf-io.c	2003-01-27 21:44:30.000000000 +0530
@@ -344,4 +344,5 @@
  #if JCF_USE_SCANDIR
    char *sep;
+  char origsep;
    char *base;
    memoized_dirlist_entry *dent;
@@ -357,6 +358,11 @@
    /* Get the name of the directory.  */
    sep = strrchr (filename, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+  if (! sep)
+    sep = strrchr (filename, DIR_SEPARATOR_2);
+#endif
    if (sep)
      {
+      origsep = *sep;
        *sep = '\0';
        base = sep + 1;
@@ -365,5 +371,5 @@
      base = filename;

-  /* Obtain the entry for this directory form the hash table.  */
+  /* Obtain the entry for this directory from the hash table.  */
    slot = htab_find_slot (memoized_dirlists, filename, INSERT);
    if (!*slot)
@@ -386,7 +392,7 @@
      dent = *((memoized_dirlist_entry **) slot);

-  /* Put the spearator back.  */
+  /* Put the separator back.  */
    if (sep)
-    *sep = DIR_SEPARATOR;
+    *sep = origsep;

    /* If the file is not in the list, there is no need to stat it; it
--- jcf-path.c	2003-01-27 21:43:44.000000000 +0530
+++ jcf-path.c	2003-01-28 20:28:07.000000000 +0530
@@ -149,6 +149,12 @@

    len = strlen (filename);
+
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM) && defined (HAVE_STRCASECMP)
+  if (len > 4 && (strcasecmp (filename + len - 4, ".zip") == 0
+		  || strcasecmp (filename + len - 4, ".jar") == 0))
+#else
    if (len > 4 && (strcmp (filename + len - 4, ".zip") == 0
  		  || strcmp (filename + len - 4, ".jar") == 0))
+#endif
      {
        n->flags |= FLAG_ZIP;
@@ -157,5 +163,9 @@
  	 way.  Symlinks will fool this test.  This is only used for
  	 -MM and -MMD, so it probably isn't terribly important.  */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM) && defined (HAVE_STRCASECMP)
+      if (! strcasecmp (filename, LIBGCJ_ZIP_FILE))
+#else
        if (! strcmp (filename, LIBGCJ_ZIP_FILE))
+#endif
  	n->flags |= FLAG_SYSTEM;
      }
@@ -164,5 +174,5 @@
       This is a little hack that lets the searching code in jcf-io.c
       work more easily.  Eww.  */
-  if (filename[len - 1] != '/' && filename[len - 1] != DIR_SEPARATOR)
+  if (! IS_DIR_SEPARATOR (filename[len - 1]))
      {
        char *f2 = alloca (len + 2);
@@ -379,5 +389,5 @@
  					     + strlen (direntp->d_name) + 2);
  			strcpy (name, buf);
-			if (name[dirname_length-1] != DIR_SEPARATOR)
+			if (! IS_DIR_SEPARATOR (name[dirname_length-1]))
  			  {
  			    name[dirname_length] = DIR_SEPARATOR;
--- jcf-write.c	2003-01-27 21:46:11.000000000 +0530
+++ jcf-write.c	2003-01-28 22:59:04.000000000 +0530
@@ -3338,4 +3338,5 @@
    char *r;
    struct stat sb;
+  char sep;

    cname = IDENTIFIER_POINTER (identifier_subst (DECL_NAME (TYPE_NAME (clas)),
@@ -3349,9 +3350,17 @@
        dname = DECL_SOURCE_FILE (TYPE_NAME (clas));
        slash = strrchr (dname, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+      if (! slash)
+        slash = strrchr (dname, DIR_SEPARATOR_2);
+#endif
        if (! slash)
  	{
-	  dname = ".";
-	  slash = dname + 1;
+          dname = ".";
+          slash = dname + 1;
+          sep = DIR_SEPARATOR;
  	}
+      else
+        sep = *slash;
+
        t = strrchr (cname, DIR_SEPARATOR);
        if (t)
@@ -3360,5 +3369,18 @@
    else
      {
+      char *s;
+
        dname = jcf_write_base_directory;
+
+      s = strrchr (dname, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+      if (! s)
+        s = strrchr (dname, DIR_SEPARATOR_2);
+#endif
+      if (s)
+        sep = *s;
+      else
+        sep = DIR_SEPARATOR;
+
        slash = dname + strlen (dname);
      }
@@ -3366,5 +3388,5 @@
    r = xmalloc (slash - dname + strlen (cname) + 2);
    strncpy (r, dname, slash - dname);
-  r[slash - dname] = DIR_SEPARATOR;
+  r[slash - dname] = sep;
    strcpy (&r[slash - dname + 1], cname);

@@ -3378,5 +3400,5 @@
    while (1)
      {
-      char *s = strchr (dname, DIR_SEPARATOR);
+      char *s = strchr (dname, sep);
        if (s == NULL)
  	break;
@@ -3387,7 +3409,7 @@
  	fatal_io_error ("can't create directory %s", r);

-      *s = DIR_SEPARATOR;
+      *s = sep;
        /* Skip consecutive separators.  */
-      for (dname = s + 1; *dname && *dname == DIR_SEPARATOR; ++dname)
+      for (dname = s + 1; *dname && *dname == sep; ++dname)
  	;
      }
-------------------------------- 8< --------------------------------

Sincerely Yours,
Ranjit

-- 
Ranjit Mathew        Email: rmathew AT hotmail DOT com
Bangalore,
INDIA.               Web: http://ranjitmathew.tripod.com/




More information about the Java mailing list