System.IO.FileSystemWatcher.RunningInstance.AddDirectoryWatchUnlocked C# (CSharp) Méthode

AddDirectoryWatchUnlocked() private méthode

Adds a watch on a directory to the existing inotify handle.
private AddDirectoryWatchUnlocked ( WatchedDirectory parent, string directoryName ) : void
parent WatchedDirectory The parent directory entry.
directoryName string The new directory path to monitor, relative to the root.
Résultat void
            private void AddDirectoryWatchUnlocked(WatchedDirectory parent, string directoryName)
            {
                string fullPath = parent != null ? parent.GetPath(false, directoryName) : directoryName;

                // inotify_add_watch will fail if this is a symlink, so check that we didn't get a symlink
                Interop.Sys.FileStatus status = default(Interop.Sys.FileStatus);
                if ((Interop.Sys.LStat(fullPath, out status) == 0) &&
                    ((status.Mode & (uint)Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK))
                {
                    return;
                }

                // Add a watch for the full path.  If the path is already being watched, this will return 
                // the existing descriptor.  This works even in the case of a rename. We also add the DONT_FOLLOW
                // and EXCL_UNLINK flags to keep parity with Windows where we don't pickup symlinks or unlinked
                // files (which don't exist in Windows)
                int wd = Interop.Sys.INotifyAddWatch(_inotifyHandle, fullPath, (uint)(this._notifyFilters | Interop.Sys.NotifyEvents.IN_DONT_FOLLOW | Interop.Sys.NotifyEvents.IN_EXCL_UNLINK));
                if (wd == -1)
                {
                    // If we get an error when trying to add the watch, don't let that tear down processing.  Instead,
                    // raise the Error event with the exception and let the user decide how to handle it.

                    Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
                    Exception exc;
                    if (error.Error == Interop.Error.ENOSPC)
                    {
                        string maxValue = ReadMaxUserLimit(MaxUserWatchesPath);
                        string message = !string.IsNullOrEmpty(maxValue) ?
                            SR.Format(SR.IOException_INotifyWatchesUserLimitExceeded_Value, maxValue) :
                            SR.IOException_INotifyWatchesUserLimitExceeded;
                        exc = new IOException(message, error.RawErrno);
                    }
                    else
                    {
                        exc = Interop.GetExceptionForIoErrno(error, fullPath);
                    }

                    FileSystemWatcher watcher;
                    if (_weakWatcher.TryGetTarget(out watcher))
                    {
                        watcher.OnError(new ErrorEventArgs(exc));
                    }

                    return;
                }

                // Then store the path information into our map.
                WatchedDirectory directoryEntry;
                bool isNewDirectory = false;
                if (_wdToPathMap.TryGetValue(wd, out directoryEntry))
                {
                    // The watch descriptor was already in the map.  Hard links on directories
                    // aren't possible, and symlinks aren't annotated as IN_ISDIR,
                    // so this is a rename. (In extremely remote cases, this could be
                    // a recycled watch descriptor if many, many events were lost
                    // such that our dictionary got very inconsistent with the state
                    // of the world, but there's little that can be done about that.)
                    if (directoryEntry.Parent != parent)
                    {
                        if (directoryEntry.Parent != null)
                        {
                            directoryEntry.Parent.Children.Remove (directoryEntry);
                        }
                        directoryEntry.Parent = parent;
                        if (parent != null)
                        {
                            parent.InitializedChildren.Add (directoryEntry);
                        }
                    }
                    directoryEntry.Name = directoryName;
                }
                else
                {
                    // The watch descriptor wasn't in the map.  This is a creation.
                    directoryEntry = new WatchedDirectory 
                    {
                        Parent = parent,
                        WatchDescriptor = wd,
                        Name = directoryName
                    };
                    if (parent != null)
                    {
                        parent.InitializedChildren.Add (directoryEntry);
                    }
                    _wdToPathMap.Add(wd, directoryEntry);
                    isNewDirectory = true;
                }

                // Since inotify doesn't handle nesting implicitly, explicitly
                // add a watch for each child directory if the developer has
                // asked for subdirectories to be included.
                if (isNewDirectory && _includeSubdirectories)
                {
                    // This method is recursive.  If we expect to see hierarchies
                    // so deep that it would cause us to overflow the stack, we could
                    // consider using an explicit stack object rather than recursion.
                    // This is unlikely, however, given typical directory names
                    // and max path limits.
                    foreach (string subDir in Directory.EnumerateDirectories(fullPath))
                    {
                        AddDirectoryWatchUnlocked(directoryEntry, System.IO.Path.GetFileName(subDir));
                        // AddDirectoryWatchUnlocked will add the new directory to 
                        // this.Children, so we don't have to / shouldn't also do it here.
                    }
                }
            }