2 using System.Collections.Generic;
5 using System.IO.Compression;
10 using System.Threading.Tasks;
22 public const int DefaultBufferSize = 4096;
32 var tasks =
new List<Task>();
34 foreach (var subDir
in dir.EnumerateDirectories())
36 cancellationToken.ThrowIfCancellationRequested();
37 if (!subDir.Attributes.HasFlag(FileAttributes.Directory) || subDir.Attributes.HasFlag(FileAttributes.ReparsePoint))
41 tasks.Add(NormalizeAndDelete(subDir, cancellationToken));
43 foreach (var file
in dir.EnumerateFiles())
45 cancellationToken.ThrowIfCancellationRequested();
46 file.Attributes = FileAttributes.Normal;
49 await Task.WhenAll(tasks).ConfigureAwait(
false);
50 cancellationToken.ThrowIfCancellationRequested();
59 static FileStream OpenWriteStream(
string path) =>
new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize,
true);
69 IEnumerable<Task>
CopyDirectoryImpl(
string src,
string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
71 var dir =
new DirectoryInfo(src);
72 var atLeastOneSubDir =
false;
73 foreach (var I
in dir.EnumerateDirectories())
75 if (ignore != null && ignore.Contains(I.Name))
77 foreach (var J
in CopyDirectoryImpl(I.FullName, Path.Combine(dest, I.Name), null, cancellationToken))
79 atLeastOneSubDir =
true;
84 async Task CopyThisDirectory()
86 if (!atLeastOneSubDir)
87 await CreateDirectory(dest, cancellationToken).ConfigureAwait(
false);
89 var tasks =
new List<Task>();
91 await dir.EnumerateFiles().ToAsyncEnumerable().ForEachAsync(I =>
93 if (ignore != null && ignore.Contains(I.Name))
95 tasks.Add(CopyFile(I.FullName, Path.Combine(dest, I.Name), cancellationToken));
96 }).ConfigureAwait(
false);
98 await Task.WhenAll(tasks).ConfigureAwait(
false);
101 yield
return CopyThisDirectory();
105 public async Task
CopyDirectory(
string src,
string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
108 throw new ArgumentNullException(nameof(src));
110 throw new ArgumentNullException(nameof(src));
112 src = ResolvePath(src);
113 dest = ResolvePath(dest);
114 foreach (var directoryCopy
in CopyDirectoryImpl(src, dest, ignore, cancellationToken))
115 await directoryCopy.ConfigureAwait(
false);
119 public async Task
AppendAllText(
string path,
string additional_contents, CancellationToken cancellationToken)
121 if (additional_contents == null)
122 throw new ArgumentNullException(nameof(additional_contents));
123 using (var destStream =
new FileStream(ResolvePath(path), FileMode.Append, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize,
true))
125 var buf = Encoding.UTF8.GetBytes(additional_contents);
126 await destStream.WriteAsync(buf, 0, buf.Length, cancellationToken).ConfigureAwait(
false);
134 throw new ArgumentNullException(nameof(paths));
135 return Path.Combine(paths);
139 public async Task
CopyFile(
string src,
string dest, CancellationToken cancellationToken)
142 throw new ArgumentNullException(nameof(src));
144 throw new ArgumentNullException(nameof(dest));
145 using (var srcStream =
new FileStream(ResolvePath(src), FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize,
true))
146 using (var destStream =
new FileStream(ResolvePath(dest), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize,
true))
147 await srcStream.CopyToAsync(destStream, 81920, cancellationToken).ConfigureAwait(
false);
151 public Task CreateDirectory(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.CreateDirectory(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
156 path = ResolvePath(path);
157 var di =
new DirectoryInfo(path);
160 await NormalizeAndDelete(di, cancellationToken).ConfigureAwait(
false);
164 public Task DeleteFile(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Delete(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
167 public Task<bool> FileExists(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
170 public Task<bool> DirectoryExists(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
173 public string GetDirectoryName(
string path) => Path.GetDirectoryName(path ??
throw new ArgumentNullException(nameof(path)));
176 public string GetFileName(
string path) => Path.GetFileName(path ??
throw new ArgumentNullException(nameof(path)));
179 public string GetFileNameWithoutExtension(
string path) => Path.GetFileNameWithoutExtension(path ??
throw new ArgumentNullException(nameof(path)));
182 public Task<List<string>> GetFilesWithExtension(
string path,
string extension, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
184 path = ResolvePath(path);
185 if (extension == null)
186 throw new ArgumentNullException(extension);
187 var results =
new List<string>();
188 foreach (var I
in Directory.EnumerateFiles(path, String.Format(CultureInfo.InvariantCulture,
"*.{0}", extension), SearchOption.TopDirectoryOnly))
190 cancellationToken.ThrowIfCancellationRequested();
194 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
197 public Task MoveFile(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
199 if (destination == null)
200 throw new ArgumentNullException(nameof(destination));
201 source = ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
202 destination = ResolvePath(destination);
203 File.Move(source, destination);
204 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
207 public Task MoveDirectory(
string source,
string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
209 if (destination == null)
210 throw new ArgumentNullException(nameof(destination));
211 source = ResolvePath(source ??
throw new ArgumentNullException(nameof(source)));
212 destination = ResolvePath(destination);
213 Directory.Move(source, destination);
214 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
217 public async Task<byte[]>
ReadAllBytes(
string path, CancellationToken cancellationToken)
219 path = ResolvePath(path);
220 using (var file =
new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize,
true))
223 buf =
new byte[file.Length];
224 await file.ReadAsync(buf, 0, (
int)file.Length, cancellationToken).ConfigureAwait(
false);
230 public virtual string ResolvePath(
string path) => Path.GetFullPath(path ??
throw new ArgumentNullException(nameof(path)));
233 public async Task
WriteAllBytes(
string path, byte[] contents, CancellationToken cancellationToken)
235 path = ResolvePath(path);
236 using (var file = OpenWriteStream(path))
237 await file.WriteAsync(contents, 0, contents.Length, cancellationToken).ConfigureAwait(
false);
241 public Task<IReadOnlyList<string>> GetDirectories(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
243 path = ResolvePath(path);
244 var results =
new List<string>();
245 cancellationToken.ThrowIfCancellationRequested();
246 foreach (var I
in Directory.EnumerateDirectories(path))
249 cancellationToken.ThrowIfCancellationRequested();
251 return (IReadOnlyList<string>)results;
252 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
255 public Task<IReadOnlyList<string>> GetFiles(
string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
257 path = ResolvePath(path);
258 var results =
new List<string>();
259 cancellationToken.ThrowIfCancellationRequested();
260 foreach (var I
in Directory.EnumerateFiles(path))
263 cancellationToken.ThrowIfCancellationRequested();
265 return (IReadOnlyList<string>)results;
266 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
269 public Task CreateSymlink(
string target,
string link, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
271 target = ResolvePath(target);
272 link = ResolvePath(link);
274 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
277 public async Task<byte[]>
DownloadFile(Uri url, CancellationToken cancellationToken)
280 using (var wc =
new WebClient())
282 var tcs =
new TaskCompletionSource<byte[]>();
283 wc.DownloadDataCompleted += (a, b) =>
286 tcs.TrySetException(b.Error);
287 else if (b.Cancelled)
288 tcs.TrySetCanceled();
290 tcs.TrySetResult(b.Result);
292 wc.DownloadDataAsync(url);
293 using (cancellationToken.Register(() =>
296 tcs.TrySetCanceled();
298 return await tcs.Task.ConfigureAwait(
false);
303 public Task ZipToDirectory(
string path, byte[] zipFileBytes, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
305 path = ResolvePath(path);
306 if (zipFileBytes == null)
307 throw new ArgumentNullException(nameof(zipFileBytes));
309 using (var ms =
new MemoryStream(zipFileBytes))
310 using (var archive =
new ZipArchive(ms, ZipArchiveMode.Read))
311 archive.ExtractToDirectory(path);
312 }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
315 public bool PathContainsParentAccess(
string path) => path?.Split(
new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }).Any(x => x ==
"..") ??
throw new ArgumentNullException(nameof(path));
async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
string ConcatPath(params string[] paths)
Combines an array of strings into a path
Use server authentication
async Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest
static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
Recursively empty a directory
async Task AppendAllText(string path, string additional_contents, CancellationToken cancellationToken)
async Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
async Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
IIOManager that resolves paths to Environment.CurrentDirectory
Interface for using filesystems