/// <summary>
        /// Adds a directory entry to the <see cref="CpioFile"/>.
        /// </summary>
        /// <param name="entry">
        /// The <see cref="ArchiveEntry"/> which represents the directory.
        /// </param>
        /// <param name="cpioFile">
        /// The <see cref="CpioFile"/> to which to add the directory entry.
        /// </param>
        public void AddDirectory(ArchiveEntry entry, CpioFile cpioFile)
        {
            // Write out an entry for the current directory
            CpioHeader directoryHeader = new CpioHeader()
            {
                Check        = 0,
                DevMajor     = 1,
                DevMinor     = 0,
                FileSize     = 0,
                Gid          = 0,
                Ino          = entry.Inode,
                FileMode     = entry.Mode,
                LastModified = entry.Modified,
                Nlink        = 1,
                RDevMajor    = 0,
                RDevMinor    = 0,
                Signature    = "070701",
                Uid          = 0,
                NameSize     = 0
            };

            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            cpioFile.Write(directoryHeader, targetPath, new MemoryStream(Array.Empty <byte>()));
        }
        /// <summary>
        /// Adds a file entry to a <see cref="CpioFile"/>.
        /// </summary>
        /// <param name="entry">
        /// The file entry to add.
        /// </param>
        /// <param name="cpioFile">
        /// The <see cref="CpioFile"/> to which to add the entry.
        /// </param>
        public void AddFile(ArchiveEntry entry, CpioFile cpioFile)
        {
            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            using (Stream fileStream = File.OpenRead(entry.SourceFilename))
            {
                CpioHeader cpioHeader = new CpioHeader()
                {
                    Check        = 0,
                    DevMajor     = 1,
                    DevMinor     = 0,
                    FileSize     = entry.FileSize,
                    Gid          = 0, // root
                    Uid          = 0, // root
                    Ino          = entry.Inode,
                    FileMode     = entry.Mode,
                    LastModified = entry.Modified,
                    NameSize     = (uint)entry.TargetPath.Length + 1,
                    Nlink        = 1,
                    RDevMajor    = 0,
                    RDevMinor    = 0,
                    Signature    = "070701",
                };

                cpioFile.Write(cpioHeader, targetPath, fileStream);
            }
        }
        /// <summary>
        /// Adds a symlink entry to a <see cref="CpioFile"/>.
        /// </summary>
        /// <param name="entry">
        /// The symlink entry to add.
        /// </param>
        /// <param name="cpioFile">
        /// The <see cref="CpioFile"/> to which to add the entry.
        /// </param>
        public void AddSymlink(ArchiveEntry entry, CpioFile cpioFile)
        {
            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            CpioHeader cpioHeader = new CpioHeader()
            {
                Check        = 0,
                DevMajor     = 1,
                DevMinor     = 0,
                FileSize     = entry.FileSize,
                Gid          = 0, // root
                Uid          = 0, // root
                Ino          = entry.Inode,
                FileMode     = entry.Mode,
                LastModified = entry.Modified,
                NameSize     = (uint)entry.TargetPath.Length + 1,
                Nlink        = 1,
                RDevMajor    = 0,
                RDevMinor    = 0,
                Signature    = "070701",
            };

            cpioFile.Write(cpioHeader, targetPath, new MemoryStream(Encoding.UTF8.GetBytes(entry.LinkTo)));
        }
Beispiel #4
0
        public static void WriteEntry(Stream stream, ArchiveEntry entry, Stream data = null)
        {
            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            // Handle long file names (> 99 characters). If this is the case, add a "././@LongLink" pseudo-entry
            // which contains the full name.
            if (targetPath.Length > 99)
            {
                // Must include a trailing \0
                var    nameLength = Encoding.UTF8.GetByteCount(targetPath);
                byte[] entryName  = new byte[nameLength + 1];

                Encoding.UTF8.GetBytes(targetPath, 0, targetPath.Length, entryName, 0);

                ArchiveEntry nameEntry = new ArchiveEntry()
                {
                    Mode       = entry.Mode,
                    Modified   = entry.Modified,
                    TargetPath = "././@LongLink",
                    Owner      = entry.Owner,
                    Group      = entry.Group
                };

                using (MemoryStream nameStream = new MemoryStream(entryName))
                {
                    WriteEntry(stream, nameEntry, nameStream);
                }

                targetPath = targetPath.Substring(0, 99);
            }

            var isDir  = entry.Mode.HasFlag(LinuxFileMode.S_IFDIR);
            var isLink = !isDir && !string.IsNullOrWhiteSpace(entry.LinkTo);
            var isFile = !isDir && !isLink;

            TarTypeFlag type;

            if (entry.TargetPath == "././@LongLink")
            {
                type = TarTypeFlag.LongName;
            }
            else if (isFile)
            {
                type = TarTypeFlag.RegType;
            }
            else if (isDir)
            {
                type = TarTypeFlag.DirType;
            }
            else
            {
                type = TarTypeFlag.LnkType;
            }

            bool dispose = false;

            if (data == null)
            {
                if (isFile)
                {
                    dispose = true;
                    data    = File.OpenRead(entry.SourceFilename);
                }
                else
                {
                    data = new MemoryStream();
                }
            }

            try
            {
                var hdr = new TarHeader()
                {
                    // No need to set the file type, the tar header has a special field for that.
                    FileMode     = entry.Mode & LinuxFileMode.PermissionsMask,
                    DevMajor     = null,
                    DevMinor     = null,
                    FileName     = targetPath,
                    FileSize     = (uint)data.Length,
                    GroupId      = 0,
                    UserId       = 0,
                    GroupName    = entry.Group,
                    LinkName     = string.Empty,
                    Prefix       = string.Empty,
                    TypeFlag     = type,
                    UserName     = entry.Owner,
                    Version      = null,
                    LastModified = entry.Modified,
                    Magic        = "ustar"
                };
                WriteEntry(stream, hdr, data);
            }
            finally
            {
                if (dispose)
                {
                    data.Dispose();
                }
            }
        }
        public static void WriteEntry(Stream stream, ArchiveEntry entry, Stream data = null)
        {
            var targetPath = entry.TargetPath;

            if (!targetPath.StartsWith("."))
            {
                targetPath = "." + targetPath;
            }

            var isDir  = entry.Mode.HasFlag(LinuxFileMode.S_IFDIR);
            var isLink = !isDir && !string.IsNullOrWhiteSpace(entry.LinkTo);
            var isFile = !isDir && !isLink;
            var type   = isFile
                ? TarTypeFlag.RegType
                : isDir
                    ? TarTypeFlag.DirType
                    : TarTypeFlag.LnkType;

            bool dispose = false;

            if (data == null)
            {
                if (isFile)
                {
                    dispose = true;
                    data    = File.OpenRead(entry.SourceFilename);
                }
                else
                {
                    data = new MemoryStream();
                }
            }

            try
            {
                var hdr = new TarHeader()
                {
                    FileMode     = entry.Mode,
                    DevMajor     = null,
                    DevMinor     = null,
                    FileName     = targetPath,
                    FileSize     = (uint)data.Length,
                    GroupId      = 0,
                    UserId       = 0,
                    GroupName    = entry.Group,
                    LinkName     = string.Empty,
                    Prefix       = string.Empty,
                    TypeFlag     = type,
                    UserName     = entry.Owner,
                    Version      = null,
                    LastModified = entry.Modified,
                    Magic        = "ustar"
                };
                WriteEntry(stream, hdr, data);
            }
            finally
            {
                if (dispose)
                {
                    data.Dispose();
                }
            }
        }