@@ -102,12 +102,14 @@ func volumeNameLen(path string) int {
102
102
// \\.\unc\a\b\..\c into \\.\unc\a\c.
103
103
return uncLen (path , len (`\\.\UNC\` ))
104
104
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.
107
109
//
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.)
111
113
if len (path ) == 3 {
112
114
return 3 // exactly \\.
113
115
}
@@ -117,14 +119,6 @@ func volumeNameLen(path string) int {
117
119
}
118
120
return len (path ) - len (rest ) - 1
119
121
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
-
128
122
case len (path ) >= 2 && isSlash (path [1 ]):
129
123
// Path starts with \\, and is a UNC path.
130
124
return uncLen (path , 2 )
0 commit comments