Jin asked me to add this to the tracker.
How can this be reproduced? In my log I only get the following:
2009-02-16 22:28:06 ERROR: Failed to stat /home/till/mediatomb/testmedia/linka.mp3, Too many levels of symbolic links
2009-02-16 22:28:06 ERROR: Failed to stat /home/till/mediatomb/testmedia/linkb.mp3, Too many levels of symbolic links
...which indicates that MT can deal with it at least to a certain degree.
Ok, if a directory links to its parent, all files in this hierarchy will be re-added until the maximum directory depth is reached.
Here is a patch for this issue. It will detect recursive symlinks by using realpath() and recording a log of the traversed directories. If any directory in the recursion will match a previously scanned directory, further traversal is aborted.
The patch implies a bit of a performance drop during scanning due to the use of realpath(). Eventually an option should be added whether to follow symlinks at all. The code only needs to be executed when symlinks are being followed. This could speed up scanning for users that do not need this feature.
--- mediatomb/src/content_manager.h (revision 2018)
+++ mediatomb/src/content_manager.h (working copy)
@@ -450,7 +450,7 @@
void _rescanDirectory(int containerID, int scanID, scan_mode_t scanMode, scan_level_t scanLevel, zmm::Ref<CMTask> task=nil);
/* for recursive addition */
- void addRecursive(zmm::String path, bool hidden, zmm::Ref<CMTask> task);
+ void addRecursive(zmm::String path, bool hidden, zmm::Ref<CMTask> task, zmm::Array<zmm::StringBase> &dirList);
//void addRecursive2(zmm::Ref<DirCache> dirCache, zmm::String filename, bool recursive);
zmm::String extension2mimetype(zmm::String extension);
--- mediatomb/src/content_manager.cc (revision 2018)
+++ mediatomb/src/content_manager.cc (working copy)
@@ -685,7 +685,9 @@
if (recursive && IS_CDS_CONTAINER(obj->getObjectType()))
- addRecursive(path, hidden, task);
+ Array<StringBase> dirList;
+ dirList.append ( path );
+ addRecursive(path, hidden, task, dirList );
@@ -970,7 +972,7 @@
/* scans the given directory and adds everything recursively */
-void ContentManager::addRecursive(String path, bool hidden, Ref<CMTask> task)
+void ContentManager::addRecursive(String path, bool hidden, Ref<CMTask> task, Array<StringBase> &dirList)
if (hidden == false)
@@ -1079,7 +1081,42 @@
- addRecursive(newPath, hidden, task);
+ * Make sure that we do not encounter a recursive symlink
+ * by resolving the current path and resolving against
+ * previous paths
+ // resolve current path first
+ char buf[PATH_MAX];
+ char *ptr = realpath(newPath.c_str(), buf);
+ if (!ptr)
+ // buffer was too small, access problem, loop or other error
+ throw _Exception(_("realpath() failed, check your permissions"));
+ // see if current path was already traversed
+ bool recursionDetected = false;
+ for ( int i = 0; i < dirList.size (); i++ )
+ if ( String(dirList.get(i)) == String(buf) )
+ recursionDetected = true;
+ if ( !recursionDetected )
+ dirList.append ( newPath );
+ addRecursive(newPath, hidden, task, dirList);
+ throw _Exception(_( "recursive symlink detected, skipping directory" ));
The tracker seems to break formatting and I cannot attach files either. Contact me via mail to get a proper diff.
Sorry, I should have reported this personally. Mediatomb's HEAD kept following a recursive symlink, it didn't crash but it did do this for greater than 20 minutes, it either locked up in the process or it kept going, whichever I'm not sure. By the time I saw it, it was 20 directories deep, at least.
Log in to post a comment.