1#!/usr/bin/python
2# Exit 0 if "." and "./tempfile" have useful d_type information, else 1.
3# Intended to exit 0 only on Linux/GNU systems.
4import os
5import sys
6import tempfile
7
8fail = 1
9fname = None
10
11try:
12  import ctypes.util
13
14  (DT_UNKNOWN, DT_DIR, DT_REG) = (0, 4, 8)
15
16  class dirent(ctypes.Structure):
17    _fields_ = [
18      ("d_ino", ctypes.c_long),
19      ("d_off", ctypes.c_long),
20      ("d_reclen", ctypes.c_ushort),
21      ("d_type", ctypes.c_ubyte),
22      ("d_name", ctypes.c_char*256)]
23
24  # Pass NULL to dlopen, assuming the python
25  # interpreter is linked with the C runtime
26  libc = ctypes.CDLL(None)
27
28  # Setup correct types for all args and returns
29  # even if only passing, to avoid truncation etc.
30  dirp = ctypes.c_void_p
31  direntp = ctypes.POINTER(dirent)
32
33  libc.readdir.argtypes = [dirp]
34  libc.readdir.restype = direntp
35
36  libc.opendir.restype = dirp
37
38  # Ensure a file is present
39  f, fname = tempfile.mkstemp(dir='.')
40  fname = os.path.basename(fname)
41
42  dirp = libc.opendir(".")
43  if dirp:
44    while True:
45      ep = libc.readdir(dirp)
46      if not ep: break
47      d_type = ep.contents.d_type
48      name = ep.contents.d_name
49      if name == "." or name == "..":
50        if d_type != DT_DIR: break
51      # Check files too since on XFS, only dirs have DT_DIR
52      # while everything else has DT_UNKNOWN
53      elif name == fname:
54        if d_type == DT_REG:
55          fail = 0
56        break
57      elif d_type != DT_DIR and d_type != DT_UNKNOWN:
58        fail = 0
59        break
60except:
61  pass
62
63try:
64  if fname:
65    os.unlink(fname);
66except:
67  pass
68
69sys.exit(fail)
70