// // System.CodeDom.Compiler TempFileCollection Class implementation // // Author: // Dick Porter (dick@ximian.com) // // (C) Copyright 2003 Ximian, Inc. // Copyright (C) 2005 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // using System.Collections; using System.IO; using System.Security; using System.Security.Permissions; using System.Runtime.InteropServices; namespace System.CodeDom.Compiler { [Serializable] [PermissionSet (SecurityAction.LinkDemand, Unrestricted = true)] public class TempFileCollection:ICollection, IEnumerable, IDisposable { Hashtable filehash; string tempdir; bool keepfiles; string basepath; Random rnd; string ownTempDir; public TempFileCollection () : this (String.Empty, false) { } public TempFileCollection(string tempDir) : this (tempDir, false) { } public TempFileCollection(string tempDir, bool keepFiles) { filehash=new Hashtable(); tempdir = (tempDir == null) ? String.Empty : tempDir; keepfiles=keepFiles; } public string BasePath { get { if(basepath==null) { if (rnd == null) rnd = new Random (); // note: this property *cannot* change TempDir property string temp = tempdir; if (temp.Length == 0) { if (ownTempDir != null) { temp = ownTempDir; Directory.CreateDirectory (temp); } else { temp = CreateOwnTempDir (); } } // Create a temporary file at the target directory. This ensures // that the generated file name is unique. int test_counter = 1000; while (true) { int num = rnd.Next (); num++; basepath = Path.Combine (temp, num.ToString("x")); string path = basepath + ".tmp"; try { using (var f = new FileStream (path, FileMode.CreateNew)) { break; } } catch (IOException) { if (test_counter-- > 0) continue; throw; } } #if FEATURE_MONO_CAS // and you must have discovery access to the combined path // note: the cache behaviour is tested in the CAS tests if (SecurityManager.SecurityEnabled) { new FileIOPermission (FileIOPermissionAccess.PathDiscovery, basepath).Demand (); } #endif } return(basepath); } } string CreateOwnTempDir () { // this call ensure the Environment permissions check string basedir = Path.GetTempPath (); // Create a subdirectory with the correct user permissions int res = -1; bool win32 = false; switch (Environment.OSVersion.Platform) { case PlatformID.Win32S: case PlatformID.Win32Windows: case PlatformID.Win32NT: case PlatformID.WinCE: win32 = true; res = 0; break; } do { int num = rnd.Next (); num++; ownTempDir = Path.Combine (basedir, num.ToString("x")); if (Directory.Exists (ownTempDir)) continue; if (win32) Directory.CreateDirectory (ownTempDir); else 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 { return(filehash.Count); } } public bool KeepFiles { get { return(keepfiles); } set { keepfiles=value; } } public string TempDir { get { // note: we only return what we were supplied so there // is no permission protecting this information return tempdir; } } public string AddExtension(string fileExtension) { return(AddExtension(fileExtension, keepfiles)); } public string AddExtension(string fileExtension, bool keepFile) { string filename=BasePath+"."+fileExtension; AddFile(filename, keepFile); return(filename); } public void AddFile(string fileName, bool keepFile) { filehash.Add(fileName, keepFile); } public void CopyTo(string[] fileNames, int start) { filehash.Keys.CopyTo(fileNames, start); } void ICollection.CopyTo(Array array, int start) { filehash.Keys.CopyTo(array, start); } object ICollection.SyncRoot { get { return null; } } bool ICollection.IsSynchronized { get { return(false); } } void IDisposable.Dispose() { Dispose(true); } public void Delete() { 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 && filenames.Length > 0) { Directory.Delete (ownTempDir, true); } } IEnumerator IEnumerable.GetEnumerator () { return(filehash.Keys.GetEnumerator()); } public IEnumerator GetEnumerator() { return(filehash.Keys.GetEnumerator()); } protected virtual void Dispose(bool disposing) { Delete(); if (disposing) { GC.SuppressFinalize (true); } } ~TempFileCollection() { Dispose(false); } [DllImport ("libc")] private static extern int mkdir (string olpath, uint mode); } }