This is the mail archive of the java-patches@sources.redhat.com mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: File.createTempFile fixes



This patch sets the java.io.tmpdir property based on the TMPDIR
environment variable.

It also revamps temp file creation to obey the specified directory and
close the FileDescriptor once created.  Parts of it come from GNU
Classpath.

The 1.3 docs says that createTempFile throws an exception if "a
security manager exists and its
SecurityManager.checkWrite(java.io.FileDescriptor) method does not
allow a file to be created".  I'm confused.  Doesn't the fact that we
have a FileDescriptor mean the file has been created already?  I
decided to split up the test for existance and file creation.  I used
SecurityManager.checkWrite(String) in the middle.  Comments?


2000-09-04  Anthony Green  <green@redhat.com>

	Fix for PR java.io/203:
	* java/io/File.java (createTempFile): Obey directory argument.
	Use java.io.tmpdir if needed.  Don't leave FileDescripators open.
	* java/lang/natSystem.cc (init_properties): Use TMPDIR environment
	variable to set java.io.tmpdir on non-WIN32 systems.


Index: java/lang/natSystem.cc
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/lang/natSystem.cc,v
retrieving revision 1.24
diff -u -p -u -r1.24 natSystem.cc
--- natSystem.cc	2000/08/26 19:25:13	1.24
+++ natSystem.cc	2000/09/04 19:47:10
@@ -244,8 +244,10 @@ java::lang::System::init_properties (voi
   SET ("file.separator", "/");
   SET ("path.separator", ":");
   SET ("line.separator", "\n");
-  // FIXME: look at getenv("TMPDIR");
-  SET ("java.io.tmpdir", "/tmp");
+  char *tmpdir = ::getenv("TMPDIR");
+  if (! tmpdir)
+    tmpdir = "/tmp";
+  SET ("java.io.tmpdir", tmpdir);
 #endif
 
 #ifdef HAVE_UNAME
Index: java/io/File.java
===================================================================
RCS file: /cvs/java/libgcj/libjava/java/io/File.java,v
retrieving revision 1.12
diff -u -p -u -r1.12 File.java
--- File.java	2000/09/04 16:55:47	1.12
+++ File.java	2000/09/04 19:47:10
@@ -233,14 +233,26 @@ public class File implements Serializabl
 				     File directory)
     throws IOException
   {
-    FileDescriptor desc = new FileDescriptor ();
-
-    SecurityManager s = System.getSecurityManager();
-    if (s != null)
-      s.checkWrite (desc);
+    // Grab the system temp directory if necessary
+    if (directory == null)
+      {
+	String dirname = tmpdir;
+	if (dirname == null)
+	  throw 
+	    new IOException("Cannot determine system temporary directory"); 
+	
+	directory = new File(dirname);
+	if (!directory.exists())
+	  throw new IOException("System temporary directory " 
+				+ directory.getName() + " does not exist.");
+	if (!directory.isDirectory())
+	  throw new IOException("System temporary directory " 
+				+ directory.getName() 
+				+ " is not really a directory.");
+      }
 
     if (prefix.length () < 3)
-      throw new IllegalArgumentException ();
+      throw new IllegalArgumentException ("Prefix too short: " + prefix);
     if (suffix == null)
       suffix = ".tmp";
 
@@ -259,28 +271,50 @@ public class File implements Serializabl
 	  prefix = prefix.substring(0, max_length - 6 - suf_len);
       }
 
-    // We don't care about the name because we set it later.
-    File ret = new File ("");
-    // How many times should we try?  We choose 100.
-    for (int i = 0; i < 100; ++i)
+    File f;
+
+    // Synchronize because there's a race condition between checking
+    // for file existence and creating the temporary file.
+    // Synchronize on tmpdir because it is unique and convenient.
+    synchronized (tmpdir)
       {
-	// This is ugly.
-	String t = "ZZZZZZ" + nextValue ();
-	String l = prefix + t.substring(t.length() - 6) + suffix;
-	try
-	  {
-	    desc = new FileDescriptor 
-	      (l, FileDescriptor.WRITE | FileDescriptor.EXCL);
-	    desc.close ();
-	    ret.setPath(l);
-	    return ret;
-	  }
-	catch (IOException _)
+	// How many times should we try?  We choose 100.
+	for (int i = 0; i < 100; ++i)
 	  {
+	    // This is ugly.
+	    String t = "ZZZZZZ" + nextValue ();
+	    String l = prefix + t.substring(t.length() - 6) + suffix;
+	    try
+	      {
+		f = new File(directory, l);
+		if (f.exists())
+		  continue;
+		else
+		  {
+		    String af = f.getAbsolutePath ();
+
+		    // The file does not exist now. Check to see if
+		    // we're allowed to write to it.
+		    SecurityManager s = System.getSecurityManager();
+		    if (s != null)
+		      s.checkWrite (af);
+		    
+		    // Now create the file.
+		    FileDescriptor fd = 
+		      new FileDescriptor (af, 
+					  FileDescriptor.WRITE
+					  | FileDescriptor.EXCL);
+		    fd.close ();
+		    return f;
+		  }
+	      }
+	    catch (IOException _)
+	      {
+	      }
 	  }
       }
 
-    throw new IOException ("couldn't make temp file");
+    throw new IOException ("cannot create temporary file");
   }
 
   public static File createTempFile (String prefix, String suffix)

AG

-- 
Anthony Green                                                        Red Hat
                                                       Sunnyvale, California

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]