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()}");
            }
        }
Example #2
0
 public IEnumerable <BuildXL.Cache.ContentStore.Interfaces.FileSystem.FileInfo> EnumerateFiles(AbsolutePath path, EnumerateOptions options)
 {
     throw new NotImplementedException();
 }
Example #3
0
 public bool FileExists(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #4
0
 public void DenyFileWrites(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #5
0
 public IEnumerable <AbsolutePath> EnumerateDirectories(AbsolutePath path, EnumerateOptions options)
 {
     throw new NotImplementedException();
 }
Example #6
0
 public void CreateDirectory(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #7
0
 public void DeleteDirectory(AbsolutePath path, DeleteOptions deleteOptions)
 {
     throw new NotImplementedException();
 }
Example #8
0
            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));
                        }
                    }
                }
            }
Example #9
0
        /// <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);
 }
Example #11
0
 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));
            }
        }
Example #15
0
 public void AllowAttributeWrites(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #16
0
 /// <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)));
 }
Example #17
0
 public Task CopyFileAsync(AbsolutePath sourcePath, AbsolutePath destinationPath, bool replaceExisting)
 {
     throw new NotImplementedException();
 }
Example #18
0
 /// <inheritdoc />
 public Task <Stream> OpenReadOnlyAsync(AbsolutePath path, FileShare share)
 {
     return(this.OpenAsync(path, FileAccess.Read, FileMode.Open, share));
 }
Example #19
0
 public CreateHardLinkResult CreateHardLink(AbsolutePath sourceFileName, AbsolutePath destinationFileName, bool replaceExisting)
 {
     throw new NotImplementedException();
 }
Example #20
0
 /// <inheritdoc />
 public void CopyFile(AbsolutePath sourcePath, AbsolutePath destinationPath, bool replaceExisting)
 {
     CopyFileAsync(sourcePath, destinationPath, replaceExisting).GetAwaiter().GetResult();
 }
Example #21
0
 public void DeleteFile(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #22
0
        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);
            }
        }
Example #23
0
 public bool DirectoryExists(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
Example #24
0
        /// <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);
                }
            }
        }
Example #25
0
 public void EnumerateFiles(AbsolutePath path, string pattern, bool recursive, Action <BuildXL.Cache.ContentStore.Interfaces.FileSystem.FileInfo> fileHandler)
 {
     throw new NotImplementedException();
 }
Example #26
0
 private FileObject FindFileObject(AbsolutePath path)
 {
     return(FindFileObjectAndParent(path, out _));
 }
Example #27
0
 public bool FileAttributesAreSubset(AbsolutePath path, FileAttributes attributes)
 {
     throw new NotImplementedException();
 }
Example #28
0
 protected virtual TestFileSystemContentStoreInternal Create(AbsolutePath rootPath, ITestClock clock, NagleQueue <ContentHash> nagleBlock = null)
 {
     return(new TestFileSystemContentStoreInternal(FileSystem, clock, rootPath, Config, nagleQueue: nagleBlock));
 }
Example #29
0
 public DateTime GetDirectoryCreationTimeUtc(AbsolutePath path)
 {
     throw new NotImplementedException();
 }
 /// <inheritdoc />
 public bool DirectoryExists(AbsolutePath path)
 {
     path.ThrowIfPathTooLong();
     return(Directory.Exists(path.Path));
 }