From 5fe15d42a157392ef0302f9b0bacac2f616040d2 Mon Sep 17 00:00:00 2001 From: Ronan Lamy Date: Wed, 6 Apr 2016 20:00:55 +0100 Subject: [PATCH 1/2] Reuse rposix definition of TIMESPEC in rposix_stat --HG-- branch : rposix-for-3 --- rpython/rlib/rposix_stat.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py index 1b66547e50..9392f9bc1f 100644 --- a/rpython/rlib/rposix_stat.py +++ b/rpython/rlib/rposix_stat.py @@ -36,13 +36,12 @@ if _WIN32: # sub-second timestamps. # - TIMESPEC is defined when the "struct stat" contains st_atim field. -if sys.platform.startswith('linux') or sys.platform.startswith('openbsd'): - TIMESPEC = platform.Struct('struct timespec', - [('tv_sec', rffi.TIME_T), - ('tv_nsec', rffi.LONG)]) -else: +try: + from rpython.rlib.rposix import TIMESPEC +except ImportError: TIMESPEC = None + # all possible fields - some of them are not available on all platforms ALL_STAT_FIELDS = [ ("st_mode", lltype.Signed), @@ -300,13 +299,6 @@ compilation_info = ExternalCompilationInfo( includes=INCLUDES ) -if TIMESPEC is not None: - class CConfig_for_timespec: - _compilation_info_ = compilation_info - TIMESPEC = TIMESPEC - TIMESPEC = lltype.Ptr( - platform.configure(CConfig_for_timespec)['TIMESPEC']) - def posix_declaration(try_to_add=None): global STAT_STRUCT, STATVFS_STRUCT @@ -322,7 +314,7 @@ def posix_declaration(try_to_add=None): if _name == originalname: # replace the 'st_atime' field of type rffi.DOUBLE # with a field 'st_atim' of type 'struct timespec' - lst[i] = (timespecname, TIMESPEC.TO) + lst[i] = (timespecname, TIMESPEC) break _expand(LL_STAT_FIELDS, 'st_atime', 'st_atim') -- GitLab From ecdef4fd23645cefb0ade1c2e75cf0ef6527d3a9 Mon Sep 17 00:00:00 2001 From: Ronan Lamy Date: Wed, 6 Apr 2016 20:32:03 +0100 Subject: [PATCH 2/2] Add wrapper for fstatat() --HG-- branch : rposix-for-3 --- rpython/rlib/rposix_stat.py | 18 ++++++++++++++++++ rpython/rlib/test/test_rposix_stat.py | 10 ++++++++++ 2 files changed, 28 insertions(+) diff --git a/rpython/rlib/rposix_stat.py b/rpython/rlib/rposix_stat.py index 9392f9bc1f..8ef2ef21b6 100644 --- a/rpython/rlib/rposix_stat.py +++ b/rpython/rlib/rposix_stat.py @@ -23,6 +23,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib.rarithmetic import intmask from rpython.rlib.rposix import ( replace_os_function, handle_posix_error, _as_bytes0) +from rpython.rlib import rposix _WIN32 = sys.platform.startswith('win') _LINUX = sys.platform.startswith('linux') @@ -504,6 +505,23 @@ def lstat(path): path = traits.as_str0(path) return win32_xstat(traits, path, traverse=False) +if rposix.HAVE_FSTATAT: + from rpython.rlib.rposix import AT_FDCWD, AT_SYMLINK_NOFOLLOW + c_fstatat = rffi.llexternal('fstatat', + [rffi.INT, rffi.CCHARP, STAT_STRUCT, rffi.INT], rffi.INT, + compilation_info=compilation_info, + save_err=rffi.RFFI_SAVE_ERRNO, macro=True) + + def fstatat(pathname, dir_fd=AT_FDCWD, follow_symlinks=True): + if follow_symlinks: + flags = 0 + else: + flags = AT_SYMLINK_NOFOLLOW + with lltype.scoped_alloc(STAT_STRUCT.TO) as stresult: + error = c_fstatat(dir_fd, pathname, stresult, flags) + handle_posix_error('fstatat', error) + return build_stat_result(stresult) + @replace_os_function('fstatvfs') def fstatvfs(fd): with lltype.scoped_alloc(STATVFS_STRUCT.TO) as stresult: diff --git a/rpython/rlib/test/test_rposix_stat.py b/rpython/rlib/test/test_rposix_stat.py index 0a70d7306d..c16ac56693 100644 --- a/rpython/rlib/test/test_rposix_stat.py +++ b/rpython/rlib/test/test_rposix_stat.py @@ -56,3 +56,13 @@ class TestPosixStatFunctions: except OSError, e: py.test.skip("the underlying os.fstatvfs() failed: %s" % e) rposix_stat.fstatvfs(0) + +@py.test.mark.skipif("not hasattr(rposix_stat, 'fstatat')") +def test_fstatat(tmpdir): + tmpdir.join('file').write('text') + dirfd = os.open(str(tmpdir), os.O_RDONLY) + try: + result = rposix_stat.fstatat('file', dir_fd=dirfd, follow_symlinks=False) + finally: + os.close(dirfd) + assert result.st_atime == tmpdir.join('file').atime() -- GitLab