3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** Class: DirectoryInfo
10 ** <OWNER>[....]</OWNER>
13 ** Purpose: Exposes routines for enumerating through a
18 ===========================================================*/
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.Security;
25 using System.Security.AccessControl;
27 using System.Security.Permissions;
28 using Microsoft.Win32;
30 using System.Runtime.InteropServices;
31 using System.Globalization;
32 using System.Runtime.Serialization;
33 using System.Runtime.Versioning;
34 using System.Diagnostics.Contracts;
39 public sealed class DirectoryInfo : FileSystemInfo {
40 private String[] demandDir;
43 // Migrating InheritanceDemands requires this default ctor, so we can annotate it.
44 #if FEATURE_CORESYSTEM
45 [System.Security.SecurityCritical]
47 [System.Security.SecuritySafeCritical]
48 #endif //FEATURE_CORESYSTEM
49 private DirectoryInfo(){}
52 [System.Security.SecurityCritical]
53 [ResourceExposure(ResourceScope.Machine)]
54 [ResourceConsumption(ResourceScope.Machine)]
55 public static DirectoryInfo UnsafeCreateDirectoryInfo(String path)
58 throw new ArgumentNullException("path");
59 Contract.EndContractBlock();
61 DirectoryInfo di = new DirectoryInfo();
67 [System.Security.SecuritySafeCritical]
68 [ResourceExposure(ResourceScope.Machine)]
69 [ResourceConsumption(ResourceScope.Machine)]
70 public DirectoryInfo(String path)
73 throw new ArgumentNullException("path");
74 Contract.EndContractBlock();
79 [System.Security.SecurityCritical]
80 [ResourceExposure(ResourceScope.Machine)]
81 [ResourceConsumption(ResourceScope.Machine)]
82 private void Init(String path, bool checkHost)
84 // Special case "<DriveLetter>:" to point to "<CurrentDirectory>" instead
85 if ((path.Length == 2) && (path[1] == ':'))
94 // Must fully qualify the path for the security check
95 String fullPath = Path.GetFullPathInternal(path);
97 demandDir = new String[] {Directory.GetDemandDir(fullPath, true)};
101 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, OriginalPath, fullPath);
105 new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
109 DisplayPath = GetDisplayName(OriginalPath, FullPath);
112 [ResourceExposure(ResourceScope.Machine)]
113 [ResourceConsumption(ResourceScope.Machine)]
114 #if FEATURE_CORESYSTEM
115 [System.Security.SecuritySafeCritical]
116 #endif //FEATURE_CORESYSTEM
117 internal DirectoryInfo(String fullPath, bool junk)
119 Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
120 // Fast path when we know a DirectoryInfo exists.
121 OriginalPath = Path.GetFileName(fullPath);
124 DisplayPath = GetDisplayName(OriginalPath, FullPath);
125 demandDir = new String[] {Directory.GetDemandDir(fullPath, true)};
128 [System.Security.SecurityCritical] // auto-generated
129 private DirectoryInfo(SerializationInfo info, StreamingContext context) : base(info, context)
132 demandDir = new String[] {Directory.GetDemandDir(FullPath, true)};
133 new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
135 DisplayPath = GetDisplayName(OriginalPath, FullPath);
138 public override String Name {
139 [ResourceExposure(ResourceScope.Machine)]
140 [ResourceConsumption(ResourceScope.Machine)]
144 // DisplayPath is dir name for coreclr
147 // Return just dir name
148 return GetDirName(FullPath);
153 public DirectoryInfo Parent {
154 [System.Security.SecuritySafeCritical]
155 [ResourceExposure(ResourceScope.Machine)]
156 [ResourceConsumption(ResourceScope.Machine)]
159 // FullPath might be either "c:\bar" or "c:\bar\". Handle
160 // those cases, as well as avoiding mangling "c:\".
162 if (s.Length > 3 && s.EndsWith(Path.DirectorySeparatorChar))
163 s = FullPath.Substring(0, FullPath.Length - 1);
164 parentName = Path.GetDirectoryName(s);
165 if (parentName==null)
167 DirectoryInfo dir = new DirectoryInfo(parentName,false);
169 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery | FileSecurityStateAccess.Read, String.Empty, dir.demandDir[0]);
172 new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, dir.demandDir, false, false).Demand();
179 [ResourceExposure(ResourceScope.Machine)]
180 [ResourceConsumption(ResourceScope.Machine)]
182 [System.Security.SecuritySafeCritical]
184 public DirectoryInfo CreateSubdirectory(String path) {
186 throw new ArgumentNullException("path");
187 Contract.EndContractBlock();
189 return CreateSubdirectory(path, null);
193 [System.Security.SecuritySafeCritical] // auto-generated
194 [ResourceExposure(ResourceScope.Machine)]
195 [ResourceConsumption(ResourceScope.Machine)]
196 public DirectoryInfo CreateSubdirectory(String path, DirectorySecurity directorySecurity)
198 return CreateSubdirectoryHelper(path, directorySecurity);
200 #else // FEATURE_MACL
202 [System.Security.SecurityCritical] // auto-generated
204 [ResourceExposure(ResourceScope.Machine)]
205 [ResourceConsumption(ResourceScope.Machine)]
206 public DirectoryInfo CreateSubdirectory(String path, Object directorySecurity)
209 throw new ArgumentNullException("path");
210 Contract.EndContractBlock();
212 return CreateSubdirectoryHelper(path, directorySecurity);
214 #endif // FEATURE_MACL
216 [System.Security.SecurityCritical] // auto-generated
217 [ResourceExposure(ResourceScope.Machine)]
218 [ResourceConsumption(ResourceScope.Machine)]
219 private DirectoryInfo CreateSubdirectoryHelper(String path, Object directorySecurity)
221 Contract.Requires(path != null);
223 String newDirs = Path.InternalCombine(FullPath, path);
224 String fullPath = Path.GetFullPathInternal(newDirs);
226 if (0!=String.Compare(FullPath,0,fullPath,0, FullPath.Length,StringComparison.OrdinalIgnoreCase)) {
227 String displayPath = __Error.GetDisplayablePath(DisplayPath, false);
228 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSubPath", path, displayPath));
231 // Ensure we have permission to create this subdirectory.
232 String demandDirForCreation = Directory.GetDemandDir(fullPath, true);
234 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, OriginalPath, demandDirForCreation);
237 new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandDirForCreation }, false, false).Demand();
240 Directory.InternalCreateDirectory(fullPath, path, directorySecurity);
242 // Check for read permission to directory we hand back by calling this constructor.
243 return new DirectoryInfo(fullPath);
246 [ResourceExposure(ResourceScope.None)]
247 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
250 Directory.InternalCreateDirectory(FullPath, OriginalPath, null, true);
254 [ResourceExposure(ResourceScope.None)]
255 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
256 public void Create(DirectorySecurity directorySecurity)
258 Directory.InternalCreateDirectory(FullPath, OriginalPath, directorySecurity, true);
262 // Tests if the given path refers to an existing DirectoryInfo on disk.
264 // Your application must have Read permission to the directory's
267 public override bool Exists {
268 [System.Security.SecuritySafeCritical] // auto-generated
273 if (_dataInitialised == -1)
275 if (_dataInitialised != 0) // Refresh was unable to initialise the data
278 return _data.fileAttributes != -1 && (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0;
288 [ResourceExposure(ResourceScope.None)]
289 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
290 public DirectorySecurity GetAccessControl()
292 return Directory.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
295 [ResourceExposure(ResourceScope.None)]
296 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
297 public DirectorySecurity GetAccessControl(AccessControlSections includeSections)
299 return Directory.GetAccessControl(FullPath, includeSections);
302 [ResourceExposure(ResourceScope.None)]
303 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
304 public void SetAccessControl(DirectorySecurity directorySecurity)
306 Directory.SetAccessControl(FullPath, directorySecurity);
310 // Returns an array of Files in the current DirectoryInfo matching the
311 // given search criteria (ie, "*.txt").
312 [ResourceExposure(ResourceScope.Machine)]
313 [ResourceConsumption(ResourceScope.Machine)]
314 public FileInfo[] GetFiles(String searchPattern)
316 if (searchPattern == null)
317 throw new ArgumentNullException("searchPattern");
318 Contract.EndContractBlock();
320 return InternalGetFiles(searchPattern, SearchOption.TopDirectoryOnly);
323 // Returns an array of Files in the current DirectoryInfo matching the
324 // given search criteria (ie, "*.txt").
325 [ResourceExposure(ResourceScope.Machine)]
326 [ResourceConsumption(ResourceScope.Machine)]
327 public FileInfo[] GetFiles(String searchPattern, SearchOption searchOption)
329 if (searchPattern == null)
330 throw new ArgumentNullException("searchPattern");
331 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
332 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
333 Contract.EndContractBlock();
335 return InternalGetFiles(searchPattern, searchOption);
338 // Returns an array of Files in the current DirectoryInfo matching the
339 // given search criteria (ie, "*.txt").
340 [ResourceExposure(ResourceScope.Machine)]
341 [ResourceConsumption(ResourceScope.Machine)]
342 private FileInfo[] InternalGetFiles(String searchPattern, SearchOption searchOption)
344 Contract.Requires(searchPattern != null);
345 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
347 IEnumerable<FileInfo> enble = FileSystemEnumerableFactory.CreateFileInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
348 List<FileInfo> fileList = new List<FileInfo>(enble);
349 return fileList.ToArray();
352 // Returns an array of Files in the DirectoryInfo specified by path
353 [ResourceExposure(ResourceScope.Machine)]
354 [ResourceConsumption(ResourceScope.Machine)]
355 public FileInfo[] GetFiles()
357 return InternalGetFiles("*", SearchOption.TopDirectoryOnly);
360 // Returns an array of Directories in the current directory.
361 [ResourceExposure(ResourceScope.Machine)]
362 [ResourceConsumption(ResourceScope.Machine)]
363 public DirectoryInfo[] GetDirectories()
365 return InternalGetDirectories("*", SearchOption.TopDirectoryOnly);
368 // Returns an array of strongly typed FileSystemInfo entries in the path with the
369 // given search criteria (ie, "*.txt").
370 [ResourceExposure(ResourceScope.Machine)]
371 [ResourceConsumption(ResourceScope.Machine)]
372 public FileSystemInfo[] GetFileSystemInfos(String searchPattern)
374 if (searchPattern == null)
375 throw new ArgumentNullException("searchPattern");
376 Contract.EndContractBlock();
378 return InternalGetFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
381 // Returns an array of strongly typed FileSystemInfo entries in the path with the
382 // given search criteria (ie, "*.txt").
383 [ResourceExposure(ResourceScope.Machine)]
384 [ResourceConsumption(ResourceScope.Machine)]
385 public FileSystemInfo[] GetFileSystemInfos(String searchPattern, SearchOption searchOption)
387 if (searchPattern == null)
388 throw new ArgumentNullException("searchPattern");
389 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
390 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
391 Contract.EndContractBlock();
393 return InternalGetFileSystemInfos(searchPattern, searchOption);
396 // Returns an array of strongly typed FileSystemInfo entries in the path with the
397 // given search criteria (ie, "*.txt").
398 [ResourceExposure(ResourceScope.Machine)]
399 [ResourceConsumption(ResourceScope.Machine)]
400 private FileSystemInfo[] InternalGetFileSystemInfos(String searchPattern, SearchOption searchOption)
402 Contract.Requires(searchPattern != null);
403 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
405 IEnumerable<FileSystemInfo> enble = FileSystemEnumerableFactory.CreateFileSystemInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
406 List<FileSystemInfo> fileList = new List<FileSystemInfo>(enble);
407 return fileList.ToArray();
410 // Returns an array of strongly typed FileSystemInfo entries which will contain a listing
411 // of all the files and directories.
412 [ResourceExposure(ResourceScope.Machine)]
413 [ResourceConsumption(ResourceScope.Machine)]
414 public FileSystemInfo[] GetFileSystemInfos()
416 return InternalGetFileSystemInfos("*", SearchOption.TopDirectoryOnly);
419 // Returns an array of Directories in the current DirectoryInfo matching the
420 // given search criteria (ie, "System*" could match the System & System32
422 [ResourceExposure(ResourceScope.Machine)]
423 [ResourceConsumption(ResourceScope.Machine)]
424 public DirectoryInfo[] GetDirectories(String searchPattern)
426 if (searchPattern == null)
427 throw new ArgumentNullException("searchPattern");
428 Contract.EndContractBlock();
430 return InternalGetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
433 // Returns an array of Directories in the current DirectoryInfo matching the
434 // given search criteria (ie, "System*" could match the System & System32
436 [ResourceExposure(ResourceScope.Machine)]
437 [ResourceConsumption(ResourceScope.Machine)]
438 public DirectoryInfo[] GetDirectories(String searchPattern, SearchOption searchOption)
440 if (searchPattern == null)
441 throw new ArgumentNullException("searchPattern");
442 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
443 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
444 Contract.EndContractBlock();
446 return InternalGetDirectories(searchPattern, searchOption);
449 // Returns an array of Directories in the current DirectoryInfo matching the
450 // given search criteria (ie, "System*" could match the System & System32
452 [ResourceExposure(ResourceScope.Machine)]
453 [ResourceConsumption(ResourceScope.Machine)]
454 private DirectoryInfo[] InternalGetDirectories(String searchPattern, SearchOption searchOption)
456 Contract.Requires(searchPattern != null);
457 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
459 IEnumerable<DirectoryInfo> enble = FileSystemEnumerableFactory.CreateDirectoryInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
460 List<DirectoryInfo> fileList = new List<DirectoryInfo>(enble);
461 return fileList.ToArray();
464 [ResourceExposure(ResourceScope.Machine)]
465 [ResourceConsumption(ResourceScope.Machine)]
466 public IEnumerable<DirectoryInfo> EnumerateDirectories()
468 return InternalEnumerateDirectories("*", SearchOption.TopDirectoryOnly);
471 [ResourceExposure(ResourceScope.Machine)]
472 [ResourceConsumption(ResourceScope.Machine)]
473 public IEnumerable<DirectoryInfo> EnumerateDirectories(String searchPattern)
475 if (searchPattern == null)
476 throw new ArgumentNullException("searchPattern");
477 Contract.EndContractBlock();
479 return InternalEnumerateDirectories(searchPattern, SearchOption.TopDirectoryOnly);
482 [ResourceExposure(ResourceScope.Machine)]
483 [ResourceConsumption(ResourceScope.Machine)]
484 public IEnumerable<DirectoryInfo> EnumerateDirectories(String searchPattern, SearchOption searchOption)
486 if (searchPattern == null)
487 throw new ArgumentNullException("searchPattern");
488 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
489 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
490 Contract.EndContractBlock();
492 return InternalEnumerateDirectories(searchPattern, searchOption);
495 [ResourceExposure(ResourceScope.Machine)]
496 [ResourceConsumption(ResourceScope.Machine)]
497 private IEnumerable<DirectoryInfo> InternalEnumerateDirectories(String searchPattern, SearchOption searchOption)
499 Contract.Requires(searchPattern != null);
500 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
502 return FileSystemEnumerableFactory.CreateDirectoryInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
505 [ResourceExposure(ResourceScope.Machine)]
506 [ResourceConsumption(ResourceScope.Machine)]
507 public IEnumerable<FileInfo> EnumerateFiles()
509 return InternalEnumerateFiles("*", SearchOption.TopDirectoryOnly);
512 [ResourceExposure(ResourceScope.Machine)]
513 [ResourceConsumption(ResourceScope.Machine)]
514 public IEnumerable<FileInfo> EnumerateFiles(String searchPattern)
516 if (searchPattern == null)
517 throw new ArgumentNullException("searchPattern");
518 Contract.EndContractBlock();
520 return InternalEnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
523 [ResourceExposure(ResourceScope.Machine)]
524 [ResourceConsumption(ResourceScope.Machine)]
525 public IEnumerable<FileInfo> EnumerateFiles(String searchPattern, SearchOption searchOption)
527 if (searchPattern == null)
528 throw new ArgumentNullException("searchPattern");
529 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
530 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
531 Contract.EndContractBlock();
533 return InternalEnumerateFiles(searchPattern, searchOption);
536 [ResourceExposure(ResourceScope.Machine)]
537 [ResourceConsumption(ResourceScope.Machine)]
538 private IEnumerable<FileInfo> InternalEnumerateFiles(String searchPattern, SearchOption searchOption)
540 Contract.Requires(searchPattern != null);
541 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
543 return FileSystemEnumerableFactory.CreateFileInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
546 [ResourceExposure(ResourceScope.Machine)]
547 [ResourceConsumption(ResourceScope.Machine)]
548 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos()
550 return InternalEnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly);
553 [ResourceExposure(ResourceScope.Machine)]
554 [ResourceConsumption(ResourceScope.Machine)]
555 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(String searchPattern)
557 if (searchPattern == null)
558 throw new ArgumentNullException("searchPattern");
559 Contract.EndContractBlock();
561 return InternalEnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
564 [ResourceExposure(ResourceScope.Machine)]
565 [ResourceConsumption(ResourceScope.Machine)]
566 public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(String searchPattern, SearchOption searchOption)
568 if (searchPattern == null)
569 throw new ArgumentNullException("searchPattern");
570 if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
571 throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
572 Contract.EndContractBlock();
574 return InternalEnumerateFileSystemInfos(searchPattern, searchOption);
577 [ResourceExposure(ResourceScope.Machine)]
578 [ResourceConsumption(ResourceScope.Machine)]
579 private IEnumerable<FileSystemInfo> InternalEnumerateFileSystemInfos(String searchPattern, SearchOption searchOption)
581 Contract.Requires(searchPattern != null);
582 Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
584 return FileSystemEnumerableFactory.CreateFileSystemInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
587 // Returns the root portion of the given path. The resulting string
588 // consists of those rightmost characters of the path that constitute the
589 // root of the path. Possible patterns for the resulting string are: An
590 // empty string (a relative path on the current drive), "\" (an absolute
591 // path on the current drive), "X:" (a relative path on a given drive,
592 // where X is the drive letter), "X:\" (an absolute path on a given drive),
593 // and "\\server\share" (a UNC path for a given server and share name).
594 // The resulting string is null if path is null.
597 public DirectoryInfo Root {
598 [System.Security.SecuritySafeCritical]
599 [ResourceExposure(ResourceScope.None)]
600 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
604 int rootLength = Path.GetRootLength(FullPath);
605 String rootPath = FullPath.Substring(0, rootLength);
606 demandPath = Directory.GetDemandDir(rootPath, true);
609 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath);
610 sourceState.EnsureState();
612 new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false).Demand();
614 return new DirectoryInfo(rootPath);
618 [System.Security.SecuritySafeCritical]
619 [ResourceExposure(ResourceScope.Machine)]
620 [ResourceConsumption(ResourceScope.Machine)]
621 public void MoveTo(String destDirName) {
622 if (destDirName==null)
623 throw new ArgumentNullException("destDirName");
624 if (destDirName.Length==0)
625 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName");
626 Contract.EndContractBlock();
629 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, Directory.GetDemandDir(FullPath, true));
630 sourceState.EnsureState();
632 new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandDir, false, false).Demand();
634 String fullDestDirName = Path.GetFullPathInternal(destDirName);
636 if (!fullDestDirName.EndsWith(Path.DirectorySeparatorChar))
637 fullDestDirName = fullDestDirName + Path.DirectorySeparatorChar;
639 demandPath = fullDestDirName + '.';
641 // Demand read & write permission to destination. The reason is
642 // we hand back a DirectoryInfo to the destination that would allow
643 // you to read a directory listing from that directory. Sure, you
644 // had the ability to read the file contents in the old location,
645 // but you technically also need read permissions to the new
646 // location as well, and write is not a true superset of read.
648 FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, demandPath);
649 destState.EnsureState();
651 new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath).Demand();
654 String fullSourcePath;
655 if (FullPath.EndsWith(Path.DirectorySeparatorChar))
656 fullSourcePath = FullPath;
658 fullSourcePath = FullPath + Path.DirectorySeparatorChar;
660 if (String.Compare(fullSourcePath, fullDestDirName, StringComparison.OrdinalIgnoreCase) == 0)
661 throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent"));
663 String sourceRoot = Path.GetPathRoot(fullSourcePath);
664 String destinationRoot = Path.GetPathRoot(fullDestDirName);
666 if (String.Compare(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase) != 0)
667 throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot"));
669 if (!Win32Native.MoveFile(FullPath, destDirName))
671 int hr = Marshal.GetLastWin32Error();
672 if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // A dubious error code
674 hr = Win32Native.ERROR_PATH_NOT_FOUND;
675 __Error.WinIOError(hr, DisplayPath);
678 if (hr == Win32Native.ERROR_ACCESS_DENIED) // We did this for Win9x. We can't change it for backcomp.
679 throw new IOException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", DisplayPath));
681 __Error.WinIOError(hr,String.Empty);
683 FullPath = fullDestDirName;
684 OriginalPath = destDirName;
685 DisplayPath = GetDisplayName(OriginalPath, FullPath);
686 demandDir = new String[] { Directory.GetDemandDir(FullPath, true) };
688 // Flush any cached information about the directory.
689 _dataInitialised = -1;
692 [System.Security.SecuritySafeCritical]
693 [ResourceExposure(ResourceScope.None)]
694 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
695 public override void Delete()
697 Directory.Delete(FullPath, OriginalPath, false, true);
700 [System.Security.SecuritySafeCritical]
701 [ResourceExposure(ResourceScope.None)]
702 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
703 public void Delete(bool recursive)
705 Directory.Delete(FullPath, OriginalPath, recursive, true);
708 // Returns the fully qualified path
709 public override String ToString()
714 private static String GetDisplayName(String originalPath, String fullPath)
716 Contract.Assert(originalPath != null);
717 Contract.Assert(fullPath != null);
719 String displayName = "";
721 // Special case "<DriveLetter>:" to point to "<CurrentDirectory>" instead
722 if ((originalPath.Length == 2) && (originalPath[1] == ':'))
729 displayName = GetDirName(fullPath);
731 displayName = originalPath;
737 private static String GetDirName(String fullPath)
739 Contract.Assert(fullPath != null);
741 String dirName = null;
742 if (fullPath.Length > 3)
745 if (fullPath.EndsWith(Path.DirectorySeparatorChar))
747 s = fullPath.Substring(0, fullPath.Length - 1);
749 dirName = Path.GetFileName(s);
753 dirName = fullPath; // For rooted paths, like "c:\"