mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-11-15 17:00:38 +00:00
Add the UDF models (#108)
The ECMA-167 and UDF structures that the UDF reader fills in, split out of #100. The only change is that the notes on Volume moved from the summary into the remarks. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
24
SabreTools.Data.Models/UDF/AllocationExtentDescriptor.cs
Normal file
24
SabreTools.Data.Models/UDF/AllocationExtentDescriptor.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Allocation Extent Descriptor (4/14.5), continues the allocation descriptors of a File Entry
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class AllocationExtentDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical block of the previous allocation extent
|
||||
/// </summary>
|
||||
public uint PreviousAllocationExtentLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the allocation descriptors in bytes
|
||||
/// </summary>
|
||||
public uint LengthOfAllocationDescriptors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allocation descriptors, of the type given in the owning File Entry's ICB tag flags
|
||||
/// </summary>
|
||||
public byte[] AllocationDescriptors { get; set; } = [];
|
||||
}
|
||||
}
|
||||
24
SabreTools.Data.Models/UDF/AnchorVolumeDescriptorPointer.cs
Normal file
24
SabreTools.Data.Models/UDF/AnchorVolumeDescriptorPointer.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Anchor Volume Descriptor Pointer (3/10.2), recorded at sector 256 (and at the end of the volume)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class AnchorVolumeDescriptorPointer : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Extent of the Main Volume Descriptor Sequence
|
||||
/// </summary>
|
||||
public ExtentDescriptor MainVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Extent of the Reserve Volume Descriptor Sequence
|
||||
/// </summary>
|
||||
public ExtentDescriptor ReserveVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 480 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[480];
|
||||
}
|
||||
}
|
||||
20
SabreTools.Data.Models/UDF/CharacterSetSpecification.cs
Normal file
20
SabreTools.Data.Models/UDF/CharacterSetSpecification.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Character Set Specification (charspec, 1/7.2.1)
|
||||
/// UDF requires CS0 with the information "OSTA Compressed Unicode"
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class CharacterSetSpecification
|
||||
{
|
||||
/// <summary>
|
||||
/// Character set type (0 = CS0)
|
||||
/// </summary>
|
||||
public byte CharacterSetType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Character set information, padded with 0x00
|
||||
/// </summary>
|
||||
public byte[] CharacterSetInformation { get; set; } = new byte[63];
|
||||
}
|
||||
}
|
||||
126
SabreTools.Data.Models/UDF/Constants.cs
Normal file
126
SabreTools.Data.Models/UDF/Constants.cs
Normal file
@@ -0,0 +1,126 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF / ECMA-167 constant values and arrays
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||
public static class Constants
|
||||
{
|
||||
#region Volume Recognition Constants
|
||||
|
||||
/// <summary>
|
||||
/// Size of a logical sector on optical media
|
||||
/// </summary>
|
||||
public const int SectorSize = 2048;
|
||||
|
||||
/// <summary>
|
||||
/// Sector of the first Volume Structure Descriptor (after the 32KiB System Area)
|
||||
/// </summary>
|
||||
public const int VolumeRecognitionSequenceSector = 16;
|
||||
|
||||
/// <summary>
|
||||
/// Sector of the first Anchor Volume Descriptor Pointer
|
||||
/// </summary>
|
||||
public const int AnchorVolumeDescriptorPointerSector = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Beginning Extended Area Descriptor identifier, "BEA01"
|
||||
/// </summary>
|
||||
public static readonly byte[] BeginningExtendedAreaDescriptor = [0x42, 0x45, 0x41, 0x30, 0x31];
|
||||
|
||||
/// <summary>
|
||||
/// NSR Descriptor identifier for ECMA-167 2nd edition (UDF 1.02 to 1.50), "NSR02"
|
||||
/// </summary>
|
||||
public static readonly byte[] NSR02 = [0x4E, 0x53, 0x52, 0x30, 0x32];
|
||||
|
||||
/// <summary>
|
||||
/// NSR Descriptor identifier for ECMA-167 3rd edition (UDF 2.00 and later), "NSR03"
|
||||
/// </summary>
|
||||
public static readonly byte[] NSR03 = [0x4E, 0x53, 0x52, 0x30, 0x33];
|
||||
|
||||
/// <summary>
|
||||
/// Terminating Extended Area Descriptor identifier, "TEA01"
|
||||
/// </summary>
|
||||
public static readonly byte[] TerminatingExtendedAreaDescriptor = [0x54, 0x45, 0x41, 0x30, 0x31];
|
||||
|
||||
/// <summary>
|
||||
/// ISO 9660 volume descriptor identifier, "CD001" (bridge discs)
|
||||
/// </summary>
|
||||
public static readonly byte[] CD001 = [0x43, 0x44, 0x30, 0x30, 0x31];
|
||||
|
||||
/// <summary>
|
||||
/// Boot Descriptor identifier, "BOOT2"
|
||||
/// </summary>
|
||||
public static readonly byte[] BOOT2 = [0x42, 0x4F, 0x4F, 0x54, 0x32];
|
||||
|
||||
/// <summary>
|
||||
/// ECMA-168 volume descriptor identifier, "CDW02"
|
||||
/// </summary>
|
||||
public static readonly byte[] CDW02 = [0x43, 0x44, 0x57, 0x30, 0x32];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partition Map Constants
|
||||
|
||||
/// <summary>
|
||||
/// Type 1 Partition Map type
|
||||
/// </summary>
|
||||
public const byte Type1PartitionMap = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Type 2 Partition Map type
|
||||
/// </summary>
|
||||
public const byte Type2PartitionMap = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Partition type identifier of a UDF Metadata Partition (UDF 2.50 and later)
|
||||
/// </summary>
|
||||
public const string MetadataPartitionIdentifier = "*UDF Metadata Partition";
|
||||
|
||||
/// <summary>
|
||||
/// Partition type identifier of a UDF Sparable Partition
|
||||
/// </summary>
|
||||
public const string SparablePartitionIdentifier = "*UDF Sparable Partition";
|
||||
|
||||
/// <summary>
|
||||
/// Partition type identifier of a UDF Virtual Partition
|
||||
/// </summary>
|
||||
public const string VirtualPartitionIdentifier = "*UDF Virtual Partition";
|
||||
|
||||
#endregion
|
||||
|
||||
#region Character Set Constants
|
||||
|
||||
/// <summary>
|
||||
/// OSTA Compressed Unicode, 8 bits per character
|
||||
/// </summary>
|
||||
public const byte CompressionId8 = 8;
|
||||
|
||||
/// <summary>
|
||||
/// OSTA Compressed Unicode, 16 bits per character (big-endian)
|
||||
/// </summary>
|
||||
public const byte CompressionId16 = 16;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Allocation Descriptor Constants
|
||||
|
||||
/// <summary>
|
||||
/// Mask of the extent length in an allocation descriptor (the top two bits hold the extent type)
|
||||
/// </summary>
|
||||
public const uint ExtentLengthMask = 0x3FFFFFFF;
|
||||
|
||||
/// <summary>
|
||||
/// Shift of the extent type in an allocation descriptor's extent length
|
||||
/// </summary>
|
||||
public const int ExtentTypeShift = 30;
|
||||
|
||||
/// <summary>
|
||||
/// Mask of the allocation descriptor type in an ICB tag's flags
|
||||
/// </summary>
|
||||
public const ushort AllocationDescriptorTypeMask = 0x0007;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
14
SabreTools.Data.Models/UDF/Descriptor.cs
Normal file
14
SabreTools.Data.Models/UDF/Descriptor.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract UDF tagged descriptor, all start with a Descriptor Tag
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public abstract class Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Descriptor tag
|
||||
/// </summary>
|
||||
public DescriptorTag DescriptorTag { get; set; } = new();
|
||||
}
|
||||
}
|
||||
50
SabreTools.Data.Models/UDF/DescriptorTag.cs
Normal file
50
SabreTools.Data.Models/UDF/DescriptorTag.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Descriptor Tag (3/7.2), the first 16 bytes of every tagged descriptor
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class DescriptorTag
|
||||
{
|
||||
/// <summary>
|
||||
/// Type of the descriptor
|
||||
/// </summary>
|
||||
public TagIdentifier TagIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Version of the descriptor, 2 (ECMA-167 2nd edition) or 3 (3rd edition)
|
||||
/// </summary>
|
||||
public ushort DescriptorVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sum modulo 256 of bytes 0-3 and 5-15 of the tag
|
||||
/// </summary>
|
||||
public byte TagChecksum { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 0x00
|
||||
/// </summary>
|
||||
public byte Reserved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identification of a set of descriptors
|
||||
/// </summary>
|
||||
public ushort TagSerialNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// CRC-CCITT of the DescriptorCRCLength bytes following the tag
|
||||
/// </summary>
|
||||
public ushort DescriptorCRC { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of bytes after the tag covered by the DescriptorCRC
|
||||
/// </summary>
|
||||
public ushort DescriptorCRCLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of the logical sector (volume structures) or logical block (file structures)
|
||||
/// in which the descriptor is recorded
|
||||
/// </summary>
|
||||
public uint TagLocation { get; set; }
|
||||
}
|
||||
}
|
||||
24
SabreTools.Data.Models/UDF/EntityIdentifier.cs
Normal file
24
SabreTools.Data.Models/UDF/EntityIdentifier.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Entity Identifier (regid, 1/7.4)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class EntityIdentifier
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags (bit 0: dirty, bit 1: protected)
|
||||
/// </summary>
|
||||
public byte Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Identifier, padded with 0x00
|
||||
/// </summary>
|
||||
public byte[] Identifier { get; set; } = new byte[23];
|
||||
|
||||
/// <summary>
|
||||
/// Identifier suffix (UDF domain identifiers: revision as a little-endian ushort, then domain flags)
|
||||
/// </summary>
|
||||
public byte[] IdentifierSuffix { get; set; } = new byte[8];
|
||||
}
|
||||
}
|
||||
306
SabreTools.Data.Models/UDF/Enums.cs
Normal file
306
SabreTools.Data.Models/UDF/Enums.cs
Normal file
@@ -0,0 +1,306 @@
|
||||
using System;
|
||||
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum for DescriptorTag.TagIdentifier
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public enum TagIdentifier : ushort
|
||||
{
|
||||
/// <summary>
|
||||
/// Primary Volume Descriptor (3/10.1)
|
||||
/// </summary>
|
||||
PRIMARY_VOLUME_DESCRIPTOR = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Anchor Volume Descriptor Pointer (3/10.2)
|
||||
/// </summary>
|
||||
ANCHOR_VOLUME_DESCRIPTOR_POINTER = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Volume Descriptor Pointer (3/10.3)
|
||||
/// </summary>
|
||||
VOLUME_DESCRIPTOR_POINTER = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Implementation Use Volume Descriptor (3/10.4)
|
||||
/// </summary>
|
||||
IMPLEMENTATION_USE_VOLUME_DESCRIPTOR = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Partition Descriptor (3/10.5)
|
||||
/// </summary>
|
||||
PARTITION_DESCRIPTOR = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Logical Volume Descriptor (3/10.6)
|
||||
/// </summary>
|
||||
LOGICAL_VOLUME_DESCRIPTOR = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Unallocated Space Descriptor (3/10.8)
|
||||
/// </summary>
|
||||
UNALLOCATED_SPACE_DESCRIPTOR = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Terminating Descriptor (3/10.9)
|
||||
/// </summary>
|
||||
TERMINATING_DESCRIPTOR = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Logical Volume Integrity Descriptor (3/10.10)
|
||||
/// </summary>
|
||||
LOGICAL_VOLUME_INTEGRITY_DESCRIPTOR = 9,
|
||||
|
||||
/// <summary>
|
||||
/// File Set Descriptor (4/14.1)
|
||||
/// </summary>
|
||||
FILE_SET_DESCRIPTOR = 256,
|
||||
|
||||
/// <summary>
|
||||
/// File Identifier Descriptor (4/14.4)
|
||||
/// </summary>
|
||||
FILE_IDENTIFIER_DESCRIPTOR = 257,
|
||||
|
||||
/// <summary>
|
||||
/// Allocation Extent Descriptor (4/14.5)
|
||||
/// </summary>
|
||||
ALLOCATION_EXTENT_DESCRIPTOR = 258,
|
||||
|
||||
/// <summary>
|
||||
/// Indirect Entry (4/14.7)
|
||||
/// </summary>
|
||||
INDIRECT_ENTRY = 259,
|
||||
|
||||
/// <summary>
|
||||
/// Terminal Entry (4/14.8)
|
||||
/// </summary>
|
||||
TERMINAL_ENTRY = 260,
|
||||
|
||||
/// <summary>
|
||||
/// File Entry (4/14.9)
|
||||
/// </summary>
|
||||
FILE_ENTRY = 261,
|
||||
|
||||
/// <summary>
|
||||
/// Extended Attribute Header Descriptor (4/14.10.1)
|
||||
/// </summary>
|
||||
EXTENDED_ATTRIBUTE_HEADER_DESCRIPTOR = 262,
|
||||
|
||||
/// <summary>
|
||||
/// Unallocated Space Entry (4/14.11)
|
||||
/// </summary>
|
||||
UNALLOCATED_SPACE_ENTRY = 263,
|
||||
|
||||
/// <summary>
|
||||
/// Space Bitmap Descriptor (4/14.12)
|
||||
/// </summary>
|
||||
SPACE_BITMAP_DESCRIPTOR = 264,
|
||||
|
||||
/// <summary>
|
||||
/// Partition Integrity Entry (4/14.13)
|
||||
/// </summary>
|
||||
PARTITION_INTEGRITY_ENTRY = 265,
|
||||
|
||||
/// <summary>
|
||||
/// Extended File Entry (4/14.17)
|
||||
/// </summary>
|
||||
EXTENDED_FILE_ENTRY = 266,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum for FileIdentifierDescriptor.FileCharacteristics (4/14.4.3)
|
||||
/// Bits 5-7: Reserved: 0
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
[Flags]
|
||||
public enum FileCharacteristics : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// No characteristics set
|
||||
/// </summary>
|
||||
NONE = 0x00,
|
||||
|
||||
/// <summary>
|
||||
/// The existence of the file shall not be made known to the user (hidden)
|
||||
/// </summary>
|
||||
EXISTENCE = 0x01,
|
||||
|
||||
/// <summary>
|
||||
/// The file is a directory
|
||||
/// </summary>
|
||||
DIRECTORY = 0x02,
|
||||
|
||||
/// <summary>
|
||||
/// The descriptor shall be ignored (deleted)
|
||||
/// </summary>
|
||||
DELETED = 0x04,
|
||||
|
||||
/// <summary>
|
||||
/// The ICB identifies the parent directory
|
||||
/// </summary>
|
||||
PARENT = 0x08,
|
||||
|
||||
/// <summary>
|
||||
/// The file contains implementation use data (UDF: stream directory metadata)
|
||||
/// </summary>
|
||||
METADATA = 0x10,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum for ICBTag.FileType (4/14.6.6, UDF 2.3.5.4)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public enum FileType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Not specified
|
||||
/// </summary>
|
||||
UNSPECIFIED = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Unallocated Space Entry
|
||||
/// </summary>
|
||||
UNALLOCATED_SPACE_ENTRY = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Partition Integrity Entry
|
||||
/// </summary>
|
||||
PARTITION_INTEGRITY_ENTRY = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Indirect Entry
|
||||
/// </summary>
|
||||
INDIRECT_ENTRY = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Directory
|
||||
/// </summary>
|
||||
DIRECTORY = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Sequence of bytes (a regular file)
|
||||
/// </summary>
|
||||
FILE = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Block special device
|
||||
/// </summary>
|
||||
BLOCK_DEVICE = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Character special device
|
||||
/// </summary>
|
||||
CHARACTER_DEVICE = 7,
|
||||
|
||||
/// <summary>
|
||||
/// Extended attributes
|
||||
/// </summary>
|
||||
EXTENDED_ATTRIBUTES = 8,
|
||||
|
||||
/// <summary>
|
||||
/// FIFO file
|
||||
/// </summary>
|
||||
FIFO = 9,
|
||||
|
||||
/// <summary>
|
||||
/// Socket
|
||||
/// </summary>
|
||||
SOCKET = 10,
|
||||
|
||||
/// <summary>
|
||||
/// Terminal Entry
|
||||
/// </summary>
|
||||
TERMINAL_ENTRY = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Symbolic link
|
||||
/// </summary>
|
||||
SYMBOLIC_LINK = 12,
|
||||
|
||||
/// <summary>
|
||||
/// Stream directory
|
||||
/// </summary>
|
||||
STREAM_DIRECTORY = 13,
|
||||
|
||||
/// <summary>
|
||||
/// UDF Virtual Allocation Table
|
||||
/// </summary>
|
||||
VIRTUAL_ALLOCATION_TABLE = 248,
|
||||
|
||||
/// <summary>
|
||||
/// UDF Real-Time file
|
||||
/// </summary>
|
||||
REAL_TIME_FILE = 249,
|
||||
|
||||
/// <summary>
|
||||
/// UDF Metadata File
|
||||
/// </summary>
|
||||
METADATA_FILE = 250,
|
||||
|
||||
/// <summary>
|
||||
/// UDF Metadata Mirror File
|
||||
/// </summary>
|
||||
METADATA_MIRROR_FILE = 251,
|
||||
|
||||
/// <summary>
|
||||
/// UDF Metadata Bitmap File
|
||||
/// </summary>
|
||||
METADATA_BITMAP_FILE = 252,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum for the allocation descriptor type in ICBTag.Flags (4/14.6.8)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public enum AllocationDescriptorType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Short Allocation Descriptors (4/14.14.1)
|
||||
/// </summary>
|
||||
SHORT = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Long Allocation Descriptors (4/14.14.2)
|
||||
/// </summary>
|
||||
LONG = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Extended Allocation Descriptors (4/14.14.3)
|
||||
/// </summary>
|
||||
EXTENDED = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The file data is embedded in the allocation descriptors field
|
||||
/// </summary>
|
||||
EMBEDDED = 3,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum for the extent type in the top two bits of an allocation descriptor's extent length (4/14.14.1.1)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public enum ExtentType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Extent recorded and allocated
|
||||
/// </summary>
|
||||
RECORDED_AND_ALLOCATED = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Extent not recorded but allocated
|
||||
/// </summary>
|
||||
NOT_RECORDED_BUT_ALLOCATED = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Extent not recorded and not allocated
|
||||
/// </summary>
|
||||
NOT_RECORDED_NOT_ALLOCATED = 2,
|
||||
|
||||
/// <summary>
|
||||
/// The extent is the next extent of allocation descriptors
|
||||
/// </summary>
|
||||
NEXT_EXTENT = 3,
|
||||
}
|
||||
}
|
||||
30
SabreTools.Data.Models/UDF/ExtendedFileEntry.cs
Normal file
30
SabreTools.Data.Models/UDF/ExtendedFileEntry.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Extended File Entry (4/14.17, UDF 2.00 and later), a File Entry with object size,
|
||||
/// creation time and a stream directory
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class ExtendedFileEntry : FileEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Size of the file and its streams in bytes
|
||||
/// </summary>
|
||||
public ulong ObjectSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creation date and time
|
||||
/// </summary>
|
||||
public Timestamp CreationDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 0x00000000
|
||||
/// </summary>
|
||||
public uint Reserved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ICB of the stream directory, length 0 if none
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor StreamDirectoryICB { get; set; } = new();
|
||||
}
|
||||
}
|
||||
19
SabreTools.Data.Models/UDF/ExtentDescriptor.cs
Normal file
19
SabreTools.Data.Models/UDF/ExtentDescriptor.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Extent Descriptor (extent_ad, 3/7.1), an extent of logical sectors
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class ExtentDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the extent in bytes
|
||||
/// </summary>
|
||||
public uint ExtentLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical sector number of the start of the extent
|
||||
/// </summary>
|
||||
public uint ExtentLocation { get; set; }
|
||||
}
|
||||
}
|
||||
115
SabreTools.Data.Models/UDF/FileEntry.cs
Normal file
115
SabreTools.Data.Models/UDF/FileEntry.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF File Entry (4/14.9), the ICB describing a file or directory and where its data is recorded
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public class FileEntry : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// ICB tag
|
||||
/// </summary>
|
||||
public ICBTag ICBTag { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// User ID
|
||||
/// </summary>
|
||||
public uint Uid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Group ID
|
||||
/// </summary>
|
||||
public uint Gid { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Permissions
|
||||
/// </summary>
|
||||
public uint Permissions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of File Identifier Descriptors identifying this ICB
|
||||
/// </summary>
|
||||
public ushort FileLinkCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record format
|
||||
/// </summary>
|
||||
public byte RecordFormat { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record display attributes
|
||||
/// </summary>
|
||||
public byte RecordDisplayAttributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Record length
|
||||
/// </summary>
|
||||
public uint RecordLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the file in bytes
|
||||
/// </summary>
|
||||
public ulong InformationLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of recorded logical blocks
|
||||
/// </summary>
|
||||
public ulong LogicalBlocksRecorded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Access date and time
|
||||
/// </summary>
|
||||
public Timestamp AccessDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Modification date and time
|
||||
/// </summary>
|
||||
public Timestamp ModificationDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Attribute date and time
|
||||
/// </summary>
|
||||
public Timestamp AttributeDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Checkpoint
|
||||
/// </summary>
|
||||
public uint Checkpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ICB of the extended attributes, length 0 if none
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor ExtendedAttributeICB { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Unique ID
|
||||
/// </summary>
|
||||
public ulong UniqueID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the extended attributes in bytes
|
||||
/// </summary>
|
||||
public uint LengthOfExtendedAttributes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the allocation descriptors in bytes
|
||||
/// </summary>
|
||||
public uint LengthOfAllocationDescriptors { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extended attributes
|
||||
/// </summary>
|
||||
public byte[] ExtendedAttributes { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Allocation descriptors of the type given in the ICB tag flags,
|
||||
/// or the file data itself if the type is AllocationDescriptorType.EMBEDDED
|
||||
/// </summary>
|
||||
public byte[] AllocationDescriptors { get; set; } = [];
|
||||
}
|
||||
}
|
||||
49
SabreTools.Data.Models/UDF/FileIdentifierDescriptor.cs
Normal file
49
SabreTools.Data.Models/UDF/FileIdentifierDescriptor.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF File Identifier Descriptor (4/14.4), a directory entry naming a file or directory and pointing to its ICB
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class FileIdentifierDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// File version number
|
||||
/// </summary>
|
||||
public ushort FileVersionNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File characteristics
|
||||
/// </summary>
|
||||
public FileCharacteristics FileCharacteristics { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the file identifier in bytes
|
||||
/// </summary>
|
||||
public byte LengthOfFileIdentifier { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// ICB of the file or directory
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor ICB { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Length of the implementation use in bytes
|
||||
/// </summary>
|
||||
public ushort LengthOfImplementationUse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Implementation use
|
||||
/// </summary>
|
||||
public byte[] ImplementationUse { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// File identifier, d-characters (first byte = compression ID), empty for the parent directory
|
||||
/// </summary>
|
||||
public byte[] FileIdentifier { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Padding to a multiple of 4 bytes
|
||||
/// </summary>
|
||||
public byte[] Padding { get; set; } = [];
|
||||
}
|
||||
}
|
||||
99
SabreTools.Data.Models/UDF/FileSetDescriptor.cs
Normal file
99
SabreTools.Data.Models/UDF/FileSetDescriptor.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF File Set Descriptor (4/14.1), the location of the root directory
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class FileSetDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Recording date and time
|
||||
/// </summary>
|
||||
public Timestamp RecordingDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Interchange level
|
||||
/// </summary>
|
||||
public ushort InterchangeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum interchange level
|
||||
/// </summary>
|
||||
public ushort MaximumInterchangeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Character set list
|
||||
/// </summary>
|
||||
public uint CharacterSetList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum character set list
|
||||
/// </summary>
|
||||
public uint MaximumCharacterSetList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File set number
|
||||
/// </summary>
|
||||
public uint FileSetNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File Set Descriptor number
|
||||
/// </summary>
|
||||
public uint FileSetDescriptorNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical volume identifier character set
|
||||
/// </summary>
|
||||
public CharacterSetSpecification LogicalVolumeIdentifierCharacterSet { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Logical volume identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] LogicalVolumeIdentifier { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// File set character set
|
||||
/// </summary>
|
||||
public CharacterSetSpecification FileSetCharacterSet { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// File set identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] FileSetIdentifier { get; set; } = new byte[32];
|
||||
|
||||
/// <summary>
|
||||
/// Copyright file identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] CopyrightFileIdentifier { get; set; } = new byte[32];
|
||||
|
||||
/// <summary>
|
||||
/// Abstract file identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] AbstractFileIdentifier { get; set; } = new byte[32];
|
||||
|
||||
/// <summary>
|
||||
/// ICB of the root directory
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor RootDirectoryICB { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Domain identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier DomainIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Next extent of File Set Descriptors, length 0 if none
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor NextExtent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// ICB of the system stream directory (ECMA-167 3rd edition), length 0 if none
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor SystemStreamDirectoryICB { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 32 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[32];
|
||||
}
|
||||
}
|
||||
15
SabreTools.Data.Models/UDF/GenericDescriptor.cs
Normal file
15
SabreTools.Data.Models/UDF/GenericDescriptor.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF tagged descriptor of a type that is not parsed further
|
||||
/// (e.g. Implementation Use Volume Descriptor, Unallocated Space Descriptor, Terminating Descriptor)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class GenericDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Contents of the descriptor after the tag, up to the end of the logical sector
|
||||
/// </summary>
|
||||
public byte[] Data { get; set; } = [];
|
||||
}
|
||||
}
|
||||
49
SabreTools.Data.Models/UDF/ICBTag.cs
Normal file
49
SabreTools.Data.Models/UDF/ICBTag.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Information Control Block Tag (icbtag, 4/14.6)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class ICBTag
|
||||
{
|
||||
/// <summary>
|
||||
/// Prior recorded number of direct entries
|
||||
/// </summary>
|
||||
public uint PriorRecordedNumberOfDirectEntries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Strategy type (UDF: 4, or 4096 for write-once media)
|
||||
/// </summary>
|
||||
public ushort StrategyType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Strategy parameter, 2 bytes
|
||||
/// </summary>
|
||||
public byte[] StrategyParameter { get; set; } = new byte[2];
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of entries
|
||||
/// </summary>
|
||||
public ushort MaximumNumberOfEntries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 0x00
|
||||
/// </summary>
|
||||
public byte Reserved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File type
|
||||
/// </summary>
|
||||
public FileType FileType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Parent ICB location
|
||||
/// </summary>
|
||||
public LogicalBlockAddress ParentICBLocation { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Flags, the lower 3 bits hold the AllocationDescriptorType
|
||||
/// </summary>
|
||||
public ushort Flags { get; set; }
|
||||
}
|
||||
}
|
||||
19
SabreTools.Data.Models/UDF/LogicalBlockAddress.cs
Normal file
19
SabreTools.Data.Models/UDF/LogicalBlockAddress.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Recorded Address (lb_addr, 4/7.1), a logical block within a partition
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class LogicalBlockAddress
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical block number, relative to the start of the partition
|
||||
/// </summary>
|
||||
public uint LogicalBlockNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Index of the partition map in the Logical Volume Descriptor
|
||||
/// </summary>
|
||||
public ushort PartitionReferenceNumber { get; set; }
|
||||
}
|
||||
}
|
||||
69
SabreTools.Data.Models/UDF/LogicalVolumeDescriptor.cs
Normal file
69
SabreTools.Data.Models/UDF/LogicalVolumeDescriptor.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Logical Volume Descriptor (3/10.6), block size, partition maps and the location of the File Set Descriptor
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class LogicalVolumeDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||
/// </summary>
|
||||
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Descriptor character set
|
||||
/// </summary>
|
||||
public CharacterSetSpecification DescriptorCharacterSet { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Logical volume identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] LogicalVolumeIdentifier { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// Size of a logical block in bytes
|
||||
/// </summary>
|
||||
public uint LogicalBlockSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Domain identifier ("*OSTA UDF Compliant", suffix holds the UDF revision)
|
||||
/// </summary>
|
||||
public EntityIdentifier DomainIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Logical volume contents use (UDF: extent of the File Set Descriptor)
|
||||
/// </summary>
|
||||
public LongAllocationDescriptor LogicalVolumeContentsUse { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Length of the partition maps in bytes
|
||||
/// </summary>
|
||||
public uint MapTableLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of partition maps
|
||||
/// </summary>
|
||||
public uint NumberOfPartitionMaps { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Implementation identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation use, 128 bytes
|
||||
/// </summary>
|
||||
public byte[] ImplementationUse { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// Extent of the Logical Volume Integrity Sequence
|
||||
/// </summary>
|
||||
public ExtentDescriptor IntegritySequenceExtent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Partition maps, a partition reference number is the index into this array
|
||||
/// </summary>
|
||||
public PartitionMap[] PartitionMaps { get; set; } = [];
|
||||
}
|
||||
}
|
||||
25
SabreTools.Data.Models/UDF/LongAllocationDescriptor.cs
Normal file
25
SabreTools.Data.Models/UDF/LongAllocationDescriptor.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Long Allocation Descriptor (long_ad, 4/14.14.2), an extent within any partition of the logical volume
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class LongAllocationDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the extent in bytes (lower 30 bits) and the ExtentType (upper 2 bits)
|
||||
/// A length of 0 terminates a sequence of allocation descriptors
|
||||
/// </summary>
|
||||
public uint ExtentLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical block address of the start of the extent
|
||||
/// </summary>
|
||||
public LogicalBlockAddress ExtentLocation { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation use (UDF: flags and unique ID bits)
|
||||
/// </summary>
|
||||
public byte[] ImplementationUse { get; set; } = new byte[6];
|
||||
}
|
||||
}
|
||||
45
SabreTools.Data.Models/UDF/MetadataPartitionMap.cs
Normal file
45
SabreTools.Data.Models/UDF/MetadataPartitionMap.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Metadata Partition Map (UDF 2.2.10, UDF 2.50 and later), a partition whose logical blocks
|
||||
/// are the contents of the Metadata File recorded in the underlying partition
|
||||
/// </summary>
|
||||
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||
public sealed class MetadataPartitionMap : Type2PartitionMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Logical block of the Metadata File's File Entry in the underlying partition
|
||||
/// </summary>
|
||||
public uint MetadataFileLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical block of the Metadata Mirror File's File Entry in the underlying partition
|
||||
/// </summary>
|
||||
public uint MetadataMirrorFileLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical block of the Metadata Bitmap File's File Entry, 0xFFFFFFFF if not recorded
|
||||
/// </summary>
|
||||
public uint MetadataBitmapFileLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allocation unit size in logical blocks
|
||||
/// </summary>
|
||||
public uint AllocationUnitSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Alignment unit size in logical blocks
|
||||
/// </summary>
|
||||
public ushort AlignmentUnitSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags (bit 0: duplicate metadata flag)
|
||||
/// </summary>
|
||||
public byte Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 5 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved2 { get; set; } = new byte[5];
|
||||
}
|
||||
}
|
||||
64
SabreTools.Data.Models/UDF/PartitionDescriptor.cs
Normal file
64
SabreTools.Data.Models/UDF/PartitionDescriptor.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Partition Descriptor (3/10.5), the physical location of a partition
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class PartitionDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||
/// </summary>
|
||||
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition flags (bit 0: space is allocated)
|
||||
/// </summary>
|
||||
public ushort PartitionFlags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition number, referenced by the partition maps
|
||||
/// </summary>
|
||||
public ushort PartitionNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition contents ("+NSR02" or "+NSR03" for UDF)
|
||||
/// </summary>
|
||||
public EntityIdentifier PartitionContents { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Partition contents use (Partition Header Descriptor for NSR), 128 bytes
|
||||
/// </summary>
|
||||
public byte[] PartitionContentsUse { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// Access type (1 = read-only, 2 = write-once, 3 = rewritable, 4 = overwritable)
|
||||
/// </summary>
|
||||
public uint AccessType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical sector number of the first sector of the partition
|
||||
/// </summary>
|
||||
public uint PartitionStartingLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the partition in logical sectors
|
||||
/// </summary>
|
||||
public uint PartitionLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Implementation identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation use, 128 bytes
|
||||
/// </summary>
|
||||
public byte[] ImplementationUse { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 156 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[156];
|
||||
}
|
||||
}
|
||||
19
SabreTools.Data.Models/UDF/PartitionMap.cs
Normal file
19
SabreTools.Data.Models/UDF/PartitionMap.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract UDF Partition Map (3/10.7)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public abstract class PartitionMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Partition map type (1 or 2)
|
||||
/// </summary>
|
||||
public byte PartitionMapType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Length of the partition map in bytes
|
||||
/// </summary>
|
||||
public byte PartitionMapLength { get; set; }
|
||||
}
|
||||
}
|
||||
114
SabreTools.Data.Models/UDF/PrimaryVolumeDescriptor.cs
Normal file
114
SabreTools.Data.Models/UDF/PrimaryVolumeDescriptor.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Primary Volume Descriptor (3/10.1)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class PrimaryVolumeDescriptor : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume Descriptor Sequence Number, the highest number prevails
|
||||
/// </summary>
|
||||
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Primary Volume Descriptor Number
|
||||
/// </summary>
|
||||
public uint PrimaryVolumeDescriptorNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Volume identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] VolumeIdentifier { get; set; } = new byte[32];
|
||||
|
||||
/// <summary>
|
||||
/// Volume sequence number
|
||||
/// </summary>
|
||||
public ushort VolumeSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum volume sequence number
|
||||
/// </summary>
|
||||
public ushort MaximumVolumeSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Interchange level
|
||||
/// </summary>
|
||||
public ushort InterchangeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum interchange level
|
||||
/// </summary>
|
||||
public ushort MaximumInterchangeLevel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Character set list
|
||||
/// </summary>
|
||||
public uint CharacterSetList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Maximum character set list
|
||||
/// </summary>
|
||||
public uint MaximumCharacterSetList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Volume set identifier, dstring (last byte = length)
|
||||
/// </summary>
|
||||
public byte[] VolumeSetIdentifier { get; set; } = new byte[128];
|
||||
|
||||
/// <summary>
|
||||
/// Descriptor character set
|
||||
/// </summary>
|
||||
public CharacterSetSpecification DescriptorCharacterSet { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Explanatory character set
|
||||
/// </summary>
|
||||
public CharacterSetSpecification ExplanatoryCharacterSet { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Extent of the volume abstract
|
||||
/// </summary>
|
||||
public ExtentDescriptor VolumeAbstract { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Extent of the volume copyright notice
|
||||
/// </summary>
|
||||
public ExtentDescriptor VolumeCopyrightNotice { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Application identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier ApplicationIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Recording date and time
|
||||
/// </summary>
|
||||
public Timestamp RecordingDateAndTime { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier ImplementationIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Implementation use, 64 bytes
|
||||
/// </summary>
|
||||
public byte[] ImplementationUse { get; set; } = new byte[64];
|
||||
|
||||
/// <summary>
|
||||
/// Predecessor Volume Descriptor Sequence location
|
||||
/// </summary>
|
||||
public uint PredecessorVolumeDescriptorSequenceLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Flags (bit 0: volume set identification is common to all volumes of the set)
|
||||
/// </summary>
|
||||
public ushort Flags { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 22 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[22];
|
||||
}
|
||||
}
|
||||
20
SabreTools.Data.Models/UDF/ShortAllocationDescriptor.cs
Normal file
20
SabreTools.Data.Models/UDF/ShortAllocationDescriptor.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Short Allocation Descriptor (short_ad, 4/14.14.1), an extent within the partition of the descriptor
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class ShortAllocationDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Length of the extent in bytes (lower 30 bits) and the ExtentType (upper 2 bits)
|
||||
/// A length of 0 terminates a sequence of allocation descriptors
|
||||
/// </summary>
|
||||
public uint ExtentLength { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Logical block number of the start of the extent
|
||||
/// </summary>
|
||||
public uint ExtentPosition { get; set; }
|
||||
}
|
||||
}
|
||||
60
SabreTools.Data.Models/UDF/Timestamp.cs
Normal file
60
SabreTools.Data.Models/UDF/Timestamp.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Timestamp (1/7.3)
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class Timestamp
|
||||
{
|
||||
/// <summary>
|
||||
/// Type (upper 4 bits, 1 = local time) and time zone offset from UTC in minutes
|
||||
/// (lower 12 bits, signed, -2047 = not specified)
|
||||
/// </summary>
|
||||
public ushort TypeAndTimezone { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Year, 1 to 9999
|
||||
/// </summary>
|
||||
public short Year { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Month, 1 to 12
|
||||
/// </summary>
|
||||
public byte Month { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Day, 1 to 31
|
||||
/// </summary>
|
||||
public byte Day { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hour, 0 to 23
|
||||
/// </summary>
|
||||
public byte Hour { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minute, 0 to 59
|
||||
/// </summary>
|
||||
public byte Minute { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Second, 0 to 59
|
||||
/// </summary>
|
||||
public byte Second { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Centiseconds, 0 to 99
|
||||
/// </summary>
|
||||
public byte Centiseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Hundreds of microseconds, 0 to 99
|
||||
/// </summary>
|
||||
public byte HundredsOfMicroseconds { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Microseconds, 0 to 99
|
||||
/// </summary>
|
||||
public byte Microseconds { get; set; }
|
||||
}
|
||||
}
|
||||
19
SabreTools.Data.Models/UDF/Type1PartitionMap.cs
Normal file
19
SabreTools.Data.Models/UDF/Type1PartitionMap.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Type 1 Partition Map (3/10.7.2), logical blocks map 1:1 onto a Partition Descriptor's sectors
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class Type1PartitionMap : PartitionMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume sequence number of the volume containing the partition
|
||||
/// </summary>
|
||||
public ushort VolumeSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition number of the Partition Descriptor
|
||||
/// </summary>
|
||||
public ushort PartitionNumber { get; set; }
|
||||
}
|
||||
}
|
||||
37
SabreTools.Data.Models/UDF/Type2PartitionMap.cs
Normal file
37
SabreTools.Data.Models/UDF/Type2PartitionMap.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Type 2 Partition Map (3/10.7.3, UDF 2.2.8-2.2.10), a partition identified by its partition type identifier
|
||||
/// (e.g. "*UDF Virtual Partition", "*UDF Sparable Partition", "*UDF Metadata Partition")
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||
public class Type2PartitionMap : PartitionMap
|
||||
{
|
||||
/// <summary>
|
||||
/// Reserved, 2 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[2];
|
||||
|
||||
/// <summary>
|
||||
/// Partition type identifier
|
||||
/// </summary>
|
||||
public EntityIdentifier PartitionTypeIdentifier { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Volume sequence number of the volume containing the partition
|
||||
/// </summary>
|
||||
public ushort VolumeSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition number of the underlying Partition Descriptor
|
||||
/// </summary>
|
||||
public ushort PartitionNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Partition type specific data after the partition number, 24 bytes
|
||||
/// Empty for partition types that are parsed further (MetadataPartitionMap)
|
||||
/// </summary>
|
||||
public byte[] PartitionTypeData { get; set; } = [];
|
||||
}
|
||||
}
|
||||
52
SabreTools.Data.Models/UDF/Volume.cs
Normal file
52
SabreTools.Data.Models/UDF/Volume.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// A volume (or disc image) with a UDF / ECMA-167 file system
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Logical sectors and logical blocks are 2048 bytes on optical media
|
||||
/// File system structures are addressed by logical block address (partition reference number + logical block);
|
||||
/// dictionaries are keyed by ((long)PartitionReferenceNumber << 32) | LogicalBlockNumber
|
||||
/// </remarks>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
/// <see href="http://www.osta.org/specs/pdf/udf260.pdf"/>
|
||||
public sealed class Volume
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume Recognition Sequence starting at sector 16
|
||||
/// </summary>
|
||||
public VolumeStructureDescriptor[] VolumeRecognitionSequence { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Anchor Volume Descriptor Pointer
|
||||
/// </summary>
|
||||
public AnchorVolumeDescriptorPointer? AnchorVolumeDescriptorPointer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Volume Descriptor Sequence (Primary, Partition, Logical Volume, ... up to the Terminating Descriptor)
|
||||
/// </summary>
|
||||
public Descriptor[] VolumeDescriptorSequence { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// File Set Descriptor
|
||||
/// </summary>
|
||||
public FileSetDescriptor? FileSetDescriptor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File Entries (and Extended File Entries) by logical block address
|
||||
/// </summary>
|
||||
public Dictionary<long, FileEntry> FileEntries { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Allocation Extent Descriptors by logical block address
|
||||
/// </summary>
|
||||
public Dictionary<long, AllocationExtentDescriptor> AllocationExtentDescriptors { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// File Identifier Descriptors of each directory, by logical block address of the directory's File Entry
|
||||
/// </summary>
|
||||
public Dictionary<long, FileIdentifierDescriptor[]> Directories { get; set; } = [];
|
||||
}
|
||||
}
|
||||
24
SabreTools.Data.Models/UDF/VolumeDescriptorPointer.cs
Normal file
24
SabreTools.Data.Models/UDF/VolumeDescriptorPointer.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Volume Descriptor Pointer (3/10.3), continues the Volume Descriptor Sequence in another extent
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class VolumeDescriptorPointer : Descriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Volume Descriptor Sequence Number
|
||||
/// </summary>
|
||||
public uint VolumeDescriptorSequenceNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Extent of the next part of the Volume Descriptor Sequence
|
||||
/// </summary>
|
||||
public ExtentDescriptor NextVolumeDescriptorSequenceExtent { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Reserved, 484 bytes of 0x00
|
||||
/// </summary>
|
||||
public byte[] Reserved { get; set; } = new byte[484];
|
||||
}
|
||||
}
|
||||
30
SabreTools.Data.Models/UDF/VolumeStructureDescriptor.cs
Normal file
30
SabreTools.Data.Models/UDF/VolumeStructureDescriptor.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace SabreTools.Data.Models.UDF
|
||||
{
|
||||
/// <summary>
|
||||
/// UDF Volume Structure Descriptor (2/9.1), one logical sector of the Volume Recognition Sequence
|
||||
/// starting at sector 16, e.g. "BEA01", "NSR02"/"NSR03", "TEA01", or "CD001" on bridge discs
|
||||
/// </summary>
|
||||
/// <see href="https://ecma-international.org/wp-content/uploads/ECMA-167_3rd_edition_june_1997.pdf"/>
|
||||
public sealed class VolumeStructureDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure type
|
||||
/// </summary>
|
||||
public byte StructureType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Standard identifier, 5 bytes
|
||||
/// </summary>
|
||||
public byte[] StandardIdentifier { get; set; } = new byte[5];
|
||||
|
||||
/// <summary>
|
||||
/// Structure version
|
||||
/// </summary>
|
||||
public byte StructureVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Structure data, the rest of the logical sector
|
||||
/// </summary>
|
||||
public byte[] StructureData { get; set; } = [];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user