diff options
Diffstat (limited to 'mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs')
-rw-r--r-- | mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs | 95 |
1 files changed, 83 insertions, 12 deletions
diff --git a/mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs b/mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs index 0f004cf6c88..785ffb4aaa6 100644 --- a/mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs +++ b/mcs/class/System/System.CodeDom.Compiler/TempFileCollection.cs @@ -31,6 +31,7 @@ using System.Collections; using System.IO; using System.Security; using System.Security.Permissions; +using System.Runtime.InteropServices; namespace System.CodeDom.Compiler { @@ -45,6 +46,7 @@ namespace System.CodeDom.Compiler { bool keepfiles; string basepath; Random rnd; + string ownTempDir; public TempFileCollection () : this (String.Empty, false) @@ -67,19 +69,39 @@ namespace System.CodeDom.Compiler { { get { if(basepath==null) { - // note: this property *cannot* change TempDir property - string temp = tempdir; - if (temp.Length == 0) { - // this call ensure the Environment permissions check - temp = Path.GetTempPath (); - } - + if (rnd == null) rnd = new Random (); - string random = rnd.Next (10000,99999).ToString (); - basepath = Path.Combine (temp, random); + // note: this property *cannot* change TempDir property + string temp = tempdir; + if (temp.Length == 0) + temp = GetOwnTempDir (); + + // Create a temporary file at the target directory. This ensures + // that the generated file name is unique. + FileStream f = null; + do { + int num = rnd.Next (); + num++; + basepath = Path.Combine (temp, num.ToString("x")); + string path = basepath + ".tmp"; + try { + f = new FileStream (path, FileMode.CreateNew); + } + catch (System.IO.IOException) { + f = null; + continue; + } + catch { + // avoid endless loop + throw; + } + } while (f == null); + + f.Close (); + // and you must have discovery access to the combined path // note: the cache behaviour is tested in the CAS tests if (SecurityManager.SecurityEnabled) { @@ -90,7 +112,39 @@ namespace System.CodeDom.Compiler { return(basepath); } } + + string GetOwnTempDir () + { + if (ownTempDir != null) + return ownTempDir; + + // this call ensure the Environment permissions check + string basedir = Path.GetTempPath (); + + // Create a subdirectory with the correct user permissions + int res = -1; + do { + int num = rnd.Next (); + num++; + ownTempDir = Path.Combine (basedir, num.ToString("x")); + if (Directory.Exists (ownTempDir)) + continue; + res = mkdir (ownTempDir, 0x1c0); + if (res != 0) { + if (!Directory.Exists (ownTempDir)) + throw new IOException (); + // Somebody already created the dir, keep trying + } + } while (res != 0); + return ownTempDir; + } + int ICollection.Count { + get { + return filehash.Count; + } + } + public int Count { get { @@ -163,17 +217,33 @@ namespace System.CodeDom.Compiler { public void Delete() { - string[] filenames=new string[filehash.Count]; - filehash.Keys.CopyTo(filenames, 0); + bool allDeleted = true; + string[] filenames = new string[filehash.Count]; + filehash.Keys.CopyTo (filenames, 0); foreach(string file in filenames) { if((bool)filehash[file]==false) { File.Delete(file); filehash.Remove(file); - } + } else + allDeleted = false; + } + if (basepath != null) { + string tmpFile = basepath + ".tmp"; + File.Delete (tmpFile); + basepath = null; + } + if (allDeleted && ownTempDir != null) { + Directory.Delete (ownTempDir, true); + ownTempDir = null; } } + IEnumerator IEnumerable.GetEnumerator () + { + return(filehash.Keys.GetEnumerator()); + } + public IEnumerator GetEnumerator() { return(filehash.Keys.GetEnumerator()); @@ -192,5 +262,6 @@ namespace System.CodeDom.Compiler { Dispose(false); } + [DllImport ("libc")] private static extern int mkdir (string olpath, uint mode); } } |