You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

287 lines
19 KiB

  1. /* Copyright (C) 2008-2016 Peter Palotas, Jeffrey Jangli, Alexandr Normuradov
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to deal
  5. * in the Software without restriction, including without limitation the rights
  6. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. * copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. * THE SOFTWARE.
  20. */
  21. using System;
  22. using System.Collections.Generic;
  23. using System.IO;
  24. using System.Linq;
  25. using System.Security;
  26. namespace Alphaleonis.Win32.Filesystem
  27. {
  28. partial class Directory
  29. {
  30. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  31. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  32. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  33. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  34. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  35. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  36. /// </summary>
  37. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  38. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  39. /// <exception cref="ArgumentException"/>
  40. /// <exception cref="ArgumentNullException"/>
  41. /// <exception cref="DirectoryNotFoundException"/>
  42. /// <exception cref="IOException"/>
  43. /// <exception cref="NotSupportedException"/>
  44. /// <exception cref="UnauthorizedAccessException"/>
  45. /// <param name="path">The target directory.</param>
  46. [SecurityCritical]
  47. public static Dictionary<string, long> GetProperties(string path)
  48. {
  49. return GetPropertiesCore(null, path, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.RelativePath);
  50. }
  51. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  52. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  53. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  54. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  55. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  56. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  57. /// </summary>
  58. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  59. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  60. /// <exception cref="ArgumentException"/>
  61. /// <exception cref="ArgumentNullException"/>
  62. /// <exception cref="DirectoryNotFoundException"/>
  63. /// <exception cref="IOException"/>
  64. /// <exception cref="NotSupportedException"/>
  65. /// <exception cref="UnauthorizedAccessException"/>
  66. /// <param name="path">The target directory.</param>
  67. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  68. [SecurityCritical]
  69. public static Dictionary<string, long> GetProperties(string path, PathFormat pathFormat)
  70. {
  71. return GetPropertiesCore(null, path, DirectoryEnumerationOptions.FilesAndFolders, pathFormat);
  72. }
  73. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  74. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  75. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  76. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  77. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  78. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  79. /// </summary>
  80. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  81. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  82. /// <exception cref="ArgumentException"/>
  83. /// <exception cref="ArgumentNullException"/>
  84. /// <exception cref="DirectoryNotFoundException"/>
  85. /// <exception cref="IOException"/>
  86. /// <exception cref="NotSupportedException"/>
  87. /// <exception cref="UnauthorizedAccessException"/>
  88. /// <param name="path">The target directory.</param>
  89. /// <param name="options"><see cref="DirectoryEnumerationOptions"/> flags that specify how the directory is to be enumerated.</param>
  90. [SecurityCritical]
  91. public static Dictionary<string, long> GetProperties(string path, DirectoryEnumerationOptions options)
  92. {
  93. return GetPropertiesCore(null, path, options, PathFormat.RelativePath);
  94. }
  95. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  96. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  97. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  98. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  99. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  100. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  101. /// </summary>
  102. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  103. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  104. /// <exception cref="ArgumentException"/>
  105. /// <exception cref="ArgumentNullException"/>
  106. /// <exception cref="DirectoryNotFoundException"/>
  107. /// <exception cref="IOException"/>
  108. /// <exception cref="NotSupportedException"/>
  109. /// <exception cref="UnauthorizedAccessException"/>
  110. /// <param name="path">The target directory.</param>
  111. /// <param name="options"><see cref="DirectoryEnumerationOptions"/> flags that specify how the directory is to be enumerated.</param>
  112. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  113. [SecurityCritical]
  114. public static Dictionary<string, long> GetProperties(string path, DirectoryEnumerationOptions options, PathFormat pathFormat)
  115. {
  116. return GetPropertiesCore(null, path, options, pathFormat);
  117. }
  118. #region Transactional
  119. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  120. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  121. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  122. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  123. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  124. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  125. /// </summary>
  126. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  127. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  128. /// <exception cref="ArgumentException"/>
  129. /// <exception cref="ArgumentNullException"/>
  130. /// <exception cref="DirectoryNotFoundException"/>
  131. /// <exception cref="IOException"/>
  132. /// <exception cref="NotSupportedException"/>
  133. /// <exception cref="UnauthorizedAccessException"/>
  134. /// <param name="transaction">The transaction.</param>
  135. /// <param name="path">The target directory.</param>
  136. [SecurityCritical]
  137. public static Dictionary<string, long> GetPropertiesTransacted(KernelTransaction transaction, string path)
  138. {
  139. return GetPropertiesCore(transaction, path, DirectoryEnumerationOptions.FilesAndFolders, PathFormat.RelativePath);
  140. }
  141. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  142. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  143. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  144. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  145. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  146. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  147. /// </summary>
  148. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  149. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  150. /// <exception cref="ArgumentException"/>
  151. /// <exception cref="ArgumentNullException"/>
  152. /// <exception cref="DirectoryNotFoundException"/>
  153. /// <exception cref="IOException"/>
  154. /// <exception cref="NotSupportedException"/>
  155. /// <exception cref="UnauthorizedAccessException"/>
  156. /// <param name="transaction">The transaction.</param>
  157. /// <param name="path">The target directory.</param>
  158. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  159. [SecurityCritical]
  160. public static Dictionary<string, long> GetPropertiesTransacted(KernelTransaction transaction, string path, PathFormat pathFormat)
  161. {
  162. return GetPropertiesCore(transaction, path, DirectoryEnumerationOptions.FilesAndFolders, pathFormat);
  163. }
  164. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  165. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  166. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  167. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  168. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  169. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  170. /// </summary>
  171. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  172. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  173. /// <exception cref="ArgumentException"/>
  174. /// <exception cref="ArgumentNullException"/>
  175. /// <exception cref="DirectoryNotFoundException"/>
  176. /// <exception cref="IOException"/>
  177. /// <exception cref="NotSupportedException"/>
  178. /// <exception cref="UnauthorizedAccessException"/>
  179. /// <param name="transaction">The transaction.</param>
  180. /// <param name="path">The target directory.</param>
  181. /// <param name="options"><see cref="DirectoryEnumerationOptions"/> flags that specify how the directory is to be enumerated.</param>
  182. [SecurityCritical]
  183. public static Dictionary<string, long> GetPropertiesTransacted(KernelTransaction transaction, string path, DirectoryEnumerationOptions options)
  184. {
  185. return GetPropertiesCore(transaction, path, options, PathFormat.RelativePath);
  186. }
  187. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  188. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  189. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  190. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  191. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  192. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  193. /// </summary>
  194. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  195. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  196. /// <exception cref="ArgumentException"/>
  197. /// <exception cref="ArgumentNullException"/>
  198. /// <exception cref="DirectoryNotFoundException"/>
  199. /// <exception cref="IOException"/>
  200. /// <exception cref="NotSupportedException"/>
  201. /// <exception cref="UnauthorizedAccessException"/>
  202. /// <param name="transaction">The transaction.</param>
  203. /// <param name="path">The target directory.</param>
  204. /// <param name="options"><see cref="DirectoryEnumerationOptions"/> flags that specify how the directory is to be enumerated.</param>
  205. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  206. [SecurityCritical]
  207. public static Dictionary<string, long> GetPropertiesTransacted(KernelTransaction transaction, string path, DirectoryEnumerationOptions options, PathFormat pathFormat)
  208. {
  209. return GetPropertiesCore(transaction, path, options, pathFormat);
  210. }
  211. #endregion // Transactional
  212. #region Internal Methods
  213. /// <summary>[AlphaFS] Gets the properties of the particular directory without following any symbolic links or mount points.
  214. /// <para>Properties include aggregated info from <see cref="FileAttributes"/> of each encountered file system object, plus additional ones: Total, File, Size and Error.</para>
  215. /// <para><b>Total:</b> is the total number of enumerated objects.</para>
  216. /// <para><b>File:</b> is the total number of files. File is considered when object is neither <see cref="FileAttributes.Directory"/> nor <see cref="FileAttributes.ReparsePoint"/>.</para>
  217. /// <para><b>Size:</b> is the total size of enumerated objects.</para>
  218. /// <para><b>Error:</b> is the total number of errors encountered during enumeration.</para>
  219. /// </summary>
  220. /// <returns>A dictionary mapping the keys mentioned above to their respective aggregated values.</returns>
  221. /// <remarks><b>Directory:</b> is an object which has <see cref="FileAttributes.Directory"/> attribute without <see cref="FileAttributes.ReparsePoint"/> one.</remarks>
  222. /// <exception cref="ArgumentException"/>
  223. /// <exception cref="ArgumentNullException"/>
  224. /// <exception cref="DirectoryNotFoundException"/>
  225. /// <exception cref="IOException"/>
  226. /// <exception cref="NotSupportedException"/>
  227. /// <exception cref="UnauthorizedAccessException"/>
  228. /// <param name="transaction">The transaction.</param>
  229. /// <param name="path">The target directory.</param>
  230. /// <param name="options"><see cref="DirectoryEnumerationOptions"/> flags that specify how the directory is to be enumerated.</param>
  231. /// <param name="pathFormat">Indicates the format of the path parameter(s).</param>
  232. [SecurityCritical]
  233. internal static Dictionary<string, long> GetPropertiesCore(KernelTransaction transaction, string path, DirectoryEnumerationOptions options, PathFormat pathFormat)
  234. {
  235. long total = 0;
  236. long size = 0;
  237. const string propFile = "File";
  238. const string propTotal = "Total";
  239. const string propSize = "Size";
  240. var typeOfAttrs = typeof(FileAttributes);
  241. var attributes = Enum.GetValues(typeOfAttrs);
  242. var props = Enum.GetNames(typeOfAttrs).OrderBy(attrs => attrs).ToDictionary<string, string, long>(name => name, name => 0);
  243. var pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);
  244. foreach (var fsei in EnumerateFileSystemEntryInfosCore<FileSystemEntryInfo>(transaction, pathLp, Path.WildcardStarMatchAll, options, PathFormat.LongFullPath))
  245. {
  246. total++;
  247. if (!fsei.IsDirectory)
  248. size += fsei.FileSize;
  249. var fsei1 = fsei;
  250. foreach (var attributeMarker in attributes.Cast<FileAttributes>().Where(attributeMarker => (fsei1.Attributes & attributeMarker) != 0))
  251. props[((attributeMarker & FileAttributes.Directory) != 0 ? FileAttributes.Directory : attributeMarker).ToString()]++;
  252. }
  253. // Adjust regular files count.
  254. props.Add(propFile, total - props[FileAttributes.Directory.ToString()] - props[FileAttributes.ReparsePoint.ToString()]);
  255. props.Add(propTotal, total);
  256. props.Add(propSize, size);
  257. return props;
  258. }
  259. #endregion // Internal Methods
  260. }
  261. }