2424
2525#include " util/cxx17retrocompat.h"
2626#include " util/folderiterator.h"
27+ #include < algorithm>
2728#include " util/rstime.h"
2829#include " rsserver/p3face.h"
2930#include " directory_storage.h"
@@ -219,10 +220,13 @@ bool LocalDirectoryUpdater::sweepSharedDirectories(bool& some_files_not_ready)
219220 {
220221 RS_DBG4 (" recursing into \" " , stored_dir_it.name ());
221222
222- existing_dirs.insert (RsDirUtil::removeSymLinks (stored_dir_it.name ()));
223+ std::string canonical = RsDirUtil::removeSymLinks (stored_dir_it.name ());
224+ existing_dirs.insert (canonical);
225+ std::vector<std::string> current_branch_real_paths;
226+ current_branch_real_paths.push_back (canonical);
223227 recursUpdateSharedDir (
224228 stored_dir_it.name (), *stored_dir_it,
225- existing_dirs, 1 , some_files_not_ready );
229+ existing_dirs, current_branch_real_paths, 1 , some_files_not_ready );
226230 /* here we need to use the list that was stored, instead of the shared
227231 * dir list, because the two are not necessarily in the same order. */
228232 }
@@ -240,7 +244,7 @@ bool LocalDirectoryUpdater::sweepSharedDirectories(bool& some_files_not_ready)
240244
241245void LocalDirectoryUpdater::recursUpdateSharedDir (
242246 const std::string& cumulated_path, DirectoryStorage::EntryIndex indx,
243- std::set<std::string>& existing_directories, uint32_t current_depth,
247+ std::set<std::string>& existing_directories, std::vector<std::string>& current_branch_real_paths, uint32_t current_depth,
244248 bool & some_files_not_ready )
245249{
246250 RS_DBG4 (" parsing directory \" " , cumulated_path, " \" index: " , indx);
@@ -300,21 +304,31 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(
300304 || (mMaxShareDepth == 0 && current_depth >= 64 ) )
301305 dir_is_accepted = false ;
302306
303- if (dir_is_accepted && mFollowSymLinks && mIgnoreDuplicates )
307+ if (dir_is_accepted && mFollowSymLinks )
304308 {
305309 std::string real_path = RsDirUtil::removeSymLinks (
306310 RsDirUtil::makePath (cumulated_path, dirIt.file_name ()) );
307311
308- if ( existing_directories.end () !=
309- existing_directories.find (real_path) )
312+ if (std::find (current_branch_real_paths.begin (), current_branch_real_paths.end (), real_path) != current_branch_real_paths.end ())
310313 {
311- RS_WARN ( " Directory: \" " , cumulated_path,
312- " \" has real path: \" " , real_path,
313- " \" which already belongs to another "
314- " shared directory. Ignoring" );
314+ RS_WARN ( " Circular symlink detected: \" " , cumulated_path,
315+ " \" points to ancestor \" " , real_path,
316+ " \" . Ignoring." );
315317 dir_is_accepted = false ;
316318 }
317- else existing_directories.insert (real_path);
319+ else if (mIgnoreDuplicates )
320+ {
321+ if ( existing_directories.end () !=
322+ existing_directories.find (real_path) )
323+ {
324+ RS_WARN ( " Directory: \" " , cumulated_path,
325+ " \" has real path: \" " , real_path,
326+ " \" which already belongs to another "
327+ " shared directory. Ignoring" );
328+ dir_is_accepted = false ;
329+ }
330+ else existing_directories.insert (real_path);
331+ }
318332 }
319333
320334 if (dir_is_accepted) subdirs.insert (dirIt.file_name ());
@@ -364,9 +378,17 @@ void LocalDirectoryUpdater::recursUpdateSharedDir(
364378 // go through the list of sub-dirs and recursively update
365379 for ( DirectoryStorage::DirIterator stored_dir_it (mSharedDirectories , indx);
366380 stored_dir_it; ++stored_dir_it )
367- recursUpdateSharedDir ( RsDirUtil::makePath (cumulated_path, stored_dir_it.name ()),
368- *stored_dir_it, existing_directories,
381+ {
382+ std::string next_path = RsDirUtil::makePath (cumulated_path, stored_dir_it.name ());
383+ std::string canonical = RsDirUtil::removeSymLinks (next_path);
384+ current_branch_real_paths.push_back (canonical);
385+
386+ recursUpdateSharedDir ( next_path,
387+ *stored_dir_it, existing_directories, current_branch_real_paths,
369388 current_depth+1 , some_files_not_ready );
389+
390+ current_branch_real_paths.pop_back ();
391+ }
370392}
371393
372394bool LocalDirectoryUpdater::filterFile (const std::string& fname) const
0 commit comments