@@ -102,12 +102,14 @@ func volumeNameLen(path string) int {
102102 // \\.\unc\a\b\..\c into \\.\unc\a\c.
103103 return uncLen (path , len (`\\.\UNC\` ))
104104
105- case pathHasPrefixFold (path , `\\.` ):
106- // Path starts with \\., and is a Local Device path.
105+ case pathHasPrefixFold (path , `\\.` ) ||
106+ pathHasPrefixFold (path , `\\?` ) || pathHasPrefixFold (path , `\??` ):
107+ // Path starts with \\.\, and is a Local Device path; or
108+ // path starts with \\?\ or \??\ and is a Root Local Device path.
107109 //
108- // We currently treat the next component after the \\.\ prefix
109- // as part of the volume name, although there doesn't seem to be
110- // a principled reason to do this.
110+ // We treat the next component after the \\.\ prefix as
111+ // part of the volume name, which means Clean(`\\?\c:\`)
112+ // won't remove the trailing \. (See #64028.)
111113 if len (path ) == 3 {
112114 return 3 // exactly \\.
113115 }
@@ -117,14 +119,6 @@ func volumeNameLen(path string) int {
117119 }
118120 return len (path ) - len (rest ) - 1
119121
120- case pathHasPrefixFold (path , `\\?` ) || pathHasPrefixFold (path , `\??` ):
121- // Path starts with \\?\ or \??\, and is a Root Local Device path.
122- //
123- // While Windows usually treats / and \ as equivalent,
124- // /??/ does not seem to be recognized as a Root Local Device path.
125- // We treat it as one anyway here to be safe.
126- return 3
127-
128122 case len (path ) >= 2 && isSlash (path [1 ]):
129123 // Path starts with \\, and is a UNC path.
130124 return uncLen (path , 2 )
0 commit comments