diff --git a/moonraker/components/file_manager/file_manager.py b/moonraker/components/file_manager/file_manager.py index 731547d..e93dec7 100644 --- a/moonraker/components/file_manager/file_manager.py +++ b/moonraker/components/file_manager/file_manager.py @@ -268,15 +268,29 @@ class FileManager: f"Supplied path ({path}) for ({root}) is invalid. Make sure\n" "that the path exists and is not the file system root.") return False - permissions = os.R_OK + # Check Folder Permissions + missing_perms = [] + try: + # Test read + os.listdir(path) + except PermissionError: + missing_perms.append("READ") + except Exception: + logging.exception(f"Error testing read access for root {root}") if full_access: - permissions |= os.W_OK + if ( + os.access in os.supports_effective_ids and + not os.access(path, os.W_OK, effective_ids=True) + ): + missing_perms.append("WRITE") self.full_access_roots.add(root) - if not os.access(path, permissions): - self.server.add_warning( - f"Moonraker does not have permission to access path " - f"({path}) for ({root}).") - return False + if missing_perms: + mpstr = " | ".join(missing_perms) + self.server.add_log_rollover_item( + f"fm_reg_perms_{root}", + f"file_manager: Moonraker has detected the following missing " + f"permissions for root folder '{root}': {mpstr}" + ) if path != self.file_paths.get(root, ""): self.file_paths[root] = path self.server.register_static_file_handler(root, path) @@ -834,8 +848,14 @@ class FileManager: if unzip_ufp: filename = os.path.splitext(filename)[0] + ".gcode" dest_path = os.path.splitext(dest_path)[0] + ".gcode" - if os.path.isfile(dest_path) and not os.access(dest_path, os.W_OK): - raise self.server.error(f"File is read-only: {dest_path}") + if ( + os.path.isfile(dest_path) and + os.access in os.supports_effective_ids and + not os.access(dest_path, os.W_OK, effective_ids=True) + ): + logging.info( + f"Destination file exists and appears to be read-only: {dest_path}" + ) return { 'root': root, 'filename': filename, @@ -1811,17 +1831,41 @@ class InotifyObserver(BaseFileSystemObserver): try: root_node = InotifyRootNode(self, root, root_path) except Exception: + logging.exception(f"Inotify: failed to create root node '{root}'") + self.server.add_warning( + f"file_manager: Failed to create inotify root node {root}. " + "See moonraker.log for details.", + log=False + ) return self.watched_roots[root] = root_node if self.initialized: - mevts = root_node.scan_node() + try: + mevts = root_node.scan_node() + except Exception: + logging.exception(f"Inotify: failed to scan root '{root}'") + self.server.add_warning( + f"file_manager: Failed to scan inotify root node '{root}'. " + "See moonraker.log for details.", + log=False + ) + return self.log_nodes() self.event_loop.register_callback( self._notify_root_updated, mevts, root, root_path) def initialize(self) -> None: for root, node in self.watched_roots.items(): - evts = node.scan_node() + try: + evts = node.scan_node() + except Exception: + logging.exception(f"Inotify: failed to scan root '{root}'") + self.server.add_warning( + f"file_manager: Failed to scan inotify root node '{root}'. " + "See moonraker.log for details.", + log=False + ) + continue if not evts: continue root_path = node.get_path()