Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
more
  • Loading branch information
adamsitnik committed Jan 12, 2022
commit d5ba22f1e46a5b218a17023b8069598d860fb623
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,7 @@ public void MoveTo(string destDirName)
string destination = Path.GetFullPath(destDirName);
string destinationWithSeparator = PathInternal.EnsureTrailingSeparator(destination);

FileSystem.MoveDirectory(FullPath, destination, destinationWithSeparator,
OperatingSystem.IsWindows() ? null : Exists); // on Windows we don't need to perform the extra check
FileSystem.MoveDirectory(FullPath, destination, destinationWithSeparator); // on Windows we don't need to perform the extra check

Init(originalPath: destDirName,
fullPath: destinationWithSeparator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -387,43 +387,26 @@ private static void CreateParentsAndDirectory(string fullPath)
}
}

private static void MoveDirectory(string sourceFullPath, string destFullPath, bool sameDirectoryDifferentCase, bool? sourceDirectoryExists)
private static void MoveDirectory(string sourceFullPath, string destFullPath, bool sameDirectoryDifferentCase)
{
ReadOnlySpan<char> srcNoDirectorySeparator = Path.TrimEndingDirectorySeparator(sourceFullPath.AsSpan());
ReadOnlySpan<char> destNoDirectorySeparator = Path.TrimEndingDirectorySeparator(destFullPath.AsSpan());

if (!Path.EndsInDirectorySeparator(sourceFullPath))
{
destFullPath = Path.TrimEndingDirectorySeparator(destFullPath);
}

if (!sameDirectoryDifferentCase) // This check is to allow renaming of directories
{
if (Interop.Sys.Stat(destNoDirectorySeparator, out _) >= 0)
{
sourceDirectoryExists ??= DirectoryExists(sourceFullPath);

// destination exists, but before we throw we need to check whether source exists or not
// Windows will throw if the source file/directory doesn't exist, we preemptively check
// to make sure our cross platform behavior matches .NET Framework behavior.
if (!sourceDirectoryExists.Value)
if (Interop.Sys.Stat(srcNoDirectorySeparator, out Interop.Sys.FileStatus sourceFileStatus) < 0)
{
if (!FileExists(sourceFullPath))
{
throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}

// Windows doesn't care if you try and copy a file via "MoveDirectory"...
// ... but it doesn't like the source to have a trailing slash ...

// On Windows we end up with ERROR_INVALID_NAME, which is
// "The filename, directory name, or volume label syntax is incorrect."
//
// This surfaces as an IOException, if we let it go beyond here it would
// give DirectoryNotFound.

if (Path.EndsInDirectorySeparator(sourceFullPath))
{
throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}
throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}
else if ((sourceFileStatus.Mode & Interop.Sys.FileTypes.S_IFMT) != Interop.Sys.FileTypes.S_IFDIR
&& Path.EndsInDirectorySeparator(sourceFullPath))
{
throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}

// Some Unix distros will overwrite the destination file if it already exists.
Expand All @@ -432,27 +415,28 @@ private static void MoveDirectory(string sourceFullPath, string destFullPath, bo
}
}

if (Interop.Sys.Rename(sourceFullPath, destFullPath) < 0)
if (Interop.Sys.Rename(sourceFullPath, destNoDirectorySeparator.ToString()) < 0)
{
Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
switch (errorInfo.Error)
{
case Interop.Error.EACCES: // match Win32 exception
throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, sourceFullPath), errorInfo.RawErrno);
case Interop.Error.ENOENT:
sourceDirectoryExists ??= DirectoryExists(sourceFullPath);
if (sourceDirectoryExists.Value) // the source directory exists, so destination does not
if (Interop.Sys.Stat(srcNoDirectorySeparator, out Interop.Sys.FileStatus sourceFileStatus) >= 0)
{
// the source directory exists, so destination does not
// example: Move("/tmp/existing/", "/tmp/nonExisting1/nonExisting2/")
throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, destFullPath));
}
else if (Path.EndsInDirectorySeparator(sourceFullPath) || !FileExists(sourceFullPath))
{
// if (Path.EndsInDirectorySeparator(sourceFullPath))
// {
throw new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}
else
{
throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
}
// }
// else
// {
// throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
// }
case Interop.Error.ENOTDIR: // sourceFullPath exists and it's not a directory
throw new IOException(SR.Format(SR.IO_PathNotFound_Path, sourceFullPath));
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ internal static void VerifyValidPath(string path, string argName)
}
}

internal static void MoveDirectory(string sourceFullPath, string destFullPath, string destinationWithSeparator, bool? sourceDirectoryExists = default)
internal static void MoveDirectory(string sourceFullPath, string destFullPath, string destinationWithSeparator)
{
string sourcePath = PathInternal.EnsureTrailingSeparator(sourceFullPath);

Expand All @@ -47,7 +47,7 @@ internal static void MoveDirectory(string sourceFullPath, string destFullPath, s
if (!sourceRoot.Equals(destinationRoot, StringComparison.OrdinalIgnoreCase))
throw new IOException(SR.IO_SourceDestMustHaveSameRoot);

MoveDirectory(sourceFullPath, destFullPath, sameDirectoryDifferentCase, sourceDirectoryExists);
MoveDirectory(sourceFullPath, destFullPath, sameDirectoryDifferentCase);
}
}
}