Changeset 1708
- Timestamp:
- 1/28/2010 1:11:18 AM (3 years ago)
- Location:
- branches/eraser6/CodeReview/Eraser.Util
- Files:
-
- 2 edited
-
NativeMethods/Kernel.cs (modified) (1 diff)
-
StreamInfo.cs (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/eraser6/CodeReview/Eraser.Util/NativeMethods/Kernel.cs
r1593 r1708 48 48 [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 49 49 [return: MarshalAs(UnmanagedType.Bool)] 50 [Obsolete]51 50 public static extern bool DeleteFile(string lpFileName); 52 51 -
branches/eraser6/CodeReview/Eraser.Util/StreamInfo.cs
r1705 r1708 31 31 namespace Eraser.Util 32 32 { 33 public class StreamInfo 33 /// <summary> 34 /// Provides methods for the deletion, and opening of file alternate data streams, 35 /// and aids in the creation of <see cref="System.IO.FileStream"/> objects. 36 /// </summary> 37 public class StreamInfo : FileSystemInfo 34 38 { 35 39 /// <summary> 36 /// Initializes a new instance of the Eraser.Util.StreamInfo class, which 37 /// acts as a wrapper for a file path. 38 /// </summary> 39 /// <param name="path">The fully qualified name (with :ADSName for ADSes) 40 /// of the new file, or the relative file name.</param> 41 public StreamInfo(string path) 42 { 43 //Separate the path into the ADS and the file. 44 if (path.IndexOf(':') != path.LastIndexOf(':')) 45 { 46 int streamNameColon = path.IndexOf(':', path.IndexOf(':') + 1); 47 fileName = path.Substring(0, streamNameColon); 48 streamName = path.Substring(streamNameColon + 1); 49 } 50 else 51 { 52 fileName = path; 40 /// Constructor. 41 /// <param name="filename">The fully qualified name of the new file, or 42 /// the relative file name.</param> 43 public StreamInfo(string filename) 44 : this(filename, null) 45 { 46 } 47 48 /// <summary> 49 /// Constructor. 50 /// </summary> 51 /// <param name="filename">The path to the file.</param> 52 /// <param name="streamName">The name of the alternate data stream, or null 53 /// to refer to the unnamed stream.</param> 54 public StreamInfo(string filename, string streamName) 55 { 56 OriginalPath = filename; 57 FullPath = Path.GetFullPath(filename); 58 FileName = FullPath; 59 StreamName = streamName; 60 61 if (!string.IsNullOrEmpty(streamName)) 62 { 63 OriginalPath += ":" + streamName; 64 FullPath += ":" + streamName; 65 } 66 67 Refresh(); 68 } 69 70 /// <summary> 71 /// The full name of the stream, including the stream name if provided. 72 /// </summary> 73 public override string FullName 74 { 75 get 76 { 77 return FullPath; 78 } 79 } 80 81 /// <summary> 82 /// Gets a value indicating whether a file exists. 83 /// </summary> 84 public override bool Exists 85 { 86 get 87 { 88 bool result = System.IO.File.Exists(FullName); 89 return result && 90 (string.IsNullOrEmpty(StreamName) || true/*verify the ADS exists*/); 91 } 92 } 93 94 /// <summary> 95 /// Gets a string representing the directory's full path. 96 /// </summary> 97 public String DirectoryName 98 { 99 get 100 { 101 return Path.GetDirectoryName(FullPath); 53 102 } 54 103 } … … 63 112 return new DirectoryInfo(DirectoryName); 64 113 } 65 } 66 67 /// <summary> 68 /// Gets a string representing the containing directory's full path. 69 /// </summary> 70 public string DirectoryName 71 { 72 get 73 { 74 return fileName.Substring(0, fileName.LastIndexOf(Path.DirectorySeparatorChar) + 1); 75 } 76 } 77 78 /// <summary> 79 /// Gets the full name of the file, including the stream name. 80 /// </summary> 81 public string FullName 82 { 83 get 84 { 85 if (streamName != null) 86 return fileName + ':' + streamName; 87 return fileName; 88 } 89 } 90 91 /// <summary> 92 /// Gets the name of the file. 93 /// </summary> 94 public string Name 95 { 96 get { return fileName; } 97 } 98 99 /// <summary> 100 /// Gets an instance of the main file. If this object refers to an ADS, the 101 /// result is null. 114 } 115 116 /// <summary> 117 /// Gets the file which contains this stream. 102 118 /// </summary> 103 119 public FileInfo File … … 105 121 get 106 122 { 107 if (streamName == null) 108 return new FileInfo(fileName); 109 return null; 110 } 111 } 112 113 /// <summary> 114 /// Gets or sets the file attributes on this stream. 115 /// </summary> 116 public FileAttributes Attributes 117 { 118 get { return (FileAttributes)NativeMethods.GetFileAttributes(FullName); } 119 set { NativeMethods.SetFileAttributes(FullName, (uint)value); } 120 } 121 122 /// <summary> 123 /// Gets a value indicating whether the stream exists. 124 /// </summary> 125 public bool Exists 126 { 127 get 128 { 129 using (SafeFileHandle handle = NativeMethods.CreateFile( 130 FullName, NativeMethods.GENERIC_READ, NativeMethods.FILE_SHARE_READ, 131 IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero)) 123 return new FileInfo(FileName); 124 } 125 } 126 127 /// <summary> 128 /// The full path to the file we are encapsulating. 129 /// </summary> 130 public string FileName 131 { 132 get; 133 private set; 134 } 135 136 /// <summary> 137 /// Gets the name of the stream. 138 /// </summary> 139 public override string Name 140 { 141 get { return StreamName; } 142 } 143 144 /// <summary> 145 /// Gets or sets a value that determines if the current file is read only. 146 /// </summary> 147 public bool IsReadOnly 148 { 149 get { return (Attributes & FileAttributes.ReadOnly) != 0; } 150 set 151 { 152 Attributes = value ? 153 (Attributes | FileAttributes.ReadOnly) : 154 (Attributes & ~FileAttributes.ReadOnly); 155 } 156 } 157 158 /// <summary> 159 /// Gets the size, in bytes, of the current stream. 160 /// </summary> 161 public long Length 162 { 163 get 164 { 165 long fileSize; 166 using (SafeFileHandle handle = OpenHandle( 167 FileMode.Open, FileAccess.Read, FileShare.ReadWrite, FileOptions.None)) 132 168 { 133 if (!handle.IsInvalid)134 return true;135 136 int errorCode = Marshal.GetLastWin32Error();137 switch (errorCode)138 {139 case Win32ErrorCode.FileNotFound:140 case Win32ErrorCode.PathNotFound:141 return false;142 case Win32ErrorCode.AccessDenied:143 case Win32ErrorCode.SharingViolation:144 return true;145 default:146 throw Win32ErrorCode.GetExceptionForWin32Error(errorCode);147 }148 }149 }150 }151 152 /// <summary>153 /// Gets or sets a value that determines if the current file is read only.154 /// </summary>155 public bool IsReadOnly156 {157 get158 {159 return (Attributes & FileAttributes.ReadOnly) != 0;160 }161 162 set163 {164 if (value)165 Attributes |= FileAttributes.ReadOnly;166 else167 Attributes &= ~FileAttributes.ReadOnly;168 }169 }170 171 /// <summary>172 /// Gets the size of the current stream.173 /// </summary>174 public long Length175 {176 get177 {178 long fileSize;179 using (SafeFileHandle handle = fileHandle)180 169 if (NativeMethods.GetFileSizeEx(handle, out fileSize)) 181 170 return fileSize; 171 } 182 172 183 173 return 0; … … 185 175 } 186 176 187 public DateTime LastAccessTime 188 { 189 get 190 { 191 DateTime creationTime, lastAccess, lastWrite; 192 GetFileTime(out creationTime, out lastAccess, out lastWrite); 193 return lastAccess; 194 } 195 set 196 { 197 SetFileTime(DateTime.MinValue, value, DateTime.MinValue); 198 } 199 } 200 201 public DateTime LastWriteTime 202 { 203 get 204 { 205 DateTime creationTime, lastAccess, lastWrite; 206 GetFileTime(out creationTime, out lastAccess, out lastWrite); 207 return lastWrite; 208 } 209 set 210 { 211 SetFileTime(DateTime.MinValue, DateTime.MinValue, value); 212 } 213 } 214 215 public DateTime CreationTime 216 { 217 get 218 { 219 DateTime creationTime, lastAccess, lastWrite; 220 GetFileTime(out creationTime, out lastAccess, out lastWrite); 221 return creationTime; 222 } 223 set 224 { 225 SetFileTime(value, DateTime.MinValue, DateTime.MinValue); 226 } 227 } 228 229 private void GetFileTime(out DateTime creationTime, out DateTime lastAccess, 230 out DateTime lastWrite) 231 { 232 SafeFileHandle handle = exclusiveHandle; 233 bool ownsHandle = false; 234 try 235 { 236 if (handle == null || handle.IsClosed || handle.IsInvalid) 177 /// <summary> 178 /// Creates the file if it already does not exist, then creates the alternate 179 /// data stream. 180 /// </summary> 181 public FileStream Create() 182 { 183 return Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None, FileOptions.None); 184 } 185 186 /// <summary> 187 /// Permanently deletes the stream. If this refers to the unnamed stream, all 188 /// alternate data streams are also deleted. 189 /// </summary> 190 public override void Delete() 191 { 192 if (!NativeMethods.DeleteFile(FullName)) 193 { 194 int errorCode = Marshal.GetLastWin32Error(); 195 switch (errorCode) 237 196 { 238 handle = fileHandle; 239 ownsHandle = true; 197 case Win32ErrorCode.PathNotFound: 198 break; 199 default: 200 throw Win32ErrorCode.GetExceptionForWin32Error(errorCode); 240 201 } 241 202 } 242 catch (ObjectDisposedException)243 {244 handle = fileHandle;245 ownsHandle = true;246 }247 248 try249 {250 Util.File.GetFileTime(handle, out creationTime, out lastAccess, out lastWrite);251 }252 finally253 {254 if (ownsHandle)255 handle.Close();256 }257 }258 259 private void SetFileTime(DateTime creationTime, DateTime lastAccess, DateTime lastWrite)260 {261 SafeFileHandle handle = exclusiveHandle;262 bool ownsHandle = false;263 try264 {265 if (handle == null || handle.IsClosed || handle.IsInvalid)266 {267 handle = fileHandle;268 ownsHandle = true;269 }270 }271 catch (ObjectDisposedException)272 {273 handle = fileHandle;274 ownsHandle = true;275 }276 277 try278 {279 Util.File.SetFileTime(handle, creationTime, lastAccess, lastWrite);280 }281 finally282 {283 if (ownsHandle)284 handle.Close();285 }286 }287 288 /// <summary>289 /// Permanently deletes a file.290 /// </summary>291 public void Delete()292 {293 if (streamName == null)294 File.Delete();295 else296 if (!NativeMethods.DeleteFile(FullName))297 throw Win32ErrorCode.GetExceptionForWin32Error(Marshal.GetLastWin32Error());298 203 } 299 204 … … 368 273 } 369 274 275 /// <summary> 276 /// Creates a read-only System.IO.FileStream. 277 /// </summary> 278 /// <returns>A new read-only System.IO.FileStream object.</returns> 279 public FileStream OpenRead() 280 { 281 return Open(FileMode.Open, FileAccess.Read, FileShare.Read, FileOptions.None); 282 } 283 284 /// <summary> 285 /// Creates a write-only System.IO.FileStream. 286 /// </summary> 287 /// <returns>A new write-only unshared System.IO.FileStream object.</returns> 288 public FileStream OpenWrite() 289 { 290 return Open(FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, FileOptions.None); 291 } 292 370 293 private SafeFileHandle OpenHandle(FileMode mode, FileAccess access, FileShare share, 371 294 FileOptions options) … … 393 316 if ((options & FileOptions.Asynchronous) != 0) 394 317 throw new NotSupportedException("Asynchronous handles are not implemented."); 395 318 396 319 //Create the handle 397 320 SafeFileHandle result = NativeMethods.CreateFile(FullName, iAccess, … … 404 327 } 405 328 406 //Cache the handle if we have an exclusive handle - this is used for things like407 //file times.408 if (share == FileShare.None)409 exclusiveHandle = result;410 329 return result; 411 330 } … … 414 333 /// Returns the path as a string. 415 334 /// </summary> 416 /// <returns>A string representing the path.</returns>335 /// <returns>A string containing the path given to the constructor.</returns> 417 336 public override string ToString() 418 337 { 419 return FullName; 420 } 421 422 /// <summary> 423 /// Retrieves a file handle with read access and with all sharing enabled. 424 /// </summary> 425 private SafeFileHandle fileHandle 426 { 427 get 428 { 429 return OpenHandle(FileMode.Open, FileAccess.Read, FileShare.ReadWrite | 430 FileShare.Delete, FileOptions.None); 431 } 432 } 433 434 /// <summary> 435 /// Cached exclusive file handle. This is used for setting file access times 436 /// </summary> 437 private SafeFileHandle exclusiveHandle; 438 private string fileName; 439 private string streamName; 338 return OriginalPath; 339 } 340 341 /// <summary> 342 /// The name of the stream we are encapsulating. 343 /// </summary> 344 private string StreamName; 440 345 } 441 346 }
Note: See TracChangeset
for help on using the changeset viewer.
