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()
def get_stat(self): """Get the stat() of the direntry. This is implemented in such a way that it won't do both a stat() and a lstat(). """ if (self.flags & FLAG_STAT) == 0: # We don't have the 'd_stat'. If the known_type says the # direntry is not a DT_LNK, then try to get and cache the # 'd_lstat' instead. Then, or if we already have a # 'd_lstat' from before, *and* if the 'd_lstat' is not a # S_ISLNK, we can reuse it unchanged for 'd_stat'. # # Note how, in the common case where the known_type says # it is a DT_REG or DT_DIR, then we call and cache lstat() # and that's it. Also note that in a d_type-less OS or on # a filesystem that always answer DT_UNKNOWN, this method # will instead only call at most stat(), but not cache it # as 'd_lstat'. known_type = self.flags & 255 if (known_type != rposix_scandir.DT_UNKNOWN and known_type != rposix_scandir.DT_LNK): self.get_lstat() # fill the 'd_lstat' cache have_lstat = True else: have_lstat = (self.flags & FLAG_LSTAT) != 0 if have_lstat: # We have the lstat() but not the stat(). They are # the same, unless the 'd_lstat' is a S_IFLNK. must_call_stat = stat.S_ISLNK(self.d_lstat.st_mode) else: must_call_stat = True if must_call_stat: # Must call stat(). Try to use fstatat() if possible dirfd = self.scandir_iterator.dirfd if dirfd != -1 and rposix.HAVE_FSTATAT: st = rposix_stat.fstatat(self.name, dirfd, follow_symlinks=True) else: path = self.space.fsencode_w(self.fget_path( self.space)) st = rposix_stat.stat(path) else: st = self.d_lstat self.d_stat = st self.flags |= FLAG_STAT return self.d_stat
def get_lstat(self): """Get the lstat() of the direntry.""" if (self.flags & FLAG_LSTAT) == 0: # Unlike CPython, try to use fstatat() if possible dirfd = self.scandir_iterator.dirfd if rposix.HAVE_FSTATAT and dirfd != -1: st = rposix_stat.fstatat(self.name, dirfd, follow_symlinks=False) else: path = self.space.fsencode_w(self.fget_path(self.space)) st = rposix_stat.lstat(path) self.d_lstat = st self.flags |= FLAG_LSTAT return self.d_lstat