📄 tarheader.cs
字号:
public static StringBuilder ParseName(byte[] header, int offset, int length)
{
StringBuilder result = new StringBuilder(length);
for (int i = offset; i < offset + length; ++i) {
if (header[i] == 0) {
break;
}
result.Append((char)header[i]);
}
return result;
}
/// <summary>
/// Add <paramref name="name">name</paramref> to the buffer as a collection of bytes
/// </summary>
/// <param name="name">The name to add</param>
/// <param name="nameOffset">The offset of the first character</param>
/// <param name="buf">The buffer to add to</param>
/// <param name="bufferOffset">The index of the first byte to add</param>
/// <param name="length">The number of characters/bytes to add</param>
/// <returns>The next free index in the <paramref name="buf">buffer</paramref></returns>
public static int GetNameBytes(StringBuilder name, int nameOffset, byte[] buf, int bufferOffset, int length)
{
return GetNameBytes(name.ToString(), nameOffset, buf, bufferOffset, length);
}
/// <summary>
/// Add <paramref name="name">name</paramref> to the buffer as a collection of bytes
/// </summary>
/// <param name="name">The name to add</param>
/// <param name="nameOffset">The offset of the first character</param>
/// <param name="buf">The buffer to add to</param>
/// <param name="bufferOffset">The index of the first byte to add</param>
/// <param name="length">The number of characters/bytes to add</param>
/// <returns>The next free index in the <paramref name="buf">buffer</paramref></returns>
public static int GetNameBytes(string name, int nameOffset, byte[] buf, int bufferOffset, int length)
{
int i;
for (i = 0 ; i < length - 1 && nameOffset + i < name.Length; ++i) {
buf[bufferOffset + i] = (byte)name[nameOffset + i];
}
for (; i < length ; ++i) {
buf[bufferOffset + i] = 0;
}
return bufferOffset + length;
}
/// <summary>
/// Add an entry name to the buffer
/// </summary>
/// <param name="name">
/// The name to add
/// </param>
/// <param name="buf">
/// The buffer to add to
/// </param>
/// <param name="offset">
/// The offset into the buffer from which to start adding
/// </param>
/// <param name="length">
/// The number of header bytes to add
/// </param>
/// <returns>
/// The index of the next free byte in the buffer
/// </returns>
public static int GetNameBytes(StringBuilder name, byte[] buf, int offset, int length)
{
return GetNameBytes(name.ToString(), 0, buf, offset, length);
}
/// <summary>
/// Add an entry name to the buffer
/// </summary>
/// <param name="name">The name to add</param>
/// <param name="buf">The buffer to add to</param>
/// <param name="offset">The offset into the buffer from which to start adding</param>
/// <param name="length">The number of header bytes to add</param>
/// <returns>The index of the next free byte in the buffer</returns>
public static int GetNameBytes(string name, byte[] buf, int offset, int length)
{
return GetNameBytes(name, 0, buf, offset, length);
}
/// <summary>
/// Add a string to a buffer as a collection of ascii bytes.
/// </summary>
/// <param name="toAdd">The string to add</param>
/// <param name="nameOffset">The offset of the first character to add.</param>
/// <param name="buffer">The buffer to add to.</param>
/// <param name="bufferOffset">The offset to start adding at.</param>
/// <param name="length">The number of ascii characters to add.</param>
/// <returns>The next free index in the buffer.</returns>
public static int GetAsciiBytes(string toAdd, int nameOffset, byte[] buffer, int bufferOffset, int length )
{
for (int i = 0 ; i < length && nameOffset + i < toAdd.Length; ++i)
{
buffer[bufferOffset + i] = (byte)toAdd[nameOffset + i];
}
return bufferOffset + length;
}
/// <summary>
/// Put an octal representation of a value into a buffer
/// </summary>
/// <param name = "val">
/// the value to be converted to octal
/// </param>
/// <param name = "buf">
/// buffer to store the octal string
/// </param>
/// <param name = "offset">
/// The offset into the buffer where the value starts
/// </param>
/// <param name = "length">
/// The length of the octal string to create
/// </param>
/// <returns>
/// The offset of the character next byte after the octal string
/// </returns>
public static int GetOctalBytes(long val, byte[] buf, int offset, int length)
{
int idx = length - 1;
// Either a space or null is valid here. We use NULL as per GNUTar
buf[offset + idx] = 0;
--idx;
if (val > 0) {
for (long v = val; idx >= 0 && v > 0; --idx) {
buf[offset + idx] = (byte)((byte)'0' + (byte)(v & 7));
v >>= 3;
}
}
for (; idx >= 0; --idx) {
buf[offset + idx] = (byte)'0';
}
return offset + length;
}
/// <summary>
/// Put an octal representation of a value into a buffer
/// </summary>
/// <param name = "val">Value to be convert to octal</param>
/// <param name = "buf">The buffer to update</param>
/// <param name = "offset">The offset into the buffer to store the value</param>
/// <param name = "length">The length of the octal string</param>
/// <returns>Index of next byte</returns>
public static int GetLongOctalBytes(long val, byte[] buf, int offset, int length)
{
return GetOctalBytes(val, buf, offset, length);
}
/// <summary>
/// Add the checksum integer to header buffer.
/// </summary>
/// <param name = "val"></param>
/// <param name = "buf">The header buffer to set the checksum for</param>
/// <param name = "offset">The offset into the buffer for the checksum</param>
/// <param name = "length">The number of header bytes to update.
/// It's formatted differently from the other fields: it has 6 digits, a
/// null, then a space -- rather than digits, a space, then a null.
/// The final space is already there, from checksumming
/// </param>
/// <returns>The modified buffer offset</returns>
private static int GetCheckSumOctalBytes(long val, byte[] buf, int offset, int length)
{
TarHeader.GetOctalBytes(val, buf, offset, length - 1);
return offset + length;
}
/// <summary>
/// Compute the checksum for a tar entry header.
/// The checksum field must be all spaces prior to this happening
/// </summary>
/// <param name = "buf">The tar entry's header buffer.</param>
/// <returns>The computed checksum.</returns>
private static int ComputeCheckSum(byte[] buf)
{
int sum = 0;
for (int i = 0; i < buf.Length; ++i) {
sum += buf[i];
}
return sum;
}
/// <summary>
/// Make a checksum for a tar entry ignoring the checksum contents.
/// </summary>
/// <param name = "buf">The tar entry's header buffer.</param>
/// <returns>The checksum for the buffer</returns>
private static int MakeCheckSum(byte[] buf)
{
int sum = 0;
for ( int i = 0; i < CHKSUMOFS; ++i )
{
sum += buf[i];
}
for ( int i = 0; i < TarHeader.CHKSUMLEN; ++i)
{
sum += (byte)' ';
}
for (int i = CHKSUMOFS + CHKSUMLEN; i < buf.Length; ++i)
{
sum += buf[i];
}
return sum;
}
readonly static long timeConversionFactor = 10000000L; // 1 tick == 100 nanoseconds
readonly static DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);
static int GetCTime(System.DateTime dateTime)
{
return (int)((dateTime.Ticks - dateTime1970.Ticks) / timeConversionFactor);
}
static DateTime GetDateTimeFromCTime(long ticks)
{
DateTime result;
try {
result = new DateTime(dateTime1970.Ticks + ticks * timeConversionFactor);
}
catch {
result = dateTime1970;
}
return result;
}
/// <summary>
/// Parse TarHeader information from a header buffer.
/// </summary>
/// <param name = "header">
/// The tar entry header buffer to get information from.
/// </param>
public void ParseBuffer(byte[] header)
{
int offset = 0;
name = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString();
offset += TarHeader.NAMELEN;
mode = (int)TarHeader.ParseOctal(header, offset, TarHeader.MODELEN);
offset += TarHeader.MODELEN;
UserId = (int)TarHeader.ParseOctal(header, offset, TarHeader.UIDLEN);
offset += TarHeader.UIDLEN;
GroupId = (int)TarHeader.ParseOctal(header, offset, TarHeader.GIDLEN);
offset += TarHeader.GIDLEN;
Size = TarHeader.ParseOctal(header, offset, TarHeader.SIZELEN);
offset += TarHeader.SIZELEN;
ModTime = GetDateTimeFromCTime(TarHeader.ParseOctal(header, offset, TarHeader.MODTIMELEN));
offset += TarHeader.MODTIMELEN;
checksum = (int)TarHeader.ParseOctal(header, offset, TarHeader.CHKSUMLEN);
offset += TarHeader.CHKSUMLEN;
TypeFlag = header[ offset++ ];
LinkName = TarHeader.ParseName(header, offset, TarHeader.NAMELEN).ToString();
offset += TarHeader.NAMELEN;
Magic = TarHeader.ParseName(header, offset, TarHeader.MAGICLEN).ToString();
offset += TarHeader.MAGICLEN;
Version = TarHeader.ParseName(header, offset, TarHeader.VERSIONLEN).ToString();
offset += TarHeader.VERSIONLEN;
UserName = TarHeader.ParseName(header, offset, TarHeader.UNAMELEN).ToString();
offset += TarHeader.UNAMELEN;
GroupName = TarHeader.ParseName(header, offset, TarHeader.GNAMELEN).ToString();
offset += TarHeader.GNAMELEN;
DevMajor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);
offset += TarHeader.DEVLEN;
DevMinor = (int)TarHeader.ParseOctal(header, offset, TarHeader.DEVLEN);
// Fields past this point not currently parsed or used...
// TODO: prefix information.
isChecksumValid = Checksum == TarHeader.MakeCheckSum(header);
}
/// <summary>
/// 'Write' header information to buffer provided, updating the <see cref="Checksum">check sum</see>.
/// </summary>
/// <param name="outbuf">output buffer for header information</param>
public void WriteHeader(byte[] outbuf)
{
int offset = 0;
offset = GetNameBytes(this.Name, outbuf, offset, TarHeader.NAMELEN);
offset = GetOctalBytes(this.mode, outbuf, offset, TarHeader.MODELEN);
offset = GetOctalBytes(this.UserId, outbuf, offset, TarHeader.UIDLEN);
offset = GetOctalBytes(this.GroupId, outbuf, offset, TarHeader.GIDLEN);
long size = this.Size;
offset = GetLongOctalBytes(size, outbuf, offset, TarHeader.SIZELEN);
offset = GetLongOctalBytes(GetCTime(this.ModTime), outbuf, offset, TarHeader.MODTIMELEN);
int csOffset = offset;
for (int c = 0; c < TarHeader.CHKSUMLEN; ++c) {
outbuf[offset++] = (byte)' ';
}
outbuf[offset++] = this.TypeFlag;
offset = GetNameBytes(this.LinkName, outbuf, offset, NAMELEN);
offset = GetAsciiBytes(this.Magic, 0, outbuf, offset, MAGICLEN);
offset = GetNameBytes(this.Version, outbuf, offset, VERSIONLEN);
offset = GetNameBytes(this.UserName, outbuf, offset, UNAMELEN);
offset = GetNameBytes(this.GroupName, outbuf, offset, GNAMELEN);
if (this.TypeFlag == LF_CHR || this.TypeFlag == LF_BLK) {
offset = GetOctalBytes(this.DevMajor, outbuf, offset, DEVLEN);
offset = GetOctalBytes(this.DevMinor, outbuf, offset, DEVLEN);
}
for ( ; offset < outbuf.Length; ) {
outbuf[offset++] = 0;
}
checksum = ComputeCheckSum(outbuf);
GetCheckSumOctalBytes(checksum, outbuf, csOffset, CHKSUMLEN);
isChecksumValid = true;
}
}
}
/* The original Java file had this header:
*
** Authored by Timothy Gerard Endres
** <mailto:time@gjt.org> <http://www.trustice.com>
**
** This work has been placed into the public domain.
** You may use this work in any way and for any purpose you wish.
**
** THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND,
** NOT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR
** OF THIS SOFTWARE, ASSUMES _NO_ RESPONSIBILITY FOR ANY
** CONSEQUENCE RESULTING FROM THE USE, MODIFICATION, OR
** REDISTRIBUTION OF THIS SOFTWARE.
**
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -