镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Inconsistent results for path.toNamespacedPath() for win32 UNC paths #30224

Description

@btsimonh
  • Version: v12.10.0
  • Platform: windows 10 64 bit
  • Subsystem: path/fs

when using UNC paths, the function path.toNamespacedPath() gives different results from non UNC paths.

This is reproduced by running the code attached below.
Basically, most of the time in Node, you can freely use '/' and '', and most repos just use '/', for example this snippet:
fs.readdirSync(__dirname + '/grant').forEach(function(filename) {
from
https://github.com/jaredhanson/oauth2orize/blob/master/lib/index.js

The issue is that if the path being accessed is a UNC style (actually, problem is only if accessed pre-namespaced?) path, then the '/' does not get translated to a '' on windows. If the path is a 'normal' drive based windows path, then the '/' is replaced by '' in path.toNamespacedPath(), which is used by most fs functions to qualify a path, and so there is no issue.

As you can see from the results of the simple tests, path.win32.resolve('\\?\c:\Windows/System') returns '\\?\c:\Windows\System'.
path.toNamespacedPath(path) uses this internally, but returns path, not resolvedPath in this circumstance. So the resulting path from path.toNamespacedPath('\\?\c:\Windows/System') is '\\?\c:\Windows/System' - which is invalid.
(I will post a proposed solution in the next comment).

Simple example test:

on a windows system, run the following code:

var tests = [
  'c:\\Windows\\System',
  'c:\\Windows/System',
  '\\\\?\\c:\\Windows\\System',
  '\\\\?\\c:\\Windows/System',
]

var path = require('path');
var fs = require('fs');

for (var i = 0; i < tests.length; i++) {
  console.log('path.toNamespacedPath("'+tests[i]+'") -> "'+path.toNamespacedPath(tests[i])+'"');
  console.log('path.win32.normalize("'+tests[i]+'") -> "'+path.win32.normalize(tests[i])+'"');
  console.log('path.win32.resolve("'+tests[i]+'") -> "'+path.win32.resolve(tests[i])+'"');
  try{
    var dir = fs.readdirSync(tests[i]);
    console.log('fs.readdirSync("'+tests[i]+'") success');
  } catch(e) {
    console.log(e);
    console.log('fs.readdirSync("'+tests[i]+'") failed');
  }
}

Activity

  1. btsimonh commented on Nov 2, 2019

    @btsimonh
    Author

    Suggest, in path.js:

      toNamespacedPath(path) {
        // Note: this will *probably* throw somewhere.
        if (typeof path !== 'string')
          return path;
    
        if (path.length === 0) {
          return '';
        }
    
        const resolvedPath = win32.resolve(path);
    
        if (resolvedPath.length <= 2)
          return path;
    
        if (resolvedPath.charCodeAt(0) === CHAR_BACKWARD_SLASH) {
          // Possible UNC root
          if (resolvedPath.charCodeAt(1) === CHAR_BACKWARD_SLASH) {
            const code = resolvedPath.charCodeAt(2);
            if (code !== CHAR_QUESTION_MARK && code !== CHAR_DOT) {
              // Matched non-long UNC root, convert the path to a long UNC path
              return `\\\\?\\UNC\\${resolvedPath.slice(2)}`;
            }
          }
        } else if (isWindowsDeviceRoot(resolvedPath.charCodeAt(0)) &&
                   resolvedPath.charCodeAt(1) === CHAR_COLON &&
                   resolvedPath.charCodeAt(2) === CHAR_BACKWARD_SLASH) {
          // Matched device root, convert the path to a long UNC path
          return `\\\\?\\${resolvedPath}`;
        }
    
        ////// Modified - since this is ONLY on windows, why not the resolved path? /////////////
        ////// is it not always our best result? /////////////
        return resolvedPath;
        ///////////////////
      },
    
    
  2. btsimonh commented on Nov 2, 2019

    @btsimonh
    Author

    p.s.

    var tests = [
      'c:\\Windows\\System',
      'c:\\Windows/System',
      '\\\\localhost\\c$\\Windows\\System',
      '\\\\localhost\\c$\\Windows/System',
    ]
    

    works fine.... so UNC paths are all good.

  3. added
    pathIssues and PRs related to the path subsystem.
    windowsIssues and PRs related to the Windows platform.
    on Dec 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pathIssues and PRs related to the path subsystem.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions