Beispiel #1
0
        // Tries to refresh the lstat cache (_fileCache).
        // This method should not throw. Instead, we store the results, and we will throw when the user attempts to access any of the properties when there was a failure
        internal void RefreshCaches(ReadOnlySpan <char> path)
        {
            path = Path.TrimEndingDirectorySeparator(path);

#if !TARGET_BROWSER
            _isReadOnlyCache = -1;
#endif

            int rv = Interop.Sys.LStat(path, out _fileCache);
            if (rv < 0)
            {
                Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();

                if (errorInfo.Error == Interop.Error.ENOENT || // A component of the path does not exist, or path is an empty string
                    errorInfo.Error == Interop.Error.ENOTDIR)  // A component of the path prefix of path is not a directory
                {
                    _state = InitializedNotExists;
                }
                else
                {
                    Debug.Assert(errorInfo.RawErrno > 0); // Expect a positive integer
                    _state = errorInfo.RawErrno;          // Initialized with error.
                }

                return;
            }

            // Check if the main path is a directory, or a link to a directory.
            int  fileType    = _fileCache.Mode & Interop.Sys.FileTypes.S_IFMT;
            bool isDirectory = fileType == Interop.Sys.FileTypes.S_IFDIR ||
                               (fileType == Interop.Sys.FileTypes.S_IFLNK &&
                                Interop.Sys.Stat(path, out Interop.Sys.FileStatus target) == 0 &&
                                (target.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR);

            _state = isDirectory ? InitializedExistsDir : InitializedExistsFile;
        }
        /// <summary>Wrapper for getpwuid_r.</summary>
        /// <param name="buf">The scratch buffer to pass into getpwuid_r.</param>
        /// <param name="bufLen">The length of <paramref name="buf"/>.</param>
        /// <param name="path">The resulting path; null if the user didn't have an entry.</param>
        /// <returns>true if the call was successful (path may still be null); false is a larger buffer is needed.</returns>
        private static unsafe bool TryGetHomeDirectoryFromPasswd(byte* buf, int bufLen, out string path)
        {
            // Call getpwuid_r to get the passwd struct
            Interop.Sys.Passwd passwd;
            int error = Interop.Sys.GetPwUidR(Interop.Sys.GetEUid(), out passwd, buf, bufLen);

            // If the call succeeds, give back the home directory path retrieved
            if (error == 0)
            {
                Debug.Assert(passwd.HomeDirectory != null);
                path = Marshal.PtrToStringAnsi((IntPtr)passwd.HomeDirectory);
                return true;
            }

            // If the current user's entry could not be found, give back null
            // path, but still return true as false indicates the buffer was
            // too small.
            if (error == -1)
            {
                path = null;
                return true;
            }

            var errorInfo = new Interop.ErrorInfo(error);

            // If the call failed because the buffer was too small, return false to 
            // indicate the caller should try again with a larger buffer.
            if (errorInfo.Error == Interop.Error.ERANGE)
            {
                path = null;
                return false;
            }

            // Otherwise, fail.
            throw new IOException(errorInfo.GetErrorMessage(), errorInfo.RawErrno);
        }
Beispiel #3
0
        private void EnsureStatInitialized()
        {
            if (_fileStatusInitialized == -1)
            {
                Refresh();
            }

            if (_fileStatusInitialized != 0)
            {
                int errno = _fileStatusInitialized;
                _fileStatusInitialized = -1;
                var errorInfo =  new Interop.ErrorInfo(errno);

                // Windows distinguishes between whether the directory or the file isn't found,
                // and throws a different exception in these cases.  We attempt to approximate that
                // here; there is a race condition here, where something could change between
                // when the error occurs and our checks, but it's the best we can do, and the
                // worst case in such a race condition (which could occur if the file system is
                // being manipulated concurrently with these checks) is that we throw a
                // FileNotFoundException instead of DirectoryNotFoundexception.

                // directoryError is true only if a FileNotExists error was provided and the parent
                // directory of the file represented by _fullPath is nonexistent
                bool directoryError = (errorInfo.Error == Interop.Error.ENOENT && !Directory.Exists(Path.GetDirectoryName(PathHelpers.TrimEndingDirectorySeparator(FullPath)))); // The destFile's path is invalid
                throw Interop.GetExceptionForIoErrno(errorInfo, FullPath, directoryError);
            }
        }