Improved file table parsing in ISO format; still a lot of work to be done
This commit is contained in:
parent
bb311f2979
commit
096c70a133
@ -7,277 +7,324 @@ using UniversalEditor.ObjectModels.FileSystem;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.ISO
|
||||
{
|
||||
public class ISODataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
public override DataFormatReference MakeReference()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReference();
|
||||
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
_dfr.Filters.Add("ISO 9660 optical disc image", new string[] { "*.iso" });
|
||||
_dfr.ContentTypes.Add("application/x-iso9660-image");
|
||||
public class ISODataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
public override DataFormatReference MakeReference()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReference();
|
||||
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
_dfr.Filters.Add("ISO 9660 optical disc image", new string[] { "*.iso" });
|
||||
_dfr.ContentTypes.Add("application/x-iso9660-image");
|
||||
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("SystemName", "System &name:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("VolumeName", "&Volume name:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeSetSize", "Number of volumes in this set:", 1, 0, UInt16.MaxValue));
|
||||
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeSequenceNumber", "Index of this volume in set:", 0, 0, UInt16.MaxValue));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("VolumeSet", "Volume &set:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("Publisher", "&Publisher:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("DataPreparer", "&Data preparer:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("Application", "&Application:", "Universal Editor", 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("CopyrightFile", "&Copyright file:", String.Empty, 38));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("AbstractFile", "&Abstract file:", String.Empty, 36));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("BibliographicFile", "&Bibliographic file:", String.Empty, 37));
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("SystemName", "System &name:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("VolumeName", "&Volume name:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeSetSize", "Number of volumes in this set:", 1, 0, UInt16.MaxValue));
|
||||
_dfr.ExportOptions.Add(new CustomOptionNumber("VolumeSequenceNumber", "Index of this volume in set:", 0, 0, UInt16.MaxValue));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("VolumeSet", "Volume &set:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("Publisher", "&Publisher:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("DataPreparer", "&Data preparer:", String.Empty, 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("Application", "&Application:", "Universal Editor", 128));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("CopyrightFile", "&Copyright file:", String.Empty, 38));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("AbstractFile", "&Abstract file:", String.Empty, 36));
|
||||
_dfr.ExportOptions.Add(new CustomOptionText("BibliographicFile", "&Bibliographic file:", String.Empty, 37));
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
private string mvarSystemName = String.Empty;
|
||||
public string SystemName { get { return mvarSystemName; } set { mvarSystemName = value; } }
|
||||
private string mvarSystemName = String.Empty;
|
||||
public string SystemName { get { return mvarSystemName; } set { mvarSystemName = value; } }
|
||||
|
||||
private string mvarVolumeName = String.Empty;
|
||||
public string VolumeName { get { return mvarVolumeName; } set { mvarVolumeName = value; } }
|
||||
private string mvarVolumeName = String.Empty;
|
||||
public string VolumeName { get { return mvarVolumeName; } set { mvarVolumeName = value; } }
|
||||
|
||||
private ushort mvarVolumeSetSize = 0;
|
||||
public ushort VolumeSetSize { get { return mvarVolumeSetSize; } set { mvarVolumeSetSize = value; } }
|
||||
private ushort mvarVolumeSetSize = 0;
|
||||
public ushort VolumeSetSize { get { return mvarVolumeSetSize; } set { mvarVolumeSetSize = value; } }
|
||||
|
||||
private ushort mvarVolumeSequenceNumber = 0;
|
||||
public ushort VolumeSequenceNumber { get { return mvarVolumeSequenceNumber; } set { mvarVolumeSequenceNumber = value; } }
|
||||
private ushort mvarVolumeSequenceNumber = 0;
|
||||
public ushort VolumeSequenceNumber { get { return mvarVolumeSequenceNumber; } set { mvarVolumeSequenceNumber = value; } }
|
||||
|
||||
private ushort mvarLogicalBlockSize = 2048;
|
||||
public ushort LogicalBlockSize { get { return mvarLogicalBlockSize; } set { mvarLogicalBlockSize = value; } }
|
||||
private ushort mvarLogicalBlockSize = 2048;
|
||||
public ushort LogicalBlockSize { get { return mvarLogicalBlockSize; } set { mvarLogicalBlockSize = value; } }
|
||||
|
||||
private string mvarVolumeSet = String.Empty;
|
||||
public string VolumeSet { get { return mvarVolumeSet; } set { mvarVolumeSet = value; } }
|
||||
private string mvarVolumeSet = String.Empty;
|
||||
public string VolumeSet { get { return mvarVolumeSet; } set { mvarVolumeSet = value; } }
|
||||
|
||||
private string mvarPublisher = String.Empty;
|
||||
public string Publisher { get { return mvarPublisher; } set { mvarPublisher = value; } }
|
||||
private string mvarPublisher = String.Empty;
|
||||
public string Publisher { get { return mvarPublisher; } set { mvarPublisher = value; } }
|
||||
|
||||
private string mvarDataPreparer = String.Empty;
|
||||
public string DataPreparer { get { return mvarDataPreparer; } set { mvarDataPreparer = value; } }
|
||||
private string mvarDataPreparer = String.Empty;
|
||||
public string DataPreparer { get { return mvarDataPreparer; } set { mvarDataPreparer = value; } }
|
||||
|
||||
private string mvarApplication = String.Empty;
|
||||
public string Application { get { return mvarApplication; } set { mvarApplication = value; } }
|
||||
private string mvarApplication = String.Empty;
|
||||
public string Application { get { return mvarApplication; } set { mvarApplication = value; } }
|
||||
|
||||
private string mvarCopyrightFile = String.Empty;
|
||||
public string CopyrightFile { get { return mvarCopyrightFile; } set { mvarCopyrightFile = value; } }
|
||||
private string mvarCopyrightFile = String.Empty;
|
||||
public string CopyrightFile { get { return mvarCopyrightFile; } set { mvarCopyrightFile = value; } }
|
||||
|
||||
private string mvarAbstractFile = String.Empty;
|
||||
public string AbstractFile { get { return mvarAbstractFile; } set { mvarAbstractFile = value; } }
|
||||
private string mvarAbstractFile = String.Empty;
|
||||
public string AbstractFile { get { return mvarAbstractFile; } set { mvarAbstractFile = value; } }
|
||||
|
||||
private string mvarBibliographicFile = String.Empty;
|
||||
public string BibliographicFile { get { return mvarBibliographicFile; } set { mvarBibliographicFile = value; } }
|
||||
private string mvarBibliographicFile = String.Empty;
|
||||
public string BibliographicFile { get { return mvarBibliographicFile; } set { mvarBibliographicFile = value; } }
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
IO.Reader br = base.Accessor.Reader;
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
IO.Reader br = base.Accessor.Reader;
|
||||
|
||||
// skip system area (32768 bytes... WHY???)
|
||||
br.Accessor.Seek(32768, SeekOrigin.Current);
|
||||
br.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
while (true)
|
||||
{
|
||||
ISOVolumeDescriptorType type = (ISOVolumeDescriptorType)br.ReadByte();
|
||||
string identifier = br.ReadFixedLengthString(5);
|
||||
byte version = br.ReadByte();
|
||||
// skip system area (32768 bytes... WHY???)
|
||||
br.Accessor.Seek(32768, SeekOrigin.Current);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ISOVolumeDescriptorType.Primary:
|
||||
{
|
||||
Internal.PrimaryVolumeDescriptor descriptor = ReadPrimaryVolumeDescriptor(br);
|
||||
mvarSystemName = descriptor.systemName;
|
||||
mvarVolumeName = descriptor.volumeName;
|
||||
mvarVolumeSetSize = descriptor.volumeSetSize;
|
||||
mvarVolumeSequenceNumber = descriptor.volumeSequenceNumber;
|
||||
mvarLogicalBlockSize = descriptor.logicalBlockSize;
|
||||
mvarVolumeSet = descriptor.volumeSet;
|
||||
mvarPublisher = descriptor.publisher;
|
||||
mvarDataPreparer = descriptor.dataPreparer;
|
||||
mvarApplication = descriptor.application;
|
||||
mvarCopyrightFile = descriptor.copyrightFile;
|
||||
mvarAbstractFile = descriptor.abstractFile;
|
||||
mvarBibliographicFile = descriptor.bibliographicFile;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
br.Accessor.Seek(2041, SeekOrigin.Current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == ISOVolumeDescriptorType.Terminator) break;
|
||||
}
|
||||
uint pathTableLocationTypeL = 0;
|
||||
uint pathTableLocationTypeM = 0;
|
||||
|
||||
// skip 4 sectors of unknown data to get to the file names
|
||||
br.Accessor.Seek(mvarLogicalBlockSize * 4, SeekOrigin.Current);
|
||||
while (true)
|
||||
{
|
||||
ISOVolumeDescriptorType type = (ISOVolumeDescriptorType)br.ReadByte();
|
||||
string identifier = br.ReadFixedLengthString(5);
|
||||
byte version = br.ReadByte();
|
||||
|
||||
// sector 5 = file names, sector 6 = unicode file names (?)
|
||||
// sector 7 starts the file data...
|
||||
while (!br.EndOfStream)
|
||||
{
|
||||
byte[] nextSectorData = br.ReadBytes(mvarLogicalBlockSize);
|
||||
// TODO: remove this after testing
|
||||
System.IO.File.WriteAllBytes(@"T:\Libraries\UniversalEditor\Tests\FileSystem\ISO\NEXT.DAT", nextSectorData);
|
||||
}
|
||||
}
|
||||
switch (type)
|
||||
{
|
||||
case ISOVolumeDescriptorType.Primary:
|
||||
{
|
||||
Internal.PrimaryVolumeDescriptor descriptor = ReadPrimaryVolumeDescriptor(br);
|
||||
mvarSystemName = descriptor.systemName;
|
||||
mvarVolumeName = descriptor.volumeName;
|
||||
mvarVolumeSetSize = descriptor.volumeSetSize;
|
||||
mvarVolumeSequenceNumber = descriptor.volumeSequenceNumber;
|
||||
mvarLogicalBlockSize = descriptor.logicalBlockSize;
|
||||
mvarVolumeSet = descriptor.volumeSet;
|
||||
mvarPublisher = descriptor.publisher;
|
||||
mvarDataPreparer = descriptor.dataPreparer;
|
||||
mvarApplication = descriptor.application;
|
||||
mvarCopyrightFile = descriptor.copyrightFile;
|
||||
mvarAbstractFile = descriptor.abstractFile;
|
||||
mvarBibliographicFile = descriptor.bibliographicFile;
|
||||
pathTableLocationTypeL = descriptor.pathTableLocationTypeL;
|
||||
pathTableLocationTypeM = descriptor.pathTableLocationTypeM;
|
||||
break;
|
||||
}
|
||||
case ISOVolumeDescriptorType.Terminator:
|
||||
{
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
br.Accessor.Seek(2041, SeekOrigin.Current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type == ISOVolumeDescriptorType.Terminator) break;
|
||||
}
|
||||
|
||||
private Internal.PrimaryVolumeDescriptor ReadPrimaryVolumeDescriptor(IO.Reader br)
|
||||
{
|
||||
Internal.PrimaryVolumeDescriptor descriptor = new Internal.PrimaryVolumeDescriptor();
|
||||
descriptor.unused1 = br.ReadByte(); // Always 0x00.
|
||||
descriptor.systemName = br.ReadFixedLengthString(32); // The name of the system that can act upon sectors 0x00-0x0F for the volume.
|
||||
descriptor.volumeName = br.ReadFixedLengthString(32); // Identification of this volume.
|
||||
descriptor.unused2 = br.ReadUInt64(); // All zeroes.
|
||||
descriptor.volumeSpaceSize = br.ReadDoubleEndianUInt32();
|
||||
descriptor.unused3 = br.ReadBytes(32);
|
||||
descriptor.volumeSetSize = br.ReadDoubleEndianUInt16();
|
||||
descriptor.volumeSequenceNumber = br.ReadDoubleEndianUInt16();
|
||||
descriptor.logicalBlockSize = br.ReadDoubleEndianUInt16();
|
||||
descriptor.pathTableSize = br.ReadDoubleEndianUInt32();
|
||||
// go to the little-endian path table sector and read it
|
||||
br.Accessor.Seek(mvarLogicalBlockSize * pathTableLocationTypeL, SeekOrigin.Begin);
|
||||
|
||||
descriptor.pathTableLocationTypeL = br.ReadUInt32();
|
||||
descriptor.optionalPathTableLocationTypeL = br.ReadUInt32();
|
||||
// go to the big-endian path table sector and read it
|
||||
br.Accessor.Seek(mvarLogicalBlockSize * pathTableLocationTypeM, SeekOrigin.Begin);
|
||||
|
||||
br.Endianness = IO.Endianness.BigEndian;
|
||||
descriptor.pathTableLocationTypeM = br.ReadUInt32();
|
||||
descriptor.optionalPathTableLocationTypeM = br.ReadUInt32();
|
||||
br.Endianness = IO.Endianness.LittleEndian;
|
||||
|
||||
descriptor.rootDirectoryEntry = br.ReadBytes(34);
|
||||
br.Accessor.Position -= 34;
|
||||
|
||||
#region Root Directory
|
||||
ushort rootDirectoryEntrySize = br.ReadUInt16();
|
||||
uint unknown1 = br.ReadDoubleEndianUInt32();
|
||||
uint unknown2 = br.ReadDoubleEndianUInt32();
|
||||
byte[] unknown3 = br.ReadBytes(16);
|
||||
#endregion
|
||||
// our test file (C:\TEMP\ISOTEST\test-one-file-noextensions.iso) has file table in the
|
||||
// sector right after pathTableLocationTypeM
|
||||
br.Accessor.Seek(mvarLogicalBlockSize * 20, SeekOrigin.Begin);
|
||||
|
||||
descriptor.volumeSet = br.ReadFixedLengthString(128);
|
||||
descriptor.publisher = br.ReadFixedLengthString(128);
|
||||
descriptor.dataPreparer = br.ReadFixedLengthString(128);
|
||||
descriptor.application = br.ReadFixedLengthString(128);
|
||||
descriptor.copyrightFile = br.ReadFixedLengthString(38);
|
||||
descriptor.abstractFile = br.ReadFixedLengthString(36);
|
||||
descriptor.bibliographicFile = br.ReadFixedLengthString(37);
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
ushort unknown1 = br.ReadUInt16();
|
||||
uint unknown2 = br.ReadDoubleEndianUInt32();
|
||||
uint unknown3 = br.ReadDoubleEndianUInt32();
|
||||
ulong unknown4 = br.ReadUInt64();
|
||||
uint unknown5 = br.ReadUInt32();
|
||||
ushort unknown6 = br.ReadUInt16();
|
||||
ushort unknown7 = br.ReadUInt16();
|
||||
}
|
||||
|
||||
descriptor.timestampVolumeCreation = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeModification = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeExpiration = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeEffective = ReadDECDateTime(br);
|
||||
while (true)
|
||||
{ // file 1 file 2
|
||||
ushort unknown1 = br.ReadUInt16(); // 48 42
|
||||
if (unknown1 == 0) break;
|
||||
|
||||
descriptor.fileStructureVersion = br.ReadByte();
|
||||
descriptor.unused4 = br.ReadByte();
|
||||
descriptor.applicationSpecific = br.ReadBytes(512);
|
||||
descriptor.reserved = br.ReadBytes(653);
|
||||
return descriptor;
|
||||
}
|
||||
uint unknown2 = br.ReadDoubleEndianUInt32(); // 21 22
|
||||
uint unknown3 = br.ReadDoubleEndianUInt32(); // 44 20
|
||||
ulong unknown4 = br.ReadUInt64(); // ...
|
||||
ushort unknown5 = br.ReadUInt16(); // 0 0
|
||||
ushort unknown6 = br.ReadUInt16(); // 1 1
|
||||
ushort unknown7 = br.ReadUInt16(); // 256 256
|
||||
|
||||
private DateTime ReadDECDateTime(IO.Reader br)
|
||||
{
|
||||
string szYear = br.ReadFixedLengthString(4); // Year from 1 to 9999.
|
||||
string szMonth = br.ReadFixedLengthString(2); // Month from 1 to 12.
|
||||
string szDay = br.ReadFixedLengthString(2); // Day from 1 to 31.
|
||||
string szHour = br.ReadFixedLengthString(2); // Hour from 0 to 23.
|
||||
string szMinute = br.ReadFixedLengthString(2); // Minute from 0 to 59.
|
||||
string szSecond = br.ReadFixedLengthString(2); // Second from 0 to 59.
|
||||
string szHundredSeconds= br.ReadFixedLengthString(2); // Hundredths of a second from 0 to 99.
|
||||
string fileName = br.ReadLengthPrefixedString();
|
||||
byte nulTerminator = br.ReadByte();
|
||||
|
||||
// Time zone offset from GMT in 15 minute intervals, starting at interval -48 (west) and running up to
|
||||
// interval 52 (east). So value 0 indicates interval -48 which equals GMT-12 hours, and value 100
|
||||
// indicates interval 52 which equals GMT+13 hours.
|
||||
byte timeZoneOffset = br.ReadByte();
|
||||
File file = fsom.AddFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
int iYear = Int32.Parse(szYear);
|
||||
int iMonth = Int32.Parse(szMonth);
|
||||
int iDay = Int32.Parse(szDay);
|
||||
int iHour = Int32.Parse(szHour);
|
||||
int iMinute = Int32.Parse(szMinute);
|
||||
int iSecond = Int32.Parse(szSecond);
|
||||
int iHundredSeconds = Int32.Parse(szHundredSeconds);
|
||||
private Internal.PrimaryVolumeDescriptor ReadPrimaryVolumeDescriptor(IO.Reader br)
|
||||
{
|
||||
Internal.PrimaryVolumeDescriptor descriptor = new Internal.PrimaryVolumeDescriptor();
|
||||
descriptor.unused1 = br.ReadByte(); // Always 0x00.
|
||||
descriptor.systemName = br.ReadFixedLengthString(32); // The name of the system that can act upon sectors 0x00-0x0F for the volume.
|
||||
descriptor.volumeName = br.ReadFixedLengthString(32); // Identification of this volume.
|
||||
descriptor.unused2 = br.ReadUInt64(); // All zeroes.
|
||||
descriptor.volumeSpaceSize = br.ReadDoubleEndianUInt32();
|
||||
descriptor.unused3 = br.ReadBytes(32);
|
||||
descriptor.volumeSetSize = br.ReadDoubleEndianUInt16();
|
||||
descriptor.volumeSequenceNumber = br.ReadDoubleEndianUInt16();
|
||||
descriptor.logicalBlockSize = br.ReadDoubleEndianUInt16();
|
||||
descriptor.pathTableSize = br.ReadDoubleEndianUInt32();
|
||||
|
||||
DateTime dt = new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond, iHundredSeconds);
|
||||
return dt;
|
||||
}
|
||||
private void WriteDECDateTime(IO.Writer bw, DateTime dt)
|
||||
{
|
||||
bw.WriteFixedLengthString(dt.Year.ToString(), 4, ' ');
|
||||
bw.WriteFixedLengthString(dt.Month.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Day.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Hour.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Minute.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Second.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Millisecond.ToString(), 2, ' ');
|
||||
descriptor.pathTableLocationTypeL = br.ReadUInt32();
|
||||
descriptor.optionalPathTableLocationTypeL = br.ReadUInt32();
|
||||
|
||||
// Time zone offset from GMT in 15 minute intervals, starting at interval -48 (west) and running up to
|
||||
// interval 52 (east). So value 0 indicates interval -48 which equals GMT-12 hours, and value 100
|
||||
// indicates interval 52 which equals GMT+13 hours.
|
||||
byte timeZoneOffset = 0;
|
||||
bw.WriteByte(timeZoneOffset);
|
||||
}
|
||||
br.Endianness = IO.Endianness.BigEndian;
|
||||
descriptor.pathTableLocationTypeM = br.ReadUInt32();
|
||||
descriptor.optionalPathTableLocationTypeM = br.ReadUInt32();
|
||||
br.Endianness = IO.Endianness.LittleEndian;
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
IO.Writer bw = base.Accessor.Writer;
|
||||
descriptor.rootDirectoryEntry = br.ReadBytes(34);
|
||||
br.Accessor.Position -= 34;
|
||||
|
||||
// skip system area
|
||||
bw.Accessor.Seek(32768, SeekOrigin.Current);
|
||||
#region Root Directory
|
||||
ushort rootDirectoryEntrySize = br.ReadUInt16();
|
||||
uint unknown1 = br.ReadDoubleEndianUInt32();
|
||||
uint unknown2 = br.ReadDoubleEndianUInt32();
|
||||
byte[] unknown3 = br.ReadBytes(16);
|
||||
#endregion
|
||||
|
||||
Internal.PrimaryVolumeDescriptor descriptor = new Internal.PrimaryVolumeDescriptor();
|
||||
descriptor.systemName = mvarSystemName; // The name of the system that can act upon sectors 0x00-0x0F for the volume.
|
||||
descriptor.volumeName = mvarVolumeName; // Identification of this volume.
|
||||
descriptor.volumeSetSize = mvarVolumeSetSize;
|
||||
descriptor.volumeSequenceNumber = mvarVolumeSequenceNumber;
|
||||
descriptor.logicalBlockSize = mvarLogicalBlockSize;
|
||||
WritePrimaryVolumeDescriptor(bw, descriptor);
|
||||
descriptor.volumeSet = br.ReadFixedLengthString(128);
|
||||
descriptor.publisher = br.ReadFixedLengthString(128);
|
||||
descriptor.dataPreparer = br.ReadFixedLengthString(128);
|
||||
descriptor.application = br.ReadFixedLengthString(128);
|
||||
descriptor.copyrightFile = br.ReadFixedLengthString(37);
|
||||
descriptor.abstractFile = br.ReadFixedLengthString(37);
|
||||
descriptor.bibliographicFile = br.ReadFixedLengthString(37);
|
||||
|
||||
bw.Flush();
|
||||
}
|
||||
descriptor.timestampVolumeCreation = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeModification = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeExpiration = ReadDECDateTime(br);
|
||||
descriptor.timestampVolumeEffective = ReadDECDateTime(br);
|
||||
|
||||
private void WritePrimaryVolumeDescriptor(IO.Writer bw, Internal.PrimaryVolumeDescriptor descriptor)
|
||||
{
|
||||
bw.WriteByte(descriptor.unused1);
|
||||
bw.WriteFixedLengthString(descriptor.systemName, 32, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.volumeName, 32, ' ');
|
||||
bw.WriteUInt64(descriptor.unused2);
|
||||
bw.WriteDoubleEndianUInt32(descriptor.volumeSpaceSize);
|
||||
bw.WriteFixedLengthBytes(descriptor.unused3, 32);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.volumeSetSize);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.volumeSequenceNumber);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.logicalBlockSize);
|
||||
bw.WriteDoubleEndianUInt32(descriptor.pathTableSize);
|
||||
descriptor.fileStructureVersion = br.ReadByte();
|
||||
descriptor.unused4 = br.ReadByte();
|
||||
descriptor.applicationSpecific = br.ReadBytes(512);
|
||||
descriptor.reserved = br.ReadBytes(653);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
bw.WriteUInt32(descriptor.pathTableLocationTypeL);
|
||||
bw.WriteUInt32(descriptor.optionalPathTableLocationTypeL);
|
||||
private DateTime ReadDECDateTime(IO.Reader br)
|
||||
{
|
||||
string szYear = br.ReadFixedLengthString(4); // Year from 1 to 9999.
|
||||
string szMonth = br.ReadFixedLengthString(2); // Month from 1 to 12.
|
||||
string szDay = br.ReadFixedLengthString(2); // Day from 1 to 31.
|
||||
string szHour = br.ReadFixedLengthString(2); // Hour from 0 to 23.
|
||||
string szMinute = br.ReadFixedLengthString(2); // Minute from 0 to 59.
|
||||
string szSecond = br.ReadFixedLengthString(2); // Second from 0 to 59.
|
||||
string szHundredSeconds= br.ReadFixedLengthString(2); // Hundredths of a second from 0 to 99.
|
||||
|
||||
bw.Endianness = IO.Endianness.BigEndian;
|
||||
bw.WriteUInt32(descriptor.pathTableLocationTypeM);
|
||||
bw.WriteUInt32(descriptor.optionalPathTableLocationTypeM);
|
||||
bw.Endianness = IO.Endianness.LittleEndian;
|
||||
// Time zone offset from GMT in 15 minute intervals, starting at interval -48 (west) and running up to
|
||||
// interval 52 (east). So value 0 indicates interval -48 which equals GMT-12 hours, and value 100
|
||||
// indicates interval 52 which equals GMT+13 hours.
|
||||
byte timeZoneOffset = br.ReadByte();
|
||||
|
||||
bw.WriteFixedLengthBytes(descriptor.rootDirectoryEntry, 34);
|
||||
int iYear = Int32.Parse(szYear);
|
||||
int iMonth = Int32.Parse(szMonth);
|
||||
int iDay = Int32.Parse(szDay);
|
||||
int iHour = Int32.Parse(szHour);
|
||||
int iMinute = Int32.Parse(szMinute);
|
||||
int iSecond = Int32.Parse(szSecond);
|
||||
int iHundredSeconds = Int32.Parse(szHundredSeconds);
|
||||
|
||||
bw.WriteFixedLengthString(descriptor.volumeSet, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.publisher, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.dataPreparer, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.application, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.copyrightFile, 38, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.abstractFile, 36, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.bibliographicFile, 37, ' ');
|
||||
try
|
||||
{
|
||||
DateTime dt = new DateTime(iYear, iMonth, iDay, iHour, iMinute, iSecond, iHundredSeconds);
|
||||
return dt;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return DateTime.Now;
|
||||
}
|
||||
}
|
||||
private void WriteDECDateTime(IO.Writer bw, DateTime dt)
|
||||
{
|
||||
bw.WriteFixedLengthString(dt.Year.ToString(), 4, ' ');
|
||||
bw.WriteFixedLengthString(dt.Month.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Day.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Hour.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Minute.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Second.ToString(), 2, ' ');
|
||||
bw.WriteFixedLengthString(dt.Millisecond.ToString(), 2, ' ');
|
||||
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeCreation);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeModification);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeExpiration);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeEffective);
|
||||
bw.WriteByte(descriptor.fileStructureVersion);
|
||||
bw.WriteBytes(descriptor.unused3);
|
||||
bw.WriteFixedLengthBytes(descriptor.applicationSpecific, 512);
|
||||
bw.WriteFixedLengthBytes(descriptor.reserved, 653);
|
||||
}
|
||||
}
|
||||
// Time zone offset from GMT in 15 minute intervals, starting at interval -48 (west) and running up to
|
||||
// interval 52 (east). So value 0 indicates interval -48 which equals GMT-12 hours, and value 100
|
||||
// indicates interval 52 which equals GMT+13 hours.
|
||||
byte timeZoneOffset = 0;
|
||||
bw.WriteByte(timeZoneOffset);
|
||||
}
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
IO.Writer bw = base.Accessor.Writer;
|
||||
|
||||
// skip system area
|
||||
bw.Accessor.Seek(32768, SeekOrigin.Current);
|
||||
|
||||
Internal.PrimaryVolumeDescriptor descriptor = new Internal.PrimaryVolumeDescriptor();
|
||||
descriptor.systemName = mvarSystemName; // The name of the system that can act upon sectors 0x00-0x0F for the volume.
|
||||
descriptor.volumeName = mvarVolumeName; // Identification of this volume.
|
||||
descriptor.volumeSetSize = mvarVolumeSetSize;
|
||||
descriptor.volumeSequenceNumber = mvarVolumeSequenceNumber;
|
||||
descriptor.logicalBlockSize = mvarLogicalBlockSize;
|
||||
WritePrimaryVolumeDescriptor(bw, descriptor);
|
||||
|
||||
bw.Flush();
|
||||
}
|
||||
|
||||
private void WritePrimaryVolumeDescriptor(IO.Writer bw, Internal.PrimaryVolumeDescriptor descriptor)
|
||||
{
|
||||
bw.WriteByte(descriptor.unused1);
|
||||
bw.WriteFixedLengthString(descriptor.systemName, 32, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.volumeName, 32, ' ');
|
||||
bw.WriteUInt64(descriptor.unused2);
|
||||
bw.WriteDoubleEndianUInt32(descriptor.volumeSpaceSize);
|
||||
bw.WriteFixedLengthBytes(descriptor.unused3, 32);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.volumeSetSize);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.volumeSequenceNumber);
|
||||
bw.WriteDoubleEndianUInt16(descriptor.logicalBlockSize);
|
||||
bw.WriteDoubleEndianUInt32(descriptor.pathTableSize);
|
||||
|
||||
bw.WriteUInt32(descriptor.pathTableLocationTypeL);
|
||||
bw.WriteUInt32(descriptor.optionalPathTableLocationTypeL);
|
||||
|
||||
bw.Endianness = IO.Endianness.BigEndian;
|
||||
bw.WriteUInt32(descriptor.pathTableLocationTypeM);
|
||||
bw.WriteUInt32(descriptor.optionalPathTableLocationTypeM);
|
||||
bw.Endianness = IO.Endianness.LittleEndian;
|
||||
|
||||
bw.WriteFixedLengthBytes(descriptor.rootDirectoryEntry, 34);
|
||||
|
||||
bw.WriteFixedLengthString(descriptor.volumeSet, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.publisher, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.dataPreparer, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.application, 128, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.copyrightFile, 38, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.abstractFile, 36, ' ');
|
||||
bw.WriteFixedLengthString(descriptor.bibliographicFile, 37, ' ');
|
||||
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeCreation);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeModification);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeExpiration);
|
||||
WriteDECDateTime(bw, descriptor.timestampVolumeEffective);
|
||||
bw.WriteByte(descriptor.fileStructureVersion);
|
||||
bw.WriteBytes(descriptor.unused3);
|
||||
bw.WriteFixedLengthBytes(descriptor.applicationSpecific, 512);
|
||||
bw.WriteFixedLengthBytes(descriptor.reserved, 653);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user