def translate_error(event_bus, operation, path): try: yield except NTStatusError: raise except FSLocalOperationError as exc: raise NTStatusError(exc.ntstatus) from exc except FSRemoteOperationError as exc: event_bus.send("mountpoint.remote_error", exc=exc, operation=operation, path=path) raise NTStatusError(exc.ntstatus) from exc except (Cancelled, RunFinishedError) as exc: # WinFSP teardown operation doesn't make sure no concurrent operation # are running raise NTStatusError(NTSTATUS.STATUS_NO_SUCH_DEVICE) from exc except Exception as exc: logger.exception("Unhandled exception in winfsp mountpoint", operation=operation, path=path) event_bus.send("mountpoint.unhandled_error", exc=exc, operation=operation, path=path) raise NTStatusError(NTSTATUS.STATUS_INTERNAL_ERROR) from exc
def can_delete(self, file_context, file_name: str) -> None: self.fs_access.check_write_rights(file_context.path) stat = self.fs_access.entry_info(file_context.path) if stat["type"] == "file": return if file_context.is_root(): # Cannot remove root mountpoint ! raise NTStatusError(NTSTATUS.STATUS_RESOURCEMANAGER_READ_ONLY) if stat["children"]: raise NTStatusError(NTSTATUS.STATUS_DIRECTORY_NOT_EMPTY)
def read_directory(self, file_context, marker): entries = [] stat = self.fs_access.entry_info(file_context.path) if stat["type"] == "file": raise NTStatusError(NTSTATUS.STATUS_NOT_A_DIRECTORY) # NOTE: The "." and ".." directories should ONLY be included # if the queried directory is not root # Current directory if marker is None and not file_context.path.is_root(): entry = {"file_name": ".", **stat_to_winfsp_attributes(stat)} entries.append(entry) elif marker == ".": marker = None # Parent directory if marker is None and not file_context.path.is_root(): parent_stat = self.fs_access.entry_info(file_context.path.parent) entry = { "file_name": "..", **stat_to_winfsp_attributes(parent_stat) } entries.append(entry) elif marker == "..": marker = None # NOTE: we *do not* rely on alphabetically sorting to compare the # marker given `..` is always the first element event if we could # have children name before it (`.-foo` for instance) iter_children_names = iter(stat["children"]) if marker is not None: for child_name in iter_children_names: if child_name == marker: break # All remaining children are located after the marker for child_name in iter_children_names: name = winify_entry_name(child_name) child_stat = self.fs_access.entry_info(file_context.path / child_name) entry = { "file_name": name, **stat_to_winfsp_attributes(child_stat) } entries.append(entry) return entries
def get_path_and_translate_error( fs_access: ThreadFSAccess, operation: str, file_context: Union[OpenedFile, OpenedFolder, str], mountpoint: PurePath, workspace_id: EntryID, timestamp: Optional[DateTime], ) -> Iterator[FsPath]: path: FsPath = FsPath("/<unkonwn>") try: if isinstance(file_context, (OpenedFile, OpenedFolder)): path = file_context.path else: # FsPath conversion might raise an FSNameTooLongError so make # sure it runs within the try-except so it can be caught by the # FSLocalOperationError filter. path = _winpath_to_parsec(file_context) yield path except NTStatusError: raise except FSLocalOperationError as exc: raise NTStatusError(exc.ntstatus) from exc except FSRemoteOperationError as exc: fs_access.send_event( CoreEvent.MOUNTPOINT_REMOTE_ERROR, exc=exc, operation=operation, path=path, mountpoint=mountpoint, workspace_id=workspace_id, timestamp=timestamp, ) raise NTStatusError(exc.ntstatus) from exc except (Cancelled, RunFinishedError) as exc: # WinFSP teardown operation doesn't make sure no concurrent operation # are running raise NTStatusError(NTSTATUS.STATUS_NO_SUCH_DEVICE) from exc except TrioDealockTimeoutError as exc: # See the similar clause in `fuse_operations` for a detailed explanation logger.error( "The trio thread is unreachable, a deadlock might have occured", operation=operation, path=str(path), mountpoint=str(mountpoint), workspace_id=workspace_id, timestamp=timestamp, ) fs_access.send_event( CoreEvent.MOUNTPOINT_TRIO_DEADLOCK_ERROR, exc=exc, operation=operation, path=path, mountpoint=mountpoint, workspace_id=workspace_id, timestamp=timestamp, ) raise NTStatusError(NTSTATUS.STATUS_INTERNAL_ERROR) from exc except Exception as exc: logger.exception( "Unhandled exception in winfsp mountpoint", operation=operation, path=str(path), mountpoint=str(mountpoint), workspace_id=workspace_id, timestamp=timestamp, ) fs_access.send_event( CoreEvent.MOUNTPOINT_UNHANDLED_ERROR, exc=exc, operation=operation, path=path, mountpoint=mountpoint, workspace_id=workspace_id, timestamp=timestamp, ) raise NTStatusError(NTSTATUS.STATUS_INTERNAL_ERROR) from exc