The Labs \ Source Viewer \ SSCLI \ System.CodeDom.Compiler \ TempFileCollection

  1. //------------------------------------------------------------------------------
  2. // <copyright file="TempFiles.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.CodeDom.Compiler
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Diagnostics;
  20.     using System.IO;
  21.     using System.Runtime.InteropServices;
  22.     using System.Text;
  23.     using Microsoft.Win32;
  24.     using System.Security;
  25.     using System.Security.Permissions;
  26.     using System.Security.Principal;
  27.     using System.ComponentModel;
  28.     using System.Security.Cryptography;
  29.     using System.Globalization;
  30.     using System.Runtime.Versioning;
  31.    
  32.     /// <devdoc>
  33.     /// <para>Represents a collection of temporary file names that are all based on a
  34.     /// single base filename located in a temporary directory.</para>
  35.     /// </devdoc>
  36.     [PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
  37.     [PermissionSet(SecurityAction.InheritanceDemand, Name = "FullTrust")]
  38.     [Serializable()]
  39.     public class TempFileCollection : ICollection, IDisposable
  40.     {
  41.         private static RNGCryptoServiceProvider rng;
  42.        
  43.         string basePath;
  44.         string tempDir;
  45.         bool keepFiles;
  46.         Hashtable files;
  47.        
  48.         static TempFileCollection()
  49.         {
  50.             // Since creating the random generator can be expensive, only do it once
  51.             rng = new RNGCryptoServiceProvider();
  52.         }
  53.        
  54.         /// <devdoc>
  55.         /// <para>[To be supplied.]</para>
  56.         /// </devdoc>
  57.         public TempFileCollection() : this(null, false)
  58.         {
  59.         }
  60.        
  61.         /// <devdoc>
  62.         /// <para>[To be supplied.]</para>
  63.         /// </devdoc>
  64.         public TempFileCollection(string tempDir) : this(tempDir, false)
  65.         {
  66.         }
  67.        
  68.         /// <devdoc>
  69.         /// <para>[To be supplied.]</para>
  70.         /// </devdoc>
  71.         public TempFileCollection(string tempDir, bool keepFiles)
  72.         {
  73.             this.keepFiles = keepFiles;
  74.             this.tempDir = tempDir;
  75.             #if !FEATURE_CASE_SENSITIVE_FILESYSTEM
  76.             files = new Hashtable(StringComparer.OrdinalIgnoreCase);
  77.             #else
  78.             files = new Hashtable();
  79.             #endif
  80.         }
  81.        
  82.         /// <internalonly/>
  83.         /// <devdoc>
  84.         /// <para> To allow it's stuff to be cleaned up</para>
  85.         /// </devdoc>
  86.         void IDisposable.Dispose()
  87.         {
  88.             Dispose(true);
  89.             GC.SuppressFinalize(this);
  90.         }
  91.         protected virtual void Dispose(bool disposing)
  92.         {
  93.             // It is safe to call Delete from here even if Dispose is called from Finalizer
  94.             // because the graph of objects is guaranteed to be there and
  95.             // neither Hashtable nor String have a finalizer of their own that could
  96.             // be called before TempFileCollection Finalizer
  97.             Delete();
  98.         }
  99.        
  100.         /// <devdoc>
  101.         /// <para>[To be supplied.]</para>
  102.         /// </devdoc>
  103.         ~TempFileCollection()
  104.         {
  105.             Dispose(false);
  106.         }
  107.        
  108.         /// <devdoc>
  109.         /// <para>[To be supplied.]</para>
  110.         /// </devdoc>
  111.         public string AddExtension(string fileExtension)
  112.         {
  113.             return AddExtension(fileExtension, keepFiles);
  114.         }
  115.        
  116.         /// <devdoc>
  117.         /// <para>[To be supplied.]</para>
  118.         /// </devdoc>
  119.         public string AddExtension(string fileExtension, bool keepFile)
  120.         {
  121.             if (fileExtension == null || fileExtension.Length == 0)
  122.                 throw new ArgumentException(SR.GetString(SR.InvalidNullEmptyArgument, "fileExtension"), "fileExtension");
  123.             // fileExtension not specified
  124.             string fileName = BasePath + "." + fileExtension;
  125.             AddFile(fileName, keepFile);
  126.             return fileName;
  127.         }
  128.        
  129.         /// <devdoc>
  130.         /// <para>[To be supplied.]</para>
  131.         /// </devdoc>
  132.         public void AddFile(string fileName, bool keepFile)
  133.         {
  134.             if (fileName == null || fileName.Length == 0)
  135.                 throw new ArgumentException(SR.GetString(SR.InvalidNullEmptyArgument, "fileName"), "fileName");
  136.             // fileName not specified
  137.             if (files[fileName] != null)
  138.                 throw new ArgumentException(SR.GetString(SR.DuplicateFileName, fileName), "fileName");
  139.             // duplicate fileName
  140.             files.Add(fileName, (object)keepFile);
  141.         }
  142.        
  143.         /// <devdoc>
  144.         /// <para>[To be supplied.]</para>
  145.         /// </devdoc>
  146.         public IEnumerator GetEnumerator()
  147.         {
  148.             return files.Keys.GetEnumerator();
  149.         }
  150.        
  151.         /// <internalonly/>
  152.         IEnumerator IEnumerable.GetEnumerator()
  153.         {
  154.             return files.Keys.GetEnumerator();
  155.         }
  156.        
  157.         /// <internalonly/>
  158.         void ICollection.CopyTo(Array array, int start)
  159.         {
  160.             files.Keys.CopyTo(array, start);
  161.         }
  162.        
  163.         /// <devdoc>
  164.         /// <para>[To be supplied.]</para>
  165.         /// </devdoc>
  166.         public void CopyTo(string[] fileNames, int start)
  167.         {
  168.             files.Keys.CopyTo(fileNames, start);
  169.         }
  170.        
  171.         /// <devdoc>
  172.         /// <para>[To be supplied.]</para>
  173.         /// </devdoc>
  174.         public int Count {
  175.             get { return files.Count; }
  176.         }
  177.        
  178.         /// <internalonly/>
  179.         int ICollection.Count {
  180.             get { return files.Count; }
  181.         }
  182.        
  183.         /// <internalonly/>
  184.         object ICollection.SyncRoot {
  185.             get { return null; }
  186.         }
  187.        
  188.         /// <internalonly/>
  189.         bool ICollection.IsSynchronized {
  190.             get { return false; }
  191.         }
  192.        
  193.         /// <devdoc>
  194.         /// <para>[To be supplied.]</para>
  195.         /// </devdoc>
  196.         public string TempDir {
  197.             get { return tempDir == null ? string.Empty : tempDir; }
  198.         }
  199.        
  200.         /// <devdoc>
  201.         /// <para>[To be supplied.]</para>
  202.         /// </devdoc>
  203.         public string BasePath {
  204.             get {
  205.                 EnsureTempNameCreated();
  206.                 return basePath;
  207.             }
  208.         }
  209.        
  210.         void EnsureTempNameCreated()
  211.         {
  212.             if (basePath == null) {
  213.                
  214.                 string tempFileName = null;
  215.                 FileStream tempFileStream;
  216.                 bool uniqueFile = false;
  217.                 int retryCount = 5000;
  218.                 do {
  219.                     try {
  220.                         basePath = GetTempFileName(TempDir);
  221.                        
  222.                         string full = basePath;
  223.                         new EnvironmentPermission(PermissionState.Unrestricted).Assert();
  224.                         try {
  225.                             full = Path.GetFullPath(basePath);
  226.                         }
  227.                         finally {
  228.                             CodeAccessPermission.RevertAssert();
  229.                         }
  230.                        
  231.                         new FileIOPermission(FileIOPermissionAccess.AllAccess, full).Demand();
  232.                        
  233.                         // make sure the filename is unique.
  234.                         tempFileName = basePath + ".tmp";
  235.                         using (tempFileStream = new FileStream(tempFileName, FileMode.CreateNew, FileAccess.Write)) {
  236.                         }
  237.                         uniqueFile = true;
  238.                     }
  239.                     catch (IOException e) {
  240.                         retryCount--;
  241.                         if (retryCount == 0 || Marshal.GetHRForException(e) != NativeMethods.ERROR_FILE_EXISTS)
  242.                             throw;
  243.                        
  244.                         uniqueFile = false;
  245.                     }
  246.                 }
  247.                 while (!uniqueFile);
  248.                 files.Add(tempFileName, keepFiles);
  249.                
  250.             }
  251.         }
  252.        
  253.         /// <devdoc>
  254.         /// <para>[To be supplied.]</para>
  255.         /// </devdoc>
  256.         public bool KeepFiles {
  257.             get { return keepFiles; }
  258.             set { keepFiles = value; }
  259.         }
  260.        
  261.         bool KeepFile(string fileName)
  262.         {
  263.             object keep = files[fileName];
  264.             if (keep == null)
  265.                 return false;
  266.             return (bool)keep;
  267.         }
  268.        
  269.         /// <devdoc>
  270.         /// <para>[To be supplied.]</para>
  271.         /// </devdoc>
  272.         [ResourceExposure(ResourceScope.None)]
  273.         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  274.         public void Delete()
  275.         {
  276.             if (files != null) {
  277.                 string[] fileNames = new string[files.Count];
  278.                 files.Keys.CopyTo(fileNames, 0);
  279.                 foreach (string fileName in fileNames) {
  280.                     if (!KeepFile(fileName)) {
  281.                         Delete(fileName);
  282.                         files.Remove(fileName);
  283.                     }
  284.                 }
  285.             }
  286.         }
  287.        
  288.         // This function deletes files after reverting impersonation.
  289.         internal void SafeDelete()
  290.         {
  291.             try {
  292.                 Delete();
  293.             }
  294.             finally {
  295.             }
  296.         }
  297.        
  298.         [ResourceExposure(ResourceScope.Machine)]
  299.         [ResourceConsumption(ResourceScope.Machine)]
  300.         void Delete(string fileName)
  301.         {
  302.             try {
  303.                 File.Delete(fileName);
  304.             }
  305.             catch {
  306.                 // Ignore all exceptions
  307.             }
  308.         }
  309.        
  310.         [ResourceExposure(ResourceScope.Machine)]
  311.         [ResourceConsumption(ResourceScope.Machine)]
  312.         static string GetTempFileName(string tempDir)
  313.         {
  314.             if (tempDir == null || tempDir.Length == 0) {
  315.                 tempDir = Path.GetTempPath();
  316.             }
  317.            
  318.             string fileName = GenerateRandomFileName();
  319.            
  320.             if (tempDir.EndsWith("\\", StringComparison.Ordinal))
  321.                 return tempDir + fileName;
  322.             return tempDir + "\\" + fileName;
  323.         }
  324.        
  325.         // Generate a random file name with 8 characters
  326.         static string GenerateRandomFileName()
  327.         {
  328.             // Generate random bytes
  329.             byte[] data = new byte[6];
  330.            
  331.             lock (rng) {
  332.                 rng.GetBytes(data);
  333.             }
  334.            
  335.             // Turn them into a string containing only characters valid in file names/url
  336.             string s = Convert.ToBase64String(data).ToLower(CultureInfo.InvariantCulture);
  337.             s = s.Replace('/', '-');
  338.             s = s.Replace('+', '_');
  339.            
  340.             return s;
  341.         }
  342.     }
  343. }

Developer Fusion