From 33c1717e06756301ff4dec9ac3f2a5db56359cfd Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Fri, 16 Jun 2017 13:45:27 -0700 Subject: [PATCH] Add path to exception messages (dotnet/coreclr#12322) * Remove dead code * Arg_PathIllegal * IO_PathTooLong * Remove no longer necessary path sanitization * Argument_PathFormatNotSupported * Arg_PathIllegalUNC * Arg_InvalidSearchPattern * Dead strings * Missing nameof Commit migrated from https://github.com/dotnet/coreclr/commit/6ba74dc2a7194f8d6c86c3aeab572a074ef645c8 --- src/coreclr/src/mscorlib/Resources/Strings.resx | 25 ++++--- .../shared/Interop/Unix/Interop.IOErrors.cs | 4 +- .../src/mscorlib/shared/System/IO/Path.Unix.cs | 8 +-- .../src/mscorlib/shared/System/IO/Path.Windows.cs | 6 +- src/coreclr/src/mscorlib/shared/System/IO/Path.cs | 2 +- .../shared/System/IO/PathHelper.Windows.cs | 10 +-- .../src/mscorlib/shared/System/IO/PathInternal.cs | 2 +- .../src/mscorlib/shared/System/IO/Win32Marshal.cs | 2 +- src/coreclr/src/mscorlib/src/System/IO/__Error.cs | 77 +++------------------- 9 files changed, 37 insertions(+), 99 deletions(-) diff --git a/src/coreclr/src/mscorlib/Resources/Strings.resx b/src/coreclr/src/mscorlib/Resources/Strings.resx index cbf969e..52bd625c 100644 --- a/src/coreclr/src/mscorlib/Resources/Strings.resx +++ b/src/coreclr/src/mscorlib/Resources/Strings.resx @@ -88,9 +88,6 @@ Cannot set a constant field. - - SkipVerification permission is needed to modify an image-based (RVA) static field. - Cannot create an instance of void. @@ -353,7 +350,7 @@ Operation is not valid due to the current state of the object. - Search pattern cannot contain ".." to move up directories and can be contained only internally in file/directory names, as in "a..b". + Search pattern '{0}' cannot contain ".." to move up directories and can be contained only internally in file/directory names, as in "a..b". The return Type contains some invalid type (i.e. null, ByRef) @@ -589,11 +586,11 @@ Parameter count mismatch. - - The path is not of a legal form. + + The path is empty. - - The UNC path should be of the form \\\\server\\share. + + The UNC path '{0}' should be of the form \\\\server\\share. Operation is not supported on this platform. @@ -1384,8 +1381,8 @@ Path cannot be the empty string or all whitespace. - - The given path's format is not supported. + + The format of the path '{0}' is not supported. 'preAllocated' is already in use. @@ -2703,7 +2700,7 @@ Could not find file '{0}'. - Cannot create "{0}" because a file or directory with the same name already exists. + Cannot create '{0}' because a file or directory with the same name already exists. BindHandle for ThreadPool failed on this handle. @@ -2726,9 +2723,6 @@ BinaryReader encountered an invalid string length of {0} characters. - - <Path discovery permission to the specified directory was denied.> - Unable seek backward to overwrite data that previously existed in a file opened in Append mode. @@ -2756,6 +2750,9 @@ The specified file name or path is too long, or a component of the specified path is too long. + + The path '{0}' is too long, or a component of the specified path is too long. + [Unknown] diff --git a/src/coreclr/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs b/src/coreclr/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs index e9d6ce6..5babcd1 100644 --- a/src/coreclr/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs +++ b/src/coreclr/src/mscorlib/shared/Interop/Unix/Interop.IOErrors.cs @@ -138,7 +138,9 @@ internal static partial class Interop new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName, inner); case Error.ENAMETOOLONG: - return new PathTooLongException(SR.IO_PathTooLong); + return !string.IsNullOrEmpty(path) ? + new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path)) : + new PathTooLongException(SR.IO_PathTooLong); case Error.EWOULDBLOCK: return !string.IsNullOrEmpty(path) ? diff --git a/src/coreclr/src/mscorlib/shared/System/IO/Path.Unix.cs b/src/coreclr/src/mscorlib/shared/System/IO/Path.Unix.cs index 68c5f70..f8ff595 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/Path.Unix.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/Path.Unix.cs @@ -23,7 +23,7 @@ namespace System.IO throw new ArgumentNullException(nameof(path)); if (path.Length == 0) - throw new ArgumentException(SR.Arg_PathIllegal, nameof(path)); + throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); PathInternal.CheckInvalidPathChars(path); @@ -42,7 +42,7 @@ namespace System.IO if (collapsedString.Length > Interop.Sys.MaxPath) { - throw new PathTooLongException(SR.IO_PathTooLong); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path)); } string result = collapsedString.Length == 0 ? PathInternal.DirectorySeparatorCharAsString : collapsedString; @@ -120,7 +120,7 @@ namespace System.IO if (++componentCharCount > Interop.Sys.MaxName) { - throw new PathTooLongException(SR.IO_PathTooLong); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path)); } // Normalize the directory separator if needed @@ -199,7 +199,7 @@ namespace System.IO { if (path == null) return null; if (string.IsNullOrWhiteSpace(path)) - throw new ArgumentException(SR.Arg_PathIllegal, nameof(path)); + throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); return IsPathRooted(path) ? PathInternal.DirectorySeparatorCharAsString : String.Empty; } diff --git a/src/coreclr/src/mscorlib/shared/System/IO/Path.Windows.cs b/src/coreclr/src/mscorlib/shared/System/IO/Path.Windows.cs index 1e573cd..6dd4d71 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/Path.Windows.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/Path.Windows.cs @@ -70,13 +70,13 @@ namespace System.IO || (path.Length >= startIndex && path[startIndex - 1] == PathInternal.VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) || (path.Length > startIndex && path.IndexOf(PathInternal.VolumeSeparatorChar, startIndex) != -1)) { - throw new NotSupportedException(SR.Argument_PathFormatNotSupported); + throw new NotSupportedException(SR.Format(SR.Argument_PathFormatNotSupported_Path, path)); } } // Technically this doesn't matter but we used to throw for this case if (string.IsNullOrWhiteSpace(path)) - throw new ArgumentException(SR.Arg_PathIllegal); + throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); // We don't want to check invalid characters for device format- see comments for extended above string fullPath = PathHelper.Normalize(path, checkInvalidCharacters: !isDevice, expandShortPaths: true); @@ -142,7 +142,7 @@ namespace System.IO { if (path == null) return null; if (string.IsNullOrWhiteSpace(path)) - throw new ArgumentException(SR.Arg_PathIllegal, nameof(path)); + throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); PathInternal.CheckInvalidPathChars(path); diff --git a/src/coreclr/src/mscorlib/shared/System/IO/Path.cs b/src/coreclr/src/mscorlib/shared/System/IO/Path.cs index 9feb287..6db635d 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/Path.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/Path.cs @@ -79,7 +79,7 @@ namespace System.IO if (string.IsNullOrWhiteSpace(path)) { if (path == null) return null; - throw new ArgumentException(SR.Arg_PathIllegal, nameof(path)); + throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); } PathInternal.CheckInvalidPathChars(path); diff --git a/src/coreclr/src/mscorlib/shared/System/IO/PathHelper.Windows.cs b/src/coreclr/src/mscorlib/shared/System/IO/PathHelper.Windows.cs index e2ead93..c88b553 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/PathHelper.Windows.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/PathHelper.Windows.cs @@ -53,7 +53,7 @@ namespace System.IO if (fullPath.Length >= PathInternal.MaxLongPath) { // Fullpath is genuinely too long - throw new PathTooLongException(SR.IO_PathTooLong); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, fullPath.ToString())); } // Checking path validity used to happen before getting the full path name. To avoid additional input allocation @@ -109,7 +109,7 @@ namespace System.IO case '\\': segmentLength = index - lastSeparator - 1; if (segmentLength > PathInternal.MaxComponentLength) - throw new PathTooLongException(SR.IO_PathTooLong + fullPath.ToString()); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, fullPath.ToString())); lastSeparator = index; if (foundTilde) @@ -128,7 +128,7 @@ namespace System.IO // If we're at the end of the path and this is the first separator, we're missing the share. // Otherwise we're good, so ignore UNC tracking from here. if (index == fullPath.Length - 1) - throw new ArgumentException(SR.Arg_PathIllegalUNC); + throw new ArgumentException(SR.Format(SR.Arg_PathIllegalUNC_Path, fullPath.ToString())); else possibleBadUnc = false; } @@ -145,11 +145,11 @@ namespace System.IO } if (possibleBadUnc) - throw new ArgumentException(SR.Arg_PathIllegalUNC); + throw new ArgumentException(SR.Format(SR.Arg_PathIllegalUNC_Path, fullPath.ToString())); segmentLength = fullPath.Length - lastSeparator - 1; if (segmentLength > PathInternal.MaxComponentLength) - throw new PathTooLongException(SR.IO_PathTooLong); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, fullPath.ToString())); if (foundTilde && segmentLength <= MaxShortName) possibleShortPath = true; diff --git a/src/coreclr/src/mscorlib/shared/System/IO/PathInternal.cs b/src/coreclr/src/mscorlib/shared/System/IO/PathInternal.cs index 0dab5b9..63753e9 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/PathInternal.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/PathInternal.cs @@ -162,7 +162,7 @@ namespace System.IO // Terminal ".." . Files names cannot end in ".." if (index + 2 == searchPattern.Length || IsDirectorySeparator(searchPattern[index + 2])) - throw new ArgumentException(SR.Arg_InvalidSearchPattern); + throw new ArgumentException(SR.Format(SR.Arg_InvalidSearchPattern, searchPattern)); searchPattern = searchPattern.Substring(index + 2); } diff --git a/src/coreclr/src/mscorlib/shared/System/IO/Win32Marshal.cs b/src/coreclr/src/mscorlib/shared/System/IO/Win32Marshal.cs index ef76c27..a24409e 100644 --- a/src/coreclr/src/mscorlib/shared/System/IO/Win32Marshal.cs +++ b/src/coreclr/src/mscorlib/shared/System/IO/Win32Marshal.cs @@ -63,7 +63,7 @@ namespace System.IO return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode)); case Interop.Errors.ERROR_FILENAME_EXCED_RANGE: - return new PathTooLongException(SR.IO_PathTooLong); + return new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, path)); case Interop.Errors.ERROR_INVALID_PARAMETER: return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); diff --git a/src/coreclr/src/mscorlib/src/System/IO/__Error.cs b/src/coreclr/src/mscorlib/src/System/IO/__Error.cs index 1af195e..785a79e 100644 --- a/src/coreclr/src/mscorlib/src/System/IO/__Error.cs +++ b/src/coreclr/src/mscorlib/src/System/IO/__Error.cs @@ -75,63 +75,6 @@ namespace System.IO throw new ArgumentException(SR.InvalidOperation_EndWriteCalledMultiple); } - // Given a possible fully qualified path, ensure that we have path - // discovery permission to that path. If we do not, return just the - // file name. If we know it is a directory, then don't return the - // directory name. - internal static String GetDisplayablePath(String path, bool isInvalidPath) - { - if (String.IsNullOrEmpty(path)) - return String.Empty; - - // Is it a fully qualified path? - bool isFullyQualified = false; - if (path.Length < 2) - return path; - if (PathInternal.IsDirectorySeparator(path[0]) && PathInternal.IsDirectorySeparator(path[1])) - isFullyQualified = true; - else if (path[1] == Path.VolumeSeparatorChar) - { - isFullyQualified = true; - } - - if (!isFullyQualified && !isInvalidPath) - return path; - - bool safeToReturn = false; - try - { - if (!isInvalidPath) - { - safeToReturn = true; - } - } - catch (SecurityException) - { - } - catch (ArgumentException) - { - // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters - // inside FileIOPermission.AddPathList - } - catch (NotSupportedException) - { - // paths like "!Bogus\\dir:with/junk_.in it" can cause NotSupportedException to be thrown - // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path - // beyond string index position 1. - } - - if (!safeToReturn) - { - if (PathInternal.IsDirectorySeparator(path[path.Length - 1])) - path = SR.IO_NoPermissionToDirectoryName; - else - path = Path.GetFileName(path); - } - - return path; - } - internal static void WinIOError() { int errorCode = Marshal.GetLastWin32Error(); @@ -143,12 +86,8 @@ namespace System.IO // will determine the appropriate exception to throw dependent on your // error, and depending on the error, insert a string into the message // gotten from the ResourceManager. - internal static void WinIOError(int errorCode, String maybeFullPath) + internal static void WinIOError(int errorCode, String str) { - // This doesn't have to be perfect, but is a perf optimization. - bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME; - String str = GetDisplayablePath(maybeFullPath, isInvalidPath); - switch (errorCode) { case Win32Native.ERROR_FILE_NOT_FOUND: @@ -172,33 +111,33 @@ namespace System.IO case Win32Native.ERROR_ALREADY_EXISTS: if (str.Length == 0) goto default; - throw new IOException(SR.Format(SR.IO_AlreadyExists_Name, str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(SR.Format(SR.IO_AlreadyExists_Name, str), Win32Native.MakeHRFromErrorCode(errorCode), str); case Win32Native.ERROR_FILENAME_EXCED_RANGE: - throw new PathTooLongException(SR.IO_PathTooLong); + throw new PathTooLongException(SR.Format(SR.IO_PathTooLong_Path, str)); case Win32Native.ERROR_INVALID_DRIVE: throw new DriveNotFoundException(SR.Format(SR.IO_DriveNotFound_Drive, str)); case Win32Native.ERROR_INVALID_PARAMETER: - throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), str); case Win32Native.ERROR_SHARING_VIOLATION: if (str.Length == 0) - throw new IOException(SR.IO_SharingViolation_NoFileName, Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(SR.IO_SharingViolation_NoFileName, Win32Native.MakeHRFromErrorCode(errorCode), str); else - throw new IOException(SR.Format(SR.IO_SharingViolation_File, str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(SR.Format(SR.IO_SharingViolation_File, str), Win32Native.MakeHRFromErrorCode(errorCode), str); case Win32Native.ERROR_FILE_EXISTS: if (str.Length == 0) goto default; - throw new IOException(SR.Format(SR.IO_FileExists_Name, str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(SR.Format(SR.IO_FileExists_Name, str), Win32Native.MakeHRFromErrorCode(errorCode), str); case Win32Native.ERROR_OPERATION_ABORTED: throw new OperationCanceledException(); default: - throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath); + throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), str); } } -- 2.7.4