Fixed bug in TAR data format where the first four bytes of filename of first file got eaten

This commit is contained in:
Michael Becker 2014-08-08 20:57:12 -04:00
parent dafb4c6372
commit 0b1cb3fa30

View File

@ -18,228 +18,227 @@ namespace UniversalEditor.DataFormats.FileSystem.TapeArchive
_dfr = base.MakeReference();
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
_dfr.Filters.Add("Tape archive", new string[] { "*.tar", "*.tar.gz", "*.tgz", "*.tar.bz2", "*.tbz2", "*.tb2", "*.taz", "*.tar.z", "*.tlz", "*.tar.lz", "*.txz", "*.tar.xz" });
_dfr.ExportOptions.Add(new CustomOptionBoolean("IsUnixStandardTAR", "Create a UNIX standard tape archive (ustar)", true));
_dfr.ExportOptions.Add(new CustomOptionBoolean("IsUnixStandardTAR", "Create a UNIX standard tape archive (ustar)", true));
}
return _dfr;
}
private bool mvarIsUnixStandardTAR = true;
public bool IsUnixStandardTAR { get { return mvarIsUnixStandardTAR; } set { mvarIsUnixStandardTAR = value; } }
private bool mvarIsUnixStandardTAR = true;
public bool IsUnixStandardTAR { get { return mvarIsUnixStandardTAR; } set { mvarIsUnixStandardTAR = value; } }
protected override void LoadInternal(ref ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
IO.Reader br = base.Accessor.Reader;
byte[] gzhead = br.ReadBytes(4);
if (gzhead.Match(new byte[] { 31, 139, 8, 0 }))
{
br.Accessor.Position -= 4;
byte[] data = br.ReadToEnd();
data = CompressionModules.Gzip.Decompress(data);
br = new IO.Reader(new MemoryAccessor(data));
}
IO.Reader br = base.Accessor.Reader;
byte[] gzhead = br.PeekBytes(4);
if (gzhead.Match(new byte[] { 31, 139, 8, 0 }))
{
byte[] data = br.ReadToEnd();
data = CompressionModules.Gzip.Decompress(data);
br = new IO.Reader(new MemoryAccessor(data));
}
bool ustar_set = false;
while (!br.EndOfStream)
{
if (br.Remaining < 263) break;
bool ustar_set = false;
while (!br.EndOfStream)
{
if (br.Remaining < 263) break;
string fileName = br.ReadFixedLengthString(100).TrimNull();
if (fileName == String.Empty) break;
string fileName = br.ReadFixedLengthString(100).TrimNull();
if (fileName == String.Empty) break;
string fileMode = br.ReadFixedLengthString(8).TrimNull();
string owner = br.ReadFixedLengthString(8).TrimNull();
string group = br.ReadFixedLengthString(8).TrimNull();
string fileSizeInBytesOctal = br.ReadFixedLengthString(12).TrimNull();
string lastModificationTimeUnixOctal = br.ReadFixedLengthString(12).TrimNull();
string headerChecksum = br.ReadFixedLengthString(8).TrimNull();
char c = br.ReadChar();
TapeArchiveRecordType type = (TapeArchiveRecordType)((int)c);
string fileMode = br.ReadFixedLengthString(8).TrimNull();
string owner = br.ReadFixedLengthString(8).TrimNull();
string group = br.ReadFixedLengthString(8).TrimNull();
string fileSizeInBytesOctal = br.ReadFixedLengthString(12).TrimNull();
string lastModificationTimeUnixOctal = br.ReadFixedLengthString(12).TrimNull();
string headerChecksum = br.ReadFixedLengthString(8).TrimNull();
char c = br.ReadChar();
TapeArchiveRecordType type = (TapeArchiveRecordType)((int)c);
string linkedFileName = br.ReadFixedLengthString(100).TrimNull();
string linkedFileName = br.ReadFixedLengthString(100).TrimNull();
string ustar = br.ReadFixedLengthString(6);
if (ustar == "ustar ")
{
if (!ustar_set)
{
mvarIsUnixStandardTAR = true;
ustar_set = true;
}
string ustarVersion = br.ReadFixedLengthString(2).TrimNull();
string ownerName = br.ReadFixedLengthString(32).TrimNull();
string groupName = br.ReadFixedLengthString(32).TrimNull();
string deviceMajor = br.ReadFixedLengthString(8).TrimNull();
string deviceMinor = br.ReadFixedLengthString(8).TrimNull();
string filenamePrefix = br.ReadFixedLengthString(155).TrimNull();
}
else
{
if (!ustar_set)
{
mvarIsUnixStandardTAR = false;
ustar_set = true;
}
br.Accessor.Position -= 6;
}
br.Align(512);
string ustar = br.ReadFixedLengthString(6);
if (ustar == "ustar ")
{
if (!ustar_set)
{
mvarIsUnixStandardTAR = true;
ustar_set = true;
}
string ustarVersion = br.ReadFixedLengthString(2).TrimNull();
string ownerName = br.ReadFixedLengthString(32).TrimNull();
string groupName = br.ReadFixedLengthString(32).TrimNull();
string deviceMajor = br.ReadFixedLengthString(8).TrimNull();
string deviceMinor = br.ReadFixedLengthString(8).TrimNull();
string filenamePrefix = br.ReadFixedLengthString(155).TrimNull();
}
else
{
if (!ustar_set)
{
mvarIsUnixStandardTAR = false;
ustar_set = true;
}
br.Accessor.Position -= 6;
}
br.Align(512);
if (fileName.EndsWith("/"))
{
fileName = fileName.Substring(0, fileName.Length - 1);
Folder folder = fsom.AddFolder(fileName);
}
else
{
File file = fsom.AddFile(fileName);
if (fileName.EndsWith("/"))
{
fileName = fileName.Substring(0, fileName.Length - 1);
Folder folder = fsom.AddFolder(fileName);
}
else
{
File file = fsom.AddFile(fileName);
long fileSize = Convert.ToInt64(fileSizeInBytesOctal, 8);
long fileOffset = (long)br.Accessor.Position;
file.Properties.Add("reader", br);
file.Properties.Add("offset", fileOffset);
file.Properties.Add("length", fileSize);
file.Size = fileSize;
file.DataRequest += file_DataRequest;
long fileSize = Convert.ToInt64(fileSizeInBytesOctal, 8);
long fileOffset = (long)br.Accessor.Position;
file.Properties.Add("reader", br);
file.Properties.Add("offset", fileOffset);
file.Properties.Add("length", fileSize);
file.Size = fileSize;
file.DataRequest += file_DataRequest;
br.Accessor.Position += fileSize;
br.Align(512);
}
}
br.Accessor.Position += fileSize;
br.Align(512);
}
}
}
private void file_DataRequest(object sender, DataRequestEventArgs e)
{
File file = (sender as File);
IO.Reader br = (IO.Reader)file.Properties["reader"];
long offset = (long)file.Properties["offset"];
long length = (long)file.Properties["length"];
br.Accessor.Position = offset;
e.Data = br.ReadBytes(length);
}
private void file_DataRequest(object sender, DataRequestEventArgs e)
{
File file = (sender as File);
IO.Reader br = (IO.Reader)file.Properties["reader"];
long offset = (long)file.Properties["offset"];
long length = (long)file.Properties["length"];
br.Accessor.Position = offset;
e.Data = br.ReadBytes(length);
}
private long OctalToBase10(long octal)
{
long value = 0;
while (octal > 0)
{
value += (octal % 8);
octal /= 8;
}
return value;
}
private long OctalToBase10(long octal)
{
long value = 0;
while (octal > 0)
{
value += (octal % 8);
octal /= 8;
}
return value;
}
protected override void SaveInternal(ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
IO.Writer bw = base.Accessor.Writer;
foreach (Folder folder in fsom.Folders)
{
RecursiveWriteFolder(bw, folder);
}
foreach (File file in fsom.Files)
{
RecursiveWriteFile(bw, file, String.Empty);
}
}
IO.Writer bw = base.Accessor.Writer;
foreach (Folder folder in fsom.Folders)
{
RecursiveWriteFolder(bw, folder);
}
foreach (File file in fsom.Files)
{
RecursiveWriteFile(bw, file, String.Empty);
}
}
private void RecursiveWriteFolder(IO.Writer bw, Folder folder)
{
bw.WriteFixedLengthString(folder.Name + "/", 100);
private void RecursiveWriteFolder(IO.Writer bw, Folder folder)
{
bw.WriteFixedLengthString(folder.Name + "/", 100);
string fileMode = " \0";
bw.WriteFixedLengthString(fileMode, 8);
string owner = " \0";
bw.WriteFixedLengthString(owner, 8);
string group = " \0";
bw.WriteFixedLengthString(group, 8);
string fileSizeInBytesOctal = " \0";
bw.WriteFixedLengthString(fileSizeInBytesOctal, 12);
string lastModificationTimeUnixOctal = " \0";
bw.WriteFixedLengthString(lastModificationTimeUnixOctal, 12);
string headerChecksum = " \0";
bw.WriteFixedLengthString(headerChecksum, 12);
string fileMode = " \0";
bw.WriteFixedLengthString(fileMode, 8);
string owner = " \0";
bw.WriteFixedLengthString(owner, 8);
string group = " \0";
bw.WriteFixedLengthString(group, 8);
string fileSizeInBytesOctal = " \0";
bw.WriteFixedLengthString(fileSizeInBytesOctal, 12);
string lastModificationTimeUnixOctal = " \0";
bw.WriteFixedLengthString(lastModificationTimeUnixOctal, 12);
string headerChecksum = " \0";
bw.WriteFixedLengthString(headerChecksum, 12);
char c = (char)(int)TapeArchiveRecordType.Directory;
char c = (char)(int)TapeArchiveRecordType.Directory;
string linkedFileName = String.Empty;
bw.WriteFixedLengthString(linkedFileName, 100);
string linkedFileName = String.Empty;
bw.WriteFixedLengthString(linkedFileName, 100);
if (mvarIsUnixStandardTAR)
{
bw.WriteFixedLengthString("ustar ", 6);
if (mvarIsUnixStandardTAR)
{
bw.WriteFixedLengthString("ustar ", 6);
string ustarVersion = String.Empty;
bw.WriteFixedLengthString(ustarVersion, 2);
string ownerName = String.Empty;
bw.WriteFixedLengthString(ownerName, 32);
string groupName = String.Empty;
bw.WriteFixedLengthString(groupName, 32);
string deviceMajor = String.Empty;
bw.WriteFixedLengthString(deviceMajor, 8);
string deviceMinor = String.Empty;
bw.WriteFixedLengthString(deviceMinor, 8);
string filenamePrefix = String.Empty;
bw.WriteFixedLengthString(filenamePrefix, 155);
}
bw.Align(512);
string ustarVersion = String.Empty;
bw.WriteFixedLengthString(ustarVersion, 2);
string ownerName = String.Empty;
bw.WriteFixedLengthString(ownerName, 32);
string groupName = String.Empty;
bw.WriteFixedLengthString(groupName, 32);
string deviceMajor = String.Empty;
bw.WriteFixedLengthString(deviceMajor, 8);
string deviceMinor = String.Empty;
bw.WriteFixedLengthString(deviceMinor, 8);
string filenamePrefix = String.Empty;
bw.WriteFixedLengthString(filenamePrefix, 155);
}
bw.Align(512);
foreach (Folder folder1 in folder.Folders)
{
RecursiveWriteFolder(bw, folder1);
}
foreach (File file1 in folder.Files)
{
RecursiveWriteFile(bw, file1, folder.Name + "/");
}
}
private void RecursiveWriteFile(IO.Writer bw, File file, string parentPath)
{
if (!String.IsNullOrEmpty(parentPath)) parentPath = parentPath + "/";
parentPath = parentPath + file.Name;
foreach (Folder folder1 in folder.Folders)
{
RecursiveWriteFolder(bw, folder1);
}
foreach (File file1 in folder.Files)
{
RecursiveWriteFile(bw, file1, folder.Name + "/");
}
}
private void RecursiveWriteFile(IO.Writer bw, File file, string parentPath)
{
if (!String.IsNullOrEmpty(parentPath)) parentPath = parentPath + "/";
parentPath = parentPath + file.Name;
bw.WriteFixedLengthString(parentPath, 100);
bw.WriteFixedLengthString(parentPath, 100);
string fileMode = " \0";
bw.WriteFixedLengthString(fileMode, 8);
string owner = " \0";
bw.WriteFixedLengthString(owner, 8);
string group = " \0";
bw.WriteFixedLengthString(group, 8);
string fileSizeInBytesOctal = Convert.ToString(file.Size, 8).PadLeft(11, ' ') + "\0";
bw.WriteFixedLengthString(fileSizeInBytesOctal, 12);
string lastModificationTimeUnixOctal = " \0";
bw.WriteFixedLengthString(lastModificationTimeUnixOctal, 12);
string headerChecksum = " \0";
bw.WriteFixedLengthString(headerChecksum, 12);
string fileMode = " \0";
bw.WriteFixedLengthString(fileMode, 8);
string owner = " \0";
bw.WriteFixedLengthString(owner, 8);
string group = " \0";
bw.WriteFixedLengthString(group, 8);
string fileSizeInBytesOctal = Convert.ToString(file.Size, 8).PadLeft(11, ' ') + "\0";
bw.WriteFixedLengthString(fileSizeInBytesOctal, 12);
string lastModificationTimeUnixOctal = " \0";
bw.WriteFixedLengthString(lastModificationTimeUnixOctal, 12);
string headerChecksum = " \0";
bw.WriteFixedLengthString(headerChecksum, 12);
char c = (char)(int)TapeArchiveRecordType.Directory;
char c = (char)(int)TapeArchiveRecordType.Directory;
string linkedFileName = String.Empty;
bw.WriteFixedLengthString(linkedFileName, 100);
string linkedFileName = String.Empty;
bw.WriteFixedLengthString(linkedFileName, 100);
if (mvarIsUnixStandardTAR)
{
bw.WriteFixedLengthString("ustar ", 6);
if (mvarIsUnixStandardTAR)
{
bw.WriteFixedLengthString("ustar ", 6);
string ustarVersion = String.Empty;
bw.WriteFixedLengthString(ustarVersion, 2);
string ownerName = String.Empty;
bw.WriteFixedLengthString(ownerName, 32);
string groupName = String.Empty;
bw.WriteFixedLengthString(groupName, 32);
string deviceMajor = String.Empty;
bw.WriteFixedLengthString(deviceMajor, 8);
string deviceMinor = String.Empty;
bw.WriteFixedLengthString(deviceMinor, 8);
string filenamePrefix = String.Empty;
bw.WriteFixedLengthString(filenamePrefix, 155);
}
bw.Align(512);
}
string ustarVersion = String.Empty;
bw.WriteFixedLengthString(ustarVersion, 2);
string ownerName = String.Empty;
bw.WriteFixedLengthString(ownerName, 32);
string groupName = String.Empty;
bw.WriteFixedLengthString(groupName, 32);
string deviceMajor = String.Empty;
bw.WriteFixedLengthString(deviceMajor, 8);
string deviceMinor = String.Empty;
bw.WriteFixedLengthString(deviceMinor, 8);
string filenamePrefix = String.Empty;
bw.WriteFixedLengthString(filenamePrefix, 155);
}
bw.Align(512);
}
}
}