コード例 #1
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        internal static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            Debug.Assert(path != null);

            // If we fail to open the file due to a path not existing, we need to know whether to blame
            // the file itself or its directory.  If we're creating the file, then we blame the directory,
            // otherwise we blame the file.
            bool enoentDueToDirectory = (flags & Interop.Sys.OpenFlags.O_CREAT) != 0;

            // Open the file.
            SafeFileHandle handle = Interop.CheckIo(
                Interop.Sys.Open(path, flags, mode),
                path,
                isDirectory: enoentDueToDirectory,
                errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e);

            // Make sure it's not a directory; we do this after opening it once we have a file descriptor
            // to avoid race conditions.
            Interop.Sys.FileStatus status;
            if (Interop.Sys.FStat(handle, out status) != 0)
            {
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), path);
            }
            if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
            {
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
            }

            return(handle);
        }
コード例 #2
0
        private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options)
        {
            // FileStream performs most of the general argument validation.  We can assume here that the arguments
            // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.)
            // Store the arguments
            _mode    = mode;
            _options = options;

            if (_useAsyncIO)
            {
                _asyncState = new AsyncState();
            }

            // Translate the arguments into arguments for an open call.
            Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, _access, options); // FileShare currently ignored

            // If the file gets created a new, we'll select the permissions for it.  Most utilities by default use 666 (read and
            // write for all). However, on Windows it's possible to write out a file and then execute it.  To maintain that similarity,
            // we use 766, so that in addition the user has execute privileges. No matter what we choose, it'll be subject to the umask
            // applied by the system, such that the actual permissions will typically be less than what we select here.
            const Interop.Sys.Permissions openPermissions =
                Interop.Sys.Permissions.S_IRWXU |
                Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP |
                Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH;

            // Open the file and store the safe handle.
            return(SafeFileHandle.Open(_path, openFlags, (int)openPermissions));
        }
コード例 #3
0
        internal static SafeFileHandle Open(string fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, long preallocationSize)
        {
            // Translate the arguments into arguments for an open call.
            Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, access, share, options);

            // If the file gets created a new, we'll select the permissions for it.  Most Unix utilities by default use 666 (read and
            // write for all), so we do the same (even though this doesn't match Windows, where by default it's possible to write out
            // a file and then execute it). No matter what we choose, it'll be subject to the umask applied by the system, such that the
            // actual permissions will typically be less than what we select here.
            const Interop.Sys.Permissions OpenPermissions =
                Interop.Sys.Permissions.S_IRUSR | Interop.Sys.Permissions.S_IWUSR |
                Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP |
                Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH;

            SafeFileHandle safeFileHandle = Open(fullPath, openFlags, (int)OpenPermissions);

            try
            {
                safeFileHandle.Init(fullPath, mode, access, share, options, preallocationSize);

                return(safeFileHandle);
            }
            catch (Exception)
            {
                safeFileHandle.Dispose();

                throw;
            }
        }
コード例 #4
0
ファイル: FileStream.Unix.cs プロジェクト: wecing/coreclr
        private SafeFileHandle OpenHandle(FileMode mode, FileShare share, FileOptions options)
        {
            // FileStream performs most of the general argument validation.  We can assume here that the arguments
            // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.)
            // Store the arguments
            _mode    = mode;
            _options = options;

            if (_useAsyncIO)
            {
                _asyncState = new AsyncState();
            }

            // Translate the arguments into arguments for an open call.
            Interop.Sys.OpenFlags openFlags = PreOpenConfigurationFromOptions(mode, _access, share, options);

            // If the file gets created a new, we'll select the permissions for it.  Most Unix utilities by default use 666 (read and
            // write for all), so we do the same (even though this doesn't match Windows, where by default it's possible to write out
            // a file and then execute it). No matter what we choose, it'll be subject to the umask applied by the system, such that the
            // actual permissions will typically be less than what we select here.
            const Interop.Sys.Permissions OpenPermissions =
                Interop.Sys.Permissions.S_IRUSR | Interop.Sys.Permissions.S_IWUSR |
                Interop.Sys.Permissions.S_IRGRP | Interop.Sys.Permissions.S_IWGRP |
                Interop.Sys.Permissions.S_IROTH | Interop.Sys.Permissions.S_IWOTH;

            // Open the file and store the safe handle.
            return(SafeFileHandle.Open(_path, openFlags, (int)OpenPermissions));
        }
コード例 #5
0
        internal static Interop.Sys.OpenFlags TranslateFlags(PipeDirection direction, PipeOptions options, HandleInheritability inheritability)
        {
            // Translate direction
            Interop.Sys.OpenFlags flags =
                direction == PipeDirection.InOut ? Interop.Sys.OpenFlags.O_RDWR :
                direction == PipeDirection.Out ? Interop.Sys.OpenFlags.O_WRONLY :
                Interop.Sys.OpenFlags.O_RDONLY;

            // Translate options
            if ((options & PipeOptions.WriteThrough) != 0)
            {
                flags |= Interop.Sys.OpenFlags.O_SYNC;
            }

            // Translate inheritability.
            if ((inheritability & HandleInheritability.Inheritable) == 0)
            {
                flags |= Interop.Sys.OpenFlags.O_CLOEXEC;
            }

            // PipeOptions.Asynchronous is ignored, at least for now.  Asynchronous processing
            // is handling just by queueing a work item to do the work synchronously on a pool thread.

            return(flags);
        }
コード例 #6
0
        /// <summary>Translates the FileMode, FileAccess, and FileOptions values into flags to be passed when opening the file.</summary>
        /// <param name="mode">The FileMode provided to the stream's constructor.</param>
        /// <param name="access">The FileAccess provided to the stream's constructor</param>
        /// <param name="share">The FileShare provided to the stream's constructor</param>
        /// <param name="options">The FileOptions provided to the stream's constructor</param>
        /// <returns>The flags value to be passed to the open system call.</returns>
        private static Interop.Sys.OpenFlags PreOpenConfigurationFromOptions(FileMode mode, FileAccess access, FileShare share, FileOptions options)
        {
            // Translate FileMode.  Most of the values map cleanly to one or more options for open.
            Interop.Sys.OpenFlags flags = default;
            switch (mode)
            {
            default:
            case FileMode.Open:     // Open maps to the default behavior for open(...).  No flags needed.
            case FileMode.Truncate: // We truncate the file after getting the lock
                break;

            case FileMode.Append:     // Append is the same as OpenOrCreate, except that we'll also separately jump to the end later
            case FileMode.OpenOrCreate:
            case FileMode.Create:     // We truncate the file after getting the lock
                flags |= Interop.Sys.OpenFlags.O_CREAT;
                break;

            case FileMode.CreateNew:
                flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL);
                break;
            }

            // Translate FileAccess.  All possible values map cleanly to corresponding values for open.
            switch (access)
            {
            case FileAccess.Read:
                flags |= Interop.Sys.OpenFlags.O_RDONLY;
                break;

            case FileAccess.ReadWrite:
                flags |= Interop.Sys.OpenFlags.O_RDWR;
                break;

            case FileAccess.Write:
                flags |= Interop.Sys.OpenFlags.O_WRONLY;
                break;
            }

            // Handle Inheritable, other FileShare flags are handled by Init
            if ((share & FileShare.Inheritable) == 0)
            {
                flags |= Interop.Sys.OpenFlags.O_CLOEXEC;
            }

            // Translate some FileOptions; some just aren't supported, and others will be handled after calling open.
            // - Asynchronous: Handled in ctor, setting _useAsync and SafeFileHandle.IsAsync to true
            // - DeleteOnClose: Doesn't have a Unix equivalent, but we approximate it in Dispose
            // - Encrypted: No equivalent on Unix and is ignored
            // - RandomAccess: Implemented after open if posix_fadvise is available
            // - SequentialScan: Implemented after open if posix_fadvise is available
            // - WriteThrough: Handled here
            if ((options & FileOptions.WriteThrough) != 0)
            {
                flags |= Interop.Sys.OpenFlags.O_SYNC;
            }

            return(flags);
        }
コード例 #7
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        internal static SafePipeHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            // Ideally this would be a constrained execution region, but we don't have access to PrepareConstrainedRegions.
            SafePipeHandle handle = Interop.CheckIo(Interop.Sys.OpenPipe(path, flags, mode));

            Debug.Assert(!handle.IsInvalid);

            return(handle);
        }
コード例 #8
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        private static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            Debug.Assert(path != null);
            SafeFileHandle handle = Interop.Sys.Open(path, flags, mode);

            handle._path = path;

            if (handle.IsInvalid)
            {
                Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
                handle.Dispose();

                // If we fail to open the file due to a path not existing, we need to know whether to blame
                // the file itself or its directory.  If we're creating the file, then we blame the directory,
                // otherwise we blame the file.
                //
                // When opening, we need to align with Windows, which considers a missing path to be
                // FileNotFound only if the containing directory exists.

                bool isDirectory = (error.Error == Interop.Error.ENOENT) &&
                                   ((flags & Interop.Sys.OpenFlags.O_CREAT) != 0 ||
                                    !DirectoryExists(System.IO.Path.GetDirectoryName(System.IO.Path.TrimEndingDirectorySeparator(path !)) !));

                Interop.CheckIo(
                    error.Error,
                    path,
                    isDirectory,
                    errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e);
            }

            // Make sure it's not a directory; we do this after opening it once we have a file descriptor
            // to avoid race conditions.
            Interop.Sys.FileStatus status;
            if (Interop.Sys.FStat(handle, out status) != 0)
            {
                Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(error, path);
            }
            if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
            {
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
            }

            if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFREG)
            {
                // we take advantage of the information provided by the fstat syscall
                // and for regular files (most common case)
                // avoid one extra sys call for determining whether file can be seeked
                handle._canSeek = NullableBool.True;
                Debug.Assert(Interop.Sys.LSeek(handle, 0, Interop.Sys.SeekWhence.SEEK_CUR) >= 0);
            }

            return(handle);
        }
コード例 #9
0
            static Exception?CreateOpenException(Interop.ErrorInfo error, Interop.Sys.OpenFlags flags, string path)
            {
                // If the destination path points to a directory, we throw to match Windows behaviour.
                if (error.Error == Interop.Error.EEXIST && DirectoryExists(path))
                {
                    return(new IOException(SR.Format(SR.Arg_FileIsDirectory_Name, path)));
                }

                return(null); // Let SafeFileHandle create the exception for this error.
            }
コード例 #10
0
        private static FileStream CreateSharedBackingObject(
            Interop.libc.MemoryMappedProtections protections, long capacity)
        {
            // The POSIX shared memory object name must begin with '/'.  After that we just want something short and unique.
            string mapName = "/corefx_map_" + Guid.NewGuid().ToString("N");

            // Determine the flags to use when creating the shared memory object
            Interop.Sys.OpenFlags flags = (protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0 ?
                                          Interop.Sys.OpenFlags.O_RDWR :
                                          Interop.Sys.OpenFlags.O_RDONLY;
            flags |= Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL; // CreateNew

            // Determine the permissions with which to create the file
            Interop.Sys.Permissions perms = default(Interop.Sys.Permissions);
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_READ) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IRUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_WRITE) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IWUSR;
            }
            if ((protections & Interop.libc.MemoryMappedProtections.PROT_EXEC) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IXUSR;
            }

            // Create the shared memory object.
            int fd;

            Interop.CheckIo(fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms), mapName);
            SafeFileHandle fileHandle = new SafeFileHandle((IntPtr)fd, ownsHandle: true);

            try
            {
                // Unlink the shared memory object immediatley so that it'll go away once all handles
                // to it are closed (as with opened then unlinked files, it'll remain usable via
                // the open handles even though it's unlinked and can't be opened anew via its name).
                Interop.CheckIo(Interop.Sys.ShmUnlink(mapName));

                // Give it the right capacity.  We do this directly with ftruncate rather
                // than via FileStream.SetLength after the FileStream is created because, on some systems,
                // lseek fails on shared memory objects, causing the FileStream to think it's unseekable,
                // causing it to preemptively throw from SetLength.
                Interop.CheckIo(Interop.libc.ftruncate(fd, capacity));

                // Wrap the file descriptor in a stream and return it.
                return(new FileStream(fileHandle, TranslateProtectionsToFileAccess(protections)));
            }
            catch
            {
                fileHandle.Dispose();
                throw;
            }
        }
コード例 #11
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        internal static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            Debug.Assert(path != null);

            // SafeFileHandle wraps a file descriptor rather than a pointer, and a file descriptor is always 4 bytes
            // rather than being pointer sized, which means we can't utilize the runtime's ability to marshal safe handles.
            // Ideally this would be a constrained execution region, but we don't have access to PrepareConstrainedRegions.
            // We still use a finally block to house the code that opens the file and stores the handle in hopes
            // of making it as non-interruptable as possible.  The SafeFileHandle is also allocated first to avoid
            // the allocation after getting the file descriptor but before storing it.
            SafeFileHandle handle = new SafeFileHandle(ownsHandle: true);

            try { } finally
            {
                // If we fail to open the file due to a path not existing, we need to know whether to blame
                // the file itself or its directory.  If we're creating the file, then we blame the directory,
                // otherwise we blame the file.
                bool enoentDueToDirectory = (flags & Interop.Sys.OpenFlags.O_CREAT) != 0;

                // Open the file.
                int fd;
                while (Interop.CheckIo(fd = Interop.Sys.Open(path, flags, mode), path, isDirectory: enoentDueToDirectory,
                                       errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e))
                {
                    ;
                }
                Debug.Assert(fd >= 0);
                handle.SetHandle((IntPtr)fd);
                Debug.Assert(!handle.IsInvalid);

                // Make sure it's not a directory; we do this after opening it once we have a file descriptor
                // to avoid race conditions.
                Interop.Sys.FileStatus status;
                if (Interop.Sys.FStat(fd, out status) != 0)
                {
                    handle.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), path);
                }
                if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
                {
                    handle.Dispose();
                    throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
                }
            }
            return(handle);
        }
コード例 #12
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        internal static SafeFileHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            Debug.Assert(path != null);
            SafeFileHandle handle = Interop.Sys.Open(path, flags, mode);

            if (handle.IsInvalid)
            {
                handle.Dispose();
                Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();

                // If we fail to open the file due to a path not existing, we need to know whether to blame
                // the file itself or its directory.  If we're creating the file, then we blame the directory,
                // otherwise we blame the file.
                //
                // When opening, we need to align with Windows, which considers a missing path to be
                // FileNotFound only if the containing directory exists.

                bool isDirectory = (error.Error == Interop.Error.ENOENT) &&
                                   ((flags & Interop.Sys.OpenFlags.O_CREAT) != 0 ||
                                    !DirectoryExists(Path.GetDirectoryName(Path.TrimEndingDirectorySeparator(path !)) !));

                Interop.CheckIo(
                    error.Error,
                    path,
                    isDirectory,
                    errorRewriter: e => (e.Error == Interop.Error.EISDIR) ? Interop.Error.EACCES.Info() : e);
            }

            // Make sure it's not a directory; we do this after opening it once we have a file descriptor
            // to avoid race conditions.
            Interop.Sys.FileStatus status;
            if (Interop.Sys.FStat(handle, out status) != 0)
            {
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo(), path);
            }
            if ((status.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
            {
                handle.Dispose();
                throw Interop.GetExceptionForIoErrno(Interop.Error.EACCES.Info(), path, isDirectory: true);
            }

            return(handle);
        }
コード例 #13
0
ファイル: UnixFileStream.cs プロジェクト: ikopylov/corefx
        /// <summary>Initializes a stream for reading or writing a Unix file.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="mode">How the file should be opened.</param>
        /// <param name="access">Whether the file will be read, written, or both.</param>
        /// <param name="share">What other access to the file should be allowed.  This is currently ignored.</param>
        /// <param name="bufferSize">The size of the buffer to use when buffering.</param>
        /// <param name="options">Additional options for working with the file.</param>
        internal UnixFileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, FileStream parent)
            : base(parent)
        {
            // FileStream performs most of the general argument validation.  We can assume here that the arguments
            // are all checked and consistent (e.g. non-null-or-empty path; valid enums in mode, access, share, and options; etc.)
            // Store the arguments
            _path         = path;
            _access       = access;
            _mode         = mode;
            _options      = options;
            _bufferLength = bufferSize;
            _useAsyncIO   = (options & FileOptions.Asynchronous) != 0;

            // Translate the arguments into arguments for an open call
            Interop.Sys.OpenFlags   openFlags       = PreOpenConfigurationFromOptions(mode, access, options); // FileShare currently ignored
            Interop.Sys.Permissions openPermissions = Interop.Sys.Permissions.S_IRWXU;                        // creator has read/write/execute permissions; no permissions for anyone else

            // Open the file and store the safe handle. Subsequent code in this method expects the safe handle to be initialized.
            _fileHandle         = SafeFileHandle.Open(path, openFlags, (int)openPermissions);
            _fileHandle.IsAsync = _useAsyncIO;

            // Lock the file if requested via FileShare.  This is only advisory locking. FileShare.None implies an exclusive
            // lock on the file and all other modes use a shared lock.  While this is not as granular as Windows, not mandatory,
            // and not atomic with file opening, it's better than nothing.
            try
            {
                Interop.Sys.LockOperations lockOperation = (share == FileShare.None) ? Interop.Sys.LockOperations.LOCK_EX : Interop.Sys.LockOperations.LOCK_SH;
                SysCall <Interop.Sys.LockOperations, int>((fd, op, _) => Interop.Sys.FLock(fd, op), lockOperation | Interop.Sys.LockOperations.LOCK_NB);
            }
            catch
            {
                _fileHandle.Dispose();
                throw;
            }

            // Perform additional configurations on the stream based on the provided FileOptions
            PostOpenConfigureStreamFromOptions();

            // Jump to the end of the file if opened as Append.
            if (_mode == FileMode.Append)
            {
                _appendStart = SeekCore(0, SeekOrigin.End);
            }
        }
コード例 #14
0
        /// <summary>Opens the specified file with the requested flags and mode.</summary>
        /// <param name="path">The path to the file.</param>
        /// <param name="flags">The flags with which to open the file.</param>
        /// <param name="mode">The mode for opening the file.</param>
        /// <returns>A SafeFileHandle for the opened file.</returns>
        internal static SafePipeHandle Open(string path, Interop.Sys.OpenFlags flags, int mode)
        {
            // SafePipeHandle wraps a file descriptor rather than a pointer, and a file descriptor is always 4 bytes
            // rather than being pointer sized, which means we can't utilize the runtime's ability to marshal safe handles.
            // Ideally this would be a constrained execution region, but we don't have access to PrepareConstrainedRegions.
            // We still use a finally block to house the code that opens the file and stores the handle in hopes
            // of making it as non-interruptable as possible.  The SafePipeHandle is also allocated first to avoid
            // the allocation after getting the file descriptor but before storing it.
            SafePipeHandle handle = new SafePipeHandle();

            try { }
            finally
            {
                int fd;
                while (Interop.CheckIo(fd = Interop.Sys.Open(path, flags, mode)))
                {
                    ;
                }
                Debug.Assert(fd >= 0);
                handle.SetHandle((IntPtr)fd);
            }
            return(handle);
        }
コード例 #15
0
ファイル: UnixFileStream.cs プロジェクト: ikopylov/corefx
        /// <summary>Translates the FileMode, FileAccess, and FileOptions values into flags to be passed when opening the file.</summary>
        /// <param name="mode">The FileMode provided to the stream's constructor.</param>
        /// <param name="access">The FileAccess provided to the stream's constructor</param>
        /// <param name="options">The FileOptions provided to the stream's constructor</param>
        /// <returns>The flags value to be passed to the open system call.</returns>
        private static Interop.Sys.OpenFlags PreOpenConfigurationFromOptions(FileMode mode, FileAccess access, FileOptions options)
        {
            // Translate FileMode.  Most of the values map cleanly to one or more options for open.
            Interop.Sys.OpenFlags flags = default(Interop.Sys.OpenFlags);
            switch (mode)
            {
            default:
            case FileMode.Open:     // Open maps to the default behavior for open(...).  No flags needed.
                break;

            case FileMode.Append:     // Append is the same as OpenOrCreate, except that we'll also separately jump to the end later
            case FileMode.OpenOrCreate:
                flags |= Interop.Sys.OpenFlags.O_CREAT;
                break;

            case FileMode.Create:
                flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_TRUNC);
                break;

            case FileMode.CreateNew:
                flags |= (Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL);
                break;

            case FileMode.Truncate:
                flags |= Interop.Sys.OpenFlags.O_TRUNC;
                break;
            }

            // Translate FileAccess.  All possible values map cleanly to corresponding values for open.
            switch (access)
            {
            case FileAccess.Read:
                flags |= Interop.Sys.OpenFlags.O_RDONLY;
                break;

            case FileAccess.ReadWrite:
                flags |= Interop.Sys.OpenFlags.O_RDWR;
                break;

            case FileAccess.Write:
                flags |= Interop.Sys.OpenFlags.O_WRONLY;
                break;
            }

            // Translate some FileOptions; some just aren't supported, and others will be handled after calling open.
            switch (options)
            {
            case FileOptions.Asynchronous:        // Handled in ctor, setting _useAsync and SafeFileHandle.IsAsync to true
            case FileOptions.DeleteOnClose:       // DeleteOnClose doesn't have a Unix equivalent, but we approximate it in Dispose
            case FileOptions.Encrypted:           // Encrypted does not have an equivalent on Unix and is ignored.
            case FileOptions.RandomAccess:        // Implemented after open if posix_fadvise is available
            case FileOptions.SequentialScan:      // Implemented after open if posix_fadvise is available
                break;

            case FileOptions.WriteThrough:
                flags |= Interop.Sys.OpenFlags.O_SYNC;
                break;
            }

            return(flags);
        }
コード例 #16
0
        // -----------------------------
        // ---- PAL layer ends here ----
        // -----------------------------

        private static FileStream CreateSharedBackingObjectUsingMemory(
            Interop.Sys.MemoryMappedProtections protections, long capacity)
        {
            // The POSIX shared memory object name must begin with '/'.  After that we just want something short and unique.
            string mapName = "/corefx_map_" + Guid.NewGuid().ToString("N");

            // Determine the flags to use when creating the shared memory object
            Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ?
                                          Interop.Sys.OpenFlags.O_RDWR :
                                          Interop.Sys.OpenFlags.O_RDONLY;
            flags |= Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL; // CreateNew

            // Determine the permissions with which to create the file
            Interop.Sys.Permissions perms = default(Interop.Sys.Permissions);
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_READ) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IRUSR;
            }
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IWUSR;
            }
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IXUSR;
            }

            // Create the shared memory object.
            SafeFileHandle fd = Interop.Sys.ShmOpen(mapName, flags, (int)perms);

            if (fd.IsInvalid)
            {
                Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
                if (errorInfo.Error == Interop.Error.ENOTSUP)
                {
                    // If ShmOpen is not supported, fall back to file backing object.
                    // Note that the System.Native shim will force this failure on platforms where
                    // the result of native shm_open does not work well with our subsequent call
                    // to mmap.
                    return(null);
                }

                throw Interop.GetExceptionForIoErrno(errorInfo);
            }

            try
            {
                // Unlink the shared memory object immediately so that it'll go away once all handles
                // to it are closed (as with opened then unlinked files, it'll remain usable via
                // the open handles even though it's unlinked and can't be opened anew via its name).
                Interop.CheckIo(Interop.Sys.ShmUnlink(mapName));

                // Give it the right capacity.  We do this directly with ftruncate rather
                // than via FileStream.SetLength after the FileStream is created because, on some systems,
                // lseek fails on shared memory objects, causing the FileStream to think it's unseekable,
                // causing it to preemptively throw from SetLength.
                Interop.CheckIo(Interop.Sys.FTruncate(fd, capacity));

                // Wrap the file descriptor in a stream and return it.
                return(new FileStream(fd, TranslateProtectionsToFileAccess(protections)));
            }
            catch
            {
                fd.Dispose();
                throw;
            }
        }
コード例 #17
0
        private static FileStream?CreateSharedBackingObjectUsingMemory(
            Interop.Sys.MemoryMappedProtections protections, long capacity, HandleInheritability inheritability)
        {
            // Determine the flags to use when creating the shared memory object
            Interop.Sys.OpenFlags flags = (protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0 ?
                                          Interop.Sys.OpenFlags.O_RDWR :
                                          Interop.Sys.OpenFlags.O_RDONLY;
            flags |= Interop.Sys.OpenFlags.O_CREAT | Interop.Sys.OpenFlags.O_EXCL; // CreateNew

            // Determine the permissions with which to create the file
            Interop.Sys.Permissions perms = default(Interop.Sys.Permissions);
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_READ) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IRUSR;
            }
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_WRITE) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IWUSR;
            }
            if ((protections & Interop.Sys.MemoryMappedProtections.PROT_EXEC) != 0)
            {
                perms |= Interop.Sys.Permissions.S_IXUSR;
            }

            string         mapName;
            SafeFileHandle fd;

            do
            {
                mapName = GenerateMapName();
                fd      = Interop.Sys.ShmOpen(mapName, flags, (int)perms); // Create the shared memory object.

                if (fd.IsInvalid)
                {
                    Interop.ErrorInfo errorInfo = Interop.Sys.GetLastErrorInfo();
                    fd.Dispose();

                    if (errorInfo.Error == Interop.Error.ENOTSUP)
                    {
                        // If ShmOpen is not supported, fall back to file backing object.
                        // Note that the System.Native shim will force this failure on platforms where
                        // the result of native shm_open does not work well with our subsequent call to mmap.
                        return(null);
                    }
                    else if (errorInfo.Error != Interop.Error.EEXIST) // map with same name already existed
                    {
                        throw Interop.GetExceptionForIoErrno(errorInfo);
                    }
                }
            } while (fd.IsInvalid);

            try
            {
                // Unlink the shared memory object immediately so that it'll go away once all handles
                // to it are closed (as with opened then unlinked files, it'll remain usable via
                // the open handles even though it's unlinked and can't be opened anew via its name).
                Interop.CheckIo(Interop.Sys.ShmUnlink(mapName));

                // Give it the right capacity.  We do this directly with ftruncate rather
                // than via FileStream.SetLength after the FileStream is created because, on some systems,
                // lseek fails on shared memory objects, causing the FileStream to think it's unseekable,
                // causing it to preemptively throw from SetLength.
                Interop.CheckIo(Interop.Sys.FTruncate(fd, capacity));

                // shm_open sets CLOEXEC implicitly.  If the inheritability requested is Inheritable, remove CLOEXEC.
                if (inheritability == HandleInheritability.Inheritable &&
                    Interop.Sys.Fcntl.SetFD(fd, 0) == -1)
                {
                    throw Interop.GetExceptionForIoErrno(Interop.Sys.GetLastErrorInfo());
                }

                // Wrap the file descriptor in a stream and return it.
                return(new FileStream(fd, TranslateProtectionsToFileAccess(protections)));
            }
            catch
            {
                fd.Dispose();
                throw;
            }