diff --git a/AMWD.Common/Packing/Ar/ArReader.cs b/AMWD.Common/Packing/Ar/ArReader.cs index a260bb6..28b2e41 100644 --- a/AMWD.Common/Packing/Ar/ArReader.cs +++ b/AMWD.Common/Packing/Ar/ArReader.cs @@ -13,11 +13,9 @@ namespace AMWD.Common.Packing.Ar { // Source: http://en.wikipedia.org/wiki/Ar_%28Unix%29 - private readonly Stream inStream; - private readonly List files = new(); - private readonly long streamStartPosition; - - private static readonly DateTime unixEpoch = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + private readonly Stream _inStream; + private readonly List _files = new(); + private readonly long _streamStartPosition; /// /// Initializes a new instance of the class. @@ -28,8 +26,8 @@ namespace AMWD.Common.Packing.Ar if (!inStream.CanRead || !inStream.CanSeek) throw new ArgumentException("Stream not readable or seekable", nameof(inStream)); - streamStartPosition = inStream.Position; - this.inStream = inStream; + _streamStartPosition = inStream.Position; + _inStream = inStream; Initialize(); } @@ -38,9 +36,7 @@ namespace AMWD.Common.Packing.Ar /// Returns a list with all filenames of the archive. /// public IEnumerable GetFileList() - { - return files.Select(fi => fi.FileName).ToList(); - } + => _files.Select(fi => fi.FileName).ToList(); /// /// Returns the file info of a specific file in the archive. @@ -48,7 +44,7 @@ namespace AMWD.Common.Packing.Ar /// The name of the specific file. public ArFileInfo GetFileInfo(string fileName) { - return files + return _files .Where(fi => fi.FileName == fileName) .Select(fi => new ArFileInfo { @@ -72,23 +68,23 @@ namespace AMWD.Common.Packing.Ar if (!outStream.CanWrite) throw new ArgumentException("Stream not writable", nameof(outStream)); - var info = files.Where(fi => fi.FileName == fileName).FirstOrDefault(); + var info = _files.Where(fi => fi.FileName == fileName).FirstOrDefault(); if (info == null) return; long bytesToRead = info.FileSize; byte[] buffer = new byte[1024 * 1024]; - inStream.Seek(info.DataPosition, SeekOrigin.Begin); + _inStream.Seek(info.DataPosition, SeekOrigin.Begin); while (bytesToRead > 0) { int readCount = (int)Math.Min(bytesToRead, buffer.Length); - inStream.Read(buffer, 0, readCount); + _inStream.Read(buffer, 0, readCount); outStream.Write(buffer, 0, readCount); bytesToRead -= readCount; } - inStream.Seek(streamStartPosition, SeekOrigin.Begin); + _inStream.Seek(_streamStartPosition, SeekOrigin.Begin); } /// @@ -98,7 +94,7 @@ namespace AMWD.Common.Packing.Ar /// The destination path on disk. public void ReadFile(string fileName, string destinationPath) { - var info = files.Where(fi => fi.FileName == fileName).FirstOrDefault(); + var info = _files.Where(fi => fi.FileName == fileName).FirstOrDefault(); if (info == null) return; @@ -112,7 +108,7 @@ namespace AMWD.Common.Packing.Ar private void Initialize() { // Reset stream - inStream.Seek(streamStartPosition, SeekOrigin.Begin); + _inStream.Seek(_streamStartPosition, SeekOrigin.Begin); // Read header string header = ReadAsciiString(8); @@ -120,33 +116,33 @@ namespace AMWD.Common.Packing.Ar throw new FormatException("The file stream is no archive"); // Create file list - while (inStream.Position < inStream.Length) + while (_inStream.Position < _inStream.Length) { var info = ReadFileHeader(); - files.Add(info); + _files.Add(info); // Move stream behind file content - inStream.Seek(info.FileSize, SeekOrigin.Current); + _inStream.Seek(info.FileSize, SeekOrigin.Current); // Align to even offsets (padded with LF bytes) - if (inStream.Position % 2 != 0) - inStream.Seek(1, SeekOrigin.Current); + if (_inStream.Position % 2 != 0) + _inStream.Seek(1, SeekOrigin.Current); } // Reset stream - inStream.Seek(streamStartPosition, SeekOrigin.Begin); + _inStream.Seek(_streamStartPosition, SeekOrigin.Begin); } private string ReadAsciiString(int byteCount) { byte[] buffer = new byte[byteCount]; - inStream.Read(buffer, 0, byteCount); + _inStream.Read(buffer, 0, byteCount); return Encoding.ASCII.GetString(buffer); } private ArFileInfoExtended ReadFileHeader() { - long startPosition = inStream.Position; + long startPosition = _inStream.Position; string fileName = ReadAsciiString(16).Trim(); @@ -159,7 +155,7 @@ namespace AMWD.Common.Packing.Ar // file magic byte[] magic = new byte[2]; - inStream.Read(magic, 0, magic.Length); + _inStream.Read(magic, 0, magic.Length); if (magic[0] != 0x60 || magic[1] != 0x0A) // `\n throw new FormatException("Invalid file magic"); @@ -167,9 +163,9 @@ namespace AMWD.Common.Packing.Ar return new ArFileInfoExtended { HeaderPosition = startPosition, - DataPosition = inStream.Position, + DataPosition = _inStream.Position, FileName = fileName, - ModifyTime = unixEpoch.AddSeconds(unixTimestamp), + ModifyTime = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp).DateTime, UserId = userId, GroupId = groupId, Mode = mode, diff --git a/AMWD.Common/Packing/Ar/ArWriter.cs b/AMWD.Common/Packing/Ar/ArWriter.cs index 321149c..c871079 100644 --- a/AMWD.Common/Packing/Ar/ArWriter.cs +++ b/AMWD.Common/Packing/Ar/ArWriter.cs @@ -14,8 +14,7 @@ namespace AMWD.Common.Packing.Ar { // Source: http://en.wikipedia.org/wiki/Ar_%28Unix%29 - private readonly Stream outStream; - private static readonly DateTime unixEpoch = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + private readonly Stream _outStream; /// /// Initialises a new instance of the class. @@ -26,7 +25,7 @@ namespace AMWD.Common.Packing.Ar if (!outStream.CanWrite) throw new ArgumentException("Stream not writable", nameof(outStream)); - this.outStream = outStream; + _outStream = outStream; Initialize(); } @@ -60,13 +59,13 @@ namespace AMWD.Common.Packing.Ar WriteFileHeader(fileName, modifyTime, userId, groupId, mode, stream.Length); // Write file contents - stream.CopyTo(outStream); + stream.CopyTo(_outStream); // Align to even offsets, pad with LF bytes - if ((outStream.Position % 2) != 0) + if ((_outStream.Position % 2) != 0) { byte[] bytes = new byte[] { 0x0A }; - outStream.Write(bytes, 0, 1); + _outStream.Write(bytes, 0, 1); } } @@ -90,7 +89,7 @@ namespace AMWD.Common.Packing.Ar WriteAsciiString(fileName.PadRight(16, ' ')); // File modification timestamp - int unixTime = (int)(modifyTime - unixEpoch).TotalSeconds; + long unixTime = ((DateTimeOffset)DateTime.SpecifyKind(modifyTime, DateTimeKind.Utc)).ToUnixTimeSeconds(); WriteAsciiString(unixTime.ToString().PadRight(12, ' ')); // User ID @@ -131,7 +130,7 @@ namespace AMWD.Common.Packing.Ar // File magic byte[] bytes = new byte[] { 0x60, 0x0A }; - outStream.Write(bytes, 0, 2); + _outStream.Write(bytes, 0, 2); } /// @@ -141,7 +140,7 @@ namespace AMWD.Common.Packing.Ar private void WriteAsciiString(string str) { byte[] bytes = Encoding.ASCII.GetBytes(str); - outStream.Write(bytes, 0, bytes.Length); + _outStream.Write(bytes, 0, bytes.Length); } } } diff --git a/AMWD.Common/Packing/Tar/TarReader.cs b/AMWD.Common/Packing/Tar/TarReader.cs index edb5bac..90de862 100644 --- a/AMWD.Common/Packing/Tar/TarReader.cs +++ b/AMWD.Common/Packing/Tar/TarReader.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Text; using AMWD.Common.Packing.Tar.Interfaces; using AMWD.Common.Packing.Tar.Utils; @@ -16,10 +14,10 @@ namespace AMWD.Common.Packing.Tar /// public class TarReader { - private readonly byte[] dataBuffer = new byte[512]; - private readonly UsTarHeader header; - private readonly Stream inStream; - private long remainingBytesInFile; + private readonly byte[] _dataBuffer = new byte[512]; + private readonly UsTarHeader _header; + private readonly Stream _inStream; + private long _remainingBytesInFile; /// /// Constructs TarReader object to read data from `tarredData` stream @@ -27,14 +25,11 @@ namespace AMWD.Common.Packing.Tar /// A stream to read tar archive from public TarReader(Stream tarredData) { - inStream = tarredData; - header = new UsTarHeader(); + _inStream = tarredData; + _header = new UsTarHeader(); } - public ITarHeader FileInfo - { - get { return header; } - } + public ITarHeader FileInfo => _header; /// /// Read all files from an archive to a directory. It creates some child directories to @@ -49,7 +44,7 @@ namespace AMWD.Common.Packing.Tar /// to your business logic. public void ReadToEnd(string destDirectory) { - while (MoveNext(false)) + while (MoveNext(skipData: false)) { string fileNameFromArchive = FileInfo.FileName; string totalPath = destDirectory + Path.DirectorySeparatorChar + fileNameFromArchive; @@ -59,14 +54,14 @@ namespace AMWD.Common.Packing.Tar Directory.CreateDirectory(totalPath); continue; } + // If record is a file string fileName = Path.GetFileName(totalPath); string directory = totalPath.Remove(totalPath.Length - fileName.Length); Directory.CreateDirectory(directory); - using (FileStream file = File.Create(totalPath)) - { - Read(file); - } + + using FileStream file = File.Create(totalPath); + Read(file); } } @@ -74,55 +69,57 @@ namespace AMWD.Common.Packing.Tar /// Read data from a current file to a Stream. /// /// A stream to read data to - /// /// public void Read(Stream dataDestanation) { - Debug.WriteLine("tar stream position Read in: " + inStream.Position); + Debug.WriteLine("tar stream position Read in: " + _inStream.Position); + int readBytes; - byte[] read; - while ((readBytes = Read(out read)) != -1) + while ((readBytes = Read(out byte[] read)) != -1) { - Debug.WriteLine("tar stream position Read while(...) : " + inStream.Position); + Debug.WriteLine("tar stream position Read while(...) : " + _inStream.Position); dataDestanation.Write(read, 0, readBytes); } - Debug.WriteLine("tar stream position Read out: " + inStream.Position); + + Debug.WriteLine("tar stream position Read out: " + _inStream.Position); } protected int Read(out byte[] buffer) { - if (remainingBytesInFile == 0) + if (_remainingBytesInFile == 0) { buffer = null; return -1; } + int align512 = -1; - long toRead = remainingBytesInFile - 512; + long toRead = _remainingBytesInFile - 512; if (toRead > 0) + { toRead = 512; + } else { - align512 = 512 - (int)remainingBytesInFile; - toRead = remainingBytesInFile; + align512 = 512 - (int)_remainingBytesInFile; + toRead = _remainingBytesInFile; } + int bytesRead = _inStream.Read(_dataBuffer, 0, (int)toRead); + _remainingBytesInFile -= bytesRead; - int bytesRead = inStream.Read(dataBuffer, 0, (int)toRead); - remainingBytesInFile -= bytesRead; - - if (inStream.CanSeek && align512 > 0) + if (_inStream.CanSeek && align512 > 0) { - inStream.Seek(align512, SeekOrigin.Current); + _inStream.Seek(align512, SeekOrigin.Current); } else while (align512 > 0) { - inStream.ReadByte(); + _inStream.ReadByte(); --align512; } - buffer = dataBuffer; + buffer = _dataBuffer; return bytesRead; } @@ -135,7 +132,8 @@ namespace AMWD.Common.Packing.Tar { foreach (byte b in buffer) { - if (b != 0) return false; + if (b != 0) + return false; } return true; } @@ -154,56 +152,52 @@ namespace AMWD.Common.Packing.Tar /// public bool MoveNext(bool skipData) { - Debug.WriteLine("tar stream position MoveNext in: " + inStream.Position); - if (remainingBytesInFile > 0) + Debug.WriteLine("tar stream position MoveNext in: " + _inStream.Position); + if (_remainingBytesInFile > 0) { if (!skipData) { throw new TarException( "You are trying to change file while not all the data from the previous one was read. If you do want to skip files use skipData parameter set to true."); } + // Skip to the end of file. - if (inStream.CanSeek) + if (_inStream.CanSeek) { - long remainer = (remainingBytesInFile % 512); - inStream.Seek(remainingBytesInFile + (512 - (remainer == 0 ? 512 : remainer)), SeekOrigin.Current); + long remainer = _remainingBytesInFile % 512; + _inStream.Seek(_remainingBytesInFile + (512 - (remainer == 0 ? 512 : remainer)), SeekOrigin.Current); } else { - byte[] buffer; - while (Read(out buffer) != -1) - { - } + while (Read(out _) != -1) ; } } - byte[] bytes = header.GetBytes(); + byte[] bytes = _header.GetBytes(); - int headerRead = inStream.Read(bytes, 0, header.HeaderSize); + int headerRead = _inStream.Read(bytes, 0, _header.HeaderSize); if (headerRead < 512) - { throw new TarException("Can not read header"); - } if (IsEmpty(bytes)) { - headerRead = inStream.Read(bytes, 0, header.HeaderSize); + headerRead = _inStream.Read(bytes, 0, _header.HeaderSize); if (headerRead == 512 && IsEmpty(bytes)) { - Debug.WriteLine("tar stream position MoveNext out(false): " + inStream.Position); + Debug.WriteLine("tar stream position MoveNext out(false): " + _inStream.Position); return false; } throw new TarException("Broken archive"); } - if (header.UpdateHeaderFromBytes()) + if (_header.UpdateHeaderFromBytes()) { throw new TarException("Checksum check failed"); } - remainingBytesInFile = header.SizeInBytes; + _remainingBytesInFile = _header.SizeInBytes; - Debug.WriteLine("tar stream position MoveNext out(true): " + inStream.Position); + Debug.WriteLine("tar stream position MoveNext out(true): " + _inStream.Position); return true; } } diff --git a/AMWD.Common/Packing/Tar/TarWriter.cs b/AMWD.Common/Packing/Tar/TarWriter.cs index 740864b..77c8f7b 100644 --- a/AMWD.Common/Packing/Tar/TarWriter.cs +++ b/AMWD.Common/Packing/Tar/TarWriter.cs @@ -8,9 +8,9 @@ namespace AMWD.Common.Packing.Tar // https://github.com/ygoe/DotnetMakeDeb/blob/v1.1.0/DotnetMakeDeb/Tar/TarWriter.cs public class TarWriter : LegacyTarWriter { - public TarWriter(Stream outStream) : base(outStream) - { - } + public TarWriter(Stream outStream) + : base(outStream) + { } protected override void WriteHeader(string name, DateTime lastModificationTime, long count, int userId, int groupId, int mode, EntryType entryType) { diff --git a/AMWD.Common/Packing/Tar/Utils/DataWriter.cs b/AMWD.Common/Packing/Tar/Utils/DataWriter.cs index 10a1b23..2401fcd 100644 --- a/AMWD.Common/Packing/Tar/Utils/DataWriter.cs +++ b/AMWD.Common/Packing/Tar/Utils/DataWriter.cs @@ -5,39 +5,39 @@ namespace AMWD.Common.Packing.Tar.Utils { internal class DataWriter : IArchiveDataWriter { - private readonly long size; - private long remainingBytes; - private readonly Stream stream; + private readonly long _size; + private long _remainingBytes; + private readonly Stream _stream; public DataWriter(Stream data, long dataSizeInBytes) { - size = dataSizeInBytes; - remainingBytes = size; - stream = data; + _size = dataSizeInBytes; + _remainingBytes = _size; + _stream = data; } public bool CanWrite { get; private set; } = true; public int Write(byte[] buffer, int count) { - if (remainingBytes == 0) + if (_remainingBytes == 0) { CanWrite = false; return -1; } int bytesToWrite; - if (remainingBytes - count < 0) + if (_remainingBytes - count < 0) { - bytesToWrite = (int)remainingBytes; + bytesToWrite = (int)_remainingBytes; } else { bytesToWrite = count; } - stream.Write(buffer, 0, bytesToWrite); - remainingBytes -= bytesToWrite; + _stream.Write(buffer, 0, bytesToWrite); + _remainingBytes -= bytesToWrite; return bytesToWrite; } diff --git a/AMWD.Common/Packing/Tar/Utils/LegacyTarWriter.cs b/AMWD.Common/Packing/Tar/Utils/LegacyTarWriter.cs index ad249aa..82612d0 100644 --- a/AMWD.Common/Packing/Tar/Utils/LegacyTarWriter.cs +++ b/AMWD.Common/Packing/Tar/Utils/LegacyTarWriter.cs @@ -14,10 +14,13 @@ namespace AMWD.Common.Packing.Tar.Utils /// public class LegacyTarWriter : IDisposable { - private readonly Stream outStream; + private readonly Stream _outStream; + private bool _isClosed; + + /// + /// The buffer for writing. + /// protected byte[] buffer = new byte[1024]; - private bool isClosed; - public bool ReadOnZero = true; /// /// Writes tar (see GNU tar) archive to a stream @@ -25,16 +28,25 @@ namespace AMWD.Common.Packing.Tar.Utils /// stream to write archive to public LegacyTarWriter(Stream outStream) { - this.outStream = outStream; + _outStream = outStream; } + /// + /// Gets or sets a value indicating whether to read on zero. + /// + public bool ReadOnZero { get; set; } = true; + + /// + /// Gets the output stream. + /// protected virtual Stream OutStream { - get { return outStream; } + get { return _outStream; } } #region IDisposable Members + /// public void Dispose() { Close(); @@ -85,13 +97,13 @@ namespace AMWD.Common.Packing.Tar.Utils WriteDirectoryEntry(directory, 0, 0, 0755); string[] files = Directory.GetFiles(directory); - foreach (var fileName in files) + foreach (string fileName in files) { Write(fileName); } string[] directories = Directory.GetDirectories(directory); - foreach (var dirName in directories) + foreach (string dirName in directories) { WriteDirectoryEntry(dirName, 0, 0, 0755); if (doRecursive) @@ -134,10 +146,9 @@ namespace AMWD.Common.Packing.Tar.Utils AlignTo512(dataSizeInBytes, false); } - public virtual void Write(Stream data, long dataSizeInBytes, string name, int userId, int groupId, int mode, - DateTime lastModificationTime) + public virtual void Write(Stream data, long dataSizeInBytes, string name, int userId, int groupId, int mode, DateTime lastModificationTime) { - if (isClosed) + if (_isClosed) throw new TarException("Can not write to the closed writer"); // handle long file names (> 99 characters) @@ -172,7 +183,7 @@ namespace AMWD.Common.Packing.Tar.Utils private void WriteLongName(string name, int userId, int groupId, int mode, DateTime lastModificationTime) { // must include a trailing \0 - var nameLength = Encoding.UTF8.GetByteCount(name); + int nameLength = Encoding.UTF8.GetByteCount(name); byte[] entryName = new byte[nameLength + 1]; Encoding.UTF8.GetBytes(name, 0, name.Length, entryName, 0); @@ -238,7 +249,7 @@ namespace AMWD.Common.Packing.Tar.Utils public void AlignTo512(long size, bool acceptZero) { - size = size % 512; + size %= 512; if (size == 0 && !acceptZero) return; while (size < 512) { @@ -249,10 +260,13 @@ namespace AMWD.Common.Packing.Tar.Utils public virtual void Close() { - if (isClosed) return; + if (_isClosed) + return; + AlignTo512(0, true); AlignTo512(0, true); - isClosed = true; + + _isClosed = true; } } } diff --git a/AMWD.Common/Packing/Tar/Utils/TarException.cs b/AMWD.Common/Packing/Tar/Utils/TarException.cs index c3dbf70..34ef3f4 100644 --- a/AMWD.Common/Packing/Tar/Utils/TarException.cs +++ b/AMWD.Common/Packing/Tar/Utils/TarException.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace AMWD.Common.Packing.Tar.Utils { diff --git a/AMWD.Common/Packing/Tar/Utils/TarHeader.cs b/AMWD.Common/Packing/Tar/Utils/TarHeader.cs index 01ccbc1..c1f1107 100644 --- a/AMWD.Common/Packing/Tar/Utils/TarHeader.cs +++ b/AMWD.Common/Packing/Tar/Utils/TarHeader.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Net; using System.Text; using AMWD.Common.Packing.Tar.Interfaces; @@ -7,8 +8,11 @@ namespace AMWD.Common.Packing.Tar.Utils { internal class TarHeader : ITarHeader { - private readonly byte[] buffer = new byte[512]; - private long headerChecksum; + private static readonly byte[] _spaces = Encoding.ASCII.GetBytes(" "); + private readonly byte[] _buffer = new byte[512]; + + private string _fileName; + private long _headerChecksum; public TarHeader() { @@ -18,63 +22,51 @@ namespace AMWD.Common.Packing.Tar.Utils GroupId = 61; // 101 dec } - private string fileName; - protected readonly DateTime TheEpoch = new DateTime(1970, 1, 1, 0, 0, 0); public EntryType EntryType { get; set; } - private static byte[] spaces = Encoding.ASCII.GetBytes(" "); public virtual string FileName { - get - { - return fileName.Replace("\0", string.Empty); - } + get => _fileName.Replace("\0", string.Empty); set { if (value.Length > 100) - { throw new TarException("A file name can not be more than 100 chars long"); - } - fileName = value; + + _fileName = value; } } + public int Mode { get; set; } public string ModeString - { - get { return Convert.ToString(Mode, 8).PadLeft(7, '0'); } - } + => Convert.ToString(Mode, 8).PadLeft(7, '0'); public int UserId { get; set; } + public virtual string UserName { - get { return UserId.ToString(); } - set { UserId = Int32.Parse(value); } + get => UserId.ToString(); + set => UserId = int.Parse(value); } public string UserIdString - { - get { return Convert.ToString(UserId, 8).PadLeft(7, '0'); } - } + => Convert.ToString(UserId, 8).PadLeft(7, '0'); public int GroupId { get; set; } + public virtual string GroupName { - get { return GroupId.ToString(); } - set { GroupId = Int32.Parse(value); } + get => GroupId.ToString(); + set => GroupId = int.Parse(value); } public string GroupIdString - { - get { return Convert.ToString(GroupId, 8).PadLeft(7, '0'); } - } + => Convert.ToString(GroupId, 8).PadLeft(7, '0'); public long SizeInBytes { get; set; } public string SizeString - { - get { return Convert.ToString(SizeInBytes, 8).PadLeft(11, '0'); } - } + => Convert.ToString(SizeInBytes, 8).PadLeft(11, '0'); public DateTime LastModification { get; set; } @@ -82,71 +74,63 @@ namespace AMWD.Common.Packing.Tar.Utils { get { - return Convert.ToString((long)(LastModification - TheEpoch).TotalSeconds, 8).PadLeft(11, '0'); + long unixTime = ((DateTimeOffset)DateTime.SpecifyKind(LastModification, DateTimeKind.Utc)).ToUnixTimeSeconds(); + return Convert.ToString(unixTime, 8).PadLeft(11, '0'); } } public string HeaderChecksumString - { - get { return Convert.ToString(headerChecksum, 8).PadLeft(6, '0'); } - } + => Convert.ToString(_headerChecksum, 8).PadLeft(6, '0'); - public virtual int HeaderSize - { - get { return 512; } - } + public virtual int HeaderSize => 512; - public byte[] GetBytes() - { - return buffer; - } + public byte[] GetBytes() => _buffer.ToArray(); public virtual bool UpdateHeaderFromBytes() { - FileName = Encoding.ASCII.GetString(buffer, 0, 100); - // thanks to Shasha Alperocivh. Trimming nulls. - Mode = Convert.ToInt32(Encoding.ASCII.GetString(buffer, 100, 7).Trim(), 8); - UserId = Convert.ToInt32(Encoding.ASCII.GetString(buffer, 108, 7).Trim(), 8); - GroupId = Convert.ToInt32(Encoding.ASCII.GetString(buffer, 116, 7).Trim(), 8); + FileName = Encoding.ASCII.GetString(_buffer, 0, 100); - EntryType = (EntryType)buffer[156]; + // Thanks to Shasha Alperocivh. Trimming nulls. + Mode = Convert.ToInt32(Encoding.ASCII.GetString(_buffer, 100, 7).Trim(), 8); + UserId = Convert.ToInt32(Encoding.ASCII.GetString(_buffer, 108, 7).Trim(), 8); + GroupId = Convert.ToInt32(Encoding.ASCII.GetString(_buffer, 116, 7).Trim(), 8); - if ((buffer[124] & 0x80) == 0x80) // if size in binary + EntryType = (EntryType)_buffer[156]; + + if ((_buffer[124] & 0x80) == 0x80) // if size in binary { - long sizeBigEndian = BitConverter.ToInt64(buffer, 0x80); + long sizeBigEndian = BitConverter.ToInt64(_buffer, 0x80); SizeInBytes = IPAddress.NetworkToHostOrder(sizeBigEndian); } else { - SizeInBytes = Convert.ToInt64(Encoding.ASCII.GetString(buffer, 124, 11), 8); + SizeInBytes = Convert.ToInt64(Encoding.ASCII.GetString(_buffer, 124, 11), 8); } - long unixTimeStamp = Convert.ToInt64(Encoding.ASCII.GetString(buffer, 136, 11), 8); - LastModification = TheEpoch.AddSeconds(unixTimeStamp); + long unixTimeStamp = Convert.ToInt64(Encoding.ASCII.GetString(_buffer, 136, 11), 8); + LastModification = DateTimeOffset.FromUnixTimeSeconds(unixTimeStamp).DateTime; - var storedChecksum = Convert.ToInt32(Encoding.ASCII.GetString(buffer, 148, 6)); - RecalculateChecksum(buffer); - if (storedChecksum == headerChecksum) - { + int storedChecksum = Convert.ToInt32(Encoding.ASCII.GetString(_buffer, 148, 6)); + RecalculateChecksum(_buffer); + if (storedChecksum == _headerChecksum) return true; - } - RecalculateAltChecksum(buffer); - return storedChecksum == headerChecksum; + RecalculateAltChecksum(_buffer); + return storedChecksum == _headerChecksum; } private void RecalculateAltChecksum(byte[] buf) { - spaces.CopyTo(buf, 148); - headerChecksum = 0; + _spaces.CopyTo(buf, 148); + _headerChecksum = 0; foreach (byte b in buf) { if ((b & 0x80) == 0x80) { - headerChecksum -= b ^ 0x80; + _headerChecksum -= b ^ 0x80; } else { - headerChecksum += b; + _headerChecksum += b; } } } @@ -154,41 +138,42 @@ namespace AMWD.Common.Packing.Tar.Utils public virtual byte[] GetHeaderValue() { // Clean old values - Array.Clear(buffer, 0, buffer.Length); + Array.Clear(_buffer, 0, _buffer.Length); - if (string.IsNullOrEmpty(FileName)) throw new TarException("FileName can not be empty."); - if (FileName.Length >= 100) throw new TarException("FileName is too long. It must be less than 100 bytes."); + if (string.IsNullOrEmpty(FileName)) + throw new TarException("FileName can not be empty."); + + if (FileName.Length >= 100) + throw new TarException("FileName is too long. It must be less than 100 bytes."); // Fill header - Encoding.ASCII.GetBytes(FileName.PadRight(100, '\0')).CopyTo(buffer, 0); - Encoding.ASCII.GetBytes(ModeString).CopyTo(buffer, 100); - Encoding.ASCII.GetBytes(UserIdString).CopyTo(buffer, 108); - Encoding.ASCII.GetBytes(GroupIdString).CopyTo(buffer, 116); - Encoding.ASCII.GetBytes(SizeString).CopyTo(buffer, 124); - Encoding.ASCII.GetBytes(LastModificationString).CopyTo(buffer, 136); + Encoding.ASCII.GetBytes(FileName.PadRight(100, '\0')).CopyTo(_buffer, 0); + Encoding.ASCII.GetBytes(ModeString).CopyTo(_buffer, 100); + Encoding.ASCII.GetBytes(UserIdString).CopyTo(_buffer, 108); + Encoding.ASCII.GetBytes(GroupIdString).CopyTo(_buffer, 116); + Encoding.ASCII.GetBytes(SizeString).CopyTo(_buffer, 124); + Encoding.ASCII.GetBytes(LastModificationString).CopyTo(_buffer, 136); // buffer[156] = 20; - buffer[156] = ((byte)EntryType); + _buffer[156] = ((byte)EntryType); - RecalculateChecksum(buffer); + RecalculateChecksum(_buffer); // Write checksum - Encoding.ASCII.GetBytes(HeaderChecksumString).CopyTo(buffer, 148); + Encoding.ASCII.GetBytes(HeaderChecksumString).CopyTo(_buffer, 148); - return buffer; + return _buffer; } protected virtual void RecalculateChecksum(byte[] buf) { // Set default value for checksum. That is 8 spaces. - spaces.CopyTo(buf, 148); + _spaces.CopyTo(buf, 148); // Calculate checksum - headerChecksum = 0; + _headerChecksum = 0; foreach (byte b in buf) - { - headerChecksum += b; - } + _headerChecksum += b; } } } diff --git a/AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs b/AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs index f9d530c..4f26bf3 100644 --- a/AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs +++ b/AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs @@ -9,59 +9,48 @@ namespace AMWD.Common.Packing.Tar.Utils /// internal class UsTarHeader : TarHeader { - private const string magic = "ustar"; - private const string version = " "; - private string groupName; + private const string Magic = "ustar"; + private const string Version = " "; - private string namePrefix = string.Empty; - private string userName; + private string _groupName; + + private string _namePrefix = string.Empty; + private string _userName; public override string UserName { - get - { - return userName.Replace("\0", string.Empty); - } + get => _userName.Replace("\0", string.Empty); set { if (value.Length > 32) - { throw new TarException("user name can not be longer than 32 chars"); - } - userName = value; + + _userName = value; } } public override string GroupName { - get - { - return groupName.Replace("\0", string.Empty); - } + get => _groupName.Replace("\0", string.Empty); set { if (value.Length > 32) - { throw new TarException("group name can not be longer than 32 chars"); - } - groupName = value; + + _groupName = value; } } public override string FileName { - get - { - return namePrefix.Replace("\0", string.Empty) + base.FileName.Replace("\0", string.Empty); - } + get => _namePrefix.Replace("\0", string.Empty) + base.FileName.Replace("\0", string.Empty); set { if (value.Length > 100) { if (value.Length > 255) - { throw new TarException("UsTar fileName can not be longer thatn 255 chars"); - } + int position = value.Length - 100; // Find first path separator in the remaining 100 chars of the file name @@ -75,7 +64,8 @@ namespace AMWD.Common.Packing.Tar.Utils } if (position == value.Length) position = value.Length - 100; - namePrefix = value.Substring(0, position); + _namePrefix = value.Substring(0, position); + base.FileName = value.Substring(position, value.Length - position); } else @@ -88,26 +78,26 @@ namespace AMWD.Common.Packing.Tar.Utils public override bool UpdateHeaderFromBytes() { byte[] bytes = GetBytes(); + UserName = Encoding.ASCII.GetString(bytes, 0x109, 32); GroupName = Encoding.ASCII.GetString(bytes, 0x129, 32); - namePrefix = Encoding.ASCII.GetString(bytes, 347, 157); + _namePrefix = Encoding.ASCII.GetString(bytes, 347, 157); + return base.UpdateHeaderFromBytes(); } internal static bool IsPathSeparator(char ch) - { - return (ch == '\\' || ch == '/' || ch == '|'); // All the path separators I ever met. - } + => ch == '\\' || ch == '/' || ch == '|'; // All the path separators I ever met. public override byte[] GetHeaderValue() { byte[] header = base.GetHeaderValue(); - Encoding.ASCII.GetBytes(magic).CopyTo(header, 0x101); // Mark header as ustar - Encoding.ASCII.GetBytes(version).CopyTo(header, 0x106); + Encoding.ASCII.GetBytes(Magic).CopyTo(header, 0x101); // Mark header as ustar + Encoding.ASCII.GetBytes(Version).CopyTo(header, 0x106); Encoding.ASCII.GetBytes(UserName).CopyTo(header, 0x109); Encoding.ASCII.GetBytes(GroupName).CopyTo(header, 0x129); - Encoding.ASCII.GetBytes(namePrefix).CopyTo(header, 347); + Encoding.ASCII.GetBytes(_namePrefix).CopyTo(header, 347); if (SizeInBytes >= 0x1FFFFFFFF) { @@ -117,6 +107,7 @@ namespace AMWD.Common.Packing.Tar.Utils RecalculateChecksum(header); Encoding.ASCII.GetBytes(HeaderChecksumString).CopyTo(header, 148); + return header; } @@ -128,7 +119,7 @@ namespace AMWD.Common.Packing.Tar.Utils private static byte[] AlignTo12(byte[] bytes) { - var retVal = new byte[12]; + byte[] retVal = new byte[12]; bytes.CopyTo(retVal, 12 - bytes.Length); return retVal; } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bdc6ca..df739fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ###### Diffs -- [AMWD.Common](https://git.am-wd.de/AM.WD/common/compare/v2.0.1...main) -- [AMWD.Common.AspNetCore](https://git.am-wd.de/AM.WD/common/compare/asp/v3.0.0...main) -- [AMWD.Common.EntityFrameworkCore](https://git.am-wd.de/AM.WD/common/compare/efc/v3.0.0...main) -- [AMWD.Common.Test](https://git.am-wd.de/AM.WD/common/compare/test/v2.1.1...main) +- [AMWD.Common](https://git.am-wd.de/AM.WD/common/compare/v2.0.1...HEAD) +- [AMWD.Common.AspNetCore](https://git.am-wd.de/AM.WD/common/compare/asp/v3.0.0...HEAD) +- [AMWD.Common.EntityFrameworkCore](https://git.am-wd.de/AM.WD/common/compare/efc/v3.0.0...HEAD) +- [AMWD.Common.Test](https://git.am-wd.de/AM.WD/common/compare/test/v2.1.1...HEAD) ### Added diff --git a/Directory.Build.props b/Directory.Build.props index 06b7292..3d0cb4f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -30,11 +30,11 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive