[banshee] Follow symlinks when scanning (bgo#545768)



commit d346266f47a3f030b05ed7f778d24113d2c76649
Author: Alexander Kojevnikov <alexander kojevnikov com>
Date:   Thu Feb 4 22:24:16 2010 +1100

    Follow symlinks when scanning (bgo#545768)

 .../Banshee.Unix/Banshee.IO.Unix/Directory.cs      |   39 ++++++++++++++++----
 .../Banshee.IO/DirectoryScannerPipelineElement.cs  |   14 ++++++-
 2 files changed, 44 insertions(+), 9 deletions(-)
---
diff --git a/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs b/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
index fcfefc0..8749775 100644
--- a/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
+++ b/src/Backends/Banshee.Unix/Banshee.IO.Unix/Directory.cs
@@ -88,9 +88,12 @@ namespace Banshee.IO.Unix
 
         public IEnumerable<string> GetFiles (string directory)
         {
-            UnixDirectoryInfo unix_dir = new UnixDirectoryInfo (directory);
-            foreach (UnixFileSystemInfo entry in unix_dir.GetFileSystemEntries ()) {
-                if (!entry.IsDirectory && entry.IsRegularFile && !entry.IsSocket && entry.Exists) {
+            var unix_dir = TraverseSymlink(new UnixDirectoryInfo (directory)) as UnixDirectoryInfo;
+            if (unix_dir == null) {
+                yield break;
+            }
+            foreach (var entry in unix_dir.GetFileSystemEntries ()) {
+                if (entry != null && !entry.IsDirectory && entry.IsRegularFile && !entry.IsSocket && entry.Exists) {
                     yield return entry.FullName;
                 }
             }
@@ -98,11 +101,33 @@ namespace Banshee.IO.Unix
 
         public IEnumerable<string> GetDirectories (string directory)
         {
-            UnixDirectoryInfo unix_dir = new UnixDirectoryInfo (directory);
-            foreach (UnixFileSystemInfo entry in unix_dir.GetFileSystemEntries ()) {
-                if (entry.IsDirectory && entry.Exists && !entry.IsSocket) {
-                    yield return entry.FullName;
+            var unix_dir = new UnixDirectoryInfo (directory);
+            foreach (var entry in unix_dir.GetFileSystemEntries ()) {
+                var info = TraverseSymlink (entry);
+                if (info != null && info.IsDirectory && info.Exists && !info.IsSocket) {
+                    yield return info.FullName;
+                }
+            }
+        }
+
+        private readonly HashSet<string> visited_symlinks = new HashSet<string> ();
+        private UnixFileSystemInfo TraverseSymlink (UnixFileSystemInfo info)
+        {
+            lock (visited_symlinks) {
+                visited_symlinks.Clear ();
+                while (info.IsSymbolicLink) {
+                    if (visited_symlinks.Contains (info.FullName)) {
+                        return null;
+                    }
+                    visited_symlinks.Add (info.FullName);
+                    var target = new UnixSymbolicLinkInfo (info.FullName).GetContents ();
+                    if (info.FullName.StartsWith (target.FullName)) {
+                        return null;
+                    }
+                    info = target;
                 }
+
+                return info;
             }
         }
 
diff --git a/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs b/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
index 5c71f4f..9147b46 100644
--- a/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
+++ b/src/Core/Banshee.Core/Banshee.IO/DirectoryScannerPipelineElement.cs
@@ -27,6 +27,7 @@
 //
 
 using System;
+using System.Collections.Generic;
 using System.IO;
 
 using Hyena.Collections;
@@ -39,10 +40,16 @@ namespace Banshee.IO
     {
         protected override string ProcessItem (string item)
         {
-            ScanForFiles (item, false);
+            try {
+                ScanForFiles (item, false);
+            }
+            finally {
+                visited_dirs.Clear ();
+            }
             return null;
         }
 
+        private readonly HashSet<string> visited_dirs = new HashSet<string> ();
         private void ScanForFiles (string source, bool skip_hidden)
         {
             CheckForCanceled ();
@@ -72,13 +79,16 @@ namespace Banshee.IO
                     // Normalise the path (remove the trailing directory separator)
                     source = Path.Combine (Path.GetDirectoryName (source), Path.GetFileName (source));
                     if (!skip_hidden || !Path.GetFileName (source).StartsWith (".")) {
+                        visited_dirs.Add (source);
                         try {
                             foreach (string file in Banshee.IO.Directory.GetFiles (source)) {
                                 ScanForFiles (file, true);
                             }
 
                             foreach (string directory in Banshee.IO.Directory.GetDirectories (source)) {
-                                ScanForFiles (directory, true);
+                                if (!visited_dirs.Contains (directory)) {
+                                    ScanForFiles (directory, true);
+                                }
                             }
                         } catch {
                         }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]