| from _recopendirtype import ffi, lib |
| |
| |
| def _posix_error(): |
| raise OSError(ffi.errno, os.strerror(ffi.errno)) |
| |
| _dtype_to_smode = { |
| lib.DT_BLK: 0o060000, |
| lib.DT_CHR: 0o020000, |
| lib.DT_DIR: 0o040000, |
| lib.DT_FIFO: 0o010000, |
| lib.DT_LNK: 0o120000, |
| lib.DT_REG: 0o100000, |
| lib.DT_SOCK: 0o140000, |
| } |
| |
| def opendir(dir): |
| if len(dir) == 0: |
| dir = b'.' |
| dirname = dir |
| if not dirname.endswith(b'/'): |
| dirname += b'/' |
| dirp = lib.opendir(dir) |
| if dirp == ffi.NULL: |
| raise _posix_error() |
| dirent = ffi.new("struct dirent *") |
| result = ffi.new("struct dirent **") |
| try: |
| while True: |
| ffi.errno = 0 |
| err = lib.readdir_r(dirp, dirent, result) |
| if err: # really got an error |
| raise OSError(err, os.strerror(err)) |
| if result[0] == ffi.NULL: |
| return # |
| name = ffi.string(dirent.d_name) |
| if name == b'.' or name == b'..': |
| continue |
| name = dirname + name |
| try: |
| smode = _dtype_to_smode[dirent.d_type] |
| except KeyError: |
| smode = os.lstat(name).st_mode |
| yield name, smode |
| finally: |
| lib.closedir(dirp) |
| |
| if __name__ == '__main__': |
| for name, smode in opendir(b'/tmp'): |
| print(hex(smode), name) |