private CreateHardLinkResult CreateHardLinkUnix(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting) { var createOrOpenResult = FileUtilities.TryCreateOrOpenFile(sourceFileName.ToString(), 0, FileShare.ReadWrite | FileShare.Delete, FileMode.Open, FileFlagsAndAttributes.FileFlagOverlapped, out var sourceFileHandle); using (sourceFileHandle) { if (!createOrOpenResult.Succeeded) { switch (createOrOpenResult.Status) { case OpenFileStatus.Success: break; case OpenFileStatus.FileNotFound: case OpenFileStatus.PathNotFound: return(CreateHardLinkResult.FailedSourceDoesNotExist); case OpenFileStatus.Timeout: case OpenFileStatus.AccessDenied: case OpenFileStatus.UnknownError: default: throw ThrowLastWin32Error(destinationFileName.Path, $"Failed to create or open file {sourceFileName.Path} to create hard link. Status: {createOrOpenResult.Status}"); } } } if (!replaceExisting && FileExists(destinationFileName)) { return(CreateHardLinkResult.FailedDestinationExists); } var createHardLinkResult = FileUtilities.TryCreateHardLink(destinationFileName.ToString(), sourceFileName.ToString()); if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedAccessDenied)) { return(CreateHardLinkResult.FailedAccessDenied); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedDueToPerFileLinkLimit)) { return(CreateHardLinkResult.FailedMaxHardLinkLimitReached); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedSinceDestinationIsOnDifferentVolume)) { return(CreateHardLinkResult.FailedSourceAndDestinationOnDifferentVolumes); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.FailedSinceNotSupportedByFilesystem)) { return(CreateHardLinkResult.FailedNotSupported); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.Failed)) { return(CreateHardLinkResult.Unknown); } else if (createHardLinkResult.HasFlag(CreateHardLinkStatus.Success)) { return(CreateHardLinkResult.Success); } else { throw ThrowLastWin32Error(sourceFileName.Path, $"Failed to create hard link for file {sourceFileName.Path} with unknown error: {createHardLinkResult.ToString()}"); } }
public IEnumerable <BuildXL.Cache.ContentStore.Interfaces.FileSystem.FileInfo> EnumerateFiles(AbsolutePath path, EnumerateOptions options) { throw new NotImplementedException(); }
public bool FileExists(AbsolutePath path) { throw new NotImplementedException(); }
public void DenyFileWrites(AbsolutePath path) { throw new NotImplementedException(); }
public IEnumerable <AbsolutePath> EnumerateDirectories(AbsolutePath path, EnumerateOptions options) { throw new NotImplementedException(); }
public void CreateDirectory(AbsolutePath path) { throw new NotImplementedException(); }
public void DeleteDirectory(AbsolutePath path, DeleteOptions deleteOptions) { throw new NotImplementedException(); }
public void CheckForDelete(AbsolutePath linkPath, bool checkForReadOnly, bool disallowOnAnyOpened = false) { lock (this) { if (checkForReadOnly && Attributes.HasFlag(FileAttributes.ReadOnly)) { throw new IOException("Cannot delete a read-only file or directory."); } if (IsDirectory) { if (Children.Any()) { throw new IOException("Cannot delete a non-empty directory."); } } else { bool disallowDelete = false; foreach (var kvp in _readersByPath.Where(x => !x.Key.Equals(linkPath))) { if (!kvp.Value.Share.HasFlag(FileShare.Delete)) { disallowDelete = true; } } foreach (var kvp in _writersByPath.Where(x => !x.Key.Equals(linkPath))) { if (!kvp.Value.Share.HasFlag(FileShare.Delete)) { disallowDelete = true; } } if (_readersByPath.ContainsKey(linkPath)) { if (!_readersByPath[linkPath].Share.HasFlag(FileShare.Delete) || disallowOnAnyOpened) { disallowDelete = true; } } if (_writersByPath.ContainsKey(linkPath)) { if (!_writersByPath[linkPath].Share.HasFlag(FileShare.Delete) || disallowOnAnyOpened) { disallowDelete = true; } } if (disallowDelete) { throw new UnauthorizedAccessException( "Cannot delete/overwrite a file when this file is in use. \n\n" + "Links: \n" + string.Join("\n", _linkedPaths.Select(path => path.Path)) + "\n\nOpen Stacks: \n\n" + string.Join("\n\n-----------------\n\n", _openStacks)); } } } }
/// <inheritdoc /> /// <remarks>Ref count limit is not implemented for the In Memory file system.</remarks> public CreateHardLinkResult CreateHardLink(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting) { lock (_drives) { if (!_useHardLinks) { return(CreateHardLinkResult.FailedNotSupported); } FileObject fileObj = FindFileObject(sourceFileName); if (fileObj == null) { return(CreateHardLinkResult.FailedSourceDoesNotExist); } if (destinationFileName.Length >= FileSystemConstants.MaxPath) { // Please note, we use FileSystemConstants.MaxPath that returns // ShortMaxPath or LongMaxPath depending on whether the system supports long paths or not. return(CreateHardLinkResult.FailedPathTooLong); } FileObject destination = FindFileObjectAndParent(destinationFileName, out var parentDestination); if (parentDestination == null) { throw new IOException( string.Format(CultureInfo.InvariantCulture, "Parent of destination {0} does not exist", destinationFileName.Path)); } // ReSharper disable PossibleNullReferenceException char sourceDrive = sourceFileName.DriveLetter; char destinationDrive = destinationFileName.DriveLetter; // ReSharper restore PossibleNullReferenceException if (sourceDrive != destinationDrive) { return(CreateHardLinkResult.FailedSourceAndDestinationOnDifferentVolumes); } if (!fileObj.CanAddLink()) { return(CreateHardLinkResult.FailedMaxHardLinkLimitReached); } if (destination != null) { if (!replaceExisting) { return(CreateHardLinkResult.FailedDestinationExists); } try { destination.DeleteLink(destinationFileName, false, true); } catch (UnauthorizedAccessException) { return(CreateHardLinkResult.FailedAccessDenied); } } fileObj.AddLink(destinationFileName); parentDestination.Children[destinationFileName.FileName] = fileObj; } return(CreateHardLinkResult.Success); }
/// <inheritdoc /> public void CreateDirectory(AbsolutePath path) { path.ThrowIfPathTooLong(); Directory.CreateDirectory(path.Path); }
public void AddLink(AbsolutePath linkPath) { _linkedPaths.Add(linkPath); }
/// <inheritdoc /> public byte[] ReadAllBytes(AbsolutePath path) { path.ThrowIfPathTooLong(); return(File.ReadAllBytes(path.Path)); }
/// <inheritdoc /> public bool FileExists(AbsolutePath path) { path.ThrowIfPathTooLong(); return(File.Exists(path.Path)); }
private CreateHardLinkResult CreateHardLinkWin(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting) { SafeFileHandle sourceFileHandle = NativeMethods.CreateFile( sourceFileName.Path, 0, /* Do not need to request any particular access to modify link info */ FileShare.ReadWrite | FileShare.Delete, IntPtr.Zero, FileMode.Open, 0 /* Allow symbolic links to redirect us */, IntPtr.Zero); using (sourceFileHandle) { if (sourceFileHandle.IsInvalid) { switch (Marshal.GetLastWin32Error()) { case NativeMethods.ERROR_FILE_NOT_FOUND: case NativeMethods.ERROR_PATH_NOT_FOUND: return(CreateHardLinkResult.FailedSourceDoesNotExist); case NativeMethods.ERROR_ACCESS_DENIED: return(CreateHardLinkResult.FailedSourceAccessDenied); default: return(CreateHardLinkResult.FailedSourceHandleInvalid); } } if (destinationFileName.Length >= FileSystemConstants.MaxPath) { return(CreateHardLinkResult.FailedPathTooLong); } const string DosToNtPathPrefix = @"\??\"; // NtSetInformationFile always expects a special prefix even for short paths. string path = DosToNtPathPrefix + destinationFileName.GetPathWithoutLongPathPrefix(); var linkInfo = new NativeMethods.FileLinkInformation(path, replaceExisting); NativeMethods.NtStatus status = setLink(sourceFileHandle, linkInfo); if (status.StatusCodeUint == (uint)NativeMethods.NtStatusCode.StatusAccessDenied) { // Access denied status can be returned by two reasons: // 1. Something went wrong with the source path // 2. Something went wrong with the destination path. // The second case is potentially recoverable: so, we'll check the destination's file attribute // and if the file has readonly attributes, then we'll remove them and will try to create hardlink one more time. if (this.TryGetFileAttributes(destinationFileName, out var attributes) && (attributes & FileAttributes.ReadOnly) != 0) { SetFileAttributes(destinationFileName, FileAttributes.Normal); status = setLink(sourceFileHandle, linkInfo); } } if (status.Failed) { switch (status.StatusCodeUint) { case (uint)NativeMethods.NtStatusCode.StatusTooManyLinks: return(CreateHardLinkResult.FailedMaxHardLinkLimitReached); case (uint)NativeMethods.NtStatusCode.StatusObjectNameCollision: return(CreateHardLinkResult.FailedDestinationExists); case (uint)NativeMethods.NtStatusCode.StatusNotSameDevice: return(CreateHardLinkResult.FailedSourceAndDestinationOnDifferentVolumes); case (uint)NativeMethods.NtStatusCode.StatusAccessDenied: return(CreateHardLinkResult.FailedAccessDenied); case (uint)NativeMethods.NtStatusCode.StatusNotSupported: return(CreateHardLinkResult.FailedNotSupported); case (uint)NativeMethods.NtStatusCode.StatusObjectPathNotFound: return(CreateHardLinkResult.FailedDestinationDirectoryDoesNotExist); default: throw new NTStatusException(status.StatusCodeUint, status.StatusName, string.Format( CultureInfo.InvariantCulture, "Unable to create hard link at '{0}', pointing to existing file '{1}' with NTSTATUS:[0x{2:X}] = [{3}]", destinationFileName, sourceFileName, status.StatusCodeUint, status.StatusName)); } } return(CreateHardLinkResult.Success); } NativeMethods.NtStatus setLink(SafeFileHandle handle, NativeMethods.FileLinkInformation linkInfo) { return(NativeMethods.NtSetInformationFile( handle, out _, linkInfo, (uint)Marshal.SizeOf(linkInfo), NativeMethods.FileInformationClass.FileLinkInformation)); } }
public void AllowAttributeWrites(AbsolutePath path) { throw new NotImplementedException(); }
/// <inheritdoc /> public Task <Stream> OpenAsync(AbsolutePath path, FileAccess fileAccess, FileMode fileMode, FileShare share, FileOptions options, int bufferSize) { return(Task.FromResult((Stream)OpenStreamInternal(path, fileAccess, fileMode, share))); }
public Task CopyFileAsync(AbsolutePath sourcePath, AbsolutePath destinationPath, bool replaceExisting) { throw new NotImplementedException(); }
/// <inheritdoc /> public Task <Stream> OpenReadOnlyAsync(AbsolutePath path, FileShare share) { return(this.OpenAsync(path, FileAccess.Read, FileMode.Open, share)); }
public CreateHardLinkResult CreateHardLink(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting) { throw new NotImplementedException(); }
/// <inheritdoc /> public void CopyFile(AbsolutePath sourcePath, AbsolutePath destinationPath, bool replaceExisting) { CopyFileAsync(sourcePath, destinationPath, replaceExisting).GetAwaiter().GetResult(); }
public void DeleteFile(AbsolutePath path) { throw new NotImplementedException(); }
private FileObject.FileMemoryStream OpenStreamInternal(AbsolutePath path, FileAccess accessMode, FileMode mode, FileShare share) { if (mode == FileMode.CreateNew && accessMode == FileAccess.Read) { throw new ArgumentException("FileMode.CreateNew and FileAccess.Read is an invalid combination."); } lock (_drives) { FileObject fileObj = FindFileObjectAndParent(path, out var parent); if (parent == null) { return(null); } switch (mode) { case FileMode.Create: if (fileObj != null) { fileObj.DeleteLink(path, false); parent.Children.Remove(path.FileName); } fileObj = new FileObject(path, this, new byte[] {}); parent.Children[path.FileName] = fileObj; break; case FileMode.Open: if (fileObj == null) { return(null); } break; case FileMode.OpenOrCreate: if (fileObj == null) { fileObj = new FileObject(path, this, new byte[] {}); parent.Children[path.FileName] = fileObj; } break; case FileMode.CreateNew: if (fileObj != null) { unchecked { throw new IOException("File already exists", new IOException("File exists", Hresult.FileExists)); } } fileObj = new FileObject(path, this, new byte[] {}); parent.Children[path.FileName] = fileObj; break; default: throw new NotImplementedException($"Mode '{mode}' is not supported."); } var file = fileObj.Open(path, accessMode, share); if (accessMode.HasFlag(FileAccess.Write)) { _currentStatistics.FileOpensForWrite++; } else { _currentStatistics.FileOpensForRead++; } return(file); } }
public bool DirectoryExists(AbsolutePath path) { throw new NotImplementedException(); }
/// <summary> /// Initializes a new instance of the <see cref="MemoryFileSystem" /> class. /// </summary> /// <param name="clock">Clock to use.</param> /// <param name="drives">Drives to support. If null, have the same drive letters as the current OS.</param> /// <param name="useHardLinks">Whether all drives support hardlinks.</param> /// <param name="tempPath">Optional override of default temporary directory.</param> public MemoryFileSystem(ITestClock clock, IEnumerable <char> drives = null, bool useHardLinks = true, AbsolutePath tempPath = null) { Contract.Requires(clock != null); Clock = clock; _useHardLinks = useHardLinks; if (OperatingSystemHelper.IsUnixOS) { _drives.Add(Path.VolumeSeparatorChar, new FileObject()); } else { drives = drives ?? Directory.GetLogicalDrives().Select(driveString => driveString[0]); foreach (char driveLetter in drives) { _drives.Add(char.ToUpperInvariant(driveLetter), new FileObject()); } } if (tempPath != null) { if (!_drives.ContainsKey(char.ToUpperInvariant(tempPath.Path[0]))) { throw new ArgumentException("tempPath is not on an available drive"); } _tempPath = tempPath; } else { if (OperatingSystemHelper.IsUnixOS) { _tempPath = new AbsolutePath(Path.VolumeSeparatorChar + "temp"); } else { var firstDriveLetter = _drives.Keys.First(); var path = string.Format(CultureInfo.InvariantCulture, "{0}:\\temp", firstDriveLetter); _tempPath = new AbsolutePath(path); } } }
public void EnumerateFiles(AbsolutePath path, string pattern, bool recursive, Action <BuildXL.Cache.ContentStore.Interfaces.FileSystem.FileInfo> fileHandler) { throw new NotImplementedException(); }
private FileObject FindFileObject(AbsolutePath path) { return(FindFileObjectAndParent(path, out _)); }
public bool FileAttributesAreSubset(AbsolutePath path, FileAttributes attributes) { throw new NotImplementedException(); }
protected virtual TestFileSystemContentStoreInternal Create(AbsolutePath rootPath, ITestClock clock, NagleQueue <ContentHash> nagleBlock = null) { return(new TestFileSystemContentStoreInternal(FileSystem, clock, rootPath, Config, nagleQueue: nagleBlock)); }
public DateTime GetDirectoryCreationTimeUtc(AbsolutePath path) { throw new NotImplementedException(); }
/// <inheritdoc /> public bool DirectoryExists(AbsolutePath path) { path.ThrowIfPathTooLong(); return(Directory.Exists(path.Path)); }