Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dir.pwd showing wrong Windows UNC path when UNC path is a current directory at startup #3665

Open
rsim opened this issue Feb 14, 2016 · 9 comments
Labels

Comments

@rsim
Copy link

rsim commented Feb 14, 2016

There is a strange Dir.pwd bug which shows current Windows UNC path //server/share/directory as //server/share/:/server/share/directory if JRuby was started from this Windows UNC path as a current directory. I debugged that this invalid Windows drive //server/share/: is added by org.jruby.util.NormalizedFile class method getCanonicalPath.

See how to reproduce the issue. Start Windows Power Shell (as cmd.exe does not support changing the current directory to Windows UNC path) and execute the following commands. -Djruby.home is added due to the #3661 issue.

PS C:\> cd \\server\share\directory
PS Microsoft.PowerShell.Core\FileSystem::\\server\share\directory> java "-Djruby.home=uri:classloader://META-INF/jruby.home" -jar jruby-complete-1.7.24.jar -S irb
irb(main):001:0> Dir.pwd
=> "//server/share/:/server/share/directory"
irb(main):002:0> org.jruby.util.NormalizedFile.new(JRuby.runtime.getCurrentDirectory).getCanonicalPath
=> "//server/share/:/server/share/directory"
irb(main):003:0> JRuby.runtime.getCurrentDirectory
=> "//server/share/directory"
@rsim
Copy link
Author

rsim commented Feb 14, 2016

@enebo Here is another problem with UNC path support on Windows.

@enebo enebo added this to the JRuby 1.7.25 milestone Feb 15, 2016
@enebo enebo added the windows label Feb 15, 2016
@enebo
Copy link
Member

enebo commented Feb 15, 2016

@rsim thanks for reducing this so much

@enebo
Copy link
Member

enebo commented Feb 15, 2016

@rsim unfortunately this is how java.io.File is representing this path coming from Java APIs themselves. I guess we could try post-processing this from //s/sh/:/s/sh/.. to //s/sh/..

@rsim
Copy link
Author

rsim commented Feb 15, 2016

When I was debugging Dir.pwd then it seemed to me that org.jruby.util.NormalizedFile.new(JRuby.runtime.getCurrentDirectory).getCanonicalPath returned this strange result only when UNC path was the initial current directory. Otherwise getCanonicalPath raised an exception and then RubyDir method getCWD ignored this exception.

For example, if I start JRuby from C:\ and do

irb(main):001:0> Dir.chdir("/C:/PROGRA~1"){Dir.pwd}
=> "C:/Program Files"

Then I see the 8.3 short file name expanded to the full file name. But if I create \\server\share\Program Files directory then (assuming that the short name is PROGRA~1) getCanonicalPath raises an error:

irb(main):001:0> Dir.chdir("//server/share/PROGRA~1"){Dir.pwd}
=> "//server/share/PROGRA~1"
irb(main):002:0> org.jruby.util.NormalizedFile.new("//server/share/PROGRA~1").getCanonicalPath
Java::JavaIo::IOException: The filename, directory name, or volume label syntax is incorrect
        from java.io.WinNTFileSystem.canonicalize0(Native Method)
        from jnr.posix.JavaSecuredFile.getCanonicalPath(jnr/posix/JavaSecuredFile.java:187)
        from RUBY.evaluate((irb):3)
irb(main):003:0> org.jruby.util.NormalizedFile.new("//server/share/Program Files").getCanonicalPath
Java::JavaIo::IOException: The filename, directory name, or volume label syntax is incorrect
        from java.io.WinNTFileSystem.canonicalize0(Native Method)
        from jnr.posix.JavaSecuredFile.getCanonicalPath(jnr/posix/JavaSecuredFile.java:187)
        from RUBY.evaluate((irb):3)

Probably getCWD should check the result of getCanonicalPath and if it is returning invalid strange Windows drive letter then ignore the result and return just runtime.getCurrentDirectory().

@enebo
Copy link
Member

enebo commented Apr 12, 2016

@rsim This is so weird. I cannot see how this actually works the way it does. It totally confounds me. Something in Normalized file is interacting with the impl of File.getCanonicalPath. Seems really weird since java.io.File and JavaSecuredFile both work as expected.

Current theory is that File and FileSystem are somehow calling overriden versions of methods in NormalizedFile but those methods return '/' delimited paths and not ''. It gets confused and returns the wrong thing. If true then I should not even need powershell to repro this (and I happen to have a NAS drive so I am seeing exact same behavior).

@enebo
Copy link
Member

enebo commented Apr 12, 2016

This UNC path exists but WindowsFileSystem is horking on the result. This is basically just a variation of your stack trace but there is no 8.3 thing mixed into this. I will see if I can figure out WFS is doing but if it involves getting '/' vs '' paths from normalized file then ????

We can fallover on exception in this case and maybe it will work if we fix the goofy path but honestly I think we will just find lots of other places where we start seeing this stacktrace show up:

irb(main):006:0> path = "//nasdf2504/pc"
=> "//nasdf2504/pc"
irb(main):007:0> jf = java.io.File.new path
=> #<Java::JavaIo::File:0x376a2553>
irb(main):008:0> sf = Java::jnr.posix.JavaSecuredFile.new path
=> #<Java::JnrPosix::JavaSecuredFile:0x1e441100>
irb(main):009:0> nf = org.jruby.util.NormalizedFile.new path
=> #<Java::OrgJrubyUtil::NormalizedFile:0xb540042>
irb(main):010:0> files = [jf, sf, nf]
=> [#<Java::JavaIo::File:0x376a2553>, #<Java::JnrPosix::JavaSecuredFile:0x1e441100>, #<Java::OrgJrubyUtil::NormalizedFile:0xb540042>]
irb(main):011:0> files.each { |f| p f.path }
"\\\\nasdf2504\\pc"
"\\\\nasdf2504\\pc"
"//nasdf2504/pc"
=> [#<Java::JavaIo::File:0x376a2553>, #<Java::JnrPosix::JavaSecuredFile:0x1e441100>, #<Java::OrgJrubyUtil::NormalizedFile:0xb540042>]
irb(main):012:0> files.each { |f| p f.absolute_path }
"\\\\nasdf2504\\pc"
"\\\\nasdf2504\\pc"
"//nasdf2504/pc"
=> [#<Java::JavaIo::File:0x376a2553>, #<Java::JnrPosix::JavaSecuredFile:0x1e441100>, #<Java::OrgJrubyUtil::NormalizedFile:0xb540042>]
irb(main):013:0> files.each { |f| p f.canonical_path }
"\\\\nasdf2504\\pc"
"\\\\nasdf2504\\pc"
Java::JavaIo::IOException: The filename, directory name, or volume label syntax is incorrect
        from java.io.WinNTFileSystem.canonicalize0(Native Method)
        from java.io.Win32FileSystem.canonicalize(java/io/Win32FileSystem.java:414)
        from java.io.File.getCanonicalPath(java/io/File.java:618)
        from jnr.posix.JavaSecuredFile.getCanonicalPath(jnr/posix/JavaSecuredFile.java:187)
        from java.lang.reflect.Method.invoke(java/lang/reflect/Method.java:606)
        from RUBY.evaluate((irb):13)
        from org.jruby.RubyArray.each(org/jruby/RubyArray.java:1613)
        from RUBY.evaluate((irb):13)
        from org.jruby.RubyKernel.eval(org/jruby/RubyKernel.java:1079)
        from org.jruby.RubyKernel.loop(org/jruby/RubyKernel.java:1479)
        from org.jruby.RubyKernel.catch(org/jruby/RubyKernel.java:1242)
        from org.jruby.RubyKernel.catch(org/jruby/RubyKernel.java:1242)
        from C_3a_.opt.jruby_minus_1_7.bin.jirb.(root)(C:/opt/jruby-1_7/bin/jirb:13)
        from C_3a_.opt.jruby_minus_1_7.bin.jirb.(root)(C_3a_/opt/jruby_minus_1_7/bin/C:/opt/jruby-1_7/bin/jirb:13)

@enebo enebo modified the milestones: JRuby 1.7.26, JRuby 1.7.25 Apr 13, 2016
@enebo
Copy link
Member

enebo commented Apr 13, 2016

@rsim The bad news is that we have to change the planet to make this work. I tried changing getCWD in RubyDir to canonicalize the path without using NormalizedFile instance and it fixes the immediate problem. However ANYTHING which refers to these paths like FileResource, Dir, File which happen to ask for the directory will wrap in a NormalizedFile and get this weird result or likely dump. I can fix it so NormalizedFile.getCanonicalPath catches and tries to hack around this but I really really feel it will not actually solve most issues. I would also need to make the same hack in RegularFileResource.

A workaround for now I think which works fine is to CD to network share via drive mapping in Windows. As a drive-letter all our code seems to work and I have not seen it strip off letter and move to UNC anywhere yet. I'm sorry we are not going to fix this for 1.7.25 but UNC is exposing a lot of stuff we did not anticipate.

@rsim
Copy link
Author

rsim commented Apr 13, 2016

@enebo Thanks for the update. Currently, we are using a workaround that when JRuby on Rails app is installed on the UNC path we start Java from C: drive and then later Rails changes the working directory to the UNC path. In this case (if initial current working directory was on C:) then later Dir.pwd shows correct UNC path.

@enebo enebo modified the milestones: JRuby 1.7.26, JRuby 1.7.27 Aug 26, 2016
@headius
Copy link
Member

headius commented Mar 15, 2017

Sounds like when the JVM's cwd is a UNC path it causes plenty of problems...more than we can really work around. I almost wonder if we shouldn't warn on startup: "JRuby starting from a UNC path. This may cause paths to resolve incorrectly" or something.

@enebo enebo removed this from the JRuby 1.7.27 milestone Apr 24, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants