File: readdir_ctypes.py

package info (click to toggle)
python-cffi 1.12.2-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,540 kB
  • sloc: python: 26,777; ansic: 13,858; asm: 116; makefile: 103; sh: 28
file content (69 lines) | stat: -rw-r--r-- 1,789 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# A Linux-only demo
#
# For comparison purposes, this is a ctypes version of readdir.py.
import sys
import ctypes

if not sys.platform.startswith('linux'):
    raise Exception("Linux-only demo")


DIR_p = ctypes.c_void_p
ino_t = ctypes.c_long
off_t = ctypes.c_long

class DIRENT(ctypes.Structure):
    _fields_ = [
        ('d_ino', ino_t),                 # inode number
        ('d_off', off_t),                 # offset to the next dirent
        ('d_reclen', ctypes.c_ushort),    # length of this record
        ('d_type', ctypes.c_ubyte),       # type of file; not supported
                                          #   by all file system types
        ('d_name', ctypes.c_char * 256),  # filename
        ]
DIRENT_p = ctypes.POINTER(DIRENT)
DIRENT_pp = ctypes.POINTER(DIRENT_p)

C = ctypes.CDLL(None)

readdir_r = C.readdir_r
readdir_r.argtypes = [DIR_p, DIRENT_p, DIRENT_pp]
readdir_r.restype = ctypes.c_int

openat = C.openat
openat.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int]
openat.restype = ctypes.c_int

fdopendir = C.fdopendir
fdopendir.argtypes = [ctypes.c_int]
fdopendir.restype = DIR_p

closedir = C.closedir
closedir.argtypes = [DIR_p]
closedir.restype = ctypes.c_int


def walk(basefd, path):
    print '{', path
    dirfd = openat(basefd, path, 0)
    if dirfd < 0:
        # error in openat()
        return
    dir = fdopendir(dirfd)
    dirent = DIRENT()
    result = DIRENT_p()
    while True:
        if readdir_r(dir, dirent, result):
            # error in readdir_r()
            break
        if not result:
            break
        name = dirent.d_name
        print '%3d %s' % (dirent.d_type, name)
        if dirent.d_type == 4 and name != '.' and name != '..':
            walk(dirfd, name)
    closedir(dir)
    print '}'


walk(-1, "/tmp")