/
FileSystemInfo.cs
187 lines (163 loc) · 8.27 KB
/
FileSystemInfo.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
namespace System.IO
{
public abstract partial class FileSystemInfo : MarshalByRefObject, ISerializable
{
// FullPath and OriginalPath are documented fields
protected string FullPath = null!; // fully qualified path of the file or directory
protected string OriginalPath = null!; // path passed in by the user
internal string? _name;
private string? _linkTarget;
private bool _linkTargetIsValid;
[Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected FileSystemInfo(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
}
internal void Invalidate()
{
_linkTargetIsValid = false;
InvalidateCore();
}
[Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new PlatformNotSupportedException();
}
// Full path of the directory/file
public virtual string FullName => FullPath;
public string Extension
{
get
{
int length = FullPath.Length;
for (int i = length; --i >= 0;)
{
char ch = FullPath[i];
if (ch == '.')
return FullPath.Substring(i, length - i);
if (PathInternal.IsDirectorySeparator(ch) || ch == Path.VolumeSeparatorChar)
break;
}
return string.Empty;
}
}
public abstract string Name { get; }
// Whether a file/directory exists
public abstract bool Exists { get; }
// Delete a file/directory
public abstract void Delete();
public DateTime CreationTime
{
get => CreationTimeUtc.ToLocalTime();
set => CreationTimeUtc = value.ToUniversalTime();
}
public DateTime CreationTimeUtc
{
get => CreationTimeCore.UtcDateTime;
set => CreationTimeCore = File.GetUtcDateTimeOffset(value);
}
public DateTime LastAccessTime
{
get => LastAccessTimeUtc.ToLocalTime();
set => LastAccessTimeUtc = value.ToUniversalTime();
}
public DateTime LastAccessTimeUtc
{
get => LastAccessTimeCore.UtcDateTime;
set => LastAccessTimeCore = File.GetUtcDateTimeOffset(value);
}
public DateTime LastWriteTime
{
get => LastWriteTimeUtc.ToLocalTime();
set => LastWriteTimeUtc = value.ToUniversalTime();
}
public DateTime LastWriteTimeUtc
{
get => LastWriteTimeCore.UtcDateTime;
set => LastWriteTimeCore = File.GetUtcDateTimeOffset(value);
}
/// <summary>
/// If this <see cref="FileSystemInfo"/> instance represents a link, returns the link target's path.
/// If a link does not exist in <see cref="FullName"/>, or this instance does not represent a link, returns <see langword="null"/>.
/// </summary>
public string? LinkTarget
{
get
{
if (_linkTargetIsValid)
{
return _linkTarget;
}
_linkTarget = FileSystem.GetLinkTarget(FullPath, this is DirectoryInfo);
_linkTargetIsValid = true;
return _linkTarget;
}
}
/// <summary>Gets or sets the Unix file mode for the current file or directory.</summary>
/// <value><see cref="T:System.IO.UnixFileMode" /> of the current <see cref="T:System.IO.FileSystemInfo" />.</value>
/// <exception cref="T:System.ArgumentException">The caller attempts to set an invalid file mode.</exception>
/// <exception cref="T:System.UnauthorizedAccessException">The caller does not have the required permission.</exception>
/// <exception cref="T:System.IO.PathTooLongException">The specified path exceeds the system-defined maximum length.</exception>
/// <exception cref="T:System.IO.DirectoryNotFoundException">The specified path is invalid. Only thrown when setting the property value.</exception>
/// <exception cref="T:System.IO.FileNotFoundException">The specified file doesn't exist. Only thrown when setting the property value.</exception>
/// <exception cref="T:System.IO.IOException"><see cref="M:System.IO.FileSystemInfo.Refresh" /> cannot initialize the data.</exception>
///
/// <remarks>
/// The value may be cached when either the value itself or other <see cref="T:System.IO.FileSystemInfo" /> properties are accessed. To get the latest value, call the <see cref="M:System.IO.FileSystemInfo.Refresh" /> method.
///
/// If the path doesn't exist as of the last cached state, the return value is `(UnixFileMode)(-1)`. <see cref="FileNotFoundException"/> or <see cref="DirectoryNotFoundException"/> can only be thrown when setting the value.
/// </remarks>
public UnixFileMode UnixFileMode
{
get => UnixFileModeCore;
[UnsupportedOSPlatform("windows")]
set => UnixFileModeCore = value;
}
/// <summary>
/// Creates a symbolic link located in <see cref="FullName"/> that points to the specified <paramref name="pathToTarget"/>.
/// </summary>
/// <param name="pathToTarget">The path of the symbolic link target.</param>
/// <exception cref="ArgumentNullException"><paramref name="pathToTarget"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="pathToTarget"/> is empty.
/// -or-
/// This instance was not created passing an absolute path.
/// -or-
/// <paramref name="pathToTarget"/> contains invalid path characters.</exception>
/// <exception cref="IOException">A file or directory already exists in the location of <see cref="FullName"/>.
/// -or-
/// An I/O error occurred.</exception>
public void CreateAsSymbolicLink(string pathToTarget)
{
FileSystem.VerifyValidPath(pathToTarget, nameof(pathToTarget));
FileSystem.CreateSymbolicLink(OriginalPath, pathToTarget, this is DirectoryInfo);
Invalidate();
}
/// <summary>
/// Gets the target of the specified link.
/// </summary>
/// <param name="returnFinalTarget"><see langword="true"/> to follow links to the final target; <see langword="false"/> to return the immediate next link.</param>
/// <returns>A <see cref="FileSystemInfo"/> instance if the link exists, independently if the target exists or not; <see langword="null"/> if this file or directory is not a link.</returns>
/// <exception cref="IOException">The file or directory does not exist.
/// -or-
/// The link's file system entry type is inconsistent with that of its target.
/// -or-
/// Too many levels of symbolic links.</exception>
/// <remarks>When <paramref name="returnFinalTarget"/> is <see langword="true"/>, the maximum number of symbolic links that are followed are 40 on Unix and 63 on Windows.</remarks>
public FileSystemInfo? ResolveLinkTarget(bool returnFinalTarget) =>
FileSystem.ResolveLinkTarget(FullPath, returnFinalTarget, this is DirectoryInfo);
/// <summary>
/// Returns the original path. Use FullName or Name properties for the full path or file/directory name.
/// </summary>
public override string ToString() => OriginalPath ?? string.Empty;
}
}