1from _recopendirtype import ffi, lib 2 3 4def _posix_error(): 5 raise OSError(ffi.errno, os.strerror(ffi.errno)) 6 7_dtype_to_smode = { 8 lib.DT_BLK: 0o060000, 9 lib.DT_CHR: 0o020000, 10 lib.DT_DIR: 0o040000, 11 lib.DT_FIFO: 0o010000, 12 lib.DT_LNK: 0o120000, 13 lib.DT_REG: 0o100000, 14 lib.DT_SOCK: 0o140000, 15} 16 17def opendir(dir): 18 if len(dir) == 0: 19 dir = b'.' 20 dirname = dir 21 if not dirname.endswith(b'/'): 22 dirname += b'/' 23 dirp = lib.opendir(dir) 24 if dirp == ffi.NULL: 25 raise _posix_error() 26 dirent = ffi.new("struct dirent *") 27 result = ffi.new("struct dirent **") 28 try: 29 while True: 30 ffi.errno = 0 31 err = lib.readdir_r(dirp, dirent, result) 32 if err: # really got an error 33 raise OSError(err, os.strerror(err)) 34 if result[0] == ffi.NULL: 35 return # 36 name = ffi.string(dirent.d_name) 37 if name == b'.' or name == b'..': 38 continue 39 name = dirname + name 40 try: 41 smode = _dtype_to_smode[dirent.d_type] 42 except KeyError: 43 smode = os.lstat(name).st_mode 44 yield name, smode 45 finally: 46 lib.closedir(dirp) 47 48if __name__ == '__main__': 49 for name, smode in opendir(b'/tmp'): 50 print(hex(smode), name) 51