WIP: Added packing of AR and TAR
This commit is contained in:
136
AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs
Normal file
136
AMWD.Common/Packing/Tar/Utils/UsTarHeader.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace AMWD.Common.Packing.Tar.Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// UsTar header implementation.
|
||||
/// </summary>
|
||||
internal class UsTarHeader : TarHeader
|
||||
{
|
||||
private const string magic = "ustar";
|
||||
private const string version = " ";
|
||||
private string groupName;
|
||||
|
||||
private string namePrefix = string.Empty;
|
||||
private string userName;
|
||||
|
||||
public override string UserName
|
||||
{
|
||||
get
|
||||
{
|
||||
return userName.Replace("\0", string.Empty);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Length > 32)
|
||||
{
|
||||
throw new TarException("user name can not be longer than 32 chars");
|
||||
}
|
||||
userName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GroupName
|
||||
{
|
||||
get
|
||||
{
|
||||
return groupName.Replace("\0", string.Empty);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value.Length > 32)
|
||||
{
|
||||
throw new TarException("group name can not be longer than 32 chars");
|
||||
}
|
||||
groupName = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return 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
|
||||
while (!IsPathSeparator(value[position]))
|
||||
{
|
||||
++position;
|
||||
if (position == value.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (position == value.Length)
|
||||
position = value.Length - 100;
|
||||
namePrefix = value.Substring(0, position);
|
||||
base.FileName = value.Substring(position, value.Length - position);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.FileName = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
return base.UpdateHeaderFromBytes();
|
||||
}
|
||||
|
||||
internal static bool IsPathSeparator(char ch)
|
||||
{
|
||||
return (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(UserName).CopyTo(header, 0x109);
|
||||
Encoding.ASCII.GetBytes(GroupName).CopyTo(header, 0x129);
|
||||
Encoding.ASCII.GetBytes(namePrefix).CopyTo(header, 347);
|
||||
|
||||
if (SizeInBytes >= 0x1FFFFFFFF)
|
||||
{
|
||||
byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(SizeInBytes));
|
||||
SetMarker(AlignTo12(bytes)).CopyTo(header, 124);
|
||||
}
|
||||
|
||||
RecalculateChecksum(header);
|
||||
Encoding.ASCII.GetBytes(HeaderChecksumString).CopyTo(header, 148);
|
||||
return header;
|
||||
}
|
||||
|
||||
private static byte[] SetMarker(byte[] bytes)
|
||||
{
|
||||
bytes[0] |= 0x80;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static byte[] AlignTo12(byte[] bytes)
|
||||
{
|
||||
var retVal = new byte[12];
|
||||
bytes.CopyTo(retVal, 12 - bytes.Length);
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user