public static void GetFileProperties(string path, out DateTimeOffset?creationTime, out DateTimeOffset?lastWriteTime, out FileAttributes?fileAttributes #if DOTNET5_4 , bool isDirectory = false #endif ) { #if !DOTNET5_4 path = LongPath.ToUncPath(path); if (path.EndsWith(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal)) { path = path.Substring(0, path.Length - 1); } NativeMethods.WIN32_FIND_DATA findData; NativeMethods.SafeFindHandle findHandle; findHandle = NativeMethods.FindFirstFileW(path, out findData); if (findHandle.IsInvalid) { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(); } else { findHandle.Dispose(); findHandle = null; } long dt = (findData.LastWriteTime.dwLowDateTime & 0xFFFFFFFF); dt |= ((long)findData.LastWriteTime.dwHighDateTime) << 32; lastWriteTime = DateTimeOffset.FromFileTime(dt).UtcDateTime; dt = (findData.CreationTime.dwLowDateTime & 0xFFFFFFFF); dt |= ((long)findData.CreationTime.dwHighDateTime) << 32; creationTime = DateTimeOffset.FromFileTime(dt).UtcDateTime; fileAttributes = (FileAttributes)findData.FileAttributes; #else fileAttributes = File.GetAttributes(path); if (isDirectory) { creationTime = Directory.GetCreationTimeUtc(path); lastWriteTime = Directory.GetLastWriteTimeUtc(path); } else { creationTime = File.GetCreationTimeUtc(path); lastWriteTime = File.GetLastWriteTimeUtc(path); } #endif #if DEBUG if (null != TestHookCallbacks.GetFileAttributesCallback) { fileAttributes = TestHookCallbacks.GetFileAttributesCallback(path); } #endif }
public static bool Exists(string path) { #if DOTNET5_4 return(Directory.Exists(path)); #else try { if (String.IsNullOrEmpty(path)) { return(false); } path = LongPath.ToUncPath(path); bool success = NativeMethods.PathFileExistsW(path); if (!success) { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(new int[] { 0, NativeMethods.ERROR_DIRECTORY_NOT_FOUND, NativeMethods.ERROR_FILE_NOT_FOUND }); } var fileAttributes = LongPathFile.GetAttributes(path); return(success && (FileAttributes.Directory == (fileAttributes & FileAttributes.Directory))); } catch (ArgumentException) { } catch (NotSupportedException) { } // Security can throw this on ":" catch (System.Security.SecurityException) { } catch (IOException) { } catch (UnauthorizedAccessException) { } return(false); #endif }
private static string GetFileSDDL( string filePath, NativeMethods.SECURITY_INFORMATION securityInfo) { filePath = LongPath.ToUncPath(filePath); // Note: to get the SACL, special permissions are needed. Refer https://docs.microsoft.com/en-us/windows/win32/api/aclapi/nf-aclapi-getsecurityinfo IntPtr pZero = IntPtr.Zero; IntPtr pSid = pZero; IntPtr psd = pZero; uint errorReturn = NativeMethods.GetNamedSecurityInfoW( filePath, NativeMethods.SE_OBJECT_TYPE.SE_FILE_OBJECT, securityInfo, out pSid, out pZero, out pZero, out pZero, out psd); #if !DMLIB_TEST if (errorReturn == NativeMethods.ERROR_PRIVILEGE_NOT_HELD) { throw new TransferException( string.Format( CultureInfo.CurrentCulture, Resources.PrivilegeRequiredException, NativeMethods.SACLPrivilegeName)); } else if (errorReturn != 0) { throw new Win32Exception((int)errorReturn); } #else if (errorReturn != 0) { throw new Win32Exception((int)errorReturn); } #endif try { IntPtr sdString = IntPtr.Zero; UIntPtr sd_string_size_ptr = new UIntPtr(); bool success = NativeMethods.ConvertSecurityDescriptorToStringSecurityDescriptor(psd, NativeMethods.SDDL_REVISION_1, securityInfo, out sdString, out sd_string_size_ptr); try { return(Marshal.PtrToStringAuto(sdString)); } finally { Marshal.FreeHGlobal(sdString); } } finally { NativeMethods.LocalFree(psd); } }
public static FileStream Open(string filePath, FileMode mode, FileAccess access, FileShare share) { #if DOTNET5_4 return(new FileStream(filePath, mode, access, share)); #else filePath = LongPath.ToUncPath(filePath); SafeFileHandle fileHandle = GetFileHandle(filePath, mode, access, share); return(new FileStream(fileHandle, access)); #endif }
public static void SetFileTime(string path, DateTimeOffset creationTimeUtc, DateTimeOffset lastWriteTimeUtc, bool isDirectory = false) { #if !DOTNET5_4 path = LongPath.ToUncPath(path); SafeFileHandle fileHandle = GetFileHandle(path, FileMode.Open, FileAccess.Write, FileShare.None, isDirectory); try { NativeMethods.FILETIME ftCreationTime = new NativeMethods.FILETIME(); NativeMethods.FILETIME ftLastAccessTime = new NativeMethods.FILETIME(); NativeMethods.FILETIME ftLastWriteTime = new NativeMethods.FILETIME(); long dt = lastWriteTimeUtc.UtcDateTime.ToFileTimeUtc(); ftLastWriteTime.dwLowDateTime = (uint)dt & 0xFFFFFFFF; ftLastWriteTime.dwHighDateTime = (uint)(dt >> 32) & 0xFFFFFFFF; dt = creationTimeUtc.UtcDateTime.ToFileTimeUtc(); ftCreationTime.dwLowDateTime = (uint)dt & 0xFFFFFFFF; ftCreationTime.dwHighDateTime = (uint)(dt >> 32) & 0xFFFFFFFF; if (true != NativeMethods.SetFileTime(fileHandle, ref ftCreationTime, ref ftLastAccessTime, ref ftLastWriteTime)) { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(); } } finally { fileHandle.Close(); fileHandle = null; } #else if (isDirectory) { Directory.SetCreationTimeUtc(path, creationTimeUtc.UtcDateTime); Directory.SetLastWriteTimeUtc(path, lastWriteTimeUtc.UtcDateTime); } else { File.SetCreationTimeUtc(path, creationTimeUtc.UtcDateTime); File.SetLastWriteTimeUtc(path, lastWriteTimeUtc.UtcDateTime); } #endif }
public static void SetAttributes(string path, FileAttributes fileAttributes) { #if DEBUG if (null != TestHookCallbacks.SetFileAttributesCallback) { TestHookCallbacks.SetFileAttributesCallback(path, fileAttributes); return; } #endif #if DOTNET5_4 File.SetAttributes(path, fileAttributes); #else path = LongPath.ToUncPath(path); if (!NativeMethods.SetFileAttributesW(path, (uint)(fileAttributes))) { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(); } #endif }
/// <summary> /// Creates all directories and subdirectories in the specified path unless they already exist. /// </summary> /// <param name="path">The directory to create.</param> public static void CreateDirectory(string path) { #if DOTNET5_4 Directory.CreateDirectory(path); #else var dir = LongPath.GetDirectoryName(path); if (!string.IsNullOrEmpty(dir) && !LongPathDirectory.Exists(dir)) { LongPathDirectory.CreateDirectory(dir); } path = LongPath.ToUncPath(path); if (!NativeMethods.CreateDirectoryW(path, IntPtr.Zero)) { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(new int[] { NativeMethods.ERROR_SUCCESS, NativeMethods.ERROR_ALREADY_EXISTS }); } #endif }
public static IEnumerable <string> EnumerateFileSystemEntries(string path, string searchPattern, SearchOption searchOption, FilesOrDirectory filter) { #if DOTNET5_4 return(Directory.EnumerateFileSystemEntries(path, searchPattern, searchOption)); #else NativeMethods.WIN32_FIND_DATA findData; NativeMethods.SafeFindHandle findHandle; string currentPath = null; int errorCode = 0; Queue <string> folders = new Queue <string>(); String searchPath = LongPath.Combine(path, searchPattern); path = LongPath.GetDirectoryName(searchPath); searchPattern = LongPath.GetFileName(searchPath); folders.Enqueue(path); while (folders.Count > 0) { currentPath = folders.Dequeue(); if (searchOption == SearchOption.AllDirectories) { findHandle = NativeMethods.FindFirstFileW(LongPath.Combine(LongPath.ToUncPath(currentPath), "*"), out findData); if (!findHandle.IsInvalid) { do { if (findData.FileName != "." && findData.FileName != "..") { if (findData.FileAttributes == FileAttributes.Directory) { folders.Enqueue(LongPath.Combine(currentPath, findData.FileName)); } } }while (NativeMethods.FindNextFileW(findHandle, out findData)); // Get last Win32 error right after native calls. // Dispose SafeFindHandle will call native methods, it is possible to set last Win32 error. errorCode = Marshal.GetLastWin32Error(); if (findHandle != null && !findHandle.IsInvalid) { findHandle.Dispose(); } NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(errorCode, new int[] { NativeMethods.ERROR_SUCCESS, NativeMethods.ERROR_NO_MORE_FILES, NativeMethods.ERROR_FILE_NOT_FOUND }); } else { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(new int[] { NativeMethods.ERROR_SUCCESS, NativeMethods.ERROR_NO_MORE_FILES, NativeMethods.ERROR_FILE_NOT_FOUND }); } } findHandle = NativeMethods.FindFirstFileW(LongPath.Combine(LongPath.ToUncPath(currentPath), searchPattern), out findData); if (!findHandle.IsInvalid) { do { if (findData.FileName != "." && findData.FileName != "..") { if ((filter == FilesOrDirectory.All) || (filter == FilesOrDirectory.Directory && findData.FileAttributes == FileAttributes.Directory) || (filter == FilesOrDirectory.File && findData.FileAttributes != FileAttributes.Directory)) { yield return(LongPath.Combine(currentPath, findData.FileName)); } } }while (NativeMethods.FindNextFileW(findHandle, out findData)); // Get last Win32 error right after native calls. // Dispose SafeFindHandle will call native methods, it is possible to set last Win32 error. errorCode = Marshal.GetLastWin32Error(); if (findHandle != null && !findHandle.IsInvalid) { findHandle.Dispose(); } NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(errorCode, new int[] { NativeMethods.ERROR_SUCCESS, NativeMethods.ERROR_NO_MORE_FILES, NativeMethods.ERROR_FILE_NOT_FOUND }); } else { NativeMethods.ThrowExceptionForLastWin32ErrorIfExists(new int[] { NativeMethods.ERROR_SUCCESS, NativeMethods.ERROR_NO_MORE_FILES, NativeMethods.ERROR_FILE_NOT_FOUND }); } } #endif }
public static void SetFileSecurity(string filePath, string portableSDDL, PreserveSMBPermissions preserveSMBPermissions) { #if DEBUG if (null != TestHookCallbacks.SetFilePermissionsCallback) { TestHookCallbacks.SetFilePermissionsCallback(filePath, portableSDDL, preserveSMBPermissions); return; } #endif filePath = LongPath.ToUncPath(filePath); if (PreserveSMBPermissions.None == preserveSMBPermissions) { return; } if (string.IsNullOrEmpty(portableSDDL)) { return; } IntPtr pSecurityDescriptor = new IntPtr(); UIntPtr securityDescriptorLength = new UIntPtr(); if (!NativeMethods.ConvertStringSecurityDescriptorToSecurityDescriptor(portableSDDL, NativeMethods.SDDL_REVISION_1, out pSecurityDescriptor, out securityDescriptorLength)) { throw Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()); } try { NativeMethods.SetFileSecurity(filePath, (int)(ToSecurityInfo(preserveSMBPermissions)), pSecurityDescriptor); int errorCode = Marshal.GetLastWin32Error(); int hresult = Marshal.GetHRForLastWin32Error(); if ((errorCode == NativeMethods.ERROR_PRIVILEGE_NOT_HELD) || (errorCode == NativeMethods.ERROR_ACCESS_DENIED) || (errorCode == NativeMethods.ERROR_INVALID_OWNER)) { #if !DMLIB_TEST string privilegeName = null; if ((preserveSMBPermissions & PreserveSMBPermissions.Owner) == PreserveSMBPermissions.Owner) { privilegeName = NativeMethods.OwnerPrivilegeName; } if ((preserveSMBPermissions & PreserveSMBPermissions.SACL) == PreserveSMBPermissions.SACL) { if (null == privilegeName) { privilegeName = NativeMethods.SACLPrivilegeName; } else { privilegeName += " "; privilegeName += NativeMethods.SACLPrivilegeName; } } if (null != privilegeName) { throw new TransferException( string.Format( CultureInfo.CurrentCulture, Resources.PrivilegeRequiredException, privilegeName)); } #else throw new Win32Exception(errorCode); #endif } if (errorCode != 0) { Marshal.ThrowExceptionForHR(hresult); } } finally { NativeMethods.LocalFree(pSecurityDescriptor); } }
private void CreateDestinationDirectory(CancellationToken cancellationToken) { if (this.dest.Type == TransferLocationType.AzureBlobDirectory) { // No physical destination directory needed. return; } if ((this.dest.Type == TransferLocationType.AzureFileDirectory) && (null == (this.dest as AzureFileDirectoryLocation).FileDirectory.Parent)) { //Root Azure File directory, no need to create. return; } CloudFileNtfsAttributes? fileAttributes = null; DateTimeOffset? creationTime = null; DateTimeOffset? lastWriteTime = null; IDictionary <string, string> metadata = null; if (this.source.Type == TransferLocationType.LocalDirectory) { if (this.baseDirectoryTransfer.PreserveSMBAttributes) { var sourceLocalDirLocation = this.source as DirectoryLocation; FileAttributes?localFileAttributes = null; string longDirectoryPath = sourceLocalDirLocation.DirectoryPath; if (Interop.CrossPlatformHelpers.IsWindows) { longDirectoryPath = LongPath.ToUncPath(longDirectoryPath); } #if DOTNET5_4 LongPathFile.GetFileProperties(longDirectoryPath, out creationTime, out lastWriteTime, out localFileAttributes, true); #else LongPathFile.GetFileProperties(longDirectoryPath, out creationTime, out lastWriteTime, out localFileAttributes); #endif fileAttributes = Utils.LocalAttributesToAzureFileNtfsAttributes(localFileAttributes.Value); } } else if (this.source.Type == TransferLocationType.AzureFileDirectory) { if (this.baseDirectoryTransfer.PreserveSMBAttributes || this.dest.Type == TransferLocationType.AzureFileDirectory) { AzureFileDirectoryLocation sourceFileDirLocation = this.source as AzureFileDirectoryLocation; var sourceFileDirectory = sourceFileDirLocation.FileDirectory; sourceFileDirectory.FetchAttributesAsync( null, Utils.GenerateFileRequestOptions(sourceFileDirLocation.FileRequestOptions), Utils.GenerateOperationContext(this.baseDirectoryTransfer.Context), cancellationToken).GetAwaiter().GetResult(); if (this.baseDirectoryTransfer.PreserveSMBAttributes) { fileAttributes = sourceFileDirectory.Properties.NtfsAttributes; creationTime = sourceFileDirectory.Properties.CreationTime; lastWriteTime = sourceFileDirectory.Properties.LastWriteTime; } metadata = sourceFileDirectory.Metadata; } } if (this.dest.Type == TransferLocationType.LocalDirectory) { var localFileDestLocation = this.dest as DirectoryLocation; if (!LongPathDirectory.Exists(localFileDestLocation.DirectoryPath)) { LongPathDirectory.CreateDirectory(localFileDestLocation.DirectoryPath); } if (fileAttributes.HasValue) { LongPathFile.SetFileTime(localFileDestLocation.DirectoryPath, creationTime.Value, lastWriteTime.Value, true); LongPathFile.SetAttributes(localFileDestLocation.DirectoryPath, Utils.AzureFileNtfsAttributesToLocalAttributes(fileAttributes.Value)); } } else if (this.dest.Type == TransferLocationType.AzureFileDirectory) { AzureFileDirectoryLocation fileDirLocation = this.dest as AzureFileDirectoryLocation; var fileDirectory = fileDirLocation.FileDirectory; if (string.Equals(fileDirectory.SnapshotQualifiedUri.AbsolutePath, fileDirectory.Share.SnapshotQualifiedUri.AbsolutePath)) { return; } try { CreateCloudFileDestinationDirectory(fileDirectory, fileAttributes, creationTime, lastWriteTime, metadata, cancellationToken); } catch (StorageException storageException) { if ((null != storageException.InnerException) && (storageException.InnerException is OperationCanceledException)) { throw storageException.InnerException; } else { throw new TransferException(TransferErrorCode.FailToVadlidateDestination, string.Format(CultureInfo.CurrentCulture, Resources.FailedToValidateDestinationException, storageException.ToErrorDetail()), storageException); } } } }
public static string ToLongPath(this string originPath) { return(TransferManager.Configurations.SupportUncPath ? LongPath.ToUncPath(originPath) : originPath); }