Пример #1
0
        private static UnixFileMode DetermineUMask()
        {
            // To determine the umask, we'll create a file with full permissions and see
            // what gets filtered out.
            // note: only the owner of a file, and root can change file permissions.

            const UnixFileMode OwnershipPermissions =
                UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
                UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
                UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute;

            string            filename = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            FileStreamOptions options  = new()
            {
                Mode           = FileMode.CreateNew,
                UnixCreateMode = OwnershipPermissions,
                Options        = FileOptions.DeleteOnClose,
                Access         = FileAccess.Write,
                BufferSize     = 0
            };

            using var fs = new FileStream(filename, options);
            UnixFileMode actual = File.GetUnixFileMode(fs.SafeFileHandle);

            return(OwnershipPermissions & ~actual);
        }
Пример #2
0
        private void SetUnixFileMode(SafeFileHandle?handle, string?path, UnixFileMode mode)
        {
            if ((mode & ~FileSystem.ValidUnixFileModes) != 0)
            {
                throw new ArgumentException(SR.Arg_InvalidUnixFileMode, nameof(UnixFileMode));
            }

            // Use ThrowNotFound to throw the appropriate exception when the file doesn't exist.
            if (handle is null && path is not null)
            {
                EnsureCachesInitialized(path);

                if (!EntryExists || IsBrokenLink)
                {
                    FileSystemInfo.ThrowNotFound(path);
                }
            }

            // Linux does not support link permissions.
            // To have consistent cross-platform behavior we operate on the link target.
            int rv = handle is not null?Interop.Sys.FChMod(handle, (int)mode)
                         : Interop.Sys.ChMod(path !, (int)mode);

            Interop.CheckIo(rv, path);

            InvalidateCaches();
        }
Пример #3
0
        protected void VerifyPlatformSpecificMetadata(string filePath, TarEntry entry)
        {
            Assert.True(entry.ModificationTime > DateTimeOffset.UnixEpoch);

            UnixFileMode expectedMode = DefaultWindowsMode;

            Assert.Equal(expectedMode, entry.Mode);

            Assert.Equal(DefaultUid, entry.Uid);
            Assert.Equal(DefaultGid, entry.Gid);

            if (entry is PosixTarEntry posix)
            {
                Assert.Equal(DefaultGName, posix.GroupName);
                Assert.Equal(DefaultUName, posix.UserName);

                Assert.Equal(DefaultDeviceMajor, posix.DeviceMajor);
                Assert.Equal(DefaultDeviceMinor, posix.DeviceMinor);

                if (entry is PaxTarEntry pax)
                {
                    VerifyExtendedAttributeTimestamps(pax);
                }

                if (entry is GnuTarEntry gnu)
                {
                    VerifyGnuTimestamps(gnu);
                }
            }
        }
Пример #4
0
        private static bool IsExecutable(string fullPath)
        {
            Interop.Sys.FileStatus fileinfo;

            if (Interop.Sys.Stat(fullPath, out fileinfo) < 0)
            {
                return(false);
            }

            // Check if the path is a directory.
            if ((fileinfo.Mode & Interop.Sys.FileTypes.S_IFMT) == Interop.Sys.FileTypes.S_IFDIR)
            {
                return(false);
            }

            const UnixFileMode AllExecute = UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute;

            UnixFileMode permissions = ((UnixFileMode)fileinfo.Mode) & AllExecute;

            // Avoid checking user/group when permission.
            if (permissions == AllExecute)
            {
                return(true);
            }
            else if (permissions == 0)
            {
                return(false);
            }

            uint euid = Interop.Sys.GetEUid();

            if (euid == 0)
            {
                return(true); // We're root.
            }

            if (euid == fileinfo.Uid)
            {
                // We own the file.
                return((permissions & UnixFileMode.UserExecute) != 0);
            }

            bool groupCanExecute = (permissions & UnixFileMode.GroupExecute) != 0;
            bool otherCanExecute = (permissions & UnixFileMode.OtherExecute) != 0;

            // Avoid group check when group and other have same permissions.
            if (groupCanExecute == otherCanExecute)
            {
                return(groupCanExecute);
            }

            if (Interop.Sys.IsMemberOfGroup(fileinfo.Gid))
            {
                return(groupCanExecute);
            }
            else
            {
                return(otherCanExecute);
            }
        }
Пример #5
0
        public void ItGeneratesExecutableImage()
        {
            using TestDirectory testDirectory = TestDirectory.Create();
            string sourceAppHostMock   = PrepareAppHostMockFile(testDirectory);
            string destinationFilePath = Path.Combine(testDirectory.Path, "DestinationAppHost.exe.mock");
            string appBinaryFilePath   = "Test/App/Binary/Path.dll";

            // strip executable permissions from this AppHost template binary
            File.SetUnixFileMode(sourceAppHostMock, UnixFileMode.UserRead | UnixFileMode.GroupRead | UnixFileMode.OtherRead);

            // -rwxr-xr-x
            const UnixFileMode expectedPermissions = UnixFileMode.UserRead | UnixFileMode.UserExecute | UnixFileMode.UserWrite |
                                                     UnixFileMode.GroupRead | UnixFileMode.GroupExecute |
                                                     UnixFileMode.OtherRead | UnixFileMode.OtherExecute;

            HostWriter.CreateAppHost(
                sourceAppHostMock,
                destinationFilePath,
                appBinaryFilePath,
                windowsGraphicalUserInterface: true);

            // assert that the generated app has executable permissions
            // despite different permissions on the template binary.
            File.GetUnixFileMode(destinationFilePath)
            .Should()
            .Be(expectedPermissions);
        }
        public void CreateDoesntChangeExistingMode()
        {
            string        path        = GetRandomDirPath();
            DirectoryInfo dir         = Directory.CreateDirectory(path, AllAccess);
            UnixFileMode  initialMode = dir.UnixFileMode;

            DirectoryInfo sameDir = Directory.CreateDirectory(path, UnixFileMode.UserRead);

            Assert.Equal(initialMode, sameDir.UnixFileMode);
        }
        public void InvalidModeThrows(UnixFileMode mode, bool alreadyExists)
        {
            string path = GetRandomDirPath();

            if (alreadyExists)
            {
                Directory.CreateDirectory(path);
            }

            Assert.Throws <ArgumentException>(() => Directory.CreateDirectory(path, mode));
        }
        public void CreateWithUnixFileMode(UnixFileMode mode)
        {
            string        path = GetRandomDirPath();
            DirectoryInfo dir  = Directory.CreateDirectory(path, mode);

            // under Linux the created directory gets mode (mode & ~umask & 01777).
            // under OSX, it gets (mode & ~umask & 0777).
            UnixFileMode platformFilter = UnixFileMode.SetGroup | UnixFileMode.SetUser | (PlatformDetection.IsBsdLike ? UnixFileMode.StickyBit : UnixFileMode.None);
            UnixFileMode expectedMode   = mode & ~GetUmask() & ~platformFilter;

            Assert.Equal(expectedMode, dir.UnixFileMode);
        }
        public void MissingParentsHaveDefaultPermissions()
        {
            string parent = GetRandomDirPath();
            string child  = Path.Combine(parent, "child");

            const UnixFileMode childMode = UnixFileMode.UserRead | UnixFileMode.UserExecute;
            DirectoryInfo      childDir  = Directory.CreateDirectory(child, childMode);

            Assert.Equal(childMode, childDir.UnixFileMode);

            UnixFileMode defaultPermissions = Directory.CreateDirectory(GetRandomDirPath()).UnixFileMode;

            Assert.Equal(defaultPermissions, File.GetUnixFileMode(parent));
        }
Пример #10
0
        public void SetThenGet(UnixFileMode mode)
        {
            if (GetModeNeedsReadableFile)
            {
                // Ensure the file remains readable.
                mode |= UnixFileMode.UserRead;
            }

            string path = CreateTestItem();

            SetMode(path, mode);

            Assert.Equal(mode, GetMode(path));
        }
Пример #11
0
        public void CreateDoesntChangeExistingUnixFileMode(FileMode fileMode)
        {
            // Create file as writable for user only.
            const UnixFileMode mode     = UnixFileMode.UserWrite;
            string             filename = GetTestFilePath();

            CreateFileStream(filename, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0, mode).Dispose();

            // Now open with AllAccess.
            using FileStream fs = CreateFileStream(filename, fileMode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0, AllAccess);
            UnixFileMode actualMode = File.GetUnixFileMode(filename);

            Assert.Equal(mode, actualMode);
        }
Пример #12
0
        private static DirectoryInfo CreateDirectoryCore(string path, UnixFileMode unixCreateMode)
        {
            ArgumentException.ThrowIfNullOrEmpty(path);

            if ((unixCreateMode & ~FileSystem.ValidUnixFileModes) != 0)
            {
                throw new ArgumentException(SR.Arg_InvalidUnixFileMode, nameof(unixCreateMode));
            }

            string fullPath = Path.GetFullPath(path);

            FileSystem.CreateDirectory(fullPath, unixCreateMode);

            return(new DirectoryInfo(path, fullPath, isNormalized: true));
        }
Пример #13
0
        public void CreateWithUnixFileMode(UnixFileMode mode)
        {
            string     filename = GetTestFilePath();
            FileStream fs       = CreateFileStream(filename, FileMode.CreateNew, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0, mode);

            fs.Dispose();

            UnixFileMode platformFilter = PlatformDetection.IsBsdLike
                                            ? (UnixFileMode.SetGroup | UnixFileMode.SetUser | UnixFileMode.StickyBit)
                                            : UnixFileMode.None;
            UnixFileMode expectedMode = mode & ~GetUmask() & ~platformFilter;
            UnixFileMode actualMode   = File.GetUnixFileMode(filename);

            Assert.Equal(expectedMode, actualMode);
        }
Пример #14
0
        private void SetUnixFileMode(SafeFileHandle?handle, string?path, UnixFileMode mode)
        {
            if ((mode & ~FileSystem.ValidUnixFileModes) != 0)
            {
                throw new ArgumentException(SR.Arg_InvalidUnixFileMode, nameof(UnixFileMode));
            }

            // Linux does not support link permissions.
            // To have consistent cross-platform behavior we operate on the link target.
            int rv = handle is not null?Interop.Sys.FChMod(handle, (int)mode)
                         : Interop.Sys.ChMod(path !, (int)mode);

            Interop.CheckIo(rv, path);

            InvalidateCaches();
        }
Пример #15
0
        public void UnixCreateModeThrowsForNonCreatingFileModes(FileMode fileMode, bool canSetUnixCreateMode)
        {
            const UnixFileMode unixMode = UnixFileMode.UserWrite;
            string             filename = GetTestFilePath();

            if (canSetUnixCreateMode)
            {
                CreateFileStream(filename, fileMode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0, unixMode).Dispose();

                UnixFileMode actualMode = File.GetUnixFileMode(filename);
                Assert.Equal(unixMode, actualMode);
            }
            else
            {
                Assert.Throws <ArgumentException>(() => CreateFileStream(filename, fileMode, FileAccess.Write, FileShare.None, bufferSize: 1, FileOptions.None, preallocationSize: 0, unixMode));
            }
        }
Пример #16
0
 protected static UnixFileMode GetUmask()
 {
     if (s_umask == (UnixFileMode)(-1))
     {
         // The umask can't be retrieved without changing it.
         // We launch a child process to get its value.
         using Process px = Process.Start(new ProcessStartInfo
         {
             FileName               = "/bin/sh",
             ArgumentList           = { "-c", "umask" },
             RedirectStandardOutput = true
         });
         string stdout = px.StandardOutput.ReadToEnd().Trim();
         s_umask = (UnixFileMode)Convert.ToInt32(stdout, 8);
     }
     return(s_umask);
 }
Пример #17
0
        protected void VerifyPlatformSpecificMetadata(string filePath, TarEntry entry)
        {
            Interop.Sys.FileStatus status = default;
            status.Mode = default;
            status.Dev  = default;
            Interop.CheckIo(Interop.Sys.LStat(filePath, out status));

            Assert.Equal((int)status.Uid, entry.Uid);
            Assert.Equal((int)status.Gid, entry.Gid);

            if (entry is PosixTarEntry posix)
            {
                string gname = Interop.Sys.GetGroupName(status.Gid);
                string uname = Interop.Sys.GetUserNameFromPasswd(status.Uid);

                Assert.Equal(gname, posix.GroupName);
                Assert.Equal(uname, posix.UserName);

                if (entry.EntryType is not TarEntryType.BlockDevice and not TarEntryType.CharacterDevice)
                {
                    Assert.Equal(DefaultDeviceMajor, posix.DeviceMajor);
                    Assert.Equal(DefaultDeviceMinor, posix.DeviceMinor);
                }
            }

            if (entry.EntryType is not TarEntryType.Directory)
            {
                UnixFileMode expectedMode = (UnixFileMode)(status.Mode & 4095); // First 12 bits

                Assert.Equal(expectedMode, entry.Mode);
                Assert.True(entry.ModificationTime > DateTimeOffset.UnixEpoch);

                if (entry is PaxTarEntry pax)
                {
                    VerifyExtendedAttributeTimestamps(pax);
                }

                if (entry is GnuTarEntry gnu)
                {
                    VerifyGnuTimestamps(gnu);
                }
            }
        }
Пример #18
0
        public void SetThenGet_SymbolicLink(UnixFileMode mode)
        {
            if (GetModeNeedsReadableFile)
            {
                // Ensure the file remains readable.
                mode |= UnixFileMode.UserRead;
            }

            string path = CreateTestItem();

            string linkPath = GetTestFilePath();

            File.CreateSymbolicLink(linkPath, path);

            SetMode(linkPath, mode);

            Assert.Equal(mode, GetMode(linkPath));
            Assert.Equal(mode, GetMode(path));
        }
Пример #19
0
        public void Get()
        {
            string path = CreateTestItem();

            UnixFileMode mode = GetMode(path); // Doesn't throw.

            Assert.NotEqual((UnixFileMode)(-1), mode);

            UnixFileMode required = UnixFileMode.UserRead | UnixFileMode.UserWrite;

            if (IsDirectory)
            {
                required |= UnixFileMode.UserExecute;
            }
            Assert.True((mode & required) == required);

            if (!PlatformDetection.IsBrowser)
            {
                // The umask should prevent this file from being writable by others.
                Assert.Equal(UnixFileMode.None, mode & UnixFileMode.OtherWrite);
            }
        }
Пример #20
0
        /// <summary>
        /// Gets the file type from the mode
        /// </summary>
        /// <param name="mode">the file mode flags</param>
        /// <returns></returns>
        private static FileTypes GetFileType(UnixFileMode mode)
        {
            if ((mode & UnixFileMode.Socket) == UnixFileMode.Socket)
            {
                return(FileListingService.FileTypes.Socket);
            }

            if ((mode & UnixFileMode.SymbolicLink) == UnixFileMode.SymbolicLink)
            {
                return(FileListingService.FileTypes.Link);
            }

            if ((mode & UnixFileMode.Regular) == UnixFileMode.Regular)
            {
                return(FileListingService.FileTypes.File);
            }

            if ((mode & UnixFileMode.Block) == UnixFileMode.Block)
            {
                return(FileListingService.FileTypes.Block);
            }

            if ((mode & UnixFileMode.Directory) == UnixFileMode.Directory)
            {
                return(FileListingService.FileTypes.Directory);
            }

            if ((mode & UnixFileMode.Character) == UnixFileMode.Character)
            {
                return(FileListingService.FileTypes.Character);
            }

            if ((mode & UnixFileMode.FIFO) == UnixFileMode.FIFO)
            {
                return(FileListingService.FileTypes.FIFO);
            }

            return(FileListingService.FileTypes.Other);
        }
        /// <summary>
        /// Creates a file on the file system with the entry?s contents and the specified name.
        /// The last write time of the file is set to the entry?s last write time.
        /// This method does allows overwriting of an existing file with the same name.
        /// </summary>
        ///
        /// <exception cref="UnauthorizedAccessException">The caller does not have the required permission.</exception>
        /// <exception cref="ArgumentException">destinationFileName is a zero-length string, contains only whitespace,
        /// or contains one or more invalid characters as defined by InvalidPathChars. -or- destinationFileName specifies a directory.</exception>
        /// <exception cref="ArgumentNullException">destinationFileName is null.</exception>
        /// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length.
        /// For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.</exception>
        /// <exception cref="DirectoryNotFoundException">The path specified in destinationFileName is invalid
        /// (for example, it is on an unmapped drive).</exception>
        /// <exception cref="IOException">An I/O error has occurred.
        /// -or- The entry is currently open for writing.
        /// -or- The entry has been deleted from the archive.</exception>
        /// <exception cref="NotSupportedException">destinationFileName is in an invalid format
        /// -or- The ZipArchive that this entry belongs to was opened in a write-only mode.</exception>
        /// <exception cref="InvalidDataException">The entry is missing from the archive or is corrupt and cannot be read
        /// -or- The entry has been compressed using a compression method that is not supported.</exception>
        /// <exception cref="ObjectDisposedException">The ZipArchive that this entry belongs to has been disposed.</exception>
        /// <param name="source">The zip archive entry to extract a file from.</param>
        /// <param name="destinationFileName">The name of the file that will hold the contents of the entry.
        /// The path is permitted to specify relative or absolute path information.
        /// Relative path information is interpreted as relative to the current working directory.</param>
        /// <param name="overwrite">True to indicate overwrite.</param>
        public static void ExtractToFile(this ZipArchiveEntry source, string destinationFileName, bool overwrite)
        {
            ArgumentNullException.ThrowIfNull(source);
            ArgumentNullException.ThrowIfNull(destinationFileName);

            FileStreamOptions fileStreamOptions = new()
            {
                Access     = FileAccess.Write,
                Mode       = overwrite ? FileMode.Create : FileMode.CreateNew,
                Share      = FileShare.None,
                BufferSize = 0x1000
            };

            const UnixFileMode OwnershipPermissions =
                UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
                UnixFileMode.GroupRead | UnixFileMode.GroupWrite | UnixFileMode.GroupExecute |
                UnixFileMode.OtherRead | UnixFileMode.OtherWrite | UnixFileMode.OtherExecute;

            // Restore Unix permissions.
            // For security, limit to ownership permissions, and respect umask (through UnixCreateMode).
            // We don't apply UnixFileMode.None because .zip files created on Windows and .zip files created
            // with previous versions of .NET don't include permissions.
            UnixFileMode mode = (UnixFileMode)(source.ExternalAttributes >> 16) & OwnershipPermissions;

            if (mode != UnixFileMode.None && !OperatingSystem.IsWindows())
            {
                fileStreamOptions.UnixCreateMode = mode;
            }

            using (FileStream fs = new FileStream(destinationFileName, fileStreamOptions))
            {
                using (Stream es = source.Open())
                    es.CopyTo(fs);
            }

            ArchivingUtils.AttemptSetLastWriteTime(destinationFileName, source.LastWriteTime);
        }
Пример #22
0
        public void CreateTempSubdirectory(string prefix)
        {
            DirectoryInfo tmpDir = Directory.CreateTempSubdirectory(prefix);

            try
            {
                Assert.True(tmpDir.Exists);
                Assert.Equal(-1, tmpDir.FullName.IndexOfAny(Path.GetInvalidPathChars()));
                Assert.Empty(Directory.GetFileSystemEntries(tmpDir.FullName));
                Assert.Equal(Path.TrimEndingDirectorySeparator(Path.GetTempPath()), tmpDir.Parent.FullName);

                if (!string.IsNullOrEmpty(prefix))
                {
                    Assert.StartsWith(prefix, tmpDir.Name);
                    int expectedNameLength = prefix.Length + (OperatingSystem.IsWindows() ? 12 : 6);
                    Assert.Equal(expectedNameLength, tmpDir.Name.Length);
                }

                if (!OperatingSystem.IsWindows())
                {
                    UnixFileMode userRWX = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute;
                    Assert.Equal(userRWX, tmpDir.UnixFileMode);
                }

                // Ensure a file can be written to the directory
                string tempFile = Path.Combine(tmpDir.FullName, "newFile");
                using (FileStream fs = File.Create(tempFile, bufferSize: 1024, FileOptions.DeleteOnClose))
                {
                    Assert.Equal(0, fs.Length);
                }
            }
            finally
            {
                tmpDir.Delete(recursive: true);
            }
        }
        /// <summary>
        /// Checks the store directory has the correct permissions.
        /// </summary>
        /// <param name="path">
        /// The path of the directory to check.
        /// </param>
        /// <param name="userId">
        /// The current userId from GetEUid().
        /// </param>
        private static void EnsureDirectoryPermissions(string path, uint userId)
        {
            Interop.Sys.FileStatus dirStat;
            if (Interop.Sys.Stat(path, out dirStat) != 0)
            {
                Interop.ErrorInfo error = Interop.Sys.GetLastErrorInfo();
                throw new CryptographicException(
                          SR.Cryptography_FileStatusError,
                          new IOException(error.GetErrorMessage(), error.RawErrno));
            }

            if (dirStat.Uid != userId)
            {
                throw new CryptographicException(SR.Format(SR.Cryptography_OwnerNotCurrentUser, path));
            }

            const UnixFileMode UserReadWriteExecute = UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute;
            UnixFileMode       permissions          = File.GetUnixFileMode(path);

            if ((permissions & UserReadWriteExecute) != UserReadWriteExecute)
            {
                throw new CryptographicException(SR.Format(SR.Cryptography_InvalidDirectoryPermissions, path));
            }
        }
Пример #24
0
 /// <summary>
 /// Opens a UNIX file.
 /// </summary>
 /// <param name="fileName">The filepath.</param>
 /// <param name="fileMode">The file access mode.</param>
 /// <returns>A opened file.</returns>
 public static IFile Open(string fileName, UnixFileMode fileMode) {
     return new UnixFile(fileName, fileMode);
 }
Пример #25
0
 public static extern SafeUnixHandle Open(string path, uint flags, UnixFileMode mode);
Пример #26
0
 protected override FileStream CreateFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, long preallocationSize, UnixFileMode unixFileMode)
 => new FileInfo(path).Open(
     new FileStreamOptions {
     Mode              = mode,
     Access            = access,
     Share             = share,
     BufferSize        = bufferSize,
     Options           = options,
     PreallocationSize = preallocationSize,
     UnixCreateMode    = unixFileMode
 });
Пример #27
0
        public void VerifyIncludeBaseDirectory(bool includeBaseDirectory)
        {
            using TempDirectory source      = new TempDirectory();
            using TempDirectory destination = new TempDirectory();

            UnixFileMode baseDirectoryMode = TestPermission1;

            SetUnixFileMode(source.Path, baseDirectoryMode);

            string fileName1 = "file1.txt";
            string filePath1 = Path.Join(source.Path, fileName1);

            File.Create(filePath1).Dispose();
            UnixFileMode filename1Mode = TestPermission2;

            SetUnixFileMode(filePath1, filename1Mode);

            string subDirectoryName = "dir/"; // The trailing separator is preserved in the TarEntry.Name
            string subDirectoryPath = Path.Join(source.Path, subDirectoryName);

            Directory.CreateDirectory(subDirectoryPath);
            UnixFileMode subDirectoryMode = TestPermission3;

            SetUnixFileMode(subDirectoryPath, subDirectoryMode);

            string fileName2 = "file2.txt";
            string filePath2 = Path.Join(subDirectoryPath, fileName2);

            File.Create(filePath2).Dispose();
            UnixFileMode filename2Mode = TestPermission4;

            SetUnixFileMode(filePath2, filename2Mode);

            string destinationArchiveFileName = Path.Join(destination.Path, "output.tar");

            TarFile.CreateFromDirectory(source.Path, destinationArchiveFileName, includeBaseDirectory);

            using FileStream fileStream = File.OpenRead(destinationArchiveFileName);
            using TarReader reader      = new TarReader(fileStream);

            List <TarEntry> entries = new List <TarEntry>();

            TarEntry entry;

            while ((entry = reader.GetNextEntry()) != null)
            {
                entries.Add(entry);
            }

            int expectedCount = 3 + (includeBaseDirectory ? 1 : 0);

            Assert.Equal(expectedCount, entries.Count);

            string prefix = includeBaseDirectory ? Path.GetFileName(source.Path) + '/' : string.Empty;

            if (includeBaseDirectory)
            {
                TarEntry baseEntry = entries.FirstOrDefault(x =>
                                                            x.EntryType == TarEntryType.Directory &&
                                                            x.Name == prefix);
                Assert.NotNull(baseEntry);
                AssertEntryModeFromFileSystemEquals(baseEntry, baseDirectoryMode);
            }

            TarEntry entry1 = entries.FirstOrDefault(x =>
                                                     x.EntryType == TarEntryType.RegularFile &&
                                                     x.Name == prefix + fileName1);

            Assert.NotNull(entry1);
            AssertEntryModeFromFileSystemEquals(entry1, filename1Mode);

            TarEntry directory = entries.FirstOrDefault(x =>
                                                        x.EntryType == TarEntryType.Directory &&
                                                        x.Name == prefix + subDirectoryName);

            Assert.NotNull(directory);
            AssertEntryModeFromFileSystemEquals(directory, subDirectoryMode);

            string   actualFileName2 = subDirectoryName + fileName2; // Notice the trailing separator in subDirectoryName
            TarEntry entry2          = entries.FirstOrDefault(x =>
                                                              x.EntryType == TarEntryType.RegularFile &&
                                                              x.Name == prefix + actualFileName2);

            Assert.NotNull(entry2);
            AssertEntryModeFromFileSystemEquals(entry2, filename2Mode);
        }
        private void AddCertToStore(ICertificatePal certPal)
        {
            // This may well be the first time that we've added something to this store.
            Directory.CreateDirectory(_storePath);

            uint userId = Interop.Sys.GetEUid();

            EnsureDirectoryPermissions(_storePath, userId);

            OpenSslX509CertificateReader cert = (OpenSslX509CertificateReader)certPal;

            using (X509Certificate2 copy = new X509Certificate2(cert.DuplicateHandles()))
            {
                string thumbprint = copy.Thumbprint;
                bool   findOpenSlot;

                // The odds are low that we'd have a thumbprint collision, but check anyways.
                string?existingFilename = FindExistingFilename(copy, _storePath, out findOpenSlot);

                if (existingFilename != null)
                {
                    if (!copy.HasPrivateKey)
                    {
                        return;
                    }

                    try
                    {
                        using (X509Certificate2 fromFile = new X509Certificate2(existingFilename))
                        {
                            if (fromFile.HasPrivateKey)
                            {
                                // We have a private key, the file has a private key, we're done here.
                                return;
                            }
                        }
                    }
                    catch (CryptographicException)
                    {
                        // We can't read this file anymore, but a moment ago it was this certificate,
                        // so go ahead and overwrite it.
                    }
                }

                const UnixFileMode UserReadWrite = UnixFileMode.UserRead | UnixFileMode.UserWrite;

                string            destinationFilename;
                FileStreamOptions options = new()
                {
                    Mode           = FileMode.CreateNew,
                    UnixCreateMode = UserReadWrite,
                    Access         = FileAccess.Write
                };

                if (existingFilename != null)
                {
                    destinationFilename = existingFilename;
                    options.Mode        = FileMode.Create;

                    // Before we open the file for writing the certificate,
                    // ensure it is only accessible to the owner.
                    try
                    {
                        File.SetUnixFileMode(existingFilename, UserReadWrite);
                    }
                    catch (IOException) // Ignore errors. We verify permissions when we've opened the file.
                    { }
                }
                else if (findOpenSlot)
                {
                    destinationFilename = FindOpenSlot(thumbprint);
                }
                else
                {
                    destinationFilename = Path.Combine(_storePath, thumbprint + PfxExtension);
                }

                using (FileStream stream = new FileStream(destinationFilename, options))
                {
                    // Verify the file can only be read/written to by the owner.
                    UnixFileMode actualMode = File.GetUnixFileMode(stream.SafeFileHandle);
                    if (actualMode != UserReadWrite)
                    {
                        throw new CryptographicException(SR.Format(SR.Cryptography_InvalidFilePermissions, stream.Name));
                    }

                    byte[] pkcs12 = copy.Export(X509ContentType.Pkcs12) !;
                    stream.Write(pkcs12, 0, pkcs12.Length);
                }
            }
        }
Пример #29
0
 /// <summary>
 /// Opens a UNIX file and returns the file descriptor.
 /// </summary>
 /// <param name="fileName">The filepath.</param>
 /// <param name="fileMode">The file access mode.</param>
 /// <returns>The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.</returns>
 public static int OpenFileDescriptor(string fileName, UnixFileMode fileMode) {
     var mode = unchecked ((int) fileMode);
     return open(fileName, mode);
 }
Пример #30
0
 internal void SetUnixFileMode(SafeFileHandle handle, UnixFileMode mode)
 => SetUnixFileMode(handle, handle.Path, mode);
Пример #31
0
 internal void SetUnixFileMode(string path, UnixFileMode mode)
 => SetUnixFileMode(handle: null, path, mode);
Пример #32
0
 public static void SetUnixFileMode(SafeFileHandle fileHandle, UnixFileMode mode)
 => SetUnixFileModeCore(fileHandle, mode);
Пример #33
0
        /// <summary>
        /// Gets the file type from the mode
        /// </summary>
        /// <param name="mode">the file mode flags</param>
        /// <returns></returns>
        private static FileTypes GetFileType(UnixFileMode mode)
        {
            if ((mode & UnixFileMode.Socket) == UnixFileMode.Socket)
            {
                return FileListingService.FileTypes.Socket;
            }

            if ((mode & UnixFileMode.SymbolicLink) == UnixFileMode.SymbolicLink)
            {
                return FileListingService.FileTypes.Link;
            }

            if ((mode & UnixFileMode.Regular) == UnixFileMode.Regular)
            {
                return FileListingService.FileTypes.File;
            }

            if ((mode & UnixFileMode.Block) == UnixFileMode.Block)
            {
                return FileListingService.FileTypes.Block;
            }

            if ((mode & UnixFileMode.Directory) == UnixFileMode.Directory)
            {
                return FileListingService.FileTypes.Directory;
            }

            if ((mode & UnixFileMode.Character) == UnixFileMode.Character)
            {
                return FileListingService.FileTypes.Character;
            }

            if ((mode & UnixFileMode.FIFO) == UnixFileMode.FIFO)
            {
                return FileListingService.FileTypes.FIFO;
            }

            return FileListingService.FileTypes.Other;
        }
Пример #34
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UnixFile"/> class.
 /// </summary>
 /// <param name="filename">A pathname for the file.</param>
 /// <param name="fileMode">The file access mode.</param>
 public UnixFile(string filename, UnixFileMode fileMode)
     :this(OpenFileDescriptor(filename, fileMode)) {
     this.filename = filename;
 }