Skip to content

Commit

Permalink
file_manager: relax registration requirements
Browse files Browse the repository at this point in the history
Use EAFP techniques to test for directory read permission
during registration.  If access fails continue with registration.
This allows users to potentially fix an issue without restarting.
Inotify failures always require a restart to resolve.

Signed-off-by:  Eric Callahan <[email protected]>
  • Loading branch information
Arksine committed Dec 15, 2023
1 parent 9ad8fed commit 6d8cb76
Showing 1 changed file with 55 additions and 11 deletions.
66 changes: 55 additions & 11 deletions moonraker/components/file_manager/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,15 +268,29 @@ def register_directory(self,
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)
Expand Down Expand Up @@ -834,8 +848,14 @@ def _parse_upload_args(self,
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,
Expand Down Expand Up @@ -1811,17 +1831,41 @@ def add_root_watch(self, root: str, root_path: str) -> None:
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()
Expand Down

0 comments on commit 6d8cb76

Please sign in to comment.