From 615afca4ab9fe6c60cd3e94bb04b404750f03c03 Mon Sep 17 00:00:00 2001
From: Simon Arlott <sa.me.uk>
Date: Sun, 21 Jun 2020 09:57:54 +0100
Subject: [PATCH] Handle access errors scanning directories

Trying to read a directory that is visible but not accessible, or a
symlink to a file in a directory that is not accessible will raise a
PermissionError. Output these and then continue.

If os.scandir() raises an exception then the finally block accesses
"scanner" before it is assigned, raising an UnboundLocalError.
---
 .../music/management/commands/import_files.py | 30 ++++++++++++++-----
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/api/funkwhale_api/music/management/commands/import_files.py b/api/funkwhale_api/music/management/commands/import_files.py
index e03c9a720..16c6716b5 100644
--- a/api/funkwhale_api/music/management/commands/import_files.py
+++ b/api/funkwhale_api/music/management/commands/import_files.py
@@ -3,6 +3,7 @@ import datetime
 import itertools
 import os
 import queue
+import sys
 import threading
 import time
 import urllib.parse
@@ -29,16 +30,29 @@ def crawl_dir(dir, extensions, recursive=True, ignored=[]):
         return
     try:
         scanner = os.scandir(dir)
+    except Exception as e:
+        m = "Error while reading {}: {} {}\n".format(
+            dir, e.__class__.__name__, e
+        )
+        sys.stderr.write(m)
+        return
+    try:
         for entry in scanner:
-            if entry.is_file():
-                for e in extensions:
-                    if entry.name.lower().endswith(".{}".format(e.lower())):
-                        if entry.path not in ignored:
-                            yield entry.path
-            elif recursive and entry.is_dir():
-                yield from crawl_dir(
-                    entry.path, extensions, recursive=recursive, ignored=ignored
+            try:
+                if entry.is_file():
+                    for e in extensions:
+                        if entry.name.lower().endswith(".{}".format(e.lower())):
+                            if entry.path not in ignored:
+                                yield entry.path
+                elif recursive and entry.is_dir():
+                    yield from crawl_dir(
+                        entry.path, extensions, recursive=recursive, ignored=ignored
+                    )
+            except Exception as e:
+                m = "Error while reading {}: {} {}\n".format(
+                    entry.name, e.__class__.__name__, e
                 )
+                sys.stderr.write(m)
     finally:
         if hasattr(scanner, "close"):
             scanner.close()
-- 
GitLab