コード例 #1
0
        /// <summary>
        /// Returns the volume name for dos, UNC and device paths.
        /// </summary>
        internal static ReadOnlySpan <char> GetVolumeName(ReadOnlySpan <char> path)
        {
            // 3 cases: UNC ("\\server\share"), Device ("\\?\C:\"), or Dos ("C:\")
            ReadOnlySpan <char> root = GetPathRoot(path);

            if (root.Length == 0)
            {
                return(root);
            }

            // Cut from "\\?\UNC\Server\Share" to "Server\Share"
            // Cut from  "\\Server\Share" to "Server\Share"
            int startOffset = GetUncRootLength(path);

            if (startOffset == -1)
            {
                if (PathInternal.IsDevice(path))
                {
                    startOffset = 4; // Cut from "\\?\C:\" to "C:"
                }
                else
                {
                    startOffset = 0; // e.g. "C:"
                }
            }

            ReadOnlySpan <char> pathToTrim = root.Slice(startOffset);

            return(Path.EndsInDirectorySeparator(pathToTrim) ? pathToTrim.Slice(0, pathToTrim.Length - 1) : pathToTrim);
        }
コード例 #2
0
        /// <summary>
        /// Returns the volume name for dos, UNC and device paths.
        /// </summary>
        internal static ReadOnlySpan <char> GetVolumeName(ReadOnlySpan <char> path)
        {
            // 3 cases: UNC ("\\server\share"), Device ("\\?\C:\"), or Dos ("C:\")
            ReadOnlySpan <char> root = GetPathRoot(path);

            if (root.Length == 0)
            {
                return(root);
            }

            int offset = GetUncRootLength(path);

            if (offset >= 0)
            {
                // Cut from "\\?\UNC\Server\Share" to "Server\Share"
                // Cut from  "\\Server\Share" to "Server\Share"
                return(TrimEndingDirectorySeparator(root.Slice(offset)));
            }
            else if (PathInternal.IsDevice(path))
            {
                return(TrimEndingDirectorySeparator(root.Slice(4))); // Cut from "\\?\C:\" to "C:"
            }

            return(TrimEndingDirectorySeparator(root)); // e.g. "C:"
        }
コード例 #3
0
    public void IsDeviceTest(string path, bool expected)
    {
        StringBuffer sb = new StringBuffer();

        sb.Append(path);

        Assert.Equal(expected, PathInternal.IsDevice(sb));

        Assert.Equal(expected, PathInternal.IsDevice(path));
    }
コード例 #4
0
        internal static int GetUncRootLength(ReadOnlySpan <char> path)
        {
            bool isDevice = PathInternal.IsDevice(path);

            if (!isDevice && path.Slice(0, 2).EqualsOrdinal(@"\\".AsSpan()))
            {
                return(2);
            }
            else if (isDevice && path.Length >= 8 &&
                     (path.Slice(0, 8).EqualsOrdinal(PathInternal.UncExtendedPathPrefix.AsSpan()) ||
                      path.Slice(5, 4).EqualsOrdinal(@"UNC\".AsSpan())))
            {
                return(8);
            }

            return(-1);
        }
コード例 #5
0
        /// <summary>
        /// Perform the additional path checks that would normally happen when creating a FileIOPermission object.
        /// </summary>
        /// <param name="fullPath">A path that has already gone through GetFullPath or Normalize</param>
        internal static void EmulateFileIOPermissionChecks(string fullPath)
        {
            // Callers should have already made checks for invalid path format via normalization. This method will only make the
            // additional checks needed to throw the same exceptions that would normally throw when using FileIOPermission.
            // These checks are done via CheckIllegalCharacters() and StringExpressionSet in AddPathList() above.

#if !PLATFORM_UNIX
            // Checking for colon / invalid characters on device paths blocks legitimate access to objects such as named pipes.
            if (!PathInternal.IsDevice(fullPath))
            {
                // GetFullPath already checks normal invalid path characters. We need to just check additional (wildcard) characters here.
                // (By calling the standard helper we can allow extended paths \\?\ through when the support is enabled.)
                if (PathInternal.HasWildCardCharacters(fullPath))
                {
                    throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
                }

                if (PathInternal.HasInvalidVolumeSeparator(fullPath))
                {
                    throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
                }
            }
#endif // !PLATFORM_UNIX
        }
コード例 #6
0
        public static string GetFullPath(string path, string basePath)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (basePath == null)
            {
                throw new ArgumentNullException(nameof(basePath));
            }

            if (!IsPathFullyQualified(basePath))
            {
                throw new ArgumentException(SR.Arg_BasePathNotFullyQualified, nameof(basePath));
            }

            if (basePath.Contains('\0') || path.Contains('\0'))
            {
                throw new ArgumentException(SR.Argument_InvalidPathChars);
            }

            if (IsPathFullyQualified(path))
            {
                return(GetFullPath(path));
            }

            if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
            {
                return(basePath);
            }

            int    length = path.Length;
            string combinedPath;

            if (length >= 1 && PathInternal.IsDirectorySeparator(path[0]))
            {
                // Path is current drive rooted i.e. starts with \:
                // "\Foo" and "C:\Bar" => "C:\Foo"
                // "\Foo" and "\\?\C:\Bar" => "\\?\C:\Foo"
                combinedPath = Join(GetPathRoot(basePath.AsSpan()), path.AsSpan(1)); // Cut the separator to ensure we don't end up with two separators when joining with the root.
            }
            else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
            {
                // Drive relative paths
                Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));

                if (GetVolumeName(path.AsSpan()).EqualsOrdinal(GetVolumeName(basePath.AsSpan())))
                {
                    // Matching root
                    // "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
                    // "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                    combinedPath = Join(basePath.AsSpan(), path.AsSpan(2));
                }
                else
                {
                    // No matching root, root to specified drive
                    // "D:Foo" and "C:\Bar" => "D:Foo"
                    // "D:Foo" and "\\?\C:\Bar" => "\\?\D:\Foo"
                    combinedPath = !PathInternal.IsDevice(basePath.AsSpan())
                        ? path.Insert(2, @"\")
                        : length == 2
                            ? JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(), @"\".AsSpan())
                            : JoinInternal(basePath.AsSpan(0, 4), path.AsSpan(0, 2), @"\".AsSpan(), path.AsSpan(2));
                }
            }
            else
            {
                // "Simple" relative path
                // "Foo" and "C:\Bar" => "C:\Bar\Foo"
                // "Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                combinedPath = JoinInternal(basePath.AsSpan(), path.AsSpan());
            }

            // Device paths are normalized by definition, so passing something of this format (i.e. \\?\C:\.\tmp, \\.\C:\foo)
            // to Windows APIs won't do anything by design. Additionally, GetFullPathName() in Windows doesn't root
            // them properly. As such we need to manually remove segments and not use GetFullPath().

            return(PathInternal.IsDevice(combinedPath.AsSpan())
                ? PathInternal.RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath.AsSpan()))
                : GetFullPath(combinedPath));
        }
コード例 #7
0
 public void IsDeviceTest(string path, bool expected)
 {
     Assert.Equal(expected, PathInternal.IsDevice(path));
 }