3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*============================================================
8 ** <OWNER>[....]</OWNER>
13 ** Purpose: A collection of methods for manipulating Files.
15 ** April 09,2000 (some design refactorization)
17 ===========================================================*/
20 #if FEATURE_MACL || MONO
21 using System.Security.AccessControl;
23 using System.Security.Permissions;
24 using PermissionSet = System.Security.PermissionSet;
25 using Win32Native = Microsoft.Win32.Win32Native;
26 using System.Runtime.InteropServices;
28 using System.Runtime.Serialization;
29 using System.Globalization;
30 using System.Runtime.Versioning;
31 using System.Diagnostics.Contracts;
34 // Class for creating FileStream objects, and some basic file management
35 // routines such as Delete, etc.
38 public sealed class FileInfo: FileSystemInfo
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
51 [System.Security.SecurityCritical]
52 [ResourceExposure(ResourceScope.Machine)]
53 [ResourceConsumption(ResourceScope.Machine)]
54 public static FileInfo UnsafeCreateFileInfo(String fileName)
57 throw new ArgumentNullException("fileName");
58 Contract.EndContractBlock();
60 FileInfo fi = new FileInfo();
61 fi.Init(fileName, false);
66 [System.Security.SecuritySafeCritical]
67 [ResourceExposure(ResourceScope.Machine)]
68 [ResourceConsumption(ResourceScope.Machine)]
69 public FileInfo(String fileName)
72 throw new ArgumentNullException("fileName");
73 Contract.EndContractBlock();
75 #if FEATURE_LEGACYNETCF
76 if(CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
78 System.Reflection.Assembly callingAssembly = System.Reflection.Assembly.GetCallingAssembly();
79 if(callingAssembly != null && !callingAssembly.IsProfileAssembly)
81 string caller = new System.Diagnostics.StackFrame(1).GetMethod().FullName;
82 string callee = System.Reflection.MethodBase.GetCurrentMethod().FullName;
83 throw new MethodAccessException(String.Format(
84 CultureInfo.CurrentCulture,
85 Environment.GetResourceString("Arg_MethodAccessException_WithCaller"),
90 #endif // FEATURE_LEGACYNETCF
95 [System.Security.SecurityCritical]
96 [ResourceExposure(ResourceScope.Machine)]
97 [ResourceConsumption(ResourceScope.Machine)]
98 private void Init(String fileName, bool checkHost)
100 OriginalPath = fileName;
101 // Must fully qualify the path for the security check
102 String fullPath = Path.GetFullPathInternal(fileName);
107 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, fileName, fullPath);
111 FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
115 _name = Path.GetFileName(fileName);
117 DisplayPath = GetDisplayPath(fileName);
120 private String GetDisplayPath(String originalPath)
123 return Path.GetFileName(originalPath);
130 [System.Security.SecurityCritical] // auto-generated
131 private FileInfo(SerializationInfo info, StreamingContext context) : base(info, context)
135 FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, FullPath, false, false);
138 _name = Path.GetFileName(OriginalPath);
139 DisplayPath = GetDisplayPath(OriginalPath);
142 #if FEATURE_CORESYSTEM
143 [System.Security.SecuritySafeCritical]
144 #endif //FEATURE_CORESYSTEM
145 internal FileInfo(String fullPath, bool ignoreThis)
148 Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
150 _name = Path.GetFileName(fullPath);
151 OriginalPath = _name;
156 public override String Name {
157 get { return _name; }
162 [System.Security.SecuritySafeCritical] // auto-generated
164 if (_dataInitialised == -1)
167 if (_dataInitialised != 0) // Refresh was unable to initialise the data
168 __Error.WinIOError(_dataInitialised, DisplayPath);
170 if ((_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0)
171 __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, DisplayPath);
176 return ((long)_data.fileSizeHigh) << 32 | ((long)_data.fileSizeLow & 0xFFFFFFFFL);
181 /* Returns the name of the directory that the file is in */
182 public String DirectoryName
184 [System.Security.SecuritySafeCritical]
187 String directoryName = Path.GetDirectoryName(FullPath);
188 if (directoryName != null)
192 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath);
195 FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, directoryName, false, false);
199 return directoryName;
203 /* Creates an instance of the the parent directory */
204 public DirectoryInfo Directory
206 [ResourceExposure(ResourceScope.Machine)]
207 [ResourceConsumption(ResourceScope.Machine)]
210 String dirName = DirectoryName;
213 return new DirectoryInfo(dirName);
217 public bool IsReadOnly {
219 return (Attributes & FileAttributes.ReadOnly) != 0;
223 Attributes |= FileAttributes.ReadOnly;
225 Attributes &= ~FileAttributes.ReadOnly;
229 #if FEATURE_MACL || MONO
230 [ResourceExposure(ResourceScope.None)]
231 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
232 public FileSecurity GetAccessControl()
234 return File.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
237 [ResourceExposure(ResourceScope.None)]
238 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
239 public FileSecurity GetAccessControl(AccessControlSections includeSections)
241 return File.GetAccessControl(FullPath, includeSections);
244 [ResourceExposure(ResourceScope.None)]
245 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
246 public void SetAccessControl(FileSecurity fileSecurity)
248 File.SetAccessControl(FullPath, fileSecurity);
252 [System.Security.SecuritySafeCritical] // auto-generated
253 [ResourceExposure(ResourceScope.Machine)]
254 [ResourceConsumption(ResourceScope.Machine)]
255 public StreamReader OpenText()
257 return new StreamReader(FullPath, Encoding.UTF8, true, StreamReader.DefaultBufferSize, false);
260 [ResourceExposure(ResourceScope.Machine)]
261 [ResourceConsumption(ResourceScope.Machine)]
262 public StreamWriter CreateText()
264 return new StreamWriter(FullPath,false);
267 [ResourceExposure(ResourceScope.Machine)]
268 [ResourceConsumption(ResourceScope.Machine)]
269 public StreamWriter AppendText()
271 return new StreamWriter(FullPath,true);
275 // Copies an existing file to a new file. An exception is raised if the
276 // destination file already exists. Use the
277 // Copy(String, String, boolean) method to allow
278 // overwriting an existing file.
280 // The caller must have certain FileIOPermissions. The caller must have
281 // Read permission to sourceFileName
282 // and Write permissions to destFileName.
284 [ResourceExposure(ResourceScope.Machine)]
285 [ResourceConsumption(ResourceScope.Machine)]
286 public FileInfo CopyTo(String destFileName) {
287 if (destFileName == null)
288 throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
289 if (destFileName.Length == 0)
290 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
291 Contract.EndContractBlock();
293 destFileName = File.InternalCopy(FullPath, destFileName, false, true);
294 return new FileInfo(destFileName, false);
298 // Copies an existing file to a new file. If overwrite is
299 // false, then an IOException is thrown if the destination file
300 // already exists. If overwrite is true, the file is
303 // The caller must have certain FileIOPermissions. The caller must have
304 // Read permission to sourceFileName and Create
305 // and Write permissions to destFileName.
307 [ResourceExposure(ResourceScope.Machine)]
308 [ResourceConsumption(ResourceScope.Machine)]
309 public FileInfo CopyTo(String destFileName, bool overwrite) {
310 if (destFileName == null)
311 throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
312 if (destFileName.Length == 0)
313 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
314 Contract.EndContractBlock();
316 destFileName = File.InternalCopy(FullPath, destFileName, overwrite, true);
317 return new FileInfo(destFileName, false);
320 [ResourceExposure(ResourceScope.None)]
321 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
322 public FileStream Create() {
323 return File.Create(FullPath);
326 // Deletes a file. The file specified by the designated path is deleted.
327 // If the file does not exist, Delete succeeds without throwing
330 // On NT, Delete will fail for a file that is open for normal I/O
331 // or a file that is memory mapped. On Win95, the file will be
332 // deleted irregardless of whether the file is being used.
334 // Your application must have Delete permission to the target file.
336 [System.Security.SecuritySafeCritical]
337 [ResourceExposure(ResourceScope.None)]
338 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
339 public override void Delete()
343 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, DisplayPath, FullPath);
346 // For security check, path should be resolved to an absolute path.
347 FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, FullPath, false, false);
354 if (MonoIO.ExistsDirectory (FullPath, out error))
355 __Error.WinIOError (Win32Native.ERROR_ACCESS_DENIED, DisplayPath);
357 if (!MonoIO.DeleteFile (FullPath, out error)) {
358 int hr = (int) error;
360 bool r = Win32Native.DeleteFile(FullPath);
362 int hr = Marshal.GetLastWin32Error();
364 if (hr==Win32Native.ERROR_FILE_NOT_FOUND)
367 __Error.WinIOError(hr, DisplayPath);
372 [ResourceExposure(ResourceScope.None)]
373 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
374 public void Decrypt()
376 File.Decrypt(FullPath);
380 [ResourceExposure(ResourceScope.None)]
381 [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
382 public void Encrypt()
384 File.Encrypt(FullPath);
387 // Tests if the given file exists. The result is true if the file
388 // given by the specified path exists; otherwise, the result is
391 // Your application must have Read permission for the target directory.
392 public override bool Exists {
393 [System.Security.SecuritySafeCritical] // auto-generated
396 if (_dataInitialised == -1)
398 if (_dataInitialised != 0) {
399 // Refresh was unable to initialise the data.
400 // We should normally be throwing an exception here,
401 // but Exists is supposed to return true or false.
404 return (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0;
416 // User must explicitly specify opening a new file or appending to one.
417 [ResourceExposure(ResourceScope.Machine)]
418 [ResourceConsumption(ResourceScope.Machine)]
419 public FileStream Open(FileMode mode) {
420 return Open(mode, FileAccess.ReadWrite, FileShare.None);
423 [ResourceExposure(ResourceScope.Machine)]
424 [ResourceConsumption(ResourceScope.Machine)]
425 public FileStream Open(FileMode mode, FileAccess access) {
426 return Open(mode, access, FileShare.None);
429 [ResourceExposure(ResourceScope.Machine)]
430 [ResourceConsumption(ResourceScope.Machine)]
431 public FileStream Open(FileMode mode, FileAccess access, FileShare share) {
432 return new FileStream(FullPath, mode, access, share);
437 [System.Security.SecuritySafeCritical] // auto-generated
439 [ResourceExposure(ResourceScope.Machine)]
440 [ResourceConsumption(ResourceScope.Machine)]
441 public FileStream OpenRead()
443 return new FileStream(FullPath, FileMode.Open, FileAccess.Read,
444 FileShare.Read, 4096, false);
448 [ResourceExposure(ResourceScope.Machine)]
449 [ResourceConsumption(ResourceScope.Machine)]
450 public FileStream OpenWrite() {
451 return new FileStream(FullPath, FileMode.OpenOrCreate,
452 FileAccess.Write, FileShare.None);
460 // Moves a given file to a new location and potentially a new file name.
461 // This method does work across volumes.
463 // The caller must have certain FileIOPermissions. The caller must
464 // have Read and Write permission to
465 // sourceFileName and Write
466 // permissions to destFileName.
468 [System.Security.SecuritySafeCritical]
469 [ResourceExposure(ResourceScope.Machine)]
470 [ResourceConsumption(ResourceScope.Machine)]
471 public void MoveTo(String destFileName) {
472 if (destFileName==null)
473 throw new ArgumentNullException("destFileName");
474 if (destFileName.Length==0)
475 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
476 Contract.EndContractBlock();
478 String fullDestFileName = Path.GetFullPathInternal(destFileName);
481 FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, FullPath);
482 FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName);
483 sourceState.EnsureState();
484 destState.EnsureState();
486 FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, FullPath, false, false);
487 FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
493 if (!MonoIO.MoveFile (FullPath, fullDestFileName, out error))
494 __Error.WinIOError ((int) error, String.Empty);
496 if (!Win32Native.MoveFile(FullPath, fullDestFileName))
497 __Error.WinIOError();
499 FullPath = fullDestFileName;
500 OriginalPath = destFileName;
501 _name = Path.GetFileName(fullDestFileName);
502 DisplayPath = GetDisplayPath(destFileName);
503 // Flush any cached information about the file.
504 _dataInitialised = -1;
508 [ResourceExposure(ResourceScope.Machine)]
509 [ResourceConsumption(ResourceScope.Machine)]
510 public FileInfo Replace(String destinationFileName, String destinationBackupFileName)
512 return Replace(destinationFileName, destinationBackupFileName, false);
516 [ResourceExposure(ResourceScope.Machine)]
517 [ResourceConsumption(ResourceScope.Machine)]
518 public FileInfo Replace(String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors)
520 File.Replace(FullPath, destinationFileName, destinationBackupFileName, ignoreMetadataErrors);
521 return new FileInfo(destinationFileName);
524 // Returns the display path
525 public override String ToString()