Skip to content

Commit 1bcf171

Browse files
gerhardgruberheadius
authored andcommittedNov 12, 2017
[#3953] Use java.nio for FileTest#symlink?
1 parent 2693dd8 commit 1bcf171

File tree

2 files changed

+13
-39
lines changed

2 files changed

+13
-39
lines changed
 

Diff for: ‎core/src/main/java/org/jruby/RubyFileTest.java

+13-7
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@
3636
import java.io.File;
3737
import java.io.IOException;
3838
import java.io.InputStream;
39+
import java.nio.file.Files;
40+
import java.nio.file.LinkOption;
41+
import java.nio.file.Path;
42+
import java.nio.file.attribute.BasicFileAttributes;
3943

4044
import jnr.posix.FileStat;
4145
import org.jruby.anno.JRubyMethod;
@@ -278,21 +282,23 @@ public static IRubyObject sticky_p(IRubyObject recv, IRubyObject filename) {
278282
@JRubyMethod(name = "symlink?", required = 1, module = true)
279283
public static RubyBoolean symlink_p(IRubyObject recv, IRubyObject filename) {
280284
Ruby runtime = recv.getRuntime();
281-
IRubyObject oldExc = runtime.getGlobalVariables().get("$!"); // Save $!
282-
285+
286+
Path p = new File(filename.toString()).toPath();
287+
283288
try {
284289
// Note: We can't use file.exists() to check whether the symlink
285290
// exists or not, because that method returns false for existing
286291
// but broken symlink. So, we try without the existence check,
287292
// but in the try-catch block.
288293
// MRI behavior: symlink? on broken symlink should return true.
289-
FileStat stat = fileResource(filename).lstat();
294+
BasicFileAttributes attrs = Files.readAttributes(p, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS);
290295

291-
return runtime.newBoolean(stat != null && stat.isSymlink());
292-
} catch (SecurityException re) {
296+
return runtime.newBoolean(attrs != null && attrs.isSymbolicLink());
297+
} catch (SecurityException se) {
298+
return runtime.getFalse();
299+
} catch (IOException ie) {
293300
return runtime.getFalse();
294-
} catch (RaiseException re) {
295-
runtime.getGlobalVariables().set("$!", oldExc); // Restore $!
301+
} catch (UnsupportedOperationException uoe) {
296302
return runtime.getFalse();
297303
}
298304
}

Diff for: ‎core/src/main/ruby/jruby/kernel/file.rb

-32
Original file line numberDiff line numberDiff line change
@@ -122,38 +122,6 @@ def self.symlink(target, link)
122122
0 # Comply with spec
123123
end
124124

125-
# Returns whether or not +file+ is a symlink.
126-
#
127-
def self.symlink?(file)
128-
file = string_check(file)
129-
130-
return false if file =~ /^(classpath:|classloader:|uri:classloader|jar:)/ || !File.exist?(file)
131-
132-
file.slice!(5..-1) if file =~ /^file:/
133-
wfile = file.wincode
134-
attrib = GetFileAttributesW(wfile)
135-
136-
if attrib == INVALID_FILE_ATTRIBUTES
137-
raise SystemCallError.new('GetFileAttributes', FFI.errno)
138-
end
139-
140-
if attrib & FILE_ATTRIBUTE_REPARSE_POINT > 0
141-
begin
142-
find_data = WIN32_FIND_DATA.new
143-
handle = FindFirstFileW(wfile, find_data)
144-
145-
if handle == INVALID_HANDLE_VALUE
146-
raise SystemCallError.new('FindFirstFile', FFI.errno)
147-
end
148-
149-
return true if find_data[:dwReserved0] == IO_REPARSE_TAG_SYMLINK
150-
ensure
151-
CloseHandle(handle)
152-
end
153-
end
154-
false
155-
end
156-
157125
private
158126

159127
# Simulate Ruby's string checking

0 commit comments

Comments
 (0)
Please sign in to comment.