public static async Task Download(DateTime dateTime) { var directoryPath = Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "NYTimesPdfs"); Directory.CreateDirectory(directoryPath); var path = Path.Join(directoryPath, SubPath(dateTime)); if (File.Exists(path)) { return; } var url = $"http://www.hawes.com/{dateTime.Year}/{SubPath(dateTime)}"; var response = await Client.GetAsync(url); var j = 1; while (!response.IsSuccessStatusCode) { Thread.Sleep(j * 1000); response = await Client.GetAsync(url); j *= 2; } Console.WriteLine(dateTime); var responseBody = await response.Content.ReadAsByteArrayAsync(); await File.WriteAllBytesAsync(path, responseBody); }
private static void WriteDummyFile(string prefix, string dirName, string subdirName, string name) { var parent = Path.Join(prefix, dirName, subdirName); System.IO.Directory.CreateDirectory(parent); var path = Path.Join(parent, name); System.IO.File.WriteAllText(path, "some content"); }
public void TestThatFilesAreMatchedAsRootedPaths() { using var tmpdir = new TemporaryDirectory(); WriteDummyFile(tmpdir.Path, "a", "b", "Program.cs"); List <string> matchedFiles = Input.MatchFiles( tmpdir.Path, new List <string> { Path.Join(tmpdir.Path, "**", "*.cs") }, new List <string>()) .ToList(); var expectedFiles = new List <string>() { Path.Join(tmpdir.Path, "a", "b", "Program.cs") }; Assert.That(matchedFiles, Is.EquivalentTo(expectedFiles)); }
public void TestExclude(bool patternIsRooted, bool excludeIsRooted) { using var tmpdir = new TemporaryDirectory(); WriteDummyFile(tmpdir.Path, "a", "b", "Program.cs"); WriteDummyFile(tmpdir.Path, "a", "obj", "AnotherProgram.cs"); string pattern = (patternIsRooted) ? Path.Join(tmpdir.Path, "**", "*.cs") : Path.Join("**", "*.cs"); string exclude = (excludeIsRooted) ? Path.Join(tmpdir.Path, "**", "obj", "**", "*.cs") : Path.Join("**", "obj", "**", "*.cs"); List <string> matchedFiles = Input.MatchFiles( tmpdir.Path, new List <string>() { pattern }, new List <string>() { exclude }) .ToList(); var expectedFiles = (patternIsRooted) ? new List <string>() { Path.Join(tmpdir.Path, "a", "b", "Program.cs") } : new List <string>() { Path.Join("a", "b", "Program.cs") }; Assert.That(matchedFiles, Is.EquivalentTo(expectedFiles)); }
public static string Join(string path1, string path2, string path3, string path4) { return(Path.Join(path1.AsSpan(), path2.AsSpan(), path3.AsSpan(), path4.AsSpan())); }
/// <summary> /// Gets reparse point information associated to <paramref name="linkPath"/>. /// </summary> /// <returns>The immediate link target, absolute or relative or null if the file is not a supported link.</returns> internal static unsafe string?GetImmediateLinkTarget(string linkPath, bool isDirectory, bool throwOnError, bool returnFullPath) { using SafeFileHandle handle = OpenSafeFileHandle(linkPath, Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS | Interop.Kernel32.FileOperations.FILE_FLAG_OPEN_REPARSE_POINT); if (handle.IsInvalid) { if (!throwOnError) { return(null); } int error = Marshal.GetLastWin32Error(); // File not found doesn't make much sense coming from a directory. if (isDirectory && error == Interop.Errors.ERROR_FILE_NOT_FOUND) { error = Interop.Errors.ERROR_PATH_NOT_FOUND; } throw Win32Marshal.GetExceptionForWin32Error(error, linkPath); } byte[] buffer = ArrayPool <byte> .Shared.Rent(Interop.Kernel32.MAXIMUM_REPARSE_DATA_BUFFER_SIZE); try { bool success = Interop.Kernel32.DeviceIoControl( handle, dwIoControlCode: Interop.Kernel32.FSCTL_GET_REPARSE_POINT, lpInBuffer: IntPtr.Zero, nInBufferSize: 0, lpOutBuffer: buffer, nOutBufferSize: Interop.Kernel32.MAXIMUM_REPARSE_DATA_BUFFER_SIZE, out _, IntPtr.Zero); if (!success) { if (!throwOnError) { return(null); } int error = Marshal.GetLastWin32Error(); // The file or directory is not a reparse point. if (error == Interop.Errors.ERROR_NOT_A_REPARSE_POINT) { return(null); } throw Win32Marshal.GetExceptionForWin32Error(error, linkPath); } Span <byte> bufferSpan = new(buffer); success = MemoryMarshal.TryRead(bufferSpan, out Interop.Kernel32.SymbolicLinkReparseBuffer rbSymlink); Debug.Assert(success); // We always use SubstituteName(Offset|Length) instead of PrintName(Offset|Length), // the latter is just the display name of the reparse point and it can show something completely unrelated to the target. if (rbSymlink.ReparseTag == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_SYMLINK) { int offset = sizeof(Interop.Kernel32.SymbolicLinkReparseBuffer) + rbSymlink.SubstituteNameOffset; int length = rbSymlink.SubstituteNameLength; Span <char> targetPath = MemoryMarshal.Cast <byte, char>(bufferSpan.Slice(offset, length)); bool isRelative = (rbSymlink.Flags & Interop.Kernel32.SYMLINK_FLAG_RELATIVE) != 0; if (!isRelative) { // Absolute target is in NT format and we need to clean it up before return it to the user. if (targetPath.StartsWith(PathInternal.UncNTPathPrefix.AsSpan())) { // We need to prepend the Win32 equivalent of UNC NT prefix. return(Path.Join(PathInternal.UncPathPrefix.AsSpan(), targetPath.Slice(PathInternal.UncNTPathPrefix.Length))); } return(GetTargetPathWithoutNTPrefix(targetPath)); } else if (returnFullPath) { return(Path.Join(Path.GetDirectoryName(linkPath.AsSpan()), targetPath)); } else { return(targetPath.ToString()); } } else if (rbSymlink.ReparseTag == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT) { success = MemoryMarshal.TryRead(bufferSpan, out Interop.Kernel32.MountPointReparseBuffer rbMountPoint); Debug.Assert(success); int offset = sizeof(Interop.Kernel32.MountPointReparseBuffer) + rbMountPoint.SubstituteNameOffset; int length = rbMountPoint.SubstituteNameLength; Span <char> targetPath = MemoryMarshal.Cast <byte, char>(bufferSpan.Slice(offset, length)); // Unlike symbolic links, mount point paths cannot be relative. Debug.Assert(!PathInternal.IsPartiallyQualified(targetPath)); // Mount points cannot point to a remote location. Debug.Assert(!targetPath.StartsWith(PathInternal.UncNTPathPrefix.AsSpan())); return(GetTargetPathWithoutNTPrefix(targetPath)); } return(null); } finally { ArrayPool <byte> .Shared.Return(buffer); }
private static void RemoveDirectoryRecursive(string fullPath, ref Interop.Kernel32.WIN32_FIND_DATA findData, bool topLevel) { int errorCode; Exception?exception = null; using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(Path.Join(fullPath, "*"), ref findData)) { if (handle.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(fullPath); } do { if ((findData.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0) { // File string fileName = findData.cFileName.GetStringFromFixedBuffer(); if (!Interop.Kernel32.DeleteFile(Path.Combine(fullPath, fileName)) && exception == null) { errorCode = Marshal.GetLastWin32Error(); // We don't care if something else deleted the file first if (errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND) { exception = Win32Marshal.GetExceptionForWin32Error(errorCode, fileName); } } } else { // Directory, skip ".", "..". if (findData.cFileName.FixedBufferEqualsString(".") || findData.cFileName.FixedBufferEqualsString("..")) { continue; } string fileName = findData.cFileName.GetStringFromFixedBuffer(); if (!IsNameSurrogateReparsePoint(ref findData)) { // Not a reparse point, or the reparse point isn't a name surrogate, recurse. try { RemoveDirectoryRecursive( Path.Combine(fullPath, fileName), findData: ref findData, topLevel: false); } catch (Exception e) { if (exception == null) { exception = e; } } } else { // Name surrogate reparse point, don't recurse, simply remove the directory. // If a mount point, we have to delete the mount point first. if (findData.dwReserved0 == Interop.Kernel32.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT) { // Mount point. Unmount using full path plus a trailing '\'. // (Note: This doesn't remove the underlying directory) string mountPoint = Path.Join(fullPath, fileName, PathInternal.DirectorySeparatorCharAsString); if (!Interop.Kernel32.DeleteVolumeMountPoint(mountPoint) && exception == null) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_SUCCESS && errorCode != Interop.Errors.ERROR_PATH_NOT_FOUND) { exception = Win32Marshal.GetExceptionForWin32Error(errorCode, fileName); } } } // Note that RemoveDirectory on a symbolic link will remove the link itself. if (!Interop.Kernel32.RemoveDirectory(Path.Combine(fullPath, fileName)) && exception == null) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_PATH_NOT_FOUND) { exception = Win32Marshal.GetExceptionForWin32Error(errorCode, fileName); } } } } } while (Interop.Kernel32.FindNextFile(handle, ref findData)); if (exception != null) { throw exception; } errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_SUCCESS && errorCode != Interop.Errors.ERROR_NO_MORE_FILES) { throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } } // As we successfully removed all of the files we shouldn't care about the directory itself // not being empty. As file deletion is just a marker to remove the file when all handles // are closed we could still have undeleted contents. RemoveDirectoryInternal(fullPath, topLevel: topLevel, allowDirectoryNotEmpty: true); }
/// <summary> /// Creates a temporary file with the specified extension. /// </summary> /// <param name="extension"> /// The extension to give the file. /// </param> public RandomFile(string extension) { extension = Guard.NotNullOrWhiteSpace(extension, nameof(extension)); Path = IoPath.Join(IoPath.GetTempPath(), $"{Guid.NewGuid().ToStringWithDigitsOnly()}.{extension.ReplaceInvariant(".", "")}"); using var _ = File.Create(Path); }