379 lines
14 KiB
C#
379 lines
14 KiB
C#
|
// ==++==
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// ==--==
|
||
|
/*============================================================
|
||
|
**
|
||
|
** Class: DirectoryInfo
|
||
|
**
|
||
|
**
|
||
|
** Purpose: Exposes routines for enumerating through a
|
||
|
** directory.
|
||
|
**
|
||
|
** Date: March 5, 2000
|
||
|
** April 11,2000
|
||
|
**
|
||
|
===========================================================*/
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Diagnostics;
|
||
|
using Microsoft.Singularity;
|
||
|
using System.Text;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Globalization;
|
||
|
|
||
|
//@TODO: Add a static SystemDirectoryInfo property returning a URI
|
||
|
namespace System.IO {
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo"]/*' />
|
||
|
public sealed class DirectoryInfo : FileSystemInfo {
|
||
|
private DirectoryInfo() {
|
||
|
}
|
||
|
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.DirectoryInfo"]/*' />
|
||
|
public DirectoryInfo(String path)
|
||
|
{
|
||
|
if (path==null)
|
||
|
throw new ArgumentNullException("path");
|
||
|
|
||
|
OriginalPath = path;
|
||
|
|
||
|
// Must fully qualify the path for the security check
|
||
|
String fullPath = Path.GetFullPathInternal(path);
|
||
|
FullPath = fullPath;
|
||
|
|
||
|
}
|
||
|
|
||
|
internal DirectoryInfo(String! fullPath, bool junk)
|
||
|
{
|
||
|
Debug.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
|
||
|
// Fast path when we know a DirectoryInfo exists.
|
||
|
OriginalPath = Path.GetFileName(fullPath);
|
||
|
FullPath = fullPath;
|
||
|
}
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Name"]/*' />
|
||
|
public override String Name {
|
||
|
get {
|
||
|
// FullPath might be either "c:\bar" or "c:\bar\". Handle
|
||
|
// those cases, as well as avoiding mangling "c:\".
|
||
|
String s = FullPath;
|
||
|
if (s.Length > 3) {
|
||
|
if (s.EndsWith(Path.DirectorySeparatorChar))
|
||
|
s = FullPath.Substring(0, FullPath.Length - 1);
|
||
|
return Path.GetFileName(s);
|
||
|
}
|
||
|
return FullPath; // For rooted paths, like "c:\"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Parent"]/*' />
|
||
|
public DirectoryInfo Parent {
|
||
|
get {
|
||
|
String parentName;
|
||
|
// FullPath might be either "c:\bar" or "c:\bar\". Handle
|
||
|
// those cases, as well as avoiding mangling "c:\".
|
||
|
String s = FullPath;
|
||
|
if (s.Length > 3 && s.EndsWith(Path.DirectorySeparatorChar))
|
||
|
s = FullPath.Substring(0, FullPath.Length - 1);
|
||
|
parentName = Path.GetDirectoryName(s);
|
||
|
if (parentName==null)
|
||
|
return null;
|
||
|
DirectoryInfo dir = new DirectoryInfo(parentName,false);
|
||
|
return dir;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.CreateSubdirectory"]/*' />
|
||
|
public DirectoryInfo CreateSubdirectory(String path) {
|
||
|
if (path==null)
|
||
|
throw new ArgumentNullException("path");
|
||
|
|
||
|
String newDirs = Path.InternalCombine(FullPath, path);
|
||
|
String fullPath = Path.GetFullPathInternal(newDirs);
|
||
|
|
||
|
if (0!=String.Compare(FullPath,0,fullPath,0, FullPath.Length,true))
|
||
|
throw new ArgumentException(String.Format("Argument_InvalidSubPath",path,OriginalPath));
|
||
|
|
||
|
Directory.InternalCreateDirectory(fullPath,path);
|
||
|
return new DirectoryInfo(fullPath, false);
|
||
|
}
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Create"]/*' />
|
||
|
public void Create()
|
||
|
{
|
||
|
Directory.InternalCreateDirectory(FullPath,OriginalPath);
|
||
|
}
|
||
|
|
||
|
// Tests if the given path refers to an existing DirectoryInfo on disk.
|
||
|
//
|
||
|
// Your application must have Read permission to the directory's
|
||
|
// contents.
|
||
|
//
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Exists"]/*' />
|
||
|
public override bool Exists {
|
||
|
get
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
if (_dataInitialised == -1)
|
||
|
Refresh();
|
||
|
if (_dataInitialised != 0) // Refresh was unable to initialise the data
|
||
|
return false;
|
||
|
|
||
|
return _data.fileAttributes != -1 && (_data.fileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY) != 0;
|
||
|
}
|
||
|
catch(Exception)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Returns an array of Files in the current DirectoryInfo matching the
|
||
|
// given search criteria (ie, "*.txt").
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetFiles"]/*' />
|
||
|
public FileInfo[] GetFiles(String searchPattern)
|
||
|
{
|
||
|
if (searchPattern==null)
|
||
|
throw new ArgumentNullException("searchPattern");
|
||
|
|
||
|
searchPattern = searchPattern.TrimEnd();
|
||
|
if (searchPattern.Length == 0)
|
||
|
return new FileInfo[0];
|
||
|
|
||
|
String path = FullPath;
|
||
|
|
||
|
String searchPath = Path.GetDirectoryName(searchPattern);
|
||
|
|
||
|
if (searchPath != null && searchPath != String.Empty) // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
|
||
|
{
|
||
|
path = Path.Combine(path,searchPath);
|
||
|
}
|
||
|
|
||
|
String[] fileNames = Directory.InternalGetFiles(FullPath, OriginalPath, searchPattern);
|
||
|
for (int i = 0; i < fileNames.Length; i++)
|
||
|
fileNames[i] = Path.InternalCombine(path, fileNames[i]);
|
||
|
FileInfo[] files = new FileInfo[fileNames.Length];
|
||
|
for(int i=0; i<fileNames.Length; i++)
|
||
|
files[i] = new FileInfo((!)fileNames[i], false);
|
||
|
return files;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Returns an array of Files in the DirectoryInfo specified by path
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetFiles1"]/*' />
|
||
|
public FileInfo[] GetFiles()
|
||
|
{
|
||
|
return GetFiles("*");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Returns an array of Directories in the current directory.
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetDirectories"]/*' />
|
||
|
public DirectoryInfo[] GetDirectories()
|
||
|
{
|
||
|
return GetDirectories("*");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Returns an array of strongly typed FileSystemInfo entries in the path with the
|
||
|
// given search criteria (ie, "*.txt").
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetFileSystemInfos"]/*' />
|
||
|
public FileSystemInfo[] GetFileSystemInfos(String searchPattern)
|
||
|
{
|
||
|
if (searchPattern==null)
|
||
|
throw new ArgumentNullException("searchPattern");
|
||
|
|
||
|
searchPattern = searchPattern.TrimEnd();
|
||
|
if (searchPattern.Length == 0)
|
||
|
return new FileSystemInfo[0];
|
||
|
|
||
|
String path = FullPath;
|
||
|
|
||
|
String searchPath = Path.GetDirectoryName(searchPattern);
|
||
|
if (searchPath != null && searchPath != String.Empty) // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
|
||
|
{
|
||
|
path = Path.Combine(path,searchPath);
|
||
|
}
|
||
|
|
||
|
String [] dirNames = Directory.InternalGetDirectories(FullPath, OriginalPath, searchPattern);
|
||
|
String [] fileNames = Directory.InternalGetFiles(FullPath, OriginalPath, searchPattern);
|
||
|
FileSystemInfo [] fileSystemEntries = new FileSystemInfo[dirNames.Length + fileNames.Length];
|
||
|
String[] permissionNames = new String[dirNames.Length];
|
||
|
|
||
|
for (int i = 0;i<dirNames.Length;i++) {
|
||
|
dirNames[i] = Path.InternalCombine(path, dirNames[i]);
|
||
|
permissionNames[i] = dirNames[i] + "\\.";
|
||
|
}
|
||
|
|
||
|
for (int i = 0;i<fileNames.Length;i++)
|
||
|
fileNames[i] = Path.InternalCombine(path, fileNames[i]);
|
||
|
|
||
|
int count = 0;
|
||
|
for (int i = 0;i<dirNames.Length;i++)
|
||
|
fileSystemEntries[count++] = new DirectoryInfo((!)dirNames[i], false);
|
||
|
|
||
|
for (int i = 0;i<fileNames.Length;i++)
|
||
|
fileSystemEntries[count++] = new FileInfo((!)fileNames[i], false);
|
||
|
|
||
|
return fileSystemEntries;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Returns an array of strongly typed FileSystemInfo entries which will contain a listing
|
||
|
// of all the files and directories.
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetFileSystemInfos1"]/*' />
|
||
|
public FileSystemInfo[] GetFileSystemInfos()
|
||
|
{
|
||
|
return GetFileSystemInfos("*");
|
||
|
}
|
||
|
|
||
|
// Returns an array of Directories in the current DirectoryInfo matching the
|
||
|
// given search criteria (ie, "System*" could match the System & System32
|
||
|
// directories).
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.GetDirectories1"]/*' />
|
||
|
public DirectoryInfo[] GetDirectories(String searchPattern)
|
||
|
{
|
||
|
if (searchPattern==null)
|
||
|
throw new ArgumentNullException("searchPattern");
|
||
|
|
||
|
searchPattern = searchPattern.TrimEnd();
|
||
|
if (searchPattern.Length == 0)
|
||
|
return new DirectoryInfo[0];
|
||
|
|
||
|
String path = FullPath;
|
||
|
|
||
|
String searchPath = Path.GetDirectoryName(searchPattern);
|
||
|
if (searchPath != null && searchPath != String.Empty) // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
|
||
|
{
|
||
|
path = Path.Combine(path,searchPath);
|
||
|
}
|
||
|
|
||
|
String fullPath = Path.InternalCombine(FullPath, searchPattern);
|
||
|
|
||
|
String[] dirNames = Directory.InternalGetFileDirectoryNames(fullPath, OriginalPath, false);
|
||
|
String[] permissionNames = new String[dirNames.Length];
|
||
|
for (int i = 0; i<dirNames.Length; i++) {
|
||
|
dirNames[i] = Path.InternalCombine(path, dirNames[i]);
|
||
|
permissionNames[i] = dirNames[i] + "\\."; // these will never have a slash at end
|
||
|
}
|
||
|
DirectoryInfo[] dirs = new DirectoryInfo[dirNames.Length];
|
||
|
for(int i=0; i<dirNames.Length; i++)
|
||
|
dirs[i] = new DirectoryInfo((!)dirNames[i], false);
|
||
|
return dirs;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Returns the root portion of the given path. The resulting string
|
||
|
// consists of those rightmost characters of the path that constitute the
|
||
|
// root of the path. Possible patterns for the resulting string are: An
|
||
|
// empty string (a relative path on the current drive), "\" (an absolute
|
||
|
// path on the current drive), "X:" (a relative path on a given drive,
|
||
|
// where X is the drive letter), "X:\" (an absolute path on a given drive),
|
||
|
// and "\\server\share" (a UNC path for a given server and share name).
|
||
|
// The resulting string is null if path is null.
|
||
|
//
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Root"]/*' />
|
||
|
public DirectoryInfo Root {
|
||
|
get
|
||
|
{
|
||
|
int rootLength = Path.GetRootLength(FullPath);
|
||
|
String rootPath = FullPath.Substring(0, rootLength);
|
||
|
return new DirectoryInfo(rootPath);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.MoveTo"]/*' />
|
||
|
public void MoveTo(String destDirName) {
|
||
|
if (destDirName==null)
|
||
|
throw new ArgumentNullException("destDirName");
|
||
|
if (destDirName.Length==0)
|
||
|
throw new ArgumentException("Argument_EmptyFileName", "destDirName");
|
||
|
|
||
|
String fullDestDirName = Path.GetFullPathInternal(destDirName);
|
||
|
if (!fullDestDirName.EndsWith( '\\'))
|
||
|
fullDestDirName = fullDestDirName + "\\";
|
||
|
|
||
|
String fullSourcePath;
|
||
|
if (FullPath.EndsWith( '\\' ))
|
||
|
fullSourcePath = FullPath;
|
||
|
else
|
||
|
fullSourcePath = FullPath + "\\";
|
||
|
|
||
|
if (CompareInfo.Compare(fullSourcePath, fullDestDirName, CompareOptions.IgnoreCase) == 0)
|
||
|
throw new IOException("IO.IO_SourceDestMustBeDifferent");
|
||
|
|
||
|
String sourceRoot = Path.GetPathRoot(fullSourcePath);
|
||
|
String destinationRoot = Path.GetPathRoot(fullDestDirName);
|
||
|
|
||
|
if (CompareInfo.Compare(sourceRoot, destinationRoot, CompareOptions.IgnoreCase) != 0)
|
||
|
throw new IOException("IO.IO_SourceDestMustHaveSameRoot");
|
||
|
|
||
|
if (!Native.MoveFile(FullPath, destDirName))
|
||
|
{
|
||
|
__Error.WinIOError(Native.ERROR_PATH_NOT_FOUND, OriginalPath);
|
||
|
}
|
||
|
FullPath = fullDestDirName;
|
||
|
OriginalPath = destDirName;
|
||
|
|
||
|
// Flush any cached information about the directory.
|
||
|
_dataInitialised = -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Delete"]/*' />
|
||
|
public override void Delete()
|
||
|
{
|
||
|
Directory.Delete(FullPath, OriginalPath, false);
|
||
|
}
|
||
|
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.Delete1"]/*' />
|
||
|
public void Delete(bool recursive)
|
||
|
{
|
||
|
Directory.Delete(FullPath, OriginalPath, recursive);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Returns the fully qualified path
|
||
|
//| <include file='doc\DirectoryInfo.uex' path='docs/doc[@for="DirectoryInfo.ToString"]/*' />
|
||
|
#if false
|
||
|
public override String ToString()
|
||
|
{
|
||
|
return OriginalPath;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
|
||
|
// Constants defined in WINBASE.H
|
||
|
private const int GetFileExInfoStandard = 0;
|
||
|
|
||
|
// Defined in WinError.h
|
||
|
private const int ERROR_SUCCESS = 0;
|
||
|
}
|
||
|
|
||
|
}
|