Ejemplo n.º 1
0
        public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode, DiskTransferVerificationMode verificationMode)
        {
            Ensure.That(sourcePath, () => sourcePath).IsValidPath();
            Ensure.That(targetPath, () => targetPath).IsValidPath();

            if (mode == TransferMode.Move && !_diskProvider.FolderExists(targetPath))
            {
                if (verificationMode == DiskTransferVerificationMode.TryTransactional || verificationMode == DiskTransferVerificationMode.VerifyOnly)
                {
                    var sourceMount = _diskProvider.GetMount(sourcePath);
                    var targetMount = _diskProvider.GetMount(targetPath);

                    // If we're on the same mount, do a simple folder move.
                    if (sourceMount != null && targetMount != null && sourceMount.RootDirectory == targetMount.RootDirectory)
                    {
                        _logger.Debug("Move Directory [{0}] > [{1}]", sourcePath, targetPath);
                        _diskProvider.MoveFolder(sourcePath, targetPath);
                        return(mode);
                    }
                }
            }

            if (!_diskProvider.FolderExists(targetPath))
            {
                _diskProvider.CreateFolder(targetPath);

                _diskProvider.CopyPermissions(sourcePath, targetPath);
            }

            var result = mode;

            foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath))
            {
                if (ShouldIgnore(subDir))
                {
                    continue;
                }

                result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode, verificationMode);
            }

            foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath))
            {
                if (ShouldIgnore(sourceFile))
                {
                    continue;
                }

                var destFile = Path.Combine(targetPath, sourceFile.Name);

                result &= TransferFile(sourceFile.FullName, destFile, mode, true, verificationMode);
            }

            if (mode.HasFlag(TransferMode.Move))
            {
                _diskProvider.DeleteFolder(sourcePath, true);
            }

            return(result);
        }
        protected override bool IsValid(PropertyValidatorContext context)
        {
            if (context.PropertyValue == null)
            {
                return(false);
            }

            if (OsInfo.IsNotWindows)
            {
                return(true);
            }

            if (!_runtimeInfo.IsWindowsService)
            {
                return(true);
            }

            var path = context.PropertyValue.ToString();

            if (!DriveRegex.IsMatch(path))
            {
                return(true);
            }

            var mount = _diskProvider.GetMount(path);

            if (mount != null && mount.DriveType == DriveType.Network)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 3
0
        public override HealthCheck Check()
        {
            // Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution.
            var mounts = _authorService.AllAuthorPaths()
                         .Select(p => _diskProvider.GetMount(p.Value))
                         .Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly)
                         .DistinctBy(m => m.RootDirectory)
                         .ToList();

            if (mounts.Any())
            {
                return(new HealthCheck(GetType(), HealthCheckResult.Error, _localizationService.GetLocalizedString("MountCheckMessage") + string.Join(", ", mounts.Select(m => m.Name)), "#author-mount-ro"));
            }

            return(new HealthCheck(GetType()));
        }
Ejemplo n.º 4
0
        public override HealthCheck Check()
        {
            // Not best for optimization but due to possible symlinks and junctions, we get mounts based on series path so internals can handle mount resolution.
            var mounts = _artistService.GetAllArtists()
                         .Select(artist => _diskProvider.GetMount(artist.Path))
                         .Where(m => m != null && m.MountOptions != null && m.MountOptions.IsReadOnly)
                         .DistinctBy(m => m.RootDirectory)
                         .ToList();

            if (mounts.Any())
            {
                return(new HealthCheck(GetType(), HealthCheckResult.Error, "Mount containing a artist path is mounted read-only: " + string.Join(",", mounts.Select(m => m.Name)), "#artist-mount-ro"));
            }

            return(new HealthCheck(GetType()));
        }
Ejemplo n.º 5
0
        public TransferMode TransferFile(string sourcePath, string targetPath, TransferMode mode, bool overwrite, DiskTransferVerificationMode verificationMode)
        {
            Ensure.That(sourcePath, () => sourcePath).IsValidPath();
            Ensure.That(targetPath, () => targetPath).IsValidPath();

            _logger.Debug("{0} [{1}] > [{2}]", mode, sourcePath, targetPath);

            var originalSize = _diskProvider.GetFileSize(sourcePath);

            if (sourcePath == targetPath)
            {
                throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath));
            }

            if (sourcePath.PathEquals(targetPath, StringComparison.InvariantCultureIgnoreCase))
            {
                if (mode.HasFlag(TransferMode.HardLink) || mode.HasFlag(TransferMode.Copy))
                {
                    throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath));
                }

                if (mode.HasFlag(TransferMode.Move))
                {
                    var tempPath = sourcePath + ".backup~";

                    _diskProvider.MoveFile(sourcePath, tempPath, true);
                    try
                    {
                        ClearTargetPath(targetPath, overwrite);

                        _diskProvider.MoveFile(tempPath, targetPath);

                        return(TransferMode.Move);
                    }
                    catch
                    {
                        RollbackMove(sourcePath, tempPath);
                        throw;
                    }
                }

                return(TransferMode.None);
            }

            if (sourcePath.GetParentPath() == targetPath.GetParentPath())
            {
                if (mode.HasFlag(TransferMode.Move))
                {
                    TryMoveFileVerified(sourcePath, targetPath, originalSize);
                    return(TransferMode.Move);
                }
            }

            if (sourcePath.IsParentPath(targetPath))
            {
                throw new IOException(string.Format("Destination cannot be a child of the source [{0}] => [{1}]", sourcePath, targetPath));
            }

            ClearTargetPath(targetPath, overwrite);

            if (mode.HasFlag(TransferMode.HardLink))
            {
                var createdHardlink = _diskProvider.TryCreateHardLink(sourcePath, targetPath);
                if (createdHardlink)
                {
                    return(TransferMode.HardLink);
                }
                if (!mode.HasFlag(TransferMode.Copy))
                {
                    throw new IOException("Hardlinking from '" + sourcePath + "' to '" + targetPath + "' failed.");
                }
            }

            // We force a transactional transfer if the transfer occurs between mounts and one of the mounts is cifs, it would be a copy anyway.
            if (verificationMode == DiskTransferVerificationMode.TryTransactional && OsInfo.IsNotWindows)
            {
                var sourceMount = _diskProvider.GetMount(sourcePath);
                var targetMount = _diskProvider.GetMount(targetPath);

                if (sourceMount != null && targetMount != null && sourceMount.RootDirectory != targetMount.RootDirectory &&
                    (sourceMount.DriveFormat == "cifs" || targetMount.DriveFormat == "cifs"))
                {
                    verificationMode = DiskTransferVerificationMode.Transactional;
                }
            }

            if (mode.HasFlag(TransferMode.Copy))
            {
                if (verificationMode == DiskTransferVerificationMode.Transactional || verificationMode == DiskTransferVerificationMode.TryTransactional)
                {
                    if (TryCopyFileTransactional(sourcePath, targetPath, originalSize))
                    {
                        return(TransferMode.Copy);
                    }

                    throw new IOException(string.Format("Failed to completely transfer [{0}] to [{1}], aborting.", sourcePath, targetPath));
                }
                else if (verificationMode == DiskTransferVerificationMode.VerifyOnly)
                {
                    TryCopyFileVerified(sourcePath, targetPath, originalSize);
                    return(TransferMode.Copy);
                }
                else
                {
                    _diskProvider.CopyFile(sourcePath, targetPath);
                    return(TransferMode.Copy);
                }
            }

            if (mode.HasFlag(TransferMode.Move))
            {
                if (verificationMode == DiskTransferVerificationMode.Transactional || verificationMode == DiskTransferVerificationMode.TryTransactional)
                {
                    if (TryMoveFileTransactional(sourcePath, targetPath, originalSize, verificationMode))
                    {
                        return(TransferMode.Move);
                    }

                    throw new IOException(string.Format("Failed to completely transfer [{0}] to [{1}], aborting.", sourcePath, targetPath));
                }
                else if (verificationMode == DiskTransferVerificationMode.VerifyOnly)
                {
                    TryMoveFileVerified(sourcePath, targetPath, originalSize);
                    return(TransferMode.Move);
                }
                else
                {
                    _diskProvider.MoveFile(sourcePath, targetPath);
                    return(TransferMode.Move);
                }
            }

            return(TransferMode.None);
        }
Ejemplo n.º 6
0
        public TransferMode TransferFolder(string sourcePath, string targetPath, TransferMode mode)
        {
            Ensure.That(sourcePath, () => sourcePath).IsValidPath();
            Ensure.That(targetPath, () => targetPath).IsValidPath();

            sourcePath = ResolveRealParentPath(sourcePath);
            targetPath = ResolveRealParentPath(targetPath);

            _logger.Debug("{0} Directory [{1}] > [{2}]", mode, sourcePath, targetPath);

            if (sourcePath == targetPath)
            {
                throw new IOException(string.Format("Source and destination can't be the same {0}", sourcePath));
            }

            if (mode == TransferMode.Move && sourcePath.PathEquals(targetPath, StringComparison.InvariantCultureIgnoreCase) && _diskProvider.FolderExists(targetPath))
            {
                // Move folder out of the way to allow case-insensitive renames
                var tempPath = sourcePath + ".backup~";
                _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", sourcePath, tempPath);
                _diskProvider.MoveFolder(sourcePath, tempPath);

                if (!_diskProvider.FolderExists(targetPath))
                {
                    _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", tempPath, targetPath);
                    _logger.Debug("Rename Directory [{0}] > [{1}]", sourcePath, targetPath);
                    _diskProvider.MoveFolder(tempPath, targetPath);
                    return(mode);
                }

                // There were two separate folders, revert the intermediate rename and let the recursion deal with it
                _logger.Trace("Rename Intermediate Directory [{0}] > [{1}]", tempPath, sourcePath);
                _diskProvider.MoveFolder(tempPath, sourcePath);
            }

            if (mode == TransferMode.Move && !_diskProvider.FolderExists(targetPath))
            {
                var sourceMount = _diskProvider.GetMount(sourcePath);
                var targetMount = _diskProvider.GetMount(targetPath);

                // If we're on the same mount, do a simple folder move.
                if (sourceMount != null && targetMount != null && sourceMount.RootDirectory == targetMount.RootDirectory)
                {
                    _logger.Debug("Rename Directory [{0}] > [{1}]", sourcePath, targetPath);
                    _diskProvider.MoveFolder(sourcePath, targetPath);
                    return(mode);
                }
            }

            if (!_diskProvider.FolderExists(targetPath))
            {
                _diskProvider.CreateFolder(targetPath);

                _diskProvider.CopyPermissions(sourcePath, targetPath);
            }

            var result = mode;

            foreach (var subDir in _diskProvider.GetDirectoryInfos(sourcePath))
            {
                if (ShouldIgnore(subDir))
                {
                    continue;
                }

                result &= TransferFolder(subDir.FullName, Path.Combine(targetPath, subDir.Name), mode);
            }

            foreach (var sourceFile in _diskProvider.GetFileInfos(sourcePath))
            {
                if (ShouldIgnore(sourceFile))
                {
                    continue;
                }

                var destFile = Path.Combine(targetPath, sourceFile.Name);

                result &= TransferFile(sourceFile.FullName, destFile, mode, true);
            }

            if (mode.HasFlag(TransferMode.Move))
            {
                var totalSize = _diskProvider.GetFileInfos(sourcePath).Sum(v => v.Length);

                if (totalSize > (100 * 1024L * 1024L))
                {
                    throw new IOException($"Large files still exist in {sourcePath} after folder move, not deleting source folder");
                }

                _diskProvider.DeleteFolder(sourcePath, true);
            }

            return(result);
        }