281 lines
6.3 KiB
C#
Raw Normal View History

//
// 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 MONO_FEATURE_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);
}
}