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

Cannot resolve or detect symlinks on Windows #3287

Closed
nlowe opened this issue Aug 26, 2015 · 7 comments
Closed

Cannot resolve or detect symlinks on Windows #3287

nlowe opened this issue Aug 26, 2015 · 7 comments

Comments

@nlowe
Copy link

nlowe commented Aug 26, 2015

jruby 1.7.21 (1.9.3p551) 2015-07-07 a741a82 on Java HotSpot(TM) 64-Bit Server VM 1.8.0_51-b16 +jit [Windows 8.1-amd64]

While doing some testing for running gollum under windows I discovered that JRuby under windows appears to lack support for resolving symlinks. From gollum/gollum#1044:


It doesn't seem that Pathname can detect windows symlinks. For this test, I have created the following:

  • C:\SymlinkTest\a.txt
  • C:\SymlinkTest\b.txt => softlink to C:\SymlinkTest\a.txt (mklink C:\SymlinkTest\b.txt C:\SymlinkTest\a.txt)
  • C:\SymlinkTest\c.txt => hardlink to C:\SymlinkTest\a.txt (fsutil hardlink create C:\SymlinkTest\b.txt C:\SymlinkTest\a.txt)
irb(main):001:0> b = Pathname.new('C:\\SymlinkTest\\b.txt')
=> <Pathname:C:\SymlinkTest\b.txt>
irb(main):002:0> p.symlink?
=> false
irb(main):003:0> c = Pathname.new('C:\\SymlinkTest\\c.txt')
=> <Pathname:C:\SymlinkTest\c.txt>
irb(main):004:0> p.symlink?
=> false
irb(main):005:0> b.realpath
=> <Pathname:C:\SymlinkTest\b.txt>
irb(main):006:0> c.realpath
=> <Pathname:C:\SymlinkTest\c.txt>
irb(main):007:0> File.readlink('C:\\SymlinkTests\\b.txt')
NotImplementedError: readlink unsupported or native support failed to load
        from org/jruby/RubyFile.java:1049:in `readlink'
        from (irb):1:in `evaluate'
        from org/jruby/RubyKernel.java:1079:in `eval'
        from org/jruby/RubyKernel.java:1479:in `loop'
        from org/jruby/RubyKernel.java:1242:in `catch'
        from org/jruby/RubyKernel.java:1242:in `catch'
        from C:/jruby-1.7.21/bin/jirb:13:in `(root)'
irb(main):008:0> File.readlink('C:\\SymlinkTests\\c.txt')
NotImplementedError: readlink unsupported or native support failed to load
        from org/jruby/RubyFile.java:1049:in `readlink'
        from (irb):2:in `evaluate'
        from org/jruby/RubyKernel.java:1079:in `eval'
        from org/jruby/RubyKernel.java:1479:in `loop'
        from org/jruby/RubyKernel.java:1242:in `catch'
        from org/jruby/RubyKernel.java:1242:in `catch'
        from C:/jruby-1.7.21/bin/jirb:13:in `(root)'
@nlowe nlowe changed the title Cannot resolve symlinks on Windows Cannot resolve or detect symlinks on Windows Aug 26, 2015
@enebo
Copy link
Member

enebo commented Aug 27, 2015

Article on links for windows as a note when we try and figure this out: http://www.sevenforums.com/tutorials/278262-mklink-create-use-links-windows.html. This will get fixed upstream in jnr/jnr-posix to get fixed in jruby proper.

@headius
Copy link
Member

headius commented Sep 3, 2015

Does this work in MRI? I thought I might find that they had shimmed out a win32 version of readlink, but it appears they simply raise NotImplementedError when readlink is not present on the given system. We could do that too; perhaps gollum checks if it's supported before trying to use it?

@headius
Copy link
Member

headius commented Sep 3, 2015

I went ahead and "fixed" this the same way MRI does, by marking File.readlink as not implemented on Windows. I do feel like we could both provide readlink using Win32 API calls, but our behavior now aligns with MRI.

@techwiz24 Tonight's nightly builds of 1.7.23 and 9.0.2.0 will have this fix...perhaps you can check whether it's working? I suspect gollum checks for readlink or perhaps it should. If you believe we should actually support readlink, we'll need to have that conversation with ruby-core too.

@nlowe
Copy link
Author

nlowe commented Sep 3, 2015

@headius Thank you for looking into this. For the specific test that was failing, this is what gollum looks for:

# Return the file path to this file on disk, if available.
#
# Returns nil if the file isn't available on disk. This can occur if the
# repo is bare, if the commit isn't the HEAD, or if there are problems
# resolving symbolic links.
def get_disk_reference(name, commit)
  return false if @wiki.repo.bare
  return false if commit.sha != @wiki.repo.head.commit.sha

  # This will try to resolve symbolic links, as well
  pathname = Pathname.new(::File.expand_path(::File.join(@wiki.repo.path, '..', name)))
  if pathname.symlink?
    source   = ::File.readlink(pathname.to_path)
    realpath = ::File.join(::File.dirname(pathname.to_path), source)
    return false unless realpath && ::File.exist?(realpath)
    @on_disk_path = realpath.to_s
  else
    @on_disk_path = pathname.to_path
  end
  true
end

I believe what you're saying is that we'll have to wrap pathname.symlink? to catch a NotImplemented under windows, correct?

@bartkamphorst
Copy link

I do feel like we could both provide readlink using Win32 API calls, but our behavior now aligns with MRI.

Thank you @headius , appreciate your time and effort! Another way to go might be to rely on java.nio.file, which, as @techwiz24 confirmed, can be used to read symlinks on Windows. Unsure if that would be a viable option though. And yes, there is of course the alignment with MRI issue.

@Wadeck
Copy link

Wadeck commented Apr 20, 2018

Necroposting apart, it could good for reader coming from Google search.

rely on java.nio.file

I imagine you meant: File#toPath().toRealPath()
Just a short notice on that workaround, it works iff you check a file/folder that exist. If you have a symlink inside the hierarchy of a file that is not yet written, the method will throw an exception.

Concerning the support in "native" getCanonicalPath, it was requested in OpenJDK in 2012 and still not done.

@bartkamphorst
Copy link

Thanks @Wadeck for sharing this info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants