aboutsummaryrefslogtreecommitdiffstats
path: root/benchmark
diff options
context:
space:
mode:
authorJeremy Evans <code@jeremyevans.net>2019-04-27 20:18:55 -0700
committerJeremy Evans <code@jeremyevans.net>2019-07-01 11:46:30 -0700
commit11c311e36fa6f27a9144b0aefe16bdffea651251 (patch)
tree17c8f43e31c90d357680a00285601d4278091e70 /benchmark
parent81fe82be4e5040b314717e8d6f9ba12de222b6e6 (diff)
downloadruby-11c311e36fa6f27a9144b0aefe16bdffea651251.tar.gz
Use realpath(3) instead of custom realpath implementation if available
This approach is simpler than the previous approach which tries to emulate realpath(3). It also performs much better on both Linux and OpenBSD on the included benchmarks. By using realpath(3), we can better integrate with system security features such as OpenBSD's unveil(2) system call. This does not use realpath(3) on Windows even if it exists, as the approach for checking for absolute paths does not work for drive letters. This can be fixed without too much difficultly, though until Windows defines realpath(3), there is no need to do so. For File.realdirpath, where the last element of the path is not required to exist, fallback to the previous approach, as realpath(3) on most operating systems requires the whole path be valid (per POSIX), and the operating systems where this isn't true either plan to conform to POSIX or may change to conform to POSIX in the future. glibc realpath(3) does not handle /path/to/file.rb/../other_file.rb paths, returning ENOTDIR in that case. Fallback to the previous code if realpath(3) returns ENOTDIR. glibc doesn't like realpath(3) usage for paths like /dev/fd/5, returning ENOENT even though the path may appear to exist in the filesystem. If ENOENT is returned and the path exists, then fall back to the default approach.
Diffstat (limited to 'benchmark')
-rw-r--r--benchmark/realpath.yml30
1 files changed, 30 insertions, 0 deletions
diff --git a/benchmark/realpath.yml b/benchmark/realpath.yml
new file mode 100644
index 0000000000..90a029d5b9
--- /dev/null
+++ b/benchmark/realpath.yml
@@ -0,0 +1,30 @@
+prelude: |
+ f = File
+ pwd = Dir.pwd
+ Dir.mkdir('b') unless f.directory?('b')
+ f.write('b/a', '') unless f.file?('b/a')
+
+ relative = 'b/a'
+ absolute = File.join(pwd, relative)
+ dir = 'b'
+ file = 'a'
+
+ relative_dir = 'b/c'
+ absolute_dir = File.join(pwd, relative_dir)
+ file_dir = 'c'
+benchmark:
+ relative_nil: "f.realpath(relative, nil)"
+ absolute_nil: "f.realpath(absolute, nil)"
+ relative_relative: "f.realpath(file, dir)"
+ absolute_relative: "f.realpath(absolute, dir)"
+ relative_absolute: "f.realpath(relative, pwd)"
+ relative_nil_dir: "f.realdirpath(relative_dir, nil)"
+ absolute_nil_dir: "f.realdirpath(absolute_dir, nil)"
+ relative_relative_dir: "f.realdirpath(file_dir, dir)"
+ absolute_relative_dir: "f.realdirpath(absolute_dir, dir)"
+ relative_absolute_dir: "f.realdirpath(relative_dir, pwd)"
+ relative_nil_notexist: "f.realpath(relative_dir, nil) rescue nil"
+ absolute_nil_notexist: "f.realpath(absolute_dir, nil) rescue nil"
+ relative_relative_notexist: "f.realpath(file_dir, dir) rescue nil"
+ absolute_relative_notexist: "f.realpath(absolute_dir, dir) rescue nil"
+ relative_absolute_notexist: "f.realpath(relative_dir, pwd) rescue nil"