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); }
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())); }
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())); }
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); }
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); }