11extern alias References ;
22
33using Oxide . Core . Libraries ;
4- using References ::Mono . Posix ;
54using System ;
65using System . Collections . Generic ;
76using System . IO ;
7+ using System . Text ;
88#if ! NETSTANDARD
99using System . Security . Permissions ;
1010#endif
1111using System . Text . RegularExpressions ;
12+ using Oxide . Pooling ;
13+ using References ::Mono . Unix . Native ;
14+ using Syscall = References ::Mono . Unix . Native . Syscall ;
1215
1316namespace Oxide . Core . Plugins . Watchers
1417{
@@ -35,6 +38,7 @@ private class QueuedChange
3538 private Timer timers ;
3639
3740 private Dictionary < string , FileSystemWatcher > m_symlinkWatchers = new Dictionary < string , FileSystemWatcher > ( ) ;
41+ private IPoolProvider < StringBuilder > StringPool { get ; }
3842
3943 /// <summary>
4044 /// Initializes a new instance of the FSWatcher class
@@ -43,6 +47,7 @@ private class QueuedChange
4347 /// <param name="filter"></param>
4448 public FSWatcher ( string directory , string filter )
4549 {
50+ StringPool = Interface . Oxide . PoolFactory . GetProvider < StringBuilder > ( ) ;
4651 watchedPlugins = new HashSet < string > ( ) ;
4752 changeQueue = new Dictionary < string , QueuedChange > ( ) ;
4853 timers = Interface . Oxide . GetLibrary < Timer > ( ) ;
@@ -80,21 +85,46 @@ private bool IsFileSymlink(string path)
8085#endif
8186 private void LoadWatcherSymlink ( string path )
8287 {
83- string realPath = Syscall . readlink ( path ) ;
84- string realDirName = Path . GetDirectoryName ( realPath ) ;
85- string realFileName = Path . GetFileName ( realPath ) ;
88+ StringBuilder str = StringPool . Take ( ) ;
89+ try
90+ {
91+ int count = Syscall . readlink ( path , str ) ;
8692
87- void symlinkTarget_Changed ( object sender , FileSystemEventArgs e ) => watcher_Changed ( sender , e ) ;
93+ if ( count == - 1 )
94+ {
95+ Errno err = Stdlib . GetLastError ( ) ;
96+
97+ switch ( err )
98+ {
99+ case Errno . EINVAL :
100+ return ;
101+
102+ default :
103+ throw new IOException ( $ "Unable to process symlink | { err } ", ( int ) err ) ;
104+ }
105+ }
106+
107+ string realPath = str . ToString ( 0 , count ) ;
108+ string realDirName = Path . GetDirectoryName ( realPath ) ;
109+ string realFileName = Path . GetFileName ( realPath ) ;
110+
111+ void symlinkTarget_Changed ( object sender , FileSystemEventArgs e ) => watcher_Changed ( sender , e ) ;
112+
113+ FileSystemWatcher watcher = new FileSystemWatcher ( realDirName , realFileName ) ;
114+ m_symlinkWatchers [ path ] = watcher ;
115+ watcher . Changed += symlinkTarget_Changed ;
116+ watcher . Created += symlinkTarget_Changed ;
117+ watcher . Deleted += symlinkTarget_Changed ;
118+ watcher . Error += watcher_Error ;
119+ watcher . NotifyFilter = NotifyFilters . LastWrite ;
120+ watcher . IncludeSubdirectories = false ;
121+ watcher . EnableRaisingEvents = true ;
122+ }
123+ finally
124+ {
125+ StringPool . Return ( str ) ;
126+ }
88127
89- FileSystemWatcher watcher = new FileSystemWatcher ( realDirName , realFileName ) ;
90- m_symlinkWatchers [ path ] = watcher ;
91- watcher . Changed += symlinkTarget_Changed ;
92- watcher . Created += symlinkTarget_Changed ;
93- watcher . Deleted += symlinkTarget_Changed ;
94- watcher . Error += watcher_Error ;
95- watcher . NotifyFilter = NotifyFilters . LastWrite ;
96- watcher . IncludeSubdirectories = false ;
97- watcher . EnableRaisingEvents = true ;
98128 }
99129
100130 /// <summary>
0 commit comments