aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-20 06:54:23 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2019-02-20 06:54:23 +0000
commit15a98ab42838be248a5b59ca342033ee338357ad (patch)
tree54d37b82280acbc3dc0dc10017b7470a77135c23
parentd034fcb13f04b096f99d1824d5e7dd8ed256713e (diff)
downloadruby-15a98ab42838be248a5b59ca342033ee338357ad.tar.gz
Try statx syscall
* file.c (rb_file_s_birthtime): export for pathname to check if birthtime is supported. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@67097 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--configure.ac15
-rw-r--r--ext/pathname/extconf.rb2
-rw-r--r--ext/pathname/pathname.c3
-rw-r--r--file.c30
-rw-r--r--test/pathname/test_pathname.rb13
5 files changed, 51 insertions, 12 deletions
diff --git a/configure.ac b/configure.ac
index 895afee804..f4a03778fe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1897,7 +1897,18 @@ AC_CHECK_FUNCS(sigaltstack)
AC_CHECK_FUNCS(sigprocmask)
AC_CHECK_FUNCS(sinh)
AC_CHECK_FUNCS(spawnv)
-AC_CHECK_FUNCS(statx)
+AC_CHECK_FUNCS(statx, [],
+ [AS_CASE(["$target_os"], [linux*],
+ [AC_CHECK_DECLS([__NR_statx], [ac_cv_func_statx=syscall], [],
+ [
+ @%:@ ifdef HAVE_SYSCALL_H
+ @%:@ include <syscall.h>
+ @%:@ elif defined HAVE_SYS_SYSCALL_H
+ @%:@ include <sys/syscall.h>
+ @%:@ endif
+ ])
+ ])
+])
AC_CHECK_FUNCS(symlink)
AC_CHECK_FUNCS(syscall)
AC_CHECK_FUNCS(sysconf)
@@ -1913,6 +1924,8 @@ AC_CHECK_FUNCS(utimes)
AC_CHECK_FUNCS(wait4)
AC_CHECK_FUNCS(waitpid)
+AS_IF([test "$ac_cv_func_statx" = syscall], [AC_DEFINE(HAVE_STATX, 0)])
+
AS_CASE(["$ac_cv_func_memset_s:$ac_cv_func_qsort_s"], [*yes*],
[RUBY_DEFINE_IF([!defined __STDC_WANT_LIB_EXT1__], [__STDC_WANT_LIB_EXT1__], 1)])
diff --git a/ext/pathname/extconf.rb b/ext/pathname/extconf.rb
index c9133bc153..84e68277aa 100644
--- a/ext/pathname/extconf.rb
+++ b/ext/pathname/extconf.rb
@@ -1,4 +1,4 @@
# frozen_string_literal: false
require 'mkmf'
-have_struct_member("struct stat", "st_birthtimespec", "sys/stat.h")
+have_func("rb_file_s_birthtime")
create_makefile('pathname')
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index d5e58c52d8..9cf6c32039 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -512,7 +512,7 @@ path_atime(VALUE self)
return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
}
-#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) || defined(_WIN32)
+#if defined(HAVE_RB_FILE_S_BIRTHTIME)
/*
* call-seq:
* pathname.birthtime -> time
@@ -528,6 +528,7 @@ path_birthtime(VALUE self)
return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
}
#else
+/* check at compilation time for `respond_to?` */
# define path_birthtime rb_f_notimplement
#endif
diff --git a/file.c b/file.c
index c00c43e5d4..513bde5c65 100644
--- a/file.c
+++ b/file.c
@@ -1113,6 +1113,24 @@ stat_without_gvl(const char *path, struct stat *st)
}
#ifdef HAVE_STATX
+
+# if HAVE_STATX == 0
+# ifdef HAVE_SYSCALL_H
+# include <syscall.h>
+# elif defined HAVE_SYS_SYSCALL_H
+# include <sys/syscall.h>
+# endif
+# if defined __linux__
+# include <linux/stat.h>
+static inline int
+statx(int dirfd, const char *pathname, int flags,
+ unsigned int mask, struct statx *statxbuf)
+{
+ return syscall(__NR_statx, dirfd, pathname, flags, mask, statxbuf);
+}
+# endif
+# endif
+
typedef struct no_gvl_statx_data {
struct statx *stx;
int fd;
@@ -2360,9 +2378,10 @@ rb_file_ctime(VALUE obj)
*
*/
-#if defined(HAVE_STAT_BIRTHTIME)
-static VALUE
+#if defined(HAVE_STAT_BIRTHTIME) || defined(HAVE_STATX)
+RUBY_FUNC_EXPORTED VALUE
rb_file_s_birthtime(VALUE klass, VALUE fname)
+# if defined(HAVE_STAT_BIRTHTIME)
{
struct stat st;
@@ -2373,9 +2392,7 @@ rb_file_s_birthtime(VALUE klass, VALUE fname)
}
return stat_birthtime(&st);
}
-#elif defined(HAVE_STATX)
-static VALUE
-rb_file_s_birthtime(VALUE klass, VALUE fname)
+# elif defined(HAVE_STATX)
{
struct statx stx;
@@ -2390,6 +2407,9 @@ rb_file_s_birthtime(VALUE klass, VALUE fname)
}
return statx_birthtime(&stx);
}
+# else
+# error Not implemented
+# endif
#else
# define rb_file_s_birthtime rb_f_notimplement
#endif
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index f8e4937802..78f0af71df 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -789,10 +789,15 @@ class TestPathname < Test::Unit::TestCase
end
def test_birthtime
- assert_kind_of(Time, Pathname(__FILE__).birthtime)
- rescue NotImplementedError
- assert_raise(NotImplementedError) do
- File.birthtime(__FILE__)
+ # Check under a (probably) local filesystem.
+ # Remote filesystems often may not support birthtime.
+ with_tmpchdir('rubytest-pathname') do |dir|
+ open("a", "w") {}
+ assert_kind_of(Time, Pathname("a").birthtime)
+ rescue NotImplementedError
+ assert_raise(NotImplementedError) do
+ File.birthtime("a")
+ end
end
end