示例#1
0
        /// <summary>
        /// Returns offset as -1 if the path is not in Unc format, otherwise returns the root length.
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        internal static int GetUncRootLength(ReadOnlySpan <char> path)
        {
            bool isDevice = PathInternal.IsDevice(path);

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

            return(-1);
        }
示例#2
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));
            }

            int    length       = path.Length;
            string combinedPath = null;

            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);
            }
            else if (length >= 2 && PathInternal.IsValidDriveChar(path[0]) && path[1] == PathInternal.VolumeSeparatorChar)
            {
                // Drive relative paths
                Debug.Assert(length == 2 || !PathInternal.IsDirectorySeparator(path[2]));

                if (StringSpanHelpers.Equals(GetVolumeName(path), GetVolumeName(basePath)))
                {
                    // Matching root
                    // "C:Foo" and "C:\Bar" => "C:\Bar\Foo"
                    // "C:Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                    combinedPath = Join(basePath, path.AsSpan().Slice(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)
                        ? path.Insert(2, @"\")
                        : length == 2
                            ? JoinInternal(basePath.AsSpan().Slice(0, 4), path, @"\")
                            : JoinInternal(basePath.AsSpan().Slice(0, 4), path.AsSpan().Slice(0, 2), @"\", path.AsSpan().Slice(2));
                }
            }
            else
            {
                // "Simple" relative path
                // "Foo" and "C:\Bar" => "C:\Bar\Foo"
                // "Foo" and "\\?\C:\Bar" => "\\?\C:\Bar\Foo"
                combinedPath = JoinInternal(basePath, path);
            }

            // Device paths are normalized by definition, so passing something of this format
            // to GetFullPath() won't do anything by design. Additionally, GetFullPathName() in
            // Windows doesn't root them properly. As such we need to manually remove segments.
            return(PathInternal.IsDevice(combinedPath)
                ? RemoveRelativeSegments(combinedPath, PathInternal.GetRootLength(combinedPath))
                : GetFullPath(combinedPath));
        }