Esempio n. 1
0
        /// <summary>
        /// Get the next directory entry for the given handle. **Note** the actual memory used may be allocated
        /// by the OS and will be freed when the handle is closed. As such, the handle lifespan MUST be kept tightly
        /// controlled. The DirectoryEntry name cannot be accessed after the handle is closed.
        ///
        /// Call <see cref="ReadBufferSize"/> to see what size buffer to allocate.
        /// </summary>
        internal static int ReadDir(SafeDirectoryHandle dir, Span <byte> buffer, ref DirectoryEntry entry)
        {
            // The calling pattern for ReadDir is described in src/Native/Unix/System.Native/pal_io.cpp|.h
            Debug.Assert(buffer.Length >= ReadBufferSize, "should have a big enough buffer for the raw data");

            // ReadBufferSize is zero when the native implementation does not support reading into a buffer.
            return(ReadDirR(dir.DangerousGetHandle(), ref MemoryMarshal.GetReference(buffer), ReadBufferSize, ref entry));
        }
        // The calling pattern for ReadDir is described in src/Native/System.Native/pal_readdir.cpp
        internal static int ReadDir(SafeDirectoryHandle dir, out DirectoryEntry outputEntry)
        {
            bool addedRef = false;

            try
            {
                // We avoid a native string copy into InternalDirectoryEntry.
                // - If the platform suppors reading into a buffer, the data is read directly into the buffer. The
                //   data can be read as long as the buffer is valid.
                // - If the platform does not support reading into a buffer, the information returned in
                //   InternalDirectoryEntry points to native memory owned by the SafeDirectoryHandle. The data is only
                //   valid until the next call to CloseDir/ReadDir. We extend the reference until we have copied all data
                //   to ensure it does not become invalid by a CloseDir; and we copy the data so our caller does not
                //   use the native memory held by the SafeDirectoryHandle.
                dir.DangerousAddRef(ref addedRef);

                unsafe
                {
                    // s_readBufferSize is zero when the native implementation does not support reading into a buffer.
                    byte *buffer = stackalloc byte[s_readBufferSize];
                    InternalDirectoryEntry temp;
                    int ret = ReadDirR(dir.DangerousGetHandle(), buffer, s_readBufferSize, out temp);
                    // We copy data into DirectoryEntry to ensure there are no dangling references.
                    outputEntry = ret == 0 ?
                                  new DirectoryEntry()
                    {
                        InodeName = GetDirectoryEntryName(temp), InodeType = temp.InodeType
                    } :
                    default(DirectoryEntry);

                    return(ret);
                }
            }
            finally
            {
                if (addedRef)
                {
                    dir.DangerousRelease();
                }
            }
        }