public static byte[] CreateHeader(string fileName, bool isDir, long size, DateTime lastWriteTime, out int paddingSize, bool isLongLinkPseudoentry = false)
{
byte[] hdr = new byte[512];
byte[] longLinkPrefix = null;
fileName = fileName.Replace('\\', '/');
if (isDir && !fileName.EndsWith("/"))
fileName += "/";
string fnPrefix = null;
if (fileName.Length > 100)
{
int idx = fileName.Length - 100;
idx = fileName.IndexOf('/', idx);
if (idx != -1 && idx != fileName.Length - 1)
{
fnPrefix = fileName.Substring(0, idx);
fileName = fileName.Substring(idx + 1);
}
else
{
byte[] rawName = Encoding.UTF8.GetBytes(fileName);
int sectors = (rawName.Length + 511) / 512;
int unused;
longLinkPrefix = new byte[512 + sectors * 512];
CreateHeader("././@LongLink", false, rawName.Length, lastWriteTime, out unused, true).CopyTo(longLinkPrefix, 0);
longLinkPrefix[156] = (byte)'L';
rawName.CopyTo(longLinkPrefix, 512);
}
}
paddingSize = (int)size & 511;
if (paddingSize != 0)
paddingSize = 512 - paddingSize;
WriteTextField(hdr, 0, 100, fileName);
if (isLongLinkPseudoentry)
{
WriteOctalField(hdr, 100, 8, 0); //File mode
WriteOctalField(hdr, 108, 8, 0); //User ID
WriteOctalField(hdr, 116, 8, 0); //Group ID
WriteOctalField(hdr, 136, 12, 0); //Last modification time
}
else
{
WriteOctalField(hdr, 100, 8, Convert.ToInt32("755", 8)); //File mode
WriteOctalField(hdr, 108, 8, 500); //User ID
WriteOctalField(hdr, 116, 8, 544); //Group ID
WriteOctalField(hdr, 136, 12, (long)(lastWriteTime - UnixEpoch).TotalSeconds); //Last modification time
}
WriteOctalField(hdr, 124, 12, size); //File size
// WriteTextField(hdr, 257, 8, "ustar ");
WriteTextField(hdr, 257, 8, "ustar\0" + "00");
// WriteTextField(hdr, 265, 32, userName);
// WriteTextField(hdr, 297, 32, groupName);
WriteTextField(hdr, 345, 155, fnPrefix);
if (isLongLinkPseudoentry)
hdr[156] = (byte)'L';
else if (isDir)
hdr[156] = (byte)'5';
else
hdr[156] = (byte)'0';
int checksum = 0x20 * 8;
for (int i = 0; i < hdr.Length; i++)
checksum += hdr[i];
WriteOctalField(hdr, 148, 8, checksum);
if (longLinkPrefix != null)
{
var result = new byte[longLinkPrefix.Length + hdr.Length];
longLinkPrefix.CopyTo(result, 0);
hdr.CopyTo(result, longLinkPrefix.Length);
return result;
}
return hdr;
}