Beispiel #1
0
        public override Task <StorageFolder> CopyAsync(
            StoragePath destinationPath,
            NameCollisionOption options,
            CancellationToken cancellationToken = default
            )
        {
            _ = destinationPath ?? throw new ArgumentNullException(nameof(destinationPath));
            if (!EnumInfo.IsDefined(options))
            {
                throw new ArgumentException(ExceptionStrings.Enum.UndefinedValue(options), nameof(options));
            }

            if (!(destinationPath is PhysicalStoragePath))
            {
                throw new ArgumentException(
                          ExceptionStrings.FsCompatibility.StoragePathTypeNotSupported(),
                          nameof(destinationPath)
                          );
            }

            return(Task.Run(() =>
            {
                var fullDestinationPath = destinationPath.FullPath;
                var destination = FileSystem.GetFolder(destinationPath);
                var overwrite = options.ToOverwriteBool();

                // Specification requires DirectoryNotFoundException if the destination parent folder
                // does not exist.
                if (destination.Parent is PhysicalStorageFolder destinationParent)
                {
                    destinationParent.EnsureExists();
                }

                if (overwrite)
                {
                    DeleteConflictingDestinationFolderWithoutDeletingThisFolder(fullDestinationPath.ToString());

                    // At this point the conflicting destination folder should be deleted.
                    // If that is not the case, we can assume that we are essentially copying
                    // the folder to the same location (because otherwise, the method above would
                    // have deleted the folder at the destination path).
                    if (Directory.Exists(fullDestinationPath.ToString()))
                    {
                        throw new IOException(ExceptionStrings.StorageFolder.CannotCopyToSameLocation());
                    }
                }
                else
                {
                    // The CopyDirectory helper cannot easily verify that no conflicting folder exists
                    // at the destination. Specification requires an IOException on conflicts for the Fail option.
                    if (Directory.Exists(fullDestinationPath.ToString()))
                    {
                        throw new IOException(ExceptionStrings.StorageFolder.CopyConflictingFolderExistsAtDestination());
                    }
                }

                FsHelper.CopyDirectory(_fullPath.ToString(), fullDestinationPath.ToString(), cancellationToken);
                return destination;
            }, cancellationToken));
        }
Beispiel #2
0
        public override Task <StorageFile> CopyAsync(
            StoragePath destinationPath,
            NameCollisionOption options,
            CancellationToken cancellationToken = default
            )
        {
            _ = destinationPath ?? throw new ArgumentNullException(nameof(destinationPath));
            if (!EnumInfo.IsDefined(options))
            {
                throw new ArgumentException(ExceptionStrings.Enum.UndefinedValue(options), nameof(options));
            }

            if (!(destinationPath is PhysicalStoragePath))
            {
                throw new ArgumentException(
                          ExceptionStrings.FsCompatibility.StoragePathTypeNotSupported(),
                          nameof(destinationPath)
                          );
            }

            return(Task.Run(() =>
            {
                var fullDstPath = destinationPath.FullPath;
                var overwrite = options.ToOverwriteBool();

#if NETCOREAPP2_0 || NETCOREAPP2_1 || NETCOREAPP2_2
                // File.Copy on Unix systems AND .NET Core 2.0 - 2.2 has this weird behavior where
                // no exception is thrown if the destination is a folder. When copying a file to
                // a conflicting folder, the API, instead of throwing, simply moves the file *into*
                // the folder. For example, assume that we copy "src/srcFile.ext" to "dst":
                // |_ src
                // |  |_ srcFile.ext
                // |_ dst
                //
                // We'd assume that this throws, but instead, this happens:
                // |_ src
                // |  |_ srcFile.ext
                // |_ dst
                //    |_ srcFile.ext
                //
                // This can be fixed by preemptively verifying that there is no conflicting folder.
                // This has the disadvantage that we lose the inner exception which would normally
                // be thrown (the UnauthorizedAccessException below). To not lose it with other TFMs,
                // only include the check in the failing .NET Core versions.
                EnsureNoConflictingFolderExists(fullDstPath.ToString());
#endif

                try
                {
                    File.Copy(_fullPath.ToString(), fullDstPath.ToString(), overwrite);
                    return FileSystem.GetFile(destinationPath);
                }
                catch (UnauthorizedAccessException ex)
                {
                    EnsureNoConflictingFolderExists(_fullPath.ToString(), ex);
                    EnsureNoConflictingFolderExists(fullDstPath.ToString(), ex);
                    throw;
                }
            }, cancellationToken));
        }
Beispiel #3
0
        public override Task <StorageFolder> MoveAsync(
            StoragePath destinationPath,
            NameCollisionOption options,
            CancellationToken cancellationToken = default
            )
        {
            _ = destinationPath ?? throw new ArgumentNullException(nameof(destinationPath));
            if (!EnumInfo.IsDefined(options))
            {
                throw new ArgumentException(ExceptionStrings.Enum.UndefinedValue(options), nameof(options));
            }

            if (!(destinationPath is PhysicalStoragePath))
            {
                throw new ArgumentException(
                          ExceptionStrings.FsCompatibility.StoragePathTypeNotSupported(),
                          nameof(destinationPath)
                          );
            }

            return(Task.Run(() =>
            {
                // For whatever reason, Directory.Move moves files instead of throwing an exception.
                // We've got to manually verify that the current location actually is a directory and not a file.
                EnsureNoConflictingFileExists();

                var fullDestinationPath = destinationPath.FullPath;
                var destination = FileSystem.GetFolder(destinationPath);
                var overwrite = options.ToOverwriteBool();

                if (overwrite)
                {
                    DeleteConflictingDestinationFolderWithoutDeletingThisFolder(fullDestinationPath.ToString());

                    // At this point the conflicting destination folder should be deleted.
                    // If that is not the case, we can assume that we are essentially moving
                    // the folder to the same location (because otherwise, the method above would
                    // have deleted the folder at the destination path).
                    if (Directory.Exists(fullDestinationPath.ToString()))
                    {
                        throw new IOException(ExceptionStrings.StorageFolder.CannotMoveToSameLocation());
                    }
                }

                cancellationToken.ThrowIfCancellationRequested();
                Directory.Move(_fullPath.ToString(), fullDestinationPath.ToString());
                return destination;
            }, cancellationToken));
        }
Beispiel #4
0
        public override Task <StorageFile> MoveAsync(
            StoragePath destinationPath,
            NameCollisionOption options,
            CancellationToken cancellationToken = default
            )
        {
            _ = destinationPath ?? throw new ArgumentNullException(nameof(destinationPath));
            if (!EnumInfo.IsDefined(options))
            {
                throw new ArgumentException(ExceptionStrings.Enum.UndefinedValue(options), nameof(options));
            }

            if (!(destinationPath is PhysicalStoragePath))
            {
                throw new ArgumentException(
                          ExceptionStrings.FsCompatibility.StoragePathTypeNotSupported(),
                          nameof(destinationPath)
                          );
            }

            return(Task.Run(() =>
            {
                EnsureExists(cancellationToken);

                var fullDestinationPath = destinationPath.FullPath;
                var overwrite = options.ToOverwriteBool();

                // System.IO doesn't throw when moving files to the same location.
                // Detecting this via paths will not always work, but it fulfills the spec most of the time.
                if (_fullPath == fullDestinationPath)
                {
                    throw new IOException(ExceptionStrings.StorageFile.CannotMoveToSameLocation());
                }

                try
                {
                    FilePolyfills.Move(_fullPath.ToString(), fullDestinationPath.ToString(), overwrite);
                    return FileSystem.GetFile(destinationPath);
                }
                catch (UnauthorizedAccessException ex)
                {
                    EnsureNoConflictingFolderExists(_fullPath.ToString(), ex);
                    EnsureNoConflictingFolderExists(fullDestinationPath.ToString(), ex);
                    throw;
                }
            }, cancellationToken));
        }