Esempio n. 1
0
        internal static bool Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            string rootDirectory,
            string originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;

            // Get from the dir entry whether the entry is a file or directory.
            // We classify everything as a file unless we know it to be a directory.
            // (This includes regular files, FIFOs, etc.)

            bool isDirectory = false;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
            {
                // We know it's a directory.
                isDirectory = true;
            }
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK || directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus targetStatus) >= 0)
            {
                // It's a symlink or unknown: stat to it to see if we can resolve it to a directory.
                isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
            }

            FileStatus.Initialize(ref entry._status, isDirectory);
            return(isDirectory);
        }
Esempio n. 2
0
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;

            // IMPORTANT: Attribute logic must match the logic in FileStatus

            bool isDirectory = false;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
            {
                // We know it's a directory.
                isDirectory = true;
            }
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK ||
                      directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus targetStatus) >= 0)
            {
                // Symlink or unknown: Stat to it to see if we can resolve it to a directory.
                isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
            }

            entry._status = default;
            FileStatus.Initialize(ref entry._status, isDirectory);

            FileAttributes attributes = default;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK)
            {
                attributes |= FileAttributes.ReparsePoint;
            }
            if (isDirectory)
            {
                attributes |= FileAttributes.Directory;
            }
            if (directoryEntry.Name[0] == '.')
            {
                attributes |= FileAttributes.Hidden;
            }

            if (attributes == default)
            {
                attributes = FileAttributes.Normal;
            }

            entry._initialAttributes = attributes;
            return(attributes);
        }
Esempio n. 3
0
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;

            entry._status.InvalidateCaches();

            bool isDirectory = directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR;
            bool isSymlink   = directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK;
            bool isUnknown   = directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN;

            // Some operating systems don't have the inode type in the dirent structure,
            // so we use DT_UNKNOWN as a sentinel value. As such, check if the dirent is a
            // symlink or a directory.
            if (isUnknown)
            {
                isSymlink = entry.IsSymbolicLink;
                // Need to fail silently in case we are enumerating
                isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true);
            }
            // Same idea as the directory check, just repeated for (and tweaked due to the
            // nature of) symlinks.
            // Whether we had the dirent structure or not, we treat a symlink to a directory as a directory,
            // so we need to reflect that in our isDirectory variable.
            else if (isSymlink)
            {
                // Need to fail silently in case we are enumerating
                isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true);
            }

            entry._status.InitiallyDirectory = isDirectory;

            FileAttributes attributes = default;

            if (isSymlink)
            {
                attributes |= FileAttributes.ReparsePoint;
            }
            if (isDirectory)
            {
                attributes |= FileAttributes.Directory;
            }

            return(attributes);
        }
Esempio n. 4
0
        private static string?GetDirectoryEntryFullPath(ref Interop.Sys.DirectoryEntry dirent, string currentPath)
        {
            ReadOnlySpan <char> direntName = dirent.GetName(stackalloc char[Interop.Sys.DirectoryEntry.NameBufferSize]);

            if ((direntName.Length == 1 && direntName[0] == '.') ||
                (direntName.Length == 2 && direntName[0] == '.' && direntName[1] == '.'))
            {
                return(null);
            }

            return(Path.Join(currentPath.AsSpan(), direntName));
        }
Esempio n. 5
0
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;
            entry._isDirectory          = false;
            entry._status.InvalidateCaches();

            bool isDirectory = directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR;
            bool isSymlink   = directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK;
            bool isUnknown   = directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN;

            if (isDirectory)
            {
                entry._isDirectory = true;
            }
            else if (isSymlink)
            {
                entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true);
            }
            else if (isUnknown)
            {
                entry._isDirectory = entry._status.IsDirectory(entry.FullPath, continueOnError: true);
                if (entry._status.IsSymbolicLink(entry.FullPath, continueOnError: true))
                {
                    entry._directoryEntry.InodeType = Interop.Sys.NodeType.DT_LNK;
                }
            }

            FileAttributes attributes = default;

            if (entry.IsSymbolicLink)
            {
                attributes |= FileAttributes.ReparsePoint;
            }
            if (entry.IsDirectory)
            {
                attributes |= FileAttributes.Directory;
            }

            return(attributes);
        }
Esempio n. 6
0
        // TODO: Unix implementation https://github.com/dotnet/corefx/issues/26715
        // Inital implementation is naive and not optimized.

        internal static void Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            bool isDirectory,
            ReadOnlySpan <char> directory,
            string rootDirectory,
            string originalRootDirectory)
        {
            entry._directoryEntry       = directoryEntry;
            entry._isDirectory          = isDirectory;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
        }
Esempio n. 7
0
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;

            // IMPORTANT: Attribute logic must match the logic in FileStatus

            bool isDirectory = false;
            bool isSymlink   = false;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
            {
                // We know it's a directory.
                isDirectory = true;
            }
            // Some operating systems don't have the inode type in the dirent structure,
            // so we use DT_UNKNOWN as a sentinel value. As such, check if the dirent is a
            // directory.
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK ||
                      directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus statInfo) >= 0)
            {
                // Symlink or unknown: Stat to it to see if we can resolve it to a directory.
                isDirectory = FileStatus.IsDirectory(statInfo);
            }

            // Same idea as the directory check, just repeated for (and tweaked due to the nature of) symlinks.
            int resultLStat = Interop.Sys.LStat(entry.FullPath, out Interop.Sys.FileStatus lstatInfo);

            bool isReadOnly = resultLStat >= 0 && FileStatus.IsReadOnly(lstatInfo);

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK)
            {
                isSymlink = true;
            }
            else if (resultLStat >= 0 && directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN)
            {
                isSymlink = FileStatus.IsSymLink(lstatInfo);
            }

            // If the filename starts with a period or has UF_HIDDEN flag set, it's hidden.
            bool isHidden = directoryEntry.Name[0] == '.' || (resultLStat >= 0 && FileStatus.IsHidden(lstatInfo));

            entry._status = default;
            FileStatus.Initialize(ref entry._status, isDirectory);

            FileAttributes attributes = FileStatus.GetAttributes(isReadOnly, isSymlink, isDirectory, isHidden);

            entry._initialAttributes = attributes;
            return(attributes);
        }
Esempio n. 8
0
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;

            // IMPORTANT: Attribute logic must match the logic in FileStatus

            bool isDirectory = false;
            bool isSymlink   = false;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
            {
                // We know it's a directory.
                isDirectory = true;
            }
            // Some operating systems don't have the inode type in the dirent structure,
            // so we use DT_UNKNOWN as a sentinel value. As such, check if the dirent is a
            // directory.
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK ||
                      directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus targetStatus) >= 0)
            {
                // Symlink or unknown: Stat to it to see if we can resolve it to a directory.
                isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
            }
            // Same idea as the directory check, just repeated for (and tweaked due to the
            // nature of) symlinks.
            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK)
            {
                isSymlink = true;
            }
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     (Interop.Sys.LStat(entry.FullPath, out Interop.Sys.FileStatus linkTargetStatus) >= 0))
            {
                isSymlink = (linkTargetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFLNK;
            }

            entry._status = default;
            FileStatus.Initialize(ref entry._status, isDirectory);

            FileAttributes attributes = default;

            if (isSymlink)
            {
                attributes |= FileAttributes.ReparsePoint;
            }
            if (isDirectory)
            {
                attributes |= FileAttributes.Directory;
            }
            if (directoryEntry.Name[0] == '.')
            {
                attributes |= FileAttributes.Hidden;
            }

            if (attributes == default)
            {
                attributes = FileAttributes.Normal;
            }

            entry._initialAttributes = attributes;
            return(attributes);
        }
        internal static FileAttributes Initialize(
            ref FileSystemEntry entry,
            Interop.Sys.DirectoryEntry directoryEntry,
            ReadOnlySpan <char> directory,
            ReadOnlySpan <char> rootDirectory,
            ReadOnlySpan <char> originalRootDirectory,
            Span <char> pathBuffer)
        {
            entry._directoryEntry       = directoryEntry;
            entry.Directory             = directory;
            entry.RootDirectory         = rootDirectory;
            entry.OriginalRootDirectory = originalRootDirectory;
            entry._pathBuffer           = pathBuffer;
            entry._fullPath             = ReadOnlySpan <char> .Empty;
            entry._fileName             = ReadOnlySpan <char> .Empty;

            // IMPORTANT: Attribute logic must match the logic in FileStatus

            bool isDirectory = false;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_DIR)
            {
                // We know it's a directory.
                isDirectory = true;
            }
            else if ((directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK ||
                      directoryEntry.InodeType == Interop.Sys.NodeType.DT_UNKNOWN) &&
                     (Interop.Sys.Stat(entry.FullPath, out Interop.Sys.FileStatus targetStatus) >= 0 ||
                      Interop.Sys.LStat(entry.FullPath, out targetStatus) >= 0))
            {
                // Symlink or unknown: Stat to it to see if we can resolve it to a directory. If Stat fails,
                // it could be because the symlink is broken, we don't have permissions, etc., in which
                // case fall back to using LStat to evaluate based on the symlink itself.
                isDirectory = (targetStatus.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR;
            }

            entry._status = default;
            FileStatus.Initialize(ref entry._status, isDirectory);

            FileAttributes attributes = default;

            if (directoryEntry.InodeType == Interop.Sys.NodeType.DT_LNK)
            {
                attributes |= FileAttributes.ReparsePoint;
            }
            if (isDirectory)
            {
                attributes |= FileAttributes.Directory;
            }
            if (directoryEntry.Name[0] == '.')
            {
                attributes |= FileAttributes.Hidden;
            }

            if (attributes == default)
            {
                attributes = FileAttributes.Normal;
            }

            entry._initialAttributes = attributes;
            return(attributes);
        }