// // System.IO.DirectoryInfo.cs // // Authors: // Miguel de Icaza, miguel@ximian.com // Jim Richardson, develop@wtfo-guru.com // Dan Lewis, dihlewis@yahoo.co.uk // Sebastien Pouliot // Marek Safar // // Copyright (C) 2002 Ximian, Inc. // Copyright (C) 2001 Moonlight Enterprises, All Rights Reserved // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com) // Copyright (C) 2014 Xamarin, Inc (http://www.xamarin.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.Collections.Generic; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Text; using System.Security.AccessControl; namespace System.IO { [Serializable] [ComVisible (true)] public sealed class DirectoryInfo : FileSystemInfo { private string current; private string parent; public DirectoryInfo (string path) : this (path, false) { } internal DirectoryInfo (string path, bool simpleOriginalPath) { CheckPath (path); SecurityManager.EnsureElevatedPermissions (); // this is a no-op outside moonlight FullPath = Path.GetFullPath (path); if (simpleOriginalPath) OriginalPath = Path.GetFileName (path); else OriginalPath = path; Initialize (); } private DirectoryInfo (SerializationInfo info, StreamingContext context) : base (info, context) { Initialize (); } void Initialize () { int len = FullPath.Length - 1; if ((len > 1) && (FullPath [len] == Path.DirectorySeparatorChar)) len--; int last = FullPath.LastIndexOf (Path.DirectorySeparatorChar, len); if ((last == -1) || ((last == 0) && (len == 0))) { current = FullPath; parent = null; } else { current = FullPath.Substring (last + 1, len - last); if (last == 0 && !Environment.IsRunningOnWindows) parent = Path.DirectorySeparatorStr; else parent = FullPath.Substring (0, last); // adjust for drives, i.e. a special case for windows if (Environment.IsRunningOnWindows) { if ((parent.Length == 2) && (parent [1] == ':') && Char.IsLetter (parent [0])) parent += Path.DirectorySeparatorChar; } } } // properties public override bool Exists { get { Refresh (false); if (stat.Attributes == MonoIO.InvalidFileAttributes) return false; if ((stat.Attributes & FileAttributes.Directory) == 0) return false; return true; } } public override string Name { get { return current; } } public DirectoryInfo Parent { get { if ((parent == null) || (parent.Length == 0)) return null; return new DirectoryInfo (parent); } } public DirectoryInfo Root { get { string root = Path.GetPathRoot (FullPath); if (root == null) return null; return new DirectoryInfo (root); } } // creational methods public void Create () { Directory.CreateDirectory (FullPath); } public DirectoryInfo CreateSubdirectory (string path) { CheckPath (path); path = Path.Combine (FullPath, path); Directory.CreateDirectory (path); return new DirectoryInfo (path); } // directory listing methods public FileInfo [] GetFiles () { return GetFiles ("*"); } public FileInfo [] GetFiles (string searchPattern) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); string [] names = Directory.GetFiles (FullPath, searchPattern); FileInfo[] infos = new FileInfo [names.Length]; int i = 0; foreach (string name in names) infos [i++] = new FileInfo (name); return infos; } public DirectoryInfo [] GetDirectories () { return GetDirectories ("*"); } public DirectoryInfo [] GetDirectories (string searchPattern) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); string [] names = Directory.GetDirectories (FullPath, searchPattern); DirectoryInfo[] infos = new DirectoryInfo [names.Length]; int i = 0; foreach (string name in names) infos [i++] = new DirectoryInfo (name); return infos; } public FileSystemInfo [] GetFileSystemInfos () { return GetFileSystemInfos ("*"); } public FileSystemInfo [] GetFileSystemInfos (string searchPattern) { return GetFileSystemInfos (searchPattern, SearchOption.TopDirectoryOnly); } #if NET_4_0 public #endif FileSystemInfo [] GetFileSystemInfos (string searchPattern, SearchOption searchOption) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); if (searchOption != SearchOption.TopDirectoryOnly && searchOption != SearchOption.AllDirectories) throw new ArgumentOutOfRangeException ("searchOption", "Must be TopDirectoryOnly or AllDirectories"); if (!Directory.Exists (FullPath)) throw new IOException ("Invalid directory"); List infos = new List (); InternalGetFileSystemInfos (searchPattern, searchOption, infos); return infos.ToArray (); } void InternalGetFileSystemInfos (string searchPattern, SearchOption searchOption, List infos) { // UnauthorizedAccessExceptions might happen here and break everything for SearchOption.AllDirectories string [] dirs = Directory.GetDirectories (FullPath, searchPattern); string [] files = Directory.GetFiles (FullPath, searchPattern); Array.ForEach (dirs, (dir) => { infos.Add (new DirectoryInfo (dir)); }); Array.ForEach (files, (file) => { infos.Add (new FileInfo (file)); }); if (dirs.Length == 0 || searchOption == SearchOption.TopDirectoryOnly) return; foreach (string dir in dirs) { DirectoryInfo dinfo = new DirectoryInfo (dir); dinfo.InternalGetFileSystemInfos (searchPattern, searchOption, infos); } } // directory management methods public override void Delete () { Delete (false); } public void Delete (bool recursive) { Directory.Delete (FullPath, recursive); } public void MoveTo (string destDirName) { if (destDirName == null) throw new ArgumentNullException ("destDirName"); if (destDirName.Length == 0) throw new ArgumentException ("An empty file name is not valid.", "destDirName"); Directory.Move (FullPath, Path.GetFullPath (destDirName)); FullPath = OriginalPath = destDirName; Initialize (); } public override string ToString () { return OriginalPath; } public DirectoryInfo[] GetDirectories (string searchPattern, SearchOption searchOption) { //NULL-check of searchPattern is done in Directory.GetDirectories string [] names = Directory.GetDirectories (FullPath, searchPattern, searchOption); //Convert the names to DirectoryInfo instances DirectoryInfo[] infos = new DirectoryInfo [names.Length]; for (int i = 0; i EnumerateDirectories () { return EnumerateDirectories ("*", SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateDirectories (string searchPattern) { return EnumerateDirectories (searchPattern, SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateDirectories (string searchPattern, SearchOption searchOption) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); return CreateEnumerateDirectoriesIterator (searchPattern, searchOption); } IEnumerable CreateEnumerateDirectoriesIterator (string searchPattern, SearchOption searchOption) { foreach (string name in Directory.EnumerateDirectories (FullPath, searchPattern, searchOption)) yield return new DirectoryInfo (name); } public IEnumerable EnumerateFiles () { return EnumerateFiles ("*", SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateFiles (string searchPattern) { return EnumerateFiles (searchPattern, SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateFiles (string searchPattern, SearchOption searchOption) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); return CreateEnumerateFilesIterator (searchPattern, searchOption); } IEnumerable CreateEnumerateFilesIterator (string searchPattern, SearchOption searchOption) { foreach (string name in Directory.EnumerateFiles (FullPath, searchPattern, searchOption)) yield return new FileInfo (name); } public IEnumerable EnumerateFileSystemInfos () { return EnumerateFileSystemInfos ("*", SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateFileSystemInfos (string searchPattern) { return EnumerateFileSystemInfos (searchPattern, SearchOption.TopDirectoryOnly); } public IEnumerable EnumerateFileSystemInfos (string searchPattern, SearchOption searchOption) { if (searchPattern == null) throw new ArgumentNullException ("searchPattern"); if (searchOption != SearchOption.TopDirectoryOnly && searchOption != SearchOption.AllDirectories) throw new ArgumentOutOfRangeException ("searchoption"); return EnumerateFileSystemInfos (FullPath, searchPattern, searchOption); } static internal IEnumerable EnumerateFileSystemInfos (string full, string searchPattern, SearchOption searchOption) { string path_with_pattern = Path.Combine (full, searchPattern); IntPtr handle; MonoIOError error; FileAttributes rattr; bool subdirs = searchOption == SearchOption.AllDirectories; Path.Validate (full); string s = MonoIO.FindFirst (full, path_with_pattern, out rattr, out error, out handle); if (s == null) yield break; if (error != 0) throw MonoIO.GetException (Path.GetDirectoryName (path_with_pattern), (MonoIOError) error); try { do { if (((rattr & FileAttributes.ReparsePoint) == 0)){ if ((rattr & FileAttributes.Directory) != 0) yield return new DirectoryInfo (s); else yield return new FileInfo (s); } if (((rattr & FileAttributes.Directory) != 0) && subdirs) foreach (FileSystemInfo child in EnumerateFileSystemInfos (s, searchPattern, searchOption)) yield return child; } while ((s = MonoIO.FindNext (handle, out rattr, out error)) != null); } finally { MonoIO.FindClose (handle); } } #endif } }