diff --git a/src/libretro/api/vfs/default.py b/src/libretro/api/vfs/default.py index b6b3347..ac6601d 100644 --- a/src/libretro/api/vfs/default.py +++ b/src/libretro/api/vfs/default.py @@ -14,6 +14,7 @@ class StandardFileHandle(FileHandle): def __init__(self, path: VfsPath, mode: VfsFileAccess, hints: VfsFileAccessHint): super().__init__(path, mode, hints) + self._file: FileIO | None = None if not path: raise ValueError("Expected a non-empty path") @@ -89,6 +90,7 @@ def truncate(self, length: int) -> int: class StandardDirectoryHandle(DirectoryHandle): def __init__(self, path: VfsPath, include_hidden: bool): + super().__init__(path, include_hidden) self._dirent = os.scandir(path) def __del__(self): @@ -120,7 +122,6 @@ def open(self, path: bytes, mode: VfsFileAccess, hints: VfsFileAccessHint) -> Fi handle = StandardFileHandle(path, mode, hints) return handle except OSError as e: - # TODO: Log error return None def remove(self, path: bytes) -> bool: @@ -132,19 +133,22 @@ def rename(self, old_path: bytes, new_path: bytes) -> bool: return True def stat(self, path: bytes) -> tuple[VfsStat, int] | None: - filestat = os.stat(path) - flags = VfsStat(0) + try: + filestat = os.stat(path) + flags = VfsStat(0) - if stat.S_ISREG(filestat.st_mode): - flags |= VfsStat.IS_VALID + if stat.S_ISREG(filestat.st_mode): + flags |= VfsStat.IS_VALID - if stat.S_ISDIR(filestat.st_mode): - flags |= VfsStat.IS_DIRECTORY + if stat.S_ISDIR(filestat.st_mode): + flags |= VfsStat.IS_DIRECTORY - if stat.S_ISCHR(filestat.st_mode): - flags |= VfsStat.IS_CHARACTER_SPECIAL + if stat.S_ISCHR(filestat.st_mode): + flags |= VfsStat.IS_CHARACTER_SPECIAL - return flags, filestat.st_size + return flags, filestat.st_size + except FileNotFoundError: + return VfsStat(0), 0 def mkdir(self, path: bytes) -> VfsMkdirResult: try: diff --git a/src/libretro/api/vfs/defs.py b/src/libretro/api/vfs/defs.py index d1f005b..911e54c 100644 --- a/src/libretro/api/vfs/defs.py +++ b/src/libretro/api/vfs/defs.py @@ -52,7 +52,7 @@ def open_flag(self) -> str: retro_vfs_rename_t = CFUNCTYPE(c_int, c_char_p, c_char_p) retro_vfs_stat_t = CFUNCTYPE(c_int, c_char_p, POINTER(c_int32)) retro_vfs_mkdir_t = CFUNCTYPE(c_int, c_char_p) -retro_vfs_opendir_t = CFUNCTYPE(UNCHECKED(POINTER(retro_vfs_dir_handle)), c_char_p, c_bool) +retro_vfs_opendir_t = CFUNCTYPE(c_void_p, c_char_p, c_bool) retro_vfs_readdir_t = CFUNCTYPE(c_bool, POINTER(retro_vfs_dir_handle)) retro_vfs_dirent_get_name_t = CFUNCTYPE(c_char_p, POINTER(retro_vfs_dir_handle)) retro_vfs_dirent_is_dir_t = CFUNCTYPE(c_bool, POINTER(retro_vfs_dir_handle)) diff --git a/src/libretro/api/vfs/interface.py b/src/libretro/api/vfs/interface.py index f831da4..678b5c7 100644 --- a/src/libretro/api/vfs/interface.py +++ b/src/libretro/api/vfs/interface.py @@ -1,3 +1,4 @@ +import ctypes from abc import abstractmethod from ctypes import * from logging import Logger @@ -52,7 +53,7 @@ class DirEntry(NamedTuple): class DirectoryHandle(Protocol): @abstractmethod def __init__(self, dir: bytes, include_hidden: bool): - self._as_parameter_ = c_void_p(id(self)) + self._as_parameter_ = id(self) self._current_dirent: DirEntry | None = None @abstractmethod @@ -168,7 +169,7 @@ def __get_path(self, stream: POINTER(retro_vfs_file_handle)) -> bytes | None: case _ as result: raise TypeError(f"Expected path to return a bytes, got: {type(result).__name__}") - def __open(self, path: bytes, mode: int, hints: int) -> POINTER(retro_vfs_file_handle) | None: + def __open(self, path: bytes, mode: int, hints: int) -> c_void_p | None: if not path: return None @@ -186,7 +187,7 @@ def __open(self, path: bytes, mode: int, hints: int) -> POINTER(retro_vfs_file_h address = id(file) self.__file_handles[address] = file - return POINTER(retro_vfs_file_handle).from_address(address) + return address def __close(self, stream: POINTER(retro_vfs_file_handle)) -> int: if not stream: @@ -284,9 +285,9 @@ def __read(self, stream: POINTER(retro_vfs_file_handle), buffer: c_void_p, lengt if not buffer: return -1 - assert isinstance(buffer, c_void_p) - assert isinstance(length, int) - assert length >= 0 + #assert isinstance(buffer, c_void_p), f"Expected a c_void_p, got: {type(buffer).__name__}" + assert isinstance(length, int), f"Expected an int, got: {type(length).__name__}" + assert length >= 0, f"Expected length to be non-negative, got: {length}" if length == 0: return 0 @@ -297,7 +298,7 @@ def __read(self, stream: POINTER(retro_vfs_file_handle), buffer: c_void_p, lengt if not handle: return -1 - assert isinstance(handle, FileHandle) + assert isinstance(handle, FileHandle), f"Expected a FileHandle, got: {type(handle).__name__}" memview = memoryview_at(buffer, length) bytes_read = handle.read(memview) @@ -309,14 +310,14 @@ def __read(self, stream: POINTER(retro_vfs_file_handle), buffer: c_void_p, lengt # TODO: Log the exception return -1 - def __write(self, stream: POINTER(retro_vfs_file_handle), buffer: c_void_p, length: int) -> int: + def __write(self, stream: POINTER(retro_vfs_file_handle), buffer: int, length: int) -> int: if not stream: return -1 if not buffer: return -1 - assert isinstance(buffer, c_void_p) + assert isinstance(buffer, int) assert isinstance(length, int) assert length >= 0 @@ -412,7 +413,7 @@ def __stat(self, path: bytes, size: POINTER(c_int32)) -> int: match self.stat(path): case (VfsStat() | int() as flags), int(filesize): - if size: + if size and flags: # size is allowed to be null! size[0] = filesize @@ -442,24 +443,28 @@ def __mkdir(self, path: bytes) -> int: # TODO: Log an error here return VfsMkdirResult.ERROR - def __opendir(self, path: bytes, include_hidden: bool) -> POINTER(retro_vfs_dir_handle) | None: + def __opendir(self, path: bytes, include_hidden: bool) -> c_void_p | None: if not path: return None assert isinstance(path, bytes) assert isinstance(include_hidden, bool) - dir = self.opendir(path, include_hidden) - if not dir: - return None + try: + dir = self.opendir(path, include_hidden) + if not dir: + return None - if not isinstance(dir, DirectoryHandle): - raise TypeError(f"Expected opendir to return a DirectoryHandle, got: {type(dir).__name__}") + if not isinstance(dir, DirectoryHandle): + raise TypeError(f"Expected opendir to return a DirectoryHandle, got: {type(dir).__name__}") + except: + # TODO: Log the exception + return None address = id(dir) self.__dir_handles[address] = dir - return POINTER(retro_vfs_dir_handle).from_address(address) + return address def __readdir(self, dir: POINTER(retro_vfs_dir_handle)) -> bool: if not dir: diff --git a/src/libretro/session.py b/src/libretro/session.py index 6fd9b3c..ab7ffb8 100644 --- a/src/libretro/session.py +++ b/src/libretro/session.py @@ -937,7 +937,6 @@ def default_session( case _: raise TypeError(f"Expected vfs to be a FileSystemInterface or None, not {type(vfs).__name__}") - logger = logging.getLogger('libretro') return Session( core=core, audio=audio or ArrayAudioState(),